Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/AddOn/DataManager.php
<?php

namespace XF\AddOn;

use
XF\AddOn\DataType\AbstractDataType;

class
DataManager
{
   
/**
     * @var \XF\Mvc\Entity\Manager
     */
   
protected $em;

   
/**
     * @var DataType\AbstractDataType[]|null
     */
   
protected $types;

    public function
__construct(\XF\Mvc\Entity\Manager $em)
    {
       
$this->em = $em;
    }

    public function
exportAddOn(AddOn $addOn, array &$containers = [], array &$emptyContainers = [])
    {
       
$document = new \DOMDocument('1.0', 'utf-8');
       
$document->formatOutput = true;

       
$root = $document->createElement('addon');
       
$document->appendChild($root);

       
$addOnId = $addOn->addon_id;

        foreach (
$this->getDataTypeHandlers() AS $handler)
        {
           
$containerName = $handler->getContainerTag();
           
$container = $document->createElement($containerName);
           
$handler->exportAddOnData($addOnId, $container);
           
$root->appendChild($container);
           
$containers[] = $containerName;
        }

        return
$document;
    }

    public function
enqueueImportAddOnData(AddOn $addOn)
    {
        return \
XF::app()->jobManager()->enqueueUnique($this->getImportDataJobId($addOn), 'XF:AddOnData', [
           
'addon_id' => $addOn->addon_id
       
]);
    }

    public function
getImportDataJobId(AddOn $addOn)
    {
        return
'addOnData-' . $addOn->addon_id;
    }

    protected function
checkComposerAutoloadPath(string $file, string $path, bool $allowThrow = true): bool
   
{
       
$path = rtrim($path, \XF::$DS) . \XF::$DS;

        if (!
file_exists($path . $file))
        {
            if (
$allowThrow)
            {
                if (\
XF::$debugMode)
                {
                    throw new \
InvalidArgumentException(
                       
"Missing $file at " . \XF\Util\File::stripRootPathPrefix($path) . ". This may not be a valid composer directory."
                   
);
                }
                else
                {
                    \
XF::logError(
                       
'Error registering composer autoload directory: ' . \XF\Util\File::stripRootPathPrefix($path . $file)
                    );
                }
            }
            return
false;
        }

        return
true;
    }

    public function
rebuildActiveAddOnCache()
    {
       
$activeAddOns = [];
       
$addOnsComposer = [];

       
// cached add-on entities can end up being saved here so clear entity cache
       
$this->em->clearEntityCache('XF:AddOn');

       
$addOnManager = \XF::app()->addOnManager();

       
$addOns = $this->em->getFinder('XF:AddOn')->where('active', 1)->fetch();
        foreach (
$addOns AS $addOn)
        {
           
$activeAddOns[$addOn->addon_id] = $addOn->version_id;

           
$addOnClass = $addOnManager->getById($addOn->addon_id);
            if (
$addOnClass)
            {
               
$addOnId = $addOn->addon_id;
               
$autoloadPath = $addOnClass->composer_autoload;

                if (!
$autoloadPath)
                {
                    continue;
                }

               
$addOnAutoload = $addOnManager->getAddOnPath($addOnId) . \XF::$DS . $autoloadPath;

                if (!
$this->checkComposerAutoloadPath('installed.json', $addOnAutoload))
                {
                    continue;
                }

               
$data = [
                   
'autoload_path' => $autoloadPath . \XF::$DS,
                   
'namespaces' => false,
                   
'psr4' => false,
                   
'classmap' => false,
                   
'files' => false,
                ];

               
$hasData = false;

                if (
$this->checkComposerAutoloadPath('autoload_namespaces.php', $addOnAutoload))
                {
                   
$data['namespaces'] = true;
                   
$hasData = true;
                }
                if (
$this->checkComposerAutoloadPath('autoload_psr4.php', $addOnAutoload))
                {
                   
$data['psr4'] = true;
                   
$hasData = true;
                }
                if (
$this->checkComposerAutoloadPath('autoload_classmap.php', $addOnAutoload))
                {
                   
$data['classmap'] = true;
                   
$hasData = true;
                }
                if (
$this->checkComposerAutoloadPath('autoload_files.php', $addOnAutoload, false))
                {
                   
$data['files'] = true;
                   
$hasData = true;
                }

                if (
$hasData)
                {
                   
$addOnsComposer[$addOnId] = $data;
                }
            }
        }

        \
XF::registry()->set('addOns', $activeAddOns);
        \
XF::registry()->set('addOnsComposer', $addOnsComposer);

        return
$activeAddOns;
    }

    public function
triggerRebuildActiveChange(\XF\Entity\AddOn $addOn)
    {
       
$atomicJobs = $this->onActiveChange($addOn);

       
$addOnHandler = new AddOn($addOn, \XF::app()->addOnManager());
       
$addOnHandler->onActiveChange($addOn->active, $atomicJobs);

        if (
$atomicJobs)
        {
            \
XF::app()->jobManager()->enqueueUnique(
               
'addOnActive' . $addOn->addon_id,
               
'XF:Atomic', ['execute' => $atomicJobs]
            );
        }
    }

    protected function
onActiveChange(\XF\Entity\AddOn $addOn): array
    {
       
$atomicJobs = [];

        foreach (
$this->getDataTypeHandlers() AS $handler)
        {
           
$handler->rebuildActiveChange($addOn, $atomicJobs);
        }

        \
XF::runOnce('rebuild_addon_active', function()
        {
           
/** @var \XF\Repository\ForumType $forumTypeRepo */
           
$forumTypeRepo = $this->em->getRepository('XF:ForumType');
           
$forumTypeRepo->rebuildForumTypeCache();

           
/** @var \XF\Repository\ThreadType $threadTypeRepo */
           
$threadTypeRepo = $this->em->getRepository('XF:ThreadType');
           
$threadTypeRepo->rebuildThreadTypeCache();
        });

        return
$atomicJobs;
    }

    public function
triggerRebuildProcessingChange(\XF\Entity\AddOn $addOn)
    {
       
// Note: These rebuilds will not take effect until the next request.

       
$this->em->getRepository('XF:ClassExtension')->rebuildExtensionCache();
       
$this->em->getRepository('XF:CodeEventListener')->rebuildListenerCache();
       
$this->em->getRepository('XF:Route')->rebuildRouteCaches();
    }

    public function
updateRelatedIds(\XF\Entity\AddOn $addOn, $oldId)
    {
        if (
$oldId == $addOn->addon_id)
        {
            return;
        }

       
$newId = $addOn->addon_id;

       
$db = $this->em->getDb();
       
$db->beginTransaction();

        foreach (
$this->getDataTypeHandlers() AS $handler)
        {
           
$handler->updateAddOnId($oldId, $newId);
        }

       
$db->commit();
    }

    public function
enqueueRemoveAddOnData($id)
    {
        return \
XF::app()->jobManager()->enqueueUnique($id . 'AddOnUnInstall', 'XF:AddOnUninstallData', [
           
'addon_id' => $id
       
]);
    }

    public function
finalizeRemoveAddOnData($addOnId)
    {
       
$simpleCache = \XF::app()->simpleCache();
       
$simpleCache->deleteSet($addOnId);

       
$this->rebuildActiveAddOnCache();
    }

   
/**
     * @return AbstractDataType
     */
   
public function getDataTypeHandler($class)
    {
       
$class = \XF::stringToClass($class, '%s\AddOn\DataType\%s');
       
$class = \XF::extendClass($class);

        return new
$class($this->em);
    }

   
/**
     * @return AbstractDataType[]
     */
   
public function getDataTypeHandlers()
    {
        if (
$this->types)
        {
            return
$this->types;
        }

       
$objects = [];
        foreach (
$this->getDataTypeClasses() AS $typeClass)
        {
           
$class = \XF::stringToClass($typeClass, '%s\AddOn\DataType\%s');
           
$class = \XF::extendClass($class);
           
$objects[$typeClass] = new $class($this->em);
        }

       
$this->types = $objects;

        return
$objects;
    }

    public function
getDataTypeClasses()
    {
        return [
           
'XF:ActivitySummaryDefinition',
           
'XF:AdminNavigation',
           
'XF:AdminPermission',
           
'XF:AdvertisingPosition',
           
'XF:ApiScope',
           
'XF:BbCode',
           
'XF:BbCodeMediaSite',
           
'XF:ClassExtension',
           
'XF:CodeEvent',
           
'XF:CodeEventListener',
           
'XF:ContentTypeField',
           
'XF:CronEntry',
           
'XF:HelpPage',
           
'XF:MemberStat',
           
'XF:Navigation',
           
'XF:Option',
           
'XF:OptionGroup',
           
'XF:Permission',
           
'XF:PermissionInterfaceGroup',
           
'XF:Phrase',
           
'XF:Route',
           
'XF:StyleProperty',
           
'XF:StylePropertyGroup',
           
'XF:Template',
           
'XF:TemplateModification',
           
'XF:WidgetDefinition',
           
'XF:WidgetPosition'
       
];
    }
}