From c3ff6d3e7f4f3e3350071242441a781b8031224e Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 23 Nov 2023 16:21:44 +0800 Subject: [PATCH 1/9] if user is admin the FE should skip the verification step --- src/Http/Controllers/Internal/v1/OnboardController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Controllers/Internal/v1/OnboardController.php b/src/Http/Controllers/Internal/v1/OnboardController.php index d2b26bd..1f2e822 100644 --- a/src/Http/Controllers/Internal/v1/OnboardController.php +++ b/src/Http/Controllers/Internal/v1/OnboardController.php @@ -89,7 +89,7 @@ public function createAccount(OnboardRequest $request) 'status' => 'success', 'session' => $user->uuid, 'token' => $token->plainTextToken, - 'skipVerification' => $user->id === 1, + 'skipVerification' => $isAdmin, ]); } From cea16ffeb9cd476b30c9924ca307fdac5fc2893a Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 7 Dec 2023 10:34:36 +0800 Subject: [PATCH 2/9] bump version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bf3236d..717922b 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "fleetbase/core-api", - "version": "1.3.2", + "version": "1.3.3", "description": "Core Framework and Resources for Fleetbase API", "keywords": [ "fleetbase", From e49e69656fff325c817fe5eadd8cc1d40e43ce0f Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 14 Dec 2023 11:30:55 +0800 Subject: [PATCH 3/9] make filters expandable, also fix expansions implementation and add new method to update model meta properties --- src/Http/Filter/Filter.php | 10 ++++-- src/Providers/CoreServiceProvider.php | 11 +++++-- src/Support/Utils.php | 45 +++++++++++++++++++++++++++ src/Traits/Expandable.php | 14 ++++----- src/Traits/HasMetaAttributes.php | 12 ++++++- 5 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/Http/Filter/Filter.php b/src/Http/Filter/Filter.php index 580e131..4eb9401 100644 --- a/src/Http/Filter/Filter.php +++ b/src/Http/Filter/Filter.php @@ -3,6 +3,7 @@ namespace Fleetbase\Http\Filter; use Fleetbase\Support\Http; +use Fleetbase\Traits\Expandable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; use Illuminate\Support\Arr; @@ -10,6 +11,11 @@ abstract class Filter { + /** + * Make expandable. + */ + use Expandable; + /** * The request instance. * @@ -39,7 +45,7 @@ abstract class Filter public function __construct(Request $request) { $this->request = $request; - $this->session = $request->session(); + $this->session = $request->hasSession() ? $request->session() : session(); } /** @@ -79,7 +85,7 @@ private function applyFilter($name, $value) continue; } - if (method_exists($this, $methodName)) { + if (method_exists($this, $methodName) || static::isExpansion($methodName)) { call_user_func_array([$this, $methodName], [$value]); break; } diff --git a/src/Providers/CoreServiceProvider.php b/src/Providers/CoreServiceProvider.php index d26dfd6..ccf7343 100644 --- a/src/Providers/CoreServiceProvider.php +++ b/src/Providers/CoreServiceProvider.php @@ -13,6 +13,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider; +use Illuminate\Support\Str; /** * CoreServiceProvider. @@ -341,8 +342,14 @@ function ($ns) use ($className) { continue; } - $method = $class::$method ?? Expansion::isExpandable($target) ? 'expand' : 'mixin'; - $target::$method(new $class()); + try { + $target::expand(new $class()); + } catch (\Throwable $e) { + try { + $target::mixin(new $class()); + } catch (\Throwable $e) { + } + } } } diff --git a/src/Support/Utils.php b/src/Support/Utils.php index 2db5309..1e51115 100644 --- a/src/Support/Utils.php +++ b/src/Support/Utils.php @@ -2152,4 +2152,49 @@ public static function getDefaultMailFromAddress(?string $default = 'hello@fleet return $from; } + + /** + * Adds 'www.' to the beginning of a URL if it is not already present. + * + * This function checks if the given URL starts with 'http://' or 'https://'. + * If it does, it parses the URL and adds 'www.' to the host part if it's not already there. + * If the URL does not start with 'http://' or 'https://', it simply checks if 'www.' is + * already present at the start of the URL. If not, it adds 'www.'. + * + * @param string $url The URL to which 'www.' should be added if it's not already present. + * @return string The modified URL with 'www.' added if it was absent. + * + * Example usage: + * echo addWwwToUrl("example.com"); // Outputs: www.example.com + * echo addWwwToUrl("https://example.com"); // Outputs: https://www.example.com + */ + public static function addWwwToUrl($url) + { + // Check if the URL already starts with 'http://' or 'https://' + if (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) { + // Check if the URL starts with 'www.' + if (strpos($url, 'www.') !== 0) { + // Add 'www.' to the start of the URL + $url = 'www.' . $url; + } + } else { + // Parse the URL and extract its components + $parsedUrl = parse_url($url); + + // Check if the host is set and does not start with 'www.' + if (isset($parsedUrl['host']) && substr($parsedUrl['host'], 0, 4) !== 'www.') { + // Add 'www.' to the start of the host + $parsedUrl['host'] = 'www.' . $parsedUrl['host']; + } + + // Rebuild the URL + $url = (isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] . '://' : '') + . (isset($parsedUrl['host']) ? $parsedUrl['host'] : '') + . (isset($parsedUrl['path']) ? $parsedUrl['path'] : '') + . (isset($parsedUrl['query']) ? '?' . $parsedUrl['query'] : '') + . (isset($parsedUrl['fragment']) ? '#' . $parsedUrl['fragment'] : ''); + } + + return $url; + } } diff --git a/src/Traits/Expandable.php b/src/Traits/Expandable.php index e3ff031..6e770f8 100644 --- a/src/Traits/Expandable.php +++ b/src/Traits/Expandable.php @@ -2,8 +2,8 @@ namespace Fleetbase\Traits; -use Closure; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Str; trait Expandable { @@ -15,7 +15,7 @@ public static function expand($name, \Closure $closure = null) return static::expandFromClass($name); } - $class = get_class(new static()); + $class = get_class(app(static::class)); if (!isset(static::$added[$class])) { static::$added[$class] = []; @@ -59,21 +59,21 @@ public static function expandFromClass($class): void public static function hasExpansion(string $name): bool { - $class = get_class(new static()); + $class = get_class(app(static::class)); return isset(static::$added[$class][$name]); } public static function isExpansion(string $name): bool { - $class = get_class(new static()); + $class = get_class(app(static::class)); return static::hasExpansion($name) && static::$added[$class][$name] instanceof \Closure; } public static function getExpansionClosure(string $name) { - $class = get_class(new static()); + $class = get_class(app(static::class)); return static::$added[$class][$name]; } @@ -87,7 +87,7 @@ public function __call($method, $parameters) } if (static::isModel()) { - if (in_array($method, ['increment', 'decrement'])) { + if (method_exists($this, $method)) { return $this->$method(...$parameters); } @@ -97,7 +97,7 @@ public function __call($method, $parameters) DB::connection()->getPdo(); } catch (\Exception $e) { // Connection failed, or other error occurred - return; + return $this->$method(...$parameters); } return $this->forwardCallTo($this->newQuery(), $method, $parameters); diff --git a/src/Traits/HasMetaAttributes.php b/src/Traits/HasMetaAttributes.php index 6c8ad41..9561d39 100644 --- a/src/Traits/HasMetaAttributes.php +++ b/src/Traits/HasMetaAttributes.php @@ -4,6 +4,7 @@ use Fleetbase\Support\Utils; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; trait HasMetaAttributes { @@ -110,10 +111,19 @@ public function updateMeta($key, $value = null) $meta[$key] = static::prepareValue($value); $this->setAttribute('meta', $meta); - return $this->update(['meta' => $meta]); } + public function updateMetaProperties(array $data = []) + { + $currentMetaObject = data_get($this, 'meta', []); + $currentMetaObject = array_merge($currentMetaObject, $data); + + return DB::table($this->getTable())->where($this->getKeyName(), $this->getKey())->update([ + 'meta' => json_encode($currentMetaObject) + ]); + } + /** * Checks if key is missing from meta-data. * From 32954e16ae945afa61455adaa6cdc882f812ccdd Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 14 Dec 2023 11:34:20 +0800 Subject: [PATCH 4/9] remove unnecessary imports in `Fleetbase\Providers\CoreServiceProvider` --- src/Providers/CoreServiceProvider.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Providers/CoreServiceProvider.php b/src/Providers/CoreServiceProvider.php index ccf7343..5cee655 100644 --- a/src/Providers/CoreServiceProvider.php +++ b/src/Providers/CoreServiceProvider.php @@ -3,7 +3,6 @@ namespace Fleetbase\Providers; use Fleetbase\Models\Setting; -use Fleetbase\Support\Expansion; use Fleetbase\Support\NotificationRegistry; use Fleetbase\Support\Utils; use Illuminate\Console\Scheduling\Schedule; @@ -13,7 +12,6 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider; -use Illuminate\Support\Str; /** * CoreServiceProvider. From c34607c86df13e22273e8db8e1a9140c453936a0 Mon Sep 17 00:00:00 2001 From: Doljinsuren Enkhbayar Date: Thu, 14 Dec 2023 17:32:29 +0800 Subject: [PATCH 5/9] added organization controller --- .../Api/v1/OrganizationController.php | 47 +++++++++++++++++++ src/Http/Resources/Organization.php | 6 ++- src/routes.php | 13 +++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/Http/Controllers/Api/v1/OrganizationController.php diff --git a/src/Http/Controllers/Api/v1/OrganizationController.php b/src/Http/Controllers/Api/v1/OrganizationController.php new file mode 100644 index 0000000..875bdd5 --- /dev/null +++ b/src/Http/Controllers/Api/v1/OrganizationController.php @@ -0,0 +1,47 @@ +bearerToken(); + $isSecretKey = Str::startsWith($token, '$'); + + // Depending on API key format set the connection to find credential on + $connection = Str::startsWith($token, 'flb_test_') ? 'sandbox' : 'mysql'; + + // Find the API Credential record + $findApKey = ApiCredential::on($connection) + ->where(function ($query) use ($isSecretKey, $token) { + if ($isSecretKey) { + $query->where('secret', $token); + } else { + $query->where('key', $token); + } + }) + ->with(['company.owner']) + ->withoutGlobalScopes(); + + // Get the api credential model record + $apiCredential = $findApKey->first(); + + // Handle no api credential found + if (!$apiCredential) { + return response()->error('No API key found to fetch company details with.'); + } + + // Get the organization owning the API key + $organization = Company::where('uuid', $apiCredential->company_uuid)->first(); + + return new Organization($organization); + } +} diff --git a/src/Http/Resources/Organization.php b/src/Http/Resources/Organization.php index 286f223..fa81bdf 100644 --- a/src/Http/Resources/Organization.php +++ b/src/Http/Resources/Organization.php @@ -3,6 +3,8 @@ namespace Fleetbase\Http\Resources; use Fleetbase\Support\Http; +use Fleetbase\Models\Setting; + class Organization extends FleetbaseResource { @@ -25,10 +27,12 @@ public function toArray($request) 'timezone' => $this->timezone, 'logo_url' => $this->logo_url, 'backdrop_url' => $this->backdrop_url, + 'branding' => Setting::getBranding(), 'options' => $this->options, 'slug' => $this->slug, - 'created_at' => $this->created_at, 'status' => $this->status, + 'updated_at' => $this->updated_at, + 'created_at' => $this->created_at, ]; } } diff --git a/src/routes.php b/src/routes.php index fca5a05..7a1daad 100644 --- a/src/routes.php +++ b/src/routes.php @@ -21,6 +21,19 @@ function ($router) { $router->get('/', 'Controller@hello'); + /* + |-------------------------------------------------------------------------- + | Public/Consumable Routes + |-------------------------------------------------------------------------- + | + | Routes for users and public applications to consume. + */ + $router->prefix('v1') + ->namespace('Api\v1') + ->group(function ($router) { + $router->get('organizations','OrganizationController@getOrganization'); + }); + /* |-------------------------------------------------------------------------- | Internal Routes From 9dabd44002d94ce6ed0ffe8e54dfc0efff2470c0 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 18 Dec 2023 13:42:59 +0800 Subject: [PATCH 6/9] added default `logo_url` and `icon_url` attribute to branding --- src/Models/Setting.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Models/Setting.php b/src/Models/Setting.php index 40c3233..d03c865 100644 --- a/src/Models/Setting.php +++ b/src/Models/Setting.php @@ -159,7 +159,7 @@ public static function lookup(string $key, $defaultValue = null) public static function getBranding() { - $brandingSettings = ['id' => 1, 'uuid' => 1]; + $brandingSettings = ['id' => 1, 'uuid' => 1, 'icon_url' => null, 'logo_url' => null]; $iconUuid = static::where('key', 'branding.icon_uuid')->value('value'); $logoUuid = static::where('key', 'branding.logo_uuid')->value('value'); $defaultTheme = static::where('key', 'branding.default_theme')->value('value'); From 6a2bc619ee7e14c1260e8b98add54052a12fb35a Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 18 Dec 2023 13:44:24 +0800 Subject: [PATCH 7/9] ran linter --- src/Http/Controllers/Api/v1/OrganizationController.php | 8 ++++---- src/Http/Resources/Organization.php | 3 +-- src/Support/Utils.php | 3 ++- src/Traits/Expandable.php | 1 - src/Traits/HasMetaAttributes.php | 3 ++- src/routes.php | 10 +++++----- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Http/Controllers/Api/v1/OrganizationController.php b/src/Http/Controllers/Api/v1/OrganizationController.php index 875bdd5..0940bc7 100644 --- a/src/Http/Controllers/Api/v1/OrganizationController.php +++ b/src/Http/Controllers/Api/v1/OrganizationController.php @@ -2,21 +2,21 @@ namespace Fleetbase\Http\Controllers\Api\v1; -use Illuminate\Http\Request; use Fleetbase\Http\Controllers\Controller; use Fleetbase\Http\Resources\Organization; use Fleetbase\Models\ApiCredential; use Fleetbase\Models\Company; +use Illuminate\Http\Request; use Illuminate\Support\Str; class OrganizationController extends Controller { public function getOrganization(Request $request) { - $token = $request->bearerToken(); + $token = $request->bearerToken(); $isSecretKey = Str::startsWith($token, '$'); - // Depending on API key format set the connection to find credential on + // Depending on API key format set the connection to find credential on $connection = Str::startsWith($token, 'flb_test_') ? 'sandbox' : 'mysql'; // Find the API Credential record @@ -41,7 +41,7 @@ public function getOrganization(Request $request) // Get the organization owning the API key $organization = Company::where('uuid', $apiCredential->company_uuid)->first(); - + return new Organization($organization); } } diff --git a/src/Http/Resources/Organization.php b/src/Http/Resources/Organization.php index fa81bdf..e24e99e 100644 --- a/src/Http/Resources/Organization.php +++ b/src/Http/Resources/Organization.php @@ -2,9 +2,8 @@ namespace Fleetbase\Http\Resources; -use Fleetbase\Support\Http; use Fleetbase\Models\Setting; - +use Fleetbase\Support\Http; class Organization extends FleetbaseResource { diff --git a/src/Support/Utils.php b/src/Support/Utils.php index 1e51115..baf1d5e 100644 --- a/src/Support/Utils.php +++ b/src/Support/Utils.php @@ -2158,10 +2158,11 @@ public static function getDefaultMailFromAddress(?string $default = 'hello@fleet * * This function checks if the given URL starts with 'http://' or 'https://'. * If it does, it parses the URL and adds 'www.' to the host part if it's not already there. - * If the URL does not start with 'http://' or 'https://', it simply checks if 'www.' is + * If the URL does not start with 'http://' or 'https://', it simply checks if 'www.' is * already present at the start of the URL. If not, it adds 'www.'. * * @param string $url The URL to which 'www.' should be added if it's not already present. + * * @return string The modified URL with 'www.' added if it was absent. * * Example usage: diff --git a/src/Traits/Expandable.php b/src/Traits/Expandable.php index 6e770f8..7479401 100644 --- a/src/Traits/Expandable.php +++ b/src/Traits/Expandable.php @@ -3,7 +3,6 @@ namespace Fleetbase\Traits; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Str; trait Expandable { diff --git a/src/Traits/HasMetaAttributes.php b/src/Traits/HasMetaAttributes.php index 9561d39..62315a8 100644 --- a/src/Traits/HasMetaAttributes.php +++ b/src/Traits/HasMetaAttributes.php @@ -111,6 +111,7 @@ public function updateMeta($key, $value = null) $meta[$key] = static::prepareValue($value); $this->setAttribute('meta', $meta); + return $this->update(['meta' => $meta]); } @@ -120,7 +121,7 @@ public function updateMetaProperties(array $data = []) $currentMetaObject = array_merge($currentMetaObject, $data); return DB::table($this->getTable())->where($this->getKeyName(), $this->getKey())->update([ - 'meta' => json_encode($currentMetaObject) + 'meta' => json_encode($currentMetaObject), ]); } diff --git a/src/routes.php b/src/routes.php index 7a1daad..f917bf1 100644 --- a/src/routes.php +++ b/src/routes.php @@ -21,7 +21,7 @@ function ($router) { $router->get('/', 'Controller@hello'); - /* + /* |-------------------------------------------------------------------------- | Public/Consumable Routes |-------------------------------------------------------------------------- @@ -29,10 +29,10 @@ function ($router) { | Routes for users and public applications to consume. */ $router->prefix('v1') - ->namespace('Api\v1') - ->group(function ($router) { - $router->get('organizations','OrganizationController@getOrganization'); - }); + ->namespace('Api\v1') + ->group(function ($router) { + $router->get('organizations', 'OrganizationController@getOrganization'); + }); /* |-------------------------------------------------------------------------- From aa3c7457641108c5875b8556fea3a45358643a2c Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 18 Dec 2023 13:47:02 +0800 Subject: [PATCH 8/9] change endpoint to get current organization from `GET /v1/organizations` to `GET /v1/organizations/current` --- src/Http/Controllers/Api/v1/OrganizationController.php | 2 +- src/routes.php | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Http/Controllers/Api/v1/OrganizationController.php b/src/Http/Controllers/Api/v1/OrganizationController.php index 0940bc7..ce1e165 100644 --- a/src/Http/Controllers/Api/v1/OrganizationController.php +++ b/src/Http/Controllers/Api/v1/OrganizationController.php @@ -11,7 +11,7 @@ class OrganizationController extends Controller { - public function getOrganization(Request $request) + public function getCurrent(Request $request) { $token = $request->bearerToken(); $isSecretKey = Str::startsWith($token, '$'); diff --git a/src/routes.php b/src/routes.php index f917bf1..04e15a5 100644 --- a/src/routes.php +++ b/src/routes.php @@ -31,7 +31,12 @@ function ($router) { $router->prefix('v1') ->namespace('Api\v1') ->group(function ($router) { - $router->get('organizations', 'OrganizationController@getOrganization'); + $router->group( + ['prefix' => 'organizations'], + function ($router) { + $router->get('current', 'OrganizationController@getCurrent'); + } + ); }); /* From 6717d782b694f60a41c573b7d71f462f7df5f840 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 25 Dec 2023 14:31:10 +0800 Subject: [PATCH 9/9] hotfix reset branding handling --- .../Internal/v1/SettingController.php | 4 + src/Models/Setting.php | 2 +- src/Traits/HasMetaAttributes.php | 132 +++++++++--------- 3 files changed, 70 insertions(+), 68 deletions(-) diff --git a/src/Http/Controllers/Internal/v1/SettingController.php b/src/Http/Controllers/Internal/v1/SettingController.php index a806155..b0f4ed0 100644 --- a/src/Http/Controllers/Internal/v1/SettingController.php +++ b/src/Http/Controllers/Internal/v1/SettingController.php @@ -448,10 +448,14 @@ public function saveBrandingSettings(Request $request) if ($iconUuid) { Setting::configure('branding.icon_uuid', $iconUuid); + } else { + Setting::configure('branding.icon_uuid', null); } if ($logoUuid) { Setting::configure('branding.logo_uuid', $logoUuid); + } else { + Setting::configure('branding.logo_uuid', null); } $brandingSettings = Setting::getBranding(); diff --git a/src/Models/Setting.php b/src/Models/Setting.php index d03c865..6a0c21f 100644 --- a/src/Models/Setting.php +++ b/src/Models/Setting.php @@ -184,7 +184,7 @@ public static function getBranding() // set branding settings $brandingSettings['icon_uuid'] = $iconUuid; - $brandingSettings['logo_uuid'] = $iconUuid; + $brandingSettings['logo_uuid'] = $logoUuid; $brandingSettings['default_theme'] = $defaultTheme ?? 'dark'; return $brandingSettings; diff --git a/src/Traits/HasMetaAttributes.php b/src/Traits/HasMetaAttributes.php index 62315a8..5fe1182 100644 --- a/src/Traits/HasMetaAttributes.php +++ b/src/Traits/HasMetaAttributes.php @@ -9,46 +9,48 @@ trait HasMetaAttributes { /** - * Sets a meta-data property with a value. + * Sets a single or multiple meta-data properties with values. * + * Usage: * $resource->setMeta('id', '1846473'); * $resource->setMeta('customer.name', 'John Doe'); + * $resource->setMeta(['id' => '1846473', 'customer.name' => 'John Doe']); * - * { - * "id": "1846473", - * "customer": { - * "name": "John Doe" - * } - * } + * @param string|array $keys key(s) of the meta-data to set + * @param mixed $value value to set if keys is a string * - * @return \Fleetbase\Models\Model + * @return $this */ - public function setMeta($keys, $value) + public function setMeta($keys, $value = null) { + $meta = $this->getAllMeta(); + if (is_array($keys)) { foreach ($keys as $key => $value) { - $this->setMeta($key, $value); + Arr::set($meta, $key, static::prepareValue($value)); } - - return $this; + } else { + Arr::set($meta, $keys, static::prepareValue($value)); } - $value = static::prepareValue($value); - $meta = $this->getAllMeta(); - $meta = Utils::set($meta, $keys, $value); - $this->setAttribute('meta', $meta); return $this; } /** - * Get a meta-data property. - * - * @param string|array $key - * @param [type] $defaultValue + * Retrieves all meta-data properties. + */ + public function getAllMeta(): array + { + return $this->getAttribute('meta') ?? []; + } + + /** + * Retrieves a meta-data property or all meta-data if no key is provided. * - * @return void + * @param string|array|null $key key of the meta-data to retrieve + * @param mixed|null $defaultValue default value if the key does not exist */ public function getMeta($key = null, $defaultValue = null) { @@ -58,101 +60,102 @@ public function getMeta($key = null, $defaultValue = null) return $meta; } - return Utils::get($meta, $key, $defaultValue); + return Arr::get($meta, $key, $defaultValue); } - public function getMetaAttributes($properties = []) + /** + * Retrieves meta-data for the specified properties. + * + * @param array $properties keys of meta-data to retrieve + */ + public function getMetaAttributes(array $properties = []): array { $metaAttributes = []; foreach ($properties as $key) { - Utils::set($metaAttributes, $key, $this->getMeta($key)); + Arr::set($metaAttributes, $key, $this->getMeta($key)); } return $metaAttributes; } /** - * Check if property exists in meta by key. + * Checks if a meta-data property exists. * - * @return bool + * @param string|array $keys key(s) to check existence in the meta-data */ - public function hasMeta($keys) + public function hasMeta($keys): bool { + $meta = $this->getAllMeta(); + if (is_array($keys)) { - return Arr::every($keys, function ($key) { - return $this->hasMeta($key); - }); + foreach ($keys as $key) { + if (!Arr::has($meta, $key)) { + return false; + } + } + + return true; } - return in_array($keys, array_keys($this->getAttribute('meta') ?? [])); + return Arr::has($meta, $keys); } /** - * Update meta with database write. + * Updates meta-data properties in the database. * - * @param string|array $key - * @param mixed|null $value + * @param string|array $key key(s) of the meta-data to update + * @param mixed|null $value value to update if key is a string * * @return $this */ public function updateMeta($key, $value = null) { + $this->setMeta($key, $value); $meta = $this->getAttribute('meta'); - if (is_array($key)) { - foreach ($key as $k => $v) { - $this->updateMeta($k, $v); - } - - return $this; - } - - $meta[$key] = static::prepareValue($value); - - $this->setAttribute('meta', $meta); - return $this->update(['meta' => $meta]); } - public function updateMetaProperties(array $data = []) + /** + * Updates multiple meta-data properties in the database. + * + * @param array $data array of key-value pairs to update in meta-data + */ + public function updateMetaProperties(array $data = []): bool { - $currentMetaObject = data_get($this, 'meta', []); - $currentMetaObject = array_merge($currentMetaObject, $data); + $currentMetaObject = $this->getAllMeta(); + $updatedMetaObject = array_merge($currentMetaObject, $data); return DB::table($this->getTable())->where($this->getKeyName(), $this->getKey())->update([ - 'meta' => json_encode($currentMetaObject), + 'meta' => json_encode($updatedMetaObject), ]); } /** - * Checks if key is missing from meta-data. + * Checks if a meta-data key is missing. * - * @param [type] $key - * - * @return void + * @param string $key key of the meta-data to check */ - public function missingMeta($key) + public function missingMeta($key): bool { return !$this->hasMeta($key); } /** - * Checks if meta-data key value is true. - * - * @param string $key + * Checks if a meta-data property's value is true. * - * @return bool + * @param string $key key of the meta-data to check */ - public function isMeta($key) + public function isMeta($key): bool { return $this->getMeta($key) === true; } /** - * Prepares value for meta-data insertion. + * Prepares a value for meta-data insertion. * - * @return void + * @param mixed $value value to prepare */ private static function prepareValue($value) { @@ -162,9 +165,4 @@ private static function prepareValue($value) return $value; } - - public function getAllMeta() - { - return $this->getAttribute('meta') ?? []; - } }