Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
96.88% |
62 / 64 |
|
77.78% |
7 / 9 |
CRAP | |
0.00% |
0 / 1 |
data_access | |
96.88% |
62 / 64 |
|
77.78% |
7 / 9 |
19 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
get_bbcodes | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
get_smilies | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
get_styles | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
get_styles_templates | |
96.97% |
32 / 33 |
|
0.00% |
0 / 1 |
6 | |||
resolve_style_filename | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
4.05 | |||
get_censored_words | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
decode_rowset | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
fetch_decoded_rowset | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | namespace phpbb\textformatter; |
15 | |
16 | /** |
17 | * Data access layer that fetchs BBCodes, smilies and censored words from the database. |
18 | * To be extended to include insert/update/delete operations. |
19 | * |
20 | * Also used to get templates. |
21 | */ |
22 | class data_access |
23 | { |
24 | /** |
25 | * @var string Name of the BBCodes table |
26 | */ |
27 | protected $bbcodes_table; |
28 | |
29 | /** |
30 | * @var \phpbb\db\driver\driver_interface |
31 | */ |
32 | protected $db; |
33 | |
34 | /** |
35 | * @var string Name of the smilies table |
36 | */ |
37 | protected $smilies_table; |
38 | |
39 | /** |
40 | * @var string Name of the styles table |
41 | */ |
42 | protected $styles_table; |
43 | |
44 | /** |
45 | * @var string Path to the styles dir |
46 | */ |
47 | protected $styles_path; |
48 | |
49 | /** |
50 | * @var string Name of the words table |
51 | */ |
52 | protected $words_table; |
53 | |
54 | /** |
55 | * Constructor |
56 | * |
57 | * @param \phpbb\db\driver\driver_interface $db Database connection |
58 | * @param string $bbcodes_table Name of the BBCodes table |
59 | * @param string $smilies_table Name of the smilies table |
60 | * @param string $styles_table Name of the styles table |
61 | * @param string $words_table Name of the words table |
62 | * @param string $styles_path Path to the styles dir |
63 | */ |
64 | public function __construct(\phpbb\db\driver\driver_interface $db, $bbcodes_table, $smilies_table, $styles_table, $words_table, $styles_path) |
65 | { |
66 | $this->db = $db; |
67 | |
68 | $this->bbcodes_table = $bbcodes_table; |
69 | $this->smilies_table = $smilies_table; |
70 | $this->styles_table = $styles_table; |
71 | $this->words_table = $words_table; |
72 | |
73 | $this->styles_path = $styles_path; |
74 | } |
75 | |
76 | /** |
77 | * Return the list of custom BBCodes |
78 | * |
79 | * @return array |
80 | */ |
81 | public function get_bbcodes() |
82 | { |
83 | $sql = 'SELECT bbcode_match, bbcode_tpl FROM ' . $this->bbcodes_table; |
84 | |
85 | return $this->fetch_decoded_rowset($sql, ['bbcode_match']); |
86 | } |
87 | |
88 | /** |
89 | * Return the list of smilies |
90 | * |
91 | * @return array |
92 | */ |
93 | public function get_smilies() |
94 | { |
95 | // NOTE: smilies that are displayed on the posting page are processed first because they're |
96 | // typically the most used smilies and it ends up producing a slightly more efficient |
97 | // renderer |
98 | $sql = 'SELECT code, emotion, smiley_url, smiley_width, smiley_height |
99 | FROM ' . $this->smilies_table . ' |
100 | ORDER BY display_on_posting DESC'; |
101 | |
102 | return $this->fetch_decoded_rowset($sql, ['code', 'emotion', 'smiley_url']); |
103 | } |
104 | |
105 | /** |
106 | * Return the list of installed styles |
107 | * |
108 | * @return array |
109 | */ |
110 | protected function get_styles() |
111 | { |
112 | $sql = 'SELECT style_id, style_path, style_parent_id, bbcode_bitfield FROM ' . $this->styles_table; |
113 | |
114 | return $this->fetch_decoded_rowset($sql); |
115 | } |
116 | |
117 | /** |
118 | * Return the bbcode.html template for every installed style |
119 | * |
120 | * @return array 2D array. style_id as keys, each element is an array with a "template" element that contains the style's bbcode.html and a "bbcodes" element that contains the name of each BBCode that is to be stylised |
121 | */ |
122 | public function get_styles_templates() |
123 | { |
124 | $templates = array(); |
125 | |
126 | $bbcode_ids = array( |
127 | 'quote' => 0, |
128 | 'b' => 1, |
129 | 'i' => 2, |
130 | 'url' => 3, |
131 | 'img' => 4, |
132 | 'size' => 5, |
133 | 'color' => 6, |
134 | 'u' => 7, |
135 | 'code' => 8, |
136 | 'list' => 9, |
137 | '*' => 9, |
138 | 'email' => 10, |
139 | 'attachment' => 12, |
140 | ); |
141 | |
142 | $styles = array(); |
143 | foreach ($this->get_styles() as $row) |
144 | { |
145 | $styles[$row['style_id']] = $row; |
146 | } |
147 | |
148 | foreach ($styles as $style_id => $style) |
149 | { |
150 | $bbcodes = array(); |
151 | |
152 | // Collect the name of the BBCodes whose bit is set in the style's bbcode_bitfield |
153 | $template_bitfield = new \bitfield($style['bbcode_bitfield']); |
154 | foreach ($bbcode_ids as $bbcode_name => $bit) |
155 | { |
156 | if ($template_bitfield->get($bit)) |
157 | { |
158 | $bbcodes[] = $bbcode_name; |
159 | } |
160 | } |
161 | |
162 | $filename = $this->resolve_style_filename($styles, $style); |
163 | if ($filename === false) |
164 | { |
165 | // Ignore this style, it will use the default templates |
166 | continue; |
167 | } |
168 | |
169 | $templates[$style_id] = array( |
170 | 'bbcodes' => $bbcodes, |
171 | 'template' => file_get_contents($filename), |
172 | ); |
173 | } |
174 | |
175 | return $templates; |
176 | } |
177 | |
178 | /** |
179 | * Resolve inheritance for given style and return the path to their bbcode.html file |
180 | * |
181 | * @param array $styles Associative array of [style_id => style] containing all styles |
182 | * @param array $style Style for which we resolve |
183 | * @return string|bool Path to this style's bbcode.html, or FALSE |
184 | */ |
185 | protected function resolve_style_filename(array $styles, array $style) |
186 | { |
187 | // Look for a bbcode.html in this style's dir |
188 | $filename = $this->styles_path . $style['style_path'] . '/template/bbcode.html'; |
189 | if (file_exists($filename)) |
190 | { |
191 | return $filename; |
192 | } |
193 | |
194 | // Resolve using this style's parent |
195 | $parent_id = $style['style_parent_id']; |
196 | if ($parent_id && !empty($styles[$parent_id])) |
197 | { |
198 | return $this->resolve_style_filename($styles, $styles[$parent_id]); |
199 | } |
200 | |
201 | return false; |
202 | } |
203 | |
204 | /** |
205 | * Return the list of censored words |
206 | * |
207 | * @return array |
208 | */ |
209 | public function get_censored_words() |
210 | { |
211 | $sql = 'SELECT word, replacement FROM ' . $this->words_table; |
212 | |
213 | return $this->fetch_decoded_rowset($sql, ['word', 'replacement']); |
214 | } |
215 | |
216 | /** |
217 | * Decode HTML special chars in given rowset |
218 | * |
219 | * @param array $rows Original rowset |
220 | * @param array $columns List of columns to decode |
221 | * @return array Decoded rowset |
222 | */ |
223 | protected function decode_rowset(array $rows, array $columns) |
224 | { |
225 | foreach ($rows as &$row) |
226 | { |
227 | foreach ($columns as $column) |
228 | { |
229 | $row[$column] = html_entity_decode($row[$column], ENT_COMPAT); |
230 | } |
231 | } |
232 | |
233 | return $rows; |
234 | } |
235 | |
236 | /** |
237 | * Fetch all rows for given query and decode plain text columns |
238 | * |
239 | * @param string $sql SELECT query |
240 | * @param array $columns List of columns to decode |
241 | * @return array |
242 | */ |
243 | protected function fetch_decoded_rowset($sql, array $columns = []) |
244 | { |
245 | $result = $this->db->sql_query($sql); |
246 | $rows = $this->db->sql_fetchrowset($result); |
247 | $this->db->sql_freeresult($result); |
248 | |
249 | return $this->decode_rowset($rows, $columns); |
250 | } |
251 | } |