PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.0.3
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.0.3
5.12.1 5.12.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
ConsoleCommand 2 years ago Dimension 2 years ago API.php 2 years ago AggregatedMetric.php 2 years ago ArchivedMetric.php 2 years ago Archiver.php 2 years ago Categories.php 2 years ago ComponentFactory.php 2 years ago ComputedMetric.php 2 years ago ConsoleCommand.php 2 years ago Controller.php 2 years ago ControllerAdmin.php 2 years ago Dependency.php 2 years ago LogTablesProvider.php 2 years ago Manager.php 2 years ago Menu.php 2 years ago MetadataLoader.php 2 years ago Metric.php 2 years ago PluginException.php 2 years ago ProcessedMetric.php 2 years ago ReleaseChannels.php 2 years ago Report.php 2 years ago ReportsProvider.php 2 years ago RequestProcessors.php 2 years ago Segment.php 2 years ago SettingsProvider.php 2 years ago Tasks.php 2 years ago ThemeStyles.php 2 years ago ViewDataTable.php 2 years ago Visualization.php 2 years ago WidgetsProvider.php 2 years ago
Segment.php
405 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 *
9 */
10 namespace Piwik\Plugin;
11
12 use Exception;
13 use Piwik\Columns\Dimension;
14 use Piwik\Development;
15 /**
16 * Creates a new segment that can be used for instance within the {@link \Piwik\Columns\Dimension::configureSegment()}
17 * method. Make sure to set at least the following values: {@link setName()}, {@link setSegment()},
18 * {@link setSqlSegment()}, {@link setType()} and {@link setCategory()}. If you are using a segment in the context of a
19 * dimension the type and the SQL segment is usually set for you automatically.
20 *
21 * Example:
22 * ```
23 $segment = new \Piwik\Plugin\Segment();
24 $segment->setType(\Piwik\Plugin\Segment::TYPE_DIMENSION);
25 $segment->setName('General_EntryKeyword');
26 $segment->setCategory('General_Visit');
27 $segment->setSegment('entryKeyword');
28 $segment->setSqlSegment('log_visit.entry_keyword');
29 $segment->setAcceptedValues('Any keywords people search for on your website such as "help" or "imprint"');
30 ```
31 * @api
32 * @since 2.5.0
33 */
34 class Segment
35 {
36 /**
37 * Segment type 'dimension'. Can be used along with {@link setType()}.
38 * @api
39 */
40 const TYPE_DIMENSION = 'dimension';
41 /**
42 * Segment type 'metric'. Can be used along with {@link setType()}.
43 * @api
44 */
45 const TYPE_METRIC = 'metric';
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 private $needsMostFrequentValues = true;
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 * @ignore
68 */
69 public final function __construct()
70 {
71 $this->init();
72 }
73 /**
74 * @var Dimension
75 */
76 public $dimension;
77 /**
78 * Here you can initialize this segment and set any default values. It is called directly after the object is
79 * created.
80 * @api
81 */
82 protected function init()
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 * 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 * Set (overwrite) the segment display name. This name will be visible in the API and the UI. It should be a
109 * translation key such as 'Actions_ColumnEntryPageTitle' or 'Resolution_ColumnResolution'.
110 * @param string $name
111 * @api
112 */
113 public function setName($name)
114 {
115 $this->name = $name;
116 }
117 /**
118 * Set (overwrite) the name of the segment. The name should be lower case first and has to be unique. The segment
119 * name defined here needs to be set in the URL to actually apply this segment. Eg if the segment is 'searches'
120 * you need to set "&segment=searches>0" in the UI.
121 * @param string $segment
122 * @api
123 */
124 public function setSegment($segment)
125 {
126 $this->segment = $segment;
127 $this->check();
128 }
129 /**
130 * Sometimes you want users to set values that differ from the way they are actually stored. For instance if you
131 * want to allow to filter by any URL than you might have to resolve this URL to an action id. Or a country name
132 * maybe has to be mapped to a 2 letter country code. You can do this by specifying either a callable such as
133 * `array('Classname', 'methodName')` or by passing a closure. There will be four values passed to the given closure
134 * or callable: `string $valueToMatch`, `string $segment` (see {@link setSegment()}), `string $matchType`
135 * (eg SegmentExpression::MATCH_EQUAL or any other match constant of this class) and `$segmentName`.
136 *
137 * If the closure returns NULL, then Piwik assumes the segment sub-string will not match any visitor.
138 *
139 * @param callable $sqlFilter
140 * @api
141 */
142 public function setSqlFilter($sqlFilter)
143 {
144 $this->sqlFilter = $sqlFilter;
145 }
146 /**
147 * Similar to {@link setSqlFilter()} you can map a given segment value to another value. For instance you could map
148 * "new" to 0, 'returning' to 1 and any other value to '2'. You can either define a callable or a closure. There
149 * will be only one value passed to the closure or callable which contains the value a user has set for this
150 * segment. This callback is called shortly before {@link setSqlFilter()}.
151 * @param string|array $sqlFilterValue
152 * @api
153 */
154 public function setSqlFilterValue($sqlFilterValue)
155 {
156 $this->sqlFilterValue = $sqlFilterValue;
157 }
158 /**
159 * Defines to which column in the MySQL database the segment belongs: 'mytablename.mycolumnname'. Eg
160 * 'log_visit.idsite'. When a segment is applied the given or filtered value will be compared with this column.
161 *
162 * @param string $sqlSegment
163 * @api
164 */
165 public function setSqlSegment($sqlSegment)
166 {
167 $this->sqlSegment = $sqlSegment;
168 $this->check();
169 }
170 /**
171 * Set a list of segments that should be used instead of fetching the values from a single column.
172 * All set segments will be applied via an OR operator.
173 *
174 * @param array $segments
175 * @api
176 */
177 public function setUnionOfSegments($segments)
178 {
179 $this->unionOfSegments = $segments;
180 $this->check();
181 }
182 /**
183 * @return array
184 * @ignore
185 */
186 public function getUnionOfSegments()
187 {
188 return $this->unionOfSegments;
189 }
190 /**
191 * @return string
192 * @ignore
193 */
194 public function getSqlSegment()
195 {
196 return $this->sqlSegment;
197 }
198 /**
199 * @return string
200 * @ignore
201 */
202 public function getSqlFilterValue()
203 {
204 return $this->sqlFilterValue;
205 }
206 /**
207 * @return string
208 * @ignore
209 */
210 public function getAcceptValues()
211 {
212 return $this->acceptValues;
213 }
214 /**
215 * @return string
216 * @ignore
217 */
218 public function getSqlFilter()
219 {
220 return $this->sqlFilter;
221 }
222 /**
223 * Set (overwrite) the type of this segment which is usually either a 'dimension' or a 'metric'.
224 * @param string $type See constants TYPE_*
225 * @api
226 */
227 public function setType($type)
228 {
229 $this->type = $type;
230 }
231 /**
232 * @return string
233 * @ignore
234 */
235 public function getType()
236 {
237 return $this->type;
238 }
239 /**
240 * @return string
241 * @ignore
242 */
243 public function getName()
244 {
245 return $this->name;
246 }
247 /**
248 * @return string
249 * @ignore
250 */
251 public function getCategoryId()
252 {
253 return $this->category;
254 }
255 /**
256 * Returns the name of this segment as it should appear in segment expressions.
257 *
258 * @return string
259 */
260 public function getSegment()
261 {
262 return $this->segment;
263 }
264 /**
265 * @return string
266 * @ignore
267 */
268 public function getSuggestedValuesCallback()
269 {
270 return $this->suggestedValuesCallback;
271 }
272 /**
273 * Set callback which will be executed when user will call for suggested values for segment.
274 *
275 * @param callable $suggestedValuesCallback
276 */
277 public function setSuggestedValuesCallback($suggestedValuesCallback)
278 {
279 $this->suggestedValuesCallback = $suggestedValuesCallback;
280 }
281 /**
282 * @return string
283 * @ignore
284 */
285 public function getSuggestedValuesApi()
286 {
287 return $this->suggestedValuesApi;
288 }
289 /**
290 * Set callback which will be executed when user will call for suggested values for segment.
291 *
292 * @param string $suggestedValuesApi
293 */
294 public function setSuggestedValuesApi($suggestedValuesApi)
295 {
296 if (!empty($suggestedValuesApi) && is_string($suggestedValuesApi)) {
297 if (Development::isEnabled() && strpos($suggestedValuesApi, '.get') === false) {
298 throw new Exception('Invalid suggested values API defined, expecting ".get" to be present.');
299 }
300 } else {
301 $suggestedValuesApi = '';
302 }
303 $this->suggestedValuesApi = $suggestedValuesApi;
304 }
305 /**
306 * @param bool $value
307 */
308 public function setNeedsMostFrequentValues(bool $value)
309 {
310 $this->needsMostFrequentValues = $value;
311 }
312 /**
313 * You can restrict the access to this segment by passing a boolean `false`. For instance if you want to make
314 * a certain segment only available to users having super user access you could do the following:
315 * `$segment->setPermission(Piwik::hasUserSuperUserAccess());`
316 * @param bool $permission
317 * @api
318 */
319 public function setPermission($permission)
320 {
321 $this->permission = $permission;
322 }
323 /**
324 * @return array
325 * @ignore
326 */
327 public function toArray()
328 {
329 $segment = array('type' => $this->type, 'category' => $this->category, 'name' => $this->name, 'segment' => $this->segment, 'sqlSegment' => $this->sqlSegment, 'needsMostFrequentValues' => $this->needsMostFrequentValues);
330 if (!empty($this->unionOfSegments)) {
331 $segment['unionOfSegments'] = $this->unionOfSegments;
332 }
333 if (!empty($this->sqlFilter)) {
334 $segment['sqlFilter'] = $this->sqlFilter;
335 }
336 if (!empty($this->sqlFilterValue)) {
337 $segment['sqlFilterValue'] = $this->sqlFilterValue;
338 }
339 if (!empty($this->acceptValues)) {
340 $segment['acceptedValues'] = $this->acceptValues;
341 }
342 if (isset($this->permission)) {
343 $segment['permission'] = $this->permission;
344 }
345 if (is_callable($this->suggestedValuesCallback)) {
346 $segment['suggestedValuesCallback'] = $this->suggestedValuesCallback;
347 }
348 if (is_string($this->suggestedValuesApi) && !empty($this->suggestedValuesApi)) {
349 $segment['suggestedValuesApi'] = $this->suggestedValuesApi;
350 }
351 return $segment;
352 }
353 /**
354 * Returns true if this segment should only be visible to registered users (see API.getSegmentsMetadata),
355 * false if it should always be visible to any user (even the anonymous user).
356 *
357 * @return boolean
358 * @ignore
359 */
360 public function isRequiresRegisteredUser()
361 {
362 return $this->requiresRegisteredUser;
363 }
364 /**
365 * Sets whether the segment should only be visible to registered users. If set to false it will be even visible to
366 * the anonymous user
367 *
368 * @param boolean $requiresRegisteredUser
369 * @ignore
370 */
371 public function setRequiresRegisteredUser($requiresRegisteredUser)
372 {
373 $this->requiresRegisteredUser = $requiresRegisteredUser;
374 }
375 /**
376 * Sets whether the segment is for internal use only and should not be visible in the UI or in API metadata output.
377 * These types of segments are, for example, used in unions for other segments, but have no value to users.
378 *
379 * @param bool $value
380 */
381 public function setIsInternal($value)
382 {
383 $this->isInternalSegment = $value;
384 }
385 /**
386 * Gets whether the segment is for internal use only and should not be visible in the UI or in API metadata output.
387 * These types of segments are, for example, used in unions for other segments, but have no value to users.
388 *
389 * @return bool
390 */
391 public function isInternal()
392 {
393 return $this->isInternalSegment;
394 }
395 private function check()
396 {
397 if ($this->sqlSegment && $this->unionOfSegments) {
398 throw new Exception(sprintf('Union of segments and SQL segment is set for segment "%s", use only one of them', $this->name));
399 }
400 if ($this->segment && $this->unionOfSegments && in_array($this->segment, $this->unionOfSegments, true)) {
401 throw new Exception(sprintf('The segment %s contains a union segment to itself', $this->name));
402 }
403 }
404 }
405