/** * parses a date string into UNIX timestamp * * if "strict dates" is set, this function uses the DateTime or IntlDateFormatter * class to parse the string according to a specific format. If it is not, we * use the conventional strtotime() function, with the enhancement that if the * non-American style format is used with slashes "d/m/Y" the string is prepared * so strtotime can parse it correctly * * @param string $string the string to parse; if not given, defaults to now * @param object $column_atts the column object; used to identify the field for * user feedback * @param bool $zero_time if set, zero the time portion of the date so it * won't interfere with date comparisons * @return int|bool UNIX timestamp or false if parse fails */ public static function parse_date($string = false, $column = '', $zero_time = false) { if (false === $string) { return false; } $string = Participants_Db::set_filter('parse_date', $string, $column); // is it already a timestamp? if (self::is_valid_timestamp($string)) { //if (WP_DEBUG and is_object($column)) error_log(__METHOD__.' tried to parse timestamp from '. $column->name); return $string; } $date = false; // if it is a default zero timestamp, treat it as "no date" if ($string === '0000-00-00 00:00:00') { return false; } /* * we have two options to parse a date string into a timestamp: the * IntlDateFormatter class or the DateTime class. The IntlDateFormatter * class can parse localized text dates, but it seems commonly unavailable, * at least on English-speaking servers. The DateTime class is widely * available, but can't parse non-English text dates. It can parse numeric * date representations, so if the intl module is not available, we try to * use DateTime. If that is not available, we use strtotime with the added trick * of swapping the date/month if they are slashes so slashed European notation * can be correctly parsed */ self::$date_mode = 'none'; $errors = false; $the_Date = false; // test for MySQL-format timestamp $is_MySQL_timestamp = preg_match('#^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$#', $string) === 1 ? true : false; //error_log(__METHOD__.' object? '.(is_object($column)?'yes':'no').' strict dates? '.(self::plugin_setting_is_true('strict_dates', false)?'yes':'no').' timestamp? '.($is_MySQL_timestamp?'yes':'no')); if (self::plugin_setting_is_true('strict_dates', false) and is_object($column) and !$is_MySQL_timestamp) { //error_log(__METHOD__.' intl? '.(class_exists('IntlDateFormatter')?'yes':'no').' datetime? '.(class_exists('DateTime')?'yes':'no')); if (class_exists('IntlDateFormatter')) { self::$date_mode = 'Intl'; $DateFormat = new IntlDateFormatter(get_locale(), IntlDateFormatter::LONG, IntlDateFormatter::NONE, NULL, NULL, Participants_Db::get_ICU_date_format(self::$plugin_options['input_date_format'])); $DateFormat->setLenient(false); // we want it strict $timestamp = $DateFormat->parse($string); if ($DateFormat->getErrorCode() !== 0) { $errors = array('code' => $DateFormat->getErrorCode(), 'error' => $DateFormat->getErrorMessage()); } if (!$errors) { $the_Date = new DateTime(); $the_Date->setTimestamp($timestamp); } elseif (WP_DEBUG) { error_log(__METHOD__ . ' IntlDateFormatter error: format string: ' . Participants_Db::get_ICU_date_format(self::$plugin_options['input_date_format']) . ' timestamp: ' . $timestamp . ' formatter error: ' . $DateFormat->getErrorMessage()); } } if (!$the_Date && class_exists('DateTime')) { self::$date_mode = 'DateTime'; $the_Date = DateTime::createFromFormat(self::$plugin_options['input_date_format'], $string); } if (is_object($the_Date)) { $errors = $the_Date->getLastErrors(); if ($errors['warning_count'] === 0 && $errors['error_count'] === 0) { $errors = false; } } if (is_array($errors) && !empty($string)) { $the_Date = false; if (is_object(self::$validation_errors) and is_object($column)) { self::$validation_errors->add_error($column->name, sprintf(__('The date for "%s" was invalid. Please input the date with the exact format shown', 'participants-database'), $column->title)); } if (WP_DEBUG) { error_log(__METHOD__ . ' DateTime parse error: ' . implode(', ', $errors)); } } /* * if we have a valid date, convert to timestamp */ if ($the_Date) { /* * zero the time so date equality comparisons can be made */ if ($zero_time) { $the_Date->setTime(0, 0); } $date = $the_Date->format('U'); } } /* * if we haven't got a timestamp, parse the date the regular way */ if ($date === false or !self::is_valid_timestamp($date)) { $date = false; // no valid date yet if (is_object($column) && $column->form_element == 'timestamp') { if ($zero_time) { /* * we need to zero the time, we first try to do it using the DateTime class */ $the_Date = new DateTime($string); if (is_object($the_Date)) { $the_Date->setTime(0, 0); $string = $the_Date->format(self::$date_format); } else { /* * remove the time portion of the timestamp */ $string = preg_replace('# [0-9]{2}:[0-9]{2}:[0-9]{2}$#', '', $string); $string .= ' 00:00 -0'; } } } /* * @version 1.6 * Most of the time, the default PHP timezone is the current setting, but * experience has shown it's necessary to reset it for the conversion to make * sure. We also must assume that the database server and PHP server are on * the same TZ. */ date_default_timezone_set(self::get_timezone()); setlocale(LC_ALL, get_locale()); /* * @version 1.6 * added strptime method for locaized dates * * this only works for known formats...so timestamps and when "strict dates" is enabled */ if (function_exists('strptime') && (self::plugin_setting_is_true('strict_dates', false) || $is_MySQL_timestamp)) { self::$date_mode = 'strptime'; if ($is_MySQL_timestamp) { $format = '%Y-%m-%d'; } else { $format_setting = Participants_Db::plugin_setting_is_set('input_date_format') ? Participants_Db::plugin_setting('input_date_format') : get_bloginfo('date_format'); $format = Participants_Db::translate_date_format($format_setting, 'strftime'); } $date_array = strptime($string, $format); $date = mktime($date_array['tm_hour'], $date_array['tm_min'], $date_array['tm_sec'], $date_array['tm_mon'] + 1, $date_array['tm_mday'], $date_array['tm_year'] + 1900); } if ($date === false) { self::$date_mode = 'strtotime'; $date = strtotime(self::date_order_fix($string)); } } return $date; }
/** * prints the main body of the list, including headers * * @param string $mode dtermines the print mode: 'noheader' skips headers, (other choices to be determined) */ private static function _main_table($mode = '') { $hscroll = Participants_Db::plugin_setting_is_true('admin_horiz_scroll'); ?> <?php if ($hscroll) { ?> <div class="pdb-horiz-scroll-scroller"> <div class="pdb-horiz-scroll-width" style="width: <?php echo count(self::$display_columns) * 10; ?> em"> <?php } ?> <table class="wp-list-table widefat fixed pages pdb-list stuffbox" cellspacing="0" > <?php $PID_pattern = '<td><a href="%2$s">%1$s</a></td>'; //template for outputting a column $col_pattern = '<td>%s</td>'; if (count(self::$participants) > 0) { if ($mode != 'noheader') { ?> <thead> <tr> <?php self::_print_header_row(); ?> </tr> </thead> <?php } // table header row // print the table footer row if there is a long list if ($mode != 'noheader' && count(self::$participants) > 10) { ?> <tfoot> <tr> <?php self::_print_header_row(); ?> </tr> </tfoot> <?php } // table footer row ?> <tbody> <?php // output the main list foreach (self::$participants as $value) { ?> <tr> <?php // print delete check ?> <td> <?php if (current_user_can(Participants_Db::plugin_capability('plugin_admin_capability', 'delete participants'))) { ?> <input type="checkbox" class="delete-check" name="pid[]" value="<?php echo $value['id']; ?> " /> <?php } ?> <a href="admin.php?page=<?php echo 'participants-database'; ?> -edit_participant&action=edit&id=<?php echo $value['id']; ?> " title="<?php _e('Edit', 'participants-database'); ?> "><span class="glyphicon glyphicon-edit"></span></a> </td> <?php foreach (self::$display_columns as $column) { // this is where we place form-element-specific text transformations for display switch ($column->form_element) { case 'image-upload': $image_params = array('filename' => basename($value[$column->name]), 'link' => '', 'mode' => Participants_Db::plugin_setting_is_true('admin_thumbnails') ? 'image' : 'filename'); if (Participants_Db::is_single_record_link($column)) { $page_link = get_permalink(Participants_Db::plugin_setting('single_record_page')); $image_params['link'] = Participants_Db::add_uri_conjunction($page_link) . 'pdb=' . $value['id']; } // this is to display the image as a linked thumbnail $image = new PDb_Image($image_params); $display_value = $image->get_image_html(); break; case 'date': case 'timestamp': if (!empty($value[$column->name])) { $format = Participants_Db::$date_format; if (Participants_Db::plugin_setting_is_true('show_time') and $column->form_element == 'timestamp') { // replace spaces with so the time value stays together on a broken line $format .= ' ' . str_replace(' ', '&\\nb\\sp;', get_option('time_format')); } $time = Participants_Db::is_valid_timestamp($value[$column->name]) ? (int) $value[$column->name] : Participants_Db::parse_date($value[$column->name], $column->name, $column->form_element == 'date'); $display_value = $value[$column->name] == '0000-00-00 00:00:00' ? '' : date_i18n($format, $time); //$display_value = date_i18n($format, $time); } else { $display_value = ''; } break; case 'multi-select-other': case 'multi-checkbox': // multi selects are displayed as comma separated lists $column->value = $value[$column->name]; $display_value = PDb_FormElement::get_field_value_display($column, false); //$display_value = is_serialized($value[$column->name]) ? implode(', ', unserialize($value[$column->name])) : $value[$column->name]; break; case 'link': $link_value = maybe_unserialize($value[$column->name]); if (count($link_value) === 1) { $link_value = array_fill(0, 2, current((array) $link_value)); } $display_value = Participants_Db::make_link($link_value[0], $link_value[1]); break; case 'rich-text': if (!empty($value[$column->name])) { $display_value = '<span class="textarea">' . $value[$column->name] . '</span>'; } else { $display_value = ''; } break; case 'text-line': if (Participants_Db::is_single_record_link($column)) { $url = get_permalink(Participants_Db::plugin_setting('single_record_page')); $template = '<a href="%1$s" >%2$s</a>'; $delimiter = false !== strpos($url, '?') ? '&' : '?'; $url = $url . $delimiter . 'pdb=' . $value['id']; $display_value = sprintf($template, $url, $value[$column->name]); } elseif (Participants_Db::plugin_setting_is_true('make_links')) { $field = new stdClass(); $field->value = $value[$column->name]; $display_value = PDb_FormElement::make_link($field); } else { $display_value = $value[$column->name] === '' ? $column->default : esc_html($value[$column->name]); } break; case 'hidden': $display_value = $value[$column->name] === '' ? '' : esc_html($value[$column->name]); break; default: $column->value = $value[$column->name]; $display_value = PDb_FormElement::get_field_value_display($column, false); } if ($column->name === 'private_id' && Participants_Db::plugin_setting_is_set('registration_page')) { printf($PID_pattern, $display_value, Participants_Db::get_record_link($display_value)); } else { printf($col_pattern, $display_value); } } ?> </tr> <?php } ?> </tbody> <?php } else { // if there are no records to show; do this ?> <tbody> <tr> <td><?php _e('No records found', 'participants-database'); ?> </td> </tr> </tbody> <?php } // participants array ?> </table> <?php if ($hscroll) { ?> </div> </div> <?php } ?> </form> <?php }