| 
									
										
										
										
											2016-02-28 03:24:42 +08:00
										 |  |  | <?php namespace BookStack; | 
					
						
							| 
									
										
										
										
											2015-08-16 21:51:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  | class Entity extends Ownable | 
					
						
							| 
									
										
										
										
											2015-08-16 21:51:45 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-22 01:22:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-16 21:51:45 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Compares this entity to another given entity. | 
					
						
							|  |  |  |      * Matches by comparing class and id. | 
					
						
							|  |  |  |      * @param $entity | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function matches($entity) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return [get_class($this), $this->id] === [get_class($entity), $entity->id]; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-08-17 01:59:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-30 02:06:55 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Checks if an entity matches or contains another given entity. | 
					
						
							|  |  |  |      * @param Entity $entity | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function matchesOrContains(Entity $entity) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $matches = [get_class($this), $this->id] === [get_class($entity), $entity->id]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($matches) return true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-02 22:48:35 +08:00
										 |  |  |         if (($entity->isA('chapter') || $entity->isA('page')) && $this->isA('book')) { | 
					
						
							| 
									
										
										
										
											2015-11-30 02:06:55 +08:00
										 |  |  |             return $entity->book_id === $this->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($entity->isA('page') && $this->isA('chapter')) { | 
					
						
							|  |  |  |             return $entity->chapter_id === $this->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-17 01:59:23 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2015-11-22 01:22:14 +08:00
										 |  |  |      * Gets the activity objects for this entity. | 
					
						
							| 
									
										
										
										
											2015-08-17 01:59:23 +08:00
										 |  |  |      * @return \Illuminate\Database\Eloquent\Relations\MorphMany | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function activity() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         return $this->morphMany(Activity::class, 'entity')->orderBy('created_at', 'desc'); | 
					
						
							| 
									
										
										
										
											2015-08-17 01:59:23 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 01:22:14 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get View objects for this entity. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function views() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         return $this->morphMany(View::class, 'viewable'); | 
					
						
							| 
									
										
										
										
											2015-11-22 01:22:14 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |      * Get the Tag models that have been user assigned to this entity. | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |      * @return \Illuminate\Database\Eloquent\Relations\MorphMany | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-14 04:20:21 +08:00
										 |  |  |     public function tags() | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-15 03:02:00 +08:00
										 |  |  |         return $this->morphMany(Tag::class, 'entity')->orderBy('order', 'asc'); | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-31 18:43:28 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-02-28 18:49:41 +08:00
										 |  |  |      * Get this entities restrictions. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function permissions() | 
					
						
							| 
									
										
										
										
											2016-02-28 18:49:41 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         return $this->morphMany(EntityPermission::class, 'restrictable'); | 
					
						
							| 
									
										
										
										
											2016-02-28 18:49:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Check if this entity has a specific restriction set against it. | 
					
						
							|  |  |  |      * @param $role_id | 
					
						
							|  |  |  |      * @param $action | 
					
						
							| 
									
										
										
										
											2015-08-31 18:43:28 +08:00
										 |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-28 18:49:41 +08:00
										 |  |  |     public function hasRestriction($role_id, $action) | 
					
						
							| 
									
										
										
										
											2015-08-31 18:43:28 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         return $this->permissions()->where('role_id', '=', $role_id) | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |             ->where('action', '=', $action)->count() > 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Check if this entity has live (active) restrictions in place. | 
					
						
							|  |  |  |      * @param $role_id | 
					
						
							|  |  |  |      * @param $action | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function hasActiveRestriction($role_id, $action) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-01 00:16:06 +08:00
										 |  |  |         return $this->getRawAttribute('restricted') && $this->hasRestriction($role_id, $action); | 
					
						
							| 
									
										
										
										
											2015-08-31 18:43:28 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Get the entity jointPermissions this is connected to. | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |      * @return \Illuminate\Database\Eloquent\Relations\MorphMany | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |     public function jointPermissions() | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         return $this->morphMany(JointPermission::class, 'entity'); | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2015-08-31 18:43:28 +08:00
										 |  |  |      * Allows checking of the exact class, Used to check entity type. | 
					
						
							|  |  |  |      * Cleaner method for is_a. | 
					
						
							|  |  |  |      * @param $type | 
					
						
							|  |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-11-30 01:33:25 +08:00
										 |  |  |     public static function isA($type) | 
					
						
							| 
									
										
										
										
											2015-08-31 18:43:28 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-24 01:14:26 +08:00
										 |  |  |         return static::getType() === strtolower($type); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get entity type. | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public static function getType() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return strtolower(static::getClassName()); | 
					
						
							| 
									
										
										
										
											2015-08-31 18:43:28 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-07 03:33:08 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get an instance of an entity of the given type. | 
					
						
							|  |  |  |      * @param $type | 
					
						
							|  |  |  |      * @return Entity | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public static function getEntityInstance($type) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $types = ['Page', 'Book', 'Chapter']; | 
					
						
							|  |  |  |         $className = str_replace([' ', '-', '_'], '', ucwords($type)); | 
					
						
							|  |  |  |         if (!in_array($className, $types)) { | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return app('BookStack\\' . $className); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 22:41:51 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-02-28 03:24:42 +08:00
										 |  |  |      * Gets a limited-length version of the entities name. | 
					
						
							| 
									
										
										
										
											2015-12-05 22:41:51 +08:00
										 |  |  |      * @param int $length | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getShortName($length = 25) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-03-05 04:49:35 +08:00
										 |  |  |         if (strlen($this->name) <= $length) return $this->name; | 
					
						
							|  |  |  |         return substr($this->name, 0, $length - 3) . '...'; | 
					
						
							| 
									
										
										
										
											2015-12-05 22:41:51 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Perform a full-text search on this entity. | 
					
						
							|  |  |  |      * @param string[] $fieldsToSearch | 
					
						
							|  |  |  |      * @param string[] $terms | 
					
						
							| 
									
										
										
										
											2015-09-01 22:35:11 +08:00
										 |  |  |      * @param string[] array $wheres | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |     public function fullTextSearchQuery($fieldsToSearch, $terms, $wheres = []) | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-03-05 04:49:35 +08:00
										 |  |  |         $exactTerms = []; | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |         if (count($terms) === 0) { | 
					
						
							|  |  |  |             $search = $this; | 
					
						
							|  |  |  |             $orderBy = 'updated_at'; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             foreach ($terms as $key => $term) { | 
					
						
							|  |  |  |                 $term = htmlentities($term, ENT_QUOTES); | 
					
						
							|  |  |  |                 $term = preg_replace('/[+\-><\(\)~*\"@]+/', ' ', $term); | 
					
						
							|  |  |  |                 if (preg_match('/\s/', $term)) { | 
					
						
							|  |  |  |                     $exactTerms[] = '%' . $term . '%'; | 
					
						
							|  |  |  |                     $term = '"' . $term . '"'; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     $term = '' . $term . '*'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if ($term !== '*') $terms[$key] = $term; | 
					
						
							| 
									
										
										
										
											2016-03-04 16:33:57 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |             $termString = implode(' ', $terms); | 
					
						
							|  |  |  |             $fields = implode(',', $fieldsToSearch); | 
					
						
							|  |  |  |             $search = static::selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance', [$termString]); | 
					
						
							|  |  |  |             $search = $search->whereRaw('MATCH(' . $fields . ') AGAINST(? IN BOOLEAN MODE)', [$termString]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Ensure at least one exact term matches if in search
 | 
					
						
							|  |  |  |             if (count($exactTerms) > 0) { | 
					
						
							|  |  |  |                 $search = $search->where(function ($query) use ($exactTerms, $fieldsToSearch) { | 
					
						
							|  |  |  |                     foreach ($exactTerms as $exactTerm) { | 
					
						
							|  |  |  |                         foreach ($fieldsToSearch as $field) { | 
					
						
							|  |  |  |                             $query->orWhere($field, 'like', $exactTerm); | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2016-03-05 04:49:35 +08:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |                 }); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $orderBy = 'title_relevance'; | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2016-03-05 04:49:35 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-05 23:11:48 +08:00
										 |  |  |         // Add additional where terms
 | 
					
						
							| 
									
										
										
										
											2015-09-01 22:35:11 +08:00
										 |  |  |         foreach ($wheres as $whereTerm) { | 
					
						
							|  |  |  |             $search->where($whereTerm[0], $whereTerm[1], $whereTerm[2]); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-12-05 23:11:48 +08:00
										 |  |  |         // Load in relations
 | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |         if ($this->isA('page')) { | 
					
						
							| 
									
										
										
										
											2016-02-21 20:53:58 +08:00
										 |  |  |             $search = $search->with('book', 'chapter', 'createdBy', 'updatedBy'); | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |         } else if ($this->isA('chapter')) { | 
					
						
							| 
									
										
										
										
											2016-02-21 20:53:58 +08:00
										 |  |  |             $search = $search->with('book'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-11-30 01:33:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |         return $search->orderBy($orderBy, 'desc'); | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-07 21:29:43 +08:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2015-08-16 21:51:45 +08:00
										 |  |  | } |