From 01cda991393fb7b33951e413be96f07c356cbfb7 Mon Sep 17 00:00:00 2001 From: Netkas Date: Thu, 31 Aug 2023 18:25:37 -0400 Subject: [PATCH] - `\ncc\Objects\ProjectConfiguration > Dependency > __construct()` now requires the parameters `$name`, `$source_type`, `$source` and `$version` - `\ncc\Objects\ProjectConfiguration > Dependency > fromArray()` Throws an `ConfigurationException` if the property `name` is missing in the dependency configuration - Also updated a bunch of objects in a similar fashion to the ones above, (BuildConfiguration, Execute, ExitHandle, ExitHandler, Repository, Assembly, Build, Dependency, ExecutionPolicy, Installer, Project, UpdateSource) I'm not going to list them all here, but you can find them in the commit history. - Added a new interface class `ValidatableObjectInterface` to implement validatable objects, this method will throw a `ConfigurationException` if the object is not valid or a `NotSupportedException` if the object contains methods that are not supported by the current version of ncc or project. --- CHANGELOG.md | 10 ++ src/ncc/Enums/RemoteSourceType.php | 8 +- .../Interfaces/ValidatableObjectInterface.php | 38 +++++ src/ncc/Objects/ProjectConfiguration.php | 150 +++++++----------- .../Objects/ProjectConfiguration/Assembly.php | 117 ++++++-------- .../Objects/ProjectConfiguration/Build.php | 72 ++++----- .../Build/BuildConfiguration.php | 117 +++++--------- .../ProjectConfiguration/Dependency.php | 96 +++++------ .../ProjectConfiguration/ExecutionPolicy.php | 16 +- .../ExecutionPolicy/Execute.php | 75 ++++----- .../ExecutionPolicy/ExitHandle.php | 46 +++--- .../ExecutionPolicy/ExitHandlers.php | 2 + .../ProjectConfiguration/Installer.php | 49 +++--- .../Objects/ProjectConfiguration/Project.php | 7 +- .../ProjectConfiguration/UpdateSource.php | 34 ++-- .../UpdateSource/Repository.php | 35 +++- 16 files changed, 415 insertions(+), 457 deletions(-) create mode 100644 src/ncc/Interfaces/ValidatableObjectInterface.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 34a38bd..547e46a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ features and reduced the number of exceptions down to 15 exceptions. - Added new exception `OperationException` in `\ncc\Exceptions` to replace all generic related exceptions - Added a new interface class `SerializableObjectInterface` to implement serializable objects, `BytecodeObjectInterface` extends this interface to allow for serialization of compiled assets + - Added a new interface class `ValidatableObjectInterface` to implement validatable objects, this method will throw a + `ConfigurationException` if the object is not valid or a `NotSupportedException` if the object contains methods that + are not supported by the current version of ncc or project. ### Fixed - Fixed MITM attack vector in `\ncc\Classes > HttpClient > prepareCurl()` @@ -211,6 +214,13 @@ features and reduced the number of exceptions down to 15 exceptions. - `\ncc\Objects > ProjectConfiguration > fromArray()` Throws an `ConfigurationException` if the property 'project' is missing in the root configuration - `\ncc\Objects\ProjectConfiguration > Project > __construct()` now requires the parameter `$compiler` + - `\ncc\Objects\ProjectConfiguration > Dependency > __construct()` now requires the parameters `$name`, `$source_type`, + `$source` and `$version` + - `\ncc\Objects\ProjectConfiguration > Dependency > fromArray()` Throws an `ConfigurationException` if the property + `name` is missing in the dependency configuration + - Also updated a bunch of objects in a similar fashion to the ones above, (BuildConfiguration, Execute, ExitHandle, + ExitHandler, Repository, Assembly, Build, Dependency, ExecutionPolicy, Installer, Project, UpdateSource) I'm not + going to list them all here, but you can find them in the commit history. ### Removed diff --git a/src/ncc/Enums/RemoteSourceType.php b/src/ncc/Enums/RemoteSourceType.php index 062e04a..f12f280 100644 --- a/src/ncc/Enums/RemoteSourceType.php +++ b/src/ncc/Enums/RemoteSourceType.php @@ -42,9 +42,15 @@ namespace ncc\Enums; */ public const UNKNOWN = 'unknown'; + /** + * No remote source type + */ + public const NONE = 'none'; + public const All = [ self::BUILTIN, self::DEFINED, - self::UNKNOWN + self::UNKNOWN, + self::NONE ]; } \ No newline at end of file diff --git a/src/ncc/Interfaces/ValidatableObjectInterface.php b/src/ncc/Interfaces/ValidatableObjectInterface.php new file mode 100644 index 0000000..2ffa1c4 --- /dev/null +++ b/src/ncc/Interfaces/ValidatableObjectInterface.php @@ -0,0 +1,38 @@ +project = new Project(); - $this->assembly = new Assembly(); + $this->project = $project; + $this->assembly = $assembly; + $this->build = $build; $this->execution_policies = []; - $this->build = new Build(); } /** @@ -172,55 +173,19 @@ } /** - * Validates the object for any errors - * - * @param bool $throw_exception - * @return bool - * @throws ConfigurationException - * @throws NotSupportedException + * @inheritDoc */ - public function validate(bool $throw_exception=True): bool + public function validate(): void { - if(!$this->project->validate($throw_exception)) - { - return false; - } - - if(!$this->assembly->validate($throw_exception)) - { - return false; - } - - if(!$this->build->validate($throw_exception)) - { - return false; - } - - - try - { - $this->getRequiredExecutionPolicies(BuildConfigurationValues::ALL); - } - catch(Exception $e) - { - if($throw_exception) - { - throw $e; - } - - return false; - } + $this->project->validate(); + $this->assembly->validate(); + $this->build->validate(); if($this->build->getMain() !== null) { if($this->execution_policies === null || count($this->execution_policies) === 0) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Build configuration build.main uses an execution policy "%s" but no policies are defined', $this->build->getMain())); - } - - return false; + throw new ConfigurationException(sprintf('Build configuration build.main uses an execution policy "%s" but no policies are defined', $this->build->getMain())); } @@ -236,25 +201,14 @@ if(!$found) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Build configuration build.main points to a undefined execution policy "%s"', $this->build->getMain())); - } - return false; + throw new ConfigurationException(sprintf('Build configuration build.main points to a undefined execution policy "%s"', $this->build->getMain())); } if($this->build->getMain() === BuildConfigurationValues::ALL) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Build configuration build.main cannot be set to "%s"', BuildConfigurationValues::ALL)); - } - - return false; + throw new ConfigurationException(sprintf('Build configuration build.main cannot be set to "%s"', BuildConfigurationValues::ALL)); } } - - return true; } /** @@ -301,9 +255,8 @@ // Check the installer by batch if($this->installer !== null) { - $array_rep = $this->installer->toArray(); /** @var string[] $value */ - foreach($array_rep as $key => $value) + foreach($this->installer->toArray() as $key => $value) { if($value === null || count($value) === 0) { @@ -510,17 +463,8 @@ */ public function toArray(bool $bytecode=false): array { - $execution_policies = null; - if($this->execution_policies !== null) - { - $execution_policies = []; - foreach($this->execution_policies as $executionPolicy) - { - $execution_policies[$executionPolicy->getName()] = $executionPolicy->toArray($bytecode); - } - } - $results = []; + if($this->project !== null) { $results[($bytecode ? Functions::cbc('project') : 'project')] = $this->project->toArray($bytecode); @@ -541,8 +485,15 @@ $results[($bytecode ? Functions::cbc('installer') : 'installer')] = $this->installer->toArray($bytecode); } - if($execution_policies !== null && count($execution_policies) > 0) + if(count($this->execution_policies) > 0) { + $execution_policies = []; + + foreach($this->execution_policies as $executionPolicy) + { + $execution_policies[$executionPolicy->getName()] = $executionPolicy->toArray($bytecode); + } + $results[($bytecode ? Functions::cbc('execution_policies') : 'execution_policies')] = $execution_policies; } @@ -558,30 +509,37 @@ */ public static function fromArray(array $data): ProjectConfiguration { - $object = new self(); - - $object->project = Functions::array_bc($data, 'project'); - if($object->project !== null) + $project = Functions::array_bc($data, 'project'); + if($project !== null) { - $object->project = Project::fromArray($object->project); + $project = Project::fromArray($project); } else { throw new ConfigurationException('The project configuration is missing the required property "project" in the root of the configuration'); } - $object->assembly = Functions::array_bc($data, 'assembly'); - if($object->assembly !== null) + $assembly = Functions::array_bc($data, 'assembly'); + if($assembly !== null) { - $object->assembly = Assembly::fromArray($object->assembly); + $assembly = Assembly::fromArray($assembly); + } + else + { + throw new ConfigurationException('The project configuration is missing the required property "assembly" in the root of the configuration'); } - - $object->build = Functions::array_bc($data, 'build'); - if($object->build !== null) + $build = Functions::array_bc($data, 'build'); + if($build !== null) { - $object->build = Build::fromArray($object->build); + $build = Build::fromArray($build); } + else + { + throw new ConfigurationException('The project configuration is missing the required property "build" in the root of the configuration'); + } + + $object = new self($project, $assembly, $build); $object->installer = Functions::array_bc($data, 'installer'); if($object->installer !== null) @@ -592,11 +550,9 @@ $execution_policies = Functions::array_bc($data, 'execution_policies'); if(!is_null($execution_policies)) { - $object->execution_policies = []; - foreach(Functions::array_bc($data, 'execution_policies') as $execution_policy) - { - $object->execution_policies[] = ExecutionPolicy::fromArray($execution_policy); - } + $object->execution_policies = array_map(static function($policy) { + return ExecutionPolicy::fromArray($policy); + }, $execution_policies); } return $object; diff --git a/src/ncc/Objects/ProjectConfiguration/Assembly.php b/src/ncc/Objects/ProjectConfiguration/Assembly.php index 0cf84f8..caea8af 100644 --- a/src/ncc/Objects/ProjectConfiguration/Assembly.php +++ b/src/ncc/Objects/ProjectConfiguration/Assembly.php @@ -27,6 +27,9 @@ use ncc\Enums\RegexPatterns; use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; + use ncc\Interfaces\ValidatableObjectInterface; + use ncc\ThirdParty\Symfony\Uid\Uuid; + use ncc\ThirdParty\Symfony\Uid\UuidV4; use ncc\Utilities\Functions; use ncc\Utilities\Validate; @@ -34,7 +37,7 @@ * @author Zi Xing Narrakas * @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved. */ - class Assembly implements BytecodeObjectInterface + class Assembly implements BytecodeObjectInterface, ValidatableObjectInterface { /** * The software name @@ -97,6 +100,25 @@ */ private $uuid; + /** + * Assembly constructor. + */ + public function __construct(string $name, string $package, string $version='1.0.0', ?string $uuid=null) + { + $this->name = $name; + $this->package = $package; + $this->version = $version; + + if($uuid === null) + { + $this->uuid = Uuid::v4()->toRfc4122(); + } + else + { + $this->uuid = $uuid; + } + } + /** * @return string */ @@ -242,105 +264,54 @@ } /** - * Validates the object information to detect possible errors - * - * @param bool $throw_exception - * @return bool - * @throws ConfigurationException + * @inheritDoc */ - public function validate(bool $throw_exception=True): bool + public function validate(): void { if(!preg_match(RegexPatterns::UUID, $this->uuid)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The UUID is not a valid v4 UUID: %s, in property Assembly.UUID', $this->uuid)); - } - - return false; + throw new ConfigurationException(sprintf('The UUID is not a valid v4 UUID: %s, in property assembly.uuid', $this->uuid)); } if($this->version !== null && !Validate::version($this->version)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The version number is invalid: %s, in property Assembly.Version', $this->version)); - } - - return false; + throw new ConfigurationException(sprintf('The version number is invalid: %s, in property assembly.version', $this->version)); } if($this->package !== null && !preg_match(RegexPatterns::PACKAGE_NAME_FORMAT, $this->package)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The package name is invalid: %s, in property Assembly.Package', $this->package)); - } - - return false; + throw new ConfigurationException(sprintf('The package name is invalid: %s, in property assembly.package', $this->package)); } if($this->name !== null && strlen($this->name) > 126) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The name cannot be larger than 126 characters: %s, in property Assembly.Name', $this->name)); - } - - return false; + throw new ConfigurationException(sprintf('The name cannot be larger than 126 characters: %s, in property assembly.name', $this->name)); } if($this->description !== null && strlen($this->description) > 512) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The description cannot be larger than 512 characters: %s, in property Assembly.Description', $this->description)); - } - - return false; + throw new ConfigurationException(sprintf('The description cannot be larger than 512 characters: %s, in property assembly.description', $this->description)); } if($this->company !== null && strlen($this->company) > 126) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The company cannot be larger than 126 characters: %s, in property Assembly.Company', $this->company)); - } - - return false; + throw new ConfigurationException(sprintf('The company cannot be larger than 126 characters: %s, in property assembly.company', $this->company)); } if($this->product !== null && strlen($this->product) > 256) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The product cannot be larger than 256 characters: %s, in property Assembly.Product', $this->product)); - } - - return false; + throw new ConfigurationException(sprintf('The product cannot be larger than 256 characters: %s, in property assembly.product', $this->product)); } if($this->copyright !== null && strlen($this->copyright) > 256) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The copyright cannot be larger than 256 characters: %s, in property Assembly.Copyright', $this->company)); - } - - return false; + throw new ConfigurationException(sprintf('The copyright cannot be larger than 256 characters: %s, in property assembly.copyright', $this->company)); } if($this->trademark !== null && strlen($this->trademark) > 256) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The trademark cannot be larger than 256 characters: %s, in property Assembly.Trademark', $this->trademark)); - } - - return false; + throw new ConfigurationException(sprintf('The trademark cannot be larger than 256 characters: %s, in property assembly.trademark', $this->trademark)); } - - return true; } /** @@ -400,20 +371,30 @@ /** * @inheritDoc + * @throws ConfigurationException */ public static function fromArray(array $data): Assembly { - $object = new self(); + $name = Functions::array_bc($data, 'name'); + $package = Functions::array_bc($data, 'package'); + + if($name === null) + { + throw new ConfigurationException('The property \'assembly.name\' must not be null.'); + } + + if($package === null) + { + throw new ConfigurationException('The property \'assembly.package\' must not be null.'); + } + + $object = new self($name, $package, Functions::array_bc($data, 'version'), Functions::array_bc($data, 'uuid')); - $object->name = Functions::array_bc($data, 'name'); - $object->package = Functions::array_bc($data, 'package'); $object->description = Functions::array_bc($data, 'description'); $object->company = Functions::array_bc($data, 'company'); $object->product = Functions::array_bc($data, 'product'); $object->copyright = Functions::array_bc($data, 'copyright'); $object->trademark = Functions::array_bc($data, 'trademark'); - $object->version = Functions::array_bc($data, 'version'); - $object->uuid = Functions::array_bc($data, 'uuid'); return $object; } diff --git a/src/ncc/Objects/ProjectConfiguration/Build.php b/src/ncc/Objects/ProjectConfiguration/Build.php index 9cd52ef..32b9f76 100644 --- a/src/ncc/Objects/ProjectConfiguration/Build.php +++ b/src/ncc/Objects/ProjectConfiguration/Build.php @@ -27,6 +27,7 @@ use ncc\Enums\Options\BuildConfigurationValues; use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; + use ncc\Interfaces\ValidatableObjectInterface; use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration; use ncc\Utilities\Functions; use ncc\Utilities\Validate; @@ -35,7 +36,7 @@ * @author Zi Xing Narrakas * @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved. */ - class Build implements BytecodeObjectInterface + class Build implements BytecodeObjectInterface, ValidatableObjectInterface { /** * The source directory that the compiler will target to generate a build @@ -110,8 +111,10 @@ /** * Public Constructor */ - public function __construct() + public function __construct(string $source_path, ?string $default_configuration=null) { + $this->source_path = $source_path; + $this->default_configuration = $default_configuration ?? BuildConfigurationValues::DEFAULT; $this->exclude_files = []; $this->options = []; $this->define_constants = []; @@ -365,7 +368,7 @@ } /** - * Adds a new pre build policy to the build + * Adds a new pre-build policy to the build * * @param string $policy * @return void @@ -496,13 +499,9 @@ } /** - * Validates the build configuration object - * - * @param bool $throw_exception - * @return bool - * @throws ConfigurationException + * @inheritDoc */ - public function validate(bool $throw_exception=True): bool + public function validate(): void { // Check the defined constants foreach($this->define_constants as $name => $value) @@ -519,46 +518,24 @@ { if(in_array($configuration->getName(), $build_configurations, true)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $configuration->getName())); - } - - return false; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $configuration->getName())); } } foreach($this->build_configurations as $configuration) { - if (!$configuration->validate($throw_exception)) - { - return false; - } + $configuration->validate(); } if($this->default_configuration === null) { - if($throw_exception) - { - throw new ConfigurationException('The default build configuration is not set'); - } - - return false; + throw new ConfigurationException('The default build configuration is not set'); } if(!Validate::nameFriendly($this->default_configuration)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('The default build configuration name "%s" is not valid', $this->default_configuration)); - } - - return false; + throw new ConfigurationException(sprintf('The default build configuration name "%s" is not valid', $this->default_configuration)); } - - $this->getBuildConfiguration($this->default_configuration); - - return true; } /** @@ -621,10 +598,12 @@ if($this->build_configurations !== null && count($this->build_configurations) > 0) { $configurations = []; + foreach($this->build_configurations as $configuration) { $configurations[] = $configuration->toArray($bytecode); } + $results[($bytecode ? Functions::cbc('configurations') : 'configurations')] = $configurations; } @@ -636,31 +615,38 @@ * * @param array $data * @return Build + * @throws ConfigurationException */ public static function fromArray(array $data): Build { - $object = new self(); + $source_path = Functions::array_bc($data, 'source_path'); + if($source_path === null) + { + throw new ConfigurationException('The property \'project.build.source_path\' must not be null.'); + } + + $object = new self($source_path, Functions::array_bc($data, 'default_configuration')); - $object->source_path = Functions::array_bc($data, 'source_path'); - $object->default_configuration = Functions::array_bc($data, 'default_configuration'); $object->exclude_files = (Functions::array_bc($data, 'exclude_files') ?? []); $object->options = (Functions::array_bc($data, 'options') ?? []); - $object->main = Functions::array_bc($data, 'main'); $object->define_constants = (Functions::array_bc($data, 'define_constants') ?? []); $object->pre_build = (Functions::array_bc($data, 'pre_build') ?? []); $object->post_build = (Functions::array_bc($data, 'post_build') ?? []); + $object->main = Functions::array_bc($data, 'main'); - if(Functions::array_bc($data, 'dependencies') !== null) + $dependencies = Functions::array_bc($data, 'dependencies'); + if($dependencies !== null) { - foreach(Functions::array_bc($data, 'dependencies') as $dependency) + foreach($dependencies as $dependency) { $object->dependencies[] = Dependency::fromArray($dependency); } } - if(Functions::array_bc($data, 'configurations') !== null) + $configurations = Functions::array_bc($data, 'configurations'); + if($configurations !== null) { - foreach(Functions::array_bc($data, 'configurations') as $configuration) + foreach($configurations as $configuration) { $object->build_configurations[] = BuildConfiguration::fromArray($configuration); } diff --git a/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php b/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php index 44ab17a..f9048dc 100644 --- a/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php +++ b/src/ncc/Objects/ProjectConfiguration/Build/BuildConfiguration.php @@ -96,10 +96,11 @@ /** * Public Constructor */ - public function __construct() + public function __construct(string $name, string $output_path) { + $this->name = $name; + $this->output_path = $output_path; $this->options = []; - $this->output_path = 'build'; $this->define_constants = []; $this->exclude_files = []; $this->pre_build = []; @@ -114,97 +115,47 @@ * @return bool * @throws ConfigurationException */ - public function validate(bool $throw_exception=True): bool + public function validate(): bool { if(!Validate::nameFriendly($this->name)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); - } - - return False; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); } if(!Validate::pathName($this->output_path)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); - } - - return False; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); } if($this->define_constants !== null && !is_array($this->define_constants)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); - } - - return False; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); } if($this->exclude_files !== null && !is_array($this->exclude_files)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); - } - - return False; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); } if($this->pre_build !== null && !is_array($this->pre_build)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); - } - - return False; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); } if($this->post_build !== null && !is_array($this->post_build)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); - } - - return False; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); } if($this->dependencies !== null && !is_array($this->dependencies)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); - } - - return False; + throw new ConfigurationException(sprintf('Invalid build configuration name "%s"', $this->name)); } /** @var Dependency $dependency */ foreach($this->dependencies as $dependency) { - try - { - if (!$dependency->validate($throw_exception)) - { - return False; - } - } - catch (ConfigurationException $e) - { - if($throw_exception) - { - throw $e; - } - - return False; - } + $dependency->validate(); } return True; @@ -418,37 +369,30 @@ { $results = []; - if($this->name !== null && $this->name !== '') - { - $results[($bytecode ? Functions::cbc('name') : 'name')] = $this->name; - } + $results[($bytecode ? Functions::cbc('name') : 'name')] = $this->name; + $results[($bytecode ? Functions::cbc('output_path') : 'output_path')] = $this->output_path; - if($this->options !== null && count($this->options) > 0) + if(count($this->options) > 0) { $results[($bytecode ? Functions::cbc('options') : 'options')] = $this->options; } - if($this->output_path !== null && $this->output_path !== '') - { - $results[($bytecode ? Functions::cbc('output_path') : 'output_path')] = $this->output_path; - } - - if($this->define_constants !== null && count($this->define_constants) > 0) + if(count($this->define_constants) > 0) { $results[($bytecode ? Functions::cbc('define_constants') : 'define_constants')] = $this->define_constants; } - if($this->exclude_files !== null && count($this->exclude_files) > 0) + if(count($this->exclude_files) > 0) { $results[($bytecode ? Functions::cbc('exclude_files') : 'exclude_files')] = $this->exclude_files; } - if($this->pre_build !== null && count($this->pre_build) > 0) + if(count($this->pre_build) > 0) { $results[($bytecode ? Functions::cbc('pre_build') : 'pre_build')] = $this->pre_build; } - if($this->dependencies !== null && count($this->dependencies) > 0) + if(count($this->dependencies) > 0) { $dependencies = array_map(static function(Dependency $Dependency) use ($bytecode) { @@ -463,22 +407,35 @@ /** * @inheritDoc + * @throws ConfigurationException */ public static function fromArray(array $data): BuildConfiguration { - $object = new BuildConfiguration(); + $name = Functions::array_bc($data, 'name'); + $output_path = Functions::array_bc($data, 'output_path'); + + if($name === null) + { + throw new ConfigurationException('Build configuration "name" property is required'); + } + + if($output_path === null) + { + throw new ConfigurationException('Build configuration "output_path" property is required'); + } + + $object = new BuildConfiguration($name, $output_path); - $object->name = Functions::array_bc($data, 'name'); $object->options = Functions::array_bc($data, 'options') ?? []; - $object->output_path = Functions::array_bc($data, 'output_path'); $object->define_constants = Functions::array_bc($data, 'define_constants') ?? []; $object->exclude_files = Functions::array_bc($data, 'exclude_files') ?? []; $object->pre_build = Functions::array_bc($data, 'pre_build') ?? []; $object->post_build = Functions::array_bc($data, 'post_build') ?? []; - if(Functions::array_bc($data, 'dependencies') !== null) + $dependencies = Functions::array_bc($data, 'dependencies'); + if($dependencies !== null) { - foreach(Functions::array_bc($data, 'dependencies') as $item) + foreach($dependencies as $item) { $object->dependencies[] = Dependency::fromArray($item); } diff --git a/src/ncc/Objects/ProjectConfiguration/Dependency.php b/src/ncc/Objects/ProjectConfiguration/Dependency.php index a10e1c9..317979f 100644 --- a/src/ncc/Objects/ProjectConfiguration/Dependency.php +++ b/src/ncc/Objects/ProjectConfiguration/Dependency.php @@ -24,8 +24,11 @@ namespace ncc\Objects\ProjectConfiguration; + use ncc\Enums\RemoteSourceType; + use ncc\Enums\Versions; use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; + use ncc\Interfaces\ValidatableObjectInterface; use ncc\Utilities\Functions; use ncc\Utilities\Validate; @@ -33,7 +36,7 @@ * @author Zi Xing Narrakas * @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved. */ - class Dependency implements BytecodeObjectInterface + class Dependency implements BytecodeObjectInterface, ValidatableObjectInterface { /** * @var string @@ -41,19 +44,35 @@ private $name; /** - * @var string|null + * @var string */ private $source_type; + /** + * @var string + */ + private $version; + /** * @var string|null */ private $source; /** - * @var string|null + * Dependency constructor. + * + * @param string $name + * @param string|null $source_type + * @param string|null $source + * @param string|null $version */ - private $version; + public function __construct(string $name, ?string $source_type=null, ?string $source=null, ?string $version=null) + { + $this->name = $name; + $this->source_type = $source_type ?? RemoteSourceType::NONE; + $this->version = $version ?? Versions::LATEST; + $this->source = $source; + } /** * Returns the name of the dependency @@ -79,22 +98,23 @@ /** * Optional. Returns the type of source from where ncc can fetch the dependency from * - * @return string|null + * @return string */ - public function getSourceType(): ?string + public function getSourceType(): string { return $this->source_type; } /** - * Sets the type of source from where ncc can fetch the dependency from + * Sets the type of source from where ncc can fetch the dependency from, + * if the source type is not defined, it will be set to RemoteSourceType::NONE * * @param string|null $source_type * @return void */ public function setSourceType(?string $source_type): void { - $this->source_type = $source_type; + $this->source_type = ($source_type ?? RemoteSourceType::NONE); } /** @@ -125,50 +145,35 @@ */ public function getVersion(): string { - return $this->version ?? 'latest'; + return $this->version ?? Versions::LATEST; } /** * Returns the required version of the dependency or null if no version is required + * if the version is not defined, it will be set to Versions::LATEST * * @param string|null $version * @return void */ public function setVersion(?string $version): void { - $this->version = $version; + $this->version = ($version ?? Versions::LATEST); } /** - * Validates the dependency configuration - * - * @param bool $throw_exception - * @return bool - * @throws ConfigurationException + * @inheritDoc */ - public function validate(bool $throw_exception): bool + public function validate(): void { if(!Validate::packageName($this->name)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid dependency name "%s"', $this->name)); - } - - return false; + throw new ConfigurationException(sprintf('Invalid dependency name "%s"', $this->name)); } - if($this->version !== null && !Validate::version($this->version)) + if($this->version !== Versions::LATEST && !Validate::version($this->version)) { - if($throw_exception) - { - throw new ConfigurationException(sprintf('Invalid dependency version "%s"', $this->version)); - } - - return false; + throw new ConfigurationException(sprintf('Invalid dependency version "%s"', $this->version)); } - - return true; } /** @@ -179,37 +184,34 @@ $results = []; $results[($bytecode ? Functions::cbc('name') : 'name')] = $this->name; - - if($this->source_type !== null && $this->source_type !== '') - { - $results[($bytecode ? Functions::cbc('source_type') : 'source_type')] = $this->source_type; - } + $results[($bytecode ? Functions::cbc('source_type') : 'source_type')] = $this->source_type; + $results[($bytecode ? Functions::cbc('version') : 'version')] = $this->version; if($this->source !== null && $this->source !== '') { $results[($bytecode ? Functions::cbc('source') : 'source')] = $this->source; } - if($this->version !== null && $this->version !== '') - { - $results[($bytecode ? Functions::cbc('version') : 'version')] = $this->version; - } - return $results; } /** * @inheritDoc + * @throws ConfigurationException */ public static function fromArray(array $data): Dependency { - $object = new self(); + $name = Functions::array_bc($data, 'name'); - $object->name = Functions::array_bc($data, 'name'); - $object->source_type = Functions::array_bc($data, 'source_type'); - $object->source = Functions::array_bc($data, 'source'); - $object->version = Functions::array_bc($data, 'version'); + if($name === null) + { + throw new ConfigurationException('Dependency name is required'); + } - return $object; + return new self($name, + Functions::array_bc($data, 'source_type'), + Functions::array_bc($data, 'source'), + Functions::array_bc($data, 'version') + ); } } \ No newline at end of file diff --git a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy.php b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy.php index 22394ef..bb0f4aa 100644 --- a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy.php +++ b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy.php @@ -45,13 +45,6 @@ */ private $runner; - /** - * The message to display when the policy is invoked - * - * @var string|null - */ - private $message; - /** * The execution process of the policy * @@ -62,10 +55,17 @@ /** * The configuration for exit handling * - * @var ExitHandlers + * @var ExitHandlers|null */ private $exit_handlers; + /** + * The message to display when the policy is invoked + * + * @var string|null + */ + private $message; + /** * @return string */ diff --git a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/Execute.php b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/Execute.php index a742a4a..9349c6f 100644 --- a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/Execute.php +++ b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/Execute.php @@ -25,6 +25,7 @@ namespace ncc\Objects\ProjectConfiguration\ExecutionPolicy; use ncc\Enums\SpecialConstants\RuntimeConstants; + use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; use ncc\Utilities\Functions; @@ -41,7 +42,7 @@ * The working directory to execute the policy in, if not specified the * value "%CWD%" will be used as the default * - * @var string|null + * @var string */ private $working_directory; @@ -89,11 +90,14 @@ /** * Public Constructor */ - public function __construct() + public function __construct(string $target, ?string $working_directory) { - $this->tty = false; + $this->target = $target; + $this->working_directory = $working_directory ?? RuntimeConstants::CWD; + $this->options = []; + $this->environment_variables = []; $this->silent = false; - $this->working_directory = "%CWD%"; + $this->tty = true; } /** @@ -135,7 +139,7 @@ */ public function setWorkingDirectory(?string $working_directory): void { - $this->working_directory = $working_directory; + $this->working_directory = $working_directory ?? RuntimeConstants::CWD; } /** @@ -175,7 +179,7 @@ */ public function isSilent(): bool { - return $this->silent ?? false; + return $this->silent; } /** @@ -191,7 +195,7 @@ */ public function isTty(): bool { - return $this->tty ?? true; + return $this->tty; } /** @@ -234,8 +238,6 @@ $this->idle_timeout = $idle_timeout; } - - /** * @inheritDoc */ @@ -243,58 +245,37 @@ { $results = []; + $results[($bytecode ? Functions::cbc('working_directory') : 'working_directory')] = $this->working_directory; + $results[($bytecode ? Functions::cbc('options') : 'options')] = $this->options; + $results[($bytecode ? Functions::cbc('environment_variables') : 'environment_variables')] = $this->environment_variables; + $results[($bytecode ? Functions::cbc('silent') : 'silent')] = (bool)$this->silent; + $results[($bytecode ? Functions::cbc('tty') : 'tty')] = (bool)$this->tty; + $results[($bytecode ? Functions::cbc('timeout') : 'timeout')] = (int)$this->timeout; + $results[($bytecode ? Functions::cbc('idle_timeout') : 'idle_timeout')] = (int)$this->idle_timeout; + if($this->target !== null) { $results[($bytecode ? Functions::cbc('target') : 'target')] = $this->target; } - if($this->working_directory !== null) - { - $results[($bytecode ? Functions::cbc('working_directory') : 'working_directory')] = $this->working_directory; - } - - if($this->options !== null) - { - $results[($bytecode ? Functions::cbc('options') : 'options')] = $this->options; - } - - if($this->environment_variables !== null) - { - $results[($bytecode ? Functions::cbc('environment_variables') : 'environment_variables')] = $this->environment_variables; - } - - if($this->silent !== null) - { - $results[($bytecode ? Functions::cbc('silent') : 'silent')] = (bool)$this->silent; - } - - if($this->tty !== null) - { - $results[($bytecode ? Functions::cbc('tty') : 'tty')] = (bool)$this->tty; - } - - if($this->timeout !== null) - { - $results[($bytecode ? Functions::cbc('timeout') : 'timeout')] = (int)$this->timeout; - } - - if($this->idle_timeout !== null) - { - $results[($bytecode ? Functions::cbc('idle_timeout') : 'idle_timeout')] = (int)$this->idle_timeout; - } - return $results; } /** * @inheritDoc + * @throws ConfigurationException */ public static function fromArray(array $data): Execute { - $object = new self(); + $target = Functions::array_bc($data, 'target'); + + if($target === null) + { + throw new ConfigurationException("The ExecutionPolicy's Execute target is required"); + } + + $object = new self($target, Functions::array_bc($data, 'working_directory')); - $object->target = Functions::array_bc($data, 'target'); - $object->working_directory = Functions::array_bc($data, 'working_directory'); $object->options = Functions::array_bc($data, 'options') ?? []; $object->environment_variables = Functions::array_bc($data, 'environment_variables') ?? []; $object->silent = Functions::array_bc($data, 'silent') ?? false; diff --git a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandle.php b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandle.php index 55b710b..dce6d52 100644 --- a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandle.php +++ b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandle.php @@ -24,11 +24,26 @@ namespace ncc\Objects\ProjectConfiguration\ExecutionPolicy; + use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; use ncc\Utilities\Functions; class ExitHandle implements BytecodeObjectInterface { + /** + * The name of another execution policy to execute (optionally) when this exit handle is triggered + * + * @var string + */ + private $run; + + /** + * The exit code that needs to be returned from the process to trigger this handle + * + * @var int + */ + private $exit_code; + /** * The message to display when the handle is triggered * @@ -47,24 +62,11 @@ */ private $end_process; - /** - * The name of another execution policy to execute (optionally) when this exit handle is triggered - * - * @var string|null - */ - private $run; - - /** - * The exit code that needs to be returned from the process to trigger this handle - * - * @var int - */ - private $exit_code; - - public function __construct() + public function __construct(string $run, int $exit_code=0) { + $this->run = $run; + $this->exit_code = $exit_code; $this->end_process = false; - $this->exit_code = 0; } /** @@ -161,15 +163,21 @@ /** * @inheritDoc + * @throws ConfigurationException */ public static function fromArray(array $data): ExitHandle { - $object = new self(); + $run = Functions::array_bc($data, 'run'); + if($run === null) + { + throw new ConfigurationException('Exit handle "run" property is required'); + } + + $object = new self($run, (Functions::array_bc($data, 'exit_code') ?? 0)); - $object->message = Functions::array_bc($data, 'message'); $object->end_process = Functions::array_bc($data, 'end_process') ?? false; + $object->message = Functions::array_bc($data, 'message'); $object->run = Functions::array_bc($data, 'run'); - $object->exit_code = Functions::array_bc($data, 'exit_code') ?? 0; return $object; } diff --git a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandlers.php b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandlers.php index 66a24ae..d8559cf 100644 --- a/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandlers.php +++ b/src/ncc/Objects/ProjectConfiguration/ExecutionPolicy/ExitHandlers.php @@ -24,6 +24,7 @@ namespace ncc\Objects\ProjectConfiguration\ExecutionPolicy; + use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; use ncc\Utilities\Functions; @@ -112,6 +113,7 @@ /** * @inheritDoc + * @throws ConfigurationException */ public static function fromArray(array $data): ExitHandlers { diff --git a/src/ncc/Objects/ProjectConfiguration/Installer.php b/src/ncc/Objects/ProjectConfiguration/Installer.php index 6cef2b9..1f85d93 100644 --- a/src/ncc/Objects/ProjectConfiguration/Installer.php +++ b/src/ncc/Objects/ProjectConfiguration/Installer.php @@ -32,45 +32,58 @@ /** * An array of execution policies to execute pre-installation * - * @var string[]|null + * @var string[] */ private $pre_install; /** * An array of execution policies to execute post-installation * - * @var string[]|null + * @var string[] */ private $post_install; /** * An array of execution policies to execute pre-uninstallation * - * @var string[]|null + * @var string[] */ private $pre_uninstall; /** * An array of execution policies to execute post-uninstallation * - * @var string[]|null + * @var string[] */ private $post_uninstall; /** * An array of execution policies to execute pre-update * - * @var string[]|null + * @var string[] */ private $pre_update; /** * An array of execution policies to execute post-update * - * @var string[]|null + * @var string[] */ private $post_update; + /** + * Installer constructor. + */ + public function __construct() + { + $this->pre_install = []; + $this->post_install = []; + $this->pre_uninstall = []; + $this->post_uninstall = []; + $this->pre_update = []; + $this->post_update = []; + } + /** * @inheritDoc */ @@ -78,32 +91,32 @@ { $results = []; - if($this->pre_install !== null && count($this->pre_install) > 0) + if(count($this->pre_install) > 0) { $results[($bytecode ? Functions::cbc('pre_install') : 'pre_install')] = $this->pre_install; } - if($this->post_install !== null && count($this->post_install) > 0) + if(count($this->post_install) > 0) { $results[($bytecode ? Functions::cbc('post_install') : 'post_install')] = $this->post_install; } - if($this->pre_uninstall !== null && count($this->pre_uninstall) > 0) + if(count($this->pre_uninstall) > 0) { $results[($bytecode ? Functions::cbc('pre_uninstall') : 'pre_uninstall')] = $this->pre_uninstall; } - if($this->post_uninstall !== null && count($this->post_uninstall) > 0) + if(count($this->post_uninstall) > 0) { $results[($bytecode ? Functions::cbc('post_uninstall') : 'post_uninstall')] = $this->post_uninstall; } - if($this->pre_update !== null && count($this->pre_update) > 0) + if(count($this->pre_update) > 0) { $results[($bytecode ? Functions::cbc('pre_update') : 'pre_update')] = $this->pre_update; } - if($this->post_update !== null && count($this->post_update) > 0) + if(count($this->post_update) > 0) { $results[($bytecode ? Functions::cbc('post_update') : 'post_update')] = $this->post_update; } @@ -118,12 +131,12 @@ { $object = new self(); - $object->pre_install = Functions::array_bc($data, 'pre_install'); - $object->post_install = Functions::array_bc($data, 'post_install'); - $object->pre_uninstall = Functions::array_bc($data, 'pre_uninstall'); - $object->post_uninstall = Functions::array_bc($data, 'post_uninstall'); - $object->pre_update = Functions::array_bc($data, 'pre_update'); - $object->post_update = Functions::array_bc($data, 'post_update'); + $object->pre_install = Functions::array_bc($data, 'pre_install') ?? []; + $object->post_install = Functions::array_bc($data, 'post_install') ?? []; + $object->pre_uninstall = Functions::array_bc($data, 'pre_uninstall') ?? []; + $object->post_uninstall = Functions::array_bc($data, 'post_uninstall') ?? []; + $object->pre_update = Functions::array_bc($data, 'pre_update') ?? []; + $object->post_update = Functions::array_bc($data, 'post_update') ?? []; return $object; } diff --git a/src/ncc/Objects/ProjectConfiguration/Project.php b/src/ncc/Objects/ProjectConfiguration/Project.php index 99bf0a2..159a009 100644 --- a/src/ncc/Objects/ProjectConfiguration/Project.php +++ b/src/ncc/Objects/ProjectConfiguration/Project.php @@ -180,12 +180,7 @@ throw new ConfigurationException('The project configuration is missing the required property "compiler" in the project section.'); } - $object->options = Functions::array_bc($data, 'options'); - if($object->options === null) - { - $object->options = []; - } - + $object->options = Functions::array_bc($data, 'options') ?? []; $object->update_source = Functions::array_bc($data, 'update_source'); if($object->update_source !== null) { diff --git a/src/ncc/Objects/ProjectConfiguration/UpdateSource.php b/src/ncc/Objects/ProjectConfiguration/UpdateSource.php index bd41e6d..196035e 100644 --- a/src/ncc/Objects/ProjectConfiguration/UpdateSource.php +++ b/src/ncc/Objects/ProjectConfiguration/UpdateSource.php @@ -24,6 +24,7 @@ namespace ncc\Objects\ProjectConfiguration; + use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; use ncc\Objects\ProjectConfiguration\UpdateSource\Repository; use ncc\Utilities\Functions; @@ -44,6 +45,16 @@ */ private $repository; + /** + * @param string $source + * @param Repository|null $repository + */ + public function __construct(string $source, ?Repository $repository=null) + { + $this->source = $source; + $this->repository = $repository; + } + /** * @return string */ @@ -77,10 +88,7 @@ } /** - * Returns an array representation of the object - * - * @param bool $bytecode - * @return array + * @inheritDoc */ public function toArray(bool $bytecode=false): array { @@ -90,25 +98,17 @@ ]; } - /** - * Constructs object from an array representation - * - * @param array $data - * @return UpdateSource + * @inheritDoc */ public static function fromArray(array $data): UpdateSource { - $object = new self(); - - $object->source = Functions::array_bc($data, 'source'); - $object->repository = Functions::array_bc($data, 'repository'); - - if($object->repository !== null) + $source = Functions::array_bc($data, 'source'); + if($source === null) { - $object->repository = Repository::fromArray($object->repository); + throw new ConfigurationException('The UpdateSource requires the "source" property'); } - return $object; + return new self($source, Functions::array_bc($data, 'repository')); } } \ No newline at end of file diff --git a/src/ncc/Objects/ProjectConfiguration/UpdateSource/Repository.php b/src/ncc/Objects/ProjectConfiguration/UpdateSource/Repository.php index 17934fa..c79eb0f 100644 --- a/src/ncc/Objects/ProjectConfiguration/UpdateSource/Repository.php +++ b/src/ncc/Objects/ProjectConfiguration/UpdateSource/Repository.php @@ -25,6 +25,7 @@ namespace ncc\Objects\ProjectConfiguration\UpdateSource; use ncc\Enums\RemoteSourceType; + use ncc\Exceptions\ConfigurationException; use ncc\Interfaces\BytecodeObjectInterface; use ncc\Utilities\Functions; @@ -58,6 +59,14 @@ */ private $ssl; + public function __construct(string $name, string $host, ?string $type=null, bool $ssl=false) + { + $this->name = $name; + $this->host = $host; + $this->type = $type; + $this->ssl = $ssl; + } + /** * @return string */ @@ -137,16 +146,30 @@ /** * @inheritDoc + * @throws ConfigurationException */ public static function fromArray(array $data): Repository { - $object = new self(); + $name = Functions::array_bc($data, 'name'); + $type = Functions::array_bc($data, 'type'); + $host = Functions::array_bc($data, 'host'); + $ssl = Functions::array_bc($data, 'ssl') ?? false; - $object->name = Functions::array_bc($data, 'name'); - $object->type = Functions::array_bc($data, 'type') ?? RemoteSourceType::UNKNOWN; - $object->host = Functions::array_bc($data, 'host'); - $object->ssl = Functions::array_bc($data, 'ssl') ?? false; + if($name === null) + { + throw new ConfigurationException("The UpdateSource's Repository property requires 'main'"); + } - return $object; + if($type === null) + { + throw new ConfigurationException("The UpdateSource's Repository property requires 'type'"); + } + + if($host === null) + { + throw new ConfigurationException("The UpdateSource's Repository property requires 'host'"); + } + + return new self($name, $host, $type, $ssl); } } \ No newline at end of file