ModulePlugin

Package engine.modules
Inheritance class ModulePlugin » Module » LsObject
Since 1.0
Source Code /engine/modules/plugin/Plugin.class.php
Модуль управления плагинами

Protected Properties

Hide inherited properties

PropertyTypeDescriptionDefined By
aDelegates array Список engine-rewrite`ов (модули, экшены, сущности, шаблоны) ModulePlugin
aInherits array Стек наследований ModulePlugin
aPluginsList array Список плагинов ModulePlugin
bIsInit bool Указывает на то, была ли проведенна инициализация модуля Module
oEngine Engine Объект ядра Module
sPluginsDir string Путь к директории с плагинами ModulePlugin

Public Methods

Hide inherited methods

MethodDescriptionDefined By
Delegate() Перенаправление вызовов на модули, экшены, сущности ModulePlugin
Delete() Удаляет плагины с сервера ModulePlugin
GetActivePlugins() Возвращает список активированных плагинов в системе ModulePlugin
GetDelegate() Возвращает делегат модуля, экшена, сущности. ModulePlugin
GetDelegateObjectList() Возвращает список объектов, доступных для делегирования ModulePlugin
GetDelegateSign() Возвращает подпись делегата модуля, экшена, сущности. ModulePlugin
GetDelegater() Возвращает делегирующий объект по имени делегата ModulePlugin
GetDelegates() ModulePlugin
GetDelegationChain() Возвращает цепочку делегатов ModulePlugin
GetInherits() Возвращает список наследуемых классов ModulePlugin
GetLastInherit() Возвращает последнего наследника в цепочке ModulePlugin
GetList() Получает список информации о всех плагинах, загруженных в plugin-директорию ModulePlugin
GetParentInherit() Получает следующего родителя у наследника. ModulePlugin
GetRootDelegater() Возвращает делегируемый класс ModulePlugin
Inherit() Добавляет в стек наследника класса ModulePlugin
Init() Инициализация модуля ModulePlugin
SetActivePlugins() Записывает список активных плагинов в файл PLUGINS.DAT ModulePlugin
SetInit() Помечает модуль как инициализированный Module
Shutdown() Метод срабатывает при завершении работы ядра Module
Toggle() Переключает состояние плагина активный/не активный ModulePlugin
__call() Ставим хук на вызов неизвестного метода и считаем что хотели вызвать метод какого либо модуля Module
__construct() При создании модуля передаем объект ядра Module
collectAllDelegatesRecursive() Составляет цепочку делегатов ModulePlugin
isDelegated() Возвращает true, если устано ModulePlugin
isDelegater() Возвращает true, если установлено правило делегирования ModulePlugin
isInit() Возвращает значение флага инициализации модуля Module

Protected Methods

Hide inherited methods

MethodDescriptionDefined By
Xlang() Получает значение параметра из XML на основе языковой разметки ModulePlugin
__clone() Блокируем копирование/клонирование объекта Module

Property Details

aDelegates property
protected array $aDelegates;

Список engine-rewrite`ов (модули, экшены, сущности, шаблоны) Определяет типы объектов, которые может переопределить/унаследовать плагин

aInherits property
protected array $aInherits;

Стек наследований

aPluginsList property
protected array $aPluginsList;

Список плагинов

sPluginsDir property
protected string $sPluginsDir;

Путь к директории с плагинами

Method Details

Delegate() method
public void Delegate(string $sType, string $sFrom, string $sTo, string $sSign='ModulePlugin')
$sType string
$sFrom string
$sTo string
$sSign string
Source Code: /engine/modules/plugin/Plugin.class.php#376 (show)
public function Delegate($sType,$sFrom,$sTo,$sSign=__CLASS__) {
    
/**
     * Запрещаем неподписанные делегаты
     */
    
if(!is_string($sSign) or !strlen($sSign)) return null;
    if(!
in_array($sType,array_keys($this->aDelegates)) or !$sFrom or !$sTo) return null;

    
$this->aDelegates[$sType][trim($sFrom)]=array(
        
'delegate'=>trim($sTo),
        
'sign'=>$sSign
    
);
}

Перенаправление вызовов на модули, экшены, сущности

Delete() method
public void Delete(array $aPlugins)
$aPlugins array Список плагинов для удаления
Source Code: /engine/modules/plugin/Plugin.class.php#352 (show)
public function Delete($aPlugins) {
    if(!
is_array($aPlugins)) $aPlugins=array($aPlugins);

    
$aActivePlugins=$this->GetActivePlugins();
    foreach (
$aPlugins as $sPluginCode) {
        
/**
         * Если плагин активен, деактивируем его
         */
        
if(in_array($sPluginCode,$aActivePlugins)) $this->Toggle($sPluginCode,'deactivate');

        
/**
         * Удаляем директорию с плагином
         */
        
func_rmdir($this->sPluginsDir.$sPluginCode);
    }
}

Удаляет плагины с сервера

GetActivePlugins() method
public array GetActivePlugins()
{return} array
Source Code: /engine/modules/plugin/Plugin.class.php#321 (show)
public function GetActivePlugins() {
    
/**
     * Читаем данные из файла PLUGINS.DAT
     */
    
$aPlugins=@file($this->sPluginsDir.Config::Get('sys.plugins.activation_file'));
    
$aPlugins =(is_array($aPlugins))?array_unique(array_map('trim',$aPlugins)):array();

    return 
$aPlugins;
}

Возвращает список активированных плагинов в системе

GetDelegate() method
public string GetDelegate(string $sType, string $sFrom)
$sType string
$sFrom string
{return} string
Source Code: /engine/modules/plugin/Plugin.class.php#451 (show)
public function GetDelegate($sType,$sFrom) {
    if (isset(
$this->aDelegates[$sType][$sFrom]['delegate'])) {
        return 
$this->aDelegates[$sType][$sFrom]['delegate'];
    } elseif (
$aInherit=$this->GetLastInherit($sFrom)) {
        return 
$aInherit['inherit'];
    }
    return 
$sFrom;
}

Возвращает делегат модуля, экшена, сущности. Если делегат не определен, пытается найти наследника, иначе отдает переданный в качестве sender`a параметр

GetDelegateObjectList() method
public array GetDelegateObjectList()
{return} array
Source Code: /engine/modules/plugin/Plugin.class.php#623 (show)
public function GetDelegateObjectList() {
    return 
array_keys($this->aDelegates);
}

Возвращает список объектов, доступных для делегирования

GetDelegateSign() method
public string|null GetDelegateSign(string $sType, string $sFrom)
$sType string
$sFrom string
{return} string|null
Source Code: /engine/modules/plugin/Plugin.class.php#559 (show)
public function GetDelegateSign($sType,$sFrom) {
    if (isset(
$this->aDelegates[$sType][$sFrom]['sign'])) {
        return 
$this->aDelegates[$sType][$sFrom]['sign'];
    }
    if (
$aInherit=$this->GetLastInherit($sFrom)) {
        return 
$aInherit['sign'];
    }
    return 
null;
}

Возвращает подпись делегата модуля, экшена, сущности.

GetDelegater() method
public string GetDelegater(string $sType, string $sTo)
$sType string Объект
$sTo string Делегат
{return} string
Source Code: /engine/modules/plugin/Plugin.class.php#528 (show)
public function GetDelegater($sType,$sTo) {
    
$aDelegateMapper=array();
    foreach(
$this->aDelegates[$sType] as $kk=>$vv) {
        if (
$vv['delegate']==$sTo) {
            
$aDelegateMapper[$kk]=$vv;
        }
    }
    if (
is_array($aDelegateMapper) and count($aDelegateMapper))    {
        
$aKeys=array_keys($aDelegateMapper);
        return 
array_shift($aKeys);
    }
    foreach (
$this->aInherits as $k=>$v) {
        
$aInheritMapper=array();
        foreach(
$v['items'] as $kk=>$vv) {
            if (
$vv['inherit']==$sTo) {
                
$aInheritMapper[$kk]=$vv;
            }
        }
        if (
is_array($aInheritMapper) and count($aInheritMapper))    {
            return 
$k;
        }
    }
    return 
$sTo;
}

Возвращает делегирующий объект по имени делегата

GetDelegates() method
public array|null GetDelegates(string $sType, string $sFrom)
$sType string
$sFrom string
{return} array|null
Source Code: /engine/modules/plugin/Plugin.class.php#464 (show)
public function GetDelegates($sType,$sFrom) {
    if (isset(
$this->aDelegates[$sType][$sFrom]['delegate'])) {
        return array(
$this->aDelegates[$sType][$sFrom]['delegate']);
    } else if(
$aInherits=$this->GetInherits($sFrom)) {
        
$aReturn=array();
        foreach(
array_reverse($aInherits) as $v) {
            
$aReturn[]=$v['inherit'];
        }
        return 
$aReturn;
    }
    return 
null;
}

GetDelegationChain() method
public array GetDelegationChain(string $sType, string $sTo)
$sType string
$sTo string
{return} array
Source Code: /engine/modules/plugin/Plugin.class.php#483 (show)
public function GetDelegationChain($sType,$sTo) {
    
$sRootDelegater $this->GetRootDelegater($sType,$sTo);
    return 
$this->collectAllDelegatesRecursive($sType,array($sRootDelegater));
}

Возвращает цепочку делегатов

GetInherits() method
public null|array GetInherits(string $sFrom)
$sFrom string
{return} null|array
Source Code: /engine/modules/plugin/Plugin.class.php#425 (show)
public function GetInherits($sFrom) {
    if (isset(
$this->aInherits[trim($sFrom)])) {
        return 
$this->aInherits[trim($sFrom)]['items'];
    }
    return 
null;
}

Возвращает список наследуемых классов

GetLastInherit() method
public null|string GetLastInherit($sFrom $sFrom)
$sFrom $sFrom
{return} null|string
Source Code: /engine/modules/plugin/Plugin.class.php#437 (show)
public function GetLastInherit($sFrom) {
    if (isset(
$this->aInherits[trim($sFrom)])) {
        return 
$this->aInherits[trim($sFrom)]['items'][count($this->aInherits[trim($sFrom)]['items'])-1];
    }
    return 
null;
}

Возвращает последнего наследника в цепочке

GetList() method
public array GetList($aFilter=array ( ))
$aFilter
{return} array
Source Code: /engine/modules/plugin/Plugin.class.php#76 (show)
public function GetList($aFilter=array()) {
    if (
$aPaths=glob($this->sPluginsDir.'*',GLOB_ONLYDIR)) {
        
$aList=array_map('basename',$aPaths);
        
$aActivePlugins=$this->GetActivePlugins();
        foreach(
$aList as $sPlugin) {
            
$this->aPluginsList[$sPlugin] = array(
                
'code'      => $sPlugin,
                
'is_active' => in_array($sPlugin,$aActivePlugins)
            );

            
/**
             * Считываем данные из XML файла описания
             */
            
$sPluginXML $this->sPluginsDir.$sPlugin.'/'.self::PLUGIN_XML_FILE;
            if(
$oXml = @simplexml_load_file($sPluginXML)) {
                
/**
                 * Обрабатываем данные, считанные из XML-описания
                 */
                
$sLang=$this->Lang_GetLang();

                
$this->Xlang($oXml,'name',$sLang);
                
$this->Xlang($oXml,'author',$sLang);
                
$this->Xlang($oXml,'description',$sLang);
                
$oXml->homepage=$this->Text_Parser($oXml->homepage);
                
$oXml->settings=preg_replace('/{([^}]+)}/',Router::GetPath('$1'),$oXml->settings);

                
$this->aPluginsList[$sPlugin]['property']=$oXml;
            } else {
                
/**
                 * Если XML-файл описания отсутствует, или не является валидным XML,
                 * удаляем плагин из списка
                 */
                
unset($this->aPluginsList[$sPlugin]);
            }
        }
    }
    
/**
     * Если нужно сортировать плагины
     */
    
if (isset($aFilter['order'])) {
        if (
$aFilter['order']=='name') {
            
$aPlugins=$this->aPluginsList;
            
uasort($aPluginscreate_function('$a,$b',"if ((string)\$a['property']->name->data == (string)\$b['property']->name->data) { return 0; } return ((string)\$a['property']->name->data < (string)\$b['property']->name->data) ? -1 : 1;"));
            return 
$aPlugins;
        }
    }
    return 
$this->aPluginsList;
}

Получает список информации о всех плагинах, загруженных в plugin-директорию

GetParentInherit() method
public string GetParentInherit(string $sFrom)
$sFrom string
{return} string
Source Code: /engine/modules/plugin/Plugin.class.php#412 (show)
public function GetParentInherit($sFrom) {
    if (!isset(
$this->aInherits[$sFrom]['items']) or count($this->aInherits[$sFrom]['items'])<=or $this->aInherits[$sFrom]['position']<1) {
        return 
$sFrom;
    }
    
$this->aInherits[$sFrom]['position']--;
    return 
$this->aInherits[$sFrom]['items'][$this->aInherits[$sFrom]['position']]['inherit'];
}

Получает следующего родителя у наследника. ВНИМАНИЕ! Данный метод нужно вызвать только из __autoload()

GetRootDelegater() method
public string GetRootDelegater(string $sType, string $sTo)
$sType string
$sTo string
{return} string
Source Code: /engine/modules/plugin/Plugin.class.php#494 (show)
public function GetRootDelegater($sType,$sTo) {
    
$sItem $sTo;
    
$sItemDelegater $this->GetDelegater($sType,$sTo);
    while(empty(
$sRootDelegater)) {
        if(
$sItem==$sItemDelegater) {
            
$sRootDelegater $sItem;
        }
        
$sItem $sItemDelegater;
        
$sItemDelegater $this->GetDelegater($sType,$sItemDelegater);
    }
    return 
$sRootDelegater;
}

Возвращает делегируемый класс

Inherit() method
public void Inherit(string $sFrom, string $sTo, string $sSign='ModulePlugin')
$sFrom string
$sTo string
$sSign string
Source Code: /engine/modules/plugin/Plugin.class.php#395 (show)
public function Inherit($sFrom,$sTo,$sSign=__CLASS__) {
    if(!
is_string($sSign) or !strlen($sSign)) return null;
    if(!
$sFrom or !$sTo) return null;

    
$this->aInherits[trim($sFrom)]['items'][]=array(
        
'inherit'=>trim($sTo),
        
'sign'=>$sSign
    
);
    
$this->aInherits[trim($sFrom)]['position']=count($this->aInherits[trim($sFrom)]['items'])-1;
}

Добавляет в стек наследника класса

Init() method
public void Init()
Source Code: /engine/modules/plugin/Plugin.class.php#68 (show)
public function Init() {
    
$this->sPluginsDir=Config::Get('path.root.server').'/plugins/';
}

Инициализация модуля

SetActivePlugins() method
public bool SetActivePlugins(array|string $aPlugins)
$aPlugins array|string Список плагинов
{return} bool
Source Code: /engine/modules/plugin/Plugin.class.php#336 (show)
public function SetActivePlugins($aPlugins) {
    if(!
is_array($aPlugins)) $aPlugins = array($aPlugins);
    
$aPlugins=array_unique(array_map('trim',$aPlugins));
    
/**
     * Записываем данные в файл PLUGINS.DAT
     */
    
if (@file_put_contents($this->sPluginsDir.Config::Get('sys.plugins.activation_file'), implode(PHP_EOL,$aPlugins))!==false) {
        return 
true;
    }
    return 
false;
}

Записывает список активных плагинов в файл PLUGINS.DAT

Toggle() method
public null|bool Toggle(string $sPlugin, $sAction $sAction)
$sPlugin string Название плагина(код)
$sAction $sAction Действие - activate/deactivate
{return} null|bool
Source Code: /engine/modules/plugin/Plugin.class.php#146 (show)
public function Toggle($sPlugin,$sAction) {
    
$aPlugins=$this->GetList();
    if(!isset(
$aPlugins[$sPlugin])) return null;

    
$sPluginName=func_camelize($sPlugin);

    switch (
$sAction) {
        case 
'activate':
        case 
'deactivate':
            
$sAction=ucfirst($sAction);

            
$sFile="{$this->sPluginsDir}{$sPlugin}/Plugin{$sPluginName}.class.php";
            if(
is_file($sFile)) {
                require_once(
$sFile);

                
$sClassName="Plugin{$sPluginName}";
                
$oPlugin=new $sClassName;

                if(
$sAction=='Activate') {
                    
/**
                     * Проверяем совместимость с версией LS
                     */
                    
if(defined('LS_VERSION')
                        and 
version_compare(LS_VERSION,(string)$aPlugins[$sPlugin]['property']->requires->livestreet,'<')) {
                        
$this->Message_AddError(
                            
$this->Lang_Get(
                                
'plugins_activation_version_error',
                                array(
                                    
'version'=>$aPlugins[$sPlugin]['property']->requires->livestreet)
                            ),
                            
$this->Lang_Get('error'),
                            
true
                        
);
                        return;
                    }
                    
/**
                     * Проверяем наличие require-плагинов
                     */
                    
if($aPlugins[$sPlugin]['property']->requires->plugins) {
                        
$aActivePlugins=$this->GetActivePlugins();
                        
$iConflict=0;
                        foreach (
$aPlugins[$sPlugin]['property']->requires->plugins->children() as $sReqPlugin) {
                            if(!
in_array($sReqPlugin,$aActivePlugins)) {
                                
$iConflict++;
                                
$this->Message_AddError(
                                    
$this->Lang_Get('plugins_activation_requires_error',
                                                    array(
                                                        
'plugin'=>func_camelize($sReqPlugin)
                                                    )
                                    ),
                                    
$this->Lang_Get('error'),
                                    
true
                                
);
                            }
                        }
                        if(
$iConflict) { return; }
                    }

                    
/**
                     * Проверяем, не вступает ли данный плагин в конфликт с уже активированными
                     * (по поводу объявленных делегатов)
                     */
                    
$aPluginDelegates=$oPlugin->GetDelegates();
                    
$aPluginInherits=$oPlugin->GetInherits();
                    
$iConflict=0;
                    foreach (
$this->aDelegates as $sGroup=>$aReplaceList) {
                        
$iCount=0;
                        if(isset(
$aPluginDelegates[$sGroup])
                            and 
is_array($aPluginDelegates[$sGroup])
                                and 
$iCount=count($aOverlap=array_intersect_key($aReplaceList,$aPluginDelegates[$sGroup]))) {
                            
$iConflict+=$iCount;
                            foreach (
$aOverlap as $sResource=>$aConflict) {
                                
$this->Message_AddError(
                                    
$this->Lang_Get('plugins_activation_overlap', array(
                                        
'resource'=>$sResource,
                                        
'delegate'=>$aConflict['delegate'],
                                        
'plugin'  =>$aConflict['sign']
                                    )),
                                    
$this->Lang_Get('error'), true
                                
);
                            }
                        }
                        if(isset(
$aPluginInherits[$sGroup])
                            and 
is_array($aPluginInherits[$sGroup])
                                and 
$iCount=count($aOverlap=array_intersect_key($aReplaceList,$aPluginInherits[$sGroup]))) {
                            
$iConflict+=$iCount;
                            foreach (
$aOverlap as $sResource=>$aConflict) {
                                
$this->Message_AddError(
                                    
$this->Lang_Get('plugins_activation_overlap', array(
                                        
'resource'=>$sResource,
                                        
'delegate'=>$aConflict['delegate'],
                                        
'plugin'  =>$aConflict['sign']
                                    )),
                                    
$this->Lang_Get('error'), true
                                
);
                            }
                        }
                        if(
$iCount){ return; }
                    }
                    
/**
                     * Проверяем на конфликт с наследуемыми классами
                     */
                    
$iConflict=0;
                    foreach (
$aPluginDelegates as $sGroup=>$aReplaceList) {
                        foreach (
$aReplaceList as $sResource=>$aConflict) {
                            if (isset(
$this->aInherits[$sResource])) {
                                
$iConflict+=count($this->aInherits[$sResource]['items']);
                                foreach (
$this->aInherits[$sResource]['items'] as $aItem) {
                                    
$this->Message_AddError(
                                        
$this->Lang_Get('plugins_activation_overlap_inherit', array(
                                            
'resource'=>$sResource,
                                            
'plugin'  =>$aItem['sign']
                                        )),
                                        
$this->Lang_Get('error'), true
                                    
);
                                }
                            }
                        }
                    }
                    if(
$iConflict){ return; }
                }

                
$bResult=$oPlugin->$sAction();
            } else {
                
/**
                 * Исполняемый файл плагина не найден
                 */
                
$this->Message_AddError($this->Lang_Get('plugins_activation_file_not_found'),$this->Lang_Get('error'),true);
                return;
            }

            if(
$bResult) {
                
/**
                 * Переопределяем список активированных пользователем плагинов
                 */
                
$aActivePlugins=$this->GetActivePlugins();
                if(
$sAction=='Activate') {
                    
/**
                     * Вносим данные в файл об активации плагина
                     */
                    
$aActivePlugins[] = $sPlugin;
                } else {
                    
/**
                     * Вносим данные в файл о деактивации плагина
                     */
                    
$aIndex=array_keys($aActivePlugins,$sPlugin);
                    if(
is_array($aIndex)) {
                        unset(
$aActivePlugins[array_shift($aIndex)]);
                    }
                }
                
/**
                 * Сбрасываем весь кеш, т.к. могут быть закешированы унаследованые плагинами сущности
                 */
                
$this->Cache_Clean();
                if (!
$this->SetActivePlugins($aActivePlugins)) {
                    
$this->Message_AddError($this->Lang_Get('plugins_activation_file_write_error'),$this->Lang_Get('error'),true);
                    return;
                }
                
/**
                 * Очищаем компиленые шаблоны от Smarty
                 */
                
$oSmarty=$this->Viewer_GetSmartyObject();
                
$oSmarty->clearCompiledTemplate();
            }
            return 
$bResult;

        default:
            return 
null;
    }
}

Переключает состояние плагина активный/не активный

Xlang() method
protected void Xlang(SimpleXMLElement $oXml, string $sProperty, string $sLang)
$oXml SimpleXMLElement XML узел
$sProperty string Свойство, которое нужно вернуть
$sLang string Название языка
Source Code: /engine/modules/plugin/Plugin.class.php#131 (show)
protected function Xlang($oXml,$sProperty,$sLang) {
    
$sProperty=trim($sProperty);

    if (!
count($data=$oXml->xpath("{$sProperty}/lang[@name='{$sLang}']"))) {
        
$data=$oXml->xpath("{$sProperty}/lang[@name='default']");
    }
    
$oXml->$sProperty->data=$this->Text_Parser(trim((string)array_shift($data)));
}

Получает значение параметра из XML на основе языковой разметки

collectAllDelegatesRecursive() method
public array collectAllDelegatesRecursive(string $sType, string $aDelegates)
$sType string
$aDelegates string
{return} array
Source Code: /engine/modules/plugin/Plugin.class.php#513 (show)
public function collectAllDelegatesRecursive($sType,$aDelegates) {
    foreach(
$aDelegates as $sClass) {
        if(
$aNewDelegates=$this->GetDelegates($sType,$sClass)) {
            
$aDelegates array_merge($this->collectAllDelegatesRecursive($sType,$aNewDelegates),$aDelegates);
        }
    }
    return 
$aDelegates;
}

Составляет цепочку делегатов

isDelegated() method
public bool isDelegated(string $sType, string $sTo)
$sType string
$sTo string
{return} bool
Source Code: /engine/modules/plugin/Plugin.class.php#591 (show)
public function isDelegated($sType,$sTo) {
    
/**
     * Фильтруем маппер делегатов/наследников
     * @var array
     */
    
$aDelegateMapper=array();
    foreach(
$this->aDelegates[$sType] as $kk=>$vv) {
        if (
$vv['delegate']==$sTo) {
            
$aDelegateMapper[$kk]=$vv;
        }
    }
    if (
is_array($aDelegateMapper) and count($aDelegateMapper))    {
        return 
true;
    }
    foreach (
$this->aInherits as $k=>$v) {
        
$aInheritMapper=array();
        foreach(
$v['items'] as $kk=>$vv) {
            if (
$vv['inherit']==$sTo) {
                
$aInheritMapper[$kk]=$vv;
            }
        }
        if (
is_array($aInheritMapper) and count($aInheritMapper))    {
            return 
true;
        }
    }
    return 
false;
}

Возвращает true, если устано

isDelegater() method
public bool isDelegater(string $sType, string $sFrom)
$sType string
$sFrom string
{return} bool
Source Code: /engine/modules/plugin/Plugin.class.php#576 (show)
public function isDelegater($sType,$sFrom) {
    if (isset(
$this->aDelegates[$sType][$sFrom]['delegate'])) {
        return 
true;
    } elseif (
$aInherit=$this->GetLastInherit($sFrom)) {
        return 
true;
    }
    return 
false;
}

Возвращает true, если установлено правило делегирования и класс является базовым в данном правиле