1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
projectaccesscodesprovider.php
См. документацию.
1<?php
2
3namespace Bitrix\Socialnetwork\Integration\UI\EntitySelector;
4
5use Bitrix\Main\Access\AccessCode;
6use Bitrix\Main\Localization\Loc;
7use Bitrix\Main\Type\Collection;
8use Bitrix\Socialnetwork\EO_Workgroup;
9use Bitrix\Socialnetwork\Item\Workgroup\Type;
10use Bitrix\UI\EntitySelector\BaseProvider;
11use Bitrix\UI\EntitySelector\Dialog;
12use Bitrix\UI\EntitySelector\Item;
13use Bitrix\UI\EntitySelector\RecentItem;
14use Bitrix\UI\EntitySelector\SearchQuery;
15use Bitrix\UI\EntitySelector\Tab;
16
18{
19 private const ENTITY_ID = 'project-access-codes';
20 private const TAB_ID = self::ENTITY_ID;
21 private const RECENT_LIMIT = 30;
22 private const FILL_LIMIT = self::RECENT_LIMIT;
23 private const SEARCH_LIMIT = 100;
24
25 public function __construct(array $options = [])
26 {
27 parent::__construct();
28
29 $this->options['fillAccessCodesTab'] = true;
30 if (isset($options['fillAccessCodesTab']) && is_bool($options['fillAccessCodesTab']))
31 {
32 $this->options['fillAccessCodesTab'] = $options['fillAccessCodesTab'];
33 }
34
35 $this->options['fillRecentTab'] = null; // auto
36 if (isset($options['fillRecentTab']) && is_bool($options['fillRecentTab']))
37 {
38 $this->options['fillRecentTab'] = $options['fillRecentTab'];
39 }
40 }
41
42 public function isAvailable(): bool
43 {
44 return $GLOBALS['USER']->isAuthorized();
45 }
46
50 public function getItems(array $ids): array
51 {
52 $ids = array_map(strval(...), $ids);
53
54 $projectIdsToFetch = $this->getProjectIds($ids);
55 if (empty($projectIdsToFetch))
56 {
57 return [];
58 }
59
61 'projectId' => $projectIdsToFetch,
62 ]);
63 if ($projects->isEmpty())
64 {
65 return [];
66 }
67
68 $allProjectsRoles = [];
69 foreach ($projects as $project)
70 {
71 foreach ($this->makeFlatItems($project) as $role)
72 {
73 $allProjectsRoles[$role->getId()] = $role;
74 }
75 }
76
77 $items = [];
78 foreach ($ids as $originalId)
79 {
80 if (isset($allProjectsRoles[$originalId]))
81 {
82 $items[] = $allProjectsRoles[$originalId];
83 }
84 }
85
86 return $items;
87 }
88
89 private function getProjectIds(array $itemIds): array
90 {
91 $projectIds = [];
92 foreach ($itemIds as $id)
93 {
94 $accessCode = new AccessCode($id);
95 if ($accessCode->getEntityType() === AccessCode::TYPE_SOCNETGROUP)
96 {
97 $projectIds[] = $accessCode->getEntityId();
98 }
99 }
100
101 Collection::normalizeArrayValuesByInt($projectIds);
102
103 return $projectIds;
104 }
105
109 private function makeFlatItems(EO_Workgroup $project): array
110 {
111 $items = [];
112 foreach ($this->getProjectRoles($project) as $role => $roleName)
113 {
114 $items[] = new Item([
115 'id' => $this->makeId($project->getId(), $role),
116 'entityId' => self::ENTITY_ID,
117 'entityType' => ProjectProvider::makeProjectEntityType($project),
118 'avatar' => ProjectProvider::makeProjectAvatar($project),
119 'link' => $this->makeLink($project),
120 'title' => $project->requireName() . '. ' . $roleName,
121 'tabs' => [
122 self::TAB_ID,
123 ],
124 ]);
125 }
126
127 return $items;
128 }
129
130 private function makeId(int $projectId, string $role): string
131 {
132 return 'SG' . $projectId . '_' . $role;
133 }
134
135 private function makeLink(EO_Workgroup $project): string
136 {
137 $url = \Bitrix\Socialnetwork\Site\GroupUrl::get($project->getId(), $project->getType());
138 if ($project->requireType() !== Type::Collab->value)
139 {
140 $url .= 'card/';
141 }
142
143 return $url;
144 }
145
146 private function getProjectRoles(EO_Workgroup $project): array
147 {
148 $roles = $this->getProjectTypeToRolesMap()[$project->requireType()] ?? null;
149 if ($roles === null)
150 {
151 return $this->getProjectTypeToRolesMap()[Type::getDefault()->value];
152 }
153
154 return $roles;
155 }
156
157 private function getProjectTypeToRolesMap(): array
158 {
159 static $rolesMapCache = null;
160
161 // roles here are sorted from more specific to more generic, as last role could be used as root in a tree branch
162 $rolesMapCache ??= [
163 Type::Group->value => [
164 SONET_ROLES_OWNER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_GROUP_OWNER'),
165 SONET_ROLES_MODERATOR => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_GROUP_MODERATOR'),
166 SONET_ROLES_USER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_GROUP_USER'),
167 ],
168 Type::Project->value => [
169 SONET_ROLES_OWNER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_PROJECT_OWNER'),
170 SONET_ROLES_MODERATOR => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_PROJECT_MODERATOR'),
171 SONET_ROLES_USER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_PROJECT_USER'),
172 ],
173 Type::Scrum->value => [
174 SONET_ROLES_OWNER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_SCRUM_OWNER'),
175 SONET_ROLES_MODERATOR => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_SCRUM_MODERATOR'),
176 SONET_ROLES_USER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_SCRUM_USER'),
177 ],
178 Type::Collab->value => [
179 SONET_ROLES_OWNER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_COLLAB_OWNER'),
180 SONET_ROLES_MODERATOR => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_COLLAB_MODERATOR'),
181 SONET_ROLES_USER => Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_COLLAB_USER'),
182 ],
183 ];
184
185 return $rolesMapCache;
186 }
187
188 public function fillDialog(Dialog $dialog): void
189 {
190 $this->addAccessCodesTab($dialog);
191
192 $dialogHasOnlyThisEntity = count($dialog->getEntities()) === 1;
193
194 $fillRecentTab = (
195 $this->options['fillRecentTab'] === true ||
196 ($this->options['fillRecentTab'] !== false && $dialogHasOnlyThisEntity)
197 );
198
199 if ($fillRecentTab)
200 {
201 $this->fillRecentTab($dialog);
202 }
203
204 if ($this->getOption('fillAccessCodesTab'))
205 {
206 $this->fillAccessCodesTab($dialog);
207 }
208 }
209
210 private function addAccessCodesTab(Dialog $dialog): void
211 {
212 $icon =
213 'data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2223%22%20height%3D%2223%22%20'.
214 'fill%3D%22none%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cpath%20d%3D%22M11'.
215 '.934%202.213a.719.719%200%2001.719%200l3.103%201.79c.222.13.36.367.36.623V8.21a.719.71'.
216 '9%200%2001-.36.623l-3.103%201.791a.72.72%200%2001-.719%200L8.831%208.832a.719.719%200%'.
217 '2001-.36-.623V4.627c0-.257.138-.495.36-.623l3.103-1.791zM7.038%2010.605a.719.719%200%2'.
218 '001.719%200l3.103%201.792a.72.72%200%2001.359.622v3.583a.72.72%200%2001-.36.622l-3.102'.
219 '%201.792a.719.719%200%2001-.72%200l-3.102-1.791a.72.72%200%2001-.36-.623v-3.583c0-.257'.
220 '.138-.494.36-.622l3.103-1.792zM20.829%2013.02a.719.719%200%2000-.36-.623l-3.102-1.792a'.
221 '.719.719%200%2000-.72%200l-3.102%201.792a.72.72%200%2000-.36.622v3.583a.72.72%200%2000'.
222 '.36.622l3.103%201.792a.719.719%200%2000.719%200l3.102-1.791a.719.719%200%2000.36-.623v'.
223 '-3.583z%22%20fill%3D%22%23ABB1B8%22/%3E%3C/svg%3E';
224
225 $dialog->addTab(new Tab([
226 'id' => self::TAB_ID,
227 'title' => (string)Loc::getMessage('SOCNET_ENTITY_SELECTOR_PROJECT_ACCESS_CODES_TAB'),
228 'icon' => [
229 'default' => $icon,
230 'selected' => str_replace('ABB1B8', 'fff', $icon),
231 ]
232 ]));
233 }
234
235 private function fillRecentTab(Dialog $dialog): void
236 {
237 $howMuchLeftToFill = self::RECENT_LIMIT;
238 $recentItems = $dialog->getRecentItems()->getEntityItems(self::ENTITY_ID);
239
240 $howMuchLeftToFill -= count($recentItems);
241 if ($howMuchLeftToFill <= 0)
242 {
243 return;
244 }
245
246 $globalRecentItems = $dialog->getGlobalRecentItems()->getEntityItems(self::ENTITY_ID);
247 foreach ($globalRecentItems as $globalRecentItem)
248 {
249 if ($howMuchLeftToFill <= 0)
250 {
251 return;
252 }
253
254 $dialog->getRecentItems()->add($globalRecentItem);
255 $howMuchLeftToFill--;
256 }
257
258 if ($howMuchLeftToFill <= 0)
259 {
260 return;
261 }
262
263 $projects = ProjectProvider::getProjects([
264 'limit' => $howMuchLeftToFill,
265 ]);
266
267 foreach ($projects as $project)
268 {
269 foreach (array_keys($this->getProjectRoles($project)) as $role)
270 {
271 $dialog->getRecentItems()->add(
272 new RecentItem([
273 'id' => $this->makeId($project->getId(), $role),
274 'entityId' => self::ENTITY_ID,
275 ])
276 );
277 }
278 }
279 }
280
281 private function fillAccessCodesTab(Dialog $dialog): void
282 {
283 $projects = ProjectProvider::getProjects([
284 'limit' => self::FILL_LIMIT,
285 ]);
286
287 foreach ($projects as $project)
288 {
289 $roles = $this->getProjectRoles($project);
290
291 // select the most generic role possible, as it should include all the others as branches
292 $root = array_key_last($roles);
293
294 $rootItem = new Item([
295 'id' => $this->makeId($project->getId(), $root),
296 'entityId' => self::ENTITY_ID,
297 'title' => $project->requireName(),
298 'entityType' => ProjectProvider::makeProjectEntityType($project),
299 'avatar' => ProjectProvider::makeProjectAvatar($project),
300 'link' => $this->makeLink($project),
301 'tabs' => [
302 self::TAB_ID,
303 ],
304 ]);
305
306 foreach ($roles as $role => $roleName)
307 {
308 // yes, we include root here as well
309
310 $rootItem->addChild(new Item([
311 'id' => $this->makeId($project->getId(), $role),
312 'entityId' => self::ENTITY_ID,
313 'entityType' => ProjectProvider::makeProjectEntityType($project),
314 'title' => $project->requireName() . '. ' . $roleName,
315 'avatar' => ProjectProvider::makeProjectAvatar($project),
316 'link' => $this->makeLink($project),
317 'nodeOptions' => [
318 'title' => $roleName,
319 'supertitle' => '',
320 'avatar' => '',
321 'link' => '',
322 ]
323 ]));
324 }
325
326 $dialog->addItem($rootItem);
327 }
328 }
329
330 public function doSearch(SearchQuery $searchQuery, Dialog $dialog): void
331 {
332 $projects = ProjectProvider::getProjects([
333 'searchQuery' => $searchQuery->getQuery(),
334 'searchLimit' => self::SEARCH_LIMIT,
335 ]);
336
337 if ($projects->count() >= self::SEARCH_LIMIT)
338 {
339 $searchQuery->setCacheable(false);
340 }
341
342 $items = [];
343 foreach ($projects as $project)
344 {
345 $items = [...$items, ...$this->makeFlatItems($project)];
346 }
347
348 $dialog->addItems($items);
349 }
350}
Определения dialog.php:11
getOption(string $option, $defaultValue=null)
Определения baseprovider.php:48
setCacheable(bool $flag=true)
Определения searchquery.php:72
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$GLOBALS['____1690880296']
Определения license.php:1
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$items
Определения template.php:224
const SONET_ROLES_USER
Определения include.php:31
const SONET_ROLES_MODERATOR
Определения include.php:30
const SONET_ROLES_OWNER
Определения include.php:29
$url
Определения iframe.php:7