HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/Neopoints/momsecurity.be/app/Komma/Components/ComponentService.php
<?php
/**
 * Created by PhpStorm.
 * User: mike
 * Date: 27/07/2018
 * Time: 15:22
 */

namespace App\Komma\Components;


use App\Komma\Dynamic\Component\Component;
use App\Komma\Dynamic\Component\ComponentAttributeKey;
use App\Komma\Dynamic\ComponentType\ComponentType;
use App\Komma\Dynamic\ComponentType\SaveState\SaveStateInterface;
use App\Komma\Dynamic\ComponentType\SaveState\SaveStateResolver;
use App\Komma\Kms\Core\Attributes\Attribute;
use App\Komma\Kms\Core\Attributes\Models\Traits\SubFolderTrait;
use Illuminate\Support\Collection;

class ComponentService
{
    use SubFolderTrait;

    /**
     * Prepare the components for usage
     * - Prepare the encoded data string for usage
     * - Make sure all the components attributes are prepared (f.e. a Documents attribute)
     * - Find a matching view for the component
     *
     * @param Collection $components
     * @return Collection
     */
    public function prepare(Collection $components)
    {
        // Create empty collection which we will return
        $preparedComponents = collect();

        // Eager load componentTypes
        $components->load('componentType');

        /** @var Component $component */
        foreach($components as $component)
        {
            /** @var ComponentType $componentType */
            $componentType = $component->componentType;

            // We need to set a new save state for each component
            /** @var SaveStateInterface $componentSaveState */
            $componentSaveState = SaveStateResolver::resolve($componentType->save_state);
            $componentType->setSaveStateInstanceAttribute($componentSaveState);

            /** @var Collection $componentTypeAttributeInstances */
            $componentTypeAttributeInstances = $componentType->save_state_instance->getAttributeInstances();

            // Convert component data to array
            // todo: use Laravel Casts function on model, therefor we also need to refactor the backend
            $attributeValues = json_decode($component->data,true);

            // Fill type attributes with data
            $component->data = $this->fillAttributeInstances($componentTypeAttributeInstances,$attributeValues);

            // Define view
            $component->view = $this->setDefaultView($component);

            // Add to collection
            $preparedComponents->push($component);
        }

        $preparedComponents = $preparedComponents->sortBy('sort_order');

        return $preparedComponents;
    }

    /**
     * Check for each attribute whether it needs to be prepared
     * For example: a Documents attribute has a encoded value, which needs to be decoded
     *
     * @param Collection $attributeInstances
     * @param array $attributeValues
     * @return Collection
     */
    private function fillAttributeInstances(Collection $attributeInstances, Array $attributeValues)
    {
        $attributes = collect();

        $count = 0;
        foreach($attributeValues as $attributeKey => $attributeValue)
        {
            /** @var Attribute $attributeInstance */
            $attributeInstance = $attributeInstances->get($count);

            // Side node: no data preparation here, for setValue can only accept a string
            $attributeInstance->setValue($attributeValue);

            /** @var ComponentAttributeKey $attributeKeyInstance */
            $attributeKeyInstance = ComponentAttributeKey::createInstanceFromString($attributeKey);
            $attributes->put($attributeKeyInstance->getAttributeReference(),$attributeInstance);

            $count++;
        }

        return $attributes;
    }

    /**
     * Set default view for a component
     * @param Component $component
     * @return string
     */
    private function setDefaultView(Component $component)
    {
        $component->view = 'site.components';

        // Add sub-folder if is set
        if( ! empty($this->getSubFolder())) $component->view .= '.' . $this->getSubFolder();

        // Add typeSlug as default file name
        $component->view .= '.' . camel_case($component->componentType->name);

        return $component->view;
    }

}