| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace BookStack\Actions; | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-25 19:30:50 +08:00
										 |  |  | use BookStack\Auth\Permissions\PermissionService; | 
					
						
							| 
									
										
										
										
											2020-11-22 08:17:45 +08:00
										 |  |  | use BookStack\Entities\Models\Entity; | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  | use Illuminate\Database\Eloquent\Builder; | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  | use Illuminate\Support\Collection; | 
					
						
							| 
									
										
										
										
											2021-09-26 22:48:22 +08:00
										 |  |  | use Illuminate\Support\Facades\DB; | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  | class TagRepo | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |     protected $tag; | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     protected $permissionService; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |     public function __construct(PermissionService $ps) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->permissionService = $ps; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |      * Start a query against all tags in the system. | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |     public function queryWithTotals(string $searchTerm, string $nameFilter): Builder | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |         $query = Tag::query() | 
					
						
							|  |  |  |             ->select([ | 
					
						
							|  |  |  |                 'name', | 
					
						
							|  |  |  |                 ($searchTerm || $nameFilter) ? 'value' : DB::raw('COUNT(distinct value) as `values`'), | 
					
						
							|  |  |  |                 DB::raw('COUNT(id) as usages'), | 
					
						
							|  |  |  |                 DB::raw('SUM(IF(entity_type = \'BookStack\\\\Page\', 1, 0)) as page_count'), | 
					
						
							|  |  |  |                 DB::raw('SUM(IF(entity_type = \'BookStack\\\\Chapter\', 1, 0)) as chapter_count'), | 
					
						
							|  |  |  |                 DB::raw('SUM(IF(entity_type = \'BookStack\\\\Book\', 1, 0)) as book_count'), | 
					
						
							|  |  |  |                 DB::raw('SUM(IF(entity_type = \'BookStack\\\\BookShelf\', 1, 0)) as shelf_count'), | 
					
						
							|  |  |  |             ]) | 
					
						
							| 
									
										
										
										
											2021-11-16 03:00:37 +08:00
										 |  |  |             ->orderBy($nameFilter ? 'value' : 'name'); | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($nameFilter) { | 
					
						
							|  |  |  |             $query->where('name', '=', $nameFilter); | 
					
						
							| 
									
										
										
										
											2021-11-16 03:00:37 +08:00
										 |  |  |             $query->groupBy('value'); | 
					
						
							| 
									
										
										
										
											2021-11-16 20:29:50 +08:00
										 |  |  |         } elseif ($searchTerm) { | 
					
						
							| 
									
										
										
										
											2021-11-16 03:00:37 +08:00
										 |  |  |             $query->groupBy('name', 'value'); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $query->groupBy('name'); | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($searchTerm) { | 
					
						
							| 
									
										
										
										
											2021-11-07 06:00:33 +08:00
										 |  |  |             $query->where(function (Builder $query) use ($searchTerm) { | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |                 $query->where('name', 'like', '%' . $searchTerm . '%') | 
					
						
							|  |  |  |                     ->orWhere('value', 'like', '%' . $searchTerm . '%'); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |      * Get tag name suggestions from scanning existing tag names. | 
					
						
							| 
									
										
										
										
											2016-06-04 22:37:28 +08:00
										 |  |  |      * If no search term is given the 50 most popular tag names are provided. | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  |     public function getNameSuggestions(?string $searchTerm): Collection | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |         $query = Tag::query() | 
					
						
							| 
									
										
										
										
											2021-03-15 03:52:07 +08:00
										 |  |  |             ->select('*', DB::raw('count(*) as count')) | 
					
						
							|  |  |  |             ->groupBy('name'); | 
					
						
							| 
									
										
										
										
											2016-06-04 22:37:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($searchTerm) { | 
					
						
							|  |  |  |             $query = $query->where('name', 'LIKE', $searchTerm . '%')->orderBy('name', 'desc'); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $query = $query->orderBy('count', 'desc')->take(50); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |         $query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |         return $query->get(['name'])->pluck('name'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-16 03:12:53 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get tag value suggestions from scanning existing tag values. | 
					
						
							| 
									
										
										
										
											2016-06-04 22:37:28 +08:00
										 |  |  |      * If no search is given the 50 most popular values are provided. | 
					
						
							|  |  |  |      * Passing a tagName will only find values for a tags with a particular name. | 
					
						
							| 
									
										
										
										
											2016-05-16 03:12:53 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  |     public function getValueSuggestions(?string $searchTerm, ?string $tagName): Collection | 
					
						
							| 
									
										
										
										
											2016-05-16 03:12:53 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |         $query = Tag::query() | 
					
						
							| 
									
										
										
										
											2021-03-15 03:52:07 +08:00
										 |  |  |             ->select('*', DB::raw('count(*) as count')) | 
					
						
							|  |  |  |             ->groupBy('value'); | 
					
						
							| 
									
										
										
										
											2016-06-04 22:37:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($searchTerm) { | 
					
						
							|  |  |  |             $query = $query->where('value', 'LIKE', $searchTerm . '%')->orderBy('value', 'desc'); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $query = $query->orderBy('count', 'desc')->take(50); | 
					
						
							| 
									
										
										
										
											2016-06-04 21:54:31 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-06-04 22:37:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  |         if ($tagName) { | 
					
						
							| 
									
										
										
										
											2018-01-29 00:58:52 +08:00
										 |  |  |             $query = $query->where('name', '=', $tagName); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-06-04 22:37:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-16 03:12:53 +08:00
										 |  |  |         $query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-16 03:12:53 +08:00
										 |  |  |         return $query->get(['value'])->pluck('value'); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-04 22:37:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * Save an array of tags to an entity. | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  |     public function saveTagsToEntity(Entity $entity, array $tags = []): iterable | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |         $entity->tags()->delete(); | 
					
						
							| 
									
										
										
										
											2020-05-23 07:28:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  |         $newTags = collect($tags)->filter(function ($tag) { | 
					
						
							|  |  |  |             return boolval(trim($tag['name'])); | 
					
						
							|  |  |  |         })->map(function ($tag) { | 
					
						
							|  |  |  |             return $this->newInstanceFromInput($tag); | 
					
						
							|  |  |  |         })->all(); | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |         return $entity->tags()->saveMany($newTags); | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |      * Create a new Tag instance from user input. | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  |      * Input must be an array with a 'name' and an optional 'value' key. | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-06-30 05:11:03 +08:00
										 |  |  |     protected function newInstanceFromInput(array $input): Tag | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-11-07 00:30:20 +08:00
										 |  |  |         return new Tag([ | 
					
						
							|  |  |  |             'name'  => trim($input['name']), | 
					
						
							|  |  |  |             'value' => trim($input['value'] ?? ''), | 
					
						
							|  |  |  |         ]); | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-29 00:58:52 +08:00
										 |  |  | } |