/** * get form fields to change the day * * @see overlays/overlay.php * * @param array hosting attributes * @return a list of ($label, $input, $hint) */ function get_fields($host, $field_pos = NULL) { global $context; $options = '<input type="hidden" name="time_stamp" value="12:00" />' . '<input type="hidden" name="duration" value="1440" />'; // default value is now if (!isset($this->attributes['date_stamp']) || $this->attributes['date_stamp'] <= NULL_DATE) { $this->attributes['date_stamp'] = gmstrftime('%Y-%m-%d %H:%M', time() + Surfer::get_gmt_offset() * 3600); } else { $this->attributes['date_stamp'] = Surfer::from_GMT($this->attributes['date_stamp']); } // split date from time list($date, $time) = explode(' ', $this->attributes['date_stamp']); // event time $label = i18n::s('Date'); $input = Skin::build_input_time('date_stamp', $date, 'date') . $options; $hint = i18n::s('Use format YYYY-MM-DD'); $fields[] = array($label, $input, $hint); // ensure that we do have a date Page::insert_script('func' . 'tion validateOnSubmit(container) {' . "\n" . "\n" . ' if(!Yacs.trim(container.date_stamp.value)) {' . "\n" . ' alert("' . i18n::s('Please provide a date.') . '");' . "\n" . ' container.date_stamp.focus();' . "\n" . ' Yacs.stopWorking();' . "\n" . ' return false;' . "\n" . ' }' . "\n\n" . ' return true;' . "\n" . '}' . "\n"); return $fields; }
/** * add some tabs * * Manage the event in a separate panel * * Accepted action codes: * - 'edit' - embedded into the main form page * * @see overlays/overlay.php * * @param string the on-going action * @param array the hosting record * @return an array of array('tab_id', 'tab_label', 'panel_id', 'panel_content') or NULL */ function &get_tabs($variant = 'view', $host = NULL) { global $context, $local; // returned tabs $tabs = array(); $now = strftime('%Y-%m-%d %H:%M:%S', time() + (Surfer::get_gmt_offset() - intval($context['gmt_offset'])) * 3600); // trackings // $manage = ''; $fields = array(); // manage the event if ($variant == 'edit') { // event preparation $manage .= Skin::build_block(i18n::s('Event preparation'), 'header2'); // induction message $label = i18n::s('Induction message'); if (!isset($this->attributes['induction_message'])) { $this->attributes['induction_message'] = $this->get_induction_default_message(); } $input = Surfer::get_editor('induction_message', $this->attributes['induction_message']); $hint = i18n::s('Displayed until the beginning of the event.'); $fields[] = array($label, $input, $hint); // other event details $fields = array_merge($fields, $this->get_event_fields()); // should we manage enrolment? if ($this->with_enrolment()) { // enrolment $label = i18n::s('Enrolment'); // none if (!isset($this->attributes['enrolment'])) { $this->attributes['enrolment'] = 'none'; } $input = '<input type="radio" name="enrolment" value="none"'; if (!isset($this->attributes['enrolment']) || $this->attributes['enrolment'] == 'none') { $input .= ' checked="checked"'; } $input .= '/> ' . i18n::s('Any page visitor can participate') . BR; // apply-and-validate $input .= '<input type="radio" name="enrolment" value="validate"'; if (!isset($this->attributes['enrolment']) || $this->attributes['enrolment'] == 'validate') { $input .= ' checked="checked"'; } $input .= '/> ' . i18n::s('Accept applications, to be confirmed by page owner') . BR; // manual registration $input .= '<input type="radio" name="enrolment" value="manual"'; if (isset($this->attributes['enrolment']) && $this->attributes['enrolment'] == 'manual') { $input .= ' checked="checked"'; } $input .= '/> ' . i18n::s('Registration is managed by page owner') . BR; // expand the form $fields[] = array($label, $input); } $manage .= Skin::build_form($fields); $fields = array(); // meeting initiation $manage .= Skin::build_block(i18n::s('During the event'), 'header2'); // lobby message $label = i18n::s('Lobby message'); if (!isset($this->attributes['lobby_message'])) { $this->attributes['lobby_message'] = $this->get_lobby_default_message(); } $input = '<textarea name="lobby_message" rows="2" cols="50">' . encode_field($this->attributes['lobby_message']) . '</textarea>'; $hint = i18n::s('Displayed one hour ahead the beginning of the event.'); $fields[] = array($label, $input, $hint); // welcome message $label = i18n::s('Welcome message'); if (!isset($this->attributes['welcome_message'])) { $this->attributes['welcome_message'] = ''; } $input = Surfer::get_editor('welcome_message', $this->attributes['welcome_message']); $hint = i18n::s('Displayed only during the event.'); $fields[] = array($label, $input, $hint); // assemble the form $manage .= Skin::build_form($fields); $fields = array(); // event follow-up $manage .= Skin::build_block(i18n::s('After the event'), 'header2'); // splash message $label = i18n::s('Follow-up message'); if (!isset($this->attributes['follow_up_message'])) { $this->attributes['follow_up_message'] = $this->get_follow_up_default_message(); } $input = Surfer::get_editor('follow_up_message', $this->attributes['follow_up_message']); $hint = i18n::s('Congratulate participants, and drive people to complementary information or action.'); $fields[] = array($label, $input, $hint); $manage .= Skin::build_form($fields); $fields = array(); } // finalize this tab if ($manage) { $tabs[] = array('management', i18n::s('Management'), 'management_panel', $manage); } // add these tabs return $tabs; }
/** * adjust a date to UTC time zone * * Use this function to convert dates received from surfer time zone * before saving them in the database. * * You should apply this function only to data received from web forms. * * @param string a stamp written on the 'YYYY-MM-DD HH:MM:SS' model * @return string a rewrite of the stamp in the UTC time zone */ public static function to_GMT($stamp) { // sanity check if (!isset($stamp) || $stamp <= NULL_DATE) { return $stamp; } // time in surfer time zone $stamp = mktime(intval(substr($stamp, 11, 2)), intval(substr($stamp, 14, 2)), intval(substr($stamp, 17, 2)), intval(substr($stamp, 5, 2)), intval(substr($stamp, 8, 2)), intval(substr($stamp, 0, 4))); // shift to UTC time zone return strftime('%Y-%m-%d %H:%M:%S', $stamp - Surfer::get_gmt_offset() * 3600); }
/** * format a time stamp * * Accept either a time stamp, or a formatted string as input parameter: * - YYYY-MM-DD HH:MM:SS * - YYMMDD HH:MM:SS GMT * * @param int or string the time to be displayed * @param string the variant -- reserved for future use * @param string the language to express this stamp * @return string the HTML to be used */ public static function &build_time($stamp, $variant = NULL, $language = NULL) { global $context, $local; // return by reference $output = ''; // sanity check if (!isset($stamp) || !$stamp) { return $output; } // surfer offset $surfer_offset = Surfer::get_gmt_offset(); // YYMMDD-HH:MM:SS GMT -- this one is natively GMT if (preg_match('/GMT$/', $stamp) && strlen($stamp) == 19) { // YYMMDD-HH:MM:SS GMT -> HH, MM, SS, MM, DD, YY $actual_stamp = mktime(substr($stamp, 7, 2), substr($stamp, 10, 2), substr($stamp, 13, 2), substr($stamp, 2, 2), substr($stamp, 4, 2), substr($stamp, 0, 2)); // adjust to surfer time zone $actual_stamp += $surfer_offset * 3600; // time()-like stamp } elseif (intval($stamp) > 1000000000) { // adjust to surfer time zone $actual_stamp = intval($stamp) + $surfer_offset * 3600; // YYYY-MM-DD HH:MM:SS, or a string that can be readed } elseif (($actual_stamp = strtotime($stamp)) != -1) { // adjust to surfer time zone $actual_stamp += $surfer_offset * 3600; } else { $output = '*' . $stamp . '*'; return $output; } if (!($items = @getdate($actual_stamp))) { $output = '*' . $stamp . '*'; return $output; } // if undefined language, use surfer language if (!$language) { $language = $context['language']; } // format the time $local['label_en'] = date('h:i a', $actual_stamp); $local['label_fr'] = date('H:i', $actual_stamp); $output = i18n::user('label'); return $output; }
/** * stamp an article * * This function is used to change various dates for one article. * * [*] If a publication date is provided, it is saved along the article. * An optional expiry date will be saved as well. * * [*] If only an expiry date is provided, it is saved along the article. * * [*] If no date is provided, the review field is updated to the current date and time. * * Dates are supposed to be in UTC time zone. * * The name of the surfer is registered as the official publisher. * As an alternative, publisher attributes ('name', 'id' and 'address') can be provided * in parameters. * * @param int the id of the item to publish * @param string the target publication date, if any * @param string the target expiration date, if any * @param array attributes of the publisher, if any * @return string either a null string, or some text describing an error to be inserted into the html response * * @see articles/publish.php * @see sections/manage.php **/ public static function stamp($id, $publication = NULL, $expiry = NULL, $publisher = NULL) { global $context; // id cannot be empty if (!$id || !is_numeric($id)) { return i18n::s('No item has the provided id.'); } // server offset $server_offset = 0; if (isset($context['gmt_offset'])) { $server_offset = intval($context['gmt_offset']); } // surfer offset $surfer_offset = Surfer::get_gmt_offset(); // no publication time is provided if (!isset($publication) || !$publication) { $publication_stamp = 0; } elseif (preg_match('/GMT$/', $publication) && strlen($publication) == 19) { // YYMMDD-HH:MM:SS GMT -> HH, MM, SS, MM, DD, YY $publication_stamp = gmmktime(intval(substr($publication, 7, 2)), intval(substr($publication, 10, 2)), intval(substr($publication, 13, 2)), intval(substr($publication, 2, 2)), intval(substr($publication, 4, 2)), intval(substr($publication, 0, 2))); // time()-like stamp } elseif (intval($publication) > 1000000000) { // adjust to UTC time zone $publication_stamp = intval($publication) + $context['gmt_offset'] * 3600; // YYYY-MM-DD HH:MM:SS, or a string that can be readed } elseif (($publication_stamp = SQL::strtotime($publication)) != -1) { } else { return sprintf(i18n::s('"%s" is not a valid date'), $publication); } // no expiry date if (!isset($expiry) || !$expiry) { $expiry_stamp = 0; } elseif (preg_match('/GMT$/', $expiry) && strlen($expiry) == 19) { // YYMMDD-HH:MM:SS GMT -> HH, MM, SS, MM, DD, YY $expiry_stamp = gmmktime(substr($expiry, 7, 2), substr($expiry, 10, 2), substr($expiry, 13, 2), substr($expiry, 2, 2), substr($expiry, 4, 2), substr($expiry, 0, 2)); // time()-like stamp } elseif (intval($expiry) > 1000000000) { // adjust to server time zone $expiry_stamp = intval($expiry) + $context['gmt_offset'] * 3600; // YYYY-MM-DD HH:MM:SS, or a string that can be readed } elseif (($expiry_stamp = SQL::strtotime($expiry)) != -1) { } else { return sprintf(i18n::s('"%s" is not a valid date'), $expiry); } // review date $review_stamp = 0; if (!$publication_stamp && !$expiry_stamp) { $review_stamp = time(); } // shape the query $query = array(); if ($publication_stamp > 0) { $query[] = "publish_name='" . SQL::escape(isset($publisher['name']) ? $publisher['name'] : Surfer::get_name()) . "'," . "publish_id=" . SQL::escape(isset($publisher['id']) ? $publisher['id'] : Surfer::get_id()) . "," . "publish_address='" . SQL::escape(isset($publisher['address']) ? $publisher['address'] : Surfer::get_email_address()) . "'," . "publish_date='" . gmstrftime('%Y-%m-%d %H:%M:%S', $publication_stamp) . "'," . "edit_name='" . SQL::escape(isset($publisher['name']) ? $publisher['name'] : Surfer::get_name()) . "'," . "edit_id=" . SQL::escape(isset($publisher['id']) ? $publisher['id'] : Surfer::get_id()) . "," . "edit_address='" . SQL::escape(isset($publisher['address']) ? $publisher['address'] : Surfer::get_email_address()) . "'," . "edit_action='article:publish'," . "edit_date='" . gmstrftime('%Y-%m-%d %H:%M:%S') . "'"; } if ($expiry_stamp > 0) { $query[] = "expiry_date='" . gmstrftime('%Y-%m-%d %H:%M:%S', $expiry_stamp) . "'"; } if ($review_stamp > 0) { $query[] = "review_date='" . gmstrftime('%Y-%m-%d %H:%M:%S', $review_stamp) . "'"; } // update an existing record $query = "UPDATE " . SQL::table_name('articles') . " SET " . implode(',', $query) . " WHERE id = " . SQL::escape($id); if (SQL::query($query) === FALSE) { return NULL; } // remember the publication in weekly and monthly categories if ($publication_stamp > 0) { Categories::remember('article:' . $id, gmstrftime('%Y-%m-%d %H:%M:%S', $publication_stamp)); } // end of job return NULL; }
/** * add some tabs * * Display additional information in panels. * * Accepted action codes: * - 'edit' - embedded into the main form page * * @see overlays/overlay.php * * @param string the on-going action * @param array the hosting record * @return an array of array('tab_id', 'tab_label', 'panel_id', 'panel_content') or NULL */ function &get_tabs($variant = 'view', $host = NULL) { global $context, $local; // returned tabs $tabs = array(); $now = strftime('%Y-%m-%d %H:%M:%S', time() + (Surfer::get_gmt_offset() - intval($context['gmt_offset'])) * 3600); // trackings // $tracking = ''; // only associates and page owners can change the status if ($variant == 'edit' && isset($this->anchor) && $this->anchor->is_owned()) { // a table of fields $fields = array(); // owner $label = i18n::s('Owner'); if (isset($host['owner_id']) && ($user = Users::get($host['owner_id']))) { $value = $user['nick_name']; } else { $value = ''; } $input = '<input type="text" name="owner" id="owner" value ="' . encode_field($value) . '" size="25" maxlength="32" />'; $hint = i18n::s('Type some letters of the name and select in the list'); $fields[] = array($label, $input, $hint); // enable owner autocompletion Page::insert_script('$(function() { Yacs.autocomplete_names("owner",true); });'); // priority $label = i18n::s('Priority'); if (!isset($this->attributes['color'])) { $this->attributes['color'] = 'green'; } $input = self::get_color_as_radio_buttons($this->attributes['color']); $fields[] = array($label, $input); // type $label = i18n::s('Workflow'); if (!isset($this->attributes['type'])) { $this->attributes['type'] = 'incident'; } $input = '<select name="type" id="type">' . self::get_type_options($this->attributes['type']) . '</select>'; $fields[] = array($label, $input); // format these fields $tracking .= Skin::build_form($fields); $fields = array(); // to represent transitions from one step to the next one Skin::define_img('NEXT_STEP', 'overlays/next_step.gif', 'V'); // status if (!isset($this->attributes['status'])) { $this->attributes['status'] = 'on-going:suspect'; } // create_date if (!isset($host['create_date']) || !$host['create_date']) { $host['create_date'] = gmstrftime('%Y-%m-%d %H:%M:%S'); } $host['create_date'] = Surfer::from_GMT($host['create_date']); if ($this->attributes['type'] == 'feature') { $label = i18n::s('Feature request has been created on %s'); } elseif ($this->attributes['type'] == 'patch') { $label = i18n::s('Patch has been submitted on %s'); } else { $label = i18n::s('Page has been created on %s'); } $tracking .= '<div class="bottom" style="margin-bottom: 1em;">' . sprintf($label, Skin::build_input_time('create_date', $host['create_date'], 'date_time') . ' <a onclick="$(\'#create_date\').val(\'' . $now . '\')" style="cursor: pointer;" class="details">' . i18n::s('now') . '</a>') . '</div>'; $tracking .= NEXT_STEP; // qualification_date if (isset($this->attributes['qualification_date'])) { $this->attributes['qualification_date'] = Surfer::from_GMT($this->attributes['qualification_date']); } $tracking .= '<div style="margin-top: 1em">' . sprintf(i18n::s('Qualification has taken place on %s'), Skin::build_input_time('qualification_date', isset($this->attributes['qualification_date']) ? $this->attributes['qualification_date'] : NULL_DATE, 'date_time') . ' <a onclick="$(\'#qualification_date\').val(\'' . $now . '\')" style="cursor: pointer;" class="details">' . i18n::s('now') . '</a>') . '<p>'; $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'on-going:problem') { $checked = 'checked="checked"'; } $tracking .= '<input type="radio" name="status" value ="on-going:problem" ' . $checked . ' /> ' . $this->get_status_label('on-going:problem'); $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'cancelled:suspect') { $checked = 'checked="checked"'; } $tracking .= BR . '<input type="radio" name="status" value ="cancelled:suspect" ' . $checked . ' /> ' . $this->get_status_label('cancelled:suspect') . '</p></div>'; $tracking .= NEXT_STEP; // analysis_date, except for maintenance cases if ($this->attributes['type'] != 'maintenance') { if (isset($this->attributes['analysis_date'])) { $this->attributes['analysis_date'] = Surfer::from_GMT($this->attributes['analysis_date']); } $tracking .= '<div style="margin-top: 1em">' . sprintf(i18n::s('Analysis has ended on %s'), Skin::build_input_time('analysis_date', isset($this->attributes['analysis_date']) ? $this->attributes['analysis_date'] : NULL_DATE, 'date_time') . ' <a onclick="$(\'#analysis_date\').val(\'' . $now . '\')" style="cursor: pointer;" class="details">' . i18n::s('now') . '</a>') . '<p>'; $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'on-going:issue') { $checked = 'checked="checked"'; } $tracking .= '<input type="radio" name="status" value ="on-going:issue" ' . $checked . ' /> ' . $this->get_status_label('on-going:issue'); $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'cancelled:problem') { $checked = 'checked="checked"'; } $tracking .= BR . '<input type="radio" name="status" value ="cancelled:problem" ' . $checked . ' /> ' . $this->get_status_label('cancelled:problem') . '</p></div>'; $tracking .= NEXT_STEP; } // resolution_date if (isset($this->attributes['resolution_date'])) { $this->attributes['resolution_date'] = Surfer::from_GMT($this->attributes['resolution_date']); } if ($this->attributes['type'] == 'feature') { $label = i18n::s('Assignment has been finalized on %s'); } elseif ($this->attributes['type'] == 'maintenance') { $label = i18n::s('Change has been finalized on %s'); } elseif ($this->attributes['type'] == 'patch') { $label = i18n::s('Assignment has been finalized on %s'); } else { $label = i18n::s('Resolution has been finalized on %s'); } $tracking .= '<div style="margin-top: 1em">' . sprintf($label, Skin::build_input_time('resolution_date', isset($this->attributes['resolution_date']) ? $this->attributes['resolution_date'] : NULL_DATE, 'date_time') . ' <a onclick="$(\'#resolution_date\').val(\'' . $now . '\')" style="cursor: pointer;" class="details">' . i18n::s('now') . '</a>') . '<p>'; $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'on-going:solution') { $checked = 'checked="checked"'; } $tracking .= '<input type="radio" name="status" value ="on-going:solution" ' . $checked . ' /> ' . $this->get_status_label('on-going:solution'); $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'cancelled:issue') { $checked = 'checked="checked"'; } $tracking .= BR . '<input type="radio" name="status" value ="cancelled:issue" ' . $checked . ' /> ' . $this->get_status_label('cancelled:issue') . '</p></div>'; $tracking .= NEXT_STEP; // close_date if (isset($this->attributes['close_date'])) { $this->attributes['close_date'] = Surfer::from_GMT($this->attributes['close_date']); } $tracking .= '<div style="margin-top: 1em">' . sprintf(i18n::s('Case has been closed on %s'), Skin::build_input_time('close_date', isset($this->attributes['close_date']) ? $this->attributes['close_date'] : NULL_DATE, 'date_time') . ' <a onclick="$(\'#close_date\').val(\'' . $now . '\')" style="cursor: pointer;" class="details">' . i18n::s('now') . '</a>') . '<p>'; $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'completed:solution') { $checked = 'checked="checked"'; } $tracking .= '<input type="radio" name="status" value ="completed:solution" ' . $checked . ' /> ' . $this->get_status_label('completed:solution'); $checked = ''; if (isset($this->attributes['status']) && $this->attributes['status'] == 'cancelled:solution') { $checked = 'checked="checked"'; } $tracking .= BR . '<input type="radio" name="status" value ="cancelled:solution" ' . $checked . ' /> ' . $this->get_status_label('cancelled:solution') . '</p></div>'; } // finalize this tab if ($tracking) { $tabs[] = array('tracking', i18n::s('Tracking'), 'tracking_panel', $tracking); } // add these tabs return $tabs; }
$context['text'] .= Skin::build_block($follow_up, 'bottom'); } // display the form on GET } else { $with_form = TRUE; } // display the form if ($with_form) { // the form $context['text'] .= '<form method="post" action="' . $context['script_url'] . '" id="main_form"><div>'; // encode fields $fields = array(); // the publication date, if any $label = i18n::s('Publication date'); // adjust date from server time zone to surfer time zone $value = strftime('%Y-%m-%d %H:%M:%S', time() + (Surfer::get_gmt_offset() - intval($context['gmt_offset'])) * 3600); $input = Skin::build_input_time('publish_date', $value, 'date_time'); $hint = i18n::s('Indicate a date (YYYY-MM-DD) in the future and let YACS make the page appear automatically.'); $fields[] = array($label, $input, $hint); // advertise public pages $ping_option = FALSE; $trackback_option = FALSE; if ($anchor->is_public() && (isset($item['active']) && $item['active'] == 'Y')) { $ping_option = TRUE; $trackback_option = TRUE; } // trackback option $label = i18n::s('Trackback'); $input = '<input type="radio" name="trackback_option" value="N"'; if (!$trackback_option) { $input .= ' checked="checked"';
/** * put something into the cache * * You can store an array or another kind of structured object, but after * serialization. * * The default caching period is 20 minutes (actually, 20m*60s = 1,200s) * * @param string the id of this item * @param string the content to store * @param string the topic related to this item * @param int the maximum time before expiration, in seconds */ public static function put($id, &$text, $topic = 'global', $duration = 1200, $f_capa = true, $f_lang = true, $f_gmt_off = true) { global $context; // maybe we don't have to cache if (isset($context['without_cache']) && $context['without_cache'] == 'Y') { return; } // cache has been poisoned if (isset($context['cache_has_been_poisoned']) && $context['cache_has_been_poisoned']) { return; } // the sql back-end may be not available during software updates or on NO_MODEL_PRELOAD if (!is_callable(array('SQL', 'query'))) { return; } // cached content depends on surfer capability if ($f_capa) { $id .= '/' . Surfer::get_capability(); } // cached content depends on selected language if ($f_lang) { $id .= '/' . $context['language']; } // cached content depends on time offset if ($f_gmt_off) { $id .= '/' . Surfer::get_gmt_offset(); } // don't cache more than expected $expiry = gmstrftime('%Y-%m-%d %H:%M:%S', time() + $duration); // cache also empty content if (!$text) { $text = ' '; } // update the database; do not report on error $query = "REPLACE INTO " . SQL::table_name('cache') . " SET" . " id='" . SQL::escape($id) . "'," . " text='" . SQL::escape($text) . "'," . " topic='" . SQL::escape($topic) . "'," . " expiry_date='" . $expiry . "'," . " edit_date='" . gmstrftime('%Y-%m-%d %H:%M:%S') . "'"; SQL::query($query, TRUE); }