PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.3.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.3.1
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Plugin / Segment.php
matomo / app / core / Plugin Last commit date
Dimension 6 years ago API.php 6 years ago AggregatedMetric.php 6 years ago ArchivedMetric.php 6 years ago Archiver.php 6 years ago Categories.php 6 years ago ComponentFactory.php 6 years ago ComputedMetric.php 6 years ago ConsoleCommand.php 6 years ago Controller.php 6 years ago ControllerAdmin.php 6 years ago Dependency.php 6 years ago LogTablesProvider.php 6 years ago Manager.php 6 years ago Menu.php 6 years ago MetadataLoader.php 6 years ago Metric.php 6 years ago PluginException.php 6 years ago ProcessedMetric.php 6 years ago ReleaseChannels.php 6 years ago Report.php 6 years ago ReportsProvider.php 6 years ago RequestProcessors.php 6 years ago Segment.php 6 years ago SettingsProvider.php 6 years ago Tasks.php 6 years ago ThemeStyles.php 6 years ago ViewDataTable.php 6 years ago Visualization.php 6 years ago WidgetsProvider.php 6 years ago
Segment.php
442 lines
1 <?php
2 /**
3 * Piwik - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9 namespace Piwik\Plugin;
10 use Exception;
11 use Piwik\Development;
12
13 /**
14 * Creates a new segment that can be used for instance within the {@link \Piwik\Columns\Dimension::configureSegment()}
15 * method. Make sure to set at least the following values: {@link setName()}, {@link setSegment()},
16 * {@link setSqlSegment()}, {@link setType()} and {@link setCategory()}. If you are using a segment in the context of a
17 * dimension the type and the SQL segment is usually set for you automatically.
18 *
19 * Example:
20 * ```
21 $segment = new \Piwik\Plugin\Segment();
22 $segment->setType(\Piwik\Plugin\Segment::TYPE_DIMENSION);
23 $segment->setName('General_EntryKeyword');
24 $segment->setCategory('General_Visit');
25 $segment->setSegment('entryKeyword');
26 $segment->setSqlSegment('log_visit.entry_keyword');
27 $segment->setAcceptedValues('Any keywords people search for on your website such as "help" or "imprint"');
28 ```
29 * @api
30 * @since 2.5.0
31 */
32 class Segment
33 {
34 /**
35 * Segment type 'dimension'. Can be used along with {@link setType()}.
36 * @api
37 */
38 const TYPE_DIMENSION = 'dimension';
39
40 /**
41 * Segment type 'metric'. Can be used along with {@link setType()}.
42 * @api
43 */
44 const TYPE_METRIC = 'metric';
45
46 private $type;
47 private $category;
48 private $name;
49 private $segment;
50 private $sqlSegment;
51 private $sqlFilter;
52 private $sqlFilterValue;
53 private $acceptValues;
54 private $permission;
55 private $suggestedValuesCallback;
56 private $unionOfSegments;
57 private $isInternalSegment = false;
58 private $suggestedValuesApi = '';
59
60 /**
61 * If true, this segment will only be visible to the user if the user has view access
62 * to one of the requested sites (see API.getSegmentsMetadata).
63 *
64 * @var bool
65 */
66 private $requiresAtLeastViewAccess = false;
67
68 /**
69 * @ignore
70 */
71 final public function __construct()
72 {
73 $this->init();
74 }
75
76 /**
77 * Here you can initialize this segment and set any default values. It is called directly after the object is
78 * created.
79 * @api
80 */
81 protected function init()
82 {
83 }
84
85 /**
86 * Here you should explain which values are accepted/useful for your segment, for example:
87 * "1, 2, 3, etc." or "comcast.net, proxad.net, etc.". If the value needs any special encoding you should mention
88 * this as well. For example "Any URL including protocol. The URL must be URL encoded."
89 *
90 * @param string $acceptedValues
91 * @api
92 */
93 public function setAcceptedValues($acceptedValues)
94 {
95 $this->acceptValues = $acceptedValues;
96 }
97
98 /**
99 * Set (overwrite) the category this segment belongs to. It should be a translation key such as 'General_Actions'
100 * or 'General_Visit'.
101 * @param string $category
102 * @api
103 */
104 public function setCategory($category)
105 {
106 $this->category = $category;
107 }
108
109 /**
110 * Set (overwrite) the segment display name. This name will be visible in the API and the UI. It should be a
111 * translation key such as 'Actions_ColumnEntryPageTitle' or 'Resolution_ColumnResolution'.
112 * @param string $name
113 * @api
114 */
115 public function setName($name)
116 {
117 $this->name = $name;
118 }
119
120 /**
121 * Set (overwrite) the name of the segment. The name should be lower case first and has to be unique. The segment
122 * name defined here needs to be set in the URL to actually apply this segment. Eg if the segment is 'searches'
123 * you need to set "&segment=searches>0" in the UI.
124 * @param string $segment
125 * @api
126 */
127 public function setSegment($segment)
128 {
129 $this->segment = $segment;
130 $this->check();
131 }
132
133 /**
134 * Sometimes you want users to set values that differ from the way they are actually stored. For instance if you
135 * want to allow to filter by any URL than you might have to resolve this URL to an action id. Or a country name
136 * maybe has to be mapped to a 2 letter country code. You can do this by specifing either a callable such as
137 * `array('Classname', 'methodName')` or by passing a closure. There will be four values passed to the given closure
138 * or callable: `string $valueToMatch`, `string $segment` (see {@link setSegment()}), `string $matchType`
139 * (eg SegmentExpression::MATCH_EQUAL or any other match constant of this class) and `$segmentName`.
140 *
141 * If the closure returns NULL, then Piwik assumes the segment sub-string will not match any visitor.
142 *
143 * @param string|\Closure $sqlFilter
144 * @api
145 */
146 public function setSqlFilter($sqlFilter)
147 {
148 $this->sqlFilter = $sqlFilter;
149 }
150
151 /**
152 * Similar to {@link setSqlFilter()} you can map a given segment value to another value. For instance you could map
153 * "new" to 0, 'returning' to 1 and any other value to '2'. You can either define a callable or a closure. There
154 * will be only one value passed to the closure or callable which contains the value a user has set for this
155 * segment. This callback is called shortly before {@link setSqlFilter()}.
156 * @param string|array $sqlFilterValue
157 * @api
158 */
159 public function setSqlFilterValue($sqlFilterValue)
160 {
161 $this->sqlFilterValue = $sqlFilterValue;
162 }
163
164 /**
165 * Defines to which column in the MySQL database the segment belongs: 'mytablename.mycolumnname'. Eg
166 * 'log_visit.idsite'. When a segment is applied the given or filtered value will be compared with this column.
167 *
168 * @param string $sqlSegment
169 * @api
170 */
171 public function setSqlSegment($sqlSegment)
172 {
173 $this->sqlSegment = $sqlSegment;
174 $this->check();
175 }
176
177 /**
178 * Set a list of segments that should be used instead of fetching the values from a single column.
179 * All set segments will be applied via an OR operator.
180 *
181 * @param array $segments
182 * @api
183 */
184 public function setUnionOfSegments($segments)
185 {
186 $this->unionOfSegments = $segments;
187 $this->check();
188 }
189
190 /**
191 * @return array
192 * @ignore
193 */
194 public function getUnionOfSegments()
195 {
196 return $this->unionOfSegments;
197 }
198
199 /**
200 * @return string
201 * @ignore
202 */
203 public function getSqlSegment()
204 {
205 return $this->sqlSegment;
206 }
207
208 /**
209 * @return string
210 * @ignore
211 */
212 public function getSqlFilterValue()
213 {
214 return $this->sqlFilterValue;
215 }
216
217 /**
218 * @return string
219 * @ignore
220 */
221 public function getAcceptValues()
222 {
223 return $this->acceptValues;
224 }
225
226 /**
227 * @return string
228 * @ignore
229 */
230 public function getSqlFilter()
231 {
232 return $this->sqlFilter;
233 }
234
235 /**
236 * Set (overwrite) the type of this segment which is usually either a 'dimension' or a 'metric'.
237 * @param string $type See constansts TYPE_*
238 * @api
239 */
240 public function setType($type)
241 {
242 $this->type = $type;
243 }
244
245 /**
246 * @return string
247 * @ignore
248 */
249 public function getType()
250 {
251 return $this->type;
252 }
253
254 /**
255 * @return string
256 * @ignore
257 */
258 public function getName()
259 {
260 return $this->name;
261 }
262
263 /**
264 * @return string
265 * @ignore
266 */
267 public function getCategoryId()
268 {
269 return $this->category;
270 }
271
272 /**
273 * Returns the name of this segment as it should appear in segment expressions.
274 *
275 * @return string
276 */
277 public function getSegment()
278 {
279 return $this->segment;
280 }
281
282 /**
283 * @return string
284 * @ignore
285 */
286 public function getSuggestedValuesCallback()
287 {
288 return $this->suggestedValuesCallback;
289 }
290
291 /**
292 * Set callback which will be executed when user will call for suggested values for segment.
293 *
294 * @param callable $suggestedValuesCallback
295 */
296 public function setSuggestedValuesCallback($suggestedValuesCallback)
297 {
298 $this->suggestedValuesCallback = $suggestedValuesCallback;
299 }
300
301 /**
302 * @return string
303 * @ignore
304 */
305 public function getSuggestedValuesApi()
306 {
307 return $this->suggestedValuesApi;
308 }
309
310 /**
311 * Set callback which will be executed when user will call for suggested values for segment.
312 *
313 * @param string $suggestedValuesApi
314 */
315 public function setSuggestedValuesApi($suggestedValuesApi)
316 {
317 if (!empty($suggestedValuesApi) && is_string($suggestedValuesApi)) {
318 if (Development::isEnabled() && strpos($suggestedValuesApi, '.get') === false) {
319 throw new Exception('Invalid suggested values API defined, expecting ".get" to be present.');
320 }
321 } else {
322 $suggestedValuesApi = '';
323 }
324 $this->suggestedValuesApi = $suggestedValuesApi;
325 }
326
327 /**
328 * You can restrict the access to this segment by passing a boolean `false`. For instance if you want to make
329 * a certain segment only available to users having super user access you could do the following:
330 * `$segment->setPermission(Piwik::hasUserSuperUserAccess());`
331 * @param bool $permission
332 * @api
333 */
334 public function setPermission($permission)
335 {
336 $this->permission = $permission;
337 }
338
339 /**
340 * @return array
341 * @ignore
342 */
343 public function toArray()
344 {
345 $segment = array(
346 'type' => $this->type,
347 'category' => $this->category,
348 'name' => $this->name,
349 'segment' => $this->segment,
350 'sqlSegment' => $this->sqlSegment,
351 );
352
353 if (!empty($this->unionOfSegments)) {
354 $segment['unionOfSegments'] = $this->unionOfSegments;
355 }
356
357 if (!empty($this->sqlFilter)) {
358 $segment['sqlFilter'] = $this->sqlFilter;
359 }
360
361 if (!empty($this->sqlFilterValue)) {
362 $segment['sqlFilterValue'] = $this->sqlFilterValue;
363 }
364
365 if (!empty($this->acceptValues)) {
366 $segment['acceptedValues'] = $this->acceptValues;
367 }
368
369 if (isset($this->permission)) {
370 $segment['permission'] = $this->permission;
371 }
372
373 if (is_callable($this->suggestedValuesCallback)) {
374 $segment['suggestedValuesCallback'] = $this->suggestedValuesCallback;
375 }
376
377 if (is_string($this->suggestedValuesApi) && !empty($this->suggestedValuesApi)) {
378 $segment['suggestedValuesApi'] = $this->suggestedValuesApi;
379 }
380
381 return $segment;
382 }
383
384 /**
385 * Returns true if this segment should only be visible to the user if the user has view access
386 * to one of the requested sites (see API.getSegmentsMetadata), false if it should always be
387 * visible to the user (even the anonymous user).
388 *
389 * @return boolean
390 * @ignore
391 */
392 public function isRequiresAtLeastViewAccess()
393 {
394 return $this->requiresAtLeastViewAccess;
395 }
396
397 /**
398 * Sets whether the segment should only be visible if the user requesting it has view access
399 * to one of the requested sites and if the user is not the anonymous user.
400 *
401 * @param boolean $requiresAtLeastViewAccess
402 * @ignore
403 */
404 public function setRequiresAtLeastViewAccess($requiresAtLeastViewAccess)
405 {
406 $this->requiresAtLeastViewAccess = $requiresAtLeastViewAccess;
407 }
408
409 /**
410 * Sets whether the segment is for internal use only and should not be visible in the UI or in API metadata output.
411 * These types of segments are, for example, used in unions for other segments, but have no value to users.
412 *
413 * @param bool $value
414 */
415 public function setIsInternal($value)
416 {
417 $this->isInternalSegment = $value;
418 }
419
420 /**
421 * Gets whether the segment is for internal use only and should not be visible in the UI or in API metadata output.
422 * These types of segments are, for example, used in unions for other segments, but have no value to users.
423 *
424 * @return bool
425 */
426 public function isInternal()
427 {
428 return $this->isInternalSegment;
429 }
430
431 private function check()
432 {
433 if ($this->sqlSegment && $this->unionOfSegments) {
434 throw new Exception(sprintf('Union of segments and SQL segment is set for segment "%s", use only one of them', $this->name));
435 }
436
437 if ($this->segment && $this->unionOfSegments && in_array($this->segment, $this->unionOfSegments, true)) {
438 throw new Exception(sprintf('The segment %s contains a union segment to itself', $this->name));
439 }
440 }
441 }
442