Whoops \ Exception \ ErrorException (E_WARNING)
Undefined array key 1 Whoops\Exception\ErrorException thrown with message "Undefined array key 1" Stacktrace: #14 Whoops\Exception\ErrorException in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php:67 #13 Whoops\Run:handleError in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php:67 #12 THEME\ViewModel\Post\Content\SplittedContentParts\Gallery:getGallery in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php:41 #11 THEME\ViewModel\Post\Content\SplittedContentParts\Gallery:split in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php:130 #10 THEME\ViewModel\Post\Content\SplittedContent:splitSections in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php:70 #9 THEME\ViewModel\Post\Content\SplittedContent:init in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php:25 #8 THEME\ViewModel\Post\Content\SplittedContent:__construct in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Templates/SingleSplittedContent.php:30 #7 THEME\ViewModel\Post\Templates\SingleSplittedContent:getContent in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Templates/Single.php:23 #6 THEME\ViewModel\Post\Templates\Single:getPostData in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Templates/SingleProdotti.php:19 #5 THEME\ViewModel\Post\Templates\SingleProdotti:getPostData in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Single.php:55 #4 THEME\ViewModel\Single:setPost in /data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Single.php:28 #3 THEME\ViewModel\Single:__construct in /data/websites/telefonino/web/app/themes/telefonino/single-prodotti.php:6 #2 include in /data/websites/telefonino/web/wp/wp-includes/template-loader.php:106 #1 require_once in /data/websites/telefonino/web/wp/wp-blog-header.php:19 #0 require in /data/websites/telefonino/web/index.php:6
Stack frames (15)
14
Whoops\Exception\ErrorException
/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php:67
13
Whoops\Run handleError
/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php:67
12
THEME\ViewModel\Post\Content\SplittedContentParts\Gallery getGallery
/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php:41
11
THEME\ViewModel\Post\Content\SplittedContentParts\Gallery split
/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php:130
10
THEME\ViewModel\Post\Content\SplittedContent splitSections
/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php:70
9
THEME\ViewModel\Post\Content\SplittedContent init
/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php:25
8
THEME\ViewModel\Post\Content\SplittedContent __construct
/web/app/themes/telefonino/src/ViewModel/Post/Templates/SingleSplittedContent.php:30
7
THEME\ViewModel\Post\Templates\SingleSplittedContent getContent
/web/app/themes/telefonino/src/ViewModel/Post/Templates/Single.php:23
6
THEME\ViewModel\Post\Templates\Single getPostData
/web/app/themes/telefonino/src/ViewModel/Post/Templates/SingleProdotti.php:19
5
THEME\ViewModel\Post\Templates\SingleProdotti getPostData
/web/app/themes/telefonino/src/ViewModel/Single.php:55
4
THEME\ViewModel\Single setPost
/web/app/themes/telefonino/src/ViewModel/Single.php:28
3
THEME\ViewModel\Single __construct
/web/app/themes/telefonino/single-prodotti.php:6
2
include
/web/wp/wp-includes/template-loader.php:106
1
require_once
/web/wp/wp-blog-header.php:19
0
require
/web/index.php:6
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php
            [ 'type' => 'content', 'content' => $gallery_split[3][0] ]
        ];
    }

    /**
     * Return the collection of the gallery images
     * of a given gallery id
     *
     * @var int gallery_id
     * @return array
     */
    public function getGallery( $gallery_id ) : array {

        $gallery = get_post($gallery_id);

        if (empty($gallery)) return [];
            
        preg_match('/\[gallery ids="(.*?)"\]/', $gallery->post_content, $output_array);
            
        $gallery_ids = explode(",", $output_array[1]);

        return array_map(function ($id) {
            
            $id = (int) $id;

            return [
                "id"  => $id,
                "thumbnail" => $this->get_attachment_image( $id, 'square_x2'),
                "full"      => $this->get_attachment_image( $id, 'full'),
                "url"       => $this->get_attachment_image( $id, 'square_x2')
            ];

        }, $gallery_ids);
    }


    private function get_attachment_image( $id, $size ) {

        $url = wp_get_attachment_image_url( $id, $size );

/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php
            [ 'type' => 'content', 'content' => $gallery_split[3][0] ]
        ];
    }

    /**
     * Return the collection of the gallery images
     * of a given gallery id
     *
     * @var int gallery_id
     * @return array
     */
    public function getGallery( $gallery_id ) : array {

        $gallery = get_post($gallery_id);

        if (empty($gallery)) return [];
            
        preg_match('/\[gallery ids="(.*?)"\]/', $gallery->post_content, $output_array);
            
        $gallery_ids = explode(",", $output_array[1]);

        return array_map(function ($id) {
            
            $id = (int) $id;

            return [
                "id"  => $id,
                "thumbnail" => $this->get_attachment_image( $id, 'square_x2'),
                "full"      => $this->get_attachment_image( $id, 'full'),
                "url"       => $this->get_attachment_image( $id, 'square_x2')
            ];

        }, $gallery_ids);
    }


    private function get_attachment_image( $id, $size ) {

        $url = wp_get_attachment_image_url( $id, $size );

/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContentParts/Gallery.php
    /**
     * If there is a gallery shortcode in the given section
     * split the content section and return a new gallery section
     * preserve the section title, if any
     *
     * @var array $sections
     * @return array that defines a section
     */
    public function split($section) {

        // takes the gallery shortcodes and the positions they start        
        $content = str_replace(["”","″"], "\"", $section['content']);
        
        preg_match_all('/(.*){{gallery=(\d+)}}(.*)/s', $content, $gallery_split);

        if (empty( $gallery_split[0])) return [];
        
        $gallery_id = (int) $gallery_split[2][0];

        $gallery = $this->getGallery($gallery_id);

        if (empty($gallery)) return [];

        return [
            [ 'type' => 'content', 'content' => $gallery_split[1][0] ],
            [ 'type' => 'gallery', 'content' => $gallery ],
            [ 'type' => 'content', 'content' => $gallery_split[3][0] ]
        ];
    }

    /**
     * Return the collection of the gallery images
     * of a given gallery id
     *
     * @var int gallery_id
     * @return array
     */
    public function getGallery( $gallery_id ) : array {

        $gallery = get_post($gallery_id);
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php
     * Recursive method that divides 
     * progressively the contents into
     * smaller, specialized sections
     * 
     * according with the given splitter
     * component
     *
     * @param Object $splitter     
     */
    private function splitSections($splitter) {
        
        $splits = [];
        
        // split content sections and
        // keep track of their positions in the array
        foreach ($this->sections as $idx => $section) {
            
            if ($section['type'] == 'content') {
 
                $split = $splitter->split($section);
                
                if (!empty($split)) {
                    $splits[] = (object) ['idx' => $idx , 'sections' => $split ];
                }
            }
        }
 
        // replace old sections with the splitted ones
        // starting from the bottom to the top
        foreach (array_reverse($splits) as $split) 
            array_splice($this->sections, $split->idx, 1, $split->sections);
        
            
        // no more splits exit the recursive loop
        if (empty($splits)) 
            return;
        
        // else do another ride
        else 
            $this->splitSections($splitter);
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php
    
    private function init($content) {   
 
        // load all the splitters
        $this->getAvailableSplitters();
 
        // cambiare gli shortcode "mutati"
        foreach($this->splitters as $splitter){
 
            $content = $splitter->convertShortCode($content);
        }
 
        // initialize the content as a big section to split
        $this->sections = [
            [ 'type' => 'content', 'content' => apply_filters('the_content', $content) ]
        ];
 
        foreach ($this->splitters as $splitter) {
 
            $this->splitSections($splitter);
        }
    }
 
    
    /**
     * Return the list of the splitters
     */
    private function getAvailableSplitters() {
 
        // una reflection un po' accroccata ma funzionale
        $composer = require get_template_directory() . '/vendor/composer/autoload_classmap.php';
 
        $namespaces = array_keys($composer);
        
        $splitters =  array_filter( $namespaces, function($item){
            return str_starts_with($item, "THEME\\ViewModel\\Post\\Content\\SplittedContentParts\\") && !str_ends_with($item, 'iSplittedContentPart');
        });
 
        $this->splitters = array_map( function( $splitter ) {  return new $splitter($this->post_id);  } , $splitters );
    }
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Content/SplittedContent.php
 * @param content:string     - is the content to split
 * @param post_id:int        - the current post id
 *
 * getSections()     - Array with the sequence of content sections to print
 *                             each one indentified with a type and a content
 *
 * splitContent()    - activate the splitter on a new content
 */
class SplittedContent
{
 
    private $splitters;
    private $sections = [];
    private $post_id  = 0;
    
    function __construct($post) {
 
        $this->post_id = $post->ID;
        
        $this->init( $post->post_content );
    }
 
    /**
     * Fix momentaneo per risolvere il problema di compatibilità con LeadPack
     *
     * @param string $content
     * @return string
     */
    function filtroH2LeadPack( string $content ) : string {
 
        $pos = strrpos($content, "[disclaimer]");
 
        return $content . ( $pos === false ? "[disclaimer]" : '' );
   }
 
    /**
     * Expose the sections
     *
     * @return Array sections
     */
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Templates/SingleSplittedContent.php
     *
    public function getPostData($post) {

        $processedPost = parent::getPostData($post);
        
        $processedPost['content'] = $this->getContent($post);

        return $processedPost;            
    }
    */

    /**
     * Returns the content as a list (array) of splitted sections
     * 
     * @param WP_Post $post
     * @return array
     */
    protected function getContent( $post ) {

        return ( new SplittedContent( $post ) )->getSections();
    }
}
 
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Templates/Single.php

use THEME\ViewModel\Post\Content\FeaturedImage;

class Single implements iTemplate {    
    

    /**
     * Basic post data for a generic Single
     *
     * @param WP_Post $post
     * @return array
     */
    public function getPostData( $post ) {

        /// basic post data 
        $postData = [
            'id'         => $post->ID,
            'title'      => $post->post_title,
            'excerpt'    => $post->post_excerpt,
            'content'    => $this->getContent( $post ),
            'image'      => $this->getImage( $post ),
            'pubdate'    => $this->getDate("post_date", $post ),
            'moddate'    => $this->getDate("post_modified", $post ),
            'tags'       => $this->getTags( $post ),
            'link'       => get_the_permalink( $post ),
            'categories' => $this->getCategories( $post )
        ];

        /// add post_meta to basic data
        $customFields = $this->getCustomFields( $post );

        if( is_array( $customFields ) && !empty( $customFields ) ) {

            $postData = array_merge( $postData, $customFields );
        }

        return $postData;
    }


/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Post/Templates/SingleProdotti.php
<?php

namespace THEME\ViewModel\Post\Templates;


/**
 * Representation of a POST into an Single context
 */
class SingleProdotti extends SingleSplittedContent implements iTemplate {
    
    /**
     * Basic post data for a generic Single
     *
     * @param WP_Post $post
     * @return array
     */
    public function getPostData( $post ) {
        
        $postData = array_merge( parent::getPostData( $post ), [

            'model' => $this->getModelName( $post )

        ]);

   
        return $postData;
    }

    protected function getModelName( $post ) {
        
        $models = get_the_terms( $post, 'modelli');
        
        return empty( $models ) ? $post->post_title : array_shift( $models )->name;        
    }

}
 
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Single.php

    }

        
    /**
     * Writes the basic page info
     */
    protected function setPageData(){       
        
        $this->data = [
            'type' => 'single_post',
            'infinite' => 'true'
        ];        
    }

    /**
     * Add the post info to data
     */
    protected function setPost() {        
        $this->data['post'] = $this->postTemplate->getPostData($this->post);
    }

  
    /**
     * set the list of the components
     * override this to add or remove components    
     */
    protected function initComponents() {

        $this->components = [
            'Author',
            'Taxonomies',
            'Credits',
            'Canonical',
            'StructuredDataFaq',
            'AnalysisTracking',
            'Meta'
        ];
    }
    
/data/websites/telefonino/web/app/themes/telefonino/src/ViewModel/Single.php
 */
class Single extends Base {

    protected $post;
    protected $postTemplate;
    
    protected $components;
    
    function __construct($post, $postTemplate = 'Single') {     
        
        parent::__construct();

        $this->post = $post;

        // assign the post template (default is 'Single')        
        $this->postTemplate = $this->postTemplateFactory($postTemplate);
        
        // init the post template 
        // (includes content details as well)
        $this->setPost(); 

        // set the components list into property
        // $components 
        $this->initComponents();

        // add all the default components 
        $this->setComponents();

    }

        
    /**
     * Writes the basic page info
     */
    protected function setPageData(){       
        
        $this->data = [
            'type' => 'single_post',
            'infinite' => 'true'
        ];        
/data/websites/telefonino/web/app/themes/telefonino/single-prodotti.php
<?php
use THEME\ViewModel\SingleProduct;
use THEME\Utils\Timber;

// load data
$data = ( new SingleProduct($posts[0], 'SingleProdotti') )->getData();

$template = 'single-product.twig';

Timber::render( $template, $data );
 
/data/websites/telefonino/web/wp/wp-includes/template-loader.php
            }
 
            break;
        }
    }
 
    if ( ! $template ) {
        $template = get_index_template();
    }
 
    /**
     * Filters the path of the current template before including it.
     *
     * @since 3.0.0
     *
     * @param string $template The path of the template to include.
     */
    $template = apply_filters( 'template_include', $template );
    if ( $template ) {
        include $template;
    } elseif ( current_user_can( 'switch_themes' ) ) {
        $theme = wp_get_theme();
        if ( $theme->errors() ) {
            wp_die( $theme->errors() );
        }
    }
    return;
}
 
/data/websites/telefonino/web/wp/wp-blog-header.php
<?php
/**
 * Loads the WordPress environment and template.
 *
 * @package WordPress
 */
 
if ( ! isset( $wp_did_header ) ) {
 
    $wp_did_header = true;
 
    // Load the WordPress library.
    require_once __DIR__ . '/wp-load.php';
 
    // Set up the WordPress query.
    wp();
 
    // Load the theme template.
    require_once ABSPATH . WPINC . '/template-loader.php';
 
}
 
/data/websites/telefonino/web/index.php
<?php
/**
 * WordPress View Bootstrapper
 */
define('WP_USE_THEMES', true);
require __DIR__ . '/wp/wp-blog-header.php';
 

Environment & details:

empty
empty
empty
empty
empty
Key Value
SERVER_SOFTWARE nginx/1.26.2
REQUEST_URI /prodotti/proscenic-washvac-f20/
USER nginx
HOME /var/lib/nginx
HTTP_REFERER https://staging.telefonino.net/prodotti/proscenic-washvac-f20
HTTP_ACCEPT_ENCODING gzip, br, zstd, deflate
HTTP_USER_AGENT Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
HTTP_ACCEPT */*
HTTP_CONNECTION close
HTTP_X_FORWARDED_FOR 216.73.216.49
HTTP_HOST staging.telefonino.net
HTTP_X_FORWARDED_PORT 443
HTTP_X_FORWARDED_PROTO https
REDIRECT_STATUS 200
SERVER_NAME staging.telefonino.net
SERVER_PORT 443
SERVER_ADDR 10.50.50.197
REMOTE_PORT 39270
REMOTE_ADDR 10.50.50.12
GATEWAY_INTERFACE CGI/1.1
HTTPS on
REQUEST_SCHEME https
SERVER_PROTOCOL HTTP/1.0
DOCUMENT_ROOT /data/websites/telefonino/web
DOCUMENT_URI /index.php
SCRIPT_NAME /index.php
CONTENT_LENGTH
CONTENT_TYPE
REQUEST_METHOD GET
QUERY_STRING
SCRIPT_FILENAME /data/websites/telefonino/web/index.php
FCGI_ROLE RESPONDER
PHP_SELF /index.php
REQUEST_TIME_FLOAT 1774566595.4015
REQUEST_TIME 1774566595
DB_NAME telefonino
DB_USER telefoninoUSR
DB_PASSWORD .T3lefon!n0.
DB_HOST localhost
DB_PREFIX wp_
GTM_ID GTM-PV4S3R4X
ASSETS_DIR /app/themes/telefonino/assets
FORMINATOR_NEWSLETTER_FORM_ID 404256
WP_ENV staging
WP_HOME https://staging.telefonino.net
WP_SITEURL https://staging.telefonino.net/wp
WP_THEMEPATH https://staging.telefonino.net/app/themes/telefonino/
WP_EMAIL no-reply@telefonino.net
WP_DEBUG true
WP_CACHE false
DISABLE_WP_CRON true
WP_MEMORY_LIMIT 512M
WP_POST_REVISIONS false
AUTH_KEY &uq&p$ypr;Yr7DiuR3ECXHD14o0M562d|MYpdP>;X.fm9q@pOvJ^D-/w9uC+`q1z
SECURE_AUTH_KEY *kkFy7N_9]uNEIk%lG{zxv|aT/_BSV:-|l+C{NU|2/|-HJqP82K[e7mg=>qX!Mef
LOGGED_IN_KEY RJ%0[1(1^$bKjvj^IXV!e[%+yD;d1_fl/)Q4/SdSO>>np:+=`+Es9UbS]dOg89J=
NONCE_KEY 1RTq(</}tixMOUC^n44?.,xA!,n-ms-6J@,LS@/aVJAk8<Ofvjaeu[1iPzU,oG{q
AUTH_SALT ,ptA@)1JrYHO3CjZxYcqX_v<7@X1>2*v7K<Ul2?ofl2qP<>!qzjkf)$Zu&iovz-k
SECURE_AUTH_SALT GA/axYdH9ls=wCH#1XwF9P&E<jOP^d4VKlFF?>vb4Czz3v$jz0dl@DES]&A3D_`^
LOGGED_IN_SALT tWjy]Qb,XQ9%th/9Oi1D;E/L@z-Oo5<TfTSVD-obR;MTyal!SWCcez=fnAGNFlFL
NONCE_SALT aMNhCOYLU+(1URHOor&2^Ux0}9%5eQ1B;MRZ({=XMcw!+42NI3Gx?;,L&Y;yYni]
ACF_PRO_KEY b3JkZXJfaWQ9NzQ2MTV8dHlwZT1kZXZlbG9wZXJ8ZGF0ZT0yMDE2LTAyLTA5IDExOjQ5OjE5
Key Value
DB_NAME telefonino
DB_USER telefoninoUSR
DB_PASSWORD .T3lefon!n0.
DB_HOST localhost
DB_PREFIX wp_
GTM_ID GTM-PV4S3R4X
ASSETS_DIR /app/themes/telefonino/assets
FORMINATOR_NEWSLETTER_FORM_ID 404256
WP_ENV staging
WP_HOME https://staging.telefonino.net
WP_SITEURL https://staging.telefonino.net/wp
WP_THEMEPATH https://staging.telefonino.net/app/themes/telefonino/
WP_EMAIL no-reply@telefonino.net
WP_DEBUG true
WP_CACHE false
DISABLE_WP_CRON true
WP_MEMORY_LIMIT 512M
WP_POST_REVISIONS false
AUTH_KEY &uq&p$ypr;Yr7DiuR3ECXHD14o0M562d|MYpdP>;X.fm9q@pOvJ^D-/w9uC+`q1z
SECURE_AUTH_KEY *kkFy7N_9]uNEIk%lG{zxv|aT/_BSV:-|l+C{NU|2/|-HJqP82K[e7mg=>qX!Mef
LOGGED_IN_KEY RJ%0[1(1^$bKjvj^IXV!e[%+yD;d1_fl/)Q4/SdSO>>np:+=`+Es9UbS]dOg89J=
NONCE_KEY 1RTq(</}tixMOUC^n44?.,xA!,n-ms-6J@,LS@/aVJAk8<Ofvjaeu[1iPzU,oG{q
AUTH_SALT ,ptA@)1JrYHO3CjZxYcqX_v<7@X1>2*v7K<Ul2?ofl2qP<>!qzjkf)$Zu&iovz-k
SECURE_AUTH_SALT GA/axYdH9ls=wCH#1XwF9P&E<jOP^d4VKlFF?>vb4Czz3v$jz0dl@DES]&A3D_`^
LOGGED_IN_SALT tWjy]Qb,XQ9%th/9Oi1D;E/L@z-Oo5<TfTSVD-obR;MTyal!SWCcez=fnAGNFlFL
NONCE_SALT aMNhCOYLU+(1URHOor&2^Ux0}9%5eQ1B;MRZ({=XMcw!+42NI3Gx?;,L&Y;yYni]
ACF_PRO_KEY b3JkZXJfaWQ9NzQ2MTV8dHlwZT1kZXZlbG9wZXJ8ZGF0ZT0yMDE2LTAyLTA5IDExOjQ5OjE5
0. Whoops\Handler\PrettyPageHandler