Québec Web

HivePress Opening Hours : problème lorsque l’heure de fermeture est après 23:59

  • Créateur
    Discussion
  • #312

    Nicolas
    Keymaster

    HivePress Opening Hours est une extension add-on payante pour la suite d’extentions gratuites HivePress, sur laquelle on se base pour créer le modèle de site de guide local à partir duquel sera déployé la nouvelle version de Québec local.

    HivePress Opening Hours (dont nous avons acheté une licence à cette fin) permet de renseigner les heures d’ouvertures pour chaque entrée HivePress. Il est ensuite possible de filter les résultats en cochant une case « Ouvert en ce moment » (Open now) pour n’afficher que les commerces actuellement ouverts.

    La fonction de filtrage échoue lorsque l’heure de fermeture du commerce est à minuit (0:00) ou plus tard, ie. lorsque l’heure de fermeture est inférieure à l’heure d’ouverture (ce qui est assez commun pour les bars, notamment). Dans ce cas précis, HivePress Opening Hours devrait afficher les commerces pour lesquels l’heure actuelle est inférieure ou égale à l’heure de fermeture OU supérieure ou égale à l’heure d’ouverture (lorsque l’heure de fermeture précède l’heure d’ouveture), plutôt que celles pour lesquels l’heure actuelle est supérieure à l’heure d’ouverture ET inférieure ou égale à l’heure de fermeture (lorsque l’heure d’ouverture précède l’heure de fermeture).

    Je dis ça, et je réalise qu’en réalité ce problème pose une difficulté supplémentaire : qu’arrive-t-il à 1 h du matin vendredi lorsque l’établissement ferme à 2 h du matin le jeudi ? La condition ne dépend pas alors de l’heure de fermeture du jour actuel, mais de celle de la veille.

    La logique de la requête (qui doit certainement se traduire en une requête SQL) reste à éclaircir, mais reste que dans l’état actuel l’extension ne fonctionne pas comme prévu. Il faudra donc faire le signalement (ou trouver le signalement correspondant) sur les forums HivePress.io — si possible en proposant une solution basée sur le code de l’extension.

    Effectuer ensuite le suivi sur ce forum.

  • Auteur
    Réponses
  • #315

    Nicolas
    Administrateur
    Apprenti

    Le cas limite heure de fermeture = 0:00 a été reporté il y a plus d’un mois ici :
    https://hivepress.io/support/topic/open-now-nothing-found/#post-12989

    @GoParkPlay (1 month, 2 weeks ago)

    When I set the hours from 5am-12am and I select “open now” nothing shows up. However, when I set the hours from 5am – 1159pm, the listing appears. This appears to be a bug. Thoughts?

    @ihor (1 month, 2 weeks ago) developer

    Thanks for reporting – added this to the bug tracker, will be fixed in the next Opening Hours update. If it’s urgent please send temporary WP access to support@hivepress.io

  • #1234

    Nicolas
    Administrateur
    Apprenti

    Je dis ça, et je réalise qu’en réalité ce problème pose une difficulté supplémentaire : qu’arrive-t-il à 1 h du matin vendredi lorsque l’établissement ferme à 2 h du matin le jeudi ? La condition ne dépend pas alors de l’heure de fermeture du jour actuel, mais de celle de la veille.

    La logique de la requête (qui doit certainement se traduire en une requête SQL) reste à éclaircir […]

    Si on a :

    veille.ouverture = heure d'ouverture du jour de la veille (hier)
    veille.fermeture = heure de fermeture du jour de la veille (hier)
    auj.ouverture = heure d'ouverture du jour actuel
    auj.fermeture = heure de fermeture du jour actuel
    heure = heure actuelle
    ouvert = état actuel d'ouverture à déterminer
    

    Alors on peut définir la condition d’ouverture actuelle du commerce ainsi :

    SI (
      ( veille.fermeture < veille.ouverture ) // fermeture la veille après minuit
      ET ( heure < veille.fermeture ) // commerce encore ouvert
    ) OU (
      ( heure >= auj.ouverture ) // commerce déjà ouvert
      ET (
        ( auj.fermeture < auj.ouverture ) // fermeture aujourd'hui après minuit
        OU ( heure < auj.fermeture ) // commerce encore ouvert
      )
    )
    ALORS ouvert = VRAI // le commerce est actuellement ouvert
    

    Cas limite : certains cas limite (quoique extrêmement improbables) pourraient ne pas être représentés, eg. un commerce qui ouvrirait à 2h du matin (le mardi) et fermerait ensuite à 4h du matin (soit le lendemain matin) pour ré-ouvrir plus tard (le mercredi) est dans l’impossibilité de représenter cela dans la structure de données actuelle de HivePress Opening Hours.

  • #390

    Nicolas
    Administrateur
    Apprenti

    J’ai proposé l’algorithme ci-haut exposé sur le forum HivePress.io : https://hivepress.io/support/topic/open-now-nothing-found/#post-16004

    Si une mise à jour n’est pas proposée par l’auteur relativement rapidement, je plongerai dans le code de l’extension pour en déterminer la logique et suggérer un patch.

  • #391

    Nicolas
    Administrateur
    Apprenti

    La réponse de @ihor a été assez rapide (~12 heures) :

    Thanks for reporting this issue, I added it to the bug tracker. If you have the Opening Hours extension. The current condition is:

    if($current_time>$opening_time and $current_time<$closing_time)

    So this may require some extra logic to detect the time after midnight.

    Ça ressemble à une demande formelle de lui proposer un patch ! J’ai donc fouillé dans le code du plugin pour retrouver la logique de filtrage. Il s’agit, effectivement, d’une requête MySQL contrôlée par un objet WP_Query auquel la méthode Opening_Hours::set_search_query( $query ) ajoute une clause meta.

    La classe Opening_Hours est définie dans hivepress-opening-hours/includes/components/class-opening-hours.php. À la ligne 143 :

            // Get day and time.
            $day  = strtolower( current_time( 'l' ) );
            $time = current_time( 'G' ) * 60 + (int) current_time( 'i' );
    
            // Get meta query.
            $meta_query = array_filter( (array) $query->get( 'meta_query' ) );
    
            // Add meta clause.
            $meta_query[] = [
                'relation' => 'AND',
    
                [
                    'key'     => hp\prefix( $day . '_from' ),
                    'value'   => $time,
                    'compare' => '<',
                    'type'    => 'NUMERIC',
                ],
                [
                    'key'     => hp\prefix( $day . '_to' ),
                    'value'   => $time,
                    'compare' => '>',
                    'type'    => 'NUMERIC',
                ],
            ];
    
            // Set meta query.
            $query->set( 'meta_query', $meta_query );
    

    Il suffit de modifier $meta_query[] pour prendre en compte la logique proposée ci-haut. Mais la class WP_Query permet-elle des conditionnelles imbriquées ? Apparemment, cela est possible depuis WordPress 3.1 ! (Voir cet exemple).

    Il nous faut d’abord obtenir le jour de la semaine correspondant à la veille en plus du jour actuel. On obtient celui-ci avec : $day = strtolower( current_time( 'l' ) );. La source de la fonction current_time (définie par WordPress) nous permettrait de paraphraser l’expression par : $day = strtolower( (new DateTime( 'now', wp_timezone() ))->format( 'l' ) );.

    On se servira donc de l’objet DateTime pour obtenir également le jour de semaine de la veille :

            $timezone = wp_timezone();
            $date = new DateTime( 'now', $timezone );
            $today = strtolower( $date->format( 'l' ) );
            $date->sub( new DateInterval('P1D') );
            $yesterday = strtolower( $date->format( 'l' ) );
    

    Ne reste qu’à ré-écrire notre méta-requête imbriquée…

    Et c’est ici qu’on frappe un nœud :

    Effectivement, WP_Meta_Query ne permet pas de comparer deux méta-variables entre elles ! Ainsi il est impossible de vérifier les conditions de type <jour>.fermeture < <jour>.ouverture dans une seule requête. Ce serait définitivement possible en SQL, mais cela impliquerait une refonte en profondeur de l’extension.

    Voie de contournement

    S’il nous est impossible de vérifier les conditions de type <jour>.fermeture < <jour>.ouverture avec une seule méta-requête au moment de la requête, il nous est cependant possible de la vérifier en avance, c’est à dire au moment où les heures sont enregistrées dans la base de données. Si on ajoutait une métadonnée, eg. hp\prefix( $day . '_night' ) qui contiendrait le résultat de la précondition (1 si <jour>.fermeture < <jour>.ouverture, 0 sinon; ou — encore mieux — ne serait définie que si la condition est vérifiée), alors on sera en mesure de construire la méta-requête ainsi :

            $meta_query[] = [
                'relation' => 'OR',
                [
                    'relation' => 'AND',
                    [
                        'key'     => hp\prefix( $yesterday . '_night' ),
                        'compare' => 'EXISTS',
                    ],
                    [
                        'key'     => hp\prefix( $yesterday . '_to' ),
                        'value'   => $time,
                        'compare' => '>',
                        'type'    => 'NUMERIC',
                    ],
                ],
                [
                    'relation' => 'AND',
                    [
                        'key'     => hp\prefix( $today . '_from' ),
                        'value'   => $time,
                        'compare' => '<=',
                        'type'    => 'NUMERIC',
                    ],
                    [
                        'relation' => 'OR',
                        [
                            'key'     => hp\prefix( $today . '_night' ),
                            'compare' => 'EXISTS',
                        ],
                        [
                            'key'     => hp\prefix( $today . '_to' ),
                            'value'   => $time,
                            'compare' => '>',
                            'type'    => 'NUMERIC',
                        ]
                    ]
                ]
            ];
    

    Reste à trouver :

    À quel moment au sein de l’extension peut-on définir cette métadonnée <hp_prefix>-<jour>-night en fonction de la pré-condition <jour>.fermeture < <jour>.ouverture ?

    Références :

Connectez-vous pour répondre.