From 756e619d38d6e907909f69e2956b6b7bd0c36fe7 Mon Sep 17 00:00:00 2001 From: Zach Garwood Date: Tue, 14 Jan 2025 12:48:19 -0600 Subject: [PATCH] Update to use data-hub-foundation [WEB-2996] --- .env.testing | 2 +- app/Helpers/CollectionHelpers.php | 2 +- app/Helpers/StringHelpers.php | 2 +- .../Controllers/Twill/BaseApiController.php | 2 +- .../Api/Builders/ApiModelBuilder.php | 689 ----------- .../Api/Builders/ApiModelBuilderSearch.php | 215 ---- .../Api/Builders/ApiQueryBuilder.php | 623 ---------- .../Api/Builders/Connection/AicConnection.php | 154 --- .../Connection/ApiConnectionInterface.php | 10 - .../Api/Builders/Grammar/AicGrammar.php | 173 --- .../Api/Builders/Grammar/MsearchGrammar.php | 31 - .../Api/Builders/Grammar/SearchGrammar.php | 13 - .../Api/Builders/Relations/BelongsTo.php | 36 - .../Api/Builders/Relations/HasMany.php | 79 -- .../Api/Builders/Relations/NullRelation.php | 34 - .../Api/Consumers/ApiConsumerInterface.php | 11 - .../Api/Consumers/GuzzleApiConsumer.php | 96 -- app/Libraries/Api/Filters/Search.php | 39 - app/Libraries/Api/Models/ApiCollection.php | 41 - app/Libraries/Api/Models/BaseApiModel.php | 1015 ----------------- .../Api/Models/Behaviors/HasApiCalls.php | 151 --- .../Models/Behaviors/HasAugmentedModel.php | 62 - .../Api/Models/Behaviors/HasRelationships.php | 129 --- app/Libraries/SmartyPants.php | 20 - app/Models/AbstractModel.php | 66 -- app/Models/Api/Audio.php | 2 +- app/Models/Api/CollectionObject.php | 2 +- app/Models/Api/Gallery.php | 2 +- app/Models/ApiRelation.php | 1 + app/Models/Audio.php | 5 +- app/Models/Behaviors/HasApiModel.php | 84 -- app/Models/Behaviors/HasApiRelations.php | 2 +- app/Models/CollectionObject.php | 3 +- app/Models/Gallery.php | 3 +- app/Models/LoanObject.php | 1 + app/Models/Transformers/ObjectTransformer.php | 4 +- app/Providers/AppServiceProvider.php | 2 +- .../Behaviors/HandleApiBrowsers.php | 6 +- composer.json | 14 +- composer.lock | 284 ++--- database/factories/Api/ApiFactory.php | 2 +- tests/Feature/ObjectSerializerTest.php | 1 + tests/MockApi.php | 4 +- 43 files changed, 129 insertions(+), 3988 deletions(-) delete mode 100644 app/Libraries/Api/Builders/ApiModelBuilder.php delete mode 100644 app/Libraries/Api/Builders/ApiModelBuilderSearch.php delete mode 100644 app/Libraries/Api/Builders/ApiQueryBuilder.php delete mode 100644 app/Libraries/Api/Builders/Connection/AicConnection.php delete mode 100644 app/Libraries/Api/Builders/Connection/ApiConnectionInterface.php delete mode 100644 app/Libraries/Api/Builders/Grammar/AicGrammar.php delete mode 100644 app/Libraries/Api/Builders/Grammar/MsearchGrammar.php delete mode 100644 app/Libraries/Api/Builders/Grammar/SearchGrammar.php delete mode 100644 app/Libraries/Api/Builders/Relations/BelongsTo.php delete mode 100644 app/Libraries/Api/Builders/Relations/HasMany.php delete mode 100644 app/Libraries/Api/Builders/Relations/NullRelation.php delete mode 100644 app/Libraries/Api/Consumers/ApiConsumerInterface.php delete mode 100644 app/Libraries/Api/Consumers/GuzzleApiConsumer.php delete mode 100644 app/Libraries/Api/Filters/Search.php delete mode 100644 app/Libraries/Api/Models/ApiCollection.php delete mode 100644 app/Libraries/Api/Models/BaseApiModel.php delete mode 100644 app/Libraries/Api/Models/Behaviors/HasApiCalls.php delete mode 100644 app/Libraries/Api/Models/Behaviors/HasAugmentedModel.php delete mode 100644 app/Libraries/Api/Models/Behaviors/HasRelationships.php delete mode 100644 app/Libraries/SmartyPants.php delete mode 100644 app/Models/AbstractModel.php delete mode 100644 app/Models/Behaviors/HasApiModel.php diff --git a/.env.testing b/.env.testing index b5406e29..c31f5c25 100644 --- a/.env.testing +++ b/.env.testing @@ -8,5 +8,5 @@ DB_CONNECTION='mysql' DB_HOST='127.0.0.1' DB_PORT=3306 DB_DATABASE='mobile-admin-test' -DB_USERNAME='mobile-admin' +DB_USERNAME='homestead' DB_PASSWORD='secret' diff --git a/app/Helpers/CollectionHelpers.php b/app/Helpers/CollectionHelpers.php index 2da3ee8b..9ad5aedf 100644 --- a/app/Helpers/CollectionHelpers.php +++ b/app/Helpers/CollectionHelpers.php @@ -12,6 +12,6 @@ class CollectionHelpers */ public static function collectApi($value = null) { - return new \App\Libraries\Api\Models\ApiCollection($value); + return new \Aic\Hub\Foundation\Library\Api\Models\ApiCollection($value); } } diff --git a/app/Helpers/StringHelpers.php b/app/Helpers/StringHelpers.php index 97d9d795..ffbd7e4a 100644 --- a/app/Helpers/StringHelpers.php +++ b/app/Helpers/StringHelpers.php @@ -178,7 +178,7 @@ public static function getLastWord($originalText) public static function convertReferenceLinks($text, $_collectedReferences) { - $codes = \App\Libraries\ShortcodeService::parse_ref($text); + $codes = \Aic\Hub\Foundation\Library\ShortcodeService::parse_ref($text); foreach ($codes as $index => $code) { if (isset($code['name']) && ($code['name'] == 'ref')) { diff --git a/app/Http/Controllers/Twill/BaseApiController.php b/app/Http/Controllers/Twill/BaseApiController.php index 5ce5b480..573673f5 100644 --- a/app/Http/Controllers/Twill/BaseApiController.php +++ b/app/Http/Controllers/Twill/BaseApiController.php @@ -21,7 +21,7 @@ use App\Helpers\UrlHelpers; use App\Http\Controllers\Behaviors\HandlesTitleMarkup; use App\Http\Controllers\Twill\Columns\ApiImage; -use App\Libraries\Api\Filters\Search; +use Aic\Hub\Foundation\Library\Api\Filters\Search; use App\Repositories\Api\BaseApiRepository; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; diff --git a/app/Libraries/Api/Builders/ApiModelBuilder.php b/app/Libraries/Api/Builders/ApiModelBuilder.php deleted file mode 100644 index 86dbfb4b..00000000 --- a/app/Libraries/Api/Builders/ApiModelBuilder.php +++ /dev/null @@ -1,689 +0,0 @@ -query = $query; - } - - /** - * Set a model instance for the model being queried. - * - * @param \App\Libraries\Api\Models\BaseApiModel - * @return $this - */ - public function setModel($model) - { - $this->model = $model; - - return $this; - } - - /** - * Set the relationships that should be included. - * - * @param mixed $relations - * @return $this - */ - public function with($relations, $callback = null) - { - $this->eagerLoad = array_merge($this->eagerLoad, $relations); - - return $this; - } - - /** - * Return counting data from the request. - * TODO: Implement it for the API. Bypassing for the moment. - * - * @param mixed $relations - * @return $this - */ - public function withCount($relations) - { - return $this; - } - - /** - * Add a basic where clause to the query. - * - * @param string|array|\Closure $column - * @param string $operator - * @param mixed $value - * @param string $boolean - * @return $this - */ - public function where($column, $operator = null, $value = null, $boolean = 'and') - { - $this->query->where(...func_get_args()); - - return $this; - } - - /** - * Perform a search - * - * @param string $search - * @return $this - */ - public function search($search) - { - $this->query->search(...func_get_args()); - $this->performSearch = true; - - return $this; - } - - /** - * Perform a raw ES search - * - * @param array $search - * @return $this - */ - public function rawSearch($search) - { - $this->query->rawSearch(...func_get_args()); - $this->performSearch = true; - - return $this; - } - - /** - * Perform a raw ES query - * - * @param array $params - * @return $this - */ - public function rawQuery($params) - { - $this->query->rawQuery(...func_get_args()); - $this->performSearch = true; - - return $this; - } - - /** - * Add aggregations to the raw ES search - * - * @param array $aggregations - * @return $this - */ - public function aggregations($aggregations) - { - $this->query->aggregations(...func_get_args()); - - return $this; - } - - /** - * When searching filter by specific resources - * - * @return $this - */ - public function resources(array $resources) - { - $this->query->resources($resources); - - return $this; - } - - /** - * Setup a TTL for this specific query call - * - * @param integer $ttl - * @return $this - */ - public function ttl($ttl) - { - $this->ttl = $ttl; - $this->query->ttl($ttl); - - return $this; - } - - /** - * Filter elements by specific ID's - * - * @return $this - */ - public function ids(array $ids) - { - $this->query->ids($ids); - - return $this; - } - - /** - * Include fields at the results - * - * @return $this - */ - public function include(array $inclusions) - { - $this->query->include($inclusions); - - return $this; - } - - /** - * Find a model by its primary key. - * - * @param mixed $id - * @param array $columns - */ - public function find($id, $columns = []) - { - if (is_array($id) || $id instanceof Arrayable) { - return $this->findMany($id, $columns); - } - - return $this->findSingle($id, $columns); - } - - /** - * Find a model by its primary key, return exception if empty. - * - * @param mixed $id - * @param array $columns - */ - public function findOrFail($id, $columns = []) - { - $result = $this->find($id, $columns); - - if (isset($result->status) && $result->status == 404) { - abort(404); - } - - if (is_array($id)) { - if (count($result) == count(array_unique($id))) { - return $result; - } - } elseif (!is_null($result)) { - return $result; - } - - throw (new ModelNotFoundException())->setModel( - get_class($this->model), - $id - ); - } - - public function findSingle($id, $columns = []) - { - $builder = clone $this; - - // Eager load relationships - if ($result = $builder->getSingle($id, $columns)) { - $result = $builder->eagerLoadRelations([$result]); - } - - return $builder->getModel()->newCollection($result)->first(); - } - - public function findMany($ids, $columns = []) - { - if (empty($ids)) { - return $this->model->newCollection(); - } - - return $this->ids($ids)->get($columns); - } - - /** - * Execute the query and return a collection of results - * - * @param array $columns - */ - public function get($columns = []) - { - $builder = clone $this; - - if (count($models = $builder->getModels($columns)) > 0) { - $models = $builder->eagerLoadRelations($models); - } - - // Return direct body if status is different than a HIT - if (isset($models->status) && $models->status != 200) { - return $models; - } - - return $builder->getModel()->newCollection($models); - } - - /** - * Execute the query and return a raw response - * - * @param array $columns - */ - public function getRaw($columns = []) - { - $builder = clone $this; - - return $this->query->getRaw($columns, $this->getEndpoint($this->resolveCollectionEndpoint()))->all(); - } - - /** - * Execute a query and return the total count from the pagination data - */ - public function count(): int - { - $builder = clone $this; - - return $builder->query->count($this->getEndpoint($this->resolveCollectionEndpoint())); - } - - /** - * Get the hydrated models - * - * @param array $columns - */ - public function getModels($columns = []) - { - $results = $this->query->get($columns, $this->getEndpoint($this->resolveCollectionEndpoint())); - - // Return direct body if status is different than a HIT - if (isset($results->status) && $results->status != 200) { - return $results; - } - - $models = $this->model->hydrate($results->all()); - - // Preserve metadata after hydrating the collection - return CollectionHelpers::collectApi($models)->setMetadata($results->getMetadata()); - } - - /** - * Get a plain search request - * - * @param array $columns - */ - public function getSearch($perPage = null, $columns = [], $pageName = 'page', $page = null) - { - $builder = clone $this; - - $page = is_null($page) ? Paginator::resolveCurrentPage($pageName) : $page; - $perPage = is_null($perPage) ? $this->model->getPerPage() : $perPage; - - $results = $this->forPage($page, $perPage)->get($columns); - - $paginationData = $results->getMetadata('pagination'); - $total = $paginationData ? $paginationData->total : $results->count(); - - // Extract IDS - $ids = $results->pluck('id')->toArray(); - - // Load the actual models using the IDS returned by search - if (empty($ids)) { - $models = CollectionHelpers::collectApi(); - } else { - $models = $this->model->newQuery()->ttl($this->ttl)->ids($ids)->get(); - } - - // Sort them by the original ids listing - $sorted = $models->sortBy(function ($model, $key) use ($ids) { - return CollectionHelpers::collectApi($ids)->search(function ($id, $key) use ($model) { - return $id == $model->id; - }); - })->values(); - - // Preserve original metadata - $sorted->setMetadata($results->getMetadata()); - - return $this->paginator($sorted, $total, $perPage ?: 1, $page, [ - 'path' => Paginator::resolveCurrentPath(), - 'pageName' => $pageName, - ]); - } - - /** - * Paginate the given query and transform the Search results to the API models - * - * @param int $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page - * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator - * - * @throws \InvalidArgumentException - */ - public function getPaginatedModel($perPage = null, $columns = [], $pageName = 'page', $page = null) - { - $results = $this->getPaginated($perPage, $columns, $pageName, $page); - - $paginationData = $results->getMetadata('pagination'); - $total = $paginationData ? $paginationData->total : $results->count(); - - // Transform each Search model to the correct instance using typeMap - $hydratedModels = $results->transform(function ($item, $key) { - return $this->model::hydrate([$item->toArray()])[0]; - }); - - // Rebuild the paginator - return $this->paginator($hydratedModels, $total, $perPage ?: 1, $page, [ - 'path' => Paginator::resolveCurrentPath(), - 'pageName' => $pageName, - ]); - } - - /** - * Eager load the relationships for the models. - * On this case just a flat include, not nested queries because - * we get all id's to be loaded on the first request to the parent model - * - * @param array $models - * @return array - */ - public function eagerLoadRelations($models) - { - // Preserve metadata when loading relationships - if ($models instanceof ApiCollection) { - $metadata = $models->getMetadata(); - } - - foreach ($this->eagerLoad as $name) { - $models = $this->eagerLoadRelation($models, $name); - } - - return isset($metadata) ? $models->setMetadata($metadata) : $models; - } - - /** - * Eagerly load the relationship on a set of models. - * - * @param array $models - * @param string $name - * @return array - */ - protected function eagerLoadRelation($models, $name, Closure $constraints = null) - { - foreach ($models as $model) { - if ($model instanceof BaseApiModel) { - // For each model get the relationship - $relation = $model->{$name}(); - - // Set the relationship loading the data from the API - // this will generate N + 1 calls in total - // improve later using real eager loading to - // reduce the number of calls to 1 + relationships_number - if ($relation) { - $model->setRelation($name, $relation->getEager()); - } - } - } - - return $models; - } - - /** - * Execute the query and return a single element - * - * @param array $columns - */ - public function getSingle($id, $columns = []) - { - $builder = clone $this; - $endpoint = $this->getEndpoint($this->resolveResourceEndpoint(), ['id' => $id]); - - $results = $this->query->get($columns, $endpoint); - - // Return direct body if status is different than a HIT - if (isset($results->status) && $results->status != 200) { - return $results; - } - - $models = $result = $this->model->hydrate($results->all()); - - return collect($models)->first(); - } - - /** - * Paginate the given query. - * - * @param int $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page - * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator - * - * @throws \InvalidArgumentException - */ - public function getPaginated($perPage = null, $columns = [], $pageName = 'page', $page = null) - { - $page = $page ?: Paginator::resolveCurrentPage($pageName); - - $perPage = $perPage ?: $this->model->getPerPage(); - - $results = $this->forPage($page, $perPage)->get($columns); - $paginationData = $results->getMetadata('pagination'); - $total = $paginationData ? $paginationData->total : $results->count(); - - return $this->paginator($results, $total, $perPage, $page, [ - 'path' => Paginator::resolveCurrentPath(), - 'pageName' => $pageName, - ]); - } - - /** - * Paginate the given query. - * - * @param int $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page - * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator - * - * @throws \InvalidArgumentException - */ - public function paginate($perPage = null, $columns = [], $pageName = 'page', $page = null) - { - if ($this->performSearch) { - return $this->getSearch($perPage, $columns, $pageName, $page); - } - - return $this->getPaginated($perPage, $columns, $pageName, $page); - } - - protected function paginator($items, $total, $perPage, $currentPage, $options) - { - return new LengthAwarePaginator( - $items, - $total, - $perPage, - $currentPage, - $options - ); - } - - /** - * Get the model instance being queried. - * - * @return string - */ - public function getEndpoint($name, $params = []) - { - return $this->model->parseEndpoint($name, $params); - } - - /** - * Force to use a specific endpoint - * - * @return string - */ - public function forceEndpoint($name) - { - $this->customEndpoint = $name; - - return $this; - } - - /** - * Resolve endpoint. Because search and listing contains different ones - * We will check if we are calling a search, and use that endpoint in that case - * - * @return string - */ - public function resolveCollectionEndpoint() - { - if ($this->customEndpoint) { - return $this->customEndpoint; - } - - return $this->performSearch ? 'search' : 'collection'; - } - - /** - * Resolve single element endpoint - * - * @return string - */ - public function resolveResourceEndpoint() - { - return $this->customEndpoint ?? 'resource'; - } - - /** - * Get the model instance being queried. - * - * @return \App\Libraries\Api\Models\BaseApiModel; - */ - public function getModel() - { - return $this->model; - } - - /** - * TODO: Apply scopes before running a passthrough - */ - public function toBase() - { - return $this; - } - - /** - * Apply the given scope on the current builder instance. - * - * @param array $parameters - * @return mixed - */ - protected function callScope(callable $scope, $parameters = []) - { - array_unshift($parameters, $this); - $result = $scope(...array_values($parameters)) ?? $this; - - return $result; - } - - /** - * Dynamically handle calls into the query instance. - * - * @param string $method - * @param array $parameters - */ - public function __call($method, $parameters): mixed - { - if (method_exists($this->model, $scope = 'scope' . ucfirst($method))) { - return $this->callScope([$this->model, $scope], $parameters); - } - - if (in_array($method, $this->passthru)) { - return $this->query->{$method}(...$parameters); - } - - $this->query->{$method}(...$parameters); - - return $this; - } - - /** - * Dynamically retrieve attributes on the model. - * - * @param string $key - */ - public function __get($key): mixed - { - return $this->query->{$key}; - } -} diff --git a/app/Libraries/Api/Builders/ApiModelBuilderSearch.php b/app/Libraries/Api/Builders/ApiModelBuilderSearch.php deleted file mode 100644 index 7f589fbf..00000000 --- a/app/Libraries/Api/Builders/ApiModelBuilderSearch.php +++ /dev/null @@ -1,215 +0,0 @@ - API class, ...] - * - */ - protected $typeMap = []; - - /** - * Get a plain search request - * - * @param array $columns - */ - public function getSearch($perPage = null, $columns = [], $pageName = 'page', $page = null, $options = []) - { - $builder = clone $this; - - $page = is_null($page) ? Paginator::resolveCurrentPage($pageName) : $page; - $perPage = is_null($perPage) ? $this->model->getPerPage() : $perPage; - - if ($columns) { - $columns = array_merge( - ['thumbnail', 'api_model', 'is_boosted', 'api_link', 'id', 'title', 'timestamp'], - $columns - ); - } - $results = $this->forPage($page, $perPage)->get($columns); - - $paginationData = $results->getMetadata('pagination'); - $total = $paginationData ? $paginationData->total : $results->count(); - - if (isset($options['do-not-extract']) && $options['do-not-extract']) { - if (isset($options['segregated']) && $options['segregated']) { - $models = $this->makeModels($results); - } else { - $models = $this->makeModelsFlat($results); - } - } else { - if (isset($options['segregated']) && $options['segregated']) { - $models = $this->extractModels($results); - } else { - $models = $this->extractModelsFlat($results); - } - } - - return $this->paginator($models, $total, $perPage ?: 1, $page, [ - 'path' => Paginator::resolveCurrentPath(), - 'pageName' => $pageName, - ]); - } - - /** - * Paginate the given query and transform the Search results to the correct API models - * - * @param int $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page - * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator - * - * @throws \InvalidArgumentException - */ - public function getPaginatedModel($perPage = null, $columns = [], $pageName = 'page', $page = null) - { - $results = $this->getPaginated($perPage, $columns, $pageName, $page); - - $paginationData = $results->getMetadata('pagination'); - $total = $paginationData ? $paginationData->total : $results->count(); - - // Transform each Search model to the correct instance using typeMap - $hydratedModels = $results->transform(function ($item, $key) { - return $this->getTypeMap()[$item->api_model]::hydrate([$item->toArray()])[0]; - }); - - // Rebuild the paginator - return $this->paginator($hydratedModels, $total, $perPage ?: 1, $page, [ - 'path' => Paginator::resolveCurrentPath(), - 'pageName' => $pageName, - ]); - } - - protected function extractModelsFlat($results) - { - $original = clone $results; - - // It's more efficient to get segregated results, and then reshuffle them into the - // original order - $segregatedResults = $this->extractModels($results); - - // Mix them all up together - $flatResults = CollectionHelpers::collectApi(array_filter(Arr::flatten($segregatedResults))); - - // Sort results in their original order - $sorted = $flatResults->sortBy(function ($model, $key) use ($original) { - return $original->search(function ($item, $key) use ($model) { - if (isset($this->getTypeMap()[$item->api_model])) { - return $this->getTypeMap()[$item->api_model] == (string) get_class($model) && $item->id == $model->id; - } - }); - })->values(); - - // Preserve metadata - $sorted->setMetadata($original->getMetadata()); - - return $sorted; - } - - protected function extractModels($results) - { - $original = clone $results; - - // Group results by type - $resultsByType = $results->groupBy('api_model'); - - // Segregate results to load a single query per entity to load them all - $segregatedResults = $resultsByType->map(function ($collection, $type) { - $ids = $collection->pluck('id')->toArray(); - $class = $this->getTypeMap()[$type]; - - if (isset($class) && $class) { - $elements = $this->getTypeMap()[$type]::query()->ids($ids); - - if ($elements && method_exists($elements, 'ttl')) { - $elements->ttl($this->ttl); - } - - return $elements->get(); - } - - if (!$class) { - return $collection; // e.g. static-pages - } - }); - - // Remove empty categories - $filtered = $segregatedResults->filter(function ($value, $key) { - return !empty($value); - }); - - return $filtered; - } - - protected function makeModelsFlat($results) - { - $original = clone $results; - - // It's more efficient to get segregated results, and then reshuffle them into the - // original order - $segregatedResults = $this->makeModels($results); - - // Mix them all up together - $flatResults = CollectionHelpers::collectApi(array_filter(Arr::flatten($segregatedResults))); - - // Sort results in their original order - $sorted = $flatResults->sortBy(function ($model, $key) use ($original) { - return $original->search(function ($item, $key) use ($model) { - if (isset($this->getTypeMap()[$item->api_model])) { - return $this->getTypeMap()[$item->api_model] == (string) get_class($model) && $item->id == $model->id; - } - }); - })->values(); - - // Preserve metadata - $sorted->setMetadata($original->getMetadata()); - - return $sorted; - } - - protected function makeModels($results) - { - $original = clone $results; - - // Group results by type - $resultsByType = $results->groupBy('api_model'); - - // Segregate results to load a single query per entity to load them all - $segregatedResults = $resultsByType->map(function ($collection, $type) { - $class = $this->getTypeMap()[$type]; - - if (isset($class) && $class) { - $elements = $collection->map(function ($searchItem) use ($class) { - $item = new $class($searchItem->getAttributes()); - - return $item; - }); - - return $elements; - } - - if (!$class) { - return $collection; // e.g. static-pages - } - }); - - // Remove empty categories - $filtered = $segregatedResults->filter(function ($value, $key) { - return !empty($value); - }); - - return $filtered; - } - - protected function getTypeMap() - { - return $this->model->typeMap; - } -} diff --git a/app/Libraries/Api/Builders/ApiQueryBuilder.php b/app/Libraries/Api/Builders/ApiQueryBuilder.php deleted file mode 100644 index 9574b3c7..00000000 --- a/app/Libraries/Api/Builders/ApiQueryBuilder.php +++ /dev/null @@ -1,623 +0,0 @@ -', '<=', '>=', '<>', '!=', '<=>' - ]; - - /** - * The orderings for the query. - * - * @var array - */ - public $orders; - - /** - * The maximum number of records to return. - * - * @var int - */ - public $limit; - - /** - * The number of records to skip. - * - * @var int - */ - public $offset; - - /** - * Whether to apply boosting or not - * - * @var boolean - */ - public $boost = true; - - /** - * The current page number - * - * @var int - */ - public $page; - - /** - * The database query grammar instance. - * - * @var \Illuminate\Database\Query\Grammars\Grammar - */ - public $grammar; - - /** - * The Cache TTL for this specific query builder - * - * @var array - */ - public $ttl; - - /** - * The columns that should be returned. - * - * @var array - */ - public $columns; - - /** - * The ids of the records that should be returned. - * - * @var array - */ - public $ids = []; - - /** - * The list of extra fields to be included - * - * @var array - */ - public $include = []; - - /** - * The where constraints for the query. - * - * @var array - */ - public $wheres = []; - - /** - * Search constraints for the query. - * - * @var string - */ - public $searchText; - - /** - * Search parameters for a raw ES query. - * - * @var array - */ - public $searchParameters = []; - - /** - * Completely raw ES query. - * - * @var array - */ - public $rawQuery = []; - - /** - * Aggregations parameters for a raw ES query. - * - * @var array - */ - public $aggregationParameters = []; - - /** - * Search specific resources. Useful only for general searches - * - * @var array - */ - public $searchResources = []; - - /** - * Pagination data saved after a request - */ - public $paginationData; - - /** - * Aggregation data saved after a request - */ - public $aggregationsData; - - /** - * Suggestion data saved after a request - */ - public $suggestionsData; - - public function __construct($connection, $grammar = null) - { - $this->connection = $connection; - $this->grammar = $grammar ?: $connection->getQueryGrammar(); - } - - /** - * Bypass whereNotIn function until it's implemented on the API - * - */ - public function whereNotIn($column, $values, $boolean = 'and') - { - return $this; - } - - public function whereIn($column, $values, $boolean = 'and', $not = false) - { - if ($column == 'id') { - $this->ids($values); - - return $this; - } - - throw new \Exception('whereIn function has been defined only for IDS at the API Query Builder'); - } - - /** - * Add a basic where clause to the query. - * - * @param string|array|\Closure $column - * @param string|null $operator - * @param mixed $value - * @param string $boolean - * @return $this - */ - public function where($column, $operator = null, $value = null, $boolean = 'and') - { - // If the column is an array, we will assume it is an array of key-value pairs - // and can add them each as a where clause. We will maintain the boolean we - // received when the method was called and pass it into the nested where. - if (is_array($column)) { - throw new \Exception('where function should be called with 1 level of nesting. No arrays.'); - } - - // If the given operator is not found in the list of valid operators we will - // assume that the developer is just short-cutting the '=' operators and - // we will set the operators to '=' and set the values appropriately. - if ($this->invalidOperator($operator)) { - [$value, $operator] = [$operator, '=']; - } - - // Now that we are working with just a simple query we can put the elements - // in our array and add the query binding to our array of bindings that - // will be bound to each SQL statements when it is finally executed. - $type = 'Basic'; - - $this->wheres[] = compact( - 'type', - 'column', - 'operator', - 'value', - 'boolean' - ); - - return $this; - } - - /** - * Add an "order by" clause to the query. - * - * @param string $column - * @param string $direction - * @return $this - */ - public function orderBy($column, $direction = 'asc') - { - $this->orders[] = [ - $column => ['order' => strtolower($direction) == 'asc' ? 'asc' : 'desc'] - ]; - - return $this; - } - - /** - * Add an "ids" clause to the query. This will bring only records with these ids - * - * @return $this - */ - public function ids($ids = []) - { - if (!empty($ids)) { - $this->ids = $ids; - } - - return $this; - } - - /** - * Add an "includes" clause to the query. This will add those attributes - * - * @return $this - */ - public function include($inclusions = []) - { - if (!empty($inclusions)) { - $this->include = $inclusions; - } - - return $this; - } - - /** - * Paginate the given query into a simple paginator. - * - * @param int $perPage - * @param array $columns - * @param string $pageName - * @param int|null $page - * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator - */ - public function paginate($perPage = 15, $columns = [], $pageName = 'page', $page = null) - { - $page = $page ?: Paginator::resolveCurrentPage($pageName); - - $results = $this->forPage($page, $perPage)->get($columns); - - $paginationData = $this->getPaginationData(); - $total = $paginationData ? $paginationData->total : $results->count(); - - $data = $results['body']->data; - - return $this->paginator($data, $total, $perPage, $page, [ - 'path' => Paginator::resolveCurrentPath(), - 'pageName' => $pageName, - ]); - } - - /** - * Create a new length-aware paginator instance. - * - * @param \Illuminate\Support\Collection $items - * @param int $total - * @param int $perPage - * @param int $currentPage - * @param array $options - * @return \Illuminate\Pagination\LengthAwarePaginator - */ - protected function paginator($items, $total, $perPage, $currentPage, $options) - { - return new LengthAwarePaginator( - $items, - $total, - $perPage, - $currentPage, - $options - ); - } - - /** - * Set the limit and offset for a given page. - * - * @param int $page - * @param int $perPage - * @return \Illuminate\Database\Query\Builder|static - */ - public function forPage($page, $perPage = 15) - { - $this->page = $page; - - return $this->skip(($page - 1) * $perPage)->take($perPage); - } - - /** - * Alias to set the "offset" value of the query. - * - * @param int $value - * @return \Illuminate\Database\Query\Builder|static - */ - public function skip($value) - { - return $this->offset($value); - } - - /** - * Set the "offset" value of the query. - * - * @param int $value - * @return $this - */ - public function offset($value) - { - $this->offset = max(0, $value); - - return $this; - } - - /** - * Alias to set the "limit" value of the query. - * - * @param int $value - * @return \Illuminate\Database\Query\Builder|static - */ - public function take($value) - { - return $this->limit($value); - } - - /** - * Set the "limit" value of the query. - * - * @param int $value - * @return $this - */ - public function limit($value) - { - if ($value >= 0) { - $this->limit = $value; - } - - return $this; - } - - /** - * Set the "boost" value of the query. - * - * @param boolean $value - * @return $this - */ - public function boost($value = true) - { - $this->boost = $value; - - return $this; - } - - /** - * Search for specific resources - * - * @return $this - */ - public function resources($resources) - { - $this->searchResources = $resources; - - return $this; - } - - /** - * Perform a search - * - * @param string $search - * @return $this - */ - public function search($search) - { - $this->searchText = empty($search) ? null : $search; - - return $this; - } - - /** - * Perform a raw ES search - * - * @param array $search - * @return $this - */ - public function rawSearch($search) - { - $this->searchParameters = array_merge_recursive($this->searchParameters, $search); - - return $this; - } - - /** - * Perform a completely raw ES query - * - * @param array $search - * @return $this - */ - public function rawQuery($search) - { - $this->rawQuery = $search; - - return $this; - } - - /** - * Add aggregations to the raw ES search - * - * @param array $aggregations - * @return $this - */ - public function aggregations($aggregations) - { - $this->aggregationParameters = array_merge_recursive($this->aggregationParameters, $aggregations); - - return $this; - } - - /** - * Execute a get query and setup pagination data - * - * @param array $columns - * @return \Illuminate\Support\Collection - */ - public function get($columns = [], $endpoint = null) - { - $original = $this->columns; - - if (is_null($original)) { - $this->columns = $columns; - } - - $results = $this->runGet($endpoint); - - // If we got anything different than a HIT return the body - if (isset($results->status) && $results->status != 200) { - if (isset($results->body)) { - return $results->body; - } - - return $results; - } - - $this->columns = $original; - - if (is_array($results->body)) { - // If it's an msearch result return first element - $collection = CollectionHelpers::collectApi($results->body[0]->data); - } elseif (is_array($results->body->data)) { - // If it's a single element return as a collection with 1 element - $collection = CollectionHelpers::collectApi($results->body->data); - } else { - $collection = CollectionHelpers::collectApi([$results->body->data]); - } - - $collection = $this->getSortedCollection($collection); - - $collection->setMetadata([ - 'pagination' => $results->body->pagination ?? null, - 'aggregations' => $results->body->aggregations ?? null, - 'suggestions' => $results->body->suggest ?? null - ]); - - return $collection; - } - - /** - * Execute a get query and return a raw response - * - * @param array $columns - * @return \Illuminate\Support\Collection - */ - public function getRaw($columns = [], $endpoint = null) - { - $original = $this->columns; - - if (is_null($original)) { - $this->columns = $columns; - } - - $results = $this->runGet($endpoint); - - if (is_array($results->body)) { - $collection = CollectionHelpers::collectApi($results->body); - } else { - $collection = CollectionHelpers::collectApi([$results->body]); - } - - $collection = $this->getSortedCollection($collection); - - $collection->setMetadata([ - 'pagination' => $results->body->pagination ?? null, - 'aggregations' => $results->body->aggregations ?? null, - 'suggestions' => $results->body->suggest ?? null - ]); - - return $collection; - } - - /** - * Execute a GET query and return the total number of results noted in the - * pagination data. - */ - public function count($endpoint = null): int - { - return $this->limit(0)->get([], $endpoint)->getMetadata('pagination')->total; - } - - public function getPaginationData() - { - return $this->paginationData; - } - - /** - * Build and execute against the API connection a GET call - * - * @return array - */ - public function runGet($endpoint) - { - $grammar = null; - - if (Str::endsWith($endpoint, '/msearch')) { - $grammar = new MsearchGrammar(); - } elseif (Str::endsWith($endpoint, '/search')) { - $grammar = new SearchGrammar(); - } - - return $this->connection->ttl($this->ttl)->get($endpoint, $this->resolveParameters($grammar)); - } - - /** - * Use grammar to generate all parameters from the scopes as an array - * - * @return string - */ - public function resolveParameters($grammar = null) - { - if ($grammar) { - return $grammar->compileParameters($this); - } - - return $this->grammar->compileParameters($this); - } - - /** - * Set a specific Caching TTL for this request - * - * @return array - */ - public function ttl($ttl = null) - { - $this->ttl = $ttl; - - return $this; - } - - /** - * Determine if the given operator is supported. - * - * @param string $operator - * @return bool - */ - protected function invalidOperator($operator) - { - return !in_array(strtolower($operator), $this->operators, true); - } - - /** - * WEB-1626: If this was an `ids` query, reorder results to match `ids`. - */ - private function getSortedCollection($collection) - { - if (empty($this->ids)) { - return $collection; - } - - return $collection->sort(function ($a, $b) use ($collection) { - if (!isset($a->id) || !isset($b->id)) { - return 0; - } - - $ia = array_search($a->id, $this->ids); - $ib = array_search($b->id, $this->ids); - - if ($ia === $ib) { - return 0; - } - - return ($ia < $ib) ? -1 : 1; - }); - } -} diff --git a/app/Libraries/Api/Builders/Connection/AicConnection.php b/app/Libraries/Api/Builders/Connection/AicConnection.php deleted file mode 100644 index 0964a7d1..00000000 --- a/app/Libraries/Api/Builders/Connection/AicConnection.php +++ /dev/null @@ -1,154 +0,0 @@ -client = \App::make('ApiClient'); - $this->useDefaultQueryGrammar(); - } - - protected function useDefaultQueryGrammar() - { - $this->queryGrammar = new $this->defaultGrammar(); - } - - public function getQueryGrammar() - { - return $this->queryGrammar; - } - - public function setQueryGrammar($queryGrammar) - { - return $this->queryGrammar = $queryGrammar; - } - - /** - * Define a custom TTL for this connection instance - * - * @param integer $ttl - * @return object - */ - public function ttl($ttl = null) - { - $this->ttl = $ttl; - - return $this; - } - - /** - * Run a get statement against the API. - * - * @param array $params - * @return object - */ - public function get($endpoint, $params) - { - $response = $this->execute($endpoint, $params); - - return $response; - } - - /** - * Execute a general call to the API client - * - * @param array $params - * @return object - */ - public function execute($endpoint = null, $params = []) - { - $headers = $this->client->headers($params); - $options = $headers; - - $queryKeys = ['ids', 'include']; - $queryParams = Arr::only($params, $queryKeys); - $bodyParams = Arr::except($params, $queryKeys); - - $verb = empty($bodyParams) ? 'GET' : 'POST'; - - if (in_array(config('api.force_verb'), ['GET', 'POST'])) { - $verb = config('api.force_verb'); - } - - if ($verb === 'GET') { - if (!empty($params)) { - // WEB-979: See DecodeParams middleware in data-aggregator - $endpoint = $endpoint . '?params=' . urlencode(json_encode($params)); - } - } else { - if (!empty($bodyParams)) { - $adaptedParameters = $this->client->adaptParameters($params); - $options = array_merge($adaptedParameters, $headers); - } - } - if (config('api.logger')) { - \Log::info($verb . ' ' . $endpoint); - \Log::info(print_r($options, true)); - $responseTimerStart = microtime(true); - } - - // Perform API request and caching - if (config('api.cache_enabled')) { - $cacheKey = $this->buildCacheKey($verb, $endpoint, $options, config('api.cache_version')); - - // Manual cachebusting - $decacheHash = Request::input('nocache'); - - if ($decacheHash && config('api.cache_buster') && $decacheHash === config('api.cache_buster')) { - \Cache::forget($cacheKey); - \Log::warning('cache busted'); - } - - // Use default TTL if no explicit has been defined - $ttl = $this->ttl ?? config('api.cache_ttl'); - $response = \Cache::remember($cacheKey, $ttl, function () use ($ttl, $verb, $endpoint, $options) { - // WEB-2259: Error handling is done in the ApiConsumer - $response = $this->client->request($verb, $endpoint, $options); - if (config('api.logger')) { - \Log::info('cache ttl = ' . $ttl . ' seconds'); - } - return $response; - }); - if (config('api.logger')) { - \Log::info('response time = ' . microtime(true) - $responseTimerStart . ' seconds'); - } - if (isset($response->status) && $response->status != 200) { - \Cache::forget($cacheKey); - } - return $response; - } - $response = $this->client->request($verb, $endpoint, $options); - if (config('api.logger')) { - \Log::info('response time = ' . microtime(true) - $responseTimerStart . ' seconds'); - \Log::info((array) $response->body); - } - return $response; - } - - /** - * WEB-1805: The cache key *must* be 250 bytes or less! Otherwise, it'll silently fail on the lookup. - */ - protected function buildCacheKey() - { - return md5(json_encode(func_get_args())); - } -} diff --git a/app/Libraries/Api/Builders/Connection/ApiConnectionInterface.php b/app/Libraries/Api/Builders/Connection/ApiConnectionInterface.php deleted file mode 100644 index 0e0b4547..00000000 --- a/app/Libraries/Api/Builders/Connection/ApiConnectionInterface.php +++ /dev/null @@ -1,10 +0,0 @@ -columns; - - // To compile the query, we'll spin through each component of the query and - // see if that component exists. If it does we'll just call the compiler - // function for the component which is responsible for making the parameters - $compiled = $this->compileComponents($query); - - $query->columns = $original; - - return $compiled; - } - - /** - * Compile the components necessary for a select clause. - * - * @param ApiQueryBuilder $query - * @return array - */ - protected function compileComponents($query) - { - $parameters = []; - - foreach ($this->selectComponents as $component) { - // To compile the query, we'll spin through each component of the query and - // see if that component exists. If it does we'll just call the compiler - // function for the component which is responsible for making the parameter/s. - if (!is_null($query->{$component})) { - $method = 'compile' . ucfirst($component); - - $parameters = array_merge($parameters, $this->{$method}($query, $query->{$component})); - } - } - - return $parameters; - } - - /** - * Compile the "where" portions of the query. - * - * @param ApiQueryBuilder $query - * @return string - */ - protected function compileWheres($query) - { - return []; - } - - /** - * Compile the "columns" portions of the query. This translates to 'fields' - * which are the columns the API will return. - * - * @param ApiQueryBuilder $query - * @return array - */ - protected function compileColumns($query, $columns) - { - return empty($columns) ? [] : ['fields' => join(',', $columns)]; - } - - /** - * Compile the "include" portions of the query. - * - * @param ApiQueryBuilder $query - * @return array - */ - protected function compileInclude($query, $columns) - { - return empty($columns) ? [] : ['include' => join(',', $columns)]; - } - - /** - * Compile the "ids" portions of the query. This will filter by an IDs array - * - * @param ApiQueryBuilder $query - * @return array - */ - protected function compileIds($query, $ids) - { - return empty($ids) ? [] : ['ids' => join(',', $ids)]; - } - - protected function compileSearchResources($query, $resources) - { - return empty($resources) ? [] : ['resources' => join(',', $resources)]; - } - - protected function compileSearchText($query, $text) - { - if ($text) { - return ['q' => $text]; - } - - return []; - } - - protected function compileSearchParameters($query, array $elasticParameters) - { - return empty($elasticParameters) ? [] : ['query' => $elasticParameters]; - } - - protected function compileRawQuery($query, array $rawQuery) - { - return empty($rawQuery) ? [] : $rawQuery; - } - - protected function compileAggregationParameters($query, array $aggregations) - { - return empty($aggregations) ? [] : ['aggregations' => $aggregations]; - } - - protected function compileOrders($query, $order) - { - return empty($order) ? [] : ['sort' => $order]; - } - - protected function compileLimit($query, $limit) - { - return [ - 'limit' => $limit, - 'size' => $limit // Elasticsearch search parameter for limiting - ]; - } - - protected function compileOffset($query, $offset) - { - return [ - 'offset' => $offset, - 'from' => $offset // Elasticsearch search parameter for offset - ]; - } - - protected function compileBoost($query, $boost) - { - return []; - } - - protected function compilePage($query, $page) - { - return ['page' => $page]; - } -} diff --git a/app/Libraries/Api/Builders/Grammar/MsearchGrammar.php b/app/Libraries/Api/Builders/Grammar/MsearchGrammar.php deleted file mode 100644 index 45cd8c27..00000000 --- a/app/Libraries/Api/Builders/Grammar/MsearchGrammar.php +++ /dev/null @@ -1,31 +0,0 @@ - $columns]; - } -} diff --git a/app/Libraries/Api/Builders/Grammar/SearchGrammar.php b/app/Libraries/Api/Builders/Grammar/SearchGrammar.php deleted file mode 100644 index 6a3a4d69..00000000 --- a/app/Libraries/Api/Builders/Grammar/SearchGrammar.php +++ /dev/null @@ -1,13 +0,0 @@ - $boost, - ]; - } -} diff --git a/app/Libraries/Api/Builders/Relations/BelongsTo.php b/app/Libraries/Api/Builders/Relations/BelongsTo.php deleted file mode 100644 index adb2751b..00000000 --- a/app/Libraries/Api/Builders/Relations/BelongsTo.php +++ /dev/null @@ -1,36 +0,0 @@ -ownerKey = $ownerKey; - $this->relationName = $relationName; - $this->foreignKey = $foreignKey; - $this->child = $child; - $this->query = $query; - $this->parent = $child; - $this->related = $query->getModel(); - $this->addConstraints(); - } - - public function getResults() - { - if (in_array(\App\Models\Behaviors\HasApiModel::class, class_uses_recursive($this->child::class))) { - $this->child->refreshApi(); - $id = $this->child->getApiModel()->{$this->foreignKey}; - } else { - $id = $this->child->getAttribute($this->foreignKey); - } - if ($id) { - return $this->query->find($id); - } - return null; - } -} diff --git a/app/Libraries/Api/Builders/Relations/HasMany.php b/app/Libraries/Api/Builders/Relations/HasMany.php deleted file mode 100644 index d672649c..00000000 --- a/app/Libraries/Api/Builders/Relations/HasMany.php +++ /dev/null @@ -1,79 +0,0 @@ -query = $query; - $this->parent = $parent; - $this->localKey = $localKey; - $this->limit = $limit; - - $this->addConstraints(); - } - - public function addConstraints() - { - // On this case we just save the Id's array coming from the API - // And pass it to the query to filter by ID. - $ids = $this->parent->{$this->localKey}; - - // Sometimes it's just an id and not an array - $ids = is_array($ids) ? $ids : [$ids]; - - if ($this->limit > -1) { - $ids = array_slice($ids, 0, $this->limit); - } - - $this->query->ids($ids); - } - - /** - * Execute eager loading. - * - * @return \Illuminate\Database\Eloquent\Collection - */ - public function getEager() - { - return $this->get(); - } - - /** - * Execute the query - * - * @param array $columns - * @return \Illuminate\Database\Eloquent\Collection - */ - public function get($columns = []) - { - return $this->query->get($columns); - } -} diff --git a/app/Libraries/Api/Builders/Relations/NullRelation.php b/app/Libraries/Api/Builders/Relations/NullRelation.php deleted file mode 100644 index 5097cd50..00000000 --- a/app/Libraries/Api/Builders/Relations/NullRelation.php +++ /dev/null @@ -1,34 +0,0 @@ -client = new \GuzzleHttp\Client($options); - } - - /** - * Intercept the Guzzle request and return a cleaner object - * - */ - public function request($method, $uri = '', array $options = []) - { - // WEB-2259, WEB-2345: Allow 4xx and 5xx responses - $options = array_merge($options, ['http_errors' => false]); - - $response = $this->client->request($method, $uri, $options); - $contents = $response->getBody()->getContents(); - $body = json_decode($contents); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \Exception('Invalid JSON: ' . $contents); - } - - if (is_object($body) && isset($body->error) && $body->status !== 404) { - throw new \Exception('API error: ' . $contents); - } - - if (!in_array($response->getStatusCode(), [200, 404])) { - throw new \Exception('API invalid response: ' . $contents); - } - - return (object) [ - 'body' => $body, - 'status' => $response->getStatusCode() - ]; - } - - /** - * Adapt raw parameters to be implemented correctly by the client library. - * You can send parameters directly, or adapt them manually. - * This method should be defined for each consumer to ease configuration. - * - */ - public function adaptParameters($params) - { - return ['body' => json_encode($params)]; - } - - /** - * Add a default header and merge with headers coming from the parameters - * - */ - public function headers($params) - { - $headers = [ - 'Content-Type' => 'application/json', - 'Accept-Encoding' => 'gzip', - ]; - - if (config('api.token')) { - $headers = array_merge($headers, [ - 'Authorization' => 'Bearer ' . config('api.token'), - ]); - } - - if (isset($params['headers'])) { - $headers = array_merge($default, $params['headers']); - } - - return ['headers' => $headers]; - } - - /** - * Captures all method calls, and bypass them to the client in case they don't - * exists locally. This way it's easier to extend/ - * - */ - public function __call($name, $args): mixed - { - if (isset($this->__classMethods[$name]) && $this->__classMethods[$name] instanceof \Closure) { - return call_user_func_array($this->__classMethods[$name], $args); - } - - // If it doesn't exists locally push the call to the API client. - return $this->client->{$name}(...$args); - } -} diff --git a/app/Libraries/Api/Filters/Search.php b/app/Libraries/Api/Filters/Search.php deleted file mode 100644 index 6c528ce2..00000000 --- a/app/Libraries/Api/Filters/Search.php +++ /dev/null @@ -1,39 +0,0 @@ -searchString) && $this->searchColumns !== []) { - $shoulds = []; - foreach ($this->searchColumns as $col) { - if ($col != 'id' || is_numeric($this->searchString)) { - $shoulds[] = [ - 'match' => [ - $col => $this->searchString, - ], - ]; - } - } - $params = [ - 'bool' => [ - 'should' => $shoulds, - 'minimum_should_match' => 1, - ], - ]; - - // \App\Libraries\Api\Models\BaseApiModel with \App\Libraries\Api\Models\Behaviors\HasApiCalls::rawSearch() - return $builder->getModel()->rawSearch($params); - } - - return $builder; - } -} diff --git a/app/Libraries/Api/Models/ApiCollection.php b/app/Libraries/Api/Models/ApiCollection.php deleted file mode 100644 index 4b021d0f..00000000 --- a/app/Libraries/Api/Models/ApiCollection.php +++ /dev/null @@ -1,41 +0,0 @@ -metadata) { - if ($name) { - return $this->metadata->get($name); - } - - return $this->metadata; - } - } - - public function setMetadata(array|Collection $data): self - { - if (!($data instanceof Collection)) { - $data = collect($data); - } - if ($this->metadata) { - $this->metadata = $this->metadata->merge($data); - } else { - $this->metadata = $data; - } - - return $this; - } -} diff --git a/app/Libraries/Api/Models/BaseApiModel.php b/app/Libraries/Api/Models/BaseApiModel.php deleted file mode 100644 index 61512e83..00000000 --- a/app/Libraries/Api/Models/BaseApiModel.php +++ /dev/null @@ -1,1015 +0,0 @@ - '', - 'resource' => '', - 'search' => '', - ]; - - /** - * The number of entities to return for pagination. - */ - protected int $perPage = 15; - - /** - * Create a new Eloquent model instance. - */ - public function __construct(array $attributes = []) - { - $this->fill($attributes); - } - - public function scopePublished(Builder $query): Builder - { - if (config('aic.is_preview_mode')) { - return $query; - } - - // scopeVisible checks for its fillable columns - $query->visible(); - - if ($this->isFillable('published')) { - $query->wherePublished(true); - } - - return $query; - } - - public function scopeAccessible(Builder $query): Builder - { - if (! TwillPermissions::enabled()) { - return $query; - } - - $model = get_class($query->getModel()); - $moduleName = TwillPermissions::getPermissionModule(getModuleNameByModel($model)); - - if ($moduleName && ! Auth::user()->isSuperAdmin()) { - // Get all permissions the logged in user has regards to the model. - $allPermissions = Auth::user()->allPermissions(); - $allModelPermissions = (clone $allPermissions)->ofModel($model); - - // If the user has any module permissions, or global manage all modules permissions, all items will be return - if ( - (clone $allModelPermissions)->module() - ->whereIn('name', Permission::available(Permission::SCOPE_MODULE)) - ->exists() - || (clone $allPermissions)->global()->where('name', 'manage-modules')->exists() - ) { - return $query; - } - - // If the module is submodule, skip the scope. - if (strpos($moduleName, '.')) { - return $query; - } - - $authorizedItemsIds = $allModelPermissions->moduleItem()->pluck('permissionable_id'); - - return $query->whereIn($this->getTable() . '.id', $authorizedItemsIds); - } - - return $query; - } - - public function scopeOnlyTrashed(Builder $query): Builder - { - return $query->onlyTrashed(); - } - - public function scopeDraft(Builder $query): Builder - { - return $query->where("{$this->getTable()}.published", false); - } - - public function getTranslatedAttributes(): array - { - return $this->translatedAttributes ?? []; - } - - /** - * Fill the model with an array of attributes. - * - * @throws MassAssignmentException - */ - public function fill(array $attributes): self - { - $totallyGuarded = $this->totallyGuarded(); - - foreach ($this->fillableFromArray($attributes) as $key => $value) { - // The developers may choose to place some attributes in the "fillable" - // array, which means only those attributes may be set through mass - // assignment to the model, and all others will just be ignored. - if ($this->isFillable($key)) { - $this->setAttribute($key, $value); - } elseif ($totallyGuarded) { - throw new MassAssignmentException($key); - } - } - - return $this; - } - - /** - * Fill the model with an array of attributes. Force mass assignment. - */ - public function forceFill(array $attributes): self - { - // Since some versions of PHP have a bug that prevents it from properly - // binding the late static context in a closure, we will first store - // the model in a variable, which we will then use in the closure. - $model = $this; - - return static::unguarded(function () use ($model, $attributes) { - return $model->fill($attributes); - }); - } - - /** - * Get the fillable attributes of a given array. - */ - protected function fillableFromArray(array $attributes): array - { - if (count($this->fillable) > 0 && !static::$unguarded) { - return array_intersect_key($attributes, array_flip($this->fillable)); - } - - return $attributes; - } - - /** - * Create a new instance of the given model. - */ - public function newInstance($attributes = []): self - { - $model = new static((array) $attributes); - - return $model; - } - - /** - * Create a collection of models from plain arrays. - */ - public static function hydrate(array $items): array - { - $instance = new static(); - - $items = array_map(function ($item) use ($instance) { - return $instance->newInstance($item); - }, $items); - - return $items; - } - - /** - * Get the hidden attributes for the model. - */ - public function getHidden(): array - { - return $this->hidden; - } - - /** - * Set the hidden attributes for the model. - */ - public function setHidden(array $hidden): self - { - $this->hidden = $hidden; - - return $this; - } - - /** - * Make the given, typically visible, attributes hidden. - */ - public function makeHidden(mixed $attributes = null): self - { - $attributes = is_array($attributes) ? $attributes : func_get_args(); - - $this->hidden = array_merge($this->hidden, $attributes); - - return $this; - } - - /** - * Make the given, typically hidden, attributes visible. - */ - public function withHidden(mixed $attributes): self - { - $this->hidden = array_diff($this->hidden, (array) $attributes); - - return $this; - } - - /** - * Get the visible attributes for the model. - */ - public function getVisible(): array - { - return $this->visible; - } - - /** - * Set the visible attributes for the model. - */ - public function setVisible(array $visible): self - { - $this->visible = $visible; - - return $this; - } - - /** - * Make the given, typically hidden, attributes visible. - */ - public function makeVisible(mixed $attributes = null): self - { - $attributes = is_array($attributes) ? $attributes : func_get_args(); - - $this->visible = array_merge($this->visible, $attributes); - - return $this; - } - - /** - * Set the accessors to append to model arrays. - */ - public function setAppends(array $appends): self - { - $this->appends = $appends; - - return $this; - } - - /** - * Get the fillable attributes for the model. - */ - public function getFillable(): array - { - return $this->fillable; - } - - /** - * Set the fillable attributes for the model. - */ - public function fillable(array $fillable): self - { - $this->fillable = $fillable; - - return $this; - } - - /** - * Get the guarded attributes for the model. - */ - public function getGuarded(): array - { - return $this->guarded; - } - - /** - * Set the guarded attributes for the model. - */ - public function guard(array $guarded): self - { - $this->guarded = $guarded; - - return $this; - } - - /** - * Disable all mass assignable restrictions. - */ - public static function unguard(bool $state = true): void - { - static::$unguarded = $state; - } - - /** - * Enable the mass assignment restrictions. - */ - public static function reguard(): void - { - static::$unguarded = false; - } - - /** - * Determine if current state is "unguarded". - */ - public static function isUnguarded(): bool - { - return static::$unguarded; - } - - /** - * Run the given callable while being unguarded. - */ - public static function unguarded(callable $callback): mixed - { - if (static::$unguarded) { - return $callback(); - } - - static::unguard(); - - $result = $callback(); - - static::reguard(); - - return $result; - } - - /** - * Determine if the given attribute may be mass assigned. - */ - public function isFillable(string $key): bool - { - if (static::$unguarded) { - return true; - } - - // If the key is in the "fillable" array, we can of course assume that it's - // a fillable attribute. Otherwise, we will check the guarded array when - // we need to determine if the attribute is black-listed on the model. - if (in_array($key, $this->fillable)) { - return true; - } - - if ($this->isGuarded($key)) { - return false; - } - - return empty($this->fillable); - } - - /** - * Determine if the given key is guarded. - */ - public function isGuarded(string $key): bool - { - return in_array($key, $this->guarded) || $this->guarded == ['*']; - } - - /** - * Determine if the model is totally guarded. - */ - public function totallyGuarded(): bool - { - return count($this->fillable) == 0 && $this->guarded == ['*']; - } - - /** - * Convert the model instance to JSON. - */ - public function toJson($options = 0): string - { - return json_encode($this->jsonSerialize(), $options); - } - - /** - * Convert the object into something JSON serializable. - */ - public function jsonSerialize(): array - { - return $this->toArray(); - } - - /** - * Convert the model instance to an array. - */ - public function toArray(): array - { - return $this->attributesToArray(); - } - - /** - * Convert the model's attributes to an array. - */ - public function attributesToArray(): array - { - $attributes = $this->getArrayableAttributes(); - - $mutatedAttributes = $this->getMutatedAttributes(); - - // We want to spin through all the mutated attributes for this model and call - // the mutator for the attribute. We cache off every mutated attributes so - // we don't have to constantly check on attributes that actually change. - foreach ($mutatedAttributes as $key) { - if (!array_key_exists($key, $attributes)) { - continue; - } - - $attributes[$key] = $this->mutateAttributeForArray( - $key, - $attributes[$key] - ); - } - - // Next we will handle any casts that have been setup for this model and cast - // the values to their appropriate type. If the attribute has a mutator we - // will not perform the cast on those attributes to avoid any confusion. - foreach ($this->casts as $key => $value) { - if ( - !array_key_exists($key, $attributes) || - in_array($key, $mutatedAttributes) - ) { - continue; - } - - $attributes[$key] = $this->castAttribute( - $key, - $attributes[$key] - ); - } - - // Here we will grab all of the appended, calculated attributes to this model - // as these attributes are not really in the attributes array, but are run - // when we need to array or JSON the model for convenience to the coder. - foreach ($this->getArrayableAppends() as $key) { - $attributes[$key] = $this->mutateAttributeForArray($key, null); - } - - return $attributes; - } - - /** - * Get an attribute array of all arrayable attributes. - */ - protected function getArrayableAttributes(): array - { - return $this->getArrayableItems($this->attributes); - } - - /** - * Get all of the appendable values that are arrayable. - */ - protected function getArrayableAppends(): array - { - if (!count($this->appends)) { - return []; - } - - return $this->getArrayableItems( - array_combine($this->appends, $this->appends) - ); - } - - /** - * Get an attribute array of all arrayable values. - */ - protected function getArrayableItems(array $values): array - { - if (count($this->getVisible()) > 0) { - return array_intersect_key($values, array_flip($this->getVisible())); - } - - return array_diff_key($values, array_flip($this->getHidden())); - } - - /** - * Get an attribute from the model. - */ - public function getAttribute(string $key): mixed - { - if ( - array_key_exists($key, $this->attributes) || - $this->hasGetMutator($key) - ) { - return $this->getAttributeValue($key); - } - - return $this->getRelationValue($key); - } - - /** - * Get a plain attribute (not a relationship). - */ - protected function getAttributeValue(string $key): mixed - { - $value = $this->getAttributeFromArray($key); - - // If the attribute has a get mutator, we will call that then return what - // it returns as the value, which is useful for transforming values on - // retrieval from the model to a form that is more useful for usage. - if ($this->hasGetMutator($key)) { - return $this->mutateAttribute($key, $value); - } - - // If the attribute exists within the cast array, we will convert it to - // an appropriate native PHP type dependant upon the associated value - // given with the key in the pair. Dayle made this comment line up. - if ($this->hasCast($key)) { - $value = $this->castAttribute($key, $value); - } - - return $value; - } - - /** - * Get an attribute from the $attributes array. - */ - protected function getAttributeFromArray(string $key) - { - if (array_key_exists($key, $this->attributes)) { - return $this->attributes[$key]; - } - } - - /** - * Determine if a get mutator exists for an attribute. - */ - public function hasGetMutator(string $key): bool - { - return method_exists($this, 'get' . Str::studly($key) . 'Attribute'); - } - - /** - * Get the value of an attribute using its mutator. - */ - protected function mutateAttribute(string $key, mixed $value): mixed - { - return $this->{'get' . Str::studly($key) . 'Attribute'}($value); - } - - /** - * Get the value of an attribute using its mutator for array conversion. - */ - protected function mutateAttributeForArray(string $key, mixed $value): mixed - { - $value = $this->mutateAttribute($key, $value); - - return $value instanceof Arrayable ? $value->toArray() : $value; - } - - /** - * Determine whether an attribute should be casted to a native type. - */ - protected function hasCast(string $key): bool - { - return array_key_exists($key, $this->casts); - } - - /** - * Determine whether a value is JSON castable for inbound manipulation. - */ - protected function isJsonCastable(string $key): bool - { - return $this->hasCast($key) && - in_array($this->getCastType($key), ['array', 'json', 'object'], true); - } - - /** - * Get the type of cast for a model attribute. - */ - protected function getCastType(string $key): string - { - return trim(strtolower($this->casts[$key])); - } - - /** - * Cast an attribute to a native PHP type. - */ - protected function castAttribute(string $key, mixed $value): mixed - { - if (is_null($value)) { - return $value; - } - - switch ($this->getCastType($key)) { - case 'int': - case 'integer': - return (int) $value; - case 'real': - case 'float': - case 'double': - return (float) $value; - case 'string': - return (string) $value; - case 'bool': - case 'boolean': - return (bool) $value; - case 'object': - return $this->fromJson($value, true); - case 'array': - case 'json': - return $this->fromJson($value); - case 'collection': - return new BaseCollection($this->fromJson($value)); - case 'datetime': - return $this->asDateTime($value); - case 'date': - return $this->asDateTime($value)->toDateString(); - default: - return $value; - } - } - - /** - * Set a given attribute on the model. - */ - public function setAttribute(string $key, mixed $value): self - { - // First we will check for the presence of a mutator for the set operation - // which simply lets the developers tweak the attribute as it is set on - // the model, such as "json_encoding" an listing of data for storage. - if ($this->hasSetMutator($key)) { - $method = 'set' . Str::studly($key) . 'Attribute'; - - return $this->{$method}($value); - } - - if ($this->isJsonCastable($key) && !is_null($value)) { - $value = $this->asJson($value); - } - - $this->attributes[$key] = $value; - - return $this; - } - - /** - * Determine if a set mutator exists for an attribute. - */ - public function hasSetMutator(string $key): bool - { - return method_exists($this, 'set' . Str::studly($key) . 'Attribute'); - } - - /** - * Encode the given value as JSON. - */ - public function asJson(mixed $value): string - { - return json_encode($value); - } - - /** - * Return a timestamp as DateTime object. - */ - public function asDateTime(mixed $value): Carbon - { - if ($value instanceof Carbon) { - return $value; - } - - if ($value instanceof DateTimeInterface) { - return new Carbon( - $value->format('Y-m-d H:i:s.u'), - $value->getTimezone() - ); - } - - if (is_numeric($value)) { - return Carbon::createFromTimestamp($value); - } - - if ($this->isStandardDateFormat($value)) { - return Carbon::createFromFormat('Y-m-d', $value)->startOfDay(); - } - - return new Carbon($value); - } - - public function getClassName(): string - { - return (new \ReflectionClass($this))->getShortName(); - } - - /** - * Determine if the given value is a standard date format. - */ - protected function isStandardDateFormat(string $value): bool - { - return preg_match('/^(\d{4})-(\d{1,2})-(\d{1,2})$/', $value); - } - - /** - * Decode the given JSON back into an array or object. - */ - public function fromJson(string $value, bool $asObject = false): mixed - { - return json_decode($value, !$asObject); - } - - /** - * Clone the model into a new, non-existing instance. - */ - public function replicate(mixed $except = null): self - { - $except = $except ?: []; - - $attributes = Arr::except($this->attributes, $except); - - return with($instance = new static())->fill($attributes); - } - - /** - * Get all of the current attributes on the model. - */ - public function getAttributes(): array - { - return $this->attributes; - } - - /** - * Get the mutated attributes for a given instance. - */ - public function getMutatedAttributes(): array - { - $class = get_class($this); - - if (!isset(static::$mutatorCache[$class])) { - static::cacheMutatedAttributes($class); - } - - return static::$mutatorCache[$class]; - } - - /** - * Extract and cache all the mutated attributes of a class. - */ - public static function cacheMutatedAttributes(string $class): void - { - $mutatedAttributes = []; - - // Here we will extract all of the mutated attributes so that we can quickly - // spin through them after we export models to their array form, which we - // need to be fast. This'll let us know the attributes that can mutate. - if (preg_match_all('/(?<=^|;)get([^;]+?)Attribute(;|$)/', implode(';', get_class_methods($class)), $matches)) { - foreach ($matches[1] as $match) { - if (static::$snakeAttributes) { - $match = Str::snake($match); - } - - $mutatedAttributes[] = lcfirst($match); - } - } - - static::$mutatorCache[$class] = $mutatedAttributes; - } - - /** - * Create a new Eloquent Collection instance. - * - * @param array $models - * @return \Illuminate\Database\Eloquent\Collection - */ - public function newCollection($models = []): BaseCollection - { - if ($models instanceof BaseCollection) { - return $models; - } - - return new BaseCollection($models); - } - - /** - * Dynamically retrieve attributes on the model. - */ - public function __get(string $key): mixed - { - $value = null; - if ($key !== 'id' && method_exists($this, 'getAugmentedModel') && $this->getAugmentedModel()) { - $value = $this->getAugmentedModel()->{$key}; - } - return $value ?? $this->getAttribute($key); - } - - /** - * TODO: Consider adding _isset() here? e.g. for WEB-1245 - */ - - /** - * Dynamically set attributes on the model. - */ - public function __set(string $key, mixed $value): void - { - $this->setAttribute($key, $value); - } - - /** - * Determine if the given attribute exists. - */ - public function offsetExists(mixed $offset): bool - { - return isset($this->{$offset}); - } - - /** - * Get the value for a given offset. - */ - public function offsetGet(mixed $offset): mixed - { - return $this->{$offset}; - } - - /** - * Set the value for a given offset. - */ - public function offsetSet(mixed $offset, mixed $value): void - { - $this->{$offset} = $value; - } - - /** - * Unset the value for a given offset. - */ - public function offsetUnset(mixed $offset): void - { - unset($this->{$offset}); - } - - /** - * Get the number of models to return per page. - */ - public function getPerPage(): int - { - return $this->perPage; - } - - /** - * Set the number of models to return per page. - */ - public function setPerPage(int $perPage): self - { - $this->perPage = $perPage; - - return $this; - } - - /** - * Get the endpoint - */ - public function getEndpoint($type): string - { - return $this->endpoints[$type]; - } - - public function getTable() - { - // Is this a no-op on purpose? - } - - /** - * Implement Basic URLRoutable functions - * - */ - - public function getRouteKey() - { - return $this->getAttribute($this->getRouteKeyName()); - } - - public function getRouteKeyName() - { - return $this->getKeyName(); - } - - public function resolveRouteBinding($value, $field = null) - { - return $this->entity; - } - - public function resolveChildRouteBinding($childType, $value, $field) - { - } - - public function getKeyName() - { - return $this->primaryKey; - } - - /** - * Determine if an attribute exists on the model. - */ - public function __isset(string $key): bool - { - return (isset($this->attributes[$key]) || isset($this->relations[$key])) || - ($this->hasGetMutator($key) && !is_null($this->getAttributeValue($key))); - } - - /** - * Unset an attribute on the model. - */ - public function __unset(string $key): void - { - unset($this->attributes[$key]); - } - - /** - * Handle dynamic static method calls into the method. - */ - public static function __callStatic(string $method, array $parameters): mixed - { - $instance = new static(); - - return call_user_func_array([$instance, $method], $parameters); - } - - /** - * Convert the model to its string representation. - */ - public function __toString(): string - { - return $this->toJson(); - } -} diff --git a/app/Libraries/Api/Models/Behaviors/HasApiCalls.php b/app/Libraries/Api/Models/Behaviors/HasApiCalls.php deleted file mode 100644 index 30daf20d..00000000 --- a/app/Libraries/Api/Models/Behaviors/HasApiCalls.php +++ /dev/null @@ -1,151 +0,0 @@ -newQuery()->with( - is_string($relations) ? func_get_args() : $relations - ); - } - - /** - * Begin querying the model. - * - * @return App\Libraries\Api\Builders\ApiModelBuilder - */ - public static function query() - { - return (new static())->newQuery(); - } - - /** - * Begin querying the model. - * - * @return App\Libraries\Api\Builders\ApiModelBuilder - */ - public static function search($value) - { - return (new static())->newQuery()->search($value); - } - - /** - * Begin querying the model. - */ - public static function rawSearch($value): ApiModelBuilder - { - return (new static())->newQuery()->rawSearch($value); - } - /** - * Get a new query builder for the model's table. - * - * @return App\Libraries\Api\Builders\ApiModelBuilder - */ - public function newQuery() - { - return $this->registerDefaultScopes($this->newQueryWithoutScopes()); - } - - /** - * Register the global scopes for this builder instance. - * - * @param App\Libraries\Api\Builders\ApiModelBuilder $builder - * @return App\Libraries\Api\Builders\ApiModelBuilder - */ - public function registerDefaultScopes($builder) - { - foreach ($this->getDefaultScopes() as $name => $parameters) { - if (empty($parameters)) { - $builder->{$name}(); - } else { - $builder->{$name}($parameters); - } - } - - return $builder; - } - - /** - * Get the default scopes for this class instance. - * - * @return array - */ - public function getDefaultScopes() - { - return static::$defaultScopes; - } - - /** - * Get a new query builder that doesn't have any global scopes. - * - * @return App\Libraries\Api\Builders\ApiModelBuilder|static - */ - public function newQueryWithoutScopes() - { - $builder = $this->newApiModelBuilder($this->newApiQueryBuilder()); - - // Once we have the query builders, we will set the model instances so the - // builder can easily access any information it may need from the model - // while it is constructing and executing various queries against it. - return $builder->setModel($this) - ->with($this->with); - } - - public function newApiModelBuilder($query) - { - return new ApiModelBuilder($query); - } - - /** - * Get a new query builder instance for the connection. - * - * @return \Illuminate\Database\Query\Builder - */ - protected function newApiQueryBuilder() - { - $connection = $this->getConnection(); - - return new ApiQueryBuilder($connection, $connection->getQueryGrammar()); - } - - public function getConnection() - { - return new AicConnection(); - } - - /** - * Parse API endpoint. Replace brackets {name} with the 'name' attribute value (usually datahub_id) - * - * This way you can define an endpoint like: - * protected $endpoint = '/api/v1/exhibitions/{datahub_id}/artwork/{id}'; - * - * And the elements will be dinamically replaced with the params values passed - * - * @return string - */ - public function parseEndpoint($type, $params = []) - { - return preg_replace_callback('!\{(\w+)\}!', function ($matches) use ($params) { - $name = $matches[1]; - - return $params[$name]; - }, $this->getEndpoint($type)); - } -} diff --git a/app/Libraries/Api/Models/Behaviors/HasAugmentedModel.php b/app/Libraries/Api/Models/Behaviors/HasAugmentedModel.php deleted file mode 100644 index 87b6fd1b..00000000 --- a/app/Libraries/Api/Models/Behaviors/HasAugmentedModel.php +++ /dev/null @@ -1,62 +0,0 @@ -augmentedModel = $model; - $this->setAttribute('is_augmented', true); - } - - public function getAugmentedModelClass() - { - return $this->augmentedModelClass; - } - - public function getAugmentedModel() - { - $this->setAttribute('is_augmented', false); - if ($this->augmentedModel) { - $this->setAttribute('is_augmented', true); - return $this->augmentedModel; - } - if ($this->augmentedModel = $this->augmentedModelClass::where('datahub_id', $this->id)->first()) { - $this->setAttribute('is_augmented', true); - $this->augmentedModel->setApiModel($this); - return $this->augmentedModel; - } - return $this->augmentedModel; - } - - public function hasAugmentedModel(): bool - { - return (bool) $this->getAugmentedModel(); - } - - public function getIsAugmentedAttribute(): bool - { - return $this->hasAugmentedModel(); - } - - /** - * Bypass missed methods to the augmented model if existent - * - */ - public function __call($method, $parameters): mixed - { - if (method_exists($this, $method)) { - return $this->{$method}($parameters); - } - - if ($this->hasAugmentedModel() && method_exists($this->getAugmentedModel(), $method)) { - return $this->getAugmentedModel()->{$method}(...$parameters); - } - - return null; - } -} diff --git a/app/Libraries/Api/Models/Behaviors/HasRelationships.php b/app/Libraries/Api/Models/Behaviors/HasRelationships.php deleted file mode 100644 index 8e5ec947..00000000 --- a/app/Libraries/Api/Models/Behaviors/HasRelationships.php +++ /dev/null @@ -1,129 +0,0 @@ -relations[$relation] = $value; - - return $this; - } - - /** - * Define a one-to-many relationship. On this case we just load all ids coming - * from the API - * - * @param string $related - * @param string $localKey - * @return App\Libraries\Api\Builders\Relations\HasMany - */ - public function hasMany($related, $localKey = 'id', $limit = -1) - { - $queryInstance = $related::query(); - - // If we have no data in our localKey we ignore the relationship to - // avoid calling to an endpoint with no data - if (empty($this->{$localKey})) { - return; - } - - return $this->newHasMany( - $queryInstance, - $this, - $localKey, - $limit - ); - } - - /** - * Instantiate a new HasMany relationship. - * - * @param App\Libraries\Api\Builders\ApiQueryBuilder $query - * @param App\Libraries\Api\Models\BaseApiModel; $parent - * @param string $localKey - * @return App\Libraries\Api\Builders\Relations\HasMany - */ - protected function newHasMany($query, $parent, $localKey, $limit) - { - return new HasMany($query, $parent, $localKey, $limit); - } - - /** - * Get a relationship. - * - * @param string $key - * @return mixed - */ - public function getRelationValue($key) - { - // If the key already exists in the relationships array, it just means the - // relationship has already been loaded, so we'll just return it out of - // here because there is no need to query within the relations twice. - if ($this->relationLoaded($key)) { - return $this->relations[$key]; - } - - if (method_exists($this, $key)) { - return $this->getRelationshipFromMethod($key); - } - } - - protected function getRelationshipFromMethod($method) - { - $relation = $this->{$method}(); - - if (!$relation) { // Empty relationships return null to avoid calling the API - return null; - } - - return tap($relation->get(), function ($results) use ($method) { - $this->setRelation($method, $results); - }); - } - - /** - * Determine if the given relation is loaded. - * - * @param string $key - * @return bool - */ - public function relationLoaded($key) - { - return array_key_exists($key, $this->relations); - } - - public function getMorphClass() - { - $morphMap = Relation::morphMap(); - - if (!empty($morphMap) && in_array(static::class, $morphMap)) { - return array_search(static::class, $morphMap, true); - } - - if (static::class === Pivot::class) { - return static::class; - } - - return static::class; - } -} diff --git a/app/Libraries/SmartyPants.php b/app/Libraries/SmartyPants.php deleted file mode 100644 index 9ec010f9..00000000 --- a/app/Libraries/SmartyPants.php +++ /dev/null @@ -1,20 +0,0 @@ -lintValue($value)); - } - - /** - * Don't just check the `published` column! Also check - * `publish_start_date` and `publish_end_date`. See - * `scopeVisible` on `\A17\Twill\Models\Model`. - */ - public function scopePublished($query): Builder - { - if (config('aic.is_preview_mode')) { - return $query; - } - - // scopeVisible checks for its fillable columns - $query->visible(); - - if ($this->isFillable('published')) { - $query->wherePublished(true); - } - - return $query; - } - - public function scopeVisible($query): Builder - { - if (config('aic.is_preview_mode')) { - return $query; - } - - return parent::scopeVisible(...func_get_args()); - } - - public function getIsPublishedAttribute() - { - return static::published()->find($this->id) !== null; - } - - public function getPreviewUrl($baseUrl) - { - // $baseUrl is missing protocol, starts with //, and ends with / - // config('app.url') should have no https:// - return '//' . config('app.url') . '/p/' . encrypt($baseUrl . $this->slug); - } -} diff --git a/app/Models/Api/Audio.php b/app/Models/Api/Audio.php index d40d52ed..79c642e6 100644 --- a/app/Models/Api/Audio.php +++ b/app/Models/Api/Audio.php @@ -2,7 +2,7 @@ namespace App\Models\Api; -use App\Libraries\Api\Models\BaseApiModel; +use Aic\Hub\Foundation\Library\Api\Models\BaseApiModel; use Database\Factories\Api\HasApiFactory; class Audio extends BaseApiModel diff --git a/app/Models/Api/CollectionObject.php b/app/Models/Api/CollectionObject.php index 5db46fd3..56274a59 100644 --- a/app/Models/Api/CollectionObject.php +++ b/app/Models/Api/CollectionObject.php @@ -2,7 +2,7 @@ namespace App\Models\Api; -use App\Libraries\Api\Models\BaseApiModel; +use Aic\Hub\Foundation\Library\Api\Models\BaseApiModel; use App\Models\Behaviors\HasMediasApi; use Database\Factories\Api\HasApiFactory; use Illuminate\Database\Eloquent\Builder; diff --git a/app/Models/Api/Gallery.php b/app/Models/Api/Gallery.php index 0dad0b08..0afa996b 100644 --- a/app/Models/Api/Gallery.php +++ b/app/Models/Api/Gallery.php @@ -2,7 +2,7 @@ namespace App\Models\Api; -use App\Libraries\Api\Models\BaseApiModel; +use Aic\Hub\Foundation\Library\Api\Models\BaseApiModel; use Database\Factories\Api\HasApiFactory; class Gallery extends BaseApiModel diff --git a/app/Models/ApiRelation.php b/app/Models/ApiRelation.php index 11eb3ea2..e8122417 100644 --- a/app/Models/ApiRelation.php +++ b/app/Models/ApiRelation.php @@ -2,6 +2,7 @@ namespace App\Models; +use Aic\Hub\Foundation\Library\Api\Models\AbstractModel; use Illuminate\Database\Eloquent\Relations\HasOne; class ApiRelation extends AbstractModel diff --git a/app/Models/Audio.php b/app/Models/Audio.php index eccf2983..40e49236 100644 --- a/app/Models/Audio.php +++ b/app/Models/Audio.php @@ -2,8 +2,9 @@ namespace App\Models; -use App\Libraries\Api\Builders\Relations\NullRelation; -use App\Models\Behaviors\HasApiModel; +use Aic\Hub\Foundation\Library\Api\Builders\Relations\NullRelation; +use Aic\Hub\Foundation\Library\Api\Models\AbstractModel; +use Aic\Hub\Foundation\Library\Api\Models\Behaviors\HasApiModel; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\HasOne; diff --git a/app/Models/Behaviors/HasApiModel.php b/app/Models/Behaviors/HasApiModel.php deleted file mode 100644 index 26954318..00000000 --- a/app/Models/Behaviors/HasApiModel.php +++ /dev/null @@ -1,84 +0,0 @@ -getApiModel(); - $this->augmentWithApiModel(); - return $this; - } - - public function getApiModel() - { - if (!$this->apiModel) { - $this->setApiModel($this->apiModelClass::query()->find($this->datahub_id)); - } - return $this->apiModel; - } - - public function setApiModel(TwillModelContract $model) - { - $this->apiModel = $model; - } - - public function getTitleAttribute(): string - { - return (string) ($this->attributes['title'] ?? $this->getApiModel()?->getAttribute('title')); - } - - /** - * Augment the entity with the values coming from the API. - * TODO: Solve name collisions - */ - public function augmentWithApiModel() - { - foreach ($this->apiModel->toArray() as $key => $value) { - if ($this->hasAttribute($key)) { - // TODO: If the attribute already exists un-tie with a mapping array and set the attr. - // Something like ['id' => 'datahub_id'] - } else { - $this->setAttribute($key, $value); - array_push($this->apiFields, $key); - } - } - } - - public function hasAttribute($attr): bool - { - return array_key_exists($attr, $this->attributes) && !is_null($this->attributes[$attr]); - } - - public function getApiField($field) - { - return $this->getApiFields[$field]; - } - - /** - * Get API fields and its values stored at the object - */ - public function getApiFields(): object - { - return (object) array_reduce($this->apiFields, function ($result, $field) { - $result[$field] = $this->{$field}; - - return $result; - }, []); - } -} diff --git a/app/Models/Behaviors/HasApiRelations.php b/app/Models/Behaviors/HasApiRelations.php index 876f87b1..676abf75 100644 --- a/app/Models/Behaviors/HasApiRelations.php +++ b/app/Models/Behaviors/HasApiRelations.php @@ -2,7 +2,7 @@ namespace App\Models\Behaviors; -use App\Libraries\Api\Builders\Relations\BelongsTo; +use Aic\Hub\Foundation\Library\Api\Builders\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphToMany; /** diff --git a/app/Models/CollectionObject.php b/app/Models/CollectionObject.php index 6a3a0c54..8ac917f6 100644 --- a/app/Models/CollectionObject.php +++ b/app/Models/CollectionObject.php @@ -2,10 +2,11 @@ namespace App\Models; +use Aic\Hub\Foundation\Library\Api\Models\AbstractModel; use A17\Twill\Models\Behaviors\HasBlocks; use A17\Twill\Models\Behaviors\HasMedias; use A17\Twill\Models\Behaviors\HasTranslation; -use App\Models\Behaviors\HasApiModel; +use Aic\Hub\Foundation\Library\Api\Models\Behaviors\HasApiModel; use App\Models\Behaviors\HasApiRelations; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; diff --git a/app/Models/Gallery.php b/app/Models/Gallery.php index 7817caa6..24b5c71b 100644 --- a/app/Models/Gallery.php +++ b/app/Models/Gallery.php @@ -2,7 +2,8 @@ namespace App\Models; -use App\Models\Behaviors\HasApiModel; +use Aic\Hub\Foundation\Library\Api\Models\AbstractModel; +use Aic\Hub\Foundation\Library\Api\Models\Behaviors\HasApiModel; use App\Models\Behaviors\Transformable; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; diff --git a/app/Models/LoanObject.php b/app/Models/LoanObject.php index b29aaa74..98ec93db 100644 --- a/app/Models/LoanObject.php +++ b/app/Models/LoanObject.php @@ -2,6 +2,7 @@ namespace App\Models; +use Aic\Hub\Foundation\Library\Api\Models\AbstractModel; use A17\Twill\Models\Behaviors\HasMedias; use App\Models\Behaviors\HasApiRelations; use Illuminate\Database\Eloquent\Factories\HasFactory; diff --git a/app/Models/Transformers/ObjectTransformer.php b/app/Models/Transformers/ObjectTransformer.php index ab821016..7a91e05a 100644 --- a/app/Models/Transformers/ObjectTransformer.php +++ b/app/Models/Transformers/ObjectTransformer.php @@ -23,8 +23,8 @@ public function transform(TwillModelContract $object): array $longitude = $object->longitude ?? $object->gallery?->longitude; switch (get_class($object)) { case CollectionObject::class: - $thumbnail = $object->getApiModel()->image('iiif', 'thumbnail'); - $image = $object->getApiModel()->image('iiif'); + $thumbnail = $object->getApiModelFilled()->image('iiif', 'thumbnail'); + $image = $object->getApiModelFilled()->image('iiif'); $objectType = Util::COLLECTION_OBJECT; break; case LoanObject::class: diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 097b6420..1c0835db 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -4,7 +4,7 @@ use A17\Twill\Facades\TwillNavigation; use A17\Twill\View\Components\Navigation\NavigationLink; -use App\Libraries\Api\Consumers\GuzzleApiConsumer; +use Aic\Hub\Foundation\Library\Api\Consumers\GuzzleApiConsumer; use App\Libraries\DamsImageService; use App\Models; use Illuminate\Database\Eloquent\Relations\Relation; diff --git a/app/Repositories/Behaviors/HandleApiBrowsers.php b/app/Repositories/Behaviors/HandleApiBrowsers.php index dc028d8f..b2e2a35f 100644 --- a/app/Repositories/Behaviors/HandleApiBrowsers.php +++ b/app/Repositories/Behaviors/HandleApiBrowsers.php @@ -4,7 +4,7 @@ use A17\Twill\Models\RelatedItem; use App\Models\ApiRelation; -use App\Libraries\Api\Models\BaseApiModel; +use Aic\Hub\Foundation\Library\Api\Models\BaseApiModel; use App\Helpers\UrlHelpers; use DamsImageService; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -44,7 +44,7 @@ trait HandleApiBrowsers protected $apiBrowsers = []; /** - * @param \App\Libraries\Api\Models\BaseApiModel $object + * @param \Aic\Hub\Foundation\Library\Api\Models\BaseApiModel $object * @param array $fields * @return void */ @@ -71,7 +71,7 @@ public function afterSaveHandleApiBrowsers($object, $fields) } /** - * @param \App\Libraries\Api\Models\BaseApiModel $object + * @param \Aic\Hub\Foundation\Library\Api\Models\BaseApiModel $object * @param array $fields * @return array */ diff --git a/composer.json b/composer.json index 441c3ec8..dde41b4a 100644 --- a/composer.json +++ b/composer.json @@ -2,12 +2,17 @@ "name": "aic/mobile-cms", "type": "project", "description": "Art Institute of Chicago mobile app CMS", - "keywords": ["mobile", "museum", "musetech", "art institute of chicago"], + "keywords": [ + "mobile", + "museum", + "musetech", + "art institute of chicago" + ], "license": "AGPL-3.0-or-later", "repositories": [ { - "type": "vcs", - "url": "https://github.com/art-institute-of-chicago/data-hub-foundation.git" + "type": "path", + "url": "../data-hub-foundation" }, { "type": "package", @@ -37,9 +42,8 @@ ], "require": { "php": "^8.1", - "aic/data-hub-foundation": "^2.3", + "aic/data-hub-foundation": "dev-feature/api-models", "area17/twill": "^3.0", - "guzzlehttp/guzzle": "^7.2", "laravel/framework": "^10.8", "laravel/sanctum": "^3.2", "laravel/tinker": "^2.8", diff --git a/composer.lock b/composer.lock index ee269455..0772f0e5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,26 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e199cc8c27df6214425ee6adc94b9476", + "content-hash": "7f997c8520c2d96c9665887082c28b32", "packages": [ { "name": "aic/data-hub-foundation", - "version": "2.3", - "source": { - "type": "git", - "url": "https://github.com/art-institute-of-chicago/data-hub-foundation.git", - "reference": "cc6d507a4ebdc5f46a578580158e589d738bc6ff" - }, + "version": "dev-feature/api-models", "dist": { - "type": "zip", - "url": "https://api.github.com/repos/art-institute-of-chicago/data-hub-foundation/zipball/cc6d507a4ebdc5f46a578580158e589d738bc6ff", - "reference": "cc6d507a4ebdc5f46a578580158e589d738bc6ff", - "shasum": "" + "type": "path", + "url": "../data-hub-foundation", + "reference": "26ea550b330306230d9af0550abde8268d13430e" }, "require": { "composer": "^2.2.0", "doctrine/dbal": "^3.0", "friendsofphp/php-cs-fixer": "^3.5", + "guzzlehttp/guzzle": "^7.9", "laravel/framework": "^10.0", "league/fractal": "^0.16.0", "netresearch/composer-patches-plugin": "^1.3.1", @@ -80,11 +75,9 @@ } ], "description": "Shared components for our data hub services.", - "support": { - "source": "https://github.com/art-institute-of-chicago/data-hub-foundation/tree/2.3", - "issues": "https://github.com/art-institute-of-chicago/data-hub-foundation/issues" - }, - "time": "2023-09-20T21:14:09+00:00" + "transport-options": { + "relative": true + } }, { "name": "area17/twill", @@ -2017,22 +2010,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.5.1", + "version": "7.9.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b964ca597e86b752cd994f27293e9fa6b6a95ed9", - "reference": "b964ca597e86b752cd994f27293e9fa6b6a95ed9", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -2041,10 +2034,11 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -2057,9 +2051,6 @@ "bamarni-bin": { "bin-links": true, "forward-command": false - }, - "branch-alias": { - "dev-master": "7.5-dev" } }, "autoload": { @@ -2125,7 +2116,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.5.1" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -2141,20 +2132,20 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:30:08+00:00" + "time": "2024-07-24T11:22:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.2", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "b94b2807d85443f9719887892882d0329d1e2598" + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", - "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", "shasum": "" }, "require": { @@ -2164,11 +2155,6 @@ "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, "autoload": { "files": [ "src/functions_include.php" @@ -2209,7 +2195,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.2" + "source": "https://github.com/guzzle/promises/tree/1.5.3" }, "funding": [ { @@ -2225,20 +2211,20 @@ "type": "tidelift" } ], - "time": "2022-08-28T14:55:35+00:00" + "time": "2023-05-21T12:31:43+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.5.0", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { @@ -2252,9 +2238,9 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -2325,7 +2311,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.5.0" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -2341,7 +2327,7 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:11:26+00:00" + "time": "2024-07-18T11:15:46+00:00" }, { "name": "guzzlehttp/uri-template", @@ -5353,16 +5339,16 @@ }, { "name": "psr/http-client", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { @@ -5399,26 +5385,26 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-04-10T20:12:12+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -5442,7 +5428,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -5454,9 +5440,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -6666,16 +6652,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.1", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -6683,12 +6669,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.3-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -6713,7 +6699,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -6729,7 +6715,7 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:25:55+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/error-handler", @@ -7674,34 +7660,30 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da" + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -7741,7 +7723,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" }, "funding": [ { @@ -7757,36 +7739,33 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -7825,7 +7804,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -7841,24 +7820,24 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -7868,12 +7847,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -7908,7 +7884,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -7924,83 +7900,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", @@ -11833,13 +11733,15 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "aic/data-hub-foundation": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.1" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.1" }, diff --git a/database/factories/Api/ApiFactory.php b/database/factories/Api/ApiFactory.php index da6ef7ef..39c73e07 100644 --- a/database/factories/Api/ApiFactory.php +++ b/database/factories/Api/ApiFactory.php @@ -2,7 +2,7 @@ namespace Database\Factories\Api; -use App\Libraries\Api\Models\BaseApiModel as ApiModel; +use Aic\Hub\Foundation\Library\Api\Models\BaseApiModel as ApiModel; use Closure; use Faker\Generator as FakerGenerator; use Illuminate\Container\Container; diff --git a/tests/Feature/ObjectSerializerTest.php b/tests/Feature/ObjectSerializerTest.php index a68f0874..daa898b8 100644 --- a/tests/Feature/ObjectSerializerTest.php +++ b/tests/Feature/ObjectSerializerTest.php @@ -35,6 +35,7 @@ public function test_serialize(): void $objects = collect()->concat($collectionObjects)->concat($loanObjects); $serializer = new ObjectSerializer(); $serialized = $serializer->serialize($objects); + dump($serialized, $objects); $this->assertArrayHasKey('objects', $serialized); $this->assertCount($collectionObjectCount + $loanObjectCount, $serialized['objects']); diff --git a/tests/MockApi.php b/tests/MockApi.php index a5d1febc..35e88027 100644 --- a/tests/MockApi.php +++ b/tests/MockApi.php @@ -2,8 +2,8 @@ namespace Tests; -use App\Libraries\Api\Consumers\GuzzleApiConsumer; -use App\Libraries\Api\Models\BaseApiModel as ApiModel; +use Aic\Hub\Foundation\Library\Api\Consumers\GuzzleApiConsumer; +use Aic\Hub\Foundation\Library\Api\Models\BaseApiModel as ApiModel; use GuzzleHttp\HandlerStack; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Middleware;