public function flushChanges()
    {
        $queue = QueuedJobService::singleton();
        if (!empty($this->toUpdate)) {
            foreach ($this->toUpdate as $queueItem) {
                $job = Injector::inst()->create(GenerateStaticCacheJob::class);

                $jobData = new \stdClass();
                $urls = $queueItem->urlsToCache();
                ksort($urls);
                $jobData->URLsToProcess = $urls;

                $job->setJobData(0, 0, false, $jobData, [
                    'Building URLs: ' . var_export(array_keys($jobData->URLsToProcess), true)
                ]);

                $queue->queueJob($job);
            }
            $this->toUpdate = array();
        }

        if (!empty($this->toDelete)) {
            foreach ($this->toDelete as $queueItem) {
                $job = Injector::inst()->create(DeleteStaticCacheJob::class);

                $jobData = new \stdClass();
                $urls = $queueItem->urlsToCache();
                ksort($urls);
                $jobData->URLsToProcess = $urls;

                $job->setJobData(0, 0, false, $jobData, [
                    'Purging URLs: ' . var_export(array_keys($jobData->URLsToProcess), true)
                ]);

                $queue->queueJob($job);
            }
            $this->toDelete = array();
        }
    }

public
function
flushChanges
(
)
{
$
queue
=
QueuedJobService
::
singleton
(
)
;
if
(
!
empty
(
$
this
->
toUpdate
)
)
{
foreach
(
$
this
->
toUpdate
as
$
queueItem
)
{
$
job
=
Injector
::
inst
(
)
->
create
(
GenerateStaticCacheJob
::
class
)
;
$
jobData
=
new
\
stdClass
(
)
;
$
urls
=
$
queueItem
->
urlsToCache
(
)
;
ksort
(
$
urls
)
;
$
jobData
->
URLsToProcess
=
$
urls
;
$
job
->
setJobData
(
0
,
0
,
false
,
$
jobData
,
[
'Building URLs: '
.
var_export
(
array_keys
(
$
jobData
->
URLsToProcess
)
,
true
)
]
)
;
$
queue
->
queueJob
(
$
job
)
;
}
$
this
->
toUpdate
=
array
(
)
;
}
if
(
!
empty
(
$
this
->
toDelete
)
)
{
foreach
(
$
this
->
toDelete
as
$
queueItem
)
{
$
job
=
Injector
::
inst
(
)
->
create
(
DeleteStaticCacheJob
::
class
)
;
$
jobData
=
new
\
stdClass
(
)
;
$
urls
=
$
queueItem
->
urlsToCache
(
)
;
ksort
(
$
urls
)
;
$
jobData
->
URLsToProcess
=
$
urls
;
$
job
->
setJobData
(
0
,
0
,
false
,
$
jobData
,
[
'Purging URLs: '
.
var_export
(
array_keys
(
$
jobData
->
URLsToProcess
)
,
true
)
]
)
;
$
queue
->
queueJob
(
$
job
)
;
}
$
this
->
toDelete
=
array
(
)
;
}
}

Execute URL deletions, enqueue URL updates.

Execute URL deletions enqueue URL updates .


protected function getModuleExtensionsGarbage($moduleMetaDataExtensions, $moduleInstalledExtensions)
    {

        $garbage = parent::getModuleExtensionsGarbage($moduleMetaDataExtensions, $moduleInstalledExtensions);

        foreach ($moduleInstalledExtensions as $coreClassName => $listOfExtensions) {
            foreach ($listOfExtensions as $extensions) {
                if (! (isset($moduleMetaDataExtensions[$coreClassName]) && $moduleMetaDataExtensions[$coreClassName] == $extensions)) {
                    $garbage[$coreClassName][] = $extensions;
                }
            }
        }

        return $garbage;
    }

protected function getModuleExtensionsGarbage ( $ moduleMetaDataExtensions , $ moduleInstalledExtensions ) { $ garbage = parent :: getModuleExtensionsGarbage ( $ moduleMetaDataExtensions , $ moduleInstalledExtensions ) ; foreach ( $ moduleInstalledExtensions as $ coreClassName => $ listOfExtensions ) { foreach ( $ listOfExtensions as $ extensions ) { if ( ! ( isset ( $ moduleMetaDataExtensions [ $ coreClassName ] ) && $ moduleMetaDataExtensions [ $ coreClassName ] == $ extensions ) ) { $ garbage [ $ coreClassName ] [ ] = $ extensions ; } } } return $ garbage ; }

Returns extension which is no longer in metadata - garbage

@param array $moduleMetaDataExtensions  extensions defined in metadata.
@param array $moduleInstalledExtensions extensions which are installed

@return array


protected function filterExtensionsByModule($modules, $module)
    {
        if ($this->isMetadataVersionGreaterEqual($module, '2.0')) {
            $moduleHelper = Registry::get(ModuleHelper::class);
            $moduleHelper->setModule($module);
            $path = $moduleHelper->getModuleNameSpace();
        } else {

            $modulePaths = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('aModulePaths');

            $moduleId = $module->getId();
            $path = '';
            if (isset($modulePaths[$moduleId])) {
                $path = $modulePaths[$moduleId] . '/';
            }

            if (!$path) {
                $path = $moduleId . "/";
            }
        }
        $filteredModules = [];

        if (!$path) {
            return $filteredModules;
        }

       foreach ($modules as $class => $extend) {
            foreach ($extend as $extendPath) {
                if (strpos($extendPath, $path) === 0) {
                    $filteredModules[$class][] = $extendPath;
                }
            }
        }

        return $filteredModules;
    }

protected function filterExtensionsByModule ( $ modules , $ module ) { if ( $ this -> isMetadataVersionGreaterEqual ( $ module , '2.0' ) ) { $ moduleHelper = Registry :: get ( ModuleHelper :: class ) ; $ moduleHelper -> setModule ( $ module ) ; $ path = $ moduleHelper -> getModuleNameSpace ( ) ; } else { $ modulePaths = \ OxidEsales \ Eshop \ Core \ Registry :: getConfig ( ) -> getConfigParam ( 'aModulePaths' ) ; $ moduleId = $ module -> getId ( ) ; $ path = '' ; if ( isset ( $ modulePaths [ $ moduleId ] ) ) { $ path = $ modulePaths [ $ moduleId ] . '/' ; } if ( ! $ path ) { $ path = $ moduleId . "/" ; } } $ filteredModules = [ ] ; if ( ! $ path ) { return $ filteredModules ; } foreach ( $ modules as $ class => $ extend ) { foreach ( $ extend as $ extendPath ) { if ( strpos ( $ extendPath , $ path ) === 0 ) { $ filteredModules [ $ class ] [ ] = $ extendPath ; } } } return $ filteredModules ; }

Returns extensions list by module id.

@param array  $modules  Module array (nested format)
@param string $module Module id/folder name

@return array


public function getModuleBlocks()
    {
        $config = Registry::getConfig();
        $activeThemeIds = oxNew(\OxidEsales\Eshop\Core\Theme::class)->getActiveThemesList();
        $activeThemeIds[] = '';

        $themeIdsSql = join(', ', \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->quoteArray($activeThemeIds));

        $aResults = DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC)->select(
            "SELECT OXID as id,
                           OXACTIVE as active,
                           OXTHEME as theme,
                           OXTEMPLATE as template,
                           OXBLOCKNAME as block,
                           OXFILE as file,
                           OXPOS
                    FROM oxtplblocks
                    WHERE oxModule = ? AND oxshopid = ? AND OXTHEME IN ($themeIdsSql)
                    ORDER BY OXTHEME, OXTEMPLATE, OXBLOCKNAME",
            [$this->getId(), $config->getShopId()]
        );

        return $aResults->fetchAll();
    }

Get template blocks defined in database.

@return array
@throws \OxidEsales\Eshop\Core\Exception\DatabaseErrorException

Get template blocks defined in database .


public function getModuleSettings()
    {
        $aResult = DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC)->select(
            'SELECT * FROM oxconfig WHERE oxModule = ? AND oxshopid = ?',
            [sprintf('module:%s', $this->getId()), Registry::getConfig()->getShopId()]
        );

        return $aResult->fetchAll();
    }

Get module settings defined in database.

@return array

Get module settings defined in database .


public function isMetadataSupported()
    {
        $sMetadataVersion = $this->getMetaDataVersion();

        $sLatestVersion = '1.0';

        if (method_exists('oxModuleList', 'getModuleVersions') || method_exists('oxModule', 'getModuleEvents')) {
            $sLatestVersion = '1.1';
        }

        if (method_exists(ModuleList::class, 'getModuleConfigParametersByKey')) {
            $sLatestVersion = '2.0';
        }

        if (method_exists(ModuleList::class, 'getSmartyPluginDirectories')) {
            $sLatestVersion = '2.1';
        }

        return version_compare($sLatestVersion, $sMetadataVersion) >= 0;
    }

public function isMetadataSupported ( ) { $ sMetadataVersion = $ this -> getMetaDataVersion ( ) ; $ sLatestVersion = '1.0' ; if ( method_exists ( 'oxModuleList' , 'getModuleVersions' ) || method_exists ( 'oxModule' , 'getModuleEvents' ) ) { $ sLatestVersion = '1.1' ; } if ( method_exists ( ModuleList :: class , 'getModuleConfigParametersByKey' ) ) { $ sLatestVersion = '2.0' ; } if ( method_exists ( ModuleList :: class , 'getSmartyPluginDirectories' ) ) { $ sLatestVersion = '2.1' ; } return version_compare ( $ sLatestVersion , $ sMetadataVersion ) >= 0 ; }

Check supported metadata version

@return bool


public function checkPhpFileExists($sClassName)
    {
        if ($this->isMetadataVersionGreaterEqual('2.0')) {
            $composerClassLoader = $this->getModuleHelper()->getAutoloader();

            return $composerClassLoader->findFile($sClassName);
        } else {
            $sExtensionPath = $sClassName . '.php';
            $res = $this->checkFileExists($sExtensionPath);
            return $res;
        }
    }

public function checkPhpFileExists ( $ sClassName ) { if ( $ this -> isMetadataVersionGreaterEqual ( '2.0' ) ) { $ composerClassLoader = $ this -> getModuleHelper ( ) -> getAutoloader ( ) ; return $ composerClassLoader -> findFile ( $ sClassName ) ; } else { $ sExtensionPath = $ sClassName . '.php' ; $ res = $ this -> checkFileExists ( $ sExtensionPath ) ; return $ res ; } }

checks if module file exists on directory
switches between metadata version for checking
checks also for namespace class if metadata version = 2.0

@param string $sClassName
@param string $sExtention

@return bool

checks if module file exists on directory switches between metadata version for checking checks also for namespace class if metadata version = 2 . 0


public function checkModuleVersions()
    {
        $sDatabaseVersion = $this->getModuleEntries(ModuleList::MODULE_KEY_VERSIONS);

        /**
         * Set version for disabled module
         */
        if (!count($sDatabaseVersion)) {
            $iLang = \OxidEsales\Eshop\Core\Registry::getLang()->getTplLanguage();
            $sDatabaseVersion = $this->getInfo("version", $iLang);
        }

        $aResult = $this->toResult(['version'=>$sDatabaseVersion]);

        return $aResult;
    }

Analyze versions in metadata
checks if metadata version is same as database entry for metadata

@return array


public function checkExtendedClasses()
    {
        $aMetadataExtend = $this->getInfo('extend');
        $aMetadataExtend = is_array($aMetadataExtend) ? $aMetadataExtend : [];

        $aResult = [];

        /**
         * only convert class names to lower if we don't use namespace
         */
        if (!$this->isMetadataVersionGreaterEqual('2.0')) {
            $aMetadataExtend = array_change_key_case($aMetadataExtend, CASE_LOWER);
            //convert legacy classnames because $aAllModules dos not contain legacy classes
            if (method_exists(Registry::class ,'getBackwardsCompatibilityClassMap')) {
                $map = Registry::getBackwardsCompatibilityClassMap();
                foreach ($aMetadataExtend as $legacyName => $file) {
                    if (isset($map[$legacyName])) {
                        $namespaceName = $map[$legacyName];
                        $aMetadataExtend[$namespaceName] = $file;
                        unset($aMetadataExtend[$legacyName]);
                    }
                }
            }
        }

        foreach ($aMetadataExtend as $sClassName => $sModuleName) {
            $key_state = $iState = self::OK;

            if (strpos($sClassName,'OxidEsales\\EshopCommunity\\') === 0 ||
                strpos($sClassName,'OxidEsales\\EshopEnterprise\\') === 0 ||
                strpos($sClassName,'OxidEsales\\EshopProfessional\\') === 0 ||
                !class_exists($sClassName)
            ) {
                if (strpos($sClassName,'oxerp') === 0) {
                    //AS ERP module does still use a own autoloader
                    //classes of oxerp will not be found with class_exists
                    $erp_dir = Registry::getConfig()->getModulesDir() .'erp/';
                    if (strpos($sClassName,'oxerptype_') === 0) {
                        $dir = $erp_dir.'objects/';
                    } else {
                        $dir = $erp_dir;
                    }

                    $sFullPath  = $dir.$sClassName.'.php';

                    if (!file_exists($sFullPath)) {
                        $key_state = self::SHOP_FILE_NOT_FOUND;
                        $this->state |= self::NEED_MANUAL_FIXED;
                    }
                } else {
                    $key_state = self::SHOP_FILE_NOT_FOUND;
                    $this->state |= self::NEED_MANUAL_FIXED;
                }
            }

            $aResult[ $sClassName ]['key_state'] = $key_state;

            if (!$this->checkPhpFileExists($sModuleName)) {
                $iState = self::MODULE_FILE_NOT_FOUND;
                $this->state |= self::NEED_MANUAL_FIXED;
            }

            $aResult[ $sClassName ][ 'data' ] = $sModuleName;
            $aResult[ $sClassName ][ 'state' ] = $iState;
        }

        return $aResult;
    }

Analyze extended class information in metadata and database.

@return array

Analyze extended class information in metadata and database .


public function checkTemplateBlocks()
    {
        $sModulePath = $this->getModulePath();
        $aDatabaseBlocks = $this->getModuleBlocks();
        $aDatabaseBlocks = is_array($aDatabaseBlocks) ? $aDatabaseBlocks : [];
        $aMetadataTemplates = $this->getInfo('templates');

        $config = Registry::getConfig();
        $sModulesDir = $config->getModulesDir();

        // Check if all blocks are injected.
        foreach ($aDatabaseBlocks as &$aBlock) {
            $iState = self::OK;

            $file = $aBlock['file'];
            if (!$this->checkFileExists( $sModulePath . '/' . $file) &&
                !$this->checkFileExists( $sModulePath . '/out/blocks/' . basename($file)) &&
                !$this->checkFileExists( $sModulePath . '/out/blocks/' . basename($file) . '.tpl')
            ) {
                $iState = self::MODULE_FILE_NOT_FOUND;
                $this->state |= self::NEED_MANUAL_FIXED;
            }

            $block = $aBlock['block'];
            $template = $aBlock['template'];
            $aBlock['state'] = $iState;

            // Check if template file exists and block is defined.

            // Get template from shop..
            $sTemplate = $config->getTemplatePath($template, false);

            // Get template from shop admin ..
            if (!$sTemplate) {
                $sTemplate = $config->getTemplatePath($template, true);
            }

            // Get template from module ..
            if (!$sTemplate && isset($aMetadataTemplates[$template])) {

                if ($this->checkFileExists($aMetadataTemplates[$template])) {
                    $sTemplate = $sModulesDir . '/' . $aMetadataTemplates[$template];
                }
            }

            if (empty($sTemplate)) {
                $aBlock['t_state'] = self::SHOP_FILE_NOT_FOUND;
                $this->state |= self::MAY_NEED_MANUAL_FIX;
            } else {
                $aBlock['t_state'] = self::OK;
                $aBlock['b_state'] = self::OK;
                $sContent = file_get_contents($sTemplate);
                if (!preg_match('/\[{\s*block[^}]+?name\s*=\s*["\']' . $block . '[\'"].*?}\]/', $sContent)) {
                    $aBlock['b_state'] = self::SHOP_FILE_NOT_FOUND;
                    $this->state |= self::MAY_NEED_MANUAL_FIX;
                }
            }

        }

        return $aDatabaseBlocks;
    }

Analyze template block information in metadata and database.

@return array

Analyze template block information in metadata and database .


public function checkModuleSettings()
    {
        $aDatabaseSettings = $this->getModuleSettings();
        $aDatabaseSettings = is_array($aDatabaseSettings) ? $aDatabaseSettings : [];
        $list = [];
        foreach ($aDatabaseSettings as $v) {
            $list[$v['OXVARNAME']] = $v['OXVARTYPE'];
        }

        $aResult = $this->toResult($list);
        return $aResult;
    }

public function checkModuleSettings ( ) { $ aDatabaseSettings = $ this -> getModuleSettings ( ) ; $ aDatabaseSettings = is_array ( $ aDatabaseSettings ) ? $ aDatabaseSettings : [ ] ; $ list = [ ] ; foreach ( $ aDatabaseSettings as $ v ) { $ list [ $ v [ 'OXVARNAME' ] ] = $ v [ 'OXVARTYPE' ] ; } $ aResult = $ this -> toResult ( $ list ) ; return $ aResult ; }

Analyze settings in metadata ans settings.

@return array

Analyze settings in metadata ans settings .


public function checkModuleTemplates()
    {
        $aDatabaseTemplates = $this->getModuleEntries(ModuleList::MODULE_KEY_TEMPLATES);
        $aResult = $this->checkFiles($aDatabaseTemplates, false);

        return $aResult;
    }

public function checkModuleTemplates ( ) { $ aDatabaseTemplates = $ this -> getModuleEntries ( ModuleList :: MODULE_KEY_TEMPLATES ) ; $ aResult = $ this -> checkFiles ( $ aDatabaseTemplates , false ) ; return $ aResult ; }

Analyze templates in metadata ans settings.

@return array

Analyze templates in metadata ans settings .


public function checkModuleController()
    {
        $oModuleStateFixer = Registry::get(ModuleStateFixer::class);
        $controllers =  $oModuleStateFixer->getModuleControllerEntries($this->getId());
        return $this->checkFiles($controllers, true);
    }

public function checkModuleController ( ) { $ oModuleStateFixer = Registry :: get ( ModuleStateFixer :: class ) ; $ controllers = $ oModuleStateFixer -> getModuleControllerEntries ( $ this -> getId ( ) ) ; return $ this -> checkFiles ( $ controllers , true ) ; }

Analyze controller in metadata

@return array


public function checkModuleFiles()
    {
        $aDatabaseFiles = $this->getModuleEntries(ModuleList::MODULE_KEY_FILES);
        return $this->checkFiles($aDatabaseFiles, false);
    }

public function checkModuleFiles ( ) { $ aDatabaseFiles = $ this -> getModuleEntries ( ModuleList :: MODULE_KEY_FILES ) ; return $ this -> checkFiles ( $ aDatabaseFiles , false ) ; }


public function checkModuleEvents()
    {
        $aDatabaseEvents = $this->getModuleEntries(ModuleList::MODULE_KEY_EVENTS);

        $aDatabaseEvents = is_array($aDatabaseEvents) ? $aDatabaseEvents : [];
        $aDatabaseEvents = array_map(function ($value){return print_r($value,true);}, $aDatabaseEvents);
        $aResult = $this->toResult($aDatabaseEvents);
        foreach ($aResult as $eventName => &$data){
            $data['key_state'] = ($eventName == 'onActivate' || $eventName == 'onDeactivate') ? self::OK : self::SHOP_FILE_NOT_FOUND;
        }
        return $aResult;
    }

public function checkModuleEvents ( ) { $ aDatabaseEvents = $ this -> getModuleEntries ( ModuleList :: MODULE_KEY_EVENTS ) ; $ aDatabaseEvents = is_array ( $ aDatabaseEvents ) ? $ aDatabaseEvents : [ ] ; $ aDatabaseEvents = array_map ( function ( $ value ) { return print_r ( $ value , true ) ; } , $ aDatabaseEvents ) ; $ aResult = $ this -> toResult ( $ aDatabaseEvents ) ; foreach ( $ aResult as $ eventName => & $ data ) { $ data [ 'key_state' ] = ( $ eventName == 'onActivate' || $ eventName == 'onDeactivate' ) ? self :: OK : self :: SHOP_FILE_NOT_FOUND ; } return $ aResult ; }

Analyze events in metadata ans settings.

@return array

Analyze events in metadata ans settings .


protected function _parseModuleIds()
    {
        if ($this->input->getOption('all')) {
            return $this->_getAvailableModuleIds();
        }

        if (count($this->input->getArguments()['module-id']) === 0) {
            throw oxNew(
                InputException::class,
                'Please specify at least one module if as argument or use --all (-a) option'
            );
        }

        $requestedModuleIds = $this->input->getArguments()['module-id'];
        $availableModuleIds = $this->_getAvailableModuleIds();

        // Checking if all provided module ids exist
        foreach ($requestedModuleIds as $moduleId) {
            if (!in_array($moduleId, $availableModuleIds)) {
                throw oxNew(
                    InputException::class,
                    "{$moduleId} module does not exist"
                );
            }
        }

        return $requestedModuleIds;
    }

Parse and return module ids from input

@return array

@throws InputException


protected function _parseShopConfigs()
    {
        if ($this->input->getOption('base-shop')) {
            return array(Registry::getConfig());
        }

        if ($shopId = $this->input->getOption('shop')) {
            if ($oConfig = ShopConfig::get($shopId)) {
                return array($oConfig);
            }

            throw oxNew(
                InputException::class,
                'Shop id does not exist'
            );
        }

        return ShopConfig::getAll();
    }

protected
function
_parseShopConfigs
(
)
{
if
(
$
this
->
input
->
getOption
(
'base-shop'
)
)
{
return
array
(
Registry
::
getConfig
(
)
)
;
}
if
(
$
shopId
=
$
this
->
input
->
getOption
(
'shop'
)
)
{
if
(
$
oConfig
=
ShopConfig
::
get
(
$
shopId
)
)
{
return
array
(
$
oConfig
)
;
}
throw
oxNew
(
InputException
::
class
,
'Shop id does not exist'
)
;
}
return
ShopConfig
::
getAll
(
)
;
}

Parse and return shop config objects from input

@return ShopConfig[]

@throws InputException


protected function _getAvailableModuleIds()
    {
        if ($this->_aAvailableModuleIds === null) {
            $oConfig = Registry::getConfig();

            // We are calling getModulesFromDir() because we want to refresh
            // the list of available modules. This is a workaround for OXID
            // bug.
            oxNew(ModuleList::class)->getModulesFromDir($oConfig->getModulesDir());
            $this->_aAvailableModuleIds = array_keys($oConfig->getConfigParam('aModulePaths'));
        }

        return $this->_aAvailableModuleIds;
    }

Get all available module ids

@return array


public function isEnabled()
    {
        $app = $this->getApplication();
        if (method_exists($app,'bootstrapOxid') ) {
                return $app->bootstrapOxid(true);
        }
        return true;
    }

public function isEnabled ( ) { $ app = $ this -> getApplication ( ) ; if ( method_exists ( $ app , 'bootstrapOxid' ) ) { return $ app -> bootstrapOxid ( true ) ; } return true ; }

important method for oxrun to bootstrap oxid
@return bool


public function getModule()
    {
        if ($this->_oModule === null) {
            $sModuleId = $this->getEditObjectId();

            $this->addTplParam('oxid', $sModuleId);
            $this->_oModule = oxNew(Module::class);
            $this->_oModule->load($sModuleId);
        }

        return $this->_oModule;
    }

public function getModule ( ) { if ( $ this -> _oModule === null ) { $ sModuleId = $ this -> getEditObjectId ( ) ; $ this -> addTplParam ( 'oxid' , $ sModuleId ) ; $ this -> _oModule = oxNew ( Module :: class ) ; $ this -> _oModule -> load ( $ sModuleId ) ; } return $ this -> _oModule ; }

Get active module object.

@return oxModule


public function getModuleCache()
    {
        if ($this->_oModuleCache === null) {
            $this->_oModuleCache = oxNew(ModuleCache::class, $this->getModule());
        }

        return $this->_oModuleCache;
    }

public function getModuleCache ( ) { if ( $ this -> _oModuleCache === null ) { $ this -> _oModuleCache = oxNew ( ModuleCache :: class , $ this -> getModule ( ) ) ; } return $ this -> _oModuleCache ; }

Returns initialized cache instance

@return oxModuleCache


public function getModuleInstaller()
    {
        if ($this->_oModuleInstaller === null) {
            $this->_oModuleInstaller = oxNew(ModuleInstaller::class, $this->getModuleCache());
        }

        return $this->_oModuleInstaller;
    }

public function getModuleInstaller ( ) { if ( $ this -> _oModuleInstaller === null ) { $ this -> _oModuleInstaller = oxNew ( ModuleInstaller :: class , $ this -> getModuleCache ( ) ) ; } return $ this -> _oModuleInstaller ; }

Returns initialized module installer instance

@return oxModuleInstaller


public function fix($module, $oConfig = null)
    {
        if ($oConfig !== null) {
            $this->setConfig($oConfig);
        }

        $moduleId = $module->getId();
        $this->needCacheClear = false;

        if ($this->init()) {
            $this->module = $module;
            $this->restoreModuleInformation($module, $moduleId);
        }
        $somethingWasFixed = $this->needCacheClear;
        $this->clearCache($module);
        return $somethingWasFixed;
    }

public function fix ( $ module , $ oConfig = null ) { if ( $ oConfig !== null ) { $ this -> setConfig ( $ oConfig ) ; } $ moduleId = $ module -> getId ( ) ; $ this -> needCacheClear = false ; if ( $ this -> init ( ) ) { $ this -> module = $ module ; $ this -> restoreModuleInformation ( $ module , $ moduleId ) ; } $ somethingWasFixed = $ this -> needCacheClear ; $ this -> clearCache ( $ module ) ; return $ somethingWasFixed ; }

Fix module states task runs version, extend, files, templates, blocks,
settings and events information fix tasks

@param Module      $module
@param Config|null $oConfig If not passed uses default base shop config

Fix module states task runs version extend files templates blocks settings and events information fix tasks


public function cleanUpExtensions(){

        //get all extions from all metadata
        $oxModuleList = $this->moduleList;
        $aModules = $oxModuleList->getList();

        //get extensions from metadata file
        $moduleClassesMf = [];
        foreach ($aModules as $module) {
            $extensions = $module->getExtensions();
            foreach ($extensions as $moduleClass) {
                $moduleClassesMf[$moduleClass] = 1;
            }
        }

        //get all extesions from db
        $extensionChainDb = Registry::getConfig()->getConfigParam('aModules');
        $extensionChainDb = $oxModuleList->parseModuleChains($extensionChainDb);

        //calculate trash as extensions that are only in db
        foreach ($extensionChainDb as $oxidClass => &$arrayOfExtendingClasses) {

            foreach ($arrayOfExtendingClasses as $key => $extendingClass){
                if (!isset($moduleClassesMf[$extendingClass])) {
                    $this->output->warning("module extension trash found: '$extendingClass'' (registered for $oxidClass)");
                    unset($arrayOfExtendingClasses[$key]);
                }
            }
            $arrayOfExtendingClasses = array_values($arrayOfExtendingClasses);
            if (empty($arrayOfExtendingClasses)) {
                unset($extensionChainDb[$oxidClass]);
            }
        }

        if (!$this->dryRun) {
            $extensionChainDb = $this->buildModuleChains($extensionChainDb);
            $this->_saveToConfig('aModules', $extensionChainDb);
        }

    }

remove extensions that are not registered by any module


protected function _addTemplateFiles($aModuleTemplates, $sModuleId)
    {
        $aTemplates = (array) Registry::getConfig()->getConfigParam('aModuleTemplates');
        $old = isset($aTemplates[$sModuleId]) ? $aTemplates[$sModuleId] : null;
        if (is_array($aModuleTemplates)) {
            $diff = $this->diff($old,$aModuleTemplates);
            if ($diff) {
                $what = $old === null ? ' everything ' :  var_export($diff, true);
                $this->output->warning("$sModuleId fixing templates");
                $this->output->debug(" $what");
                $aTemplates[$sModuleId] = $aModuleTemplates;
                $this->_saveToConfig('aModuleTemplates', $aTemplates);
                $this->needCacheClear = true;
            }
        } else {
            if ($old) {
                $this->output->warning("$sModuleId unregister templates:");
                $this->_deleteTemplateFiles($sModuleId);
                $this->needCacheClear = true;
            }
        }
    }

protected
function
_addTemplateFiles
(
$
aModuleTemplates
,
$
sModuleId
)
{
$
aTemplates
=
(
array
)
Registry
::
getConfig
(
)
->
getConfigParam
(
'aModuleTemplates'
)
;
$
old
=
isset
(
$
aTemplates
[
$
sModuleId
]
)
$
aTemplates
[
$
sModuleId
]
:
;
if
(
is_array
(
$
aModuleTemplates
)
)
{
$
diff
=
$
this
->
diff
(
$
old
,
$
aModuleTemplates
)
;
if
(
$
diff
)
{
$
what
=
$
old
===
' everything '
:
var_export
(
$
diff
,
true
)
;
$
this
->
output
->
warning
(
"$sModuleId fixing templates"
)
;
$
this
->
output
->
debug
(
" $what"
)
;
$
aTemplates
[
$
sModuleId
]
=
$
aModuleTemplates
;
$
this
->
_saveToConfig
(
'aModuleTemplates'
,
$
aTemplates
)
;
$
this
->
needCacheClear
=
true
;
}
}
else
{
if
(
$
old
)
{
$
this
->
output
->
warning
(
"$sModuleId unregister templates:"
)
;
$
this
->
_deleteTemplateFiles
(
$
sModuleId
)
;
$
this
->
needCacheClear
=
true
;
}
}
}

Add module template files to config for smarty.

@param array  $aModuleTemplates Module templates array
@param string $sModuleId        Module id

Add module template files to config for smarty .


protected function _addModuleFiles($aModuleFiles, $sModuleId)
    {
        $aFiles = (array) Registry::getConfig()->getConfigParam('aModuleFiles');

        $old =  isset($aFiles[$sModuleId]) ? $aFiles[$sModuleId] : null;
        if ($aModuleFiles !== null) {
            $aModuleFiles = array_change_key_case($aModuleFiles, CASE_LOWER);
        }

        if (is_array($aModuleFiles)) {
            $diff = $this->diff($old,$aModuleFiles);
            if ($diff) {
                $what = $old === null ? ' everything' : var_export($diff, true);
                $this->output->warning("$sModuleId fixing files");
                $this->output->debug(" $what");
                $aFiles[$sModuleId] = $aModuleFiles;
                $this->_saveToConfig('aModuleFiles', $aFiles);
                $this->needCacheClear = true;
            }
        } else {
            if ($old) {
                $this->output->warning("$sModuleId unregister files");
                $this->_deleteModuleFiles($sModuleId);
                $this->needCacheClear = true;
            }
        }

    }

protected
function
_addModuleFiles
(
$
aModuleFiles
,
$
sModuleId
)
{
$
aFiles
=
(
array
)
Registry
::
getConfig
(
)
->
getConfigParam
(
'aModuleFiles'
)
;
$
old
=
isset
(
$
aFiles
[
$
sModuleId
]
)
$
aFiles
[
$
sModuleId
]
:
;
if
(
$
aModuleFiles
!==
)
{
$
aModuleFiles
=
array_change_key_case
(
$
aModuleFiles
,
CASE_LOWER
)
;
}
if
(
is_array
(
$
aModuleFiles
)
)
{
$
diff
=
$
this
->
diff
(
$
old
,
$
aModuleFiles
)
;
if
(
$
diff
)
{
$
what
=
$
old
===
' everything'
:
var_export
(
$
diff
,
true
)
;
$
this
->
output
->
warning
(
"$sModuleId fixing files"
)
;
$
this
->
output
->
debug
(
" $what"
)
;
$
aFiles
[
$
sModuleId
]
=
$
aModuleFiles
;
$
this
->
_saveToConfig
(
'aModuleFiles'
,
$
aFiles
)
;
$
this
->
needCacheClear
=
true
;
}
}
else
{
if
(
$
old
)
{
$
this
->
output
->
warning
(
"$sModuleId unregister files"
)
;
$
this
->
_deleteModuleFiles
(
$
sModuleId
)
;
$
this
->
needCacheClear
=
true
;
}
}
}

Add module files to config for auto loader.

@param array  $aModuleFiles Module files array
@param string $sModuleId    Module id

Add module files to config for auto loader .


protected function _addModuleEvents($aModuleEvents, $sModuleId)
    {
        $aEvents = (array) Registry::getConfig()->getConfigParam('aModuleEvents');
        $old =  isset($aEvents[$sModuleId]) ? $aEvents[$sModuleId] : null;
        if (is_array($aModuleEvents) && count($aModuleEvents)) {
            $diff = $this->diff($old,$aModuleEvents);
            if ($diff) {
                $aEvents[$sModuleId] = $aModuleEvents;
                $what = $old == null ? ' everything ' : var_export($diff, true);
                $this->output->warning("$sModuleId fixing module events");
                $this->output->debug(" $what");
                $this->_saveToConfig('aModuleEvents', $aEvents);
                $this->needCacheClear = true;
            }
        } else {
            if ($old) {
                $this->output->info("$sModuleId unregister events");
                $this->_deleteModuleEvents($sModuleId);
                $this->needCacheClear = true;
            }
        }

    }

protected
function
_addModuleEvents
(
$
aModuleEvents
,
$
sModuleId
)
{
$
aEvents
=
(
array
)
Registry
::
getConfig
(
)
->
getConfigParam
(
'aModuleEvents'
)
;
$
old
=
isset
(
$
aEvents
[
$
sModuleId
]
)
$
aEvents
[
$
sModuleId
]
:
;
if
(
is_array
(
$
aModuleEvents
)
&&
count
(
$
aModuleEvents
)
)
{
$
diff
=
$
this
->
diff
(
$
old
,
$
aModuleEvents
)
;
if
(
$
diff
)
{
$
aEvents
[
$
sModuleId
]
=
$
aModuleEvents
;
$
what
=
$
old
==
' everything '
:
var_export
(
$
diff
,
true
)
;
$
this
->
output
->
warning
(
"$sModuleId fixing module events"
)
;
$
this
->
output
->
debug
(
" $what"
)
;
$
this
->
_saveToConfig
(
'aModuleEvents'
,
$
aEvents
)
;
$
this
->
needCacheClear
=
true
;
}
}
else
{
if
(
$
old
)
{
$
this
->
output
->
info
(
"$sModuleId unregister events"
)
;
$
this
->
_deleteModuleEvents
(
$
sModuleId
)
;
$
this
->
needCacheClear
=
true
;
}
}
}

Add module events to config.

@param array  $aModuleEvents Module events
@param string $sModuleId     Module id


protected function _addModuleExtensions($moduleExtensions, $moduleId)
    {
        $extensions = (array) Registry::getConfig()->getConfigParam('aModuleExtensions');
        $old = isset($extensions[$moduleId]) ? $extensions[$moduleId] : null;
        $old = (array) $old;
        $new = $moduleExtensions === null ? [] : array_values($moduleExtensions);
        if (is_array($moduleExtensions)) {
            $diff = $this->diff($old, $new);
            if ($diff) {
                $extensions[$moduleId] = array_values($moduleExtensions);
                $what =  $old === null ? ' everything ' : var_export($diff, true);
                $this->output->warning("$moduleId fixing module extensions");
                $this->output->debug(" $what");

                $this->_saveToConfig('aModuleExtensions', $extensions);
                $this->needCacheClear = true;
            }
        } else {
            $this->output->warning("$moduleId unregister module extensions");
            $this->needCacheClear = true;
            $this->_saveToConfig('aModuleExtensions', []);
        }
    }

Add module id with extensions to config.

@param array  $moduleExtensions Module version
@param string $moduleId         Module id

Add module id with extensions to config .


protected function _addModuleVersion($sModuleVersion, $sModuleId)
    {
        $aVersions = (array) Registry::getConfig()->getConfigParam('aModuleVersions');
        $old =  isset($aVersions[$sModuleId]) ? $aVersions[$sModuleId] : '';
        if (isset($sModuleVersion)) {
            if ($old !== $sModuleVersion) {
                $aVersions[$sModuleId] = $sModuleVersion;
                if($old == '') {
                    $this->output->info("register module '$sModuleId' with version $sModuleVersion");
                } else {
                    $this->output->warning("$sModuleId fixing module version from $old to $sModuleVersion");
                }
                $this->_saveToConfig('aModuleVersions', $aVersions);
                $this->needCacheClear = true;
            }
        } else {
            if ($old) {
                $this->output->info("$sModuleId unregister module version");
                $this->_deleteModuleVersions($sModuleId);
                $this->needCacheClear = true;
            }
        }

    }

Add module version to config.

@param string $sModuleVersion Module version
@param string $sModuleId      Module id


protected function diff($array1,$array2){
        if ($array1 === null) {
            if ($array2 === null) {
                return false; //indicate no diff
            }
            return $array2; //full array2 is new
        }
        if ($array2 === null) {
            //indicate that diff is there  (so return a true value) but everthing should be droped
            return 'null';
        }
        $diff = array_merge(array_diff_assoc($array1,$array2),array_diff_assoc($array2,$array1));
        return $diff;
    }

compares 2 assoc arrays
true if there is something changed
@param $array1
@param $array2
@return bool


protected function _addModuleSettings($moduleSettings, $moduleId)
    {
        $config = Registry::getConfig();
        $shopId = $config->getShopId();
        if (is_array($moduleSettings)) {
            $diff = false;
            foreach ($moduleSettings as $setting) {

                $module = $this->getModuleConfigId($moduleId);
                $name = $setting["name"];
                $type = $setting["type"];

                if (isset($setting["value"]) && is_null($config->getConfigParam($name))){
                    $diff = true;
                    $value = $setting["value"];
                    $config->saveShopConfVar($type, $name, $value, $shopId, $module);
                    $this->output->debug("$moduleId: setting for '$name' fixed'");
                } ;
            }
            if ($diff) {
                $this->output->warning("$moduleId: settings fixed'");
                $this->needCacheClear = true;
            }
        }
    }

protected
function
_addModuleSettings
(
$
moduleSettings
,
$
moduleId
)
{
$
config
=
Registry
::
getConfig
(
)
;
$
shopId
=
$
config
->
getShopId
(
)
;
if
(
is_array
(
$
moduleSettings
)
)
{
$
diff
=
false
;
foreach
(
$
moduleSettings
as
$
setting
)
{
$
module
=
$
this
->
getModuleConfigId
(
$
moduleId
)
;
$
name
=
$
setting
[
"name"
]
;
$
type
=
$
setting
[
"type"
]
;
if
(
isset
(
$
setting
[
"value"
]
)
&&
is_null
(
$
config
->
getConfigParam
(
$
name
)
)
)
{
$
diff
=
true
;
$
value
=
$
setting
[
"value"
]
;
$
config
->
saveShopConfVar
(
$
type
,
$
name
,
$
value
,
$
shopId
,
$
module
)
;
$
this
->
output
->
debug
(
"$moduleId: setting for '$name' fixed'"
)
;
}
;
}
if
(
$
diff
)
{
$
this
->
output
->
warning
(
"$moduleId: settings fixed'"
)
;
$
this
->
needCacheClear
=
true
;
}
}
}

Adds settings to database.

@param array  $moduleSettings Module settings array
@param string $moduleId       Module id


protected function setModuleControllers($moduleControllers, $moduleId, $module)
    {
        $controllersForThatModuleInDb = $this->getModuleControllerEntries($moduleId);
        $diff = $this->diff($controllersForThatModuleInDb, $moduleControllers);

        if ($diff) {
            $shopId = Registry::getConfig()->getShopId();
            $this->output->warning("in shop $shopId: $moduleId fixing module controllers");
            $this->output->warning(" (in md):"  . var_export($moduleControllers, true));
            $this->output->warning(" (in db):"  . var_export($controllersForThatModuleInDb, true));

            $this->deleteModuleControllers($moduleId);
            $this->resetModuleCache($module);
            if ($moduleControllers) {
                $this->validateModuleMetadataControllersOnActivation($moduleControllers);

                $classProviderStorage = $this->getClassProviderStorage();

                $classProviderStorage->add($moduleId, $moduleControllers);
            }

            $afterControllersForThatModuleInDb = $this->getModuleControllerEntries($moduleId);

            $this->needCacheClear = true;
        }

    }

Add controllers map for a given module Id to config

@param array  $moduleControllers Map of controller ids and class names
@param string $moduleId          The Id of the module


protected function _addExtensions(\OxidEsales\Eshop\Core\Module\Module $module)
    {
        $needFix = $this->checkExtensions($module, $aModulesDefault, $aModules);
        if ($needFix) {
            $this->needCacheClear = true;
            $onlyInAfterFix = array_diff($aModules, $aModulesDefault);
            $onlyInBeforeFix = array_diff($aModulesDefault, $aModules);
            $this->output->info("fixing " . $module->getId());
            foreach ($onlyInAfterFix as $core => $ext) {
                if ($oldChain = $onlyInBeforeFix[$core]) {
                    $newExt = substr($ext, strlen($oldChain));
                    if (!$newExt) {
                        //$newExt = substr($ext, strlen($oldChain));
                        $this->output->debug(" remove ext for $core");
                        $this->output->debug(" old: $oldChain");
                        $this->output->debug(" new: $ext");
                        //return;
                        continue;
                    } else {
                        $this->output->debug(" append $core => ...$newExt");
                    }
                    unset($onlyInBeforeFix[$core]);
                } else {
                    $this->output->debug(" add $core => $ext");
                }
            }
            foreach ($onlyInBeforeFix as $core => $ext) {
                $this->output->debug(" remove $core => $ext");
            }
            $this->_saveToConfig('aModules', $aModules);
        }
    }

Add extension to module

@param \OxidEsales\Eshop\Core\Module\Module $module


public function getList(){
        if ($this->list !== null){
            return $this->list;
        }
        $list = [];
        $packages = $this->getOxidModulePackages();
        //$moduleList = Registry::get(ModuleList::class);
        //$pathList = $moduleList->getModuleConfigParametersByKey(ModuleList::MODULE_KEY_PATHS);
        //$path2Id = array_flip($pathList);
        $config = Registry::getConfig();
        $paths = $config->getConfigParam('aModulePaths');
        $path2id = array_flip($paths);
        foreach ($packages as $package) {
            $extra = $package->getExtra();
            $oxideshop = isset($extra['oxideshop']) ? $extra['oxideshop'] : [];
            if (isset($oxideshop['target-directory'])) {
                $id = $path2id[$oxideshop['target-directory']];
                $list[$id] = $package;
            }
        }
        $this->list = $list;
        return $list;
    }


public function render()
    {
        //valid for all metadata versions
        $module = $this->getModule();
        $state = $module->checkState();
        foreach ($state as $paramName => $paramValue) {
            $this->addTplParam($paramName, $paramValue);
        }

        return $this->sTemplate;
    }

public
function
render
(
)
{
//valid for all metadata versions
$
module
=
$
this
->
getModule
(
)
;
$
state
=
$
module
->
checkState
(
)
;
foreach
(
$
state
as
$
paramName
=>
$
paramValue
)
{
$
this
->
addTplParam
(
$
paramName
,
$
paramValue
)
;
}
return
$
this
->
sTemplate
;
}

Collect info about module state.

@return string


public function block()
    {
        $request = Registry::getRequest();
        $data = $request->getRequestParameter('data');
        DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC)->execute(
        "UPDATE oxtplblocks SET OXACTIVE = NOT OXACTIVE WHERE OXID = ?",[$data]);
    }


public static function getHttp($options = array(), $adapters = null)
	{
		if (!\is_array($options) && !($options instanceof \ArrayAccess))
		{
			throw new \InvalidArgumentException(
				'The options param must be an array or implement the ArrayAccess interface.'
			);
		}

		if (!$driver = self::getAvailableDriver($options, $adapters))
		{
			throw new \RuntimeException('No transport driver available.');
		}

		return new Http($options, $driver);
	}

Method to create an Http instance.

@param   array|\ArrayAccess  $options   Client options array.
@param   array|string        $adapters  Adapter (string) or queue of adapters (array) to use for communication.

@return  Http

@since   1.0
@throws  \InvalidArgumentException
@throws  \RuntimeException


public static function getAvailableDriver($options = array(), $default = null)
	{
		if (!\is_array($options) && !($options instanceof \ArrayAccess))
		{
			throw new \InvalidArgumentException(
				'The options param must be an array or implement the ArrayAccess interface.'
			);
		}

		if ($default === null)
		{
			$availableAdapters = self::getHttpTransports();
		}
		else
		{
			settype($default, 'array');
			$availableAdapters = $default;
		}

		// Check if there is at least one available http transport adapter
		if (!\count($availableAdapters))
		{
			return false;
		}

		foreach ($availableAdapters as $adapter)
		{
			/** @var  $class  TransportInterface */
			$class = 'Joomla\\Http\\Transport\\' . ucfirst($adapter);

			if (class_exists($class))
			{
				if ($class::isSupported())
				{
					return new $class($options);
				}
			}
		}

		return false;
	}

Finds an available TransportInterface object for communication

@param   array|\ArrayAccess  $options  Options for creating TransportInterface object
@param   array|string        $default  Adapter (string) or queue of adapters (array) to use

@return  TransportInterface|boolean  Interface sub-class or boolean false if no adapters are available

@since   1.0
@throws  \InvalidArgumentException


public static function getHttpTransports()
	{
		$names    = array();
		$iterator = new \DirectoryIterator(__DIR__ . '/Transport');

		/** @var  $file  \DirectoryIterator */
		foreach ($iterator as $file)
		{
			$fileName = $file->getFilename();

			// Only load for php files.
			if ($file->isFile() && $file->getExtension() == 'php')
			{
				$names[] = substr($fileName, 0, strrpos($fileName, '.'));
			}
		}

		// Keep alphabetical order across all environments
		sort($names);

		// If curl is available set it to the first position
		$key = array_search('Curl', $names);

		if ($key)
		{
			unset($names[$key]);
			array_unshift($names, 'Curl');
		}

		return $names;
	}

Get the HTTP transport handlers

@return  array  An array of available transport handlers

@since   1.0


protected function setCAOptionAndValue($ch)
	{
		if (isset($this->options['curl.certpath']))
		{
			// Option is passed to a .PEM file.
			curl_setopt($ch, CURLOPT_CAINFO, $this->options['curl.certpath']);

			return;
		}

		$caPathOrFile = CaBundle::getSystemCaRootBundlePath();

		if (is_dir($caPathOrFile) || (is_link($caPathOrFile) && is_dir(readlink($caPathOrFile))))
		{
			curl_setopt($ch, CURLOPT_CAPATH, $caPathOrFile);

			return;
		}

		curl_setopt($ch, CURLOPT_CAINFO, $caPathOrFile);
	}

protected
function
setCAOptionAndValue
(
$
ch
)
{
if
(
isset
(
$
this
->
options
[
'curl.certpath'
]
)
)
{
// Option is passed to a .PEM file.
curl_setopt
(
$
ch
,
CURLOPT_CAINFO
,
$
this
->
options
[
'curl.certpath'
]
)
;
return
;
}
$
caPathOrFile
=
CaBundle
::
getSystemCaRootBundlePath
(
)
;
if
(
is_dir
(
$
caPathOrFile
)
||
(
is_link
(
$
caPathOrFile
)
&&
is_dir
(
readlink
(
$
caPathOrFile
)
)
)
)
{
curl_setopt
(
$
ch
,
CURLOPT_CAPATH
,
$
caPathOrFile
)
;
return
;
}
curl_setopt
(
$
ch
,
CURLOPT_CAINFO
,
$
caPathOrFile
)
;
}

Configure the cURL resources with the appropriate root certificates.

@param   resource  $ch  The cURL resource you want to configure the certificates on.

@return  void

@since   1.3.2

Configure the cURL resources with the appropriate root certificates .


protected function getResponse($content, $info)
	{
		// Create the response object.
		$return = new Response;

		// Try to get header size
		if (isset($info['header_size']))
		{
			$headerString = trim(substr($content, 0, $info['header_size']));
			$headerArray  = explode("\r\n\r\n", $headerString);

			// Get the last set of response headers as an array.
			$headers = explode("\r\n", array_pop($headerArray));

			// Set the body for the response.
			$return->body = substr($content, $info['header_size']);
		}
		// Fallback and try to guess header count by redirect count
		else
		{
			// Get the number of redirects that occurred.
			$redirects = isset($info['redirect_count']) ? $info['redirect_count'] : 0;

			/*
			 * Split the response into headers and body. If cURL encountered redirects, the headers for the redirected requests will
			 * also be included. So we split the response into header + body + the number of redirects and only use the last two
			 * sections which should be the last set of headers and the actual body.
			 */
			$response = explode("\r\n\r\n", $content, 2 + $redirects);

			// Set the body for the response.
			$return->body = array_pop($response);

			// Get the last set of response headers as an array.
			$headers = explode("\r\n", array_pop($response));
		}

		// Get the response code from the first offset of the response headers.
		preg_match('/[0-9]{3}/', array_shift($headers), $matches);

		$code = \count($matches) ? $matches[0] : null;

		if (is_numeric($code))
		{
			$return->code = (int) $code;
		}

		// No valid response code was detected.
		else
		{
			throw new InvalidResponseCodeException('No HTTP response code found.');
		}

		// Add the response headers to the response object.
		foreach ($headers as $header)
		{
			$pos                                             = strpos($header, ':');
			$return->headers[trim(substr($header, 0, $pos))] = trim(substr($header, ($pos + 1)));
		}

		return $return;
	}

Method to get a response object from a server response.

@param   string  $content  The complete server response, including headers
as a string if the response has no errors.
@param   array   $info     The cURL request information.

@return  Response

@since   1.0
@throws  InvalidResponseCodeException

Method to get a response object from a server response .


private function redirectsAllowed()
	{
		// There are no issues on PHP 5.6 and later
		if (version_compare(PHP_VERSION, '5.6', '>='))
		{
			return true;
		}

		// For PHP 5.3, redirects are not allowed if safe_mode and open_basedir are enabled
		if (PHP_MAJOR_VERSION === 5 && PHP_MINOR_VERSION === 3)
		{
			if (!ini_get('safe_mode') && !ini_get('open_basedir'))
			{
				return true;
			}
		}

		// For PHP 5.4 and 5.5, we only need to check if open_basedir is disabled
		return !ini_get('open_basedir');
	}

Check if redirects are allowed

@return  boolean

@since   1.2.1


public function options($url, array $headers = array(), $timeout = null)
	{
		return $this->makeTransportRequest('OPTIONS', $url, null, $headers, $timeout);
	}

public function options ( $ url , array $ headers = array ( ) , $ timeout = null ) { return $ this -> makeTransportRequest ( 'OPTIONS' , $ url , null , $ headers , $ timeout ) ; }

Method to send the OPTIONS command to the server.

@param   string|UriInterface  $url      The URI to the resource to request.
@param   array                $headers  An array of request headers to send with the request.
@param   integer              $timeout  Read timeout in seconds.

@return  Response

@since   1.0

Method to send the OPTIONS command to the server .


public function head($url, array $headers = array(), $timeout = null)
	{
		return $this->makeTransportRequest('HEAD', $url, null, $headers, $timeout);
	}

public function head ( $ url , array $ headers = array ( ) , $ timeout = null ) { return $ this -> makeTransportRequest ( 'HEAD' , $ url , null , $ headers , $ timeout ) ; }

Method to send the HEAD command to the server.

@param   string|UriInterface  $url      The URI to the resource to request.
@param   array                $headers  An array of request headers to send with the request.
@param   integer              $timeout  Read timeout in seconds.

@return  Response

@since   1.0

Method to send the HEAD command to the server .


public function trace($url, array $headers = array(), $timeout = null)
	{
		return $this->makeTransportRequest('TRACE', $url, null, $headers, $timeout);
	}

public function trace ( $ url , array $ headers = array ( ) , $ timeout = null ) { return $ this -> makeTransportRequest ( 'TRACE' , $ url , null , $ headers , $ timeout ) ; }

Method to send the TRACE command to the server.

@param   string|UriInterface  $url      The URI to the resource to request.
@param   array                $headers  An array of request headers to send with the request.
@param   integer              $timeout  Read timeout in seconds.

@return  Response

@since   1.0

Method to send the TRACE command to the server .


public function patch($url, $data, array $headers = array(), $timeout = null)
	{
		return $this->makeTransportRequest('PATCH', $url, $data, $headers, $timeout);
	}

public function patch ( $ url , $ data , array $ headers = array ( ) , $ timeout = null ) { return $ this -> makeTransportRequest ( 'PATCH' , $ url , $ data , $ headers , $ timeout ) ; }

Method to send the PATCH command to the server.

@param   string|UriInterface  $url      The URI to the resource to request.
@param   mixed                $data     Either an associative array or a string to be sent with the request.
@param   array                $headers  An array of request headers to send with the request.
@param   integer              $timeout  Read timeout in seconds.

@return  Response

@since   1.0

Method to send the PATCH command to the server .


public function match($relativePath, $globExpression)
    {
        if (!is_string($globExpression) && !is_null($globExpression)) {
            $message = "Given value \"$globExpression\" is not a valid glob expression. ".
                "Valid expression must be a string e.g. \"*.txt\".";

            throw new InvalidArgumentException($message);
        }

        if (Path::isAbsolute((string)$globExpression)) {
            $message = "Given value \"$globExpression\" is an absolute path. ".
                "Glob expression can only be accepted if it's a relative path.";

            throw new InvalidArgumentException($message);
        }

        if (is_null($globExpression)) {
            return true;
        }

        return static::isGlobMatch($relativePath, $globExpression);
    }

Returns true if given path matches a glob expression.

@param string $relativePath
@param string $globExpression Glob filter expressions, e.g. "*.txt" or "*.pdf".

@throws \InvalidArgumentException If given $globExpression is not a valid string.
@throws \InvalidArgumentException If given $globExpression is an absolute path.

@return bool

Returns true if given path matches a glob expression .


protected function getExtraParameterValueByKey($extraParameterKey, $defaultValue = null)
    {
        $extraParameters = $this->getPackage()->getExtra();

        $extraParameterValue = $extraParameters[static::EXTRA_PARAMETER_KEY_ROOT][$extraParameterKey] ?? null;

        return (!empty($extraParameterValue)) ? $extraParameterValue : $defaultValue;
    }

protected function getExtraParameterValueByKey ( $ extraParameterKey , $ defaultValue = null ) { $ extraParameters = $ this -> getPackage ( ) -> getExtra ( ) ; $ extraParameterValue = $ extraParameters [ static :: EXTRA_PARAMETER_KEY_ROOT ] [ $ extraParameterKey ] ?? null ; return ( ! empty ( $ extraParameterValue ) ) ? $ extraParameterValue : $ defaultValue ; }

Search for parameter with specific key in "extra" composer configuration block

@param string $extraParameterKey
@param string $defaultValue

@return array|string|null

Search for parameter with specific key in extra composer configuration block


protected function getCombinedFilters($listOfGlobExpressionLists)
    {
        $filters = [];
        foreach ($listOfGlobExpressionLists as $filter) {
            $filters = array_merge($filters, $filter);
        }

        return $filters;
    }

protected function getCombinedFilters ( $ listOfGlobExpressionLists ) { $ filters = [ ] ; foreach ( $ listOfGlobExpressionLists as $ filter ) { $ filters = array_merge ( $ filters , $ filter ) ; } return $ filters ; }

Combine multiple glob expression lists into one list

@param array $listOfGlobExpressionLists E.g. [["*.txt", "*.pdf"], ["*.md"]]

@return array


public function activate(Composer $composer, IOInterface $io)
    {
        $packageInstallerTrigger = new PackageInstallerTrigger($io, $composer);
        $composer->getInstallationManager()->addInstaller($packageInstallerTrigger);

        $this->composer = $composer;
        $this->io = $io;
        $this->packageInstallerTrigger = $packageInstallerTrigger;

        $extraSettings = $this->composer->getPackage()->getExtra();
        if (isset($extraSettings[AbstractPackageInstaller::EXTRA_PARAMETER_KEY_ROOT])) {
            $this->packageInstallerTrigger->setSettings($extraSettings[AbstractPackageInstaller::EXTRA_PARAMETER_KEY_ROOT]);
        }
    }

public function activate ( Composer $ composer , IOInterface $ io ) { $ packageInstallerTrigger = new PackageInstallerTrigger ( $ io , $ composer ) ; $ composer -> getInstallationManager ( ) -> addInstaller ( $ packageInstallerTrigger ) ; $ this -> composer = $ composer ; $ this -> io = $ io ; $ this -> packageInstallerTrigger = $ packageInstallerTrigger ; $ extraSettings = $ this -> composer -> getPackage ( ) -> getExtra ( ) ; if ( isset ( $ extraSettings [ AbstractPackageInstaller :: EXTRA_PARAMETER_KEY_ROOT ] ) ) { $ this -> packageInstallerTrigger -> setSettings ( $ extraSettings [ AbstractPackageInstaller :: EXTRA_PARAMETER_KEY_ROOT ] ) ; } }

Register shop packages installer.

@param Composer    $composer
@param IOInterface $io


public function matchAny($relativePath, $globExpressionList)
    {
        if (!is_array($globExpressionList) && (!$globExpressionList instanceof \Traversable)
            && (!is_null($globExpressionList))) {
            $message = "Given value \"$globExpressionList\" is not a valid glob expression list. ".
                "Valid entry must be a list of glob expressions e.g. [\"*.txt\", \"*.pdf\"].";

            throw new \InvalidArgumentException($message);
        }

        if (count($globExpressionList) > 0) {
            return $this->isMatchInList($relativePath, $globExpressionList);
        }

        return false;
    }

Returns true if given relative path matches against at least one glob expression from provided list.

@param string $relativePath
@param array  $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"].

@throws \InvalidArgumentException If $globExpressionList is not a \Traversable instance.

@return bool

Returns true if given relative path matches against at least one glob expression from provided list .


private function isMatchInList($relativePath, $globExpressionList)
    {
        foreach ($globExpressionList as $globExpression) {
            if ($this->globMatcher->match($relativePath, $globExpression)) {
                return true;
            }
        }

        return false;
    }

private function isMatchInList ( $ relativePath , $ globExpressionList ) { foreach ( $ globExpressionList as $ globExpression ) { if ( $ this -> globMatcher -> match ( $ relativePath , $ globExpression ) ) { return true ; } } return false ; }

Returns true if the supplied globMatcher indicates a match for at least one item in given glob expression list.

@param string $relativePath
@param array  $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"].

@return bool

Returns true if the supplied globMatcher indicates a match for at least one item in given glob expression list .


public function getShopSourcePath()
    {
        $shopSource = Path::join(getcwd(), ShopPackageInstaller::SHOP_SOURCE_DIRECTORY);

        if (isset($this->settings[AbstractPackageInstaller::EXTRA_PARAMETER_SOURCE_PATH])) {
            $shopSource = $this->settings[AbstractPackageInstaller::EXTRA_PARAMETER_SOURCE_PATH];
        }

        return $shopSource;
    }

public function getShopSourcePath ( ) { $ shopSource = Path :: join ( getcwd ( ) , ShopPackageInstaller :: SHOP_SOURCE_DIRECTORY ) ; if ( isset ( $ this -> settings [ AbstractPackageInstaller :: EXTRA_PARAMETER_SOURCE_PATH ] ) ) { $ shopSource = $ this -> settings [ AbstractPackageInstaller :: EXTRA_PARAMETER_SOURCE_PATH ] ; } return $ shopSource ; }

Get the path to shop's source directory.

@return string

Get the path to shop s source directory .


protected function createInstaller(PackageInterface $package)
    {
        return new $this->installers[$package->getType()]($this->io, $this->getShopSourcePath(), $package);
    }

protected function createInstaller ( PackageInterface $ package ) { return new $ this -> installers [ $ package -> getType ( ) ] ( $ this -> io , $ this -> getShopSourcePath ( ) , $ package ) ; }

Creates package installer.

@param PackageInterface $package
@return AbstractPackageInstaller


public function install($packagePath)
    {
        $this->writeInstallingMessage($this->getPackageTypeDescription());
        $this->writeCopyingMessage();
        $this->copyPackage($packagePath);
        $this->writeDoneMessage();
    }

public function install ( $ packagePath ) { $ this -> writeInstallingMessage ( $ this -> getPackageTypeDescription ( ) ) ; $ this -> writeCopyingMessage ( ) ; $ this -> copyPackage ( $ packagePath ) ; $ this -> writeDoneMessage ( ) ; }

Copies all shop files from vendors to source directory.

@param string $packagePath

Copies all shop files from vendors to source directory .


public function update($packagePath)
    {
        $this->writeUpdatingMessage($this->getPackageTypeDescription());
        $question = 'All files in the following directories will be overwritten:' . PHP_EOL .
                    '- ' . $this->getTargetDirectoryOfShopSource() . PHP_EOL .
                    'Do you want to overwrite them? (y/N) ';

        if ($this->askQuestionIfNotInstalled($question)) {
            $this->writeCopyingMessage();
            $this->copyPackage($packagePath);
            $this->writeDoneMessage();
        } else {
            $this->writeSkippedMessage();
        }
    }

Overwrites files in core directories.

@param string $packagePath


private function copyShopSourceFromPackageToTarget($packagePath)
    {
        $filtersToApply = [
            $this->getBlacklistFilterValue(),
            [self::HTACCESS_FILTER],
            [self::ROBOTS_EXCLUSION_FILTER],
            [self::SETUP_FILES_FILTER],
            $this->getVCSFilter(),
        ];

        CopyGlobFilteredFileManager::copy(
            $this->getPackageDirectoryOfShopSource($packagePath),
            $this->getTargetDirectoryOfShopSource(),
            $this->getCombinedFilters($filtersToApply)
        );
    }

private function copyShopSourceFromPackageToTarget ( $ packagePath ) { $ filtersToApply = [ $ this -> getBlacklistFilterValue ( ) , [ self :: HTACCESS_FILTER ] , [ self :: ROBOTS_EXCLUSION_FILTER ] , [ self :: SETUP_FILES_FILTER ] , $ this -> getVCSFilter ( ) , ] ; CopyGlobFilteredFileManager :: copy ( $ this -> getPackageDirectoryOfShopSource ( $ packagePath ) , $ this -> getTargetDirectoryOfShopSource ( ) , $ this -> getCombinedFilters ( $ filtersToApply ) ) ; }

Copy shop source files from package source to defined target path.

@param string $packagePath

Copy shop source files from package source to defined target path .


private function copyConfigurationDistFileWithinTarget()
    {
        $pathToConfig       = Path::join($this->getTargetDirectoryOfShopSource(), self::SHOP_SOURCE_CONFIGURATION_FILE);
        $pathToConfigDist   = $pathToConfig . self::DISTRIBUTION_FILE_EXTENSION_MARK;

        $this->copyFileIfIsMissing($pathToConfigDist, $pathToConfig);
    }

private function copyConfigurationDistFileWithinTarget ( ) { $ pathToConfig = Path :: join ( $ this -> getTargetDirectoryOfShopSource ( ) , self :: SHOP_SOURCE_CONFIGURATION_FILE ) ; $ pathToConfigDist = $ pathToConfig . self :: DISTRIBUTION_FILE_EXTENSION_MARK ; $ this -> copyFileIfIsMissing ( $ pathToConfigDist , $ pathToConfig ) ; }

Copy shop's configuration file from distribution file.

Copy shop s configuration file from distribution file .


private function copySetupFiles($packagePath)
    {
        $packageDirectoryOfShopSource = $this->getPackageDirectoryOfShopSource($packagePath);
        $installationDirectoryOfShopSource = $this->getTargetDirectoryOfShopSource();

        $shopConfigFileName = Path::join($installationDirectoryOfShopSource, self::SHOP_SOURCE_CONFIGURATION_FILE);

        if ($this->isConfigFileNotConfiguredOrMissing($shopConfigFileName)) {
            CopyGlobFilteredFileManager::copy(
                Path::join($packageDirectoryOfShopSource, self::SHOP_SOURCE_SETUP_DIRECTORY),
                Path::join($installationDirectoryOfShopSource, self::SHOP_SOURCE_SETUP_DIRECTORY)
            );
        }
    }

private function copySetupFiles ( $ packagePath ) { $ packageDirectoryOfShopSource = $ this -> getPackageDirectoryOfShopSource ( $ packagePath ) ; $ installationDirectoryOfShopSource = $ this -> getTargetDirectoryOfShopSource ( ) ; $ shopConfigFileName = Path :: join ( $ installationDirectoryOfShopSource , self :: SHOP_SOURCE_CONFIGURATION_FILE ) ; if ( $ this -> isConfigFileNotConfiguredOrMissing ( $ shopConfigFileName ) ) { CopyGlobFilteredFileManager :: copy ( Path :: join ( $ packageDirectoryOfShopSource , self :: SHOP_SOURCE_SETUP_DIRECTORY ) , Path :: join ( $ installationDirectoryOfShopSource , self :: SHOP_SOURCE_SETUP_DIRECTORY ) ) ; } }

Copy shop's setup files from package.

@param string $packagePath Absolute path which points to shop's package directory.


private function isConfigFileNotConfiguredOrMissing($shopConfigFileName)
    {
        if (!file_exists($shopConfigFileName)) {
            return true;
        }

        $shopConfigFileContents = file_get_contents($shopConfigFileName);
        $wordsIndicatingNotConfigured = [
            '<dbHost>',
            '<dbName>',
            '<dbUser>',
            '<dbPwd>',
            '<sShopURL>',
            '<sShopDir>',
            '<sCompileDir>',
        ];

        foreach ($wordsIndicatingNotConfigured as $word) {
            if (strpos($shopConfigFileContents, $word) !== false) {
                return true;
            }
        }

        return false;
    }

private function isConfigFileNotConfiguredOrMissing ( $ shopConfigFileName ) { if ( ! file_exists ( $ shopConfigFileName ) ) { return true ; } $ shopConfigFileContents = file_get_contents ( $ shopConfigFileName ) ; $ wordsIndicatingNotConfigured = [ '<dbHost>' , '<dbName>' , '<dbUser>' , '<dbPwd>' , '<sShopURL>' , '<sShopDir>' , '<sCompileDir>' , ] ; foreach ( $ wordsIndicatingNotConfigured as $ word ) { if ( strpos ( $ shopConfigFileContents , $ word ) !== false ) { return true ; } } return false ; }

Return true if config file is not configured or missing.

@param string $shopConfigFileName Absolute path to shop configuration file to check.

@return bool

Return true if config file is not configured or missing .


private function copyFilesFromSourceToInstallationByFilter($packagePath, $filter)
    {
        $sourceDirectory    = $this->getPackageDirectoryOfShopSource($packagePath);
        $filteredFiles      = $this->getFilteredFiles($sourceDirectory, $filter);

        foreach ($filteredFiles as $packageFilePath) {
            $installationFilePath = $this->getAbsoluteFilePathFromInstallation(
                $sourceDirectory,
                $packageFilePath
            );

            $this->copyFileIfIsMissing($packageFilePath, $installationFilePath);
        }
    }

Copy files from source to installation by filter.

@param string $packagePath
@param string $filter

Copy files from source to installation by filter .


private function getFilteredFiles($directory, $filter)
    {
        $glob = Path::join($directory, $filter);

        return new GlobIterator($glob);
    }

private function getFilteredFiles ( $ directory , $ filter ) { $ glob = Path :: join ( $ directory , $ filter ) ; return new GlobIterator ( $ glob ) ; }

Return filtered files.

@param   string $directory
@param   string $filter

@return  GlobIterator


private function getAbsoluteFilePathFromInstallation(
        $sourcePackageDirectory,
        $absolutePathToFileFromPackage
    ) {
        $installationDirectoryOfShopSource = $this->getTargetDirectoryOfShopSource();

        $relativePathOfSourceFromPackage = Path::makeRelative(
            $absolutePathToFileFromPackage,
            $sourcePackageDirectory
        );

        $absolutePathToFileFromInstallation = Path::join(
            $installationDirectoryOfShopSource,
            $relativePathOfSourceFromPackage
        );

        return $absolutePathToFileFromInstallation;
    }

private function getAbsoluteFilePathFromInstallation ( $ sourcePackageDirectory , $ absolutePathToFileFromPackage ) { $ installationDirectoryOfShopSource = $ this -> getTargetDirectoryOfShopSource ( ) ; $ relativePathOfSourceFromPackage = Path :: makeRelative ( $ absolutePathToFileFromPackage , $ sourcePackageDirectory ) ; $ absolutePathToFileFromInstallation = Path :: join ( $ installationDirectoryOfShopSource , $ relativePathOfSourceFromPackage ) ; return $ absolutePathToFileFromInstallation ; }

Return absolute path to file from installation.

@param   string  $sourcePackageDirectory
@param   string  $absolutePathToFileFromPackage

@return  string

Return absolute path to file from installation .


public function update($packagePath)
    {
        $this->writeUpdatingMessage($this->getPackageTypeDescription());
        $question = 'All files in the following directories will be overwritten:' . PHP_EOL .
                    '- ' . $this->formThemeTargetPath() . PHP_EOL .
                    '- ' . Path::join($this->getRootDirectory(), $this->formAssetsDirectoryName()) . PHP_EOL .
                    'Do you want to overwrite them? (y/N) ';

        if ($this->askQuestionIfNotInstalled($question)) {
            $this->writeCopyingMessage();
            $this->copyPackage($packagePath);
            $this->writeDoneMessage();
        } else {
            $this->writeSkippedMessage();
        }
    }

Overwrites theme files.

@param string $packagePath


protected function copyPackage($packagePath)
    {
        $filtersToApply = [
            $this->getBlacklistFilterValue(),
            $this->getVCSFilter(),
        ];

        CopyGlobFilteredFileManager::copy(
            $this->formSourcePath($packagePath),
            $this->formTargetPath(),
            $this->getCombinedFilters($filtersToApply)
        );
    }

protected function copyPackage ( $ packagePath ) { $ filtersToApply = [ $ this -> getBlacklistFilterValue ( ) , $ this -> getVCSFilter ( ) , ] ; CopyGlobFilteredFileManager :: copy ( $ this -> formSourcePath ( $ packagePath ) , $ this -> formTargetPath ( ) , $ this -> getCombinedFilters ( $ filtersToApply ) ) ; }

Copy files from package source to defined target path.

@param string $packagePath Absolute path to the package.

Copy files from package source to defined target path .


protected function formSourcePath($packagePath)
    {
        $sourceDirectory = $this->getExtraParameterValueByKey(static::EXTRA_PARAMETER_KEY_SOURCE);

        return !empty($sourceDirectory)?
            Path::join($packagePath, $sourceDirectory):
            $packagePath;
    }

protected function formSourcePath ( $ packagePath ) { $ sourceDirectory = $ this -> getExtraParameterValueByKey ( static :: EXTRA_PARAMETER_KEY_SOURCE ) ; return ! empty ( $ sourceDirectory ) ? Path :: join ( $ packagePath , $ sourceDirectory ) : $ packagePath ; }

If module source directory option provided add it's relative path.
Otherwise return plain package path.

@param string $packagePath

@return string

If module source directory option provided add it s relative path . Otherwise return plain package path .


public static function nest($flatFileSystemStructure = null)
    {
        if (null !== $flatFileSystemStructure && false === is_array($flatFileSystemStructure)) {
            throw new \InvalidArgumentException("Given input argument must be an array.");
        }

        if (null === $flatFileSystemStructure) {
            return [];
        }

        $nestedFileSystemStructure = [];

        foreach ($flatFileSystemStructure as $pathEntry => $contents) {
            $pathEntries = explode(DIRECTORY_SEPARATOR, $pathEntry);

            $pointerToBranch = &$nestedFileSystemStructure;
            foreach ($pathEntries as $singlePathEntry) {
                $singlePathEntry = trim($singlePathEntry);

                if ($singlePathEntry !== '') {
                    if (!is_array($pointerToBranch)) {
                        $pointerToBranch = [];
                    }

                    if (!key_exists($singlePathEntry, $pointerToBranch)) {
                        $pointerToBranch[$singlePathEntry] = [];
                    }

                    $pointerToBranch = &$pointerToBranch[$singlePathEntry];
                }
            }

            if (substr($pathEntry, -1) !== DIRECTORY_SEPARATOR) {
                $pointerToBranch = $contents;
            }
        }

        return $nestedFileSystemStructure;
    }

Convert given flat file system structure into nested one.

@param array|null $flatFileSystemStructure

@return array

Convert given flat file system structure into nested one .


private static function getFlatFileListIterator($sourcePath)
    {
        $recursiveFileIterator = new \RecursiveDirectoryIterator($sourcePath, \FilesystemIterator::SKIP_DOTS);
        $flatFileListIterator = new \RecursiveIteratorIterator($recursiveFileIterator);

        return $flatFileListIterator;
    }

private static function getFlatFileListIterator ( $ sourcePath ) { $ recursiveFileIterator = new \ RecursiveDirectoryIterator ( $ sourcePath , \ FilesystemIterator :: SKIP_DOTS ) ; $ flatFileListIterator = new \ RecursiveIteratorIterator ( $ recursiveFileIterator ) ; return $ flatFileListIterator ; }

Return an iterator which iterates through a given directory tree in a one-dimensional fashion.

Consider the following file/directory structure as an example:

* directory_a
* file_a_a
* directory_b
* file_b_a
* file_b_b
* file_c

RecursiveDirectoryIterator would iterate through:
* directory_a [iterator]
* directory_b [iterator]
* file_c [SplFileInfo]

In contrast current method would iterate through:
* directory_a [SplFileInfo]
* directory_a/file_a_a [SplFileInfo]
* directory_b [SplFileInfo]
* directory_b/file_b_a [SplFileInfo]
* directory_b/file_b_b [SplFileInfo]
* file_c [SplFileInfo]

@param string $sourcePath Absolute path to directory.

@return \Iterator

Return an iterator which iterates through a given directory tree in a one - dimensional fashion .


private static function copyDirectory($sourcePath, $destinationPath, $globExpressionList)
    {
        $filesystem = new Filesystem();

        $flatFileListIterator = self::getFlatFileListIterator($sourcePath);
        $filteredFileListIterator = new BlacklistFilterIterator(
            $flatFileListIterator,
            $sourcePath,
            $globExpressionList
        );

        $filesystem->mirror($sourcePath, $destinationPath, $filteredFileListIterator, ["override" => true]);
    }

private static function copyDirectory ( $ sourcePath , $ destinationPath , $ globExpressionList ) { $ filesystem = new Filesystem ( ) ; $ flatFileListIterator = self :: getFlatFileListIterator ( $ sourcePath ) ; $ filteredFileListIterator = new BlacklistFilterIterator ( $ flatFileListIterator , $ sourcePath , $ globExpressionList ) ; $ filesystem -> mirror ( $ sourcePath , $ destinationPath , $ filteredFileListIterator , [ "override" => true ] ) ; }

Copy whole directory using given glob filters.

@param string $sourcePath         Absolute path to directory.
@param string $destinationPath    Absolute path to directory.
@param array  $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"].

Copy whole directory using given glob filters .


private static function copyFile($sourcePathOfFile, $destinationPath, $globExpressionList)
    {
        $filesystem = new Filesystem();

        $relativeSourcePath = self::getRelativePathForSingleFile($sourcePathOfFile);

        if (!GlobMatcher::matchAny($relativeSourcePath, $globExpressionList)) {
            $filesystem->copy($sourcePathOfFile, $destinationPath, ["override" => true]);
        }
    }

private static function copyFile ( $ sourcePathOfFile , $ destinationPath , $ globExpressionList ) { $ filesystem = new Filesystem ( ) ; $ relativeSourcePath = self :: getRelativePathForSingleFile ( $ sourcePathOfFile ) ; if ( ! GlobMatcher :: matchAny ( $ relativeSourcePath , $ globExpressionList ) ) { $ filesystem -> copy ( $ sourcePathOfFile , $ destinationPath , [ "override" => true ] ) ; } }

Copy file using given glob filters.

@param string $sourcePathOfFile   Absolute path to file.
@param string $destinationPath    Absolute path to directory.
@param array  $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"].


public static function generateModels(array $config)
    {
        $schemas = ArrayHelper::getValue($config, 'schemas', []);
        $namespace = ArrayHelper::getValue($config, 'namespace', 'simialbi\yii2\schemaorg\models');
        $folder = ArrayHelper::getValue($config, 'folder', sprintf(
            '%1$s%2$ssimialbi%2$syii2-schema-org%2$ssrc%2$smodels',
            $config['vendorPath'],
            DIRECTORY_SEPARATOR
        ));
        $removeOld = ArrayHelper::getValue($config, 'removeOld', true);

        require_once $config['vendorPath'] . DIRECTORY_SEPARATOR . 'autoload.php';
        require_once $config['vendorPath'] . DIRECTORY_SEPARATOR . 'yiisoft' . DIRECTORY_SEPARATOR . 'yii2' . DIRECTORY_SEPARATOR . 'Yii.php';

        Yii::setAlias('@runtime', rtrim(str_replace(['\\', '/'], '/', sys_get_temp_dir()), '/'));

        new \yii\console\Application([
            'id' => 'Commmand runner',
            'basePath' => __DIR__,
            'vendorPath' => $config['vendorPath'],
            'bootstrap' => ['schema'],
            'aliases' => [],
            'modules' => [
                'schema' => [
                    'class' => 'simialbi\yii2\schemaorg\Module'
                ]
            ]
        ]);
        $options = [
            'namespace' => $namespace,
            'folder' => $folder,
            'removeOld' => $removeOld
        ];
        if (!empty($schemas)) {
            $options['schemas'] = implode(',', $schemas);
        }
        Yii::$app->runAction('schema/models/generate', $options);

        Yii::$app = null;
        unset($app);
    }

Run model generation action

@param array $config Configuration for model generation

@throws \yii\base\InvalidConfigException
@throws \yii\console\Exception
@throws \yii\base\InvalidRouteException


private function traverseClasses(array &$classes, $allClasses = null)
    {
        if ($allClasses === null) {
            $allClasses = $classes;
        }

        foreach ($classes as &$class) {
            $parentClasses = ArrayHelper::remove($class, 'rdfs:subClassOf', []);
            if (ArrayHelper::isAssociative($parentClasses)) {
                $parentClasses = [$parentClasses];
            }

            foreach ($parentClasses as $k => $parentClass) {
                $parentClasses[$k] = ArrayHelper::getValue($allClasses, $parentClass['@id']);
                if ($parentClass === null) {
                    continue;
                }
            }

            $this->traverseClasses($parentClasses, $allClasses);

            foreach ($parentClasses as $parentClass) {
                ArrayHelper::setValue($class, 'properties', ArrayHelper::merge(
                    ArrayHelper::getValue($class, 'properties', []),
                    ArrayHelper::getValue($parentClass, 'properties', [])
                ));
            }
        }
    }

private function traverseClasses ( array & $ classes , $ allClasses = null ) { if ( $ allClasses === null ) { $ allClasses = $ classes ; } foreach ( $ classes as & $ class ) { $ parentClasses = ArrayHelper :: remove ( $ class , 'rdfs:subClassOf' , [ ] ) ; if ( ArrayHelper :: isAssociative ( $ parentClasses ) ) { $ parentClasses = [ $ parentClasses ] ; } foreach ( $ parentClasses as $ k => $ parentClass ) { $ parentClasses [ $ k ] = ArrayHelper :: getValue ( $ allClasses , $ parentClass [ '@id' ] ) ; if ( $ parentClass === null ) { continue ; } } $ this -> traverseClasses ( $ parentClasses , $ allClasses ) ; foreach ( $ parentClasses as $ parentClass ) { ArrayHelper :: setValue ( $ class , 'properties' , ArrayHelper :: merge ( ArrayHelper :: getValue ( $ class , 'properties' , [ ] ) , ArrayHelper :: getValue ( $ parentClass , 'properties' , [ ] ) ) ) ; } } }

Traverse all classes and inherit properties from parents

@param array $classes
@param array $allClasses


public function toJsonLDArray($fields = [], $expand = [], $recursive = true)
    {
        return array_merge([
            '@context' => 'http://schema.org'
        ], $this->toArray($fields, $expand, $recursive));
    }

public function toJsonLDArray ( $ fields = [ ] , $ expand = [ ] , $ recursive = true ) { return array_merge ( [ '@context' => 'http://schema.org' ] , $ this -> toArray ( $ fields , $ expand , $ recursive ) ) ; }

Converts the model into an array for usage in ld+json.

This method will first identify which fields to be included in the resulting array by calling [[resolveFields()]].
It will then turn the model into an array with these fields. If `$recursive` is true,
any embedded objects will also be converted into arrays.

If the model implements the [[Linkable]] interface, the resulting array will also have a `_link` element
which refers to a list of links as specified by the interface.

@param array $fields the fields being requested. If empty, all fields as specified by [[fields()]] will be returned.
@param array $expand the additional fields being requested for exporting. Only fields declared in [[extraFields()]]
will be considered.
@param bool $recursive whether to recursively return array representation of embedded objects.

@return array the array representation of the object

Converts the model into an array for usage in ld + json .


public static function addBreadCrumbList()
    {
        if (!class_exists('\simialbi\yii2\schemaorg\models\BreadcrumbList')) {
            return;
        }

        $view = Yii::$app->view;

        /* @var $breadcrumbList \simialbi\yii2\schemaorg\models\Model */
        $breadcrumbs = ArrayHelper::getValue($view->params, 'breadcrumbs', []);
        $breadcrumbList = Yii::createObject([
            'class' => 'simialbi\yii2\schemaorg\models\BreadcrumbList'
        ]);
        if (!empty($breadcrumbs)) {
            $position = 1;
            foreach ($breadcrumbs as $breadcrumb) {
                $listItem = Yii::createObject([
                    'class' => 'simialbi\yii2\schemaorg\models\ListItem',
                    'position' => $position++
                ]);
                if (is_array($breadcrumb)) {
                    $listItem->item = [
                        '@id' => Url::to(ArrayHelper::getValue($breadcrumb, 'url', ''), true),
                        'name' => ArrayHelper::getValue($breadcrumb, 'label', '')
                    ];
                } else {
                    $listItem->item = [
                        '@id' => Yii::$app->request->absoluteUrl,
                        'name' => $breadcrumb
                    ];
                }
                $breadcrumbList->itemListElement[] = $listItem;
            }
        }

        self::add($breadcrumbList);
    }

Adds BreadcrumbList schema.org markup based on the application view `breadcrumbs` parameter
@throws \yii\base\InvalidConfigException

Adds BreadcrumbList schema . org markup based on the application view breadcrumbs parameter


public static function render()
    {
        if (!empty(self::$_models)) {
            foreach (self::$_models as $model) {
                try {
                    echo Html::script(Json::encode($model->toJsonLDArray()), ['type' => 'application/ld+json']) . "\n";
                } catch (InvalidArgumentException $e) {
                    $logger = Yii::$app->log->logger;
                    $logger->log($e->getMessage(), $logger::LEVEL_ERROR);
                }
            }
        }
    }

public static function render ( ) { if ( ! empty ( self :: $ _models ) ) { foreach ( self :: $ _models as $ model ) { try { echo Html :: script ( Json :: encode ( $ model -> toJsonLDArray ( ) ) , [ 'type' => 'application/ld+json' ] ) . "\n" ; } catch ( InvalidArgumentException $ e ) { $ logger = Yii :: $ app -> log -> logger ; $ logger -> log ( $ e -> getMessage ( ) , $ logger :: LEVEL_ERROR ) ; } } } }


public function setHTMLByView($view, array $parameters = array())
    {
        if (!$this->container) {
            throw new MissingTemplatingEngineException("To use this function, a Container object must be passed to the constructor (@service_container service)");
        }
        /** @var EngineInterface $engine */
        $engine = $this->container->get('templating');
        $this->setHTML($engine->render($view, $parameters));
    }

Set the string which represents the HTML file to be sent as email by rendering a template.

@param string $view is the view to be rendered, e.g. Acme:MyBundle:MyController:index.html.twig
@param array[optional] $parameters the array of options to be used for template rendering. This field is optional
@throws MissingTemplatingEngineException The TwigEngine must be passed to the constructor, otherwise an exception is thrown

Set the string which represents the HTML file to be sent as email by rendering a template .


public function generateStyledHTML()
    {
        if (is_null($this->html)) {
            throw new MissingParamException("The HTML must be set");
        }

        if (!is_string($this->html)) {
            throw new MissingParamException("The HTML must be a valid string");
        }

        if (is_null($this->css)) {
            throw new MissingParamException("The CSS must be set");
        }

        if (!is_string($this->css)) {
            throw new MissingParamException("The CSS must be a valid string");
        }

        return  $this->cssToInlineStyles->convert($this->html, $this->css);
    }

public
function
generateStyledHTML
(
)
{
if
(
is_null
(
$
this
->
html
)
)
{
throw
new
MissingParamException
(
"The HTML must be set"
)
;
}
if
(
!
is_string
(
$
this
->
html
)
)
{
throw
new
MissingParamException
(
"The HTML must be a valid string"
)
;
}
if
(
is_null
(
$
this
->
css
)
)
{
throw
new
MissingParamException
(
"The CSS must be set"
)
;
}
if
(
!
is_string
(
$
this
->
css
)
)
{
throw
new
MissingParamException
(
"The CSS must be a valid string"
)
;
}
return
$
this
->
cssToInlineStyles
->
convert
(
$
this
->
html
,
$
this
->
css
)
;
}

Generate the HTML ready to be sent as email.

@return string the HTML ready to be sent with an inline-style
@throws MissingParamException the HTML and CSS are mandatory.

Generate the HTML ready to be sent as email .


private function resolvePath($path)
    {
        try {
            return $this->locator->locate($path, $this->webRoot);
        } catch (\InvalidArgumentException $e) {
            // happens when path is not bundle relative
            return $this->webRoot . '/' . $path;
        }
    }

Resolve path to absolute if any bundle is mentioned
@param string $path
@return string


protected function expected(array $actual): bool
    {
        return collect($this->expected)->contains(function ($expected) use ($actual) {
            return $this->compare($expected, $actual);
        });
    }

protected function expected ( array $ actual ) : bool { return collect ( $ this -> expected ) -> contains ( function ( $ expected ) use ( $ actual ) { return $ this -> compare ( $ expected , $ actual ) ; } ) ; }

Is the actual subset expected?

@param array $actual
@return bool


protected function exists(array $expected, $actual): bool
    {
        if (!is_array($actual)) {
            return false;
        }

        return collect($actual)->contains(function ($item) use ($expected) {
            return $this->compare($expected, $item);
        });
    }

protected function exists ( array $ expected , $ actual ) : bool { if ( ! is_array ( $ actual ) ) { return false ; } return collect ( $ actual ) -> contains ( function ( $ item ) use ( $ expected ) { return $ this -> compare ( $ expected , $ item ) ; } ) ; }

Does the expected subset exist in the actual array?

@param array $expected
@param mixed $actual
@return bool


public static function assertStatusCode(
        $status,
        int $expected,
        $content = null,
        string $message = ''
    ): void
    {
        PHPUnitAssert::assertThat(
            $status,
            new HttpStatusIs($expected, $content),
            $message
        );
    }

public static function assertStatusCode ( $ status , int $ expected , $ content = null , string $ message = '' ) : void { PHPUnitAssert :: assertThat ( $ status , new HttpStatusIs ( $ expected , $ content ) , $ message ) ; }

Assert that the HTTP status matches the expected status.

This assertion will print any JSON API errors in the supplied content if
the HTTP status does not match. This is useful for understanding why the status
is not the expected status when an error has occurred.

@param $status
@param int $expected
@param mixed|null $content
@param string $message
@return void

Assert that the HTTP status matches the expected status .


public static function assertContent(
        $type,
        $content,
        $expected = self::JSON_API_MEDIA_TYPE,
        string $message = ''
    ): Document
    {
        PHPUnitAssert::assertSame($type, $expected, $message ?: "Expecting content with media type {$expected}.");
        PHPUnitAssert::assertNotEmpty($content, $message ?: 'Expecting HTTP body to have content.');

        return Document::cast($content);
    }

Assert that there is content with the expected media type.

@param $type
@param $content
@param string $expected
@param string $message
@return Document

Assert that there is content with the expected media type .


public static function assertJson(
        $status,
        $contentType,
        $content,
        int $expected = self::STATUS_OK,
        string $message = ''
    ): Document
    {
        self::assertStatusCode($status, $expected, $content, $message);

        return self::assertContent($contentType, $content, self::JSON_MEDIA_TYPE, $message);
    }

public static function assertJson ( $ status , $ contentType , $ content , int $ expected = self :: STATUS_OK , string $ message = '' ) : Document { self :: assertStatusCode ( $ status , $ expected , $ content , $ message ) ; return self :: assertContent ( $ contentType , $ content , self :: JSON_MEDIA_TYPE , $ message ) ; }

Assert a JSON HTTP message with an expected status.

@param $status
@param $contentType
@param $content
@param int $expected
the expected HTTP status.
@param string $message
@return Document

Assert a JSON HTTP message with an expected status .


public static function assertJsonApi(
        $status,
        $contentType,
        $content,
        int $expected = self::STATUS_OK,
        string $message = ''
    ): Document
    {
        self::assertStatusCode($status, $expected, $content, $message);

        return self::assertContent($contentType, $content, self::JSON_API_MEDIA_TYPE, $message);
    }

public static function assertJsonApi ( $ status , $ contentType , $ content , int $ expected = self :: STATUS_OK , string $ message = '' ) : Document { self :: assertStatusCode ( $ status , $ expected , $ content , $ message ) ; return self :: assertContent ( $ contentType , $ content , self :: JSON_API_MEDIA_TYPE , $ message ) ; }

Assert a JSON API HTTP message with an expected status.

@param $status
@param $contentType
@param $content
@param int $expected
the expected HTTP status.
@param string $message
@return Document

Assert a JSON API HTTP message with an expected status .


public static function assertFetchedOne(
        $status,
        $contentType,
        $content,
        array $expected,
        bool $strict = true,
        string $message = ''
    ): Document
    {
        return self::assertJsonApi($status, $contentType, $content, self::STATUS_OK, $message)
            ->assertHash($expected, '/data', $strict, $message);
    }

public static function assertFetchedOne ( $ status , $ contentType , $ content , array $ expected , bool $ strict = true , string $ message = '' ) : Document { return self :: assertJsonApi ( $ status , $ contentType , $ content , self :: STATUS_OK , $ message ) -> assertHash ( $ expected , '/data' , $ strict , $ message ) ; }

Assert that a resource was fetched.

@param $status
@param $contentType
@param $content
@param array $expected
the expected resource, or a subset of the expected resource.
@param bool $strict
@param string $message
@return Document


public static function assertFetchedExact(
        $status,
        $contentType,
        $content,
        array $expected,
        bool $strict = true,
        string $message = ''
    ): Document
    {
        return self::assertJsonApi($status, $contentType, $content, self::STATUS_OK, $message)
            ->assertExact($expected, '/data', $strict, $message);
    }

public static function assertFetchedExact ( $ status , $ contentType , $ content , array $ expected , bool $ strict = true , string $ message = '' ) : Document { return self :: assertJsonApi ( $ status , $ contentType , $ content , self :: STATUS_OK , $ message ) -> assertExact ( $ expected , '/data' , $ strict , $ message ) ; }

Assert that an exact resource or resource collection was fetched.

@param $status
@param $contentType
@param $content
@param array $expected
the expected content of the document's data member.
@param bool $strict
@param string $message
@return Document

Assert that an exact resource or resource collection was fetched .


public static function assertFetchedManyInOrder(
        $status,
        $contentType,
        $content,
        array $expected,
        bool $strict = true,
        string $message = ''
    ): Document
    {
        if (empty($expected)) {
            return self::assertFetchedNone($strict, $contentType, $content, $message);
        }

        return self::assertJsonApi($status, $contentType, $content, self::STATUS_OK, $message)
            ->assertListInOrder($expected, '/data', $strict, $message);
    }

public static function assertFetchedManyInOrder ( $ status , $ contentType , $ content , array $ expected , bool $ strict = true , string $ message = '' ) : Document { if ( empty ( $ expected ) ) { return self :: assertFetchedNone ( $ strict , $ contentType , $ content , $ message ) ; } return self :: assertJsonApi ( $ status , $ contentType , $ content , self :: STATUS_OK , $ message ) -> assertListInOrder ( $ expected , '/data' , $ strict , $ message ) ; }

Assert that a resource collection was fetched in the expected order.

@param $status
@param $contentType
@param $content
@param array $expected
@param bool $strict
@param string $message
@return Document

Assert that a resource collection was fetched in the expected order .


public static function assertFetchedToMany(
        $status,
        $contentType,
        $content,
        array $expected,
        bool $strict = true,
        string $message = ''
    ): Document
    {
        if (empty($expected)) {
            return self::assertFetchedNone($strict, $contentType, $content, $message);
        }

        return self::assertJsonApi($status, $contentType, $content, self::STATUS_OK, $message)
            ->assertIdentifiersList($expected, '/data', $strict, $message);
    }

public static function assertFetchedToMany ( $ status , $ contentType , $ content , array $ expected , bool $ strict = true , string $ message = '' ) : Document { if ( empty ( $ expected ) ) { return self :: assertFetchedNone ( $ strict , $ contentType , $ content , $ message ) ; } return self :: assertJsonApi ( $ status , $ contentType , $ content , self :: STATUS_OK , $ message ) -> assertIdentifiersList ( $ expected , '/data' , $ strict , $ message ) ; }

Assert that a to-many relationship was fetched.

@param $status
@param $contentType
@param $content
@param array $expected
@param bool $strict
@param string $message
@return Document

Assert that a to - many relationship was fetched .


public static function assertFetchedToManyInOrder(
        $status,
        $contentType,
        $content,
        array $expected,
        bool $strict = true,
        string $message = ''
    ): Document
    {
        if (empty($expected)) {
            return self::assertFetchedNone($strict, $contentType, $content, $message);
        }

        return self::assertJsonApi($status, $contentType, $content, self::STATUS_OK, $message)
            ->assertIdentifiersListInOrder($expected, '/data', $strict, $message);
    }

public static function assertFetchedToManyInOrder ( $ status , $ contentType , $ content , array $ expected , bool $ strict = true , string $ message = '' ) : Document { if ( empty ( $ expected ) ) { return self :: assertFetchedNone ( $ strict , $ contentType , $ content , $ message ) ; } return self :: assertJsonApi ( $ status , $ contentType , $ content , self :: STATUS_OK , $ message ) -> assertIdentifiersListInOrder ( $ expected , '/data' , $ strict , $ message ) ; }

Assert that a to-many relationship was fetched in the expected order.

@param $status
@param $contentType
@param $content
@param array $expected
@param bool $strict
@param string $message
@return Document

Assert that a to - many relationship was fetched in the expected order .


public static function assertCreatedWithClientId(
        $status,
        $contentType,
        $content,
        $location,
        string $expectedLocation,
        array $expected,
        bool $strict = true,
        string $message = ''
    ): Document
    {
        $expectedId = $expected['id'] ?? null;

        if (!$expectedId) {
            throw new \InvalidArgumentException('Expected resource hash must have an id.');
        }

        self::assertStatusCode($status, self::STATUS_CREATED, $content, $message);
        PHPUnitAssert::assertSame(
            "$expectedLocation/{$expectedId}",
            $location,
            $message ?: 'Unexpected Location header.'
        );

        return self::assertContent($contentType, $content, self::JSON_API_MEDIA_TYPE, $message)
            ->assertHash($expected, '/data', $strict, $message);
    }

Assert that a resource was created with a client generated id.

@param $status
@param $contentType
@param $content
@param $location
@param string $expectedLocation
@param array $expected
@param bool $strict
@param string $message
@return Document

Assert that a resource was created with a client generated id .


public static function assertNoContent($status, string $content = null, string $message = ''): void
    {
        self::assertStatusCode($status, self::STATUS_NO_CONTENT, $content, $message);
        PHPUnitAssert::assertEmpty($content, $message ?: 'Expecting HTTP body content to be empty.');
    }

Assert a no content response.

@param $status
@param string|null
@param string $message
@return void