140 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
| <?php
 | |
| 
 | |
| namespace BookStack\Api;
 | |
| 
 | |
| use BookStack\Entities\Models\BookChild;
 | |
| use BookStack\Entities\Models\Entity;
 | |
| use BookStack\Entities\Models\Page;
 | |
| 
 | |
| class ApiEntityListFormatter
 | |
| {
 | |
|     /**
 | |
|      * The list to be formatted.
 | |
|      * @var Entity[]
 | |
|      */
 | |
|     protected array $list = [];
 | |
| 
 | |
|     /**
 | |
|      * The fields to show in the formatted data.
 | |
|      * Can be a plain string array item for a direct model field (If existing on model).
 | |
|      * If the key is a string, with a callable value, the return value of the callable
 | |
|      * will be used for the resultant value. A null return value will omit the property.
 | |
|      * @var array<string|int, string|callable>
 | |
|      */
 | |
|     protected array $fields = [
 | |
|         'id',
 | |
|         'name',
 | |
|         'slug',
 | |
|         'book_id',
 | |
|         'chapter_id',
 | |
|         'draft',
 | |
|         'template',
 | |
|         'priority',
 | |
|         'created_at',
 | |
|         'updated_at',
 | |
|     ];
 | |
| 
 | |
|     public function __construct(array $list)
 | |
|     {
 | |
|         $this->list = $list;
 | |
| 
 | |
|         // Default dynamic fields
 | |
|         $this->withField('url', fn(Entity $entity) => $entity->getUrl());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add a field to be used in the formatter, with the property using the given
 | |
|      * name and value being the return type of the given callback.
 | |
|      */
 | |
|     public function withField(string $property, callable $callback): self
 | |
|     {
 | |
|         $this->fields[$property] = $callback;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Show the 'type' property in the response reflecting the entity type.
 | |
|      * EG: page, chapter, bookshelf, book
 | |
|      * To be included in results with non-pre-determined types.
 | |
|      */
 | |
|     public function withType(): self
 | |
|     {
 | |
|         $this->withField('type', fn(Entity $entity) => $entity->getType());
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Include tags in the formatted data.
 | |
|      */
 | |
|     public function withTags(): self
 | |
|     {
 | |
|         $this->withField('tags', fn(Entity $entity) => $entity->tags);
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Include parent book/chapter info in the formatted data.
 | |
|      */
 | |
|     public function withParents(): self
 | |
|     {
 | |
|         $this->withField('book', function (Entity $entity) {
 | |
|             if ($entity instanceof BookChild && $entity->book) {
 | |
|                 return $entity->book->only(['id', 'name', 'slug']);
 | |
|             }
 | |
|             return null;
 | |
|         });
 | |
| 
 | |
|         $this->withField('chapter', function (Entity $entity) {
 | |
|             if ($entity instanceof Page && $entity->chapter) {
 | |
|                 return $entity->chapter->only(['id', 'name', 'slug']);
 | |
|             }
 | |
|             return null;
 | |
|         });
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Format the data and return an array of formatted content.
 | |
|      * @return array[]
 | |
|      */
 | |
|     public function format(): array
 | |
|     {
 | |
|         $results = [];
 | |
| 
 | |
|         foreach ($this->list as $item) {
 | |
|             $results[] = $this->formatSingle($item);
 | |
|         }
 | |
| 
 | |
|         return $results;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Format a single entity item to a plain array.
 | |
|      */
 | |
|     protected function formatSingle(Entity $entity): array
 | |
|     {
 | |
|         $result = [];
 | |
|         $values = (clone $entity)->toArray();
 | |
| 
 | |
|         foreach ($this->fields as $field => $callback) {
 | |
|             if (is_string($callback)) {
 | |
|                 $field = $callback;
 | |
|                 if (!isset($values[$field])) {
 | |
|                     continue;
 | |
|                 }
 | |
|                 $value = $values[$field];
 | |
|             } else {
 | |
|                 $value = $callback($entity);
 | |
|                 if (is_null($value)) {
 | |
|                     continue;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             $result[$field] = $value;
 | |
|         }
 | |
| 
 | |
|         return $result;
 | |
|     }
 | |
| }
 |