Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Page profiler never treats the detected LCP image as LCP, so it gets no fetchpriority="high" (stored ID is a string, compared with === to an int)

Abierto Apto para principiantes
#1,202 3 comentarios 0 reacciones 1 asignado Ver en GitHub

Los mantenedores suelen responder en 1 día

@girishpanchal30 ya está trabajando en esto.

Desde el 29/10/2026.

  • #1213 de @girishpanchal30 — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
88/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
javascript, php

Línea de trabajo

Comienza en inc/rest.php alrededor de la línea 1032, donde el imageId del LCP se almacena mediante sanitize_text_field(), y luego inspecciona Profile.php:385-393, donde is_lcp_image_in_all_viewports() usa === estricto. Reproduce con el fragmento de WP-CLI o la prueba existente test_lazyload_viewport_with_lcp_data, que actualmente omite la ruta REST. Terminado significa que el ID almacenado es un int (o se convierte antes de la comparación), el método devuelve true para ambos perfiles de viewport, y la rama LCP de tag_replacer.php añade fetchpriority="high".

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug
Description

The page profiler detects the LCP image in the browser and sends its data-opt-id to /optimizations as an integer. The REST handler stores it with sanitize_text_field(), which always returns a string. Profile::is_lcp_image_in_all_viewports( int $image_id ) then compares that string to the int ID with ===, so it is always false.

Result, with the default "fixed|viewport" lazy load type and profile data stored for both devices:

  • Optimole never adds fetchpriority="high" to the LCP image (tag_replacer.php LCP branch is dead, and the fixed-count fallback is skipped because profile data exists).
  • If the LCP image is not in the above-the-fold list for both devices, it is lazy-loaded anyway (and any fetchpriority="high" on it is stripped).

Expected: the stored LCP image gets fetchpriority="high" and is never lazy-loaded. Likely fix: store absint( $lcp_data['i'] ?? 0 ) in inc/rest.php (or cast before comparing in Profile.php). Existing profiles in transients/object cache keep the string until they expire, so casting at compare time also covers those.

The unit test test_lazyload_viewport_with_lcp_data stores imageId as an int directly through Profile::store(), so it does not cover the REST path.

Step-by-step reproduction instructions
  1. On a test site with Optimole 4.2.17 connected and default Lazy Load settings, run this with WP-CLI (it stores LCP data the same way inc/rest.php:1032 does):
    wp eval '
    $p   = new OptimoleWP\PageProfiler\Profile();
    $img = 1578474861;
    $lcp = [ "imageId" => sanitize_text_field( $img ), "type" => "img" ];
    foreach ( [ 1, 2 ] as $d ) { $p->store( "bugcheck", $d, [], [], $lcp ); }
    OptimoleWP\PageProfiler\Profile::set_current_profile_id( "bugcheck" );
    $p->set_current_profile_data();
    var_dump( $p->is_lcp_image_in_all_viewports( $img ) );
    '
    
  2. Expected bool(true). Actual bool(false).
  3. Clean up: wp transient delete _oprof_bugcheck_1 && wp transient delete _oprof_bugcheck_2 (or flush the optimole_page_profiler cache group if an object cache is used).

End to end check on a real page: open a page with a large hero image once on desktop and once in mobile emulation so both profiles are stored, then reload and view source. The hero <img data-opt-id=...> has no fetchpriority="high" added by Optimole, and wp transient get _oprof_<profile id>_2 --format=json shows "imageId":"<id>" as a string.

Pure PHP reproduction of the same path (json_decode of the REST body, core _sanitize_text_fields cast, transient serialize round trip, the Profile.php:387 comparison), PHP 8.4:

REST param l.i type: integer
[transient] stored imageId='1578474861' (string), page image_id=1578474861 (integer) -> is_lcp_image_in_all_viewports=false; loose == would be true
[object-cache-json] stored imageId='1578474861' (string), page image_id=1578474861 (integer) -> is_lcp_image_in_all_viewports=false; loose == would be true
Screenshots, screen recording, code snippet or Help Scout ticket

Browser sends an int: https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/assets/js/modules/lcp.js#L88-L92

lcpData.imageId = parseInt(id, 10);

REST handler stores a string: https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/rest.php#L1032

$sanitized_lcp_data['imageId'] = sanitize_text_field( $lcp_data['i'] ?? '' );

Strict compare with the int data-opt-id: https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/v2/PageProfiler/Profile.php#L385-L393

public function is_lcp_image_in_all_viewports( int $image_id ): bool {
    ...
    ( ( self::$current_profile_data[ $device ]['lcp']['imageId'] ?? null ) === $image_id )

Callers that never fire:

$image_id comes from get_id_by_url(), which returns rand() (an int): https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/app_replacer.php#L691-L697

Core: _sanitize_text_fields() casts to string: https://github.com/WordPress/WordPress/blob/7.1.3/wp-includes/formatting.php#L5708-L5713

Environment info
  • Optimole 4.2.17 (same code on master and back to 4.0.0)
  • WordPress 5.5 to 7.1 (_sanitize_text_fields() casts to string in 5.5, 6.8.3 and 7.1.3)
  • PHP 7.4 to 8.4 (strict === behaves the same on all)
  • Lazy load type "fixed|viewport" (default), page profiler enabled (default)
Is the issue you are reporting a regression

No. The string store and the strict compare are both present in 4.0.0.

Found while writing the WordPress compatibility checks for Optimole.

Lenguaje dominante
PHP
Estrellas
74
Forks
14
Merge medio
1 d 22 h
PR fusionados (30 d)
29

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Codeinwp/optimole-wp

Todos los issues de Codeinwp/optimole-wp

Issues similares

Más issues de PHP

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.