PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.3.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.3.0
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 5 years ago API.php 5 years ago AggregatedMetric.php 5 years ago ArchivedMetric.php 5 years ago Archiver.php 5 years ago Categories.php 5 years ago ComponentFactory.php 5 years ago ComputedMetric.php 5 years ago ConsoleCommand.php 5 years ago Controller.php 5 years ago ControllerAdmin.php 5 years ago Dependency.php 5 years ago LogTablesProvider.php 5 years ago Manager.php 5 years ago Menu.php 5 years ago MetadataLoader.php 5 years ago Metric.php 5 years ago PluginException.php 5 years ago ProcessedMetric.php 5 years ago ReleaseChannels.php 5 years ago Report.php 5 years ago ReportsProvider.php 5 years ago RequestProcessors.php 5 years ago Segment.php 5 years ago SettingsProvider.php 5 years ago Tasks.php 5 years ago ThemeStyles.php 5 years ago ViewDataTable.php 5 years ago Visualization.php 5 years ago WidgetsProvider.php 5 years ago
Segment.php
440 lines
1 <?php
2 /**
3 * Matomo - 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 a registered user (see API.getSegmentsMetadata).
62 *
63 * @var bool
64 */
65 private $requiresRegisteredUser = false;
66
67 /**
68 * @ignore
69 */
70 final public function __construct()
71 {
72 $this->init();
73 }
74
75 /**
76 * Here you can initialize this segment and set any default values. It is called directly after the object is
77 * created.
78 * @api
79 */
80 protected function init()
81 {
82 }
83
84 /**
85 * Here you should explain which values are accepted/useful for your segment, for example:
86 * "1, 2, 3, etc." or "comcast.net, proxad.net, etc.". If the value needs any special encoding you should mention
87 * this as well. For example "Any URL including protocol. The URL must be URL encoded."
88 *
89 * @param string $acceptedValues
90 * @api
91 */
92 public function setAcceptedValues($acceptedValues)
93 {
94 $this->acceptValues = $acceptedValues;
95 }
96
97 /**
98 * Set (overwrite) the category this segment belongs to. It should be a translation key such as 'General_Actions'
99 * or 'General_Visit'.
100 * @param string $category
101 * @api
102 */
103 public function setCategory($category)
104 {
105 $this->category = $category;
106 }
107
108 /**
109 * Set (overwrite) the segment display name. This name will be visible in the API and the UI. It should be a
110 * translation key such as 'Actions_ColumnEntryPageTitle' or 'Resolution_ColumnResolution'.
111 * @param string $name
112 * @api
113 */
114 public function setName($name)
115 {
116 $this->name = $name;
117 }
118
119 /**
120 * Set (overwrite) the name of the segment. The name should be lower case first and has to be unique. The segment
121 * name defined here needs to be set in the URL to actually apply this segment. Eg if the segment is 'searches'
122 * you need to set "&segment=searches>0" in the UI.
123 * @param string $segment
124 * @api
125 */
126 public function setSegment($segment)
127 {
128 $this->segment = $segment;
129 $this->check();
130 }
131
132 /**
133 * Sometimes you want users to set values that differ from the way they are actually stored. For instance if you
134 * want to allow to filter by any URL than you might have to resolve this URL to an action id. Or a country name
135 * maybe has to be mapped to a 2 letter country code. You can do this by specifying either a callable such as
136 * `array('Classname', 'methodName')` or by passing a closure. There will be four values passed to the given closure
137 * or callable: `string $valueToMatch`, `string $segment` (see {@link setSegment()}), `string $matchType`
138 * (eg SegmentExpression::MATCH_EQUAL or any other match constant of this class) and `$segmentName`.
139 *
140 * If the closure returns NULL, then Piwik assumes the segment sub-string will not match any visitor.
141 *
142 * @param string|\Closure $sqlFilter
143 * @api
144 */
145 public function setSqlFilter($sqlFilter)
146 {
147 $this->sqlFilter = $sqlFilter;
148 }
149
150 /**
151 * Similar to {@link setSqlFilter()} you can map a given segment value to another value. For instance you could map
152 * "new" to 0, 'returning' to 1 and any other value to '2'. You can either define a callable or a closure. There
153 * will be only one value passed to the closure or callable which contains the value a user has set for this
154 * segment. This callback is called shortly before {@link setSqlFilter()}.
155 * @param string|array $sqlFilterValue
156 * @api
157 */
158 public function setSqlFilterValue($sqlFilterValue)
159 {
160 $this->sqlFilterValue = $sqlFilterValue;
161 }
162
163 /**
164 * Defines to which column in the MySQL database the segment belongs: 'mytablename.mycolumnname'. Eg
165 * 'log_visit.idsite'. When a segment is applied the given or filtered value will be compared with this column.
166 *
167 * @param string $sqlSegment
168 * @api
169 */
170 public function setSqlSegment($sqlSegment)
171 {
172 $this->sqlSegment = $sqlSegment;
173 $this->check();
174 }
175
176 /**
177 * Set a list of segments that should be used instead of fetching the values from a single column.
178 * All set segments will be applied via an OR operator.
179 *
180 * @param array $segments
181 * @api
182 */
183 public function setUnionOfSegments($segments)
184 {
185 $this->unionOfSegments = $segments;
186 $this->check();
187 }
188
189 /**
190 * @return array
191 * @ignore
192 */
193 public function getUnionOfSegments()
194 {
195 return $this->unionOfSegments;
196 }
197
198 /**
199 * @return string
200 * @ignore
201 */
202 public function getSqlSegment()
203 {
204 return $this->sqlSegment;
205 }
206
207 /**
208 * @return string
209 * @ignore
210 */
211 public function getSqlFilterValue()
212 {
213 return $this->sqlFilterValue;
214 }
215
216 /**
217 * @return string
218 * @ignore
219 */
220 public function getAcceptValues()
221 {
222 return $this->acceptValues;
223 }
224
225 /**
226 * @return string
227 * @ignore
228 */
229 public function getSqlFilter()
230 {
231 return $this->sqlFilter;
232 }
233
234 /**
235 * Set (overwrite) the type of this segment which is usually either a 'dimension' or a 'metric'.
236 * @param string $type See constansts TYPE_*
237 * @api
238 */
239 public function setType($type)
240 {
241 $this->type = $type;
242 }
243
244 /**
245 * @return string
246 * @ignore
247 */
248 public function getType()
249 {
250 return $this->type;
251 }
252
253 /**
254 * @return string
255 * @ignore
256 */
257 public function getName()
258 {
259 return $this->name;
260 }
261
262 /**
263 * @return string
264 * @ignore
265 */
266 public function getCategoryId()
267 {
268 return $this->category;
269 }
270
271 /**
272 * Returns the name of this segment as it should appear in segment expressions.
273 *
274 * @return string
275 */
276 public function getSegment()
277 {
278 return $this->segment;
279 }
280
281 /**
282 * @return string
283 * @ignore
284 */
285 public function getSuggestedValuesCallback()
286 {
287 return $this->suggestedValuesCallback;
288 }
289
290 /**
291 * Set callback which will be executed when user will call for suggested values for segment.
292 *
293 * @param callable $suggestedValuesCallback
294 */
295 public function setSuggestedValuesCallback($suggestedValuesCallback)
296 {
297 $this->suggestedValuesCallback = $suggestedValuesCallback;
298 }
299
300 /**
301 * @return string
302 * @ignore
303 */
304 public function getSuggestedValuesApi()
305 {
306 return $this->suggestedValuesApi;
307 }
308
309 /**
310 * Set callback which will be executed when user will call for suggested values for segment.
311 *
312 * @param string $suggestedValuesApi
313 */
314 public function setSuggestedValuesApi($suggestedValuesApi)
315 {
316 if (!empty($suggestedValuesApi) && is_string($suggestedValuesApi)) {
317 if (Development::isEnabled() && strpos($suggestedValuesApi, '.get') === false) {
318 throw new Exception('Invalid suggested values API defined, expecting ".get" to be present.');
319 }
320 } else {
321 $suggestedValuesApi = '';
322 }
323 $this->suggestedValuesApi = $suggestedValuesApi;
324 }
325
326 /**
327 * You can restrict the access to this segment by passing a boolean `false`. For instance if you want to make
328 * a certain segment only available to users having super user access you could do the following:
329 * `$segment->setPermission(Piwik::hasUserSuperUserAccess());`
330 * @param bool $permission
331 * @api
332 */
333 public function setPermission($permission)
334 {
335 $this->permission = $permission;
336 }
337
338 /**
339 * @return array
340 * @ignore
341 */
342 public function toArray()
343 {
344 $segment = array(
345 'type' => $this->type,
346 'category' => $this->category,
347 'name' => $this->name,
348 'segment' => $this->segment,
349 'sqlSegment' => $this->sqlSegment,
350 );
351
352 if (!empty($this->unionOfSegments)) {
353 $segment['unionOfSegments'] = $this->unionOfSegments;
354 }
355
356 if (!empty($this->sqlFilter)) {
357 $segment['sqlFilter'] = $this->sqlFilter;
358 }
359
360 if (!empty($this->sqlFilterValue)) {
361 $segment['sqlFilterValue'] = $this->sqlFilterValue;
362 }
363
364 if (!empty($this->acceptValues)) {
365 $segment['acceptedValues'] = $this->acceptValues;
366 }
367
368 if (isset($this->permission)) {
369 $segment['permission'] = $this->permission;
370 }
371
372 if (is_callable($this->suggestedValuesCallback)) {
373 $segment['suggestedValuesCallback'] = $this->suggestedValuesCallback;
374 }
375
376 if (is_string($this->suggestedValuesApi) && !empty($this->suggestedValuesApi)) {
377 $segment['suggestedValuesApi'] = $this->suggestedValuesApi;
378 }
379
380 return $segment;
381 }
382
383 /**
384 * Returns true if this segment should only be visible to registered users (see API.getSegmentsMetadata),
385 * false if it should always be visible to any user (even the anonymous user).
386 *
387 * @return boolean
388 * @ignore
389 */
390 public function isRequiresRegisteredUser()
391 {
392 return $this->requiresRegisteredUser;
393 }
394
395 /**
396 * Sets whether the segment should only be visible to registered users. If set to false it will be even visible to
397 * the anonymous user
398 *
399 * @param boolean $requiresRegisteredUser
400 * @ignore
401 */
402 public function setRequiresRegisteredUser($requiresRegisteredUser)
403 {
404 $this->requiresRegisteredUser = $requiresRegisteredUser;
405 }
406
407 /**
408 * Sets whether the segment is for internal use only and should not be visible in the UI or in API metadata output.
409 * These types of segments are, for example, used in unions for other segments, but have no value to users.
410 *
411 * @param bool $value
412 */
413 public function setIsInternal($value)
414 {
415 $this->isInternalSegment = $value;
416 }
417
418 /**
419 * Gets whether the segment is for internal use only and should not be visible in the UI or in API metadata output.
420 * These types of segments are, for example, used in unions for other segments, but have no value to users.
421 *
422 * @return bool
423 */
424 public function isInternal()
425 {
426 return $this->isInternalSegment;
427 }
428
429 private function check()
430 {
431 if ($this->sqlSegment && $this->unionOfSegments) {
432 throw new Exception(sprintf('Union of segments and SQL segment is set for segment "%s", use only one of them', $this->name));
433 }
434
435 if ($this->segment && $this->unionOfSegments && in_array($this->segment, $this->unionOfSegments, true)) {
436 throw new Exception(sprintf('The segment %s contains a union segment to itself', $this->name));
437 }
438 }
439 }
440