Completed
Push — develop ( e1201f...9e183f )
by Daniel
10:47
created

display   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 271
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 75%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 0
dl 0
loc 271
ccs 72
cts 96
cp 0.75
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A is_ancestor() 0 4 3
A count_descendants() 0 4 1
A get_node_info() 0 11 1
A qet_tree_sql() 0 22 2
A get_tree_data() 0 15 2
B display_list() 0 26 2
A recursively_close_tags() 0 7 2
A display_options() 0 22 2
A set_padding() 0 12 4
A get_padded_title() 0 4 2
A get_html_option() 0 5 2
1
<?php
2
/**
3
 *
4
 * @package sitemaker
5
 * @copyright (c) 2013 Daniel A. (blitze)
6
 * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7
 *
8
 */
9
10
namespace blitze\sitemaker\services\tree;
11
12
/**
13
* Display nested sets
14
*/
15
abstract class display
16
{
17
	/** @var \phpbb\db\driver\driver_interface */
18
	protected $db;
19
20
	/** @var string */
21
	protected $items_table;
22
23
	/** @var string */
24
	protected $pk;
25
26
	/** @var string */
27
	protected $sql_where;
28
29
	/**
30
	 * Column names in the table
31
	 * @var string
32
	 */
33
	protected $column_item_id = 'item_id';
34
	protected $column_left_id = 'left_id';
35
	protected $column_right_id = 'right_id';
36
	protected $column_parent_id = 'parent_id';
37
	protected $column_depth = 'depth';
38
39
	/** @var array */
40
	protected $errors = array();
41
42
	/** @var array */
43
	protected $data = array();
44
45
	/**
46
	* Construct
47
	*
48
	* @param \phpbb\db\driver\driver_interface		$db             Database connection
49
	* @param string									$items_table	Table name
50
	* @param string									$pk				Primary key
51
	* @param string									$sql_where		Column restriction
52
	*/
53 11
	public function __construct(\phpbb\db\driver\driver_interface $db, $items_table, $pk, $sql_where = '')
54
	{
55 11
		$this->db = $db;
56 11
		$this->pk = $pk;
57 11
		$this->items_table = $items_table;
58 11
		$this->sql_where = $sql_where;
59 11
	}
60
61
	/**
62
	 * Is subject node an ancestor of the object node?
63
	 *
64
	 * @param array $object
65
	 * @param array $subject
66
	 * @return bool
67
	 */
68 5
	public function is_ancestor(array $object, array $subject)
69
	{
70 5
		return ($subject[$this->column_left_id] < $object[$this->column_left_id] && $subject[$this->column_right_id] > $object[$this->column_right_id]) ? true : false;
71
	}
72
73
	/**
74
	 * Count node descendants
75
	 * @param array $row
76
	 * @return int
77
	 */
78 2
	public function count_descendants(array $row)
79
	{
80 2
		return (int) (($row[$this->column_right_id] - $row[$this->column_left_id] - 1) / 2);
81
	}
82
83
	/**
84
	 * Get node row
85
	 * @param int $node_id
86
	 * @return mixed
87
	 */
88 6
	public function get_node_info($node_id)
89
	{
90
		$sql = "SELECT *
91 6
			FROM $this->items_table
92 6
			WHERE $this->pk = " . (int) $node_id ;
93 6
		$result = $this->db->sql_query($sql);
94 6
		$row = $this->db->sql_fetchrow($result);
95 6
		$this->db->sql_freeresult($result);
96
97 6
		return $row;
98
	}
99
100
	/**
101
	 * Get Tree Query
102
	 *
103
	 * @param	integer	$start			Starting depth
104
	 * @param	integer $max_depth		Max depth
105
	 * @param	array	$sql_array		Array of elements to merge into query
106
	 * 										array(
107
	 * 											'SELECT'	=> array('p.*'),
108
	 * 											'WHERE'		=> array('p.post_id = 2'),
109
	 * 										)
110
	 * @return	array
111
	 */
112 3
	public function qet_tree_sql($start = 0, $max_depth = 0, $sql_array = array())
113
	{
114 3
		$sql_array = array_merge_recursive(
115
			array(
116 3
				'SELECT'	=> array('i.*'),
117
				'FROM'		=> array(
118 3
					$this->items_table => 'i'
119 3
				),
120
				'WHERE'		=> array(
121 3
					'i.depth ' . (($max_depth) ? ' BETWEEN ' . (int) $start . ' AND ' . (int) ($start + $max_depth) : ' >= ' . (int) $start),
122 3
					$this->sql_where,
123 3
				),
124 3
				'ORDER_BY'	=> 'i.left_id ASC',
125 3
			),
126
			$sql_array
127 3
		);
128
129 3
		$sql_array['SELECT'] = join(', ', array_filter($sql_array['SELECT']));
130 3
		$sql_array['WHERE'] = join(' AND ', array_filter($sql_array['WHERE']));
131
132 3
		return $sql_array;
133
	}
134
135
	/**
136
	 * Get the tree data
137
	 *
138
	 * @param	integer	$start			Starting depth
139
	 * @param	integer $max_depth		Max depth
140
	 * @param	array	$sql_array		Array of elements to merge into query
141
	 * 										array(
142
	 * 											'SELECT'	=> array('p.*'),
143
	 * 											'WHERE'		=> array('p.post_id = 2'),
144
	 * 										)
145
	 * @return array
146
	 */
147 3
	public function get_tree_data($start = 0, $max_depth = 0, $sql_array = array())
148
	{
149 3
		$sql_array = $this->qet_tree_sql($start, $max_depth, $sql_array);
150 3
		$sql = $this->db->sql_build_query('SELECT', $sql_array);
151 3
		$result = $this->db->sql_query($sql);
152
153 3
		$data = array();
154 3
		while ($row = $this->db->sql_fetchrow($result))
155
		{
156 3
			$data[$row[$this->pk]] = $row;
157 3
		}
158 3
		$this->db->sql_freeresult($result);
159
160 3
		return $data;
161
	}
162
163
	/**
164
	 * @param array $data
165
	 * @param \phpbb\template\twig\twig $template
166
	 * @param string $handle
167
	 */
168
	public function display_list(array $data, \phpbb\template\twig\twig &$template, $handle = 'tree')
169
	{
170
		$prev_depth = 0;
171
		$parental_depth = array(0 => -1);
172
		$data = array_values($data);
173
174
		for ($i = 0, $size = sizeof($data); $i < $size; $i++)
175
		{
176
			$row 		= $data[$i];
177
			$this_depth	= $parental_depth[$row[$this->column_parent_id]] + 1;
178
			$repeat		= abs($prev_depth - $this_depth);
179
180
			$tpl_data	= array(
181
				'PREV_DEPTH'	=> $prev_depth,
182
				'THIS_DEPTH'	=> $this_depth,
183
				'NUM_KIDS'		=> $this->count_descendants($row),
184
			);
185
186
			$template->assign_block_vars($handle, array_merge($tpl_data, array_change_key_case($row, CASE_UPPER)));
187
			$this->recursively_close_tags($repeat, $handle . '.close', $template);
188
189
			$prev_depth = $this_depth;
190
			$parental_depth[$row[$this->pk]] = $this_depth;
191
		}
192
		$this->recursively_close_tags($prev_depth, 'close_' . $handle, $template);
193
	}
194
195
	/**
196
	 * @param int $repeat
197
	 * @param string $handle
198
	 * @param \phpbb\template\twig\twig $template
199
	 * @return void
200
	 */
201
	protected function recursively_close_tags($repeat, $handle, \phpbb\template\twig\twig &$template)
202
	{
203
		for ($i = 0; $i < $repeat; $i++)
204
		{
205
			$template->assign_block_vars('close_' . $handle, array());
206
		}
207
	}
208
209
	/**
210
	 * Get tree as form options or data
211
	 *
212
	 * @param	array	$db_data	Raw tree data from database
213
	 * @param	string	$title_column	Database column name to use as label/title for each item
214
	 * @param	array	$selected_ids	Array of selected items
215
	 * @param	string	$return_mode	options | data
216
	 * @param	string	$pad_with		Character used to denote nesting
217
	 *
218
	 * @return	mixed	Returns array of padded titles or html string of options depending on $return_mode
219
	 */
220 3
	public function display_options($db_data, $title_column, $selected_ids = array(), $return_mode = 'options', $pad_with = '&nbsp;&nbsp;&nbsp;')
221
	{
222 3
		$right = 0;
223 3
		$padding = '';
224 3
		$padding_store = array('0' => '');
225 3
		$return = array('options' => '', 'data' => array());
226
227 3
		$db_data = array_values($db_data);
228 3
		for ($i = 0, $size = sizeof($db_data); $i < $size; $i++)
229
		{
230 3
			$row = $db_data[$i];
231
232 3
			$this->set_padding($padding, $pad_with, $row, $padding_store, $right);
233
234 3
			$right = $row[$this->column_right_id];
235 3
			$title = $this->get_padded_title($padding, $row[$title_column]);
236 3
			$return['options'] .= $this->get_html_option($row, $selected_ids, $title);
237 3
			$return['data'][$row[$this->pk]] = $title;
238 3
		}
239
240 3
		return $return[$return_mode];
241
	}
242
243
	/**
244
	 * @param string $padding
245
	 * @param string $pad_with
246
	 * @param array $row
247
	 * @param array $padding_store
248
	 * @param int $right
249
	 * @retur void
250
	 */
251 3
	protected function set_padding(&$padding, $pad_with, array $row, array $padding_store, $right)
252
	{
253 3
		if ($row[$this->column_left_id] < $right)
254 3
		{
255 3
			$padding .= $pad_with;
256 3
			$padding_store[$row[$this->column_parent_id]] = $padding;
257 3
		}
258 3
		else if ($row[$this->column_left_id] > $right + 1)
259 3
		{
260 3
			$padding = (isset($padding_store[$row[$this->column_parent_id]])) ? $padding_store[$row[$this->column_parent_id]] : '';
261 3
		}
262 3
	}
263
264
	/**
265
	 * @param string $padding
266
	 * @param string $title
267
	 * @return string
268
	 */
269 3
	protected function get_padded_title($padding, $title)
270
	{
271 3
		return (($padding) ? $padding . '&#x2937; ' : '') . $title;
272
	}
273
274
	/**
275
	 * @param array $row
276
	 * @param array $selected_ids
277
	 * @param string $title
278
	 * @return string
279
	 */
280 3
	protected function get_html_option(array $row, array $selected_ids, $title)
281
	{
282 3
		$selected = (in_array($row[$this->pk], $selected_ids)) ? ' selected="selected' : '';
283 3
		return '<option value="' . $row[$this->pk] . '"' . $selected . '>' . $title . '</option>';
284
	}
285
}
286