From 4676eaf79b4f7a8f697ae1aa31346efebc6bc21d Mon Sep 17 00:00:00 2001 From: jerome mouneyrac Date: Wed, 19 May 2010 03:21:58 +0000 Subject: [PATCH] publish course MDL-19315 refactor the publish index page + add unpublish operation --- course/publish/forms.php | 10 ++- course/publish/index.php | 76 ++++++++++++++---- course/publish/metadata.php | 16 ++-- course/publish/renderer.php | 151 +++++++++++++++++++++++------------- lang/en/hub.php | 22 ++++-- lib/hublib.php | 14 +++- pix/i/publish.png | Bin 637 -> 940 bytes 7 files changed, 207 insertions(+), 82 deletions(-) diff --git a/course/publish/forms.php b/course/publish/forms.php index 08a467f886b..e65f80ef822 100644 --- a/course/publish/forms.php +++ b/course/publish/forms.php @@ -51,12 +51,14 @@ class hub_publish_selector_form extends moodleform { //Public hub list $options = array(); foreach ($registeredhubs as $hub) { - $options[$hub->huburl] = $hub->huburl; + $hubname = $hub->hubname; $mform->addElement('hidden', clean_param($hub->huburl, PARAM_ALPHANUMEXT), $hubname); + if (empty($hubname)) { + $hubname = $hub->huburl; + } + $mform->addElement('radio','huburl',null,' '.$hubname, $hub->huburl); } - $mform->addElement('select', 'huburl', get_string('publichub','hub'), - $options, array("size" => 15)); $mform->addElement('hidden', 'id', $this->_customdata['id']); @@ -179,7 +181,7 @@ class course_publication_form extends moodleform { } if ($advertise) { - if (empty($publications)) { + if (empty($publishedcourses)) { $buttonlabel = get_string('advertiseon', 'hub', !empty($hubname)?$hubname:$huburl); } else { $buttonlabel = get_string('readvertiseon', 'hub', !empty($hubname)?$hubname:$huburl); diff --git a/course/publish/index.php b/course/publish/index.php index 4a9508e040a..63148e6e9be 100644 --- a/course/publish/index.php +++ b/course/publish/index.php @@ -42,28 +42,76 @@ if (has_capability('moodle/course:publish', get_context_instance(CONTEXT_COURSE, $PAGE->set_title(get_string('course') . ': ' . $course->fullname); $PAGE->set_heading($course->fullname); - $renderer = $PAGE->get_renderer('core', 'publish'); - echo $OUTPUT->header(); - echo $OUTPUT->heading(get_string('publishon', 'hub'), 3, 'main'); - - //check if the site is registered on Moodle.org hub - //check if the site is registered on any other specific hub $hub = new hub(); - $registeredonmoodleorg = false; - $registeredonhub = false; - $hubs = $hub->get_registered_on_hubs(); - foreach ($hubs as $hub) { - if ($hub->huburl == MOODLEORGHUBURL) { - $registeredonmoodleorg = true; + /// UNPUBLISH + $confirmmessage = ''; + $cancel = optional_param('cancel', 0, PARAM_BOOL); + if (!empty($cancel) and confirm_sesskey()) { + $confirm = optional_param('confirm', 0, PARAM_BOOL); + $hubname = optional_param('hubname', 0, PARAM_TEXT); + $huburl = optional_param('huburl', 0, PARAM_URL); + $hubcourseid = optional_param('hubcourseid', 0, PARAM_INT); + $publicationid = optional_param('publicationid', 0, PARAM_INT); + $timepublished = optional_param('timepublished', 0, PARAM_INT); + $publication->courseshortname = $course->shortname; + $publication->courseid = $course->id; + $publication->hubname = $hubname; + $publication->huburl = $huburl; + $publication->hubcourseid = $hubcourseid; + $publication->timepublished = $timepublished; + if (empty($publication->hubname)) { + $publication->hubname = $huburl; + } + $publication->id = $publicationid; + if($confirm) { + //unpublish the publication by web service + $registeredhub = $hub->get_registeredhub($huburl); + $function = 'hub_unregister_courses'; + $params = array(array( $publication->hubcourseid)); + $serverurl = $huburl."/local/hub/webservice/webservices.php"; + require_once($CFG->dirroot."/webservice/xmlrpc/lib.php"); + $xmlrpcclient = new webservice_xmlrpc_client(); + $result = $xmlrpcclient->call($serverurl, $registeredhub->token, $function, $params); + + //delete the publication from the database + $hub->delete_publication($publicationid); + + //display confirmation message + $confirmmessage = $OUTPUT->notification(get_string('courseunpublished', 'hub', $publication), 'notifysuccess'); + } else { - $registeredonhub = true; + //display confirmation page for unpublishing + + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('unpublishcourse', 'hub', $course->shortname), 3, 'main'); + echo $renderer->confirmunpublishing($publication); + echo $OUTPUT->footer(); + die(); } } - echo $renderer->publicationselector($course->id, $registeredonmoodleorg, $registeredonhub); + //check if a course was published + if (optional_param('published', 0, PARAM_TEXT)) { + $confirmmessage = $OUTPUT->notification(get_string('coursepublished', 'hub'), 'notifysuccess'); + } + + + /// OUTPUT + echo $OUTPUT->header(); + echo $confirmmessage; + + echo $OUTPUT->heading(get_string('publishcourse', 'hub', $course->shortname), 3, 'main'); + echo $renderer->publicationselector($course->id); + + $publications = $hub->get_course_publications($course->id); + if (!empty($publications)) { + echo $OUTPUT->heading(get_string('publishedon', 'hub'), 3, 'main'); + echo $renderer->registeredonhublisting($course->id, $publications); + } + echo $OUTPUT->footer(); } \ No newline at end of file diff --git a/course/publish/metadata.php b/course/publish/metadata.php index c4087fa9c8a..cb00230bc24 100644 --- a/course/publish/metadata.php +++ b/course/publish/metadata.php @@ -32,6 +32,8 @@ require_once('../../config.php'); require_once($CFG->dirroot.'/course/publish/forms.php'); require_once($CFG->dirroot.'/lib/hublib.php'); +require_once($CFG->dirroot.'/lib/filelib.php'); +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); //check user access capability to this page $id = optional_param('id', 0, PARAM_INT); @@ -39,7 +41,7 @@ $course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST); require_login($course); if (has_capability('moodle/course:publish', get_context_instance(CONTEXT_COURSE, $id))) { - + //page settings $PAGE->set_url('/course/publish/metadata.php', array('id' => $course->id)); $PAGE->set_pagelayout('course'); @@ -134,9 +136,6 @@ if (has_capability('moodle/course:publish', get_context_instance(CONTEXT_COURSE, throw new moodle_exception('coursewronglypublished'); } - $courseregisteredmsg = $OUTPUT->notification(get_string('coursepublished', 'hub'), 'notifysuccess'); - - //save the record into the published course table $publication = $hub->get_publication($courseids[0]); if (empty($publication)) { @@ -149,13 +148,14 @@ if (has_capability('moodle/course:publish', get_context_instance(CONTEXT_COURSE, // SEND FILES + $curl = new curl(); // send screenshots if (!empty($fromform->screenshots)) { require_once($CFG->dirroot. "/lib/filelib.php"); $params = array('token' => $registeredhub->token, 'filetype' => SCREENSHOT_FILE_TYPE, 'courseshortname' => $courseinfo->shortname); - $curl = new curl(); + foreach ($files as $file) { if ($file->is_valid_image()) { $params['file'] = $file; @@ -178,7 +178,11 @@ if (has_capability('moodle/course:publish', get_context_instance(CONTEXT_COURSE, //TODO: Delete the backup from user_tohub - + + + //redirect to the index publis page + redirect(new moodle_url('/course/publish/index.php', + array('sesskey' => sesskey(), 'id' => $id, 'published' => true))); } diff --git a/course/publish/renderer.php b/course/publish/renderer.php index 6fc93aafa2e..03809f31891 100644 --- a/course/publish/renderer.php +++ b/course/publish/renderer.php @@ -30,73 +30,44 @@ class core_publish_renderer extends plugin_renderer_base { /** - * Display the page to publish a course on Moodle.org or on a specific hub + * Display the selector to advertise or publish a course */ - public function publicationselector($courseid, $registeredonmoodleorg, $registeredonhub) { + public function publicationselector($courseid) { global $OUTPUT; $table = new html_table(); - $table->head = array(get_string('moodleorg', 'hub'), get_string('specifichub', 'hub')); + $table->head = array(get_string('advertise', 'hub'), get_string('share', 'hub')); $table->size = array('50%', '50%'); - //Moodle.org information cell - $moodleorgcell = get_string('moodleorgpublicationdetail', 'hub'); - $moodleorgcell .= html_writer::empty_tag('br').html_writer::empty_tag('br'); - $moodleorgcell = html_writer::tag('div', $moodleorgcell, array('class' => 'justifytext')); + //Advertise information cell + $advertisecell = get_string('advertisepublicationdetail', 'hub'); + $advertisecell .= html_writer::empty_tag('br').html_writer::empty_tag('br'); + $advertisecell = html_writer::tag('div', $advertisecell, array('class' => 'justifytext')); - //Specific hub information cell - $specifichubcell = get_string('specifichubpublicationdetail', 'hub'); - $specifichubcell .= html_writer::empty_tag('br').html_writer::empty_tag('br'); - $specifichubcell = html_writer::tag('div', $specifichubcell, array('class' => 'justifytext')); + //Share information cell + $sharecell = get_string('sharepublicationdetail', 'hub'); + $sharecell .= html_writer::empty_tag('br').html_writer::empty_tag('br'); + $sharecell = html_writer::tag('div', $sharecell, array('class' => 'justifytext')); //add information cells - $cells = array($moodleorgcell, $specifichubcell); + $cells = array($advertisecell, $sharecell); $row = new html_table_row($cells); $table->data[] = $row; - //Moodle.org button cell - if ($registeredonmoodleorg) { - $advertiseonmoodleorgurl = new moodle_url("/course/publish/metadata.php", - array('sesskey' => sesskey(), 'huburl' => MOODLEORGHUBURL, 'id' => $courseid - , 'hubname' => 'Moodle.org', 'advertise' => true)); - $advertiseonmoodleorgbutton = new single_button($advertiseonmoodleorgurl, get_string('advertiseonmoodleorg', 'hub')); - $advertiseonmoodleorgbutton->class = 'centeredbutton'; - $advertiseonmoodleorgbuttonhtml = $OUTPUT->render($advertiseonmoodleorgbutton); + $advertiseurl = new moodle_url("/course/publish/hubselector.php", + array('sesskey' => sesskey(), 'id' => $courseid, 'advertise' => true)); + $advertisebutton = new single_button($advertiseurl, get_string('selecthubforadvertise', 'hub')); + $advertisebutton->class = 'centeredbutton'; + $advertisecell = $OUTPUT->render($advertisebutton); - $shareonmoodleorgurl = new moodle_url("/course/publish/metadata.php", - array('sesskey' => sesskey(), 'huburl' => MOODLEORGHUBURL, 'id' => $courseid - , 'hubname' => 'Moodle.org', 'share' => true)); - $shareonmoodleorgbutton = new single_button($shareonmoodleorgurl, get_string('shareonmoodleorg', 'hub')); - $shareonmoodleorgbutton->class = 'centeredbutton'; - $shareonmoodleorgbuttonhtml = $OUTPUT->render($shareonmoodleorgbutton); - - $moodleorgcell = $advertiseonmoodleorgbuttonhtml." ".$shareonmoodleorgbuttonhtml; - } else { - $moodleorgcell = html_writer::tag('span', - get_string('notregisteredonmoodleorg', 'hub') , array('class' => 'publicationwarning')); - } - - //Specific hub button cell - if ($registeredonhub) { - $advertisespecifichuburl = new moodle_url("/course/publish/hubselector.php", - array('sesskey' => sesskey(), 'id' => $courseid, 'advertise' => true)); - $advertiseonspecifichubbutton = new single_button($advertisespecifichuburl, get_string('advertiseonspecifichub', 'hub')); - $advertiseonspecifichubbutton->class = 'centeredbutton'; - $advertiseonspecifichubbuttonhtml = $OUTPUT->render($advertiseonspecifichubbutton); - - $sharespecifichuburl = new moodle_url("/course/publish/hubselector.php", - array('sesskey' => sesskey(), 'id' => $courseid, 'share' => true)); - $shareonspecifichubbutton = new single_button($sharespecifichuburl, get_string('shareonspecifichub', 'hub')); - $shareonspecifichubbutton->class = 'centeredbutton'; - $shareonspecifichubbuttonhtml = $OUTPUT->render($shareonspecifichubbutton); - $specifichubcell = $advertiseonspecifichubbuttonhtml. " " . $shareonspecifichubbuttonhtml; - } else { - $specifichubcell = html_writer::tag('span', - get_string('notregisteredonhub', 'hub') , array('class' => 'publicationwarning')); - } + $shareurl = new moodle_url("/course/publish/hubselector.php", + array('sesskey' => sesskey(), 'id' => $courseid, 'share' => true)); + $sharebutton = new single_button($shareurl, get_string('selecthubforsharing', 'hub')); + $sharebutton->class = 'centeredbutton'; + $sharecell = $OUTPUT->render($sharebutton); //add button cells - $cells = array($moodleorgcell, $specifichubcell); + $cells = array($advertisecell, $sharecell); $row = new html_table_row($cells); $table->data[] = $row; @@ -104,4 +75,80 @@ class core_publish_renderer extends plugin_renderer_base { } + /** + * Display the listing of hub where a course is registered on + */ + public function registeredonhublisting($courseid, $publications) { + global $OUTPUT; + + $table = new html_table(); + $table->head = array(get_string('type', 'hub'), get_string('hub', 'hub'), get_string('date'), get_string('operation', 'hub')); + $table->size = array('10%', '50%', '30%', '%10'); + + foreach ($publications as $publication) { + + $updatebuttonhtml = ''; + + if ($publication->enrollable) { + $params = array('sesskey' => sesskey(), 'id' => $publication->courseid, + 'huburl' => $publication->huburl, 'hubname' => $publication->hubname, + 'share' => !$publication->enrollable, 'advertise' => $publication->enrollable); + $updateurl = new moodle_url("/course/publish/metadata.php", $params); + $updatebutton = new single_button($updateurl, get_string('update', 'hub')); + $updatebutton->class = 'centeredbutton'; + $updatebuttonhtml = $OUTPUT->render($updatebutton); + } + + $params = array('sesskey' => sesskey(), 'id' => $publication->courseid, 'hubcourseid' => $publication->hubcourseid, + 'huburl' => $publication->huburl, 'hubname' => $publication->hubname, + 'cancel' => true, 'publicationid' => $publication->id, 'timepublished' => $publication->timepublished); + $cancelurl = new moodle_url("/course/publish/index.php", $params); + $cancelbutton = new single_button($cancelurl, get_string('cancel', 'hub')); + $cancelbutton->class = 'centeredbutton'; + $cancelbuttonhtml = $OUTPUT->render($cancelbutton); + + if (!empty($updatebuttonhtml)) { + $brtag = html_writer::empty_tag('br'); + $operations = $updatebuttonhtml . $brtag . $cancelbuttonhtml; + } else { + $operations = $cancelbuttonhtml; + } + + $hubname = html_writer::tag('a', $publication->hubname?$publication->hubname:$publication->huburl, + array('href' => $publication->huburl)); + + //add button cells + $cells = array($publication->enrollable?get_string('advertised', 'hub'):get_string('uploaded', 'hub'), + $hubname, userdate($publication->timepublished),$operations); + $row = new html_table_row($cells); + $table->data[] = $row; + + } + + return html_writer::table($table); + + } + + /** + * Display unpublishing confirmation page + * @param object $publication + * $publication->courseshortname + $publication->courseid + $publication->hubname + $publication->huburl + $publication->id + */ + public function confirmunpublishing($publication) { + global $OUTPUT; + $optionsyes = array('sesskey' => sesskey(), 'id' => $publication->courseid, 'hubcourseid' => $publication->hubcourseid, + 'huburl' => $publication->huburl, 'hubname' => $publication->hubname, + 'cancel' => true, 'publicationid' => $publication->id, 'confirm' => true); + $optionsno = array('sesskey'=>sesskey(), 'id' => $publication->courseid); + $publication->hubname = html_writer::tag('a', $publication->hubname, + array('href' => $publication->huburl)); + $formcontinue = new single_button(new moodle_url("/course/publish/index.php", $optionsyes), get_string('unpublish', 'hub'), 'post'); + $formcancel = new single_button(new moodle_url("/course/publish/index.php", $optionsno), get_string('cancel'), 'get'); + return $OUTPUT->confirm(get_string('unpublishconfirmation', 'hub', $publication), $formcontinue, $formcancel); + } + } \ No newline at end of file diff --git a/lang/en/hub.php b/lang/en/hub.php index cf9e63cb1ec..b1f851069fb 100644 --- a/lang/en/hub.php +++ b/lang/en/hub.php @@ -26,10 +26,12 @@ $string['addedtoblock'] = 'Course added to block'; $string['advertise'] = 'Advertise this course for people to join'; +$string['advertised'] = 'Advertised'; $string['advertiseon'] = 'Advertise this course on {$a}'; +$string['readvertiseon'] = 'Update advertising information on {$a}'; $string['advertiseonhub'] = 'Advertise this course on the hub'; $string['advertiseonmoodleorg'] = 'Advertise this course on moodle.org'; -$string['advertiseonspecifichub'] = 'Advertise this course on a specific hub'; +$string['advertisepublicationdetail'] = 'Publishing your course makes it available to the world.'; $string['all'] = 'All'; $string['allowglobalsearch'] = 'Publish this hub and allow global search of all courses'; $string['allowpublicsearch'] = 'Publish this hub so people can join it'; @@ -39,6 +41,7 @@ $string['audienceeducators'] = 'Educators'; $string['audiencestudents'] = 'Students'; $string['audienceadmins'] = 'Administators'; $string['badurlformat'] = 'Bad URL format'; +$string['cancel'] = 'Cancel'; $string['community'] = 'Community'; $string['communityremoved'] = 'That course link has been removed from your list'; $string['confirmregistration'] = 'Confirm registration'; @@ -54,10 +57,11 @@ $string['coursemap'] = 'Course map'; $string['coursename'] = 'Name'; $string['courseprivate'] = 'Private'; $string['coursepublic'] = 'Public'; -$string['coursepublished'] = 'Course published'; +$string['coursepublished'] = 'Course published or updated'; $string['courseshortname'] = 'Shortname'; $string['courseshortname_help'] = 'Enter any shortname for your course. It is not an identifier (i.e many courses can have a same shortname in a search result.)'; $string['coursesnumber'] = 'Number of courses ({$a})'; +$string['courseunpublished'] = 'the course {$a->courseshortname} has been unpublished from {$a->hubname} successfully.'; $string['courseurl'] = 'Course URL'; $string['courseurl_help'] = 'Enter your course URL. By default it is the URL of your course. This url is displayed as a link in a search result.'; $string['creatorname'] = 'Creator name'; @@ -95,7 +99,6 @@ $string['licence_help'] = 'Select the licence you want to distribuate your cours $string['logourl'] = 'Logo URL'; $string['modulenumberaverage'] = 'Average number of course modules ({$a})'; $string['moodleorg'] = 'Moodle.org'; -$string['moodleorgpublicationdetail'] = 'Publishing your course on Moodle.org makes it available to the world.'; $string['moodleorgregistrationdetail'] = 'The main community hub is Moodle.org. By registering your site here your information will contribute to the statistics of the worldwide Moodle community. You also have the option of joining a low-volume mailing list to receive important early notifications of security fixes and new releases of Moodle.'; $string['moodleorgregistrationdetail2'] = 'This option allows you to register your Moodle site with Moodle.org. Registration is free. The main benefit of registering is that you will be added to a low-volume mailing list for important notifications such as security alerts and new releases of Moodle. @@ -120,7 +123,9 @@ $string['private'] = 'Private'; $string['privatehuburl'] = 'Private hub URL'; $string['publicationinfo'] = 'Course publication information'; $string['publichub'] = 'Public hub'; +$string['publishcourse'] = 'Publish {$a}'; $string['publishcourseon'] = 'Publish on {$a}'; +$string['publishedon'] = 'Published on'; $string['publishername'] = 'Publisher'; $string['publishername_help'] = 'The publisher is the person publishing the course. Most of the time it should be you, except if you do it on the behalf of someone else.'; $string['publishon'] = 'Publish on'; @@ -143,6 +148,8 @@ $string['screenshots'] = 'Screenshots'; $string['screenshots_help'] = 'Screenshots will displayed during search results.'; $string['search'] = 'Search'; $string['selecthub'] = 'Select hub'; +$string['selecthubforadvertise'] = 'Select hub for advertising'; +$string['selecthubforsharing'] = 'Select hub for uploading'; $string['sendfollowinginfo'] = 'Send the following information:'; $string['settings'] = 'Settings'; $string['settingsupdated'] = 'Settings have been updated.'; @@ -150,7 +157,7 @@ $string['share'] = 'Upload your course'; $string['shareon'] = 'Upload your course to {$a}'; $string['shareonhub'] = 'Upload your course to a hub'; $string['shareonmoodleorg'] = 'Upload your course to Moodle.org'; -$string['shareonspecifichub'] = 'Upload your course to a specific hub'; +$string['sharepublicationdetail'] = 'You can upload on a community hub.'; $string['siteadmin'] = 'Administrator'; $string['sitecreated'] = 'Site created'; $string['sitedesc'] = 'Description'; @@ -163,17 +170,22 @@ $string['siteurl'] = 'Site URL'; $string['subject'] = 'Subject'; $string['subject_help'] = 'The main course subject.'; $string['specifichub'] = 'Specific hub'; -$string['specifichubpublicationdetail'] = 'You can publish on another community hub if your site administrator has configured one.'; $string['specifichubregistrationdetail'] = 'You can also register your site with other community hubs.'; $string['statistics'] = 'Statistics privacy'; $string['subject'] = 'Subject'; $string['tags'] = 'Tags'; $string['tags_help'] = 'Your course can be searched against these tag words. Separate your tag words with a comma. Example: math, algebric, geometry'; $string['trustme'] = 'Trust'; +$string['type'] = 'Type'; $string['unlistedurl'] = 'Unlisted hub URL'; $string['unprioritise'] = 'Unprioritise'; +$string['unpublish'] = 'Unpublish'; +$string['unpublishconfirmation'] = 'Do you really want to unpublish the course {$a->courseshortname} from the hub {$a->hubname}'; +$string['unpublishcourse'] = 'Unpublish {$a}'; $string['untrustme'] = 'Untrust'; +$string['update'] = 'Update'; $string['updatesite'] = 'Update registration on {$a}'; +$string['uploaded'] = 'Uploaded'; $string['url'] = 'hub URL'; $string['usersnumber'] = 'Number of users ({$a})'; $string['wrongtoken'] = 'The registration failed. Press continue and try again.'; diff --git a/lib/hublib.php b/lib/hublib.php index cb9dba3ce1b..9f70aa4c17b 100644 --- a/lib/hublib.php +++ b/lib/hublib.php @@ -222,6 +222,19 @@ class hub { array('hubcourseid' => $hubcourseid)); } + public function get_course_publications($courseid) { + global $DB; + $sql = 'SELECT cp.id, cp.timepublished, rh.hubname, rh.huburl, cp.courseid, cp.enrollable, cp.hubcourseid + FROM {course_published} cp, {registration_hubs} rh + WHERE cp.hubid = rh.id + ORDER BY cp.enrollable DESC, rh.hubname, cp.timepublished'; + return $DB->get_records_sql($sql); + } + + public function delete_publication($publicationid) { + global $DB; + $DB->delete_records('course_published', array('id' => $publicationid)); + } /////////////////////////// @@ -229,7 +242,6 @@ class hub { /////////////////////////// - /** * Return site information for a specific hub * @param string $huburl diff --git a/pix/i/publish.png b/pix/i/publish.png index da279c1360a0ef7028851674829b7d24bae92404..6d0d7f74c0d89a5d1975eb65c3e048ace0290daf 100644 GIT binary patch delta 917 zcmV;G18V&J1gr;;C4Xl@O+f$vugEtAis=9V02y>eSaefwW^{L9a%BKPWN%_+AW3au zXJt}lVPtu6$z?nM00TZrL_t&-83n=1Ph3?1z~SG0%##_I0ftV&v4%dRS{|(+q<}_k zt;R=UqHZ)MuyEI~aN|E<(wG<%Q@b!xNi=FVrYlj}rZxzngnw#_fap*Q4UYmc!`vC} z+{Zch_43E`2um_0IqR0Gd(?fRV{z6Bq^Fd@Xk- zl8$At>>6wjgme&WaeZ@4NFlEZA>aP;9)iqr36R{ugu4VL1_8JeDnu zu!^v22PokY!+&PeonUrjc24->neX1ZQqlo{(Nhh_`Ujf3DM$}r*APOdD#F-=DYy}~ zofvDS5RWFFraSw1hv)j=0~p1#4+emb-#PZGF)#Poq)IgqRGb6_H-zOte!Wa-f1gNt z7p*Q&Ut=5B7iU_(xixy%=p8=!>AB|K6PgiYQx~9`IDaS;+}<*%Iy#H%6@qAy$f3V+ zYxC>`Ma-h)L__l~*Fb)$SSl#w;oGNu$g;hV!aiMrahS#T?t@YYAv9BppkR4c zOM{Uj8SP|k$HehNgrgCnO)>8MyNffEA`_k=6P+jGS(KeJV^hB%MNl$@FMeMsJZL!* z&vEVHB&qlj!bT3?u~9~fa3W2uJ3(7^iKmYD@qbADQEn_;VS0W7qgwHF-xC*qT)HU^ zB{G=yI;Gty(rFh{xP&xCL^m)i*XU~NMCy{xgJ+SNPhb0KbkE7^U%hg9+;jb(#usn$ zY)cn)Mh)piKwVf;8+J&BT#A(~LRx~?kDmwNgBQNwa8n0BNC)s;|J`5ncjo?F`HORH zJ%6;OOb)~qjYgRU-KJPBvam75g{wmVTo@nX-u4`Tqba2Tc rl#FWG)4l2eAPSU$OVbxOKKviB!MzCV_|S*E^l&Yo9;Xs0005{NklPj)IQZ%KDU>DYgNoq1==D3)AOsA;_4&0CDeb2evdzFab52c=G;Nl&V+;lJNV-9_8 zoyc~T*msxBrN8p-!vTSa&@jboUB{3dVJqEp{Ym2|U2azt`$`I!Q zVlR7mB_QIlo_~qv^|3M!le17G!Al}+a5!}8#2VwtSx*DNVg~js&)JdV%*h~^2}opLv?bRJ&n!}=Vi5DKwH7e6tm`Ho>w;3GAr1L9H{UQcOt z$*wCZ%iV0D7{DfjaIA&t)amCwigLhU?WxFvudSzil9?Z47?J`RVL(oET?V-(qeLYI zlHjKA{#@HnSv7xST&Yl)TT3x=w?h