system/modules/pct_customelements/PCT/CustomElements/Core/CustomElement.php line 476

Open in your IDE?
  1. <?php
  2. /**
  3.  * Contao Open Source CMS
  4.  * 
  5.  * Copyright (C) 2005-2013 Leo Feyer
  6.  * 
  7.  * @copyright    Tim Gatzky 2013, Premium Contao Webworks, Premium Contao Themes
  8.  * @author        Tim Gatzky <info@tim-gatzky.de>
  9.  * @package        pct_customelements
  10.  * @link        http://contao.org
  11.  */
  12. /**
  13.  * Namespace
  14.  */
  15. namespace PCT\CustomElements\Core;
  16. /**
  17.  * Imports
  18.  */
  19. use PCT\CustomElements\Core\CustomElementFactory as Factory;
  20. use PCT\CustomElements\Core\GroupFactory as GroupFactory;
  21. use PCT\CustomElements\Core\Origin as Origin;
  22. use PCT\CustomElements\Core\FrontendTemplate as FrontendTemplate;
  23. use PCT\CustomElements\Core\AttributeFactory as AttributeFactory;
  24. /**
  25.  * Class file
  26.  * CustomElement
  27.  * Generate CustomElements
  28.  */
  29. class CustomElement extends \PCT\CustomElements\Core\Controller
  30. {
  31.     /**
  32.      * Groups array
  33.      * @var array
  34.      */
  35.     protected $arrGroups    = array();
  36.     
  37.     /**
  38.      * Wizard data array
  39.      * @var array
  40.      */
  41.     protected $arrWizard    = array();
  42.     
  43.     /**
  44.      * Active Record database object
  45.      * @var array
  46.      */
  47.     protected $objActiveRecord;
  48.     
  49.     /**
  50.      * Origin array containing all important information about
  51.      * the element created this custom element
  52.      * @var array
  53.      */
  54.     protected $objOrigin;
  55.     
  56.     /**
  57.      * Allow to bypass the origin object (resolves in loosing the connection to the vault)
  58.      * @var boolean
  59.      */
  60.     protected $bolBypassOrigin false;
  61.     
  62.     /**
  63.      * Flag if it is generic
  64.      * @var boolean
  65.      */
  66.     protected $blnIsGeneric false;
  67.     
  68.     /**
  69.      * The generic attribute id
  70.      * @var integer
  71.      */
  72.     protected $intGenericAttribute 0;
  73.     
  74.     
  75.     /**
  76.      * Create a new instance
  77.      * @param array
  78.      */
  79.     public function __construct($arrData=array())
  80.     {
  81.         if(count($arrData) > 0)
  82.         {
  83.             $this->setData($arrData);
  84.         }
  85.     }
  86.     /**
  87.      * Generate the custom element
  88.      * @return object CustomElement
  89.      */
  90.     public function generate()
  91.     {
  92.         if(empty($this->arrData))
  93.         {
  94.             return null;
  95.         }
  96.         
  97.         // create the origin from url
  98.         if(!$this->getOrigin() && !$this->get('bolBypassOrigin'))
  99.         {
  100.             $strModel \Contao\Model::getClassFromTable\Contao\Input::get('table') );
  101.             if (class_exists($strModel))
  102.             {
  103.                 $objModel $strModel::findByPk(\Contao\Input::get('id'));
  104.             }
  105.             $objOrigin = new \PCT\CustomElements\Core\Origin();
  106.             $objOrigin->set('intPid',\Contao\Input::get('id'));
  107.             $objOrigin->set('strTable',\Contao\Input::get('table'));
  108.             $objOrigin->set('objActiveRecord',$objModel);
  109.             $objOrigin->set('intGenericAttribute',$this->getGenericAttribute());
  110.             
  111.             $this->setOrigin($objOrigin);
  112.         }
  113.         
  114.         // find groups and attributes
  115.         $groups GroupFactory::findPublishedByParentId$this->get('id') );
  116.         
  117.         $arrGroups = array();
  118.         if(count($groups) > 0)
  119.         {
  120.             foreach($groups as $objGroup)
  121.             {
  122.                 $objGroup->setOrigin($this->getOrigin());
  123.                 
  124.                 $arrAttributes = array();
  125.                 if( !empty($objGroup->getAttributes()) )
  126.                 {
  127.                     foreach($objGroup->getAttributes() as $objAttribute)
  128.                     {
  129.                         // continue on old or obsolete attributes (e.g. deinstalled from system)
  130.                         if(!$objAttribute)
  131.                         {
  132.                             continue;
  133.                         }
  134.                         $objAttribute->setOrigin($this->getOrigin());
  135.                         $arrAttributes[] = $objAttribute;
  136.                     }
  137.                     $objGroup->set('arrAttributes',$arrAttributes);
  138.                 }
  139.                 $arrGroups[] = $objGroup;
  140.             }
  141.         }
  142.         $this->set('arrGroups',$arrGroups);
  143.         
  144.         return $this;
  145.     }        
  146.         
  147.     
  148.     /**
  149.      * Return all attributes for the dca
  150.      * @param object
  151.      * @return array
  152.      */
  153.     public function getFieldsForDca($objDC)
  154.     {
  155.         $arrGroups \PCT\CustomElements\Core\Vault::getWizardData($objDC->id,$objDC->table,$this->getGenericAttribute());
  156.         
  157.         // new structure
  158.         if(isset($arrGroups['alias']))
  159.         {
  160.             $arrGroups $arrGroups['groups'];
  161.         }
  162.         
  163.         if(empty($arrGroups))
  164.         {
  165.             return array();
  166.         }
  167.         
  168.         $arrFields = array();
  169.         foreach($arrGroups as $group)
  170.         {
  171.             if(empty($group['attributes']))
  172.             {
  173.                 continue;
  174.             }
  175.             
  176.             foreach($group['attributes'] as $attr)
  177.             {
  178.                 $objAttribute \PCT\CustomElements\Core\AttributeFactory::findById($attr['id']);
  179.                 if(!$objAttribute)
  180.                 {
  181.                     continue;
  182.                 }
  183.                 $objAttribute->set('uuid',$attr['uuid']);
  184.                 
  185.                 // pass the CustomElement to the attribute
  186.                 $objAttribute->set('objCustomElement',$this);
  187.                 $arrFields[] = $objAttribute->prepareForDca($objDC);
  188.             }
  189.         }
  190.         
  191.         
  192.         return $arrFields;
  193.     }
  194.     
  195.     
  196.     /**
  197.      * Render a custom content element and return html
  198.      * @return string
  199.      */
  200.     public function render($objTemplate=null)
  201.     {
  202.         // get the origin information
  203.         $objOrigin $this->getOrigin();
  204.         
  205.         if(empty($objTemplate))
  206.         {
  207.             $objTemplate = new FrontendTemplate($this->get('template'));
  208.             $objTemplate->setData($this->get('arrData'));
  209.             $objTemplate->origin($objOrigin);
  210.         }
  211.         
  212.         $objTemplate $this->addToTemplate($objTemplate);
  213.         
  214.         $arrCssID \Contao\StringUtil::deserialize($this->get('cssID'));
  215.         $objTemplate->cssID $arrCssID[0] ? 'id="'.$arrCssID[0].'"' '';
  216.         
  217.         $arrClass = array($this->get('template'));
  218.         if(strlen($arrCssID[1]) > 0)
  219.         {
  220.             $arrClass array_unique(array_merge($arrClass,explode(' ',$arrCssID[1])));
  221.         }
  222.         $objTemplate->class implode(' '$arrClass);
  223.         $strBuffer $objTemplate->parse();
  224.         
  225.         return $strBuffer;
  226.     }
  227.     
  228.     
  229.     /**
  230.      * Add the custom element data to a template object
  231.      * @param object
  232.      */
  233.     public function addToTemplate($objTemplate)
  234.     {
  235.         $process_start 0;
  236.         if($GLOBALS['PCT_CUSTOMELEMENTS']['debug'])
  237.         {
  238.             // start time measurement
  239.             $process_start microtime(true);
  240.         }
  241.         
  242.         // get the origin information
  243.         $objOrigin $this->getOrigin();
  244.         if( empty($objOrigin) )
  245.         {
  246.             return $objTemplate;
  247.         }
  248.         $objTemplate->origin $objOrigin;
  249.         
  250.         $objActiveRecord null;
  251.         $strClass \Contao\Model::getClassFromTable($objOrigin->get('strTable'));
  252.         if( !empty($strClass) )
  253.         {
  254.             $objActiveRecord $strClass::findByPk$objOrigin->get('intPid') );
  255.             $objOrigin->set('activeRecord',$objActiveRecord);
  256.         }
  257.         
  258.         // get the wizard data
  259.         $arrData $this->getWizardData();
  260.         if(count($arrData) < 1)
  261.         {
  262.             $objTemplate->empty $GLOBALS['TL_LANG']['PCT_CUSTOMELEMENTS']['empty'];
  263.             return $objTemplate;
  264.         }
  265.         
  266.         // new structure
  267.         if($arrData['groups'] || $arrData['alias'])
  268.         {
  269.            $arrGroups $arrData['groups'];
  270.         }
  271.         else
  272.         {
  273.            $arrGroups $arrData;
  274.            unset($arrGroups['tstamp']);
  275.         }
  276.         
  277.         if(empty($arrGroups))
  278.         {
  279.            $objTemplate->empty $GLOBALS['TL_LANG']['PCT_CUSTOMELEMENTS']['empty'];
  280.            return $objTemplate;
  281.         }
  282.         
  283.         $arrTplGroups = array();        
  284.         $arrTplAttributes = array();
  285.         $arrElements = array();            // all attributes generated (html)
  286.         $arrFieldsAssoc = array();        // key is alias and alias#countCopy
  287.         $arrGroupsAssoc = array();        // key is alias and alias#countCopy
  288.         $intCountCopies 0;
  289.         $tmpCountGroups = array();        // count how many copies of the same group exists per per group id
  290.         
  291.         foreach($arrGroups as $i => $group)
  292.         {
  293.             $groupId $group['group_id'];
  294.             $groupAlias $group['group_alias'] ?? $GLOBALS['PCT_CUSTOMELEMENTS']['cache']['group'][$groupId]['alias'];
  295.             
  296.             $isCopy false;
  297.             if( isset($group['isCopy']) || isset($group['is_copy']) )
  298.             {
  299.                 $isCopy true;
  300.             }
  301.             
  302.             $objGroup null;
  303.             
  304.             if(strlen($groupAlias) > 0)
  305.             {
  306.                 $objGroup GroupFactory::findByAliasAndCustomElement($groupAlias,$this->get('alias'));
  307.             }
  308.             // hardcore fallback to first CE version
  309.             else if($groupId && strlen($groupAlias) < 1)
  310.             {
  311.                 $objGroup GroupFactory::findById($groupId);
  312.             }
  313.             
  314.             if($objGroup === null)
  315.             {
  316.                 continue;
  317.             }
  318.             
  319.             // continue if group is unpublished or empty
  320.             if(!$objGroup->get('published') || empty($group['attributes']) )
  321.             {
  322.                 continue;
  323.             }
  324.             
  325.             // start indexing
  326.             if(!isset($tmpCountGroups[$groupId]))
  327.             {
  328.                 $tmpCountGroups[$groupId] = 0;
  329.             }
  330.             
  331.             $fields = array();
  332.             foreach($group['attributes'] as $z => $attr)
  333.             {
  334.                 $attr_id $attr['id'];
  335.                 $attr_uuid $attr['uuid'];
  336.                 $attr_alias $attr['alias'];
  337.                 
  338.                 if($isCopy && strlen(strpos($attr_alias'#')) > 0)
  339.                 {
  340.                     $arr explode('#'$attr_alias);
  341.                     $attr_alias $arr[0];
  342.                     unset($arr);
  343.                 }
  344.                 
  345.                 $objAttribute null;
  346.                 
  347.                 // look up from cache
  348.                 if(Cache::getAttribute($attr_id))
  349.                 {
  350.                     $objAttribute Cache::getAttribute($attr_id);
  351.                 }
  352.                 else if(Cache::getAttribute($attr_uuid))
  353.                 {
  354.                     $objAttribute Cache::getAttribute($attr_uuid);
  355.                     if($objAttribute)
  356.                     {
  357.                         Cache::addAttribute('ce_'.$this->get('id').'_'.$objAttribute->get('alias'),$objAttribute);
  358.                     }
  359.                 }
  360.                 else if(Cache::getAttribute('ce_'.$this->get('id').'_'.$attr_alias))
  361.                 {
  362.                     $objAttribute Cache::getAttribute('ce_'.$this->get('id').'_'.$attr_alias);
  363.                 }
  364.                 else
  365.                 {
  366.                     if(!$isCopy)
  367.                     {
  368.                         // store processed attribute objects in the cache
  369.                         $objAttribute AttributeFactory::findPublishedById($attr_id);
  370.                     }
  371.                     else
  372.                     {
  373.                         // store processed attribute objects in the cache
  374.                         $objAttribute AttributeFactory::findByAliasAndCustomElement($attr_alias,$this->get('id'));
  375.                     }
  376.                     
  377.                     if($objAttribute)
  378.                     {
  379.                         Cache::addAttribute($objAttribute->get('id'),$objAttribute);
  380.                         Cache::addAttribute('ce_'.$this->get('id').'_'.$objAttribute->get('alias'),$objAttribute);
  381.                     }
  382.                 }
  383.                 
  384.                 if(!$objAttribute)
  385.                 {
  386.                     continue;
  387.                 }
  388.                 
  389.                 // flag as copy and update the uuid for generic attributes
  390.                 if($isCopy)
  391.                 {
  392.                     $objAttribute->isCopy true;
  393.                     $objAttribute->uuid $attr['uuid'];
  394.                 }
  395.                 
  396.                 // pass the origin object to the attribute
  397.                 $objAttribute->setOrigin($objOrigin);
  398.                 // pass the active record as model
  399.                 $objAttribute->set('objActiveRecord'$objActiveRecord );
  400.                 
  401.                 // get value
  402.                 $varValue $arrData['values'][$attr['uuid']];
  403.                 // check if wizard has the value data
  404.                 if(!empty($arrData['values'][$attr['uuid']]))
  405.                 {
  406.                     // check if images have the correct binary or uuid format
  407.                     if($objAttribute->get('type') == 'image' || $objAttribute->get('saveDataAs') == 'binary')
  408.                     {
  409.                         if(!\Contao\Validator::isUuid($varValue))
  410.                         {
  411.                             $varValue \PCT\CustomElements\Core\Vault::getAttributeValueByUuid( ($isCopy $objAttribute->uuid $objAttribute->get('uuid') ),$objOrigin::get('pid'),$objOrigin::get('table'),array('saveDataAs'=>$objAttribute->get('saveDataAs')));
  412.                         }
  413.                         else if(\Contao\Validator::isBinaryUuid($varValue))
  414.                         {
  415.                             if(class_exists('\Contao\StringUtil'))
  416.                             {
  417.                                 $varValue \Contao\StringUtil::binToUuid($varValue);
  418.                             }
  419.                             else
  420.                             {
  421.                                 $varValue \Contao\StringUtil::binToUuid($varValue);
  422.                             }
  423.                         }
  424.                     }
  425.                     
  426.                     // set the option values
  427.                     $arrOptionValues = array();
  428.                     $arrOptions \Contao\StringUtil::deserialize($objAttribute->get('options'));
  429.                     if(is_array($arrOptions) && strlen($attr_uuid) > 0)
  430.                     {
  431.                         foreach($arrOptions as $option)
  432.                         {
  433.                             if(is_array($option))
  434.                             {
  435.                                 continue;
  436.                             }
  437.                             
  438.                             if(isset($arrData['values'][$attr_uuid.'_'.$option]))
  439.                             {
  440.                                 $arrOptionValues[$option] = $arrData['values'][$attr_uuid.'_'.$option];
  441.                             }
  442.                         }
  443.                     }
  444.                     
  445.                     if(count($arrOptionValues) > 0)
  446.                     {
  447.                         $objAttribute->setOptionValues($arrOptionValues);
  448.                     }
  449.                 }
  450.                 
  451.                 // set attribute value
  452.                 $objAttribute->setValue($varValue);
  453.                 
  454.                 $strKey $objAttribute->get('alias');
  455.                 
  456.                 // field classes
  457.                    $arrClass = array('field_'.$z,$objAttribute->get('type'));
  458.                    $z == $arrClass[] = 'first' '';
  459.                    $z%== $arrClass[] = 'even' $arrClass[] = 'odd';
  460.                    $z >= count($group['attributes'])-$arrClass[] = 'last' '';
  461.                
  462.                 // create TemplateAttribute object
  463.                 $objTplAttribute = new TemplateAttribute($objAttribute);
  464.                 $objTplAttribute->class implode(' '$arrClass);
  465.                 $objTplAttribute->label $objAttribute->get('title');
  466.                 $objTplAttribute->name $attr['uuid'];
  467.                 $objTplAttribute->value $varValue;
  468.                 // store the field associated with a counter
  469.                    $strAssocKey $strKey.'#'.$tmpCountGroups[$groupId];
  470.                    
  471.                    $arrFieldsAssoc[$strAssocKey] = $objTplAttribute;
  472.                    $arrFieldsAssoc[$strKey] = $objTplAttribute;
  473.                    
  474.                    $fields[] = $objTplAttribute;
  475.                 $arrTplAttributes[] = $objTplAttribute;
  476.                 
  477.                 // count the attributes processed when debugging is enabled
  478.                 if($GLOBALS['PCT_CUSTOMELEMENTS']['debug'])
  479.                 {
  480.                     $GLOBALS['PCT_CUSTOMELEMENTS']['process']['attributes']++;
  481.                 }
  482.             }
  483.             
  484.             // group classes
  485.             $arrClass = array('group','group_'.$i,$groupAlias);
  486.             $i == $arrClass[] = 'first' '';
  487.             $i%== $arrClass[] = 'even' $arrClass[] = 'odd';
  488.             $i >= count($arrGroups)-$arrClass[] = 'last' '';
  489.             
  490.             if($tmpCountGroups[$groupId] == 0)
  491.             {
  492.                 $arrClass[] = 'parent';
  493.             }
  494.             else
  495.             {
  496.                 $arrClass[] = 'copy copy_'.$tmpCountGroups[$groupId];
  497.             }
  498.             
  499.             $strCssId '';
  500.             if($objGroup->cssID)
  501.             {
  502.                 $cssID \Contao\StringUtil::deserialize$objGroup->cssID );
  503.                 if(strlen($cssID[0]) > 0)
  504.                 {
  505.                     $strCssId 'id="'.$cssID[0].'"';
  506.                 }
  507.                 
  508.                 if(strlen($cssID[1]) > 0)
  509.                 {
  510.                     $arrClass[] = $cssID[1];
  511.                 }
  512.             }
  513.             
  514.             $arrTplGroups[] = array
  515.             (
  516.                 'class'        => implode(' 'array_unique($arrClass)),
  517.                 'fields'    => $fields,
  518.                 'cssID'        => $strCssId,
  519.             );
  520.             
  521.             // collect assoc groups
  522.             $arrGroupsAssoc[$groupAlias][] = $fields;
  523.             // higher the counter
  524.             ++$tmpCountGroups[$groupId];
  525.         }
  526.         
  527.         $objTemplate->customelement_elements $arrTplAttributes;
  528.         $objTemplate->customelement_groups $arrTplGroups;
  529.         $objTemplate->customelement_attributes $arrTplAttributes;
  530.         $objTemplate->customelement_field $arrFieldsAssoc;
  531.         $objTemplate->customelement_fields $arrTplAttributes;
  532.         $objTemplate->customelement_group $arrGroupsAssoc;
  533.         
  534.         // free temporary variables
  535.         unset($tmpCountGroups);
  536.         unset($arrTplAttributes);
  537.         unset($arrTplGroups);
  538.         unset($arrFieldsAssoc);
  539.         unset($arrGroupsAssoc);
  540.         
  541.         // stop time measurement
  542.         if($GLOBALS['PCT_CUSTOMELEMENTS']['debug'])
  543.         {
  544.             $process_completed sprintf('%.3f'microtime(true) - $process_start);
  545.             $GLOBALS['PCT_CUSTOMELEMENTS']['process']['time'] += $process_completed;
  546.             $GLOBALS['PCT_CUSTOMELEMENTS']['process']['customelements']++;
  547.         }
  548.         
  549.         return $objTemplate;
  550.     }
  551.     
  552.     /**
  553.      * Find an attribute in the custom elements by its alias and return it
  554.      * @param string
  555.      * @return object
  556.      */
  557.     public function getAttributeByAlias($strAttributeAlias)
  558.     {
  559.         return \PCT\CustomElements\Core\AttributeFactory::findByAlias($strAttributeAlias);
  560.     }
  561.     
  562.     
  563.     /**
  564.      * Return the groups array/objecs. Generate the custom element if it has not done before
  565.      * @return array
  566.      */
  567.     public function getGroups()
  568.     {
  569.         return $this->get('arrGroups');
  570.     }
  571.     
  572.     
  573.     /**
  574.      * Return all attributes of the custom element as array
  575.      * @return array
  576.      */
  577.     public function getAttributes()
  578.     {
  579.         \PCT\CustomElements\Core\AttributeFactory::findMultipleByCustomElement($this->id);
  580.     }
  581.     /**
  582.      * Fetch the wizard data and return it as array
  583.      * @return array
  584.      */
  585.     public function getWizardData()
  586.     {
  587.         return \PCT\CustomElements\Core\Vault::getWizardData($this->getOrigin()->get('intPid'),$this->getOrigin()->get('strTable'),$this->getGenericAttribute());
  588.     }
  589.     
  590.     
  591.     /**
  592.      * Set a generic attribute id
  593.      * @param integer
  594.      */
  595.     public function setGenericAttribute($intValue)
  596.     {
  597.         $this->set('intGenericAttribute',$intValue);
  598.         $this->set('blnIsGeneric',true);
  599.     }
  600.     
  601.     
  602.     /**
  603.      * Return the generic attribute id
  604.      * @return integer
  605.      */
  606.     public function getGenericAttribute()
  607.     {
  608.         return $this->get('intGenericAttribute') ?: 0;
  609.     }
  610.     
  611.     
  612.     /**
  613.      * Return true if the custom element created by an attribute => is generic
  614.      * @param boolean
  615.      */
  616.     public function isGeneric()
  617.     {
  618.         return $this->get('blnIsGeneric') ? true false;
  619.     }
  620.     
  621.     
  622.     /**
  623.      * Check if a backend user has access to the custom element
  624.      * @param string
  625.      * @param string
  626.      * @return boolean
  627.      */
  628.     public function hasAccess()
  629.     {
  630.         if(TL_MODE == 'FE' || !$this->get('protected'))
  631.         {
  632.             return true;
  633.         }
  634.         
  635.         $objUser \Contao\BackendUser::getInstance();
  636.         if( empty($objUser->id) )
  637.         {
  638.             $objUser->authenticate();
  639.         }
  640.         
  641.         if($objUser->isAdmin)
  642.         {
  643.             return true;
  644.         }
  645.         
  646.         // check if user has group access
  647.         $usergroups \Contao\StringUtil::deserialize($this->get('user_groups'));
  648.         if(!empty($usergroups) && is_array($usergroups))
  649.         {
  650.             foreach($usergroups as $group)
  651.             {
  652.                 if( in_array($group\Contao\StringUtil::deserialize($objUser->groups)) )
  653.                 {
  654.                     return true;
  655.                 }
  656.             }
  657.         }
  658.         
  659.         // check if user itself has access
  660.         $users \Contao\StringUtil::deserialize($this->get('users') );
  661.         if(!empty($users) && is_array($users))
  662.         {
  663.             if( in_array($objUser->id,$users) )
  664.             {
  665.                 return true;
  666.             }
  667.         }
  668.         
  669.         return false;
  670.     }
  671. }