Major overhaul of caching system (work in progress)
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / cache / builder / UserGroupPermissionCacheBuilder.class.php
1 <?php
2 namespace wcf\system\cache\builder;
3 use wcf\system\database\util\PreparedStatementConditionBuilder;
4 use wcf\system\exception\SystemException;
5 use wcf\system\WCF;
6 use wcf\util\ClassUtil;
7 use wcf\util\StringUtil;
8
9 /**
10 * Caches the merged user group options for a certain user group combination.
11 *
12 * @author Marcel Werk
13 * @copyright 2001-2013 WoltLab GmbH
14 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
15 * @package com.woltlab.wcf
16 * @subpackage system.cache.builder
17 * @category Community Framework
18 */
19 class UserGroupPermissionCacheBuilder extends AbstractCacheBuilder {
20 /**
21 * list of used group option type objects
22 * @var array<wcf\system\option\group\IGroupOptionType>
23 */
24 protected $typeObjects = array();
25
26 /**
27 * @see wcf\system\cache\builder\AbstractCacheBuilder::rebuild()
28 */
29 public function rebuild(array $parameters) {
30 $data = array();
31
32 // get all options
33 $sql = "SELECT optionName, optionID
34 FROM wcf".WCF_N."_user_group_option";
35 $statement = WCF::getDB()->prepareStatement($sql);
36 $statement->execute();
37
38 $options = array();
39 while ($row = $statement->fetchArray()) {
40 $options[$row['optionName']] = $row['optionID'];
41 }
42
43 if (!empty($options)) {
44 // get needed options
45 $conditions = new PreparedStatementConditionBuilder();
46 $conditions->add("option_value.groupID IN (?)", array($parameters));
47 $conditions->add("option_value.optionID IN (?)", array($options));
48
49 $sql = "SELECT option_table.optionName, option_table.optionType, option_value.optionValue
50 FROM wcf".WCF_N."_user_group_option_value option_value
51 LEFT JOIN wcf".WCF_N."_user_group_option option_table
52 ON (option_table.optionID = option_value.optionID)
53 ".$conditions;
54 $statement = WCF::getDB()->prepareStatement($sql);
55 $statement->execute($conditions->getParameters());
56 while ($row = $statement->fetchArray()) {
57 if (!isset($data[$row['optionName']])) {
58 $data[$row['optionName']] = array('type' => $row['optionType'], 'values' => array());
59 }
60
61 $data[$row['optionName']]['values'][] = $row['optionValue'];
62 }
63
64 // merge values
65 foreach ($data as $optionName => $option) {
66 if (count($option['values']) == 1) {
67 $result = $option['values'][0];
68 }
69 else {
70 $typeObj = $this->getTypeObject($option['type']);
71 $result = array_shift($option['values']);
72 foreach ($option['values'] as $value) {
73 $newValue = $typeObj->merge($result, $value);
74 if ($newValue !== null) {
75 $result = $newValue;
76 }
77 }
78 }
79
80 // unset false values
81 if ($result === false) {
82 unset($data[$optionName]);
83 }
84 else {
85 $data[$optionName] = $result;
86 }
87 }
88 }
89
90 $data['groupIDs'] = $parameters;
91 return $data;
92 }
93
94 /**
95 * Returns an object of the requested group option type.
96 *
97 * @param string $type
98 * @return wcf\system\option\user\group\IUserGroupOptionType
99 */
100 protected function getTypeObject($type) {
101 if (!isset($this->typeObjects[$type])) {
102 $className = 'wcf\system\option\user\group\\'.StringUtil::firstCharToUpperCase($type).'UserGroupOptionType';
103
104 // validate class
105 if (!class_exists($className)) {
106 throw new SystemException("unable to find class '".$className."'");
107 }
108 if (!ClassUtil::isInstanceOf($className, 'wcf\system\option\user\group\IUserGroupOptionType')) {
109 throw new SystemException("'".$className."' does not implement 'wcf\system\option\user\group\IUserGroupOptionType'");
110 }
111
112 // create instance
113 $this->typeObjects[$type] = new $className();
114 }
115
116 return $this->typeObjects[$type];
117 }
118 }