1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Table
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Table class supporting modified pre-order tree traversal behavior.
14 *
15 * @since 11.1
16 */
17 class JTableAsset extends JTableNested
18 {
19 /**
20 * The primary key of the asset.
21 *
22 * @var integer
23 * @since 11.1
24 */
25 public $id = null;
26
27 /**
28 * The unique name of the asset.
29 *
30 * @var string
31 * @since 11.1
32 */
33 public $name = null;
34
35 /**
36 * The human readable title of the asset.
37 *
38 * @var string
39 * @since 11.1
40 */
41 public $title = null;
42
43 /**
44 * The rules for the asset stored in a JSON string
45 *
46 * @var string
47 * @since 11.1
48 */
49 public $rules = null;
50
51 /**
52 * Constructor
53 *
54 * @param JDatabaseDriver $db Database driver object.
55 *
56 * @since 11.1
57 */
58 public function __construct($db)
59 {
60 parent::__construct('#__assets', 'id', $db);
61 }
62
63 /**
64 * Method to load an asset by its name.
65 *
66 * @param string $name The name of the asset.
67 *
68 * @return integer
69 *
70 * @since 11.1
71 */
72 public function loadByName($name)
73 {
74 $query = $this->_db->getQuery(true)
75 ->select($this->_db->quoteName('id'))
76 ->from($this->_db->quoteName('#__assets'))
77 ->where($this->_db->quoteName('name') . ' = ' . $this->_db->quote($name));
78 $this->_db->setQuery($query);
79 $assetId = (int) $this->_db->loadResult();
80
81 if (empty($assetId))
82 {
83 return false;
84 }
85
86 return $this->load($assetId);
87 }
88
89 /**
90 * Assert that the nested set data is valid.
91 *
92 * @return boolean True if the instance is sane and able to be stored in the database.
93 *
94 * @since 11.1
95 */
96 public function check()
97 {
98 $this->parent_id = (int) $this->parent_id;
99
100 if (empty($this->rules))
101 {
102 $this->rules = '{}';
103 }
104
105 // JTableNested does not allow parent_id = 0, override this.
106 if ($this->parent_id > 0)
107 {
108 // Get the JDatabaseQuery object
109 $query = $this->_db->getQuery(true)
110 ->select('1')
111 ->from($this->_db->quoteName($this->_tbl))
112 ->where($this->_db->quoteName('id') . ' = ' . $this->parent_id);
113
114 if ($this->_db->setQuery($query, 0, 1)->loadResult())
115 {
116 return true;
117 }
118
119 $this->setError('Invalid Parent ID');
120
121 return false;
122 }
123
124 return true;
125 }
126
127 /**
128 * Method to recursively rebuild the whole nested set tree.
129 *
130 * @param integer $parentId The root of the tree to rebuild.
131 * @param integer $leftId The left id to start with in building the tree.
132 * @param integer $level The level to assign to the current nodes.
133 * @param string $path The path to the current nodes.
134 *
135 * @return integer 1 + value of root rgt on success, false on failure
136 *
137 * @since 3.5
138 * @throws RuntimeException on database error.
139 */
140 public function rebuild($parentId = null, $leftId = 0, $level = 0, $path = null)
141 {
142 // If no parent is provided, try to find it.
143 if ($parentId === null)
144 {
145 // Get the root item.
146 $parentId = $this->getRootId();
147
148 if ($parentId === false)
149 {
150 return false;
151 }
152 }
153
154 $query = $this->_db->getQuery(true);
155
156 // Build the structure of the recursive query.
157 if (!isset($this->_cache['rebuild.sql']))
158 {
159 $query->clear()
160 ->select($this->_tbl_key)
161 ->from($this->_tbl)
162 ->where('parent_id = %d');
163
164 // If the table has an ordering field, use that for ordering.
165 if (property_exists($this, 'ordering'))
166 {
167 $query->order('parent_id, ordering, lft');
168 }
169 else
170 {
171 $query->order('parent_id, lft');
172 }
173
174 $this->_cache['rebuild.sql'] = (string) $query;
175 }
176
177 // Make a shortcut to database object.
178
179 // Assemble the query to find all children of this node.
180 $this->_db->setQuery(sprintf($this->_cache['rebuild.sql'], (int) $parentId));
181
182 $children = $this->_db->loadObjectList();
183
184 // The right value of this node is the left value + 1
185 $rightId = $leftId + 1;
186
187 // Execute this function recursively over all children
188 foreach ($children as $node)
189 {
190 /*
191 * $rightId is the current right value, which is incremented on recursion return.
192 * Increment the level for the children.
193 * Add this item's alias to the path (but avoid a leading /)
194 */
195 $rightId = $this->rebuild($node->{$this->_tbl_key}, $rightId, $level + 1);
196
197 // If there is an update failure, return false to break out of the recursion.
198 if ($rightId === false)
199 {
200 return false;
201 }
202 }
203
204 // We've got the left value, and now that we've processed
205 // the children of this node we also know the right value.
206 $query->clear()
207 ->update($this->_tbl)
208 ->set('lft = ' . (int) $leftId)
209 ->set('rgt = ' . (int) $rightId)
210 ->set('level = ' . (int) $level)
211 ->where($this->_tbl_key . ' = ' . (int) $parentId);
212 $this->_db->setQuery($query)->execute();
213
214 // Return the right value of this node + 1.
215 return $rightId + 1;
216 }
217 }
218