Group.php
См. документацию.
1 <?php
2 
3 /**
4  * @file
5  * @brief управление, получение, проверки данных групп пользователей
6  *
7  */
8 
9 
10 namespace Wrong\Rights;
11 
12 use Wrong\Curl\API;
14 use Wrong\Start\Env;
16 use Wrong\Auth\User;
18 
19 /**
20  * @brief Group класс, содержащий статические методы, используемые для управления группами пользователей.
21  *
22  */
23 
24 class Group
25 {
26  /** массив всех групп [id => name] */
27  public static $group_names = [];
28 
29  /** все группы */
30  public static $groups = []; // все группы
31 
32  /** все активные(включенные) группы */
33  public static $groups_active = [];
34 
35  /** все группы кроме системы */
36  public static $groups_not_system = [];
37 
38  /** все кроме гостей */
39  public static $groups_owners = [];
40 
41  /** все кроме гостей и системы */
42  public static $groups_users = [];
43 
44  /**
45  * Возвращает минимальный вес группы из массива групп
46  *
47  * @param array $arr массив идентификаторов групп
48  *
49  * @return int Минимальный вес группы из массива групп.
50  */
51  public static function min_weight($arr)
52  {
53  $w = [];
54  foreach (self::$groups as $row) {
55  if (in_array($row->id, $arr)) {
56  $w[] = $row->weight;
57  }
58  }
59  return $w ? min($w) : 0;
60  }
61 
62  /**
63  * Возвращает максимальный вес группы из массива групп
64  *
65  * @param array $arr массив идентификаторов групп
66  *
67  * @return int Максимальный вес группы из массива групп.
68  */
69  public static function max_weight($arr)
70  {
71  $w = [];
72  foreach (self::$groups as $row) {
73  if (in_array($row->id, $arr)) {
74  $w[] = $row->weight;
75  }
76  }
77  return $w ? max($w) : 0;
78  }
79 
80  /**
81  * Принимает массив идентификаторов групп и возвращает идентификатор группы с наибольшим весом.
82  *
83  * @param array $arr массив идентификаторов групп
84  *
85  * @return int Идентификатор группы с наибольшим весом.
86  */
87  public static function max_weight_group($arr)
88  {
89  $weight = 0;
90  $id = 0;
91  foreach (self::$groups as $row) {
92  if (in_array($row->id, $arr) && $row->weight > $weight) {
93  $weight = $row->weight;
94  $id = $row->id;
95  }
96  }
97  return $id;
98  }
99 
100  /**
101  * Принимает строку идентификаторов групп в формате JSON и возвращает список имен групп,
102  * разделенных запятыми.
103  *
104  * @param string $json_groups json массив имен групп
105  *
106  * @return string строка с группами
107  */
108  public static function groupNamesText($json_groups)
109  {
110  $arr = json_decode($json_groups, true);
111 
112  if (self::is_users($arr)) {
113  return 'Все авторизованные';
114  }
115 
116  if (self::is_not_system($arr)) {
117  return 'Все';
118  }
119 
120  $arr_keys = array_intersect(array_keys(self::$group_names), $arr);
121 
122  $text = implode(', ', array_map(function ($key) {
123  return self::text($key);
124  }, $arr_keys));
125 
126  return $text ?: 'Нет групп';
127  }
128 
129  /**
130  * Сортирует массив моделей по минимальному весу групп в каждой модели.
131  * Сортировка отдает первыми элементы с наибольшим минимальным весом групп в них
132  * @param array $arr массив моделей
133  *
134  * @return array отсортированный массив
135  */
136  public static function weightSort($arr)
137  {
138  if (count($arr) > 1) {
139  foreach ($arr as $key => $row) {
140  $arr[$key]->weight = Group::min_weight(json_decode($row->groups, true));
141  }
142  uasort($arr, function ($a, $b) {
143  if ($a->weight < $b->weight) {
144  return 1;
145  } else if ($a->weight > $b->weight) {
146  return -1;
147  } else {
148  if ($a->act < $b->act) {
149  return 1;
150  } else if ($a->act > $b->act) {
151  return -1;
152  } else {
153  if (self::row($a->owner_group)->weight > self::row($b->owner_group)->weight) {
154  return 1;
155  } else {
156  return -1;
157  }
158  }
159  }
160  });
161  }
162  return $arr;
163  }
164 
165  /**
166  * Проверяет доступность модели для текущего пользователя или если указан id пользователя
167  * (юзер состоит в группах доступа модели и она включена либо юзер является владельцем модели)
168  * функция не сравнивает наличие прав по весу подчиненных групп, проверяются только группы доступа модели и его владелец
169  * @param object $row проверяемая модель
170  * @param int $id опционально, если указан проверяет для данного id пользователя
171  *
172  * @return bool истинное означает наличие доступа к модели
173  */
174  public static function is_available_group($row, $id = null)
175  {
176  global $user;
177  if ($id) {
178  $user = new User($id);
179  }
180  return (bool) ((array_intersect($user->groups, json_decode($row->groups, true)) && $row->act) || ($user->id && in_array($row->owner_group, $user->groups)));
181  }
182 
183  /**
184  * получает все группы из базы данных и сохраняет их в статических свойствах класса.
185  */
186  public static function groups()
187  {
188  $dbh = Connect::getInstance()->dbh;
189  $obj = (object) [
190  'id' => 0,
191  'name' => 'Гости',
192  'owner_group' => 1,
193  'act' => 1,
194  'weight' => 0
195  ];
196  self::$groups[0] = $obj;
197  foreach ($dbh->query("SELECT * FROM `groups` ORDER BY `id` ASC")->fetchAll() as $row) {
198  self::$groups[] = $row;
199  }
200  self::$groups_active = array_filter(self::$groups, function ($row) {
201  return $row->act;
202  });
203  self::$groups_not_system = array_filter(self::$groups, function ($row) {
204  return $row->id != 1;
205  });
206  self::$groups_owners = array_filter(self::$groups, function ($row) {
207  return $row->id != 0;
208  });
209  self::$groups_users = array_filter(self::$groups, function ($row) {
210  return !in_array($row->id, [0, 1]);
211  });
212  self::$group_names = array_column(self::$groups, 'name', 'id');
213  }
214 
215  /**
216  * Возвращает true, если идентификатор группы находится в массиве идентификаторов активных групп.
217  *
218  * @param int $id Идентификатор группы.
219  *
220  * @return bool Логическиое исттинное если id группы найден
221  */
222  public static function is_active($id)
223  {
224  return in_array($id, array_column(self::$groups_active, 'id'));
225  }
226 
227  /**
228  * Возвращает название группы с заданным идентификатором или «В процессе удаления», если группа не
229  * существует.
230  *
231  * @param int $id Идентификатор группы.
232  */
233  public static function text($id)
234  {
235  return (array_column(self::$groups, 'name', 'id')[$id] ?: 'В процессе удаления') . ' [' . $id . ']';
236  }
237 
238  /**
239  * Перебирает массив объектов всех групп и возвращает объект с тем же идентификатором, что и переданный в id
240  *
241  * @param int $id Идентификатор группы, из которой вы хотите получить строку.
242  *
243  * @return object объект группы с переданным идентификатором.
244  */
245  public static function row($id)
246  {
247  foreach (self::$groups as $row) {
248  if ($row->id == $id) {
249  return $row;
250  }
251  }
252  }
253 
254  /**
255  * прверяет соответствует ли переданный массив групп, всем группам за исключением гостей и системы
256  *
257  * @param array $arr Массив идентификаторов групп для проверки
258  *
259  * @return bool|null Истинное означает успешную проверку
260  */
261  public static function is_users($arr)
262  {
263  if (count($arr) == count(self::$groups_users) && !array_diff(array_column(self::$groups_users, 'id'), $arr)) {
264  return true;
265  }
266  }
267 
268  /**
269  * прверяет соответствует ли переданный массив групп, всем группам за исключением системы
270  *
271  * @param array $arr Массив идентификаторов групп для проверки
272  *
273  * @return bool|null Истинное означает успешную проверку
274  */
275  public static function is_not_system($arr)
276  {
277  if (count($arr) == count(self::$groups_not_system) && !array_diff(array_column(self::$groups_not_system, 'id'), $arr)) {
278  return true;
279  }
280  }
281 
282 
283  /**
284  * обновляет в бд группы доступа для объекта
285  *
286  * @param int $id Идентификатор обновляемой строки
287  * @param array $arr Массив групп для установки.
288  * @param string $table_name Имя обновляемой таблицы
289  *
290  * @return int Количество строк, затронутых запросом.
291  */
292  public static function set_groups($id, $arr, $table_name)
293  {
294  $dbh = Connect::getInstance()->dbh;
295  $sth = $dbh->prepare("UPDATE {$table_name} SET `groups` = :groups WHERE `id` = :id");
296  $sth->bindValue(':groups', json_encode($arr));
297  $sth->bindValue(':id', $id);
298  $sth->execute();
299  return $sth->rowCount();
300  }
301 
302  /**
303  * обновляет идентификатор группы владельца для модели
304  *
305  * @param int $id Идентификатор обновляемой модели
306  * @param int $owner_group Идентификатор группы - владельца
307  * @param string $table_name Имя обновляемой таблицы
308  *
309  * @return int Количество строк, затронутых запросом.
310  */
311  public static function set_owner($id, $owner_group, $table_name)
312  {
313  $dbh = Connect::getInstance()->dbh;
314  $sth = $dbh->prepare("UPDATE {$table_name} SET `owner_group` = :owner_group WHERE `id` = :id");
315  $sth->bindValue(':owner_group', $owner_group);
316  $sth->bindValue(':id', $id);
317  $sth->execute();
318  return $sth->rowCount();
319  }
320 
321  /**
322  * Удаляет все модели, принадлежащие группе
323  *
324  * @param int $id Идентификатор группы, которую нужно удалить.
325  */
326  public static function delete_all_owner_models($id)
327  {
328  global $user;
329  $tables = ['actions', 'modals', 'selects', 'templates', 'pages', 'users', 'groups', 'crontabs'];
330  if (Env::$e->API && $user->api_act && $user->x_auth_token) {
331  $headers = ['X-Auth-Token: ' . $user->x_auth_token];
332  } else {
333  $headers = ['Cookie: ' . session_name() . '=' . session_id()];
334  }
335  foreach ($tables as $table) {
336  foreach (Controller::all($id, 'owner_group', $table) as $row) {
337  $data = http_build_query(['table' => $table, 'id' => $row->id, 'CSRF' => Env::$e->CSRF]);
338  session_write_close();
339  $res = API::req('/api/action/rm', 'POST', $data, $headers);
340  }
341  }
342  }
343 
344  /**
345  * подсчитывает количество записей в базе данных(моделей), принадлежащих определенной группе.
346  *
347  * @param int $id Идентификатор группы, для которой будут подсчитаны модели.
348  * @param bool $is_active Опциональная булевая для подсчета только активных моделей
349  *
350  * @return int Количество моделей, принадлежащих группе с данным идентификатором.
351  */
352  public static function count_all_owner_models($id, $is_active = false)
353  {
354  $tables = ['actions', 'modals', 'selects', 'templates', 'pages', 'users', 'groups', 'crontabs'];
355  $count = 0;
356  foreach ($tables as $table) {
357  $count += Controller::count($id, 'owner_group', $table, ($is_active ? 'AND `act` = 1' : ''));
358  }
359  return $count;
360  }
361 
362  /**
363  * подсчитывает количество записей в базе данных(моделей), с доступами определенной группы.
364  *
365  * @param int $id Идентификатор группы, для которой будут подсчитаны модели.
366  *
367  * @return int Количество моделей, в группах доступа которых есть данный идентификатор.
368  */
369  public static function count_all_available_models($id)
370  {
371  $dbh = Connect::getInstance()->dbh;
372  $tables = ['actions', 'modals', 'selects', 'templates', 'pages', 'users'];
373  $count = 0;
374  foreach ($tables as $table) {
375  foreach ($dbh->query("SELECT * FROM $table WHERE `owner_group` = $id OR `groups` LIKE '%$id%'") as $row) {
376  $count += (int) ($row->owner_group == $id || in_array($id, json_decode($row->groups)));
377  }
378  }
379  $count += Groups::count($id, 'owner_group');
380  return $count;
381  }
382 
383  /**
384  * Проверяет, принадлежит ли файл только одной группе или используется другими группами. Важно при удалении файлов группы.
385  *
386  * @param string $file Имя файла, который вы хотите проверить.
387  *
388  * @return bool Истинное означает что файл принадлежит лишь одной группе
389  */
390  public static function is_one_owner_file($file)
391  {
392  $dbh = Connect::getInstance()->dbh;
393  $tables = ['actions', 'modals', 'selects', 'templates', 'pages'];
394  $owners = [];
395  foreach ($tables as $table) {
396  $owners[] = $dbh->query("SELECT `owner_group` FROM `$table` WHERE `file` = '$file' LIMIT 1")->fetchColumn();
397  }
398  $owners = array_unique(array_filter($owners));
399  return count($owners) > 1 ? false : true;
400  }
401 }
if(!($row=Wrong\Models\Crontabs::find($_POST['id']))) if(! $user->access() ->write($row)) $sth
Definition: edit-cli.php:20
if($_POST['code']==file_get_contents($_SERVER['DOCUMENT_ROOT'] . $row->file)) $file
Definition: edit-code.php:30
if(!in_array($_POST['table'], Wrong\Database\Controller::$tables)) $table
Definition: filter.php:20
$res
if(! $response->_meta) $data
Definition: anycomment.php:18
User отвечает за работу с данными пользователя
Definition: User.php:21
API отвечает за http запросы к серверу
Definition: API.php:19
Connect создает подключение к базе данных
Definition: Connect.php:19
Controller контроллер для запросов к БД
Definition: Controller.php:17
Groups контроллер управления моделями групп пользователей, расширяет Controller.
Definition: Groups.php:21
Group класс, содержащий статические методы, используемые для управления группами пользователей.
Definition: Group.php:25
static weightSort($arr)
Definition: Group.php:136
static max_weight_group($arr)
Definition: Group.php:87
static is_not_system($arr)
Definition: Group.php:275
static $groups
Definition: Group.php:30
static count_all_available_models($id)
Definition: Group.php:369
static $groups_not_system
Definition: Group.php:36
static max_weight($arr)
Definition: Group.php:69
static is_users($arr)
Definition: Group.php:261
static $groups_users
Definition: Group.php:42
static groups()
Definition: Group.php:186
static min_weight($arr)
Definition: Group.php:51
static row($id)
Definition: Group.php:245
static set_groups($id, $arr, $table_name)
Definition: Group.php:292
static text($id)
Definition: Group.php:233
static set_owner($id, $owner_group, $table_name)
Definition: Group.php:311
static $group_names
Definition: Group.php:27
static is_one_owner_file($file)
Definition: Group.php:390
static $groups_owners
Definition: Group.php:39
static delete_all_owner_models($id)
Definition: Group.php:326
static is_available_group($row, $id=null)
Definition: Group.php:174
static groupNamesText($json_groups)
Definition: Group.php:108
static count_all_owner_models($id, $is_active=false)
Definition: Group.php:352
static $groups_active
Definition: Group.php:33
static is_active($id)
Definition: Group.php:222
Env класс управляющий, добавляющий или записывающий переменные среды
Definition: Env.php:17
$user
Definition: from-user.php:38
if(!($row=Wrong\Models\Crontabs::find($_GET['id']))) if($row->method=='CLI') $headers
$owner_group
Definition: edit-groups.php:15
if(!($row=Wrong\Database\Controller::find($_GET['id'], 'id', $_GET['table']))) $groups
Definition: edit-groups.php:14
$arr
Definition: actions.php:25
$table_name
Definition: actions.php:12
$dbh
Definition: session.php:19
if(preg_match('#//#', $request)) if($request !='/' &&preg_match('#/$#', $request)) if(preg_match('#index\.(php|html)$#', $request)) if(Wrong\Start\Env::$e->SYSTEM_CLOSED && $user->main_group_id !=1) if(preg_match('#^/api/(modal|action|select)/[a-z0-9\-]+#', $request, $matches)) if(isset($_GET['FROM_UID'])) if($request=='/' &&Wrong\Start\Env::$e->RETURN_TO_REQUEST && $user->id && $request !=$user->request && $user->request &&!isset($_GET['main'])) if(preg_match('#^/remind/([0-9]+)/([a-z0-9]+)#i', $request, $matches) &&Wrong\Auth\User::is_remind($matches[1], $matches[2])) if(preg_match('#^/email-confirm/([0-9]+)/([a-z0-9]+)#i', $request, $matches) &&Wrong\Auth\User::is_confirm($matches[1], $matches[2]) &&! $user->email_confirmed) if(Wrong\Start\Env::$e->EMAIL_CONFIRMATION && $user->id &&! $user->email_confirmed) if( $arr=Wrong\Models\Pages::all( $request, 'request'))
Definition: uri-router.php:129