PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.4.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.4.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 / classes / WpMatomo / API.php
matomo / classes / WpMatomo Last commit date
Admin 4 years ago Commands 5 years ago Db 4 years ago Ecommerce 5 years ago Report 6 years ago Site 5 years ago TrackingCode 4 years ago Updater 5 years ago User 5 years ago views 6 years ago API.php 5 years ago Access.php 6 years ago AjaxTracker.php 5 years ago Annotations.php 6 years ago Bootstrap.php 6 years ago Capabilities.php 6 years ago Compatibility.php 6 years ago Email.php 5 years ago Installer.php 5 years ago Logger.php 5 years ago OptOut.php 5 years ago Paths.php 6 years ago PrivacyBadge.php 6 years ago RedirectOnActivation.php 5 years ago Referral.php 6 years ago Roles.php 6 years ago ScheduledTasks.php 5 years ago Settings.php 4 years ago Site.php 6 years ago TrackingCode.php 5 years ago Uninstaller.php 6 years ago Updater.php 5 years ago User.php 6 years ago
API.php
233 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 * @package matomo
8 */
9
10 namespace WpMatomo;
11
12 use Piwik\API\Request;
13 use Piwik\Common;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // if accessed directly
17 }
18
19 class API {
20 const VERSION = 'matomo/v1';
21
22 const ROUTE_HIT = 'hit';
23
24 public function register_hooks() {
25 add_action( 'rest_api_init', array( $this, 'register_routes' ) );
26 }
27
28 public function register_routes() {
29 register_rest_route(
30 self::VERSION,
31 '/' . self::ROUTE_HIT . '/',
32 array(
33 'methods' => array( 'GET', 'POST' ),
34 'permission_callback' => '__return_true',
35 'callback' => array( $this, 'hit' ),
36 )
37 );
38 $this->register_route( 'API', 'getProcessedReport' );
39 $this->register_route( 'API', 'getReportMetadata' );
40 $this->register_route( 'API', 'getMatomoVersion' );
41 $this->register_route( 'API', 'getMetadata' );
42 $this->register_route( 'API', 'getSegmentsMetadata' );
43 $this->register_route( 'API', 'getWidgetMetadata' );
44 $this->register_route( 'API', 'getRowEvolution' );
45 $this->register_route( 'API', 'getSuggestedValuesForSegment' );
46 $this->register_route( 'API', 'getSettings' );
47 $this->register_route( 'Annotations', 'add' );
48 $this->register_route( 'Annotations', 'getAll' );
49 $this->register_route( 'CoreAdminHome', 'invalidateArchivedReports' );
50 $this->register_route( 'CoreAdminHome', 'runScheduledTasks' );
51 $this->register_route( 'Dashboard', 'getDashboards' );
52 $this->register_route( 'ImageGraph', 'get' );
53 $this->register_route( 'VisitsSummary', 'getVisits' );
54 $this->register_route( 'VisitsSummary', 'getUniqueVisitors' );
55 $this->register_route( 'LanguagesManager', 'getAvailableLanguages' );
56 $this->register_route( 'LanguagesManager', 'getAvailableLanguagesInfo' );
57 $this->register_route( 'LanguagesManager', 'getAvailableLanguageNames' );
58 $this->register_route( 'LanguagesManager', 'getLanguageForUser' );
59 $this->register_route( 'Live', 'getCounters' );
60 $this->register_route( 'Live', 'getLastVisitsDetails' );
61 $this->register_route( 'Live', 'getVisitorProfile' );
62 $this->register_route( 'Live', 'getMostRecentVisitorId' );
63 $this->register_route( 'PrivacyManager', 'deleteDataSubjects' );
64 $this->register_route( 'PrivacyManager', 'exportDataSubjects' );
65 $this->register_route( 'PrivacyManager', 'anonymizeSomeRawData' );
66 $this->register_route( 'ScheduledReports', 'getReports' );
67 $this->register_route( 'ScheduledReports', 'sendReport' );
68 $this->register_route( 'SegmentEditor', 'add' );
69 $this->register_route( 'SegmentEditor', 'update' );
70 $this->register_route( 'SegmentEditor', 'delete' );
71 $this->register_route( 'SegmentEditor', 'get' );
72 $this->register_route( 'SegmentEditor', 'getAll' );
73 $this->register_route( 'SitesManager', 'getAllSites' );
74 $this->register_route( 'SitesManager', 'getAllSitesId' );
75 $this->register_route( 'UsersManager', 'getUsers' );
76 $this->register_route( 'UsersManager', 'getUsersLogin' );
77 $this->register_route( 'UsersManager', 'getUser' );
78 $this->register_route( 'Goals', 'getGoals' );
79
80 // todo ideally we would make here work /goal/12345 to get goalId 12345
81 $this->register_route( 'Goals', 'getGoal' );
82 $this->register_route( 'Goals', 'addGoal' );
83 $this->register_route( 'Goals', 'updateGoal' );
84 $this->register_route( 'Goals', 'deleteGoal' );
85 }
86
87 public function hit() {
88 if ( empty( $_GET ) && empty( $_POST ) && empty( $_POST['idsite'] ) && empty( $_GET['idsite'] ) ) {
89 // todo if uploads dir is not writable, we may want to generate the matomo.js here and save it as an
90 // option... then we could also save it compressed
91 $paths = new Paths();
92 $path = $paths->get_matomo_js_upload_path();
93 header( 'Content-Type: application/javascript' );
94 header( 'Content-Length: ' . ( filesize( $path ) ) );
95 readfile( $paths->get_upload_base_dir() . '/matomo.js' ); // Reading the file into the output buffer
96 exit;
97 }
98 include_once plugin_dir_path( MATOMO_ANALYTICS_FILE ) . 'app/piwik.php';
99 exit;
100 }
101
102 public function execute_api_method( \WP_REST_Request $request ) {
103 $attributes = $request->get_attributes();
104 $method = $attributes['matomoModule'] . '.' . $attributes['matomoMethod'];
105
106 $with_idsite = true;
107
108 return $this->execute_request( $method, $with_idsite, $request->get_params() );
109 }
110
111 /**
112 * @param string $method
113 *
114 * @return string
115 * @internal
116 * for tests only
117 */
118 public function to_snake_case( $method ) {
119 preg_match_all( '!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $method, $matches );
120
121 $snake_case = $matches[0];
122
123 foreach ( $snake_case as &$match ) {
124 if ( strtoupper( $match ) === $match ) {
125 $match = strtolower( $match );
126 } else {
127 $match = lcfirst( $match );
128 }
129 }
130
131 return implode( '_', $snake_case );
132 }
133
134 /**
135 * @api
136 */
137 public function register_route( $api_module, $api_method ) {
138 $methods = array(
139 'get' => 'GET',
140 'edit' => 'PUT',
141 'update' => 'PUT',
142 'create' => 'POST',
143 'add' => 'POST',
144 'anonymize' => 'POST',
145 'invalidate' => 'POST',
146 'run' => 'POST',
147 'send' => 'POST',
148 'delete' => 'DELETE',
149 'remove' => 'DELETE',
150 );
151 $starts_with_keep_prefix = array( 'anonymize', 'invalidate', 'run', 'send' );
152
153 $method = 'GET';
154 $wp_api_module = $this->to_snake_case( $api_module );
155 $wp_api_action = $this->to_snake_case( $api_method );
156
157 foreach ( $methods as $method_starts_with => $method_to_use ) {
158 if ( strpos( $api_method, $method_starts_with ) === 0 ) {
159 $method = $method_to_use;
160 if ( ! in_array( $method_starts_with, $starts_with_keep_prefix, true ) ) {
161 $new_action = trim( ltrim( substr( $wp_api_action, strlen( $method_starts_with ) ), '_' ) );
162 if ( ! empty( $new_action ) ) {
163 $wp_api_action = $new_action;
164 }
165 }
166 break;
167 }
168 }
169
170 register_rest_route(
171 self::VERSION,
172 '/' . $wp_api_module . '/' . $wp_api_action . '/',
173 array(
174 'methods' => $method,
175 'callback' => array( $this, 'execute_api_method' ),
176 'permission_callback' => '__return_true', // permissions are checked in the method itself
177 'matomoModule' => $api_module,
178 'matomoMethod' => $api_method,
179 )
180 );
181 }
182
183 private function execute_request( $api_method, $with_idsite, $params ) {
184 if ( $with_idsite ) {
185 $site = new Site();
186 $idsite = $site->get_current_matomo_site_id();
187
188 if ( ! $idsite ) {
189 return new \WP_Error( 'Site not found. Make sure it is synced' );
190 }
191
192 $params['idSite'] = $idsite;
193 $params['idsite'] = $idsite;
194 $params['idsites'] = $idsite;
195 $params['idSites'] = $idsite;
196 }
197
198 // ensure user is authenticated through WordPress!
199 unset( $_GET['token_auth'] );
200 unset( $_POST['token_auth'] );
201
202 Bootstrap::do_bootstrap();
203
204 // refs https://github.com/matomo-org/wp-matomo/issues/370 ensuring segment will be used from default request when
205 // creating new request object and not the encoded segment
206 if (isset($params['segment'])) {
207 if (isset($_GET['segment']) || isset($_POST['segment'])) {
208 unset($params['segment']); // matomo will read the segment from default request
209 } elseif (!empty($params['segment']) && is_string($params['segment'])) {
210 // manually unsanitize this value
211 $params['segment'] = Common::unsanitizeInputValue($params['segment']);
212 }
213 }
214
215
216 try {
217 $result = Request::processRequest( $api_method, $params );
218 } catch ( \Exception $e ) {
219 $code = 'matomo_error';
220 if ( $e->getCode() ) {
221 $code .= '_' . $code;
222 }
223 if ( get_class( $e ) !== 'Exception' ) {
224 $code = str_replace( 'piwik', 'matomo', $this->to_snake_case( get_class( $e ) ) );
225 }
226
227 return new \WP_Error( $code, $e->getMessage() );
228 }
229
230 return $result;
231 }
232 }
233