PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.0.5
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.0.5
5.13.0 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 / classes / WpMatomo / User / Sync.php
matomo / classes / WpMatomo / User Last commit date
Sync.php 6 years ago
Sync.php
228 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\User;
11
12 use Piwik\Access\Role\Admin;
13 use Piwik\Access\Role\View;
14 use Piwik\Access\Role\Write;
15 use Piwik\Auth\Password;
16 use Piwik\Common;
17 use Piwik\Date;
18 use Piwik\Plugin;
19 use Piwik\Plugins\LanguagesManager\API;
20 use Piwik\Plugins\UsersManager\Model;
21 use Piwik\Plugins\UsersManager;
22 use WpMatomo\Bootstrap;
23 use WpMatomo\Capabilities;
24 use WpMatomo\Logger;
25 use WpMatomo\Site;
26 use WpMatomo\User;
27
28 if ( ! defined( 'ABSPATH' ) ) {
29 exit; // if accessed directly
30 }
31
32 class Sync {
33 /**
34 * actually allowed is 100 characters...
35 * but we do -5 to have some room to append `wp_`.$login.XYZ if needed
36 */
37 const MAX_USER_NAME_LENGTH = 95;
38
39 /**
40 * @var Logger
41 */
42 private $logger;
43
44 public function __construct() {
45 $this->logger = new Logger();
46 }
47
48 public function register_hooks() {
49 add_action( 'add_user_role', array( $this, 'sync_current_users' ), $prio = 10, $args = 0 );
50 add_action( 'remove_user_role', array( $this, 'sync_current_users' ), $prio = 10, $args = 0 );
51 add_action( 'add_user_to_blog', array( $this, 'sync_current_users' ), $prio = 10, $args = 0 );
52 add_action( 'remove_user_from_blog', array( $this, 'sync_current_users' ), $prio = 10, $args = 0 );
53 add_action( 'user_register', array( $this, 'sync_current_users' ), $prio = 10, $args = 0 );
54 add_action( 'profile_update', array( $this, 'sync_current_users' ), $prio = 10, $args = 0 );
55 }
56
57 public function sync_all() {
58 if ( function_exists( 'is_multisite' ) && is_multisite() ) {
59 foreach ( get_sites() as $site ) {
60 switch_to_blog( $site->blog_id );
61
62 $idsite = Site::get_matomo_site_id( $site->blog_id );
63
64 try {
65 if ( $idsite ) {
66 $users = get_users( array( 'blog_id' => $site->blog_id ) );
67 $this->sync_users( $users, $idsite );
68 }
69 } catch ( \Exception $e ) {
70 // we don't want to rethrow exception otherwise some other blogs might never sync
71 $this->logger->log_exception( 'user_sync ', $e );
72 }
73
74 restore_current_blog();
75 }
76 } else {
77 $this->sync_current_users();
78 }
79 }
80
81 public function sync_current_users() {
82 $idsite = Site::get_matomo_site_id( get_current_blog_id() );
83 if ( $idsite ) {
84 $users = get_users();
85 $this->sync_users( $users, $idsite );
86 }
87 }
88
89 /**
90 * Sync all users. Make sure to always pass all sites that exist within a given site... you cannot just sync an individual
91 * user... we would delete all other users
92 *
93 * @param \WP_User[] $users
94 * @param $idsite
95 */
96 protected function sync_users( $users, $idsite ) {
97 Bootstrap::do_bootstrap();
98
99 $this->logger->log( 'Matomo will now sync ' . count( $users ) . ' users' );
100
101 $super_users = array();
102 $logins_with_some_view_access = array( 'anonmyous' ); // may or may not exist... we don't want to delete this user though
103 $user_model = new Model();
104
105 // need to make sure we recreate new instance later with latest dependencies in case they changed
106 API::unsetInstance();
107
108 foreach ( $users as $user ) {
109 $user_id = $user->ID;
110
111 // todo if we used transactions we could commit it after a possibly new access has been added
112 // to prevent UI preventing randomly saying no access between deleting and adding access
113
114 $mapped_matomo_login = User::get_matomo_user_login( $user_id );
115 if ( $mapped_matomo_login ) {
116 $user_model->deleteUserAccess( $mapped_matomo_login, array( $idsite ) );
117 }
118
119 $matomo_login = null;
120
121 if ( user_can( $user, Capabilities::KEY_SUPERUSER ) ) {
122 $matomo_login = $this->ensure_user_exists( $user );
123 $super_users[ $matomo_login ] = $user;
124 $logins_with_some_view_access[] = $matomo_login;
125 } elseif ( user_can( $user, Capabilities::KEY_ADMIN ) ) {
126 $matomo_login = $this->ensure_user_exists( $user );
127 $user_model->addUserAccess( $matomo_login, Admin::ID, array( $idsite ) );
128 $user_model->setSuperUserAccess( $matomo_login, false );
129 $logins_with_some_view_access[] = $matomo_login;
130 } elseif ( user_can( $user, Capabilities::KEY_WRITE ) ) {
131 $matomo_login = $this->ensure_user_exists( $user );
132 $user_model->addUserAccess( $matomo_login, Write::ID, array( $idsite ) );
133 $user_model->setSuperUserAccess( $matomo_login, false );
134 $logins_with_some_view_access[] = $matomo_login;
135 } elseif ( user_can( $user, Capabilities::KEY_VIEW ) ) {
136 $matomo_login = $this->ensure_user_exists( $user );
137 $user_model->addUserAccess( $matomo_login, View::ID, array( $idsite ) );
138 $user_model->setSuperUserAccess( $matomo_login, false );
139 $logins_with_some_view_access[] = $matomo_login;
140 }
141
142 if ( $matomo_login ) {
143 $locale = get_user_locale( $user->ID );
144 $parts = explode( '_', $locale );
145
146 if ( ! empty( $parts[0] ) ) {
147 $lang = $parts[0];
148 if ( Plugin\Manager::getInstance()->isPluginActivated( 'LanguagesManager' )
149 && Plugin\Manager::getInstance()->isPluginInstalled( 'LanguagesManager' )
150 && API::getInstance()->isLanguageAvailable( $lang ) ) {
151 $user_lang_model = new \Piwik\Plugins\LanguagesManager\Model();
152 $user_lang_model->setLanguageForUser( $matomo_login, $lang );
153 }
154 }
155 }
156 }
157
158 foreach ( $super_users as $matomo_login => $user ) {
159 $user_model->setSuperUserAccess( $matomo_login, true );
160 }
161
162 $logins_with_some_view_access = array_unique( $logins_with_some_view_access );
163 $all_users = $user_model->getUsers( array() );
164 foreach ( $all_users as $all_user ) {
165 if ( ! in_array( $all_user['login'], $logins_with_some_view_access, true )
166 && ! empty( $all_user['login'] ) ) {
167 $user_model->deleteUserOnly( $all_user['login'] );
168 }
169 }
170 }
171
172 /**
173 * @param \WP_User $wp_user
174 */
175 protected function ensure_user_exists( $wp_user ) {
176 $user_model = new Model();
177 $user_id = $wp_user->ID;
178 $login = $wp_user->user_login;
179
180 $matomo_user_login = User::get_matomo_user_login( $user_id );
181 $user_in_matomo = null;
182
183 if ( $matomo_user_login ) {
184 $user_in_matomo = $user_model->getUser( $matomo_user_login );
185 } else {
186 $login = substr( $login, 0, self::MAX_USER_NAME_LENGTH );
187
188 if ( ! $user_model->getUser( $login ) ) {
189 // username is available...
190 $matomo_user_login = $login;
191 } else {
192 // this username seems taken... lets create another one
193
194 $index = 0;
195 do {
196 if ( ! $index ) {
197 $matomo_user_login = 'wp_' . $login;
198 } else {
199 $matomo_user_login = 'wp_' . $login . $index;
200 }
201
202 $index ++;
203 } while ( $user_model->getUser( $matomo_user_login ) );
204 }
205 }
206
207 if ( ! $matomo_user_login || empty( $user_in_matomo ) ) {
208 $this->logger->log( 'Matomo is now creating a user forUserId ' . $user_id . ' with matomo login ' . $matomo_user_login );
209
210 $now = Date::now()->getDatetime();
211 $password = new Password();
212 // we generate some random password since log in using matomo won't be happening anyway
213 $password = $password->hash( $login . $now . Common::getRandomString( 200 ) . microtime( true ) . Common::generateUniqId() );
214
215 UsersManager\API::unsetInstance(); // make sure latest instance is loaded with all current dependencies... mainly needed for tests
216 $token = UsersManager\API::getInstance()->createTokenAuth( $login );
217 $user_model->addUser( $matomo_user_login, $password, $wp_user->user_email, $login, $token, $now );
218
219 User::map_matomo_user_login( $user_id, $matomo_user_login );
220 } elseif ( $user_in_matomo['email'] !== $wp_user->user_email ) {
221 $this->logger->log( 'Matomo is now updating the email for wpUserID ' . $user_id . ' matomo login ' . $matomo_user_login );
222 $user_model->updateUserFields( $matomo_user_login, array( 'email' => $wp_user->user_email ) );
223 }
224
225 return $matomo_user_login;
226 }
227 }
228