File: D:/HostingSpaces/SBogers10/rentman2019.komma.pro/app/Komma/Kms/Core/Sections/Section.php
<?php
namespace App\Komma\Kms\Core\Sections;
use App\Helpers\KommaHelpers;
use App\Komma\Kms\Core\Attributes\Attribute;
use App\Komma\Kms\Core\Attributes\Models\Traits\HasThumbnailInterface;
use App\Komma\Kms\Core\Attributes\Traits\LabelTrait;
use App\Komma\Languages\Models\Language;
use App\Komma\Pages\Models\Page;
use App\Komma\Routes\RouteService;
use App\Komma\Sites\Models\Site;
use App\Komma\Sites\SiteServiceInterface;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\MessageBag;
/**
* Class Section. Will replace KmsSection
*/
abstract class Section
{
/** @var SiteServiceInterface */
protected $siteService;
/**
* @var SectionServiceInterface
*/
protected $sectionService;
/** @var RouteService */
protected $routeService;
protected $eventListeners = [];
/**
* @var SectionTabsCollectionInterface
*/
protected $sectionTabDirector;
/** @var Collection The AbstractSectionTabItem instances that belong to a sectionTab. Todo: this should be the sectionTab instead. If we edit this like i described then we must modify related code too */
protected $sectionTabItems;
/** @var Model|HasThumbnailInterface */
private $model = null;
protected $models = [];
protected $errors = [];
protected $successes = [];
protected $sectionNewModel = '';
protected $sectionTitle = '';
protected $sectionsubtitle = '';
protected $submitButtonLabel = '';
protected $slug = '';
// public $submitRoute = null;
public $type = 'model';
public $keyAsArray = false;
public $keyArrayKey = '';
/** @var bool whether or not the RouteService should manage routes for this section using the models translationmodels name attribute */
protected $hasRoutes = false;
//When this var is true, the right pane will be generated
public $showEntity = true;
/** @var Model */
private $forModelName;
public function __construct(
SectionServiceInterface $sectionService,
RouteService $routeService,
SiteServiceInterface $siteService,
AbstractSectionTabsDirector $sectionTabDirector
) {
$this->siteService = $siteService;
$this->sectionService = $sectionService;
$this->routeService = $routeService;
$this->sectionTabDirector = $sectionTabDirector;
$this->setSectionText();
}
public function getSectionService()
{
return $this->sectionService;
}
public function getSlug()
{
return $this->slug;
}
public function getEntities()
{
return $this->models;
}
public function getThumbnail()
{
return $this->model->getThumbnail();
}
/**
* This method will generate the list of models.
* These are used in the sidebar.
*
* @return mixed
*/
public function loadModels()
{
//If getSortable() returns true, dont load the models, they are loaded via Ajax
if ($this->getSortable()) {
return null;
}
return $this->models = $this->sectionService->getModelsForSideBar();
}
/**
* This method is called when an model is called
* eg. for the edit form via the controller
*
* @param null $idOrModel
* @return null
*/
public function loadModel($idOrModel = null)
{
// \Log::debug("KmsSection:191 loadModel");
if (is_numeric($idOrModel) || is_null($idOrModel)) {
$this->model = $this->sectionService->getModel($idOrModel);
} elseif (gettype($idOrModel) == 'object' && is_a($idOrModel, HasThumbnailInterface::class)) {
/** @var HasThumbnailInterface $idOrModel */
$this->setOrCreateModel($idOrModel);
$this->model->generateThumbnail();
} else {
throw new \InvalidArgumentException('KmsSection loadModel expected a variable of type int or numeric string or eloquent model but got a variable of type: '.gettype($idOrModel));
}
return $this->model;
}
public function setOrCreateModel($model)
{
if ($model == null) {
$this->model = $this->sectionService->newModel();
} else {
$this->model = $this->sectionService->makeAndInjectEmptyTranslationsIntoTranslatableIfNeeded($model);
}
return $this->model;
}
/**
* This method returns the model id.
* When there is no model it returns false.
*
* @return mixed False, model id
*/
public function getModelId()
{
//Check if there is an model, return false
if (! $this->model) {
return false;
}
//Return the model id
return $this->model->id;
}
/**
* @return Model
*/
public function getForModelName(): string
{
return $this->forModelName;
}
// /**
// * Gets the model name
// */
// public function getModelName($stripModelSuffix = true)
// {
// if ( ! $this->model) {
// return '';
// }
//
// $reflect = new \ReflectionClass($this->model);
//
// $className = $reflect->getShortName();
//
// if ($stripModelSuffix) {
// $className = str_ireplace('model', '', $className);
// }
//
// return $className;
// }
/**
* @return Model
*/
public function getModel()
{
// if($this->model) \Log::debug("KmsSection:250 getModel (exists)"); else \Log::debug("KmsSection:250 (does not exist)");
return $this->model;
}
/**
* This method returns the display name of the model
* It will check if there is an model name
* or returns new {type}
*
* @return string
*/
public function getModelDisplayName()
{
if (! method_exists($this->model, 'getDisplayName')) {
throw new \RuntimeException('Please add the '.DisplayNameTrait::class.' trait to '.$this->forModelName);
}
return ($this->model) ? $this->model->getDisplayName() : null;
}
/**
* Generates the attributes for this section. They all must extend the App\Komma\Kms\Core\Attributes\Attribute class
*
* @return Collection A collection of SectionTabItems
*/
abstract protected function generateAttributes(): Collection;
/**
* Generates the attributes for the section using the sections generatesAttributes method
* and adds them to the appropriate tabs
*
* @return void
*/
public function generateAttributesAndAddThemToTabs()
{
$this->sectionTabItems = $this->generateAttributes();
$this->addAttributesToTabs();
}
/**K
* Returns a rendered view
*
* @return View
*/
public function render()
{
if ($this->showEntity) {
$this->generateAttributesAndAddThemToTabs();
}
if (! $this->getModel()) {
return $this->makeView();
} //Return a view since we can't fill it with data because the model is not set.
$this->getSectionService()->fillAttributesWithData($this->sectionTabItems, $this->getModel());
return $this->makeView();
}
/**
* Makes the view and returns it
*
* @return View
*/
protected function makeView(): View
{
$saveRoute = $this->routeService->getSaveRoute($this->getSlug(), $this->getModelId());
$successes = (\Session::has('successes')) ? \Session::get('successes') : new MessageBag();
return \View::make('kms/section.index', [
'siteSlug' => ! $this->siteService->getCurrentSite()->exists ? null : $this->siteService->getCurrentSite()->slug,
'section' => $this,
'saveRoute' => $saveRoute,
'successes' => $successes,
'maxUploadSize' => KommaHelpers::fileUploadMaxSize(),
'maxPostSize' => KommaHelpers::maxPostSize(),
'preventNavigationTranslation' => json_encode(__('kms/prevent-navigation')),
]);
}
/**
* This method will trigger the save method
*
* @param $id
* @throws \Exception
*/
public function update($id)
{
$this->generateAttributesAndAddThemToTabs();
$this->save($id);
}
/**
* This method creates or updates a model.
* Based on the input data of the form.
*
* @param Model $model
* @return $id
* @throws \Exception
*/
public function save(Model $model = null)
{
$this->fillAttributesFromInput();
$model = $this->sectionService->saveModel($model, $this->sectionTabItems);
if (is_a($model, Page::class)) {
$this->routeService->createOrUpdateRoutesForModelsTranslationsIfChanged($model);
}
//Fire the event saved method
\Event::fire('kms.entity.saved.'.$this->slug, $this->model);
//Return the id
return $model;
}
/**
* This method calls the destroyModel method
* from the give repository class.
*
* @param Model $model
* @throws \Exception
*/
public function destroy(Model $model)
{
$this->sectionService->destroyModel($model);
}
/**
* Iterates over all sectionTabItem instances and builds a Validator
* from the rules and messages in them.
*
* @param array $input The input to validate. The function wil retrieve the input itself if you don't specify this.
* If you specify it must be an associative array containing input names as keys and values as values from
* those inputs.
*
* @return \Validator
*/
public function validateInputAndReturnValidator(array $input = [])
{
if (empty($input)) {
$input = \Input::all();
}
$rules = [];
$messages = [];
/** @var AbstractSectionTabItem $sectionTabItem */
foreach ($this->sectionTabItems as $sectionTabItem) {
$attribute = $sectionTabItem->getAttribute();
$set = $attribute->getValidationSet();
if (! $set->hasRulesAndMessages()) {
continue;
}
//prepend the attribute key in front of each message rule followed by a dot to make sure the message is unique for each attribute.
$set->prefixMessageRulesWith((string) $attribute->getKey());
//And replace :attribute with the label text of the attribute
if (in_array(LabelTrait::class, class_uses($attribute))) {
$set->modifyMessages(':attribute', $attribute->getLabelText());
}
$rules = array_merge($rules, [(string) $attribute->getKey() => $set->getRules()]);
$messages = array_merge($messages, $set->getMessages());
}
$validator = \Validator::make($input, $rules, $messages);
return $validator;
}
/**
* For which model this section works for.
*
* @param string $forModel Referencing a eloquent Model
*/
public function setForModelName(string $forModel)
{
$this->forModelName = $forModel;
$this->routeService->setForModelName($forModel);
}
/**
* Creates copies of the $baseAttribute for each language given.
* Also retrieves the translation that belongs to the model based on each language that is being processed.
* The translation is stored inside if it exists the attribute to later on check at which tab in a section it belongs.
*
* @param Attribute $baseAttribute
* @param $languages
* @return array with the created attributes
*/
private function createAttributesFromExistingAttributeForTheGivenLanguages(Attribute $baseAttribute, $languages)
{
$createdAttributes = [];
//Loop trough each language of the current site
foreach ($languages as $language) {
//Get the translation of the model
$clone = clone $baseAttribute;
if ($language) {
$clone->setAssociatedLanguage($language);
}
$createdAttributes[] = $clone;
}
return $createdAttributes;
}
/**
* This method create copies of the attributes you pass it for all current site languages and
* injects translations via another method
*
* @param $baseAttributes
* @return array
*/
protected function createAttributesFromExistingAttributeForCurrentSiteLanguages(array $baseAttributes)
{
//Get the languages
$languages = $this->siteService->getSiteLanguages();
$attributes = [];
foreach ($baseAttributes as $baseAttribute) {
$attributesCreatedFromBaseAttribute = $this->createAttributesFromExistingAttributeForTheGivenLanguages($baseAttribute,
$languages);
$attributes = array_merge($attributes, $attributesCreatedFromBaseAttribute);
}
return $attributes;
}
/**
* This method create copies of the attributes you pass it for all used site languages and
* injects translations via another method.
*
* @param $baseAttributes
* @return array
*/
protected function createAttributesFromExistingAttributeForAllUsedLanguagesBySites(array $baseAttributes)
{
$languages = Site::has('languages')->with(['languages'])->get()->map(function (Site $site) {
return $site->languages;
})->collapse();
$currentSiteDefaultLanguage = $this->siteService->getCurrentSite()->defaultLanguage;
$languages = $languages->push($currentSiteDefaultLanguage)->unique('id');
$attributes = [];
foreach ($baseAttributes as $baseAttribute) {
/** @var Attribute $baseAttribute */
$attributesCreatedFromBaseAttribute = $this->createAttributesFromExistingAttributeForTheGivenLanguages($baseAttribute,
$languages);
// if($baseAttribute->getsValueFrom() == Attribute::ValueFromItself && $baseAttribute->getsValueFromReference() == 'value') dd($attributesCreatedFromBaseAttribute); //Debugging helper
$attributes = array_merge($attributes, $attributesCreatedFromBaseAttribute);
}
return $attributes;
}
/**
* Fills all attributes with values from the forms / session
*
* @return void
*/
public function fillAttributesFromInput()
{
if (! $this->sectionTabItems) {
throw new \RuntimeException('No section tab items defined. Please generate them first');
}
/** @var AbstractSectionTabItem $sectionTabItem */
foreach ($this->sectionTabItems as $sectionTabItem) {
//Insert the the appropriate value in the attribute
$attribute = $sectionTabItem->getAttribute();
$input = \Input::get((string) $attribute->getKey());
if ($input !== null) {
$attribute->setValue($input);
}
//Insert the associated language (if any) into the attribute
if ($attribute->getKey()->getTranslationIso2() != '') {
//get the language associated with the attribute]
$language = Language::where('iso_2', $attribute->getKey()->getTranslationIso2())->first();
$attribute->setAssociatedLanguage($language);
}
}
}
/**
* This method will check if the repository is sortable
*
* @return bool
*/
public function getSortable()
{
if (method_exists($this->sectionService, 'getSortable')) {
return $this->sectionService->getSortable();
}
return false;
}
/**
* Returns an array containing SectionTabInterfaces representing Tabs for sections
*
* @return SectionTabInterface[]|array
*/
public function getTabs()
{
if (! $this->sectionTabDirector->getTabsCollection()) {
return [];
}
return $this->sectionTabDirector->getTabsCollection()->getTabs();
}
/**
* Adds attributes to their appropriate tabs.
*
* @return void
*/
protected function addAttributesToTabs()
{
$tabsCollection = $this->getSectionTabDirector()->getTabsCollection();
$tabs = $tabsCollection->getTabs();
foreach ($tabs as $tab) {
if ($tab->getGroup() == SectionTabGroups::General) {
$this->sectionTabItems->each(function ($sectionTabItem, $key) use ($tab) {
/** @var AbstractSectionTabItem $sectionTabItem */
if ($sectionTabItem->getGroup() == SectionTabGroups::General) {
$tab->addItem($sectionTabItem->getAttribute());
}
});
} elseif ($tab->getGroup() == SectionTabGroups::Languages) {
$this->sectionTabItems->each(function ($sectionTabItem, $key) use ($tab) {
/** @var AbstractSectionTabItem $sectionTabItem */
if ($sectionTabItem->getGroup() != SectionTabGroups::Languages) {
return;
} //Item does not belong to a language section tab. Most likely to the general tab. Skip it.
$attribute = $sectionTabItem->getAttribute();
if (! $attribute->hasAssociatedLanguage()) {
return; //attribute does not have a translation. Skip it
}
if (strtolower($attribute->getAssociatedLanguage()->iso_2) != $tab->getName()) {
return;
} //Attribute does belong to another language tab, not this one. Skip it.
$tab->addItem($attribute);
});
}
}
}
/**
* Returns the sectiontab director which manages the creation of tabs via a builder
*
* @return AbstractSectionTabsDirector
*/
public function getSectionTabDirector(): AbstractSectionTabsDirector
{
return $this->sectionTabDirector;
}
/**
* Set the section text
*/
public function setSectionText()
{
$sectionTranslationFile = 'global';
if ($this->slug != '') {
$sectionTranslationFile = $this->slug;
}
$newModelTranslationKey = ''.$sectionTranslationFile.'.section.new';
$sectionTitleTranslationKey = $sectionTranslationFile.'.section.title';
$sectionsubtitleTranslationKey = $sectionTranslationFile.'.section.subtitle';
$newModelTranslationShop = __('shop/'.$newModelTranslationKey);
if ($newModelTranslationShop !== 'shop/'.$newModelTranslationKey) {
$this->setSectionNewModelTranslation($newModelTranslationShop);
} else {
$this->setSectionNewModelTranslation(__('kms/'.$newModelTranslationKey));
}
$sectionTitleShop = __('shop/'.$sectionTitleTranslationKey);
if ($sectionTitleShop !== 'shop/'.$sectionTitleTranslationKey) {
$this->setSectionTitleTranslation($sectionTitleShop);
} else {
$this->setSectionTitleTranslation(__('kms/'.$sectionTitleTranslationKey));
}
$sectionsubtitleShop = __('shop/'.$sectionsubtitleTranslationKey);
if ($sectionsubtitleShop !== 'shop/'.$sectionsubtitleTranslationKey) {
$this->setSectionsubtitleTranslation($sectionsubtitleShop);
} else {
$this->setSectionsubtitleTranslation(__('kms/'.$sectionsubtitleTranslationKey));
}
if (\Lang::has('kms/'.$sectionTranslationFile.'.section.submitButton')) {
$this->setSubmitButtonLabel(__('kms/'.$sectionTranslationFile.'.section.submitButton'));
} else {
$this->setSubmitButtonLabel(__('kms/global.save'));
}
}
/**
* @param string $sectionNewModel
*/
public function setSectionNewModelTranslation(string $sectionNewModel)
{
$this->sectionNewModel = $sectionNewModel;
}
/**
* @param string $sectionTitle
*/
public function setSectionTitleTranslation(string $sectionTitle)
{
$this->sectionTitle = $sectionTitle;
}
/**
* @param string $sectionsubtitle
*/
public function setSectionsubtitleTranslation(string $sectionsubtitle)
{
$this->sectionsubtitle = $sectionsubtitle;
}
/**
* @param string $submitButtonLabel
*/
public function setSubmitButtonLabel(string $submitButtonLabel)
{
$this->submitButtonLabel = $submitButtonLabel;
}
/**
* @return string
*/
public function getSectionNewModel()
{
return $this->sectionNewModel;
}
/**
* @return string
*/
public function getSectionTitle()
{
return $this->sectionTitle;
}
/**
* @return string
*/
public function getSectionsubtitle()
{
return $this->sectionsubtitle;
}
/**
* @return string
*/
public function getSubmitButtonLabel()
{
return $this->submitButtonLabel;
}
}