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