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/SBogers95/rentman.io/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\Attributables\AttributableService;
use App\Komma\Dynamic\Component\Component;
use App\Komma\Dynamic\Component\ComponentAttributeKey;
use App\Komma\Dynamic\Component\ViewComponent;
use App\Komma\Dynamic\ComponentArea\ComponentAreaService;
use App\Komma\Dynamic\ComponentType\ComponentTypeFactory;
use App\Komma\Kms\Core\Attributes\Attributable;
use App\Komma\Kms\Core\Attributes\Attribute;
use App\Komma\Kms\Core\Attributes\Models\Traits\SubFolderTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;

class ComponentService
{
    use SubFolderTrait;

    /**
     * @var ComponentAreaService
     */
    private $componentAreaService;

    /**
     * ComponentService constructor.
     * @param ComponentAreaService $componentAreaService
     */
    public function __construct(ComponentAreaService $componentAreaService)
    {
        $this->componentAreaService = $componentAreaService;
    }

    /**
     * For a View we want a simplified class which includes flat values instead of Models
     *
     * @param Model $model
     * @return Collection
     * @throws \ReflectionException
     */
    public function getViewComponents(Model $model)
    {
        $viewComponents = collect();

        // Fetch components
        $components = $model->components();

        $attributableService = \App::make(AttributableService::class);

        /** @var Component $component */
        foreach ($components as $component) {
            $componentType = ComponentTypeFactory::make($component->component_type_id);

            // Create our ViewComponent and set basic stuff
            $viewComponent = new ViewComponent();
            $viewComponent->setId($component->id);
            $viewComponent->setTypeId($componentType->getId());
            $viewComponent->setType($componentType->getName());
            $viewComponent->setView($this->getDefaultView($componentType->getName()));

            $componentSaveState = $this->componentAreaService->getComponentSaveStateForComponent($component);
            $attributeInstances = $componentType->getAttributes();
            $attributeValues = $componentSaveState->getData();

            $keyedAttributeInstances = collect();
            foreach ($attributeInstances as $instance) {
                /** @var Attribute $instance */
                $key = $instance->getKey()->getValuePart();
                $keyedAttributeInstances->put($key, $instance);
            }

            // Set value on each attribute of the ViewComponent
            $count = 0;
            foreach ($attributeValues as $attributeKey => $attributeValue) {
                /** @var ComponentAttributeKey $attributeKeyInstance */
                $attributeKeyInstance = ComponentAttributeKey::createInstanceFromString($attributeKey);
                $attributeKeyReference = $attributeKeyInstance->getAttributeReference();

                /** @var Attribute $attributeInstance */
                $attributeInstance = $keyedAttributeInstances->get($attributeKeyReference);
                if (! isset($attributeInstance)) {
                    continue;
                }
                $attributeInstance->setValue($attributeValue);

                // Sometimes we need some data preparation for our values
                // We can simply check if the AttributeInstance has a prepareForViewComponent($value) method
                if (method_exists($attributeInstance, 'prepareValueForViewComponent')) {
                    $attributeValue = $attributeInstance->prepareValueForViewComponent($attributeValue);
                }

                // Use the attributeReference as name for the magic setter
                $attributeReference = $attributeKeyInstance->getAttributeReference();

                if (is_a($attributeInstance, Attributable::class)) {
                    $attributeValue = $this->mutateAttributableAttributeToCollection($attributeInstance, $attributeValue);
                }

                $viewComponent->$attributeReference = $attributeValue;

                $count++;
            }

            // Check if we need some manual preparing in the component itself
            if(method_exists($componentType, 'prepare')) {
                $componentType->prepare($viewComponent);
            }

            $viewComponents->push($viewComponent);
        }

        return $viewComponents;
    }

    /**
     * Set default view for a component
     * @param $componentTypeName
     * @return string
     */
    private function getDefaultView($componentTypeName)
    {
        $view = 'site.organisms.componentables';

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

        // Add typeSlug as default file name
        $view .= '.'.camel_case($componentTypeName);

        return $view;
    }

    /**
     * @param Attributable $attributeInstance
     * @return Collection
     */
    private function mutateAttributableAttributeToCollection(Attributable $attributeInstance, string $attributeValue)
    {
        $modelClass = $attributeInstance->getCanBeLinkedWith();
        $idsCsv = $attributeValue;

        $ids = array_map(function ($id) {
            return (int) $id;
        }, explode(',', $idsCsv));

        return $modelClass::whereIn('id', $ids)->get();
    }

    public function getTranslatableAttributes(int $componentTypeId)
    {
        $componentType = ComponentTypeFactory::make($componentTypeId);

        if (! $componentType->hasTranslatables()) {
            return null;
        }

        $translatableAttributes = $componentType->getTranslatableAttributes();
        if (count($translatableAttributes) == 0) {
            throw new \RuntimeException('ComponentService: Component type "'.$componentType->getName().'" should have translatable attributes, else the $hasTranslatables should be false.');
        }

        return $translatableAttributes;
    }
}