0

Something is wrong with the code in this class. I went over missing brackets and such but I can't find out the problem. The weird thing is, it runs fine locally, only when pushed onto the production server, it crashes (which makes it awkward to fix too).

It crashes on the very first line of the class declaration public ?string $header; It says 'syntax error, unexpected '?' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)'

<?php

namespace App\Http\Navigation;

use App\Models\Category;
use App\Models\Genus;
use App\Models\Quarter;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use phpDocumentor\Reflection\Types\This;

 /*
|--------------------------------------------------------------------------
| Sidebar Class
|--------------------------------------------------------------------------
|
| Construct and load the Sidebar object as part of the view in the 
| view controller to be processed by an included navigation/sidebar.blade
|
*/

/** @package App\Http\Navigation */
class Sidebar
{
    public ?string $header;  <- IT CRASHES HERE
    public ?array  $menu_array;
    public ?string $route_prefix;
    public ?object $categories;
    public ?string $section;
    public ?string $translation_type;
    public ?object $owner;

    public function __construct($view)
    {   
        $this->section = $view->section;
        $this->resource = $resource ?? null;
        $this->owner = owner() ?? User::first();
    }

// =========================================================================
// PUBLIC STATIC FUNCTIONS
// =========================================================================

    /** Create a Sidebar object and load all necessary data
     *
     * @param  object $view
     * @return object
     */
    public static function construct($view)
    {
        // dd('Sidebar@create() view', $view);
        if (!self::checkHasSidebar($view)) {
            return null;
        }

        $sidebar = new Sidebar($view);
        $sidebar->loadActiveMenus($view);
        $sidebar->loadMenuArray($view);

        // dd('Sidebar@construct() return', $sidebar);
        return $sidebar;
    }

// =========================================================================
// PRIVATE FUNCTIONS
// =========================================================================

    public function loadActiveMenus($view)
    {
        if (isset($view->selection) && is_object($view->selection)) {
            switch ($view->selection->resource_name) {
                case 'categories':
                    if ($view->selection->tier == 1) {
                        $this->active_top_menu = $view->selection->name;
                    } elseif ($view->selection->tier == 2) {
                        $this->active_menu = $view->selection->name;
                        $this->active_top_menu = $view->selection->parent->name;
                    } else {
                        $this->active_item = $view->selection->name;
                        $this->active_menu = $view->selection->parent->name;
                        $this->active_top_menu = $view->selection->parent->parent->name;
                    }
                    break;
    
                case 'genera':
                    $this->active_menu = $view->selection->slug;
                    $this->active_top_menu = $view->selection->subfamily->slug;
                    break;
    
                case 'quarters':
                    $this->active_menu = $view->selection->code;
                    $this->active_top_menu = $view->selection->year;
                    break;
            }
        }
    }

    /** Get the data for the sidebar menus based on the given view
     * 
     * @param object $view
     * @return string // returns updated resource key
     */
    private function loadMenuArray($view)
    {
        // dd('Sidebar@loadMenuArray, parameters', $view);

        switch ($view->section) {
            
            // BACKOFFICE
            case 'backoffice':
                switch ($view->resource_name) {
                    // ACTIVE/QUARTERS
                    case 'orders':
                    case 'payments':
                    case 'purchases':
                    case 'shipments':
                        $menu_array = $this->generateMenuArrayBackofficeQuarters($view, $view->resource_name);
                        $this->translation_type = 'language_files';
                        break;

                    // CATEGORIES
                    case 'items':
                    case 'products':
                    case 'suppliers':
                        $menu_array = $this->generateMenuArrayBackofficeCategories($view, $view->resource_name);
                        $this->translation_type = 'translations';
                        break;
                }
                break;

            // WEBSTORE
            case 'webstore':
                $menu_array = $this->generateMenuArrayWebstore($view);
                $this->translation_type = 'translations';
                break;
        }
        // dd('Sidebar@loadMenuArray return', $menu_array, $this, $view);
        return $this->menu_array = $menu_array;
    }

// =========================================================================
// MENU ARRAY FUNCTIONS
// =========================================================================
      
    /** Generate menu array for backoffice resources using Categories
     *
     * @param object $view
     * @param string $resource_name
     * @return array
     */
    private function generateMenuArrayBackofficeCategories($view, $resource_name)
    {
        $sidebar_categories = Category::where('type', $resource_name)->where('tier', 1)->orderBy('sorting_order')->with(['children'])->get();
        // Year topmenu
        foreach ($sidebar_categories as $category) {
            $menu_array[$category->name]['translated-label'] = text($category, 'name');
            if ($category->children->count() > 0) {
                foreach ($category->children->sortBy('name') as $child_category) {
                    $menu_array[$category->name]['menus'][$child_category->name] = [
                        'translated-label' => text($child_category, 'name'),
                        'url' => self::getIndexRouteUsingSelectedResource($view->section, $resource_name, $child_category->name)];
                }
            } else {
                $menu_array[$category->name]['url'] = self::getIndexRouteUsingSelectedResource($view->section, $resource_name, $category->name);
            } 
        }
        $menu_array['uncategorized'] = [
            'url' => self::getIndexRouteUsingSelectedResource($view->section, $resource_name, 'uncategorized'),
        ];
        return $menu_array;
    }  

    /** Generate menu array for backoffice resources using Quarters
     *
     * @param object $view
     * @param string $resource_name
     * @return array
     */
    private function generateMenuArrayBackofficeQuarters($view, $resource_name)
    {
        // dd('Sidebar@generateMenuArrayBackofficeQuarters view', $view, $resource_name);
        
        // $this->header = $resource_name;

        // Active and recent
        $menu_array = [
            'active'  => ['url' => self::getIndexRouteUsingSelectedResource('backoffice', $resource_name, 'active', 'selection')],
            'recent'  => ['url' => self::getIndexRouteUsingSelectedResource('backoffice', $resource_name, 'recent', 'selection')],
        ];

        $sidebar_years = DB::table('quarters')->distinct('year')->orderBy('year', 'desc')->pluck('year');
        $quarters = self::getSelectionsUsingResourceName('quarters');

        foreach ($sidebar_years as $year) {
            foreach ($quarters->where('year', $year) as $quarter) {
                if ($quarter->{'has_' . $resource_name}) {
                    $menu_array[$year]['menus'][substr($quarter->key, 4 ,2)] = [
                        'url' => self::getIndexRouteUsingSelectedResource($view->section, $resource_name, $quarter->name, 'quarter'),
                    ];
                } else {
                    $menu_array[$year]['menus'][substr($quarter->key, 4 ,2)] = ['is_disabled' => true];
                }
            }
        }
        // dd('Sidebar@generateMenuArrayBackofficeQuarters(), return', $menu_array);
        return $menu_array;
    }  

    /** Generate the menu array for the webstore
     *
     * @param object $view
     * @return array
     */
    private function generateMenuArrayWebstore($view)
    {
        // dd('Sidebar@generateMenuArrayWebstore view', $view, $this);
        $menu_array = [];

        // Show all ants item
        $menu_array['ants']['menus']['all_available_species'] = ['url' => route('webstore.species.index')];

        // Product Categories topmenus
        foreach (Category::where('type', 'products')->where('tier', 1)->orderBy('sorting_order')->get() as $category) {

            foreach ($category->children->sortBy('sorting_order') as $child_category) {
                if($child_category->has_available_products) {
                    $menu_array[$category->name]['menus'][$child_category->name] = [
                        'translated-label' => text($child_category, 'name'),
                        'url' => self::getIndexRouteUsingSelectedResource('webstore', 'products', $child_category->name)
                    ];
                }
            }
        }
        
        // Ants- Genera menu
        foreach (Genus::WhereHasPublicSpeciesPrice()->get() as $genus) {
            if ($genus->is_visible_in_sidebar) {
                $menu_array['ants']['menus']['genera']['menus'][$genus->name] = [
                    'url' => self::getIndexRouteUsingSelectedResource('webstore', 'species', $genus->name, 'genus')
                ];
            }
        }

        // Ants - Species Categories menus
        foreach (config('navigation.species_types') as $type) {

            foreach (Category::getWithType($type)->sortBy('sorting_order') as $category) {
                if ($category->has_available_colonies) {
                    $menu_array['ants']['menus'][$type]['menus'][$category->name] = [
                        'translated-label' => text($category, 'name'),
                        'url' => self::getIndexRouteUsingSelectedResource('webstore', 'species', $category->name)
                    ];
                        // self::getIndexRouteUsingSelectedResource('webstore', 'species', $category->name);
                }
            }
        }

        // dd('Sidebar@generateMenuArrayWebstore(), return', $menu_array);
        return $menu_array;
    }

// =========================================================================
// PRIVATE STATIC FUNCTIONS
// =========================================================================

    /** Check if the current view has a sidebar associated with it
     * 
     * @param object $view
     * @return string // returns updated resource key
     */
    private static function checkHasSidebar($view)
    {
        switch ($view->section) {
            
            // BACKOFFICE
            case 'backoffice':
                switch ($view->resource_name) {
                    case 'items':
                    case 'orders':
                    case 'payments':
                    case 'products':
                    case 'purchases':
                    case 'shipments':
                    case 'suppliers':
                        return true;
                        break;

                    default:
                        return false;
                        break;
                }

            // WEBSTORE
            case 'webstore':
                return true;;
                break;

            default:
                return false;
                break;
        }
    }
    
    /** Return a collection of the resources by the given resource name
     *
     * @param  string $resource_name
     * @return object  
     */
    private static function getSelectionsUsingResourceName($resource_name)
    {
        switch ($resource_name) {
            case 'quarters':
                    return Quarter::all()->sortByDesc('name');
                break;
        }
    }
    
    /** Return the url for the given resource
     *
     * @param  string $section
     * @param  string $resource_name
     * @param  string $selection_name
     * @param  string|'categories' $selection_resource_name
     * @return string
     */
    private static function getIndexRouteUsingSelectedResource($section, $resource_name, $selection_name, $selection_resource_name = 'category')
    {
        // dd('Sidebar::getIndexRouteUsingSelectedResource', $section, $resource_name, $selection_name, $selection_resource_name);

        // Don't pass the owner as parameter if the route is inside the webstore
        if ($section == 'webstore') {
            $parameters = [$selection_resource_name => $selection_name];
        } else {
            $parameters = ['owner' => owner()->slug, $selection_resource_name => $selection_name];
        }

        return route($section . '.' . $resource_name . '.index', $parameters);
    }
}

2 Answers2

1

maybe you need to upgrade your PHP version on server to > 7.4

ali ajouz
  • 56
  • 1
  • 2
1

Typed properties are only available since PHP 7.4.

If you can't upgrade, the only workaround is to remove all the types from properties.

For instance, replace:

public ?string $header;

with:

/** @var string|null */
public $header;

And do the same for all others.

(PHPDoc is of course optional, but is recommended for maintainability and works better with code editors.)

Jeto
  • 14,596
  • 2
  • 32
  • 46
  • Thank you very much! I'm quite a novice programmer, when you say PHPDoc, do you mean what I did , or what you suggested? – Stroomschok Apr 04 '21 at 07:42
  • 1
    Nah PHPDoc is the `** @var string|null */` part, which indicates that the property can be either a string or null (which is exactly equivalent to `?string` in PHP 7.4). It's not needed to work, but it's good practice. – Jeto Apr 04 '21 at 07:44