maximum supported compiler version for the selected extension - `\ncc\Objects\ProjectConfiguration > Compiler > fromArray()` throws an ConfigurationException if the property `extension` is null - `\ncc\Objects\ProjectConfiguration > Compiler > fromArray()` throws an NotSupportedException if the `extension` uses an unsupported compiler extension - `\ncc\Objects\ProjectConfiguration > Compiler > validate()` No longer accepts `$throw_exception` and throws an `ConfigurationException` or `NotSupportedException` if the validation fails, otherwise it returns `True`. - `\ncc\Objects\ProjectConfiguration > Project > fromArray()` Throws an `ConfigurationException` if the property `compiler` is missing in the project configuration - `\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` - Removed parameter `$throw_exception` from `\ncc\Objects\ProjectConfiguration > Project > validate()`
604 lines
No EOL
21 KiB
PHP
604 lines
No EOL
21 KiB
PHP
<?php
|
|
/*
|
|
* Copyright (c) Nosial 2022-2023, all rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
|
|
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
|
|
* conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
|
* of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
/** @noinspection PhpMissingFieldTypeInspection */
|
|
|
|
namespace ncc\Objects;
|
|
|
|
use Exception;
|
|
use ncc\Enums\Options\BuildConfigurationValues;
|
|
use ncc\Exceptions\ConfigurationException;
|
|
use ncc\Exceptions\IOException;
|
|
use ncc\Exceptions\NotSupportedException;
|
|
use ncc\Exceptions\PathNotFoundException;
|
|
use ncc\Interfaces\BytecodeObjectInterface;
|
|
use ncc\Objects\ProjectConfiguration\Assembly;
|
|
use ncc\Objects\ProjectConfiguration\Build;
|
|
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
|
|
use ncc\Objects\ProjectConfiguration\ExecutionPolicy;
|
|
use ncc\Objects\ProjectConfiguration\Installer;
|
|
use ncc\Objects\ProjectConfiguration\Project;
|
|
use ncc\Utilities\Functions;
|
|
|
|
/**
|
|
* @author Zi Xing Narrakas
|
|
* @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved.
|
|
*/
|
|
class ProjectConfiguration implements BytecodeObjectInterface
|
|
{
|
|
/**
|
|
* The project configuration
|
|
*
|
|
* @var Project
|
|
*/
|
|
private $project;
|
|
|
|
/**
|
|
* Assembly information for the build output
|
|
*
|
|
* @var Assembly
|
|
*/
|
|
private $assembly;
|
|
|
|
/**
|
|
* An array of execution policies
|
|
*
|
|
* @var ExecutionPolicy[]
|
|
*/
|
|
private $execution_policies;
|
|
|
|
/**
|
|
* Execution Policies to execute by the NCC installer
|
|
*
|
|
* @var Installer|null
|
|
*/
|
|
private $installer;
|
|
|
|
/**
|
|
* Build configuration for the project
|
|
*
|
|
* @var Build
|
|
*/
|
|
private $build;
|
|
|
|
/**
|
|
* Public Constructor
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->project = new Project();
|
|
$this->assembly = new Assembly();
|
|
$this->execution_policies = [];
|
|
$this->build = new Build();
|
|
}
|
|
|
|
/**
|
|
* @return Project
|
|
*/
|
|
public function getProject(): Project
|
|
{
|
|
return $this->project;
|
|
}
|
|
|
|
/**
|
|
* @param Project $project
|
|
*/
|
|
public function setProject(Project $project): void
|
|
{
|
|
$this->project = $project;
|
|
}
|
|
|
|
/**
|
|
* @return Assembly
|
|
*/
|
|
public function getAssembly(): Assembly
|
|
{
|
|
return $this->assembly;
|
|
}
|
|
|
|
/**
|
|
* @param Assembly $assembly
|
|
*/
|
|
public function setAssembly(Assembly $assembly): void
|
|
{
|
|
$this->assembly = $assembly;
|
|
}
|
|
|
|
/**
|
|
* @return array|ExecutionPolicy[]
|
|
*/
|
|
public function getExecutionPolicies(): array
|
|
{
|
|
return $this->execution_policies;
|
|
}
|
|
|
|
/**
|
|
* @param array|ExecutionPolicy[] $execution_policies
|
|
*/
|
|
public function setExecutionPolicies(array $execution_policies): void
|
|
{
|
|
$this->execution_policies = $execution_policies;
|
|
}
|
|
|
|
/**
|
|
* @return Installer|null
|
|
*/
|
|
public function getInstaller(): ?Installer
|
|
{
|
|
return $this->installer;
|
|
}
|
|
|
|
/**
|
|
* @param Installer|null $installer
|
|
*/
|
|
public function setInstaller(?Installer $installer): void
|
|
{
|
|
$this->installer = $installer;
|
|
}
|
|
|
|
/**
|
|
* @return Build
|
|
*/
|
|
public function getBuild(): Build
|
|
{
|
|
return $this->build;
|
|
}
|
|
|
|
/**
|
|
* @param Build $build
|
|
*/
|
|
public function setBuild(Build $build): void
|
|
{
|
|
$this->build = $build;
|
|
}
|
|
|
|
/**
|
|
* Validates the object for any errors
|
|
*
|
|
* @param bool $throw_exception
|
|
* @return bool
|
|
* @throws ConfigurationException
|
|
* @throws NotSupportedException
|
|
*/
|
|
public function validate(bool $throw_exception=True): bool
|
|
{
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
$found = false;
|
|
foreach($this->execution_policies as $policy)
|
|
{
|
|
if($policy->getName() === $this->build->getMain())
|
|
{
|
|
$found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @return ExecutionPolicy|null
|
|
*/
|
|
private function getExecutionPolicy(string $name): ?ExecutionPolicy
|
|
{
|
|
foreach($this->execution_policies as $executionPolicy)
|
|
{
|
|
if($executionPolicy->getName() === $name)
|
|
{
|
|
return $executionPolicy;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Runs a check on the project configuration and determines what policies are required
|
|
*
|
|
* @param string $build_configuration
|
|
* @return array
|
|
* @throws ConfigurationException
|
|
*/
|
|
public function getRequiredExecutionPolicies(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
|
{
|
|
if($this->execution_policies === null || count($this->execution_policies) === 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
$defined_polices = [];
|
|
$required_policies = [];
|
|
|
|
/** @var ExecutionPolicy $execution_policy */
|
|
foreach($this->execution_policies as $execution_policy)
|
|
{
|
|
$defined_polices[] = $execution_policy->getName();
|
|
//$execution_policy->validate();
|
|
}
|
|
|
|
// Check the installer by batch
|
|
if($this->installer !== null)
|
|
{
|
|
$array_rep = $this->installer->toArray();
|
|
/** @var string[] $value */
|
|
foreach($array_rep as $key => $value)
|
|
{
|
|
if($value === null || count($value) === 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foreach($value as $unit)
|
|
{
|
|
if(!in_array($unit, $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException('The property \'' . $key . '\' in the project configuration calls for an undefined execution policy \'' . $unit . '\'');
|
|
}
|
|
|
|
if(!in_array($unit, $required_policies, true))
|
|
{
|
|
$required_policies[] = $unit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(count($this->build->getPostBuild()) > 0)
|
|
{
|
|
foreach($this->build->getPostBuild() as $unit)
|
|
{
|
|
if(!in_array($unit, $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException('The property \'build.pre_build\' in the project configuration calls for an undefined execution policy \'' . $unit . '\'');
|
|
}
|
|
|
|
if(!in_array($unit, $required_policies, true))
|
|
{
|
|
$required_policies[] = $unit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(count($this->build->getPreBuild()) > 0)
|
|
{
|
|
foreach($this->build->getPreBuild() as $unit)
|
|
{
|
|
if(!in_array($unit, $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException('The property \'build.pre_build\' in the project configuration calls for an undefined execution policy \'' . $unit . '\'');
|
|
}
|
|
|
|
if(!in_array($unit, $required_policies, true))
|
|
{
|
|
$required_policies[] = $unit;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** @noinspection DegradedSwitchInspection */
|
|
switch($build_configuration)
|
|
{
|
|
case BuildConfigurationValues::ALL:
|
|
/** @var BuildConfiguration $configuration */
|
|
foreach($this->build->getBuildConfigurations() as $configuration)
|
|
{
|
|
foreach($this->processBuildPolicies($configuration, $defined_polices) as $policy)
|
|
{
|
|
if(!in_array($policy, $required_policies, true))
|
|
{
|
|
$required_policies[] = $policy;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
$configuration = $this->build->getBuildConfiguration($build_configuration);
|
|
foreach($this->processBuildPolicies($configuration, $defined_polices) as $policy)
|
|
{
|
|
if(!in_array($policy, $required_policies, true))
|
|
{
|
|
$required_policies[] = $policy;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
foreach($required_policies as $policy)
|
|
{
|
|
$execution_policy = $this->getExecutionPolicy($policy);
|
|
|
|
if($execution_policy?->getExitHandlers()->getSuccess()?->getRun() !== null)
|
|
{
|
|
if(!in_array($execution_policy?->getExitHandlers()->getSuccess()?->getRun(), $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException('The execution policy \'' . $execution_policy?->getName() . '\' Success exit handler points to a undefined execution policy \'' . $execution_policy?->getExitHandlers()->getSuccess()?->getRun() . '\'');
|
|
}
|
|
|
|
if(!in_array($execution_policy?->getExitHandlers()->getSuccess()?->getRun(), $required_policies, true))
|
|
{
|
|
$required_policies[] = $execution_policy?->getExitHandlers()->getSuccess()?->getRun();
|
|
}
|
|
}
|
|
|
|
if($execution_policy?->getExitHandlers()->getWarning()?->getRun() !== null)
|
|
{
|
|
if(!in_array($execution_policy?->getExitHandlers()->getWarning()?->getRun(), $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException('The execution policy \'' . $execution_policy?->getName() . '\' Warning exit handler points to a undefined execution policy \'' . $execution_policy?->getExitHandlers()->getWarning()?->getRun() . '\'');
|
|
}
|
|
|
|
if(!in_array($execution_policy?->getExitHandlers()->getWarning()?->getRun(), $required_policies, true))
|
|
{
|
|
$required_policies[] = $execution_policy?->getExitHandlers()->getWarning()?->getRun();
|
|
}
|
|
}
|
|
|
|
if($execution_policy?->getExitHandlers()->getError()?->getRun() !== null)
|
|
{
|
|
if(!in_array($execution_policy?->getExitHandlers()->getError()?->getRun(), $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException('The execution policy \'' . $execution_policy?->getName() . '\' Error exit handler points to a undefined execution policy \'' . $execution_policy?->getExitHandlers()->getError()?->getRun() . '\'');
|
|
}
|
|
|
|
if(!in_array($execution_policy?->getExitHandlers()->getError()?->getRun(), $required_policies, true))
|
|
{
|
|
$required_policies[] = $execution_policy?->getExitHandlers()->getError()?->getRun();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return $required_policies;
|
|
}
|
|
|
|
/**
|
|
* Writes a json representation of the object to a file
|
|
*
|
|
* @param string $path
|
|
* @param bool $bytecode
|
|
* @return void
|
|
* @throws IOException
|
|
*/
|
|
public function toFile(string $path, bool $bytecode=false): void
|
|
{
|
|
if(!$bytecode)
|
|
{
|
|
Functions::encodeJsonFile($this->toArray($bytecode), $path, Functions::FORCE_ARRAY | Functions::PRETTY | Functions::ESCAPE_UNICODE);
|
|
return;
|
|
}
|
|
|
|
Functions::encodeJsonFile($this->toArray($bytecode), $path, Functions::FORCE_ARRAY);
|
|
}
|
|
|
|
/**
|
|
* Loads the object from a file representation
|
|
*
|
|
* @param string $path
|
|
* @return ProjectConfiguration
|
|
* @throws IOException
|
|
* @throws PathNotFoundException
|
|
*/
|
|
public static function fromFile(string $path): ProjectConfiguration
|
|
{
|
|
return self::fromArray(Functions::loadJsonFile($path, Functions::FORCE_ARRAY));
|
|
}
|
|
|
|
/**
|
|
* @param BuildConfiguration $configuration
|
|
* @param array $defined_polices
|
|
* @return array
|
|
* @throws ConfigurationException
|
|
*/
|
|
private function processBuildPolicies(BuildConfiguration $configuration, array $defined_polices): array
|
|
{
|
|
$required_policies = [];
|
|
|
|
if (count($configuration->getPreBuild()) > 0)
|
|
{
|
|
foreach ($configuration->getPreBuild() as $unit)
|
|
{
|
|
if (!in_array($unit, $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException(sprintf("The property 'pre_build' in the build configuration '%s' calls for an undefined execution policy '%s'", $configuration->getName(), $unit));
|
|
}
|
|
|
|
$required_policies[] = $unit;
|
|
}
|
|
}
|
|
|
|
if (count($configuration->getPostBuild()) > 0)
|
|
{
|
|
foreach ($configuration->getPostBuild() as $unit)
|
|
{
|
|
if (!in_array($unit, $defined_polices, true))
|
|
{
|
|
throw new ConfigurationException(sprintf("The property 'post_build' in the build configuration '%s' calls for an undefined execution policy '%s'", $configuration->getName(), $unit));
|
|
}
|
|
|
|
$required_policies[] = $unit;
|
|
}
|
|
}
|
|
|
|
return $required_policies;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
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);
|
|
}
|
|
|
|
if($this->assembly !== null)
|
|
{
|
|
$results[($bytecode ? Functions::cbc('assembly') : 'assembly')] = $this->assembly->toArray($bytecode);
|
|
}
|
|
|
|
if($this->build !== null)
|
|
{
|
|
$results[($bytecode ? Functions::cbc('build') : 'build')] = $this->build->toArray($bytecode);
|
|
}
|
|
|
|
if($this->installer !== null)
|
|
{
|
|
$results[($bytecode ? Functions::cbc('installer') : 'installer')] = $this->installer->toArray($bytecode);
|
|
}
|
|
|
|
if($execution_policies !== null && count($execution_policies) > 0)
|
|
{
|
|
$results[($bytecode ? Functions::cbc('execution_policies') : 'execution_policies')] = $execution_policies;
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
* @param array $data
|
|
* @return ProjectConfiguration
|
|
* @throws ConfigurationException
|
|
* @throws NotSupportedException
|
|
*/
|
|
public static function fromArray(array $data): ProjectConfiguration
|
|
{
|
|
$object = new self();
|
|
|
|
$object->project = Functions::array_bc($data, 'project');
|
|
if($object->project !== null)
|
|
{
|
|
$object->project = Project::fromArray($object->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)
|
|
{
|
|
$object->assembly = Assembly::fromArray($object->assembly);
|
|
}
|
|
|
|
|
|
$object->build = Functions::array_bc($data, 'build');
|
|
if($object->build !== null)
|
|
{
|
|
$object->build = Build::fromArray($object->build);
|
|
}
|
|
|
|
$object->installer = Functions::array_bc($data, 'installer');
|
|
if($object->installer !== null)
|
|
{
|
|
$object->installer = Installer::fromArray($object->installer);
|
|
}
|
|
|
|
$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);
|
|
}
|
|
}
|
|
|
|
return $object;
|
|
}
|
|
} |