Completed
Push — develop ( ef0a0d...1387e8 )
by Daniel
09:04
created

display::display_options()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 2

Importance

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