Вход Регистрация
Файл: library/XenForo/Model/ThreadPrefix.php
Строк: 531
<?php

/**
 * Model for thread prefixes.
 */
class XenForo_Model_ThreadPrefix extends XenForo_Model
{
    const 
FETCH_FORUM_PREFIX 0x01;
    const 
FETCH_PREFIX_GROUP 0x02;

    
/**
     * Fetches a single prefix, as defined by its unique prefix ID
     *
     * @param integer $prefixId
     *
     * @return array
     */
    
public function getPrefixById($prefixId)
    {
        if (!
$prefixId)
        {
            return array();
        }

        return 
$this->_getDb()->fetchRow('
            SELECT *
            FROM xf_thread_prefix
            WHERE prefix_id = ?
        '
$prefixId);
    }

    
/**
     * Get prefixes as defined by conditions and fetch options
     *
     * @param array $conditions
     * @param array $fetchOptions
     *
     * @return array key: continuous or prefix id, value: array of prefix info
     */
    
public function getPrefixes(array $conditions = array(), array $fetchOptions = array())
    {
        
$whereConditions $this->preparePrefixConditions($conditions$fetchOptions);

        
$orderClause $this->preparePrefixOrderOptions($fetchOptions'prefix.materialized_order');
        
$joinOptions $this->preparePrefixFetchOptions($fetchOptions);
        
$limitOptions $this->prepareLimitFetchOptions($fetchOptions);

        
$fetchAll = (!empty($fetchOptions['join']) && ($fetchOptions['join'] & self::FETCH_FORUM_PREFIX));

        
$query $this->limitQueryResults('
            SELECT prefix.*
                ' 
$joinOptions['selectFields'] . '
            FROM xf_thread_prefix AS prefix
                ' 
$joinOptions['joinTables'] . '
            WHERE ' 
$whereConditions '
            ' 
$orderClause '
            '
$limitOptions['limit'], $limitOptions['offset']
        );

        return (
$fetchAll $this->_getDb()->fetchAll($query) : $this->fetchAllKeyed($query'prefix_id'));
    }

    
/**
     * Prepares a set of conditions against which to select prefixes.
     *
     * @param array $conditions List of conditions.
     * @param array $fetchOptions The fetch options that have been provided. May be edited if criteria requires.
     *
     * @return string Criteria as SQL for where clause
     */
    
public function preparePrefixConditions(array $conditions, array &$fetchOptions)
    {
        
$sqlConditions = array();

        
$db $this->_getDb();

        if (isset(
$conditions['prefix_ids']))
        {
            
$sqlConditions[] = 'prefix.prefix_id IN(' $db->quote($conditions['prefix_ids']) . ')';
        }

        if (isset(
$conditions['node_id']))
        {
            if (
is_array($conditions['node_id']))
            {
                
$sqlConditions[] = 'fp.node_id IN(' $db->quote($conditions['node_id']) . ')';
            }
            else
            {
                
$sqlConditions[] = 'fp.node_id = ' $db->quote($conditions['node_id']);
            }
            
$this->addFetchOptionJoin($fetchOptionsself::FETCH_FORUM_PREFIX);
        }

        if (isset(
$conditions['node_ids']))
        {
            
$sqlConditions[] = 'fp.node_id IN(' $db->quote($conditions['node_ids']) . ')';
            
$this->addFetchOptionJoin($fetchOptionsself::FETCH_FORUM_PREFIX);
        }

        return 
$this->getConditionsForClause($sqlConditions);
    }

    
/**
     * Prepares join-related fetch options.
     *
     * @param array $fetchOptions
     *
     * @return array Containing 'selectFields' and 'joinTables' keys.
     */
    
public function preparePrefixFetchOptions(array $fetchOptions)
    {
        
$selectFields '';
        
$joinTables '';

        if (!empty(
$fetchOptions['join']))
        {
            if (
$fetchOptions['join'] & self::FETCH_FORUM_PREFIX)
            {
                
$selectFields .= ',
                    fp.*'
;
                
$joinTables .= '
                    INNER JOIN xf_forum_prefix AS fp ON
                        (fp.prefix_id = prefix.prefix_id)'
;
            }

            if (
$fetchOptions['join'] & self::FETCH_PREFIX_GROUP)
            {
                
$selectFields .= ',
                    prefix_group.display_order AS group_display_order'
;
                
$joinTables .= '
                    LEFT JOIN xf_thread_prefix_group AS prefix_group ON
                        (prefix_group.prefix_group_id = prefix.prefix_group_id)'
;
            }
        }

        return array(
            
'selectFields' => $selectFields,
            
'joinTables'   => $joinTables
        
);
    }

    
/**
     * Construct 'ORDER BY' clause
     *
     * @param array $fetchOptions (uses 'order' key)
     * @param string $defaultOrderSql Default order SQL
     *
     * @return string
     */
    
public function preparePrefixOrderOptions(array &$fetchOptions$defaultOrderSql '')
    {
        
$choices = array(
            
'materialized_order' => 'prefix.materialized_order',
            
'canonical_order' => 'prefix_group.display_order, prefix.display_order',
        );

        if (!empty(
$fetchOptions['order']) && $fetchOptions['order'] == 'canonical_order')
        {
            
$this->addFetchOptionJoin($fetchOptionsself::FETCH_PREFIX_GROUP);
        }

        return 
$this->getOrderByClause($choices$fetchOptions$defaultOrderSql);
    }

    
/**
     * Fetches all prefixes, regardless of forum or user group associations
     *
     * @return array
     */
    
public function getAllPrefixes()
    {
        return 
$this->getPrefixes();
    }

    
/**
     * Fetches prefixes in prefix groups
     *
     * @param array $conditions
     * @param array $fetchOptions
     * @param integer $prefixCount Reference: counts the total number of prefixes
     *
     * @return [group ID => [title, prefixes => prefix]]
     */
    
public function getPrefixesByGroups(array $conditions = array(), array $fetchOptions = array(), &$prefixCount 0)
    {
        
$prefixes $this->getPrefixes($conditions$fetchOptions);

        
$prefixGroups = array();
        foreach (
$prefixes AS $prefix)
        {
            
$prefixGroups[$prefix['prefix_group_id']][$prefix['prefix_id']] = $this->preparePrefix($prefix);
        }

        
$prefixCount count($prefixes);

        return 
$prefixGroups;
    }

    
/**
     * Fetches all prefixes available in the specified forums
     *
     * @param integer|array $nodeIds
     *
     * @return array
     */
    
public function getPrefixesInForums($nodeId)
    {
        return 
$this->getPrefixes(is_array($nodeId)
            ? array(
'node_ids' => $nodeId)
            : array(
'node_id' => $nodeId)
        );
    }

    
/**
     * Fetches all prefixes available in the specified forums
     *
     * @param integer|array $nodeIds
     *
     * @return array
     */
    
public function getPrefixesInForum($nodeId)
    {
        
$output = array();
        foreach (
$this->getPrefixes(array('node_id' => $nodeId)) AS $prefix)
        {
            
$output[$prefix['prefix_id']] = $prefix;
        }

        return 
$output;
    }

    
/**
     * Fetches all prefixes usable by the visiting user in the specified forum(s)
     *
     * @param integer|array $nodeIds
     * @param array|null $viewingUser
     * @param boolean $verifyUsability
     *
     * @return array
     */
    
public function getUsablePrefixesInForums($nodeIds, array $viewingUser null$verifyUsability true)
    {
        
$this->standardizeViewingUserReference($viewingUser);

        
$prefixes $this->getPrefixesInForums($nodeIds);

        
$prefixGroups = array();
        foreach (
$prefixes AS $prefix)
        {
            if (!
$verifyUsability || $this->_verifyPrefixIsUsableInternal($prefix$viewingUser))
            {
                
$prefixId $prefix['prefix_id'];
                
$prefixGroupId $prefix['prefix_group_id'];

                if (!isset(
$prefixGroups[$prefixGroupId]))
                {
                    
$prefixGroups[$prefixGroupId] = array();

                    if (
$prefixGroupId)
                    {
                        
$prefixGroups[$prefixGroupId]['title'] = new XenForo_Phrase(
                            
$this->getPrefixGroupTitlePhraseName($prefixGroupId));
                    }

                }

                
$prefixGroups[$prefixGroupId]['prefixes'][$prefixId] = $prefix;
            }
        }

        return 
$prefixGroups;
    }

    public function 
getPrefixIfInForum($prefixId$nodeId)
    {
        return 
$this->_getDb()->fetchRow('
            SELECT prefix.*
            FROM xf_thread_prefix AS prefix
            INNER JOIN xf_forum_prefix AS fp ON (fp.prefix_id = prefix.prefix_id AND fp.node_id = ?)
            WHERE prefix.prefix_id = ?
        '
, array($nodeId$prefixId));
    }

    public function 
getForumAssociationsByPrefix($prefixId)
    {
        return 
$this->_getDb()->fetchCol('
            SELECT node_id
            FROM xf_forum_prefix
            WHERE prefix_id = ?
        '
$prefixId);
    }

    public function 
getVisiblePrefixIds(array $viewingUser null)
    {
        
$this->standardizeViewingUserReference($viewingUser);

        
$prefixes = array();

        
/** @var $forumModel XenForo_Model_Forum */
        
$forumModel $this->getModelFromCache('XenForo_Model_Forum');

        
$results $this->_getDb()->query("
            SELECT prefix.prefix_id, node.*, forum.*, cache.cache_value AS node_permission_cache
            FROM xf_thread_prefix AS prefix
            INNER JOIN xf_forum_prefix AS fp ON (fp.prefix_id = prefix.prefix_id)
            INNER JOIN xf_node AS node ON (fp.node_id = node.node_id)
            INNER JOIN xf_forum AS forum ON (node.node_id = forum.node_id)
            INNER JOIN xf_permission_cache_content AS cache ON
                (cache.content_type = 'node' AND cache.content_id = node.node_id AND cache.permission_combination_id = ?)
            ORDER BY prefix.materialized_order
        "
$viewingUser['permission_combination_id']);
        while (
$result $results->fetch())
        {
            if (isset(
$prefixes[$result['prefix_id']]))
            {
                continue;
            }

            
$permissions $forumModel->getPermissionsForForum($result);
            if (
$forumModel->canViewForum($result$null$permissions$viewingUser))
            {
                
$prefixes[$result['prefix_id']] = $result['prefix_id'];
            }
        }

        return 
$prefixes;
    }

    public function 
preparePrefix(array $prefix)
    {
        
$prefix['title'] = new XenForo_Phrase($this->getPrefixTitlePhraseName($prefix['prefix_id']));

        return 
$prefix;
    }

    public function 
preparePrefixes(array $prefixes)
    {
        foreach (
$prefixes AS &$prefix)
        {
            
$prefix $this->preparePrefix($prefix);
        }

        return 
$prefixes;
    }

    public function 
getPrefixTitlePhraseName($prefixId)
    {
        return 
'thread_prefix_' $prefixId;
    }

    public function 
updatePrefixForumAssociationByPrefix($prefixId, array $nodeIds)
    {
        
$emptyNodeKey array_search(0$nodeIds);
        if (
$emptyNodeKey !== false)
        {
            unset(
$nodeIds[$emptyNodeKey]);
        }

        
$nodeIds array_unique($nodeIds);

        
$existingNodeIds $this->getForumAssociationsByPrefix($prefixId);
        if (!
$nodeIds && !$existingNodeIds)
        {
            return; 
// nothing to do
        
}

        
$db $this->_getDb();
        
XenForo_Db::beginTransaction($db);

        
$db->delete('xf_forum_prefix''prefix_id = ' $db->quote($prefixId));

        foreach (
$nodeIds AS $nodeId)
        {
            
$db->insert('xf_forum_prefix', array(
                
'node_id' => $nodeId,
                
'prefix_id' => $prefixId
            
));
        }

        
$rebuildNodeIds array_unique(array_merge($nodeIds$existingNodeIds));
        
$this->rebuildPrefixForumAssociationCache($rebuildNodeIds);

        
XenForo_Db::commit($db);
    }

    public function 
updatePrefixForumAssociationByForum($nodeId, array $prefixIds)
    {
        
$emptyPrefixKey array_search(0$prefixIds);
        if (
$emptyPrefixKey !== false)
        {
            unset(
$prefixIds[$emptyPrefixKey]);
        }

        
$prefixIds array_unique($prefixIds);

        
$db $this->_getDb();

        
XenForo_Db::beginTransaction($db);

        
$db->delete('xf_forum_prefix''node_id = ' $db->quote($nodeId));

        foreach (
$prefixIds AS $prefixId)
        {
            
$db->insert('xf_forum_prefix', array(
                
'node_id' => $nodeId,
                
'prefix_id' => $prefixId
            
));
        }

        
$this->rebuildPrefixForumAssociationCache($nodeId);

        
XenForo_Db::commit($db);
    }

    public function 
rebuildPrefixForumAssociationCache($nodeIds)
    {
        if (!
is_array($nodeIds))
        {
            
$nodeIds = array($nodeIds);
        }
        if (!
$nodeIds)
        {
            return;
        }

        
$db $this->_getDb();

        
$newCache = array();

        foreach (
$this->getPrefixesInForums($nodeIds) AS $prefix)
        {
            
$prefixGroupId $prefix['prefix_group_id'];
            
$newCache[$prefix['node_id']][$prefixGroupId][$prefix['prefix_id']] = $prefix['prefix_id'];
        }

        
XenForo_Db::beginTransaction($db);

        foreach (
$nodeIds AS $nodeId)
        {
            
$update = (isset($newCache[$nodeId]) ? serialize($newCache[$nodeId]) : '');

            
$db->update('xf_forum', array(
                
'prefix_cache' => $update
            
), 'node_id = ' $db->quote($nodeId));
        }

        
XenForo_Db::commit($db);
    }

    
/**
     * Fetches an array of prefixes including prefix group info, for use in <xen:options source />
     *
     * @param array $conditions
     * @param array $fetchOptions
     *
     * @return array
     */
    
public function getPrefixOptions(array $conditions = array(), array $fetchOptions = array())
    {
        
$prefixGroups $this->getPrefixesByGroups($conditions$fetchOptions);

        
$options = array();

        foreach (
$prefixGroups AS $prefixGroupId => $prefixes)
        {
            if (
$prefixes)
            {
                if (
$prefixGroupId)
                {
                    
$groupTitle = new XenForo_Phrase($this->getPrefixGroupTitlePhraseName($prefixGroupId));
                    
$groupTitle = (string)$groupTitle;
                }
                else
                {
                    
$groupTitle = new XenForo_Phrase('ungrouped');
                    
$groupTitle '(' $groupTitle ')';
                }

                foreach (
$prefixes AS $prefixId => $prefix)
                {
                    
$options[$groupTitle][$prefixId] = array(
                        
'value' => $prefixId,
                        
'label' => (string)$prefix['title'],
                        
'_data' => array('css' => $prefix['css_class'])
                    );
                }
            }
        }

        return 
$options;
    }

    
/**
     * Returns an array with default values for a new prefix
     *
     * @return array
     */
    
public function getDefaultPrefixValues()
    {
        return array(
            
'prefix_group_id' => 0,
            
'display_order' => 1,
            
'css_class' => 'prefix prefixPrimary'
        
);
    }

    
/**
     * Fetches the data for the prefix cache
     *
     * @return array
     */
    
public function getPrefixCache()
    {
        return 
$this->_getDb()->fetchPairs('
            SELECT prefix_id, css_class
            FROM xf_thread_prefix
            ORDER BY materialized_order
        '
);
    }

    
/**
     * Rebuilds the 'threadPrefixes' cache
     *
     * @return array
     */
    
public function rebuildPrefixCache()
    {
        
$prefixes $this->getPrefixCache();
        
$this->_getDataRegistryModel()->set('threadPrefixes'$prefixes);

        return 
$prefixes;
    }

    
/**
     * Rebuilds the 'materialized_order' field in the prefix table,
     * based on the canonical display_order data in the prefix and prefix_group tables.
     */
    
public function rebuildPrefixMaterializedOrder()
    {
        
$prefixes $this->getPrefixes(array(), array('order' => 'canonical_order'));

        
$db $this->_getDb();
        
$ungroupedPrefixes = array();
        
$updates = array();
        
$i 0;

        foreach (
$prefixes AS $prefixId => $prefix)
        {
            if (
$prefix['prefix_group_id'])
            {
                if (++
$i != $prefix['materialized_order'])
                {
                    
$updates[$prefixId] = 'WHEN ' $db->quote($prefixId) . ' THEN ' $db->quote($i);
                }
            }
            else
            {
                
$ungroupedPrefixes[$prefixId] = $prefix;
            }
        }

        foreach (
$ungroupedPrefixes AS $prefixId => $prefix)
        {
            if (++
$i != $prefix['materialized_order'])
            {
                
$updates[$prefixId] = 'WHEN ' $db->quote($prefixId) . ' THEN ' $db->quote($i);
            }
        }

        if (!empty(
$updates))
        {
            
$db->query('
                UPDATE xf_thread_prefix SET materialized_order = CASE prefix_id
                ' 
implode(' '$updates) . '
                END
                WHERE prefix_id IN(' 
$db->quote(array_keys($updates)) . ')
            '
);
        }
    }

    public function 
verifyPrefixIsUsable($prefixId$nodeId, array $viewingUser null)
    {
        
$this->standardizeViewingUserReference($viewingUser);

        if (!
$prefixId)
        {
            return 
true// not picking one, always ok
        
}

        
$prefix $this->getPrefixIfInForum($prefixId$nodeId);
        if (!
$prefix)
        {
            return 
false// bad prefix or bad node
        
}

        return 
$this->_verifyPrefixIsUsableInternal($prefix$viewingUser);
    }

    protected function 
_verifyPrefixIsUsableInternal(array $prefix, array $viewingUser)
    {
        
$userGroups explode(','$prefix['allowed_user_group_ids']);
        if (
in_array(-1$userGroups) || in_array($viewingUser['user_group_id'], $userGroups))
        {
            return 
true// available to all groups or the primary group
        
}

        if (
$viewingUser['secondary_group_ids'])
        {
            foreach (
explode(','$viewingUser['secondary_group_ids']) AS $userGroupId)
            {
                if (
in_array($userGroupId$userGroups))
                {
                    return 
true// available to one secondary group
                
}
            }
        }

        return 
false// not available to any groups
    
}

    
// prefix groups ---------------------------------------------------------

    /**
     * Fetches a single prefix group, as defined by its unique prefix group ID
     *
     * @param integer $prefixGroupId
     *
     * @return array
     */
    
public function getPrefixGroupById($prefixGroupId)
    {
        if (!
$prefixGroupId)
        {
            return array();
        }

        return 
$this->_getDb()->fetchRow('
            SELECT *
            FROM xf_thread_prefix_group
            WHERE prefix_group_id = ?
        '
$prefixGroupId);
    }

    public function 
getAllPrefixGroups()
    {
        return 
$this->fetchAllKeyed('
            SELECT *
            FROM xf_thread_prefix_group
            ORDER BY display_order
        '
'prefix_group_id');
    }

    public function 
getPrefixGroupOptions($selectedGroupId)
    {
        
$prefixGroups $this->getAllPrefixGroups();
        
$prefixGroups $this->preparePrefixGroups($prefixGroups);

        
$options = array();

        foreach (
$prefixGroups AS $prefixGroupId => $prefixGroup)
        {
            
$options[$prefixGroupId] = $prefixGroup['title'];
        }

        return 
$options;
    }

    public function 
mergePrefixesIntoGroups(array $prefixes, array $prefixGroups)
    {
        
$merge = array();

        foreach (
$prefixGroups AS $prefixGroupId => $prefixGroup)
        {
            if (isset(
$prefixes[$prefixGroupId]))
            {
                
$merge[$prefixGroupId] = $prefixes[$prefixGroupId];
                unset(
$prefixes[$prefixGroupId]);
            }
            else
            {
                
$merge[$prefixGroupId] = array();
            }
        }

        if (!empty(
$prefixes))
        {
            foreach (
$prefixes AS $prefixGroupId => $_prefixes)
            {
                
$merge[$prefixGroupId] = $_prefixes;
            }
        }

        return 
$merge;
    }

    public function 
getPrefixGroupTitlePhraseName($prefixGroupId)
    {
        return 
'thread_prefix_group_' $prefixGroupId;
    }

    public function 
preparePrefixGroups(array $prefixGroups)
    {
        return 
array_map(array($this'preparePrefixGroup'), $prefixGroups);
    }

    public function 
preparePrefixGroup(array $prefixGroup)
    {
        
$prefixGroup['title'] = new XenForo_Phrase($this->getPrefixGroupTitlePhraseName($prefixGroup['prefix_group_id']));

        return 
$prefixGroup;
    }
}
Онлайн: 3
Реклама