Make WordPress Core

Opened 4 weeks ago

Closed 3 weeks ago

#64496 closed defect (bug) (fixed)

Type Error with gmdate() in dashboard Activity widget

Reported by: vanhoucke's profile vanhoucke Owned by: westonruter's profile westonruter
Milestone: 7.0 Priority: normal
Severity: normal Version: 6.9
Component: Administration Keywords: has-patch
Focuses: ui Cc:

Description (last modified by sabernhardt)

Uncaught Error: gmdate(): Argument #2 ($timestamp) must be of type ?int, string given
in wp-admin/includes/dashboard.php on line 1017

Call stack:

gmdate()
wp-admin/includes/dashboard.php:1017

wp_dashboard_recent_posts()
wp-admin/includes/dashboard.php:940

wp_dashboard_site_activity()
wp-admin/includes/template.php:1453

do_meta_boxes()
wp-admin/includes/dashboard.php:271

wp_dashboard()
wp-admin/index.php:204

Query Monitor

Attachments (3)

Admin-panel.png (127.9 KB) - added by vanhoucke 4 weeks ago.
Screen shoot Admin pannel
Admin-panel-debug.png (115.4 KB) - added by vanhoucke 4 weeks ago.
Screen shoot Admin Pannel debug
64496.diff (1.0 KB) - added by sabernhardt 4 weeks ago.
leaves the <span> empty if get_the_time( 'U' ) does not return an integer

Download all attachments as: .zip

Change History (12)

@vanhoucke
4 weeks ago

Screen shoot Admin pannel

@vanhoucke
4 weeks ago

Screen shoot Admin Pannel debug

#1 @Presskopp
4 weeks ago

  • Keywords has-patch removed

This ticket was mentioned in PR #10723 on WordPress/wordpress-develop by 3deiva.


4 weeks ago
#2

  • Keywords has-patch added

This pull request fixes a PHP 8.3 fatal error in the WordPress dashboard Recent Posts widget.

In wp_dashboard_recent_posts(), get_the_time( 'U' ) returns a string, but gmdate() requires an integer or null in PHP 8.3. This causes a TypeError and breaks the admin dashboard when running WordPress on PHP 8.3.

The fix casts the timestamp to an integer before passing it to gmdate(), restoring compatibility while keeping the existing behavior unchanged.

#3 @westonruter
4 weeks ago

  • Keywords reporter-feedback added

I'm not able to reproduce this issue. For me on PHP 8.3, get_the_time( 'U' ) does return an int. Do you have a get_the_time filter that is returning something else?

See on PHP Playground:

<?php
global $post;
$post = get_posts()[0];
$time = get_the_time( 'U' );
echo "get_the_time( 'U' ) === ";
var_dump( $time );

Results in:

get_the_time( 'U' ) === int(1764702503)

#4 @sabernhardt
4 weeks ago

  • Description modified (diff)
  • Focuses php-compatibility removed
  • Keywords php8.3 removed
  • Summary changed from Uncaught Error: gmdate(): Argument #2 ($timestamp) must be of type ?int, string given in wp-admin/includes/dashboard.php on line 1017 to Type Error with gmdate() in dashboard Activity widget

#60629 reported the error message earlier.

A directory search lists some of the plugins that might filter the 'get_the_time' information.

I removed the PHP 8.3 keyword and PHP compatibility focus.

  • I did not receive errors or warnings when the filtered date was a numeric string or boolean false.
  • A non-numeric string resulted in a fatal error with PHP 8.0.30, and 7.4.33 gave a warning for the same.

Testing

I added var_dump($time); immediately after $time = get_the_time( 'U' ); in wp_dashboard_recent_posts() to show the output type in my local trunk installation. Also, my time zone is UTC-6, which likely explains why the numeric string value is 6 hours different than the integer.

With no plugins, the Activity widget used integers and displayed the relative post dates.

  • int 1768214078 Today, 10:34 am
  • int 1762863730 Nov 11th 2025, 12:22 pm

Simple Location changed get_the_date output to a numeric string, but it still gave the same post dates.

  • string '1768235678' Today, 10:34 am
  • string '1762885330' Nov 11th 2025, 12:22 pm

Hide/Remove Metadata, set to Hide By PHP and Hide published date, returned false in the filter. Then the Activity widget showed today's date without the time, still including the comma and space.

  • boolean false Jan 12th 2026,
  • boolean false Jan 12th 2026,

WP Last Modified Info also can return false with its 'get_the_time' filter, but that specifically does not run in the admin area.

I reproduced the fatal error by returning a string in a custom must-use plugin.
add_filter( 'get_the_time', function ( $the_time ) { return 'gotcha'; } );

  • string 'gotcha'
    ( ! ) Fatal error: Uncaught TypeError: gmdate(): Argument #2 ($timestamp) must be of type ?int, string given in ...\wp-admin\includes\dashboard.php on line 1017
    ( ! ) TypeError: gmdate(): Argument #2 ($timestamp) must be of type ?int, string given in ...\wp-admin\includes\dashboard.php on line 1017
    

Correcting

Plugin filters could need to avoid changing the 'get_the_time' output when is_admin or when the $format is 'U'.

If Core should update the Activity widget, I think it could change the list item <span> contents if the timestamp is not an integer. Casting to an integer might work with the Simple Location plugin, but other non-integer values are likely inappropriate (for comparison or display).

#5 @westonruter
4 weeks ago

  • Keywords needs-patch added; has-patch reporter-feedback removed
  • Milestone changed from Awaiting Review to 7.0

@sabernhardt Yeah, if get_the_time( 'U' ) doesn't return a value which is_numeric(), what about just passing it straight through to be displayed?

Otherwise, I think it would make sense to just omit the SPAN entirely, treating it as if get_the_time( 'U' ) returned empty (as it can also return false).

@sabernhardt
4 weeks ago

leaves the <span> empty if get_the_time( 'U' ) does not return an integer

#6 @sabernhardt
4 weeks ago

This probably would be better as a pull request, but the .diff was easier for me.

64496.diff treats any non-integer as unreliable and ignores it in the Activity widget. It uses is_int() instead of is_numeric() because I noticed a problem with Simple Location's numeric string. When I changed a post's published date to 11:34pm yesterday, the widget said the post was published Today because it was within the GMT offset.

I chose to keep the <span> element and leave it empty when it does not have the timestamp. This does not look good, but removing it might not look any better. The first element in each list item has a width of 160 to 200 pixels and column gap of 10 pixels.

  1. If the <span> is empty, that results in 170 to 210 pixels of blank space.
  2. If the <span> is removed, the post title link width can be restricted unnecessarily, but it would be aligned with the "Recently Published" heading.
  3. If get_the_time( 'U' ) returns a non-integer with one list item, but not all of them, removing the <span> would put that post link in the same column as dates for the other list items. I changed the output for only post 1361 by adding the following filter in my must-use plugin:
    add_filter( 'get_the_time', function ( $the_time, $format, $post ) {
    	if ( isset( $post->ID ) && 1361 === $post->ID ) {
    		$the_time = 'gotcha';
    	}
    	return $the_time;
    }, 10, 3 );
    

The empty space can also hint that something is amiss without displaying an error or _doing_it_wrong message.

This ticket was mentioned in PR #10729 on WordPress/wordpress-develop by @westonruter.


4 weeks ago
#7

  • Keywords has-patch added; needs-patch removed

#8 @westonruter
4 weeks ago

  • Owner set to westonruter
  • Status changed from new to reviewing

@sabernhardt I added your patch to a PR, but I also iterated on it a bit with a proposal. What if we just use the full date format when $relative doesn't return an int?

  • src/wp-admin/includes/dashboard.php

    a b function wp_dashboard_recent_posts( $args ) { 
    10141014
    10151015                        $time = get_the_time( 'U' );
    10161016
    1017                         if ( gmdate( 'Y-m-d', $time ) === $today ) {
     1017                        if ( ! is_int( $time ) ) {
     1018                                /* translators: Date and time format for recent posts on the dashboard, from a different calendar year, see https://www.php.net/manual/datetime.format.php */
     1019                                $relative = date_i18n( __( 'M jS Y' ), $time );
     1020                        } elseif ( gmdate( 'Y-m-d', $time ) === $today ) {
    10181021                                $relative = __( 'Today' );
    10191022                        } elseif ( gmdate( 'Y-m-d', $time ) === $tomorrow ) {
    10201023                                $relative = __( 'Tomorrow' );

#9 @westonruter
3 weeks ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 61495:

Administration: Avoid PHP type error with gmdate() in wp_dashboard_recent_posts().

This fixes an issue when a non-integer is returned by get_the_time( 'U' ) which can occur when a plugin filters get_the_time. In this case, the non-relative date is displayed in the Activity dashboard widget.

Developed in https://github.com/WordPress/wordpress-develop/pull/10729

Follow-up to [26690], [26242].

Props sabernhardt, vanhoucke, westonruter.
Fixes #64496.

Note: See TracTickets for help on using tickets.