Passed
Push — master ( 054586...a82a12 )
by Anton
03:12
created

Treeview::getSubtree()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 27
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 4
nop 3
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @package Cadmium\System\Modules\Entitizer
5
 * @author Anton Romanov
6
 * @copyright Copyright (c) 2015-2017, Anton Romanov
7
 * @link http://cadmium-cms.com
8
 */
9
10
namespace Modules\Entitizer\Utils {
11
12
	use Modules\Entitizer, DB;
13
14
	abstract class Treeview extends Collection {
15
16
		/**
17
		 * Get the join statement
18
		 */
19
20
		protected function getQueryJoin(int $parent_id) : string {
21
22
			return (0 !== $parent_id) ? (("JOIN " . static::$table_relations . " rel ") .
23
24
			       ("ON rel.ancestor = " . $parent_id . " AND rel.descendant = ent.id AND rel.depth >= 1")) :
25
26
				   ("JOIN " . static::$table_relations . " rel ON rel.descendant = ent.id");
27
		}
28
29
		/**
30
		 * Get the select query
31
		 */
32
33
		private function getSelectQuery(int $parent_id, array $config, array $order_by) : string {
34
35
			return ("SELECT " . $this->getSelection() . ", COALESCE(par.ancestor, 0) as parent_id ") .
36
37
			       ("FROM " . static::$table . " ent " . $this->getQueryJoin($parent_id) . " ") .
38
39
			       ("LEFT JOIN " . static::$table_relations . " par ON par.descendant = ent.id AND par.depth = 1 ") .
40
41
			       (('' !== ($condition = $this->getCondition($config))) ? ("WHERE " . $condition . " ") : "") .
42
43
			       ("GROUP BY ent.id ORDER BY MAX(rel.depth) ASC, " . $this->getOrderBy($order_by));
44
		}
45
46
		/**
47
		 * Get the count query
48
		 */
49
50
		private function getCountQuery(int $parent_id) : string {
51
52
			return ("SELECT COUNT(DISTINCT ent.id) as count FROM " . static::$table . " ent ") .
53
54
			       $this->getQueryJoin($parent_id);
55
		}
56
57
		/**
58
		 * Get the depth query
59
		 */
60
61
		private function getDepthQuery(int $parent_id) : string {
62
63
			$query = ("SELECT COUNT(DISTINCT rel.depth) as depth FROM " . static::$table . " ent ") .
64
65
			         $this->getQueryJoin($parent_id);
66
67
			# ------------------------
68
69
			return $query;
70
		}
71
72
		/**
73
		 * Get the entity subtree
74
		 *
75
		 * @param $parent_id    an id of a parent entity
76
		 * @param $config       an array of filtering options
77
		 * @param $order_by     an array where each key is a field name and each value is a sorting direction (ASC or DESC)
78
		 *
79
		 * @return array|false : the multidimensional array containing the tree or false on failure
80
		 */
81
82
		public function getSubtree(int $parent_id = 0, array $config = [], array $order_by = []) {
83
84
			if (!(static::$nesting && ($parent_id >= 0))) return false;
85
86
			# Select entities
87
88
			$query = $this->getSelectQuery($parent_id, $config, $order_by);
89
90
			if (!(DB::send($query) && DB::getLast()->status)) return false;
91
92
			# Process results
93
94
			$items = [$parent_id => ['children' => []]];
95
96
			while (null !== ($data = DB::getLast()->getRow())) {
97
98
				$dataset = Entitizer::getDataset(static::$table, $data);
99
100
				$items[$dataset->id] = ['dataset' => $dataset, 'children' => []];
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<Modules\Entitizer\Utils\Dataset>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
101
102
				$items[intval($data['parent_id'])]['children'][] = $dataset->id;
0 ignored issues
show
Bug introduced by
The property id does not seem to exist in Modules\Entitizer\Utils\Dataset.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
103
			}
104
105
			# ------------------------
106
107
			return $items;
108
		}
109
110
		/**
111
		 * Get the count of items within the entity subtree
112
		 *
113
		 * @param $parent_id : an id of a parent entity
114
		 *
115
		 * @return int|false : the number of entities or false on failure
116
		 */
117
118 View Code Duplication
		public function getSubtreeCount(int $parent_id = 0) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119
120
			if (!(static::$nesting && ($parent_id >= 0))) return false;
121
122
			# Get count
123
124
			$query = $this->getCountQuery($parent_id);
125
126
			if (!(DB::send($query) && DB::getLast()->status)) return false;
127
128
			# ------------------------
129
130
			return intval(DB::getLast()->getRow()['count']);
131
		}
132
133
		/**
134
		 * Get the subtree depth
135
		 *
136
		 * @param $parent_id : an id of a parent entity
137
		 *
138
		 * @return int|false : the depth or false on failure
139
		 */
140
141 View Code Duplication
		public function getSubtreeDepth(int $parent_id = 0) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
143
			if (!(static::$nesting && ($parent_id >= 0))) return false;
144
145
			# Get depth
146
147
			$query = $this->getDepthQuery($parent_id);
148
149
			if (!(DB::send($query) && DB::getLast()->status)) return false;
150
151
			# ------------------------
152
153
			return intval(DB::getLast()->getRow()['depth']);
154
		}
155
156
		/**
157
		 * Get the entity path
158
		 *
159
		 * @param $parent_id : an id of a parent entity
160
		 *
161
		 * @return array|false : the array of path items or false on failure
162
		 */
163
164
		public function getPath(int $parent_id = 0) {
165
166
			if (!(static::$nesting && ($parent_id >= 0))) return false;
167
168
			# Process query
169
170
			$query = ("SELECT " . $this->getSelection() . " FROM " . static::$table . " ent ") .
171
172
			         ("JOIN " . static::$table_relations . " rel ON rel.ancestor = ent.id ") .
173
174
					 ("WHERE rel.descendant = " . $parent_id . " ORDER BY rel.depth DESC");
175
176
			# Select path
177
178
			if (!(DB::send($query) && DB::getLast()->status)) return false;
179
180
			# Process results
181
182
			$path = [];
183
184
			while (null !== ($data = DB::getLast()->getRow())) $path[] = Entitizer::getDataset(static::$table, $data)->getData();
185
186
			# ------------------------
187
188
			return $path;
189
		}
190
	}
191
}
192