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;
}
}