classes/item/ElementItem.php
File `ElementItem.php` has 313 lines of code (exceeds 250 allowed). Consider refactoring.<?php namespace Lovata\Toolbox\Classes\Item; use Model;use October\Rain\Extension\ExtendableTrait; use Kharanenka\Helper\CCache; /** * Class ElementItem * @package Lovata\Toolbox\Classes\Item * @author Andrey Kharanenka, a.khoronenko@lovata.com, LOVATA Group * * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem */`ElementItem` has 31 functions (exceeds 20 allowed). Consider refactoring.
The class ElementItem has 17 public methods. Consider refactoring ElementItem to keep number of public methods under 10.
The class ElementItem has an overall complexity of 90 which is very high. The configured complexity threshold is 50.
Class "ElementItem" has 31 methods, which is greater than 20 authorized. Split it into smaller classes.
Abstract class name is not prefixed with "Abstract"abstract class ElementItem extends MainItem{ use ExtendableTrait; const MODEL_CLASS = Model::class; const QUERY_FIELD = 'id'; public static $arQueryWith = []; public $implement = []; /** @var int */ protected $iElementID = null; /** @var \Model */ protected $obElement = null; /** @var array */ protected static $arBooted = []; /** @var array */ public $arExtendResult = []; /** * ElementItem constructor. * @param int $iElementID * @param \Model $obElement * @throws \Exception */ public function __construct($iElementID, $obElement) { if (is_string($iElementID)) { $iElementID = trim($iElementID); } $this->iElementID = $iElementID; $this->obElement = $obElement; //Check instance of obElement $sModelClass = static::MODEL_CLASS; if (!empty($this->obElement) && !$this->obElement instanceof $sModelClass) { $this->obElement = null; } $this->bootIfNotBooted(); $this->initActiveLang(); $this->extendableConstruct(); } /** * @param string $sName * @return string */ public function __get($sName) { return $this->extendableGet($sName); } /** * @param string $sName * @param mixed $obValue */ public function __set($sName, $obValue) { $this->extendableSet($sName, $obValue); } /** * @param string $sName * @param array $arParamList * @return mixed */ public function __call($sName, $arParamList) { return $this->extendableCall($sName, $arParamList); } /** * @param string $sName * @param array $arParamList * @return mixed * @throws \Exception */ public static function __callStatic($sName, $arParamList) { return self::extendableCallStatic($sName, $arParamList); } /** * Serialize item object * @return array */ public function __sleep() {Define a constant instead of duplicating this literal "iElementID" 4 times. return ['iElementID']; } /** * Unserialize object */ public function __wakeup() { $this->setCachedData(); } /** * @return string */ public function __toString() { return $this->toJSON(); } /** * @param callable $callback */ public static function extend(callable $callback) { self::extendableExtendCallback($callback); } /** * Make new element item * @param int|string $iElementID * @param \Model $obElement * * @return $this * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#makeielementid-obelement--null * @see \Lovata\Toolbox\Tests\Unit\ItemTest::testItem() */ public static function make($iElementID, $obElement = null) { if (is_string($iElementID)) { $iElementID = trim($iElementID); } $arParamList = [ 'iElementID' => $iElementID,Define a constant instead of duplicating this literal "obElement" 3 times. 'obElement' => $obElement, ]; $obItem = ItemStorage::get(static::class, $iElementID); if (!empty($obItem)) { return $obItem; } /** @var ElementItem $obItem */ $obItem = app()->make(static::class, $arParamList); //Init cached array model data $obItem->setCachedData(); ItemStorage::set(static::class, $iElementID, $obItem); return $obItem; } /** * Make new element item * @param int|string $iElementID * @param Model $obElement * @return $this * @throws \Exception */ public static function makeOnlyCache($iElementID, $obElement = null) { $arParamList = [ 'iElementID' => $iElementID, 'obElement' => $obElement, ]; $obItem = ItemStorage::get(static::class, $iElementID); if (!empty($obItem)) { return $obItem; } /** @var $this $obItem */ $obItem = app()->make(static::class, $arParamList); //Init cached array model data $obItem->setCachedData(false); if ($obItem->isEmpty()) { return $obItem; } ItemStorage::set(static::class, $iElementID, $obItem); return $obItem; } /** * Make new element item (no cache) * @param int $iElementID * @param \Model $obElement * @return $this * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#makenocacheielementid-obelement--null * @see \Lovata\Toolbox\Tests\Unit\ItemTest::testItem() */ public static function makeNoCache($iElementID, $obElement = null) { $arParamList = [ 'iElementID' => $iElementID, 'obElement' => $obElement, ]; /** @var $this $obItem */ $obItem = app()->make(static::class, $arParamList); //Init array model data (no cache) $obItem->setData(); return $obItem; } /** * Remove model data from cache * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#clearcacheielementid * @param int $iElementID */ public static function clearCache($iElementID) { if (empty($iElementID)) { return; } ItemStorage::clear(static::class, $iElementID); CCache::clear(static::getCacheTag(), $iElementID); } /** * Check model data is empty * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#isempty * @return bool */ public function isEmpty() { return empty($this->arModelData); } /** * Check model data is not empty * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#isnotempty * @return bool */ public function isNotEmpty() { return !$this->isEmpty(); } /** * Get model data * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#toarray * @return array */ public function toArray() { return $this->arModelData; } /** * Get model data in JSON string * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#tojson * @return string */ public function toJSON() { return json_encode($this->arModelData); } /** * Get model object * @link https://github.com/lovata/oc-toolbox-plugin/wiki/ElementItem#getobject * * @return \Model */ public function getObject() { $this->initElementObject(); return $this->obElement; } /** * Set data from model object */Function `setData` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. protected function setData() { $this->initElementObject(); if (empty($this->obElement)) { return; } //Set default lang (if update cache with non default lang)Define a constant instead of duplicating this literal "RainLab.Translate.Behaviors.TranslatableModel" 4 times. if (self::$bLangInit && !empty(self::$sDefaultLang) && $this->obElement->isClassExtendedWith('RainLab.Translate.Behaviors.TranslatableModel')) { $this->obElement->lang(self::$sDefaultLang); } //Get cached field list from model and add fields to cache array $this->setCachedFieldList(); //Get element data $arResult = $this->getElementData(); if (empty($arResult) || !is_array($arResult)) { $arResult = []; } //Add fields values to cached array foreach ($arResult as $sField => $sValue) { $this->setAttribute($sField, $sValue); } //Save lang properties (integration with Translate plugin) $this->setLangProperties(); //Run methods from $arExtendResult array $this->setExtendData(); } /** * Get cached field list from model and add fields to cache array */Function `setCachedFieldList` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring. protected function setCachedFieldList() { if (!$this->obElement->methodExists('getCachedField')) { return; } //Get cached field list $arFieldList = $this->obElement->getCachedField(); if (empty($arFieldList)) { return; } foreach ($arFieldList as $sField) { if (array_key_exists($sField, (array) $this->obElement->attachOne)) { $arFileData = $this->getUploadFileData($this->obElement->$sField); $sFieldName = 'attachOne|'.$sField; $this->setAttribute($sFieldName, $arFileData); } elseif (array_key_exists($sField, (array) $this->obElement->attachMany)) { $arFileList = []; $obFileList = $this->obElement->$sField; foreach ($obFileList as $obFile) { $arFileData = $this->getUploadFileData($obFile); $arFileList[] = $arFileData; } $sFieldName = 'attachMany|'.$sField; $this->setAttribute($sFieldName, $arFileList); } else { $this->setAttribute($sField, $this->obElement->$sField); } } } /** * Run methods from $arExtendResult array */Function `setExtendData` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. protected function setExtendData() { //Check extend result methods if (empty($this->arExtendResult)) { return; } //Apply extend methods foreach ($this->arExtendResult as $sMethodName) { if (empty($sMethodName) || !(method_exists($this, $sMethodName) || $this->methodExists($sMethodName))) { continue; } $this->$sMethodName(); } } /** * Set cached brand data * @param bool $bWithQuery */ protected function setCachedData($bWithQuery = true) { if (empty($this->iElementID)) { return; } $arCacheTags = static::getCacheTag(); $sCacheKey = $this->iElementID; $this->arModelData = CCache::get($arCacheTags, $sCacheKey); if (!$this->isEmpty() || !$bWithQuery) { return; } $this->setData(); //Set cache data CCache::forever($arCacheTags, $sCacheKey, $this->arModelData); } /** * Set model data from object * @return mixed */ protected function getElementData() { return []; } /** * Check if the model needs to be booted and if so, do it. * * @return void */ protected function bootIfNotBooted() { if (isset(static::$arBooted[static::class])) { return; } static::boot(); static::$arBooted[static::class] = true; } /** * The "booting" method of the model. * * @return void */ protected static function boot() { static::bootTraits(); } /** * Boot all of the bootable traits on the model. * * @return void */ protected static function bootTraits() { foreach (class_uses_recursive(get_called_class()) as $trait) { if (method_exists(get_called_class(), $method = 'boot'.class_basename($trait))) { forward_static_call([get_called_class(), $method]); } } } /** * Init element object */ protected function initElementObject() { $sModelClass = static::MODEL_CLASS; if (!empty($this->obElement) && !$this->obElement instanceof $sModelClass) { $this->obElement = null; } if (!empty($this->obElement) || empty($this->iElementID)) { return; } $this->setElementObject(); } /** * Set element object */ protected function setElementObject() { $sModelClass = static::MODEL_CLASS; $obQuery = $sModelClass::where(static::QUERY_FIELD, $this->iElementID); if (method_exists($sModelClass, 'trashed')) { $obQuery->withTrashed(); } if (!empty(static::$arQueryWith)) { $obQuery->with(static::$arQueryWith); } $this->obElement = $obQuery->first(); } /** * Get cache tag array for model * @return array */ protected static function getCacheTag() { return [static::class]; } /** * Process translatable fields and save values, how 'field_name|lang_code' */Function `setLangProperties` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.
Method `setLangProperties` has 26 lines of code (exceeds 25 allowed). Consider refactoring.
The method setLangProperties() has an NPath complexity of 1170. The configured NPath complexity threshold is 200.
The method setLangProperties() has a Cyclomatic Complexity of 15. The configured cyclomatic complexity threshold is 10.
Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed. private function setLangProperties() { if (empty($this->obElement) || !$this->obElement->isClassExtendedWith('RainLab.Translate.Behaviors.TranslatableModel')) { return; } //Check translate model property if (empty($this->obElement->translatable) || !is_array($this->obElement->translatable)) { return; } //Get active lang list from Translate plugin $arLangList = self::getActiveLangList(); if (empty($arLangList)) { return; } //Process translatable fields foreach ($this->obElement->translatable as $sField) { //Check field name if (empty($sField) || (!is_string($sField) && !is_array($sField))) { continue; } if (is_array($sField)) { $sField = array_shift($sField); } if (!isset($this->arModelData[$sField]) || array_key_exists($sField, (array) $this->obElement->attachOne) || array_key_exists($sField, (array) $this->obElement->attachMany)) { continue; } //Save field value with different lang code foreach ($arLangList as $sLangCode) { $sLangField = $sField.'|'.$sLangCode; $sValue = $this->obElement->lang($sLangCode)->$sField; $this->setAttribute($sLangField, $sValue); } } } /** * Get image data from image object * @param \System\Models\File $obFile * @return [] */Function `getUploadFileData` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring. private function getUploadFileData($obFile) : array { if (empty($obFile)) { return []; } //Set default lang in image object if (!empty(self::$sDefaultLang) && $obFile->isClassExtendedWith('RainLab.Translate.Behaviors.TranslatableModel')) { $obFile->lang(self::$sDefaultLang); } //Convert image data to array $arFileData = $obFile->toArray(); $arLangList = $this->getActiveLangList(); if (empty($arLangList) || !$obFile->isClassExtendedWith('RainLab.Translate.Behaviors.TranslatableModel')) { return $arFileData; } //Add lang fields to array foreach ($arLangList as $sLangCode) { $arFileData[$sLangCode] = []; foreach ($obFile->translatable as $sLangField) { $arFileData[$sLangCode][$sLangField] = $obFile->lang($sLangCode)->$sLangField; } } return $arFileData; }}