Seditio Source
Root |
./othercms/xenForo 2.2.8/src/XF/Service/RebuildNestedSet.php
<?php

namespace XF\Service;

use
XF\Mvc\Entity\Entity;

class
RebuildNestedSet extends AbstractService
{
   
/**
     * @var \XF\Tree
     */
   
protected $tree;

    protected
$entityType;
    protected
$config;

    public function
__construct(\XF\App $app, $entityType, array $config = [])
    {
       
parent::__construct($app);
       
$this->entityType = $entityType;
       
$this->config = array_replace($this->getDefaultConfig(), $config);
    }

    protected function
getDefaultConfig()
    {
        return [
           
'parentField' => 'parent_id',
           
'orderField' => 'display_order',
           
'titleField' => 'title',
           
'breadcrumbField' => 'breadcrumb_data',
           
'rootId' => 0
       
];
    }

    protected function
setupTree()
    {
        if (
$this->tree)
        {
            return;
        }

       
$entities = $this->getEntities();
       
$this->tree = new \XF\Tree($entities, $this->config['parentField'], $this->config['rootId']);
    }

    protected function
getEntities()
    {
        return
$this->finder($this->entityType)
            ->
order($this->config['orderField'])
            ->
fetch();
    }

    public function
rebuildNestedSetInfo()
    {
       
$this->setupTree();

       
$passDown = $this->getBasePassableData();

       
$this->db()->beginTransaction();
       
$this->_rebuildNestedSetInfo($this->config['rootId'], $passDown);
       
$this->db()->commit();
    }

    protected function
_rebuildNestedSetInfo($id, array $passDown, $depth = -1, &$counter = 0)
    {
       
/** @var \XF\Mvc\Entity\Entity $entity */
       
$entity = $this->tree->getData($id);

        if (
$entity)
        {
           
$counter++;
        }
       
$left = $counter;

        if (
$entity)
        {
           
$selfData = $this->getSelfData($passDown, $entity, $depth, $left);
           
$childPassDown = $this->getChildPassableData($passDown, $entity, $depth, $left);
        }
        else
        {
           
$selfData = [];
           
$childPassDown = $passDown;
        }

        foreach (
$this->tree->childIds($id) AS $childId)
        {
           
$this->_rebuildNestedSetInfo($childId, $childPassDown, $depth + 1, $counter);
        }

        if (
$entity)
        {
           
$counter++;
        }
       
$right = $counter;

        if (
$entity)
        {
           
$updateData = $selfData + [
               
'lft' => $left,
               
'rgt' => $right,
               
'depth' => $depth
           
];

           
$entity->fastUpdate($updateData);
        }
    }

    protected function
getBasePassableData()
    {
        return [
           
$this->config['breadcrumbField'] => []
        ];
    }

    protected function
getSelfData(array $passData, Entity $entity, $depth, $left)
    {
        return
$passData;
    }

    protected function
getChildPassableData(array $passData, Entity $entity, $depth, $left)
    {
       
$breadcrumbField = $this->config['breadcrumbField'];

       
$passData[$breadcrumbField][$entity->getEntityId()] = $this->getBreadcrumbEntry($entity, $depth, $left);

        return
$passData;
    }

    protected function
getBreadcrumbEntry(Entity $entity, $depth, $left)
    {
       
$titleField = $this->config['titleField'];
       
$title = $entity[$titleField];
       
$id = $entity->getEntityId();
       
$idField = $entity->structure()->primaryKey;

        return [
           
$idField => $id,
           
$titleField => $title,
           
'depth' => $depth,
           
'lft' => $left
       
];
    }
}