| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace BookStack\Entities\Tools; | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-09 06:34:22 +08:00
										 |  |  | use BookStack\Entities\Models\BookChild; | 
					
						
							|  |  |  | use BookStack\Interfaces\Sluggable; | 
					
						
							| 
									
										
										
										
											2021-11-06 08:32:01 +08:00
										 |  |  | use BookStack\Model; | 
					
						
							| 
									
										
										
										
											2020-06-26 00:08:13 +08:00
										 |  |  | use Illuminate\Support\Str; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  | class SlugGenerator | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Generate a fresh slug for the given entity. | 
					
						
							| 
									
										
										
										
											2021-11-06 08:32:01 +08:00
										 |  |  |      * The slug will be generated so that it doesn't conflict within the same parent item. | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-09 06:34:22 +08:00
										 |  |  |     public function generate(Sluggable $model): string | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-09 06:34:22 +08:00
										 |  |  |         $slug = $this->formatNameAsSlug($model->name); | 
					
						
							|  |  |  |         while ($this->slugInUse($slug, $model)) { | 
					
						
							|  |  |  |             $slug .= '-' . Str::random(3); | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |         return $slug; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Format a name as a url slug. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function formatNameAsSlug(string $name): string | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-06-26 00:08:13 +08:00
										 |  |  |         $slug = Str::slug($name); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |         if ($slug === '') { | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |             $slug = substr(md5(rand(1, 500)), 0, 5); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |         return $slug; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Check if a slug is already in-use for this | 
					
						
							|  |  |  |      * type of model within the same parent. | 
					
						
							| 
									
										
										
										
											2021-11-07 06:00:33 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-11-06 08:32:01 +08:00
										 |  |  |      * @param Sluggable&Model $model | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-09 06:34:22 +08:00
										 |  |  |     protected function slugInUse(string $slug, Sluggable $model): bool | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-09 06:34:22 +08:00
										 |  |  |         $query = $model->newQuery()->where('slug', '=', $slug); | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-09 06:34:22 +08:00
										 |  |  |         if ($model instanceof BookChild) { | 
					
						
							|  |  |  |             $query->where('book_id', '=', $model->book_id); | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-09 06:34:22 +08:00
										 |  |  |         if ($model->id) { | 
					
						
							|  |  |  |             $query->where('id', '!=', $model->id); | 
					
						
							| 
									
										
										
										
											2019-09-20 07:18:28 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $query->count() > 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | } |