Index: wp-includes/functions.php =================================================================== --- wp-includes/functions.php (revision 18444) +++ wp-includes/functions.php (working copy) @@ -142,6 +142,224 @@ } /** + * Builds a regular expression allowing to match a date formatted according to the specified format + * + * @param string Format of the date + * @param string Regular expression delimiters + * @return bool|string a string representing the built regular expression, or false in case of an error or if no format element is used + */ +function build_date_parse_regexp_from_format( $format, $delimiter = '/' ) { + // Regular expressions used to parse the date + $replacements = array( + 'd' => '([0-2][0-9]|3[0-1])', + 'D' => '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)', + 'j' => '([1-9]|[1-2][0-9]|3[0-1])', + 'l' => '(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)', + 'S' => '(st|nd|rd|th)', + 'z' => '(\d{1,3})', + 'F' => '(January|February|March|April|May|June|July|August|September|October|November|December)', + 'M' => '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)', + 'm' => '(0[1-9]|1[0-2])', + 'n' => '([1-9]|1[0-2])', + 'Y' => '(\d{4})', + 'y' => '(\d{2})', + 'a' => '(am|pm)', + 'A' => '(AM|PM)', + 'g' => '([0-9]|1[0-2])', + 'h' => '(0[0-9]|1[0-2])', + 'G' => '([0-9]|1[0-9]|2[0-3])', + 'H' => '([0-1][0-9]|2[0-3])', + 'i' => '([0-5][0-9])', + 's' => '([0-5][0-9])', + 'u' => '(\d{1,6})', + 'U' => '(\d{1,10})', + 'e' => '([a-zA-Z-\/]+(?:\+\d+)?)', + 'O' => '((?:\+|-)\d{4})', + 'P' => '((?:\+|-)\d{2}:\d{2})', + 'T' => '([A-Z]+)', + ); + + // Looking for used format elements + $parsed_format = $format; + $used_replacements = array(); + foreach ( $replacements as $k => $v ) { + if ( ( $p = strpos( $format, $k ) ) !== false ) { + $parsed_format = str_replace( $k, "%{$k}%", $parsed_format ); + $used_replacements[$k] = $v; + } + } + + if ( !empty( $used_replacements ) ) { + // Computing sources elements to create the regular expression + $replacement_keys = array_map( create_function( '$a', 'return "%{$a}%";' ), array_keys( $used_replacements ) ); + + // Building the regular expression + return $delimiter . '^' . str_replace( '/', '\/', str_replace( $replacement_keys, array_values( $used_replacements ), $parsed_format ) ) . '$' . $delimiter; + } + else + return false; +} + +/** + * Get info about given date formatted according to the specified format + * + * This function is a placeholder for the PHP 5.3+ date_parse_from_format() function. + * Please visit the official function documentation for further information : + * http://fr.php.net/manual/fr/function.date-parse-from-format.php + * + * This function differs from its original version in its return values : + * it returns false in case of an error instead of including errors in the returned array + * and it does not support format modifiers such as '+' or '!' (yet) + * + * @param string Format of the date + * @param string Date to parse + * @return bool|array an array containing the date components, or false in case of an error + */ +if ( !function_exists( 'date_parse_from_format' ) ) +{ + function date_parse_from_format( $format, $date ) { + // Regular expressions used to parse the date + $replacements = array( + 'd' => '([0-2][0-9]|3[0-1])', + 'D' => array( 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ), + 'j' => '([1-9]|[1-2][0-9]|3[0-1])', + 'l' => array( 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ), + 'S' => array( 'st', 'nd', 'rd', 'th' ), + 'z' => '(\d{1,3})', + 'F' => array( 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ), + 'M' => array( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ), + 'm' => '(0[1-9]|1[0-2])', + 'n' => '([1-9]|1[0-2])', + 'Y' => '(\d{4})', + 'y' => '(\d{2})', + 'a' => '(am|pm)', + 'A' => array( 'AM', 'PM' ), + 'g' => '([0-9]|1[0-2])', + 'h' => '(0[0-9]|1[0-2])', + 'G' => '([0-9]|1[0-9]|2[0-3])', + 'H' => '([0-1][0-9]|2[0-3])', + 'i' => '([0-5][0-9])', + 's' => '([0-5][0-9])', + 'u' => '(\d{1,6})', + 'U' => '(\d{1,10})', + 'e' => '([a-zA-Z-\/]+(?:\+\d+)?)', + 'O' => '((?:\+|-)\d{4})', + 'P' => '((?:\+|-)\d{2}:\d{2})', + 'T' => '([A-Z]+)', + ); + + // Looking for used format elements + $parsed_format = $format; + $used_replacements = array(); + $used_replacements_indices = array(); + foreach ( $replacements as $k => $v ) { + if ( ( $p = strpos( $format, $k ) ) !== false ) { + $parsed_format = str_replace( $k, "%{$k}%", $parsed_format ); + $used_replacements[$k] = $v; + $used_replacements_indices[$p] = $k; + } + } + + // If a format element has been found + if ( !empty( $used_replacements ) ) { + // Sort format elements to be in the same order as the results of the regular expression + ksort( $used_replacements_indices ); + + // Computing sources and replacements elements to create the regular expression + $replacement_keys = array_map( create_function( '$a', 'return "%{$a}%";' ), array_keys( $used_replacements ) ); + $replacement_values = array_map( create_function( '$a', 'return is_array($a) ? ("(" . implode("|", $a) . ")") : $a;' ), array_values( $used_replacements ) ); + + // Applying the regular expression + $regexp = '/^' . str_replace( '/', '\/', str_replace( $replacement_keys, $replacement_values, $parsed_format ) ) . '$/'; + if ( !preg_match( $regexp, $date, $regs ) ) + return false; + + // Retrieving regular expression result for each format element + $members = array(); + $i = 1; + foreach ( $used_replacements_indices as $v ) { + $members[$v] = $regs[$i++]; + } + + // Computing results + $result = array( + 'day' => false, + 'month' => false, + 'year' => false, + 'hour' => 0, + 'minute' => 0, + 'second' => 0, + 'fraction' => false + ); + foreach ( $members as $k => $v ) { + switch ($k) + { + case 'd': + case 'j': + $result['day'] = intval( $v ); + break; + + case 'M': + case 'F': + $result['month'] = array_search( $v, $replacements[$k] ) + 1; + break; + + case 'm': + case 'n': + $result['month'] = intval( $v ); + break; + + case 'Y': + $result['year'] = intval( $v ); + break; + + case 'y': + $result['year'] = intval( $v ); + if ( $result['year'] < 70 ) + $result['year'] += 2000; + else + $result['year'] += 1900; + break; + + case 'H': + case 'h': + $result['hour'] = intval( $v ); + if ( ( !empty( $members['a'] ) && $members['a'] == 'pm' ) || ( !empty( $members['A'] ) && $members['A'] == 'PM' ) ) + $result['hour'] += 12; + break; + + case 'i': + $result['minute'] = intval( $v ); + break; + + case 's': + $result['second'] = intval( $v ); + break; + + case 'u': + $result['fraction'] = floatval( $v ); + break; + + case 'U': + $ts = intval($v); + $result['day'] = date( 'j', $ts ); + $result['month'] = date( 'n', $ts ); + $result['year'] = date( 'Y', $ts ); + $result['hour'] = date( 'G', $ts ); + $result['minute'] = date( 'i', $ts ); + $result['second'] = date( 's', $ts ); + $result = array_map( 'intval', $result ); + break; + } + } + return $result; + } + else + return false; + } +} + +/** * Convert integer number to format based on the locale. * * @since 2.3.0 Index: wp-includes/script-loader.php =================================================================== --- wp-includes/script-loader.php (revision 18444) +++ wp-includes/script-loader.php (working copy) @@ -68,7 +68,69 @@ $scripts->add_data( 'common', 'group', 1 ); $scripts->localize( 'common', 'commonL10n', array( 'warnDelete' => __("You are about to permanently delete the selected items.\n 'Cancel' to stop, 'OK' to delete."), - 'l10n_print_after' => 'try{convertEntities(commonL10n);}catch(e){};' + 'l10n_print_after' => 'try{convertEntities(commonL10n);}catch(e){};', + + 'datePicker_dateFormat' => __('mm/dd/yy'), + 'datePicker_firstDay' => get_option('start_of_week'), + 'datePicker_nextText' => __('Next'), + 'datePicker_prevText' => __('Prev'), + + 'datePicker_month01' => __('January'), + 'datePicker_month02' => __('February'), + 'datePicker_month03' => __('March'), + 'datePicker_month04' => __('April'), + 'datePicker_month05' => __('May'), + 'datePicker_month06' => __('June'), + 'datePicker_month07' => __('July'), + 'datePicker_month08' => __('August'), + 'datePicker_month09' => __('September'), + 'datePicker_month10' => __('October'), + 'datePicker_month11' => __('November'), + 'datePicker_month12' => __('December'), + + 'datePicker_monthS01' => __('Jan'), + 'datePicker_monthS02' => __('Feb'), + 'datePicker_monthS03' => __('Mar'), + 'datePicker_monthS04' => __('Apr'), + 'datePicker_monthS05' => __('May'), + 'datePicker_monthS06' => __('Jun'), + 'datePicker_monthS07' => __('Jul'), + 'datePicker_monthS08' => __('Aug'), + 'datePicker_monthS09' => __('Sep'), + 'datePicker_monthS10' => __('Oct'), + 'datePicker_monthS11' => __('Nov'), + 'datePicker_monthS12' => __('Dec'), + + 'datePicker_day1' => __('Sunday'), + 'datePicker_day2' => __('Monday'), + 'datePicker_day3' => __('Tuesday'), + 'datePicker_day4' => __('Wednesday'), + 'datePicker_day5' => __('Thursday'), + 'datePicker_day6' => __('Friday'), + 'datePicker_day7' => __('Saturday'), + + 'datePicker_dayS1' => __('Sun'), + 'datePicker_dayS2' => __('Mon'), + 'datePicker_dayS3' => __('Tue'), + 'datePicker_dayS4' => __('Wed'), + 'datePicker_dayS5' => __('Thu'), + 'datePicker_dayS6' => __('Fri'), + 'datePicker_dayS7' => __('Sat'), + + 'datePicker_dayM1' => __('Su'), + 'datePicker_dayM2' => __('Mo'), + 'datePicker_dayM3' => __('Tu'), + 'datePicker_dayM4' => __('We'), + 'datePicker_dayM5' => __('Th'), + 'datePicker_dayM6' => __('Fr'), + 'datePicker_dayM7' => __('Sa'), + + 'timePicker_hourText' => __('Hour'), + 'timePicker_minuteText' => __('Minute'), + + 'date_regexp' => str_replace( '\\', '\\\\', build_date_parse_regexp_from_format( __('m/d/Y'), '' ) ), + 'date_components_order' => __('month,day,year'), + 'time_regexp' => str_replace( '\\', '\\\\', build_date_parse_regexp_from_format( __('H:i'), '' ) ) ) ); $scripts->add( 'sack', "/wp-includes/js/tw-sack$suffix.js", false, '1.6.1' ); @@ -164,7 +226,13 @@ $scripts->add( 'jquery-ui-dialog', '/wp-includes/js/jquery/ui.dialog.js', array('jquery-ui-resizable', 'jquery-ui-draggable', 'jquery-ui-button', 'jquery-ui-position'), '1.8.12' ); $scripts->add_data( 'jquery-ui-dialog', 'group', 1 ); + + $scripts->add( 'jquery-ui-timepicker', '/wp-includes/js/jquery/ui.timepicker.js', array('jquery-ui-core'), '1.8.12' ); + $scripts->add_data( 'jquery-ui-widget', 'group', 1 ); + $scripts->add( 'jquery-ui-datepicker', '/wp-includes/js/jquery/ui.datepicker.js', array('jquery-ui-core'), '1.8.12' ); + $scripts->add_data( 'jquery-ui-widget', 'group', 1 ); + // deprecated, not used in core, most functionality is included in jQuery 1.3 $scripts->add( 'jquery-form', "/wp-includes/js/jquery/jquery.form$suffix.js", array('jquery'), '2.73'); $scripts->add_data( 'jquery-form', 'group', 1 ); @@ -516,6 +584,10 @@ $styles->add( 'admin-bar', "/wp-includes/css/admin-bar$suffix.css", array(), '20110622' ); $styles->add( 'wp-jquery-ui-dialog', "/wp-includes/css/jquery-ui-dialog$suffix.css", array(), '20101224' ); $styles->add( 'wplink', "/wp-includes/js/tinymce/plugins/wplink/css/wplink$suffix.css", array(), '20101224' ); + $styles->add( 'jquery-ui-core', "/wp-includes/css/jquery-ui-core.css", array(), '20110717' ); + $styles->add( 'jquery-ui-theme', "/wp-includes/css/jquery-ui-theme.css", array(), '20110717' ); + $styles->add( 'jquery-ui-timepicker', "/wp-includes/css/jquery-ui-timepicker.css", array(), '20110622' ); + $styles->add( 'jquery-ui-datepicker', "/wp-includes/css/jquery-ui-datepicker.css", array(), '20110717' ); foreach ( $rtl_styles as $rtl_style ) { $styles->add_data( $rtl_style, 'rtl', true ); Index: wp-admin/includes/post.php =================================================================== --- wp-admin/includes/post.php (revision 18444) +++ wp-admin/includes/post.php (working copy) @@ -101,7 +101,7 @@ if (!isset( $post_data['ping_status'] )) $post_data['ping_status'] = 'closed'; - foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) { + foreach ( array('dd', 'tt') as $timeunit ) { if ( !empty( $post_data['hidden_' . $timeunit] ) && $post_data['hidden_' . $timeunit] != $post_data[$timeunit] ) { $post_data['edit_date'] = '1'; break; @@ -109,21 +109,26 @@ } if ( !empty( $post_data['edit_date'] ) ) { - $aa = $post_data['aa']; - $mm = $post_data['mm']; - $jj = $post_data['jj']; - $hh = $post_data['hh']; - $mn = $post_data['mn']; - $ss = $post_data['ss']; - $aa = ($aa <= 0 ) ? date('Y') : $aa; - $mm = ($mm <= 0 ) ? date('n') : $mm; - $jj = ($jj > 31 ) ? 31 : $jj; - $jj = ($jj <= 0 ) ? date('j') : $jj; - $hh = ($hh > 23 ) ? $hh -24 : $hh; - $mn = ($mn > 59 ) ? $mn -60 : $mn; - $ss = ($ss > 59 ) ? $ss -60 : $ss; - $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss ); - $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] ); + $date_str = sprintf( '%s %s', trim( $post_data['dd'] ), trim( $post_data['tt'] ) ); + $date_format_str = sprintf( '%s H:i', __( 'm/d/Y' ) ); + $result = date_parse_from_format( $date_format_str, $date_str ); + if ( !empty( $result ) && empty( $result['warning_count'] ) && empty( $result['error_count'] ) ) { + $aa = $result['year']; + $mm = $result['month']; + $jj = $result['day']; + $hh = $result['hour']; + $mn = $result['minute']; + $ss = $post_data['ss']; + $aa = ($aa <= 0 ) ? date('Y') : $aa; + $mm = ($mm <= 0 ) ? date('n') : $mm; + $jj = ($jj > 31 ) ? 31 : $jj; + $jj = ($jj <= 0 ) ? date('j') : $jj; + $hh = ($hh > 23 ) ? $hh -24 : $hh; + $mn = ($mn > 59 ) ? $mn -60 : $mn; + $ss = ($ss > 59 ) ? $ss -60 : $ss; + $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss ); + $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] ); + } } return $post_data; Index: wp-admin/includes/comment.php =================================================================== --- wp-admin/includes/comment.php (revision 18444) +++ wp-admin/includes/comment.php (working copy) @@ -43,7 +43,7 @@ $_POST['comment_content'] = $_POST['content']; $_POST['comment_ID'] = (int) $_POST['comment_ID']; - foreach ( array ('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) { + foreach ( array ('dd', 'tt') as $timeunit ) { if ( !empty( $_POST['hidden_' . $timeunit] ) && $_POST['hidden_' . $timeunit] != $_POST[$timeunit] ) { $_POST['edit_date'] = '1'; break; @@ -51,17 +51,26 @@ } if ( !empty ( $_POST['edit_date'] ) ) { - $aa = $_POST['aa']; - $mm = $_POST['mm']; - $jj = $_POST['jj']; - $hh = $_POST['hh']; - $mn = $_POST['mn']; - $ss = $_POST['ss']; - $jj = ($jj > 31 ) ? 31 : $jj; - $hh = ($hh > 23 ) ? $hh -24 : $hh; - $mn = ($mn > 59 ) ? $mn -60 : $mn; - $ss = ($ss > 59 ) ? $ss -60 : $ss; - $_POST['comment_date'] = "$aa-$mm-$jj $hh:$mn:$ss"; + $date_str = sprintf( '%s %s', trim( $_POST['dd'] ), trim( $_POST['tt'] ) ); + $date_format_str = sprintf( '%s H:i', __( 'm/d/Y' ) ); + $result = date_parse_from_format( $date_format_str, $date_str ); + + if ( !empty( $result ) && empty( $result['warning_count'] ) && empty( $result['error_count'] ) ) { + $aa = $result['year']; + $mm = $result['month']; + $jj = $result['day']; + $hh = $result['hour']; + $mn = $result['minute']; + $ss = $_POST['ss']; + $aa = ($aa <= 0 ) ? date('Y') : $aa; + $mm = ($mm <= 0 ) ? date('n') : $mm; + $jj = ($jj > 31 ) ? 31 : $jj; + $jj = ($jj <= 0 ) ? date('j') : $jj; + $hh = ($hh > 23 ) ? $hh -24 : $hh; + $mn = ($mn > 59 ) ? $mn -60 : $mn; + $ss = ($ss > 59 ) ? $ss -60 : $ss; + $_POST['comment_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss ); + } } wp_update_comment( $_POST ); Index: wp-admin/includes/template.php =================================================================== --- wp-admin/includes/template.php (revision 18444) +++ wp-admin/includes/template.php (working copy) @@ -280,11 +280,8 @@