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