- Refactored the entire package structure to ncc package structure 2.0 for memory efficiency and performance
This commit is contained in:
parent
d4f69522fc
commit
d41ae8114f
28 changed files with 1574 additions and 1399 deletions
5
.idea/php.xml
generated
5
.idea/php.xml
generated
|
@ -17,6 +17,11 @@
|
||||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.2">
|
<component name="PhpProjectSharedConfiguration" php_language_level="8.2">
|
||||||
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="PhpRuntimeConfiguration">
|
||||||
|
<extensions>
|
||||||
|
<extension name="msgpack" enabled="true" />
|
||||||
|
</extensions>
|
||||||
|
</component>
|
||||||
<component name="PhpStanOptionsConfiguration">
|
<component name="PhpStanOptionsConfiguration">
|
||||||
<option name="transferred" value="true" />
|
<option name="transferred" value="true" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -226,6 +226,7 @@ features and reduced the number of exceptions down to 15 exceptions.
|
||||||
ExitHandler, Repository, Assembly, Build, Dependency, ExecutionPolicy, Installer, Project, UpdateSource) I'm not
|
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.
|
going to list them all here, but you can find them in the commit history.
|
||||||
- Implemented a template engine and refactored the CLI menu for the Project Manager and added a new `template` command
|
- Implemented a template engine and refactored the CLI menu for the Project Manager and added a new `template` command
|
||||||
|
- Refactored the entire package structure to ncc package structure 2.0 for memory efficiency and performance
|
||||||
|
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Nosial 2022-2023, all rights reserved.
|
* 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
|
* 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
|
* 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
|
* 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
|
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
|
||||||
* conditions:
|
* conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
||||||
* of the Software.
|
* of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
* 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
|
* 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
|
* 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
|
* 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
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace ncc\CLI\Commands;
|
namespace ncc\CLI\Commands;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use ncc\Enums\Options\BuildConfigurationValues;
|
use ncc\Enums\Options\BuildConfigurationValues;
|
||||||
|
@ -58,33 +58,28 @@ namespace ncc\CLI\Commands;
|
||||||
*/
|
*/
|
||||||
private static function build($args): void
|
private static function build($args): void
|
||||||
{
|
{
|
||||||
// Determine the path of the project
|
|
||||||
if(isset($args['path']) || isset($args['p']))
|
if(isset($args['path']) || isset($args['p']))
|
||||||
{
|
{
|
||||||
$path_arg = ($args['path'] ?? $args['p']);
|
$project_path = $args['path'] ?? $args['p'];
|
||||||
|
}
|
||||||
// Check if the path exists
|
elseif(is_file(getcwd() . DIRECTORY_SEPARATOR . 'project.json'))
|
||||||
if(!file_exists($path_arg) || !is_dir($path_arg))
|
{
|
||||||
{
|
$project_path = getcwd();
|
||||||
Console::outError('The given path \'' . $path_arg . '\' is does not exist or is not a directory', true, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$project_path = $path_arg;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$project_path = getcwd();
|
Console::outError('Missing option: --path|-p, please specify the path to the project', true, 1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the project
|
// Load the project
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$ProjectManager = new ProjectManager($project_path);
|
$project_manager = new ProjectManager($project_path);
|
||||||
$ProjectManager->load();
|
|
||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
Console::outException('Failed to load Project Configuration (project.json)', $e, 1);
|
Console::outException('There was an error loading the project', $e, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,10 +92,7 @@ namespace ncc\CLI\Commands;
|
||||||
$build_configuration = $args['config'];
|
$build_configuration = $args['config'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$output = $ProjectManager->build($build_configuration);
|
$output = $project_manager->build($build_configuration);
|
||||||
|
|
||||||
Console::out('Successfully built ' . $output);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
|
@ -108,6 +100,7 @@ namespace ncc\CLI\Commands;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console::out($output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -178,7 +178,7 @@
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Console::out('magic_bytes: ' . json_encode(($package->getMagicBytes()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
Console::out('magic_bytes: ' . json_encode(($package->getMagicBytes()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||||
Console::out('header: ' . json_encode(($package->getHeader()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
Console::out('header: ' . json_encode(($package->getMetadata()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||||
Console::out('assembly: ' . json_encode(($package->getAssembly()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
Console::out('assembly: ' . json_encode(($package->getAssembly()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||||
Console::out('installer: ' . json_encode(($package->getInstaller()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
Console::out('installer: ' . json_encode(($package->getInstaller()?->toArray() ?? []), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||||
}
|
}
|
||||||
|
@ -559,15 +559,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::out(sprintf('Extension: %s',
|
Console::out(sprintf('Extension: %s',
|
||||||
Console::formatColor($package->getHeader()->getCompilerExtension()->getExtension(), ConsoleColors::GREEN)
|
Console::formatColor($package->getMetadata()->getCompilerExtension()->getExtension(), ConsoleColors::GREEN)
|
||||||
));
|
));
|
||||||
|
|
||||||
Console::out(sprintf('Maximum Version: %s',
|
Console::out(sprintf('Maximum Version: %s',
|
||||||
Console::formatColor($package->getHeader()->getCompilerExtension()->getMinimumVersion(), ConsoleColors::LIGHT_MAGENTA)
|
Console::formatColor($package->getMetadata()->getCompilerExtension()->getMinimumVersion(), ConsoleColors::LIGHT_MAGENTA)
|
||||||
));
|
));
|
||||||
|
|
||||||
Console::out(sprintf('Minimum Version: %s',
|
Console::out(sprintf('Minimum Version: %s',
|
||||||
Console::formatColor($package->getHeader()->getCompilerExtension()->getMinimumVersion(), ConsoleColors::LIGHT_MAGENTA)
|
Console::formatColor($package->getMetadata()->getCompilerExtension()->getMinimumVersion(), ConsoleColors::LIGHT_MAGENTA)
|
||||||
));
|
));
|
||||||
|
|
||||||
if(!$user_confirmation)
|
if(!$user_confirmation)
|
||||||
|
|
188
src/ncc/Classes/NccExtension/NccCompiler.php
Normal file
188
src/ncc/Classes/NccExtension/NccCompiler.php
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/** @noinspection PhpMissingFieldTypeInspection */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ncc\Classes\NccExtension;
|
||||||
|
|
||||||
|
use ncc\Classes\PackageWriter;
|
||||||
|
use ncc\CLI\Main;
|
||||||
|
use ncc\Enums\ComponentDataType;
|
||||||
|
use ncc\Enums\LogLevel;
|
||||||
|
use ncc\Enums\Options\BuildConfigurationValues;
|
||||||
|
use ncc\Exceptions\ConfigurationException;
|
||||||
|
use ncc\Exceptions\IOException;
|
||||||
|
use ncc\Exceptions\NotSupportedException;
|
||||||
|
use ncc\Exceptions\PathNotFoundException;
|
||||||
|
use ncc\Managers\ProjectManager;
|
||||||
|
use ncc\Objects\Package;
|
||||||
|
use ncc\Objects\Package\Resource;
|
||||||
|
use ncc\Utilities\Base64;
|
||||||
|
use ncc\Utilities\Console;
|
||||||
|
use ncc\Utilities\Functions;
|
||||||
|
use ncc\Utilities\IO;
|
||||||
|
use ncc\Utilities\Resolver;
|
||||||
|
|
||||||
|
class NccCompiler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ProjectManager
|
||||||
|
*/
|
||||||
|
private $project_manager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ProjectManager $project_manager
|
||||||
|
*/
|
||||||
|
public function __construct(ProjectManager $project_manager)
|
||||||
|
{
|
||||||
|
$this->project_manager = $project_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $build_configuration
|
||||||
|
* @return string
|
||||||
|
* @throws ConfigurationException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws NotSupportedException
|
||||||
|
* @throws PathNotFoundException
|
||||||
|
*/
|
||||||
|
public function build(string $build_configuration=BuildConfigurationValues::DEFAULT): string
|
||||||
|
{
|
||||||
|
$configuration = $this->project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
|
||||||
|
$package_path = $configuration->getOutputPath() . DIRECTORY_SEPARATOR . $this->project_manager->getProjectConfiguration()->getAssembly()->getPackage() . '.ncc';
|
||||||
|
$package_writer = new PackageWriter($package_path);
|
||||||
|
|
||||||
|
Console::out(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()));
|
||||||
|
|
||||||
|
// Debugging information
|
||||||
|
if(Resolver::checkLogLevel(LogLevel::DEBUG, Main::getLogLevel()))
|
||||||
|
{
|
||||||
|
foreach($this->project_manager->getProjectConfiguration()->getAssembly()->toArray() as $prop => $value)
|
||||||
|
{
|
||||||
|
Console::outDebug(sprintf('assembly.%s: %s', $prop, ($value ?? 'n/a')));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->project_manager->getProjectConfiguration()->getProject()->getCompiler()->toArray() as $prop => $value)
|
||||||
|
{
|
||||||
|
Console::outDebug(sprintf('compiler.%s: %s', $prop, ($value ?? 'n/a')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::outVerbose('Building package header...');
|
||||||
|
$package_writer->setMetadata($this->buildMetadata($build_configuration));
|
||||||
|
|
||||||
|
Console::outVerbose('Adding assembly information...');
|
||||||
|
$package_writer->setAssembly($this->project_manager->getProjectConfiguration()->getAssembly());
|
||||||
|
|
||||||
|
if($this->project_manager->getProjectConfiguration()->getInstaller() !== null)
|
||||||
|
{
|
||||||
|
Console::outVerbose('Adding installer information...');
|
||||||
|
/** @noinspection NullPointerExceptionInspection */
|
||||||
|
$package_writer->setInstaller($this->project_manager->getProjectConfiguration()->getInstaller());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process execution policies
|
||||||
|
if(count($this->project_manager->getProjectConfiguration()->getExecutionPolicies()) > 0)
|
||||||
|
{
|
||||||
|
Console::out('Processing execution policies...');
|
||||||
|
$execution_units = $this->project_manager->getExecutionUnits($build_configuration);
|
||||||
|
|
||||||
|
if(count($execution_units) === 0)
|
||||||
|
{
|
||||||
|
Console::outWarning('The project contains execution policies but none of them are used');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($execution_units as $unit)
|
||||||
|
{
|
||||||
|
$package_writer->addExecutionUnit($unit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile package components
|
||||||
|
foreach($this->project_manager->getComponents($build_configuration) as $component)
|
||||||
|
{
|
||||||
|
Console::outVerbose(sprintf('Compiling \'%s\'', $component));
|
||||||
|
$package_writer->addComponent($this->buildComponent($component));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile package resources
|
||||||
|
foreach($this->project_manager->getResources($build_configuration) as $resource)
|
||||||
|
{
|
||||||
|
Console::outVerbose(sprintf('Processing \'%s\'', $resource));
|
||||||
|
$package_writer->addResource($this->buildResource($resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
$package_writer->close();
|
||||||
|
return $package_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles a single component as a base64 encoded string
|
||||||
|
*
|
||||||
|
* @param string $file_path
|
||||||
|
* @return Package\Component
|
||||||
|
* @throws IOException
|
||||||
|
* @throws PathNotFoundException
|
||||||
|
*/
|
||||||
|
public function buildComponent(string $file_path): Package\Component
|
||||||
|
{
|
||||||
|
return new Package\Component(
|
||||||
|
Functions::removeBasename($file_path),
|
||||||
|
Base64::encode(IO::fread($file_path)), ComponentDataType::BASE64_ENCODED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $file_path
|
||||||
|
* @return Resource
|
||||||
|
* @throws IOException
|
||||||
|
* @throws PathNotFoundException
|
||||||
|
*/
|
||||||
|
public function buildResource(string $file_path): Package\Resource
|
||||||
|
{
|
||||||
|
return new Package\Resource(
|
||||||
|
basename($file_path), IO::fread($file_path)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the package header
|
||||||
|
*
|
||||||
|
* @param ProjectManager $project_manager
|
||||||
|
* @param string $build_configuration
|
||||||
|
* @return Package\Metadata
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function buildMetadata(string $build_configuration=BuildConfigurationValues::DEFAULT): Package\Metadata
|
||||||
|
{
|
||||||
|
$header = new Package\Metadata($this->project_manager->getProjectConfiguration()->getProject()->getCompiler());
|
||||||
|
|
||||||
|
$header->setRuntimeConstants($this->project_manager->getRuntimeConstants($build_configuration));
|
||||||
|
$header->setOptions($this->project_manager->getCompilerOptions($build_configuration));
|
||||||
|
$header->setUpdateSource($this->project_manager->getProjectConfiguration()->getProject()->getUpdateSource());
|
||||||
|
$header->setMainExecutionPolicy($this->project_manager->getProjectConfiguration()->getBuild()->getMain());
|
||||||
|
$header->setInstaller($this->project_manager->getProjectConfiguration()->getInstaller());
|
||||||
|
|
||||||
|
return $header;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,405 +0,0 @@
|
||||||
<?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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace ncc\Classes\NccExtension;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use ncc\Enums\CompilerExtensions;
|
|
||||||
use ncc\Enums\ConstantReferences;
|
|
||||||
use ncc\Enums\LogLevel;
|
|
||||||
use ncc\Enums\Options\BuildConfigurationValues;
|
|
||||||
use ncc\Enums\ProjectType;
|
|
||||||
use ncc\Classes\ComposerExtension\ComposerSourceBuiltin;
|
|
||||||
use ncc\Classes\PhpExtension\PhpCompiler;
|
|
||||||
use ncc\CLI\Main;
|
|
||||||
use ncc\Exceptions\BuildException;
|
|
||||||
use ncc\Exceptions\ConfigurationException;
|
|
||||||
use ncc\Exceptions\IOException;
|
|
||||||
use ncc\Exceptions\NotSupportedException;
|
|
||||||
use ncc\Exceptions\PathNotFoundException;
|
|
||||||
use ncc\Interfaces\CompilerInterface;
|
|
||||||
use ncc\Managers\ProjectManager;
|
|
||||||
use ncc\ncc;
|
|
||||||
use ncc\Objects\Package;
|
|
||||||
use ncc\Objects\ProjectConfiguration;
|
|
||||||
use ncc\Objects\ProjectConfiguration\Assembly;
|
|
||||||
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
|
|
||||||
use ncc\Utilities\Console;
|
|
||||||
use ncc\Utilities\Functions;
|
|
||||||
use ncc\Utilities\Resolver;
|
|
||||||
|
|
||||||
class PackageCompiler
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Compiles the project into a package
|
|
||||||
*
|
|
||||||
* @param ProjectManager $manager
|
|
||||||
* @param string $build_configuration
|
|
||||||
* @return string
|
|
||||||
* @throws BuildException
|
|
||||||
* @throws ConfigurationException
|
|
||||||
* @throws IOException
|
|
||||||
* @throws NotSupportedException
|
|
||||||
* @throws PathNotFoundException
|
|
||||||
*/
|
|
||||||
public static function compile(ProjectManager $manager, string $build_configuration=BuildConfigurationValues::DEFAULT): string
|
|
||||||
{
|
|
||||||
$configuration = $manager->getProjectConfiguration();
|
|
||||||
|
|
||||||
if(Resolver::checkLogLevel(LogLevel::DEBUG, Main::getLogLevel()))
|
|
||||||
{
|
|
||||||
foreach($configuration->getAssembly()->toArray() as $prop => $value)
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('assembly.%s: %s', $prop, ($value ?? 'n/a')));
|
|
||||||
}
|
|
||||||
foreach($configuration->getProject()->getCompiler()->toArray() as $prop => $value)
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('compiler.%s: %s', $prop, ($value ?? 'n/a')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select the correct compiler for the specified extension
|
|
||||||
if (strtolower($configuration->getProject()->getCompiler()->getExtension()) === CompilerExtensions::PHP)
|
|
||||||
{
|
|
||||||
/** @var CompilerInterface $Compiler */
|
|
||||||
$Compiler = new PhpCompiler($configuration, $manager->getProjectPath());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotSupportedException('The compiler extension \'' . $configuration->getProject()->getCompiler()->getExtension() . '\' is not supported');
|
|
||||||
}
|
|
||||||
|
|
||||||
$build_configuration = $configuration->getBuild()->getBuildConfiguration($build_configuration)->getName();
|
|
||||||
Console::out(sprintf('Building %s=%s', $configuration->getAssembly()->getPackage(), $configuration->getAssembly()->getVersion()));
|
|
||||||
$Compiler->prepare($build_configuration);
|
|
||||||
$Compiler->build();
|
|
||||||
|
|
||||||
return self::writePackage(
|
|
||||||
$manager->getProjectPath(), $Compiler->getPackage(), $configuration, $build_configuration
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to detect the project type and convert it accordingly before compiling
|
|
||||||
* Returns the compiled package path
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param string|null $version
|
|
||||||
* @return string
|
|
||||||
* @throws BuildException
|
|
||||||
*/
|
|
||||||
public static function tryCompile(string $path, ?string $version=null): string
|
|
||||||
{
|
|
||||||
$project_type = Resolver::detectProjectType($path);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if($project_type->getProjectType() === ProjectType::COMPOSER)
|
|
||||||
{
|
|
||||||
$project_path = ComposerSourceBuiltin::fromLocal($project_type->getProjectPath());
|
|
||||||
}
|
|
||||||
elseif($project_type->getProjectType() === ProjectType::NCC)
|
|
||||||
{
|
|
||||||
$project_manager = new ProjectManager($project_type->getProjectPath());
|
|
||||||
$project_manager->getProjectConfiguration()->getAssembly()->setVersion($version);
|
|
||||||
$project_path = $project_manager->build();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotSupportedException(sprintf('Failed to compile %s, project type %s is not supported', $project_type->getProjectPath(), $project_type->getProjectType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if($version !== null)
|
|
||||||
{
|
|
||||||
$package = Package::load($project_path);
|
|
||||||
$package->getAssembly()->setVersion(Functions::convertToSemVer($version));
|
|
||||||
$package->save($project_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $project_path;
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new BuildException('Failed to build project', $e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the execution policies of the package
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param ProjectConfiguration $configuration
|
|
||||||
* @return array
|
|
||||||
* @throws IOException
|
|
||||||
* @throws NotSupportedException
|
|
||||||
* @throws PathNotFoundException
|
|
||||||
*/
|
|
||||||
public static function compileExecutionPolicies(string $path, ProjectConfiguration $configuration): array
|
|
||||||
{
|
|
||||||
if(count($configuration->getExecutionPolicies()) === 0)
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::out('Compiling Execution Policies');
|
|
||||||
$total_items = count($configuration->getExecutionPolicies());
|
|
||||||
$execution_units = [];
|
|
||||||
$processed_items = 1;
|
|
||||||
|
|
||||||
/** @var ProjectConfiguration\ExecutionPolicy $policy */
|
|
||||||
foreach($configuration->getExecutionPolicies() as $policy)
|
|
||||||
{
|
|
||||||
Console::outVerbose(sprintf('Compiling Execution Policy %s', $policy->getName()));
|
|
||||||
|
|
||||||
/** @noinspection DisconnectedForeachInstructionInspection */
|
|
||||||
if($total_items > 5)
|
|
||||||
{
|
|
||||||
Console::inlineProgressBar($processed_items, $total_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
$unit_path = Functions::correctDirectorySeparator($path . $policy->getExecute()->getTarget());
|
|
||||||
$execution_units[] = Functions::compileRunner($unit_path, $policy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($total_items > 5 && ncc::cliMode())
|
|
||||||
{
|
|
||||||
print(PHP_EOL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $execution_units;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the finished package to disk, returns the output path
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param Package $package
|
|
||||||
* @param ProjectConfiguration $configuration
|
|
||||||
* @param string $build_configuration
|
|
||||||
* @return string
|
|
||||||
* @throws IOException
|
|
||||||
* @throws ConfigurationException
|
|
||||||
*/
|
|
||||||
public static function writePackage(string $path, Package $package, ProjectConfiguration $configuration, string $build_configuration=BuildConfigurationValues::DEFAULT): string
|
|
||||||
{
|
|
||||||
Console::outVerbose(sprintf('Writing package to %s', $path));
|
|
||||||
|
|
||||||
// Write the package to disk
|
|
||||||
$FileSystem = new Filesystem();
|
|
||||||
$BuildConfiguration = $configuration->getBuild()->getBuildConfiguration($build_configuration);
|
|
||||||
if(!$FileSystem->exists($path . $BuildConfiguration->getOutputPath()))
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('creating output directory %s', $path . $BuildConfiguration->getOutputPath()));
|
|
||||||
$FileSystem->mkdir($path . $BuildConfiguration->getOutputPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally write the package to the disk
|
|
||||||
$FileSystem->mkdir($path . $BuildConfiguration->getOutputPath());
|
|
||||||
$output_file = $path . $BuildConfiguration->getOutputPath() . DIRECTORY_SEPARATOR . $package->getAssembly()->getPackage() . '.ncc';
|
|
||||||
if($FileSystem->exists($output_file))
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('removing existing package %s', $output_file));
|
|
||||||
$FileSystem->remove($output_file);
|
|
||||||
}
|
|
||||||
$FileSystem->touch($output_file);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$package->save($output_file);
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new IOException('Cannot write to output file', $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the constants in the package object
|
|
||||||
*
|
|
||||||
* @param Package $package
|
|
||||||
* @param array $refs
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function compilePackageConstants(Package $package, array $refs): void
|
|
||||||
{
|
|
||||||
if($package->getAssembly() !== null)
|
|
||||||
{
|
|
||||||
$assembly = [];
|
|
||||||
|
|
||||||
foreach($package->getAssembly()->toArray() as $key => $value)
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('compiling constant Assembly.%s (%s)', $key, implode(', ', array_keys($refs))));
|
|
||||||
$assembly[$key] = self::compileConstants($value, $refs);
|
|
||||||
}
|
|
||||||
$package->setAssembly(Assembly::fromArray($assembly));
|
|
||||||
|
|
||||||
unset($assembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($package->getExecutionUnits()) > 0)
|
|
||||||
{
|
|
||||||
$units = [];
|
|
||||||
foreach($package->ExecutionUnits() as $executionUnit)
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('compiling execution unit constant %s (%s)', $executionUnit->getExecutionPolicy()->getName(), implode(', ', array_keys($refs))));
|
|
||||||
$units[] = self::compileExecutionUnitConstants($executionUnit, $refs);
|
|
||||||
}
|
|
||||||
$package->setExecutionUnits($units);
|
|
||||||
unset($units);
|
|
||||||
}
|
|
||||||
|
|
||||||
$compiled_constants = [];
|
|
||||||
foreach($package->getHeader()->getRuntimeConstants() as $name => $value)
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('compiling runtime constant %s (%s)', $name, implode(', ', array_keys($refs))));
|
|
||||||
$compiled_constants[$name] = self::compileConstants($value, $refs);
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = [];
|
|
||||||
foreach($package->getHeader()->getOptions() as $name => $value)
|
|
||||||
{
|
|
||||||
if(is_array($value))
|
|
||||||
{
|
|
||||||
$options[$name] = [];
|
|
||||||
foreach($value as $key => $val)
|
|
||||||
{
|
|
||||||
if(!is_string($val))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::outDebug(sprintf('compiling option %s.%s (%s)', $name, $key, implode(', ', array_keys($refs))));
|
|
||||||
$options[$name][$key] = self::compileConstants($val, $refs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console::outDebug(sprintf('compiling option %s (%s)', $name, implode(', ', array_keys($refs))));
|
|
||||||
$options[$name] = self::compileConstants((string)$value, $refs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$package->getHeader()->setOptions($options);
|
|
||||||
$package->getHeader()->setRuntimeConstants($compiled_constants);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the constants in a given execution unit
|
|
||||||
*
|
|
||||||
* @param Package\ExecutionUnit $unit
|
|
||||||
* @param array $refs
|
|
||||||
* @return Package\ExecutionUnit
|
|
||||||
*/
|
|
||||||
public static function compileExecutionUnitConstants(Package\ExecutionUnit $unit, array $refs): Package\ExecutionUnit
|
|
||||||
{
|
|
||||||
$unit->getExecutionPolicy()->setMessage(self::compileConstants($unit->getExecutionPolicy()->getMessage(), $refs));
|
|
||||||
|
|
||||||
if($unit->getExecutionPolicy()->getExitHandlers() !== null)
|
|
||||||
{
|
|
||||||
if($unit->getExecutionPolicy()->getExitHandlers()->getSuccess()?->getMessage() !== null)
|
|
||||||
{
|
|
||||||
$unit->getExecutionPolicy()->getExitHandlers()->getSuccess()?->setMessage(
|
|
||||||
self::compileConstants($unit->getExecutionPolicy()->getExitHandlers()->getSuccess()->getMessage(), $refs)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($unit->getExecutionPolicy()->getExitHandlers()->getError()?->getMessage() !== null)
|
|
||||||
{
|
|
||||||
$unit->getExecutionPolicy()->getExitHandlers()->getError()?->setMessage(
|
|
||||||
self::compileConstants($unit->getExecutionPolicy()->getExitHandlers()->getError()->getMessage(), $refs)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($unit->getExecutionPolicy()->getExitHandlers()->getWarning()?->getMessage() !== null)
|
|
||||||
{
|
|
||||||
$unit->getExecutionPolicy()->getExitHandlers()->getWarning()?->setMessage(
|
|
||||||
self::compileConstants($unit->getExecutionPolicy()->getExitHandlers()->getWarning()->getMessage(), $refs)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if($unit->getExecutionPolicy()->getExecute() !== null)
|
|
||||||
{
|
|
||||||
$unit->getExecutionPolicy()->getExecute()->setTarget(self::compileConstants($unit->getExecutionPolicy()->getExecute()->getTarget(), $refs));
|
|
||||||
$unit->getExecutionPolicy()->getExecute()->setWorkingDirectory(self::compileConstants($unit->getExecutionPolicy()->getExecute()->getWorkingDirectory(), $refs));
|
|
||||||
|
|
||||||
if(count($unit->getExecutionPolicy()->getExecute()->getOptions()) > 0)
|
|
||||||
{
|
|
||||||
$options = [];
|
|
||||||
foreach($unit->getExecutionPolicy()->getExecute()->getOptions() as $key=> $value)
|
|
||||||
{
|
|
||||||
$options[self::compileConstants($key, $refs)] = self::compileConstants($value, $refs);
|
|
||||||
}
|
|
||||||
|
|
||||||
$unit->getExecutionPolicy()->getExecute()->setOptions($options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles multiple types of constants
|
|
||||||
*
|
|
||||||
* @param string|null $value
|
|
||||||
* @param array $refs
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public static function compileConstants(?string $value, array $refs): ?string
|
|
||||||
{
|
|
||||||
if($value === null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($refs[ConstantReferences::ASSEMBLY]))
|
|
||||||
{
|
|
||||||
$value = ConstantCompiler::compileAssemblyConstants($value, $refs[ConstantReferences::ASSEMBLY]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($refs[ConstantReferences::BUILD]))
|
|
||||||
{
|
|
||||||
$value = ConstantCompiler::compileBuildConstants($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($refs[ConstantReferences::DATE_TIME]))
|
|
||||||
{
|
|
||||||
$value = ConstantCompiler::compileDateTimeConstants($value, $refs[ConstantReferences::DATE_TIME]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($refs[ConstantReferences::INSTALL]))
|
|
||||||
{
|
|
||||||
$value = ConstantCompiler::compileInstallConstants($value, $refs[ConstantReferences::INSTALL]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($refs[ConstantReferences::RUNTIME]))
|
|
||||||
{
|
|
||||||
$value = ConstantCompiler::compileRuntimeConstants($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
388
src/ncc/Classes/PackageReader.php
Normal file
388
src/ncc/Classes/PackageReader.php
Normal file
|
@ -0,0 +1,388 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/** @noinspection PhpMissingFieldTypeInspection */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ncc\Classes;
|
||||||
|
|
||||||
|
use ncc\Exceptions\ConfigurationException;
|
||||||
|
use ncc\Exceptions\IOException;
|
||||||
|
use ncc\Objects\Package\Component;
|
||||||
|
use ncc\Objects\Package\ExecutionUnit;
|
||||||
|
use ncc\Objects\Package\Metadata;
|
||||||
|
use ncc\Objects\ProjectConfiguration\Assembly;
|
||||||
|
use ncc\Objects\ProjectConfiguration\Installer;
|
||||||
|
use ncc\ZiProto\ZiProto;
|
||||||
|
use RuntimeException;
|
||||||
|
use ncc\Enums\PackageStructure;
|
||||||
|
|
||||||
|
class PackageReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $header_length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
private $package_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PackageReader constructor.
|
||||||
|
*
|
||||||
|
* @param string $file_path
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function __construct(string $file_path)
|
||||||
|
{
|
||||||
|
if (!is_file($file_path))
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('File \'%s\' does not exist', $file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->package_file = fopen($file_path, 'rb');
|
||||||
|
if($this->package_file === false)
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('Failed to open file \'%s\'', $file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$magic_bytes = fread($this->package_file, 7);
|
||||||
|
$header = '';
|
||||||
|
$diameter_hit = false;
|
||||||
|
$this->header_length = 7;
|
||||||
|
|
||||||
|
// Check for the magic bytes "ncc_pkg"
|
||||||
|
if($magic_bytes !== 'ncc_pkg')
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('File \'%s\' is not a valid package file (invalid magic bytes)', $file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read everything after "ncc_pkg" up until the delimiter (0x1F 0x1F)
|
||||||
|
while(!feof($this->package_file))
|
||||||
|
{
|
||||||
|
$this->header_length++;
|
||||||
|
$header .= fread($this->package_file, 1);
|
||||||
|
|
||||||
|
if(str_ends_with($header, "\x1F\x1F"))
|
||||||
|
{
|
||||||
|
$diameter_hit = true;
|
||||||
|
$header = substr($header, 0, -2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop at 100MB
|
||||||
|
if($this->header_length >= 100000000)
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('File \'%s\' is not a valid package file (header is too large)', $file_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$diameter_hit)
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('File \'%s\' is not a valid package file (invalid header)', $file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->headers = ZiProto::decode($header);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package headers
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getHeaders(): array
|
||||||
|
{
|
||||||
|
return $this->headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package file version
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFileVersion(): string
|
||||||
|
{
|
||||||
|
return $this->headers[PackageStructure::FILE_VERSION];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of flags from the package
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFlags(): array
|
||||||
|
{
|
||||||
|
return $this->headers[PackageStructure::FLAGS];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a flag from the package
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getFlag(string $name): bool
|
||||||
|
{
|
||||||
|
return in_array($name, $this->headers[PackageStructure::FLAGS], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the directory of the package
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDirectory(): array
|
||||||
|
{
|
||||||
|
return $this->headers[PackageStructure::DIRECTORY];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a resource from the package
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get(string $name): string
|
||||||
|
{
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY][$name]))
|
||||||
|
{
|
||||||
|
throw new RuntimeException(sprintf('File \'%s\' not found in package', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
$location = explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
|
||||||
|
fseek($this->package_file, ($this->header_length + (int)$location[0]));
|
||||||
|
return fread($this->package_file, (int)$location[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package's assembly
|
||||||
|
*
|
||||||
|
* @return Assembly
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getAssembly(): Assembly
|
||||||
|
{
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY]['@assembly']))
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('Package does not contain an assembly');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Assembly::fromArray(ZiProto::decode($this->get('@assembly')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package's metadata
|
||||||
|
*
|
||||||
|
* @return Metadata
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getMetadata(): Metadata
|
||||||
|
{
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY]['@metadata']))
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('Package does not contain metadata');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Metadata::fromArray(ZiProto::decode($this->get('@metadata')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional. Returns the package's installer
|
||||||
|
*
|
||||||
|
* @return Installer|null
|
||||||
|
*/
|
||||||
|
public function getInstaller(): ?Installer
|
||||||
|
{
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY]['@installer']))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Installer::fromArray(ZiProto::decode($this->get('@installer')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package's dependencies
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDependencies(): array
|
||||||
|
{
|
||||||
|
$dependencies = [];
|
||||||
|
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
|
||||||
|
{
|
||||||
|
if(str_starts_with($name, '@dependencies:'))
|
||||||
|
{
|
||||||
|
$dependencies[] = str_replace('@dependencies:', '', $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a dependency from the package
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return array
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getDependency(string $name): array
|
||||||
|
{
|
||||||
|
$dependency_name = sprintf('@dependencies:%s', $name);
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY][$dependency_name]))
|
||||||
|
{
|
||||||
|
throw new ConfigurationException(sprintf('Dependency \'%s\' not found in package', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZiProto::decode($this->get('@dependencies:' . $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of execution units from the package
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getExecutionUnits(): array
|
||||||
|
{
|
||||||
|
$execution_units = [];
|
||||||
|
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
|
||||||
|
{
|
||||||
|
if(str_starts_with($name, '@execution_units:'))
|
||||||
|
{
|
||||||
|
$execution_units[] = str_replace('@execution_units:', '', $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $execution_units;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an execution unit from the package
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return ExecutionUnit
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getExecutionUnit(string $name): ExecutionUnit
|
||||||
|
{
|
||||||
|
$execution_unit_name = sprintf('@execution_units:%s', $name);
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY][$execution_unit_name]))
|
||||||
|
{
|
||||||
|
throw new ConfigurationException(sprintf('Execution unit \'%s\' not found in package', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExecutionUnit::fromArray(ZiProto::decode($this->get($execution_unit_name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package's components
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getComponents(): array
|
||||||
|
{
|
||||||
|
$components = [];
|
||||||
|
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
|
||||||
|
{
|
||||||
|
if(str_starts_with($name, '@components:'))
|
||||||
|
{
|
||||||
|
$components[] = str_replace('@components:', '', $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $components;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a component from the package
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return Component
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getComponent(string $name): Component
|
||||||
|
{
|
||||||
|
$component_name = sprintf('@components:%s', $name);
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY][$component_name]))
|
||||||
|
{
|
||||||
|
throw new ConfigurationException(sprintf('Component \'%s\' not found in package', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Component::fromArray(ZiProto::decode($this->get('@components:' . $name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of resources from the package
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getResources(): array
|
||||||
|
{
|
||||||
|
$resources = [];
|
||||||
|
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
|
||||||
|
{
|
||||||
|
if(str_starts_with($name, '@resources:'))
|
||||||
|
{
|
||||||
|
$resources[] = str_replace('@resources:', '', $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a resource from the package
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getResource(string $name): string
|
||||||
|
{
|
||||||
|
$resource_name = sprintf('@resources:%s', $name);
|
||||||
|
if(!isset($this->headers[PackageStructure::DIRECTORY][$resource_name]))
|
||||||
|
{
|
||||||
|
throw new ConfigurationException(sprintf('Resource \'%s\' not found in package', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->get('@resources:' . $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PackageReader destructor.
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if(is_resource($this->package_file))
|
||||||
|
{
|
||||||
|
fclose($this->package_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
331
src/ncc/Classes/PackageWriter.php
Normal file
331
src/ncc/Classes/PackageWriter.php
Normal file
|
@ -0,0 +1,331 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/** @noinspection PhpMissingFieldTypeInspection */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ncc\Classes;
|
||||||
|
|
||||||
|
use ncc\Enums\PackageStructure;
|
||||||
|
use ncc\Enums\PackageStructureVersions;
|
||||||
|
use ncc\Exceptions\IOException;
|
||||||
|
use ncc\Objects\Package\Component;
|
||||||
|
use ncc\Objects\Package\ExecutionUnit;
|
||||||
|
use ncc\Objects\Package\Metadata;
|
||||||
|
use ncc\Objects\Package\Resource;
|
||||||
|
use ncc\Objects\ProjectConfiguration\Assembly;
|
||||||
|
use ncc\Objects\ProjectConfiguration\Dependency;
|
||||||
|
use ncc\Objects\ProjectConfiguration\Installer;
|
||||||
|
use ncc\ZiProto\ZiProto;
|
||||||
|
|
||||||
|
class PackageWriter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
private $temp_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
private $package_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string;
|
||||||
|
*/
|
||||||
|
private $temporary_path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PackageWriter constructor.
|
||||||
|
*
|
||||||
|
* @param string $file_path
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function __construct(string $file_path, bool $overwrite=true)
|
||||||
|
{
|
||||||
|
if(!$overwrite && is_file($file_path))
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('File \'%s\' already exists', $file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_file($file_path))
|
||||||
|
{
|
||||||
|
unlink($file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_file($file_path . '.tmp'))
|
||||||
|
{
|
||||||
|
unlink($file_path . '.tmp');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the parent directory if it doesn't exist
|
||||||
|
if(!is_dir(dirname($file_path)))
|
||||||
|
{
|
||||||
|
if (!mkdir($concurrentDirectory = dirname($file_path), 0777, true) && !is_dir($concurrentDirectory))
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('Directory "%s" was not created', $concurrentDirectory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
touch($file_path);
|
||||||
|
touch($file_path . '.tmp');
|
||||||
|
|
||||||
|
$this->temporary_path = $file_path . '.tmp';
|
||||||
|
$this->temp_file = @fopen($this->temporary_path, 'wb'); // Create a temporary data file
|
||||||
|
$this->package_file = @fopen($file_path, 'wb');
|
||||||
|
$this->headers = [
|
||||||
|
PackageStructure::FILE_VERSION => PackageStructureVersions::_2_0,
|
||||||
|
PackageStructure::FLAGS => [],
|
||||||
|
PackageStructure::DIRECTORY => []
|
||||||
|
];
|
||||||
|
|
||||||
|
if($this->temp_file === false || $this->package_file === false)
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('Failed to open file \'%s\'', $file_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package file version
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFileVersion(): string
|
||||||
|
{
|
||||||
|
return (string)$this->headers[PackageStructure::FILE_VERSION];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the package file version
|
||||||
|
*
|
||||||
|
* @param string $version
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFileVersion(string $version): void
|
||||||
|
{
|
||||||
|
$this->headers[PackageStructure::FILE_VERSION] = $version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the package flags
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getFlags(): array
|
||||||
|
{
|
||||||
|
return (array)$this->headers[PackageStructure::FLAGS];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the package flags
|
||||||
|
*
|
||||||
|
* @param array $flags
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFlags(array $flags): void
|
||||||
|
{
|
||||||
|
$this->headers[PackageStructure::FLAGS] = $flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a flag to the package
|
||||||
|
*
|
||||||
|
* @param string $flag
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addFlag(string $flag): void
|
||||||
|
{
|
||||||
|
if(!in_array($flag, $this->headers[PackageStructure::FLAGS], true))
|
||||||
|
{
|
||||||
|
$this->headers[PackageStructure::FLAGS][] = $flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a flag from the package
|
||||||
|
*
|
||||||
|
* @param string $flag
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function removeFlag(string $flag): void
|
||||||
|
{
|
||||||
|
$this->headers[PackageStructure::FLAGS] = array_diff($this->headers[PackageStructure::FLAGS], [$flag]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a file to the package by writing to the temporary data file
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $data
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function add(string $name, string $data): void
|
||||||
|
{
|
||||||
|
if(isset($this->headers[PackageStructure::DIRECTORY][$name]))
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('Resource \'%s\' already exists in package', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->headers[PackageStructure::DIRECTORY][$name] = sprintf("%d:%d", ftell($this->temp_file), strlen($data));
|
||||||
|
fwrite($this->temp_file, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the assembly of the package
|
||||||
|
*
|
||||||
|
* @param Assembly $assembly
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function setAssembly(Assembly $assembly): void
|
||||||
|
{
|
||||||
|
$this->add('@assembly', ZiProto::encode($assembly->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the metadata to the package
|
||||||
|
*
|
||||||
|
* @param Metadata $metadata
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function setMetadata(Metadata $metadata): void
|
||||||
|
{
|
||||||
|
$this->add('@metadata', ZiProto::encode($metadata->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the installer information of the package
|
||||||
|
*
|
||||||
|
* @param Installer $installer
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function setInstaller(Installer $installer): void
|
||||||
|
{
|
||||||
|
$this->add('@installer', ZiProto::encode($installer->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a dependency configuration to the package
|
||||||
|
*
|
||||||
|
* @param Dependency $dependency
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function addDependencyConfiguration(Dependency $dependency): void
|
||||||
|
{
|
||||||
|
$this->add(sprintf('@dependencies:%s', $dependency->getName()), ZiProto::encode($dependency->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an execution unit to the package
|
||||||
|
*
|
||||||
|
* @param ExecutionUnit $unit
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function addExecutionUnit(ExecutionUnit $unit): void
|
||||||
|
{
|
||||||
|
$this->add(sprintf('@execution_units:%s', $unit->getExecutionPolicy()->getName()), ZiProto::encode($unit->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a component to the package
|
||||||
|
*
|
||||||
|
* @param Component $component
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function addComponent(Component $component): void
|
||||||
|
{
|
||||||
|
$this->add(sprintf('@components:%s', $component->getName()), ZiProto::encode($component->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a resource to the package
|
||||||
|
*
|
||||||
|
* @param Resource $resource
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function addResource(Resource $resource): void
|
||||||
|
{
|
||||||
|
$this->add(sprintf('@resources:%s', $resource->getName()), $resource->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizes the package by writing the magic bytes, header length, delimiter, headers, and data to the file
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public function close(): void
|
||||||
|
{
|
||||||
|
if(!is_resource($this->package_file) || !is_resource($this->temp_file))
|
||||||
|
{
|
||||||
|
throw new IOException('Package is already closed');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the temporary data file
|
||||||
|
fclose($this->temp_file);
|
||||||
|
|
||||||
|
// Write the magic bytes "ncc_pkg" to the package and the header
|
||||||
|
fwrite($this->package_file, 'ncc_pkg');
|
||||||
|
fwrite($this->package_file, ZiProto::encode($this->headers));
|
||||||
|
fwrite($this->package_file, chr(0x1F) . chr(0x1F));
|
||||||
|
|
||||||
|
// Copy the temporary data file to the package
|
||||||
|
$temp_file = fopen($this->temporary_path, 'rb');
|
||||||
|
stream_copy_to_stream($temp_file, $this->package_file);
|
||||||
|
|
||||||
|
// Close the file handles
|
||||||
|
fclose($this->package_file);
|
||||||
|
fclose($temp_file);
|
||||||
|
|
||||||
|
unlink($this->temporary_path);
|
||||||
|
|
||||||
|
$this->package_file = null;
|
||||||
|
$this->temp_file = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the package when the object is destroyed
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
catch(IOException $e)
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
src/ncc/Classes/PhpExtension/NccCompiler.php
Normal file
65
src/ncc/Classes/PhpExtension/NccCompiler.php
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ncc\Classes\PhpExtension;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use ncc\Enums\ComponentDataType;
|
||||||
|
use ncc\Exceptions\IOException;
|
||||||
|
use ncc\Exceptions\PathNotFoundException;
|
||||||
|
use ncc\Objects\Package\Component;
|
||||||
|
use ncc\ThirdParty\nikic\PhpParser\ParserFactory;
|
||||||
|
use ncc\Utilities\Base64;
|
||||||
|
use ncc\Utilities\Console;
|
||||||
|
use ncc\Utilities\Functions;
|
||||||
|
use ncc\Utilities\IO;
|
||||||
|
use ncc\ZiProto\ZiProto;
|
||||||
|
|
||||||
|
class NccCompiler extends \ncc\Classes\NccExtension\NccCompiler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $file_path
|
||||||
|
* @return Component
|
||||||
|
* @throws IOException
|
||||||
|
* @throws PathNotFoundException
|
||||||
|
*/
|
||||||
|
public function buildComponent(string $file_path): Component
|
||||||
|
{
|
||||||
|
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$encoded = json_encode($parser->parse(IO::fread($file_path)), JSON_THROW_ON_ERROR);
|
||||||
|
return new Component(Functions::removeBasename($file_path), ZiProto::encode(json_decode($encoded, true, 512, JSON_THROW_ON_ERROR)), ComponentDataType::AST);
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
Console::outWarning(sprintf('Failed to compile file "%s" with error "%s"', $file_path, $e->getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Component(
|
||||||
|
Functions::removeBasename($file_path),
|
||||||
|
Base64::encode(IO::fread($file_path)), ComponentDataType::BASE64_ENCODED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,488 +0,0 @@
|
||||||
<?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\Classes\PhpExtension;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use FilesystemIterator;
|
|
||||||
use ncc\Enums\ComponentFileExtensions;
|
|
||||||
use ncc\Enums\ComponentDataType;
|
|
||||||
use ncc\Enums\ConstantReferences;
|
|
||||||
use ncc\Enums\DependencySourceType;
|
|
||||||
use ncc\Enums\Options\BuildConfigurationValues;
|
|
||||||
use ncc\Classes\NccExtension\PackageCompiler;
|
|
||||||
use ncc\Exceptions\BuildException;
|
|
||||||
use ncc\Exceptions\ConfigurationException;
|
|
||||||
use ncc\Exceptions\IOException;
|
|
||||||
use ncc\Exceptions\NotSupportedException;
|
|
||||||
use ncc\Exceptions\OperationException;
|
|
||||||
use ncc\Exceptions\PackageException;
|
|
||||||
use ncc\Exceptions\PathNotFoundException;
|
|
||||||
use ncc\Interfaces\CompilerInterface;
|
|
||||||
use ncc\Managers\PackageLockManager;
|
|
||||||
use ncc\Objects\Package;
|
|
||||||
use ncc\Objects\ProjectConfiguration;
|
|
||||||
use ncc\Objects\ProjectConfiguration\Dependency;
|
|
||||||
use ncc\ThirdParty\nikic\PhpParser\ParserFactory;
|
|
||||||
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
|
|
||||||
use ncc\ThirdParty\theseer\DirectoryScanner\DirectoryScanner;
|
|
||||||
use ncc\Utilities\Base64;
|
|
||||||
use ncc\Utilities\Console;
|
|
||||||
use ncc\Utilities\Functions;
|
|
||||||
use ncc\Utilities\IO;
|
|
||||||
use SplFileInfo;
|
|
||||||
|
|
||||||
class PhpCompiler implements CompilerInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var ProjectConfiguration
|
|
||||||
*/
|
|
||||||
private $project_configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Package|null
|
|
||||||
*/
|
|
||||||
private $package;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $path;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ProjectConfiguration $project
|
|
||||||
* @param string $path
|
|
||||||
*/
|
|
||||||
public function __construct(ProjectConfiguration $project, string $path)
|
|
||||||
{
|
|
||||||
$this->project_configuration = $project;
|
|
||||||
$this->path = $path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the PHP package by generating the Autoloader and detecting all components & resources
|
|
||||||
* This function must be called before calling the build function, otherwise the operation will fail
|
|
||||||
*
|
|
||||||
* @param string $build_configuration
|
|
||||||
* @return void
|
|
||||||
* @throws ConfigurationException
|
|
||||||
* @throws OperationException
|
|
||||||
* @throws PackageException
|
|
||||||
*/
|
|
||||||
public function prepare(string $build_configuration=BuildConfigurationValues::DEFAULT): void
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
/** @noinspection PhpRedundantOptionalArgumentInspection */
|
|
||||||
$this->project_configuration->validate(True);
|
|
||||||
}
|
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
throw new PackageException($e->getMessage(), $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select the build configuration
|
|
||||||
$selected_build_configuration = $this->project_configuration->getBuild()->getBuildConfiguration($build_configuration);
|
|
||||||
|
|
||||||
// Create the package object
|
|
||||||
$this->package = new Package();
|
|
||||||
$this->package->setAssembly($this->project_configuration->getAssembly());
|
|
||||||
$this->package->setDependencies($this->project_configuration->getBuild()->getDependencies());
|
|
||||||
$this->package->setMainExecutionPolicy($this->project_configuration->getBuild()->getMain());
|
|
||||||
|
|
||||||
// Add the option to create a symbolic link to the package
|
|
||||||
if(isset($this->project_configuration->getProject()->getOptions()['create_symlink']) && $this->project_configuration->getProject()->getOptions()['create_symlink'] === True)
|
|
||||||
{
|
|
||||||
$this->package->getHeader()->setOption('create_symlink', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add both the defined constants from the build configuration and the global constants.
|
|
||||||
// Global constants are overridden
|
|
||||||
$this->package->getHeader()->setRuntimeConstants(array_merge(
|
|
||||||
$selected_build_configuration->getDefineConstants(),
|
|
||||||
($this->project_configuration->getBuild()->getDefineConstants()),
|
|
||||||
($this->package->getHeader()->getRuntimeConstants() ?? [])
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->package->getHeader()->setCompilerExtension($this->project_configuration->getProject()->getCompiler());
|
|
||||||
$this->package->getHeader()->setCompilerVersion(NCC_VERSION_NUMBER);
|
|
||||||
$this->package->getHeader()->setOptions($this->project_configuration->getProject()->getOptions());
|
|
||||||
|
|
||||||
if($this->project_configuration->getProject()->getUpdateSource() !== null)
|
|
||||||
{
|
|
||||||
$this->package->getHeader()->setUpdateSource($this->project_configuration->getProject()->getUpdateSource());
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::outDebug('scanning project files');
|
|
||||||
Console::outDebug('theseer\DirectoryScanner - Copyright (c) 2009-2014 Arne Blankerts <arne@blankerts.de> All rights reserved.');
|
|
||||||
|
|
||||||
// First scan the project files and create a file struct.
|
|
||||||
$directory_scanner = new DirectoryScanner();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$directory_scanner->unsetFlag(FilesystemIterator::FOLLOW_SYMLINKS);
|
|
||||||
}
|
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
throw new PackageException('Cannot unset flag \'FOLLOW_SYMLINKS\' in DirectoryScanner, ' . $e->getMessage(), $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include file components that can be compiled
|
|
||||||
$directory_scanner->setIncludes(ComponentFileExtensions::PHP);
|
|
||||||
|
|
||||||
if(count($selected_build_configuration->getExcludeFiles()) > 0)
|
|
||||||
{
|
|
||||||
$directory_scanner->setExcludes($selected_build_configuration->getExcludeFiles());
|
|
||||||
}
|
|
||||||
|
|
||||||
$source_path = $this->path . $this->project_configuration->getBuild()->getSourcePath();
|
|
||||||
|
|
||||||
// TODO: Re-implement the scanning process outside the compiler, as this is will be redundant
|
|
||||||
// Scan for components first.
|
|
||||||
if(file_exists($source_path))
|
|
||||||
{
|
|
||||||
Console::outVerbose('Scanning for components... ');
|
|
||||||
/** @var SplFileInfo $item */
|
|
||||||
/** @noinspection PhpRedundantOptionalArgumentInspection */
|
|
||||||
foreach($directory_scanner($source_path, True) as $item)
|
|
||||||
{
|
|
||||||
// Ignore directories, they're not important. :-)
|
|
||||||
if(is_dir($item->getPathName()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$component = new Package\Component();
|
|
||||||
$component->setName(Functions::removeBasename($item->getPathname(), $this->path));
|
|
||||||
$this->package->addComponent($component);
|
|
||||||
|
|
||||||
Console::outVerbose(sprintf('Found component %s', $component->getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($this->package->getComponents()) > 0)
|
|
||||||
{
|
|
||||||
Console::outVerbose(count($this->package->getComponents()) . ' component(s) found');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console::outVerbose('No components found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear previously excludes and includes
|
|
||||||
$directory_scanner->setExcludes();
|
|
||||||
$directory_scanner->setIncludes();
|
|
||||||
|
|
||||||
// Ignore component files
|
|
||||||
if(count($selected_build_configuration->getExcludeFiles()) > 0)
|
|
||||||
{
|
|
||||||
$directory_scanner->setExcludes(array_merge($selected_build_configuration->getExcludeFiles(), ComponentFileExtensions::PHP));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$directory_scanner->setExcludes(ComponentFileExtensions::PHP);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::outVerbose('Scanning for resources... ');
|
|
||||||
/** @var SplFileInfo $item */
|
|
||||||
foreach($directory_scanner($source_path) as $item)
|
|
||||||
{
|
|
||||||
// Ignore directories, they're not important. :-)
|
|
||||||
if(is_dir($item->getPathName()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$resource = new Package\Resource();
|
|
||||||
$resource->setName(Functions::removeBasename($item->getPathname(), $this->path));
|
|
||||||
$this->package->addResource($resource);
|
|
||||||
|
|
||||||
Console::outVerbose(sprintf('found resource %s', $resource->getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($this->package->getResources()) > 0)
|
|
||||||
{
|
|
||||||
Console::outVerbose(count($this->package->getResources()) . ' resources(s) found');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console::outVerbose('No resources found');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console::outWarning('Source path does not exist, skipping resource and component scanning');
|
|
||||||
}
|
|
||||||
|
|
||||||
$selected_dependencies = [];
|
|
||||||
|
|
||||||
if(count($this->project_configuration->getBuild()->getDependencies()) > 0)
|
|
||||||
{
|
|
||||||
$selected_dependencies = array_merge($selected_dependencies, $this->project_configuration->getBuild()->getDependencies());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($selected_build_configuration->getDependencies()) > 0)
|
|
||||||
{
|
|
||||||
$selected_dependencies = array_merge($selected_dependencies, $selected_build_configuration->getDependencies());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the dependencies
|
|
||||||
if(count($selected_dependencies) > 0)
|
|
||||||
{
|
|
||||||
$package_lock_manager = new PackageLockManager();
|
|
||||||
$filesystem = new Filesystem();
|
|
||||||
|
|
||||||
$lib_path = $selected_build_configuration->getOutputPath() . DIRECTORY_SEPARATOR . 'libs';
|
|
||||||
if($filesystem->exists($lib_path))
|
|
||||||
{
|
|
||||||
$filesystem->remove($lib_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::outVerbose('Scanning for dependencies... ');
|
|
||||||
/** @var Dependency $dependency */
|
|
||||||
foreach($selected_dependencies as $dependency)
|
|
||||||
{
|
|
||||||
Console::outVerbose(sprintf('processing dependency %s', $dependency->getName()));
|
|
||||||
switch($dependency->getSourceType())
|
|
||||||
{
|
|
||||||
case DependencySourceType::STATIC:
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$out_path = $lib_path . DIRECTORY_SEPARATOR . sprintf('%s=%s.lib', $dependency->getName(), $dependency->getVersion());
|
|
||||||
|
|
||||||
$package = $package_lock_manager->getPackageLock()?->getPackage($dependency->getName());
|
|
||||||
if($package === null)
|
|
||||||
{
|
|
||||||
throw new IOException('Cannot find package lock for dependency ' . $dependency->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
$version = $package->getVersion($dependency->getVersion());
|
|
||||||
if($version === null)
|
|
||||||
{
|
|
||||||
throw new OperationException('Cannot find version ' . $dependency->getVersion() . ' for dependency ' . $dependency->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::outDebug(sprintf('copying shadow package %s=%s to %s', $dependency->getName(), $dependency->getVersion(), $out_path));
|
|
||||||
|
|
||||||
if(!$filesystem->exists($lib_path))
|
|
||||||
{
|
|
||||||
$filesystem->mkdir($lib_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
$filesystem->copy($version->location, $out_path);
|
|
||||||
$dependency->Source = 'libs' . DIRECTORY_SEPARATOR . sprintf('%s=%s.lib', $dependency->getName(), $dependency->getVersion());
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (IOException $e)
|
|
||||||
{
|
|
||||||
throw new PackageException('Static linking not possible, cannot find package lock for dependency ' . $dependency->getName(), $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case DependencySourceType::REMOTE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->package->addDependency($dependency);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($this->package->getDependencies()) > 0)
|
|
||||||
{
|
|
||||||
Console::outVerbose(count($this->package->getDependencies()) . ' dependency(ies) found');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console::outVerbose('No dependencies found');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the compile process in the correct order and returns the finalized Package object
|
|
||||||
*
|
|
||||||
* @return Package|null
|
|
||||||
* @throws BuildException
|
|
||||||
* @throws IOException
|
|
||||||
* @throws NotSupportedException
|
|
||||||
* @throws PathNotFoundException
|
|
||||||
*/
|
|
||||||
public function build(): ?Package
|
|
||||||
{
|
|
||||||
$this->compileExecutionPolicies();
|
|
||||||
$this->compileComponents();
|
|
||||||
$this->compileResources();
|
|
||||||
|
|
||||||
PackageCompiler::compilePackageConstants($this->package, [
|
|
||||||
ConstantReferences::ASSEMBLY => $this->project_configuration->getAssembly(),
|
|
||||||
ConstantReferences::BUILD => null,
|
|
||||||
ConstantReferences::DATE_TIME => time()
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $this->getPackage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the resources of the package
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @throws BuildException
|
|
||||||
* @throws IOException
|
|
||||||
* @throws PathNotFoundException
|
|
||||||
*/
|
|
||||||
public function compileResources(): void
|
|
||||||
{
|
|
||||||
if($this->package === null)
|
|
||||||
{
|
|
||||||
throw new BuildException('The prepare() method must be called before building the package');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($this->package->getResources()) === 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the resources
|
|
||||||
$total_items = count($this->package->getResources());
|
|
||||||
$processed_items = 1;
|
|
||||||
$resources = [];
|
|
||||||
|
|
||||||
if($total_items > 5)
|
|
||||||
{
|
|
||||||
Console::out('Processing resources');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->package->getResources() as $resource)
|
|
||||||
{
|
|
||||||
/** @noinspection DisconnectedForeachInstructionInspection */
|
|
||||||
if($total_items > 5)
|
|
||||||
{
|
|
||||||
Console::inlineProgressBar($processed_items, $total_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the data and
|
|
||||||
$resource->setData(Base64::encode(IO::fread(Functions::correctDirectorySeparator($this->path . $resource->getName()))));
|
|
||||||
$resource->setName(str_replace($this->project_configuration->getBuild()->getSourcePath(), (string)null, $resource->getName()));
|
|
||||||
$resource->updateChecksum();
|
|
||||||
$resources[] = $resource;
|
|
||||||
|
|
||||||
Console::outDebug(sprintf('processed resource %s', $resource->getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the resources
|
|
||||||
$this->package->setResources($resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the components of the package
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @throws BuildException
|
|
||||||
* @throws IOException
|
|
||||||
* @throws PathNotFoundException
|
|
||||||
*/
|
|
||||||
public function compileComponents(): void
|
|
||||||
{
|
|
||||||
if($this->package === null)
|
|
||||||
{
|
|
||||||
throw new BuildException('The prepare() method must be called before building the package');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($this->package->getComponents()) === 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$total_items = count($this->package->getComponents());
|
|
||||||
$processed_items = 1;
|
|
||||||
$components = [];
|
|
||||||
|
|
||||||
if($total_items > 5)
|
|
||||||
{
|
|
||||||
Console::out('Compiling components');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the components and attempt to create an AST representation of the source
|
|
||||||
foreach($this->package->getComponents() as $component)
|
|
||||||
{
|
|
||||||
if($total_items > 5)
|
|
||||||
{
|
|
||||||
Console::inlineProgressBar($processed_items, $total_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
$content = IO::fread(Functions::correctDirectorySeparator($this->path . $component->getName()));
|
|
||||||
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$stmts = $parser->parse($content);
|
|
||||||
$encoded = json_encode($stmts, JSON_THROW_ON_ERROR);
|
|
||||||
unset($stmts);
|
|
||||||
$component->setDataType(ComponentDataType::AST);
|
|
||||||
$component->setData(json_decode($encoded, true, 512, JSON_THROW_ON_ERROR));
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
$component->setDataType(ComponentDataType::BASE64_ENCODED);
|
|
||||||
$component->setData(Base64::encode($content));
|
|
||||||
unset($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($parser);
|
|
||||||
|
|
||||||
$component->setName(str_replace($this->project_configuration->getBuild()->getSourcePath(), (string)null, $component->getName()));
|
|
||||||
$component->updateChecksum();
|
|
||||||
$components[] = $component;
|
|
||||||
++$processed_items;
|
|
||||||
|
|
||||||
Console::outDebug(sprintf('processed component %s (%s)', $component->getName(), $component->getDataType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the components
|
|
||||||
$this->package->setComponents($components);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
* @throws IOException
|
|
||||||
* @throws NotSupportedException
|
|
||||||
* @throws PathNotFoundException
|
|
||||||
*/
|
|
||||||
public function compileExecutionPolicies(): void
|
|
||||||
{
|
|
||||||
$this->package->setExecutionUnits(PackageCompiler::compileExecutionPolicies($this->path, $this->project_configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getPackage(): ?Package
|
|
||||||
{
|
|
||||||
return $this->package;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -84,7 +84,7 @@
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$component->validate_checksum())
|
if(!$component->validateChecksum())
|
||||||
{
|
{
|
||||||
throw new IntegrityException(sprintf('Checksum validation failed for component: %s', $component->getName()));
|
throw new IntegrityException(sprintf('Checksum validation failed for component: %s', $component->getName()));
|
||||||
}
|
}
|
||||||
|
|
28
src/ncc/Enums/BuildOutputType.php
Normal file
28
src/ncc/Enums/BuildOutputType.php
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ncc\Enums;
|
||||||
|
|
||||||
|
final class BuildOutputType
|
||||||
|
{
|
||||||
|
public const NCC_PACKAGE = 'ncc';
|
||||||
|
}
|
32
src/ncc/Enums/PackageStructure.php
Normal file
32
src/ncc/Enums/PackageStructure.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ncc\Enums;
|
||||||
|
|
||||||
|
final class PackageStructure
|
||||||
|
{
|
||||||
|
public const FILE_VERSION = 0x73746669;
|
||||||
|
|
||||||
|
public const FLAGS = 0x73736166;
|
||||||
|
|
||||||
|
public const DIRECTORY = 0x6f746365;
|
||||||
|
}
|
|
@ -24,9 +24,21 @@ namespace ncc\Enums;
|
||||||
|
|
||||||
final class PackageStructureVersions
|
final class PackageStructureVersions
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* ncc 1.0.0 to 1.0.3
|
||||||
|
*/
|
||||||
public const _1_0 = '1.0';
|
public const _1_0 = '1.0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ncc 1.0.4 and above
|
||||||
|
*/
|
||||||
|
public const _2_0 = '2.0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All supported versions
|
||||||
|
*/
|
||||||
public const ALL = [
|
public const ALL = [
|
||||||
self::_1_0
|
self::_1_0,
|
||||||
|
self::_2_0
|
||||||
];
|
];
|
||||||
}
|
}
|
|
@ -124,7 +124,7 @@
|
||||||
return $package->getAssembly()->getPackage();
|
return $package->getAssembly()->getPackage();
|
||||||
}
|
}
|
||||||
|
|
||||||
$extension = $package->getHeader()->getCompilerExtension()->getExtension();
|
$extension = $package->getMetadata()->getCompilerExtension()->getExtension();
|
||||||
$installation_paths = new InstallationPaths($this->packages_path . DIRECTORY_SEPARATOR . $package->getAssembly()->getPackage() . '=' . $package->getAssembly()->getVersion());
|
$installation_paths = new InstallationPaths($this->packages_path . DIRECTORY_SEPARATOR . $package->getAssembly()->getPackage() . '=' . $package->getAssembly()->getVersion());
|
||||||
|
|
||||||
$installer = match ($extension)
|
$installer = match ($extension)
|
||||||
|
@ -191,7 +191,7 @@
|
||||||
Console::outDebug(sprintf('assembly.%s: %s', $prop, ($value ?? 'n/a')));
|
Console::outDebug(sprintf('assembly.%s: %s', $prop, ($value ?? 'n/a')));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($package->getHeader()->getCompilerExtension()->toArray() as $prop => $value)
|
foreach($package->getMetadata()->getCompilerExtension()->toArray() as $prop => $value)
|
||||||
{
|
{
|
||||||
Console::outDebug(sprintf('header.compiler.%s: %s', $prop, ($value ?? 'n/a')));
|
Console::outDebug(sprintf('header.compiler.%s: %s', $prop, ($value ?? 'n/a')));
|
||||||
}
|
}
|
||||||
|
@ -361,7 +361,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// After execution units are installed, create a symlink if needed
|
// After execution units are installed, create a symlink if needed
|
||||||
if(!is_null($package->getHeader()->getOption('create_symlink')) && $package->getHeader()->getOption('create_symlink'))
|
if(!is_null($package->getMetadata()->getOption('create_symlink')) && $package->getMetadata()->getOption('create_symlink'))
|
||||||
{
|
{
|
||||||
if($package->getMainExecutionPolicy() === null)
|
if($package->getMainExecutionPolicy() === null)
|
||||||
{
|
{
|
||||||
|
@ -415,18 +415,18 @@
|
||||||
Console::outDebug('no post-installation units to execute');
|
Console::outDebug('no post-installation units to execute');
|
||||||
}
|
}
|
||||||
|
|
||||||
if($package->getHeader()->getUpdateSource()?->getRepository() !== null)
|
if($package->getMetadata()->getUpdateSource()?->getRepository() !== null)
|
||||||
{
|
{
|
||||||
$sources_manager = new RemoteSourcesManager();
|
$sources_manager = new RemoteSourcesManager();
|
||||||
if($sources_manager->getRemoteSource($package->getHeader()->getUpdateSource()->getRepository()->getName()) === null)
|
if($sources_manager->getRemoteSource($package->getMetadata()->getUpdateSource()->getRepository()->getName()) === null)
|
||||||
{
|
{
|
||||||
Console::outVerbose('Adding remote source ' . $package->getHeader()->getUpdateSource()->getRepository()->getName());
|
Console::outVerbose('Adding remote source ' . $package->getMetadata()->getUpdateSource()->getRepository()->getName());
|
||||||
|
|
||||||
$defined_remote_source = new DefinedRemoteSource();
|
$defined_remote_source = new DefinedRemoteSource();
|
||||||
$defined_remote_source->setName($package->getHeader()->getUpdateSource()?->getRepository()?->getName());
|
$defined_remote_source->setName($package->getMetadata()->getUpdateSource()?->getRepository()?->getName());
|
||||||
$defined_remote_source->setHost($package->getHeader()->getUpdateSource()?->getRepository()?->getHost());
|
$defined_remote_source->setHost($package->getMetadata()->getUpdateSource()?->getRepository()?->getHost());
|
||||||
$defined_remote_source->setType($package->getHeader()->getUpdateSource()?->getRepository()?->getType());
|
$defined_remote_source->setType($package->getMetadata()->getUpdateSource()?->getRepository()?->getType());
|
||||||
$defined_remote_source->setSsl($package->getHeader()->getUpdateSource()?->getRepository()?->isSsl());
|
$defined_remote_source->setSsl($package->getMetadata()->getUpdateSource()?->getRepository()?->isSsl());
|
||||||
|
|
||||||
$sources_manager->addRemoteSource($defined_remote_source);
|
$sources_manager->addRemoteSource($defined_remote_source);
|
||||||
}
|
}
|
||||||
|
@ -995,8 +995,8 @@
|
||||||
|
|
||||||
$data_files = [
|
$data_files = [
|
||||||
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'assembly' => ZiProto::encode($package->getAssembly()->toArray(true)),
|
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'assembly' => ZiProto::encode($package->getAssembly()->toArray(true)),
|
||||||
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'ext' => ZiProto::encode($package->getHeader()->getCompilerExtension()->toArray()),
|
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'ext' => ZiProto::encode($package->getMetadata()->getCompilerExtension()->toArray()),
|
||||||
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'const' => ZiProto::encode($package->getHeader()->getRuntimeConstants()),
|
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'const' => ZiProto::encode($package->getMetadata()->getRuntimeConstants()),
|
||||||
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'dependencies' => ZiProto::encode($dependencies),
|
$paths->getDataPath() . DIRECTORY_SEPARATOR . 'dependencies' => ZiProto::encode($dependencies),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -25,23 +25,26 @@
|
||||||
|
|
||||||
namespace ncc\Managers;
|
namespace ncc\Managers;
|
||||||
|
|
||||||
use JetBrains\PhpStorm\NoReturn;
|
use ncc\Classes\PhpExtension\NccCompiler;
|
||||||
use ncc\Classes\PhpExtension\PhpCliTemplate;
|
use ncc\Classes\PhpExtension\PhpCliTemplate;
|
||||||
use ncc\Classes\PhpExtension\PhpLibraryTemplate;
|
use ncc\Classes\PhpExtension\PhpLibraryTemplate;
|
||||||
|
use ncc\Enums\BuildOutputType;
|
||||||
|
use ncc\Enums\CompilerExtensions;
|
||||||
|
use ncc\Enums\ComponentFileExtensions;
|
||||||
use ncc\Enums\Options\BuildConfigurationValues;
|
use ncc\Enums\Options\BuildConfigurationValues;
|
||||||
use ncc\Enums\Options\InitializeProjectOptions;
|
use ncc\Enums\Options\InitializeProjectOptions;
|
||||||
use ncc\Classes\NccExtension\PackageCompiler;
|
|
||||||
use ncc\Enums\ProjectTemplates;
|
use ncc\Enums\ProjectTemplates;
|
||||||
use ncc\Exceptions\BuildException;
|
use ncc\Exceptions\BuildException;
|
||||||
use ncc\Exceptions\ConfigurationException;
|
use ncc\Exceptions\ConfigurationException;
|
||||||
use ncc\Exceptions\IOException;
|
use ncc\Exceptions\IOException;
|
||||||
use ncc\Exceptions\NotSupportedException;
|
use ncc\Exceptions\NotSupportedException;
|
||||||
use ncc\Exceptions\PathNotFoundException;
|
use ncc\Exceptions\PathNotFoundException;
|
||||||
|
use ncc\Objects\Package\ExecutionUnit;
|
||||||
use ncc\Objects\ProjectConfiguration;
|
use ncc\Objects\ProjectConfiguration;
|
||||||
use ncc\Objects\ProjectConfiguration\Compiler;
|
use ncc\Objects\ProjectConfiguration\Compiler;
|
||||||
use ncc\Utilities\Console;
|
use ncc\Utilities\Console;
|
||||||
use ncc\Utilities\Functions;
|
use ncc\Utilities\Functions;
|
||||||
use ncc\Utilities\Validate;
|
use ncc\Utilities\IO;
|
||||||
|
|
||||||
class ProjectManager
|
class ProjectManager
|
||||||
{
|
{
|
||||||
|
@ -148,7 +151,16 @@
|
||||||
*/
|
*/
|
||||||
public function build(string $build_configuration=BuildConfigurationValues::DEFAULT): string
|
public function build(string $build_configuration=BuildConfigurationValues::DEFAULT): string
|
||||||
{
|
{
|
||||||
return PackageCompiler::compile($this, $build_configuration);
|
$configuration = $this->project_configuration->getBuild()->getBuildConfiguration($build_configuration);
|
||||||
|
|
||||||
|
return match (strtolower($this->project_configuration->getProject()->getCompiler()->getExtension()))
|
||||||
|
{
|
||||||
|
CompilerExtensions::PHP => match (strtolower($configuration->getBuildType())) {
|
||||||
|
BuildOutputType::NCC_PACKAGE => (new NccCompiler($this))->build($build_configuration),
|
||||||
|
default => throw new BuildException(sprintf('php cannot produce the build type \'%s\'', $configuration->getBuildType())),
|
||||||
|
},
|
||||||
|
default => throw new NotSupportedException(sprintf('The compiler extension \'%s\' is not supported', $this->project_configuration->getProject()->getCompiler()->getExtension())),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,6 +190,124 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of file extensions for the components that are part of this project
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* @throws NotSupportedException
|
||||||
|
*/
|
||||||
|
public function getComponentFileExtensions(): array
|
||||||
|
{
|
||||||
|
return match ($this->getProjectConfiguration()->getProject()->getCompiler()->getExtension())
|
||||||
|
{
|
||||||
|
CompilerExtensions::PHP => ComponentFileExtensions::PHP,
|
||||||
|
default => throw new NotSupportedException(
|
||||||
|
sprintf('The compiler extension \'%s\' is not supported', $this->getProjectConfiguration()->getProject()->getCompiler()->getExtension())
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of ExecutionUnits associated with the project by selecting all required execution units
|
||||||
|
* from the project configuration and reading the contents of the files
|
||||||
|
*
|
||||||
|
* @param string $build_configuration
|
||||||
|
* @return ExecutionUnit[]
|
||||||
|
* @throws ConfigurationException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws PathNotFoundException
|
||||||
|
*/
|
||||||
|
public function getExecutionUnits(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
||||||
|
{
|
||||||
|
$execution_units = [];
|
||||||
|
|
||||||
|
foreach($this->project_configuration->getRequiredExecutionPolicies($build_configuration) as $policy)
|
||||||
|
{
|
||||||
|
$execution_policy = $this->project_configuration->getExecutionPolicy($policy);
|
||||||
|
$execution_file = $this->getProjectPath() . DIRECTORY_SEPARATOR . $execution_policy->getExecute()->getTarget();
|
||||||
|
if(!is_file($execution_file))
|
||||||
|
{
|
||||||
|
throw new IOException(sprintf('The execution policy %s points to a non-existent file \'%s\'', $execution_policy->getName(), $execution_file));
|
||||||
|
}
|
||||||
|
|
||||||
|
$execution_units[] = new ExecutionUnit($execution_policy, IO::fread($execution_file));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $execution_units;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of file paths for the components that are part of this project
|
||||||
|
*
|
||||||
|
* @param string $build_configuration
|
||||||
|
* @return array
|
||||||
|
* @throws ConfigurationException
|
||||||
|
* @throws NotSupportedException
|
||||||
|
*/
|
||||||
|
public function getComponents(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
||||||
|
{
|
||||||
|
$configuration = $this->project_configuration->getBuild()->getBuildConfiguration($build_configuration);
|
||||||
|
|
||||||
|
return array_map(static function ($file) {
|
||||||
|
return $file;
|
||||||
|
}, Functions::scanDirectory($this->getProjectSourcePath(), $this->getComponentFileExtensions(), $configuration->getExcludeFiles()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of file paths for the resources that are part of this project
|
||||||
|
*
|
||||||
|
* @param string $build_configuration
|
||||||
|
* @return array
|
||||||
|
* @throws ConfigurationException
|
||||||
|
* @throws NotSupportedException
|
||||||
|
*/
|
||||||
|
public function getResources(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
||||||
|
{
|
||||||
|
$configuration = $this->project_configuration->getBuild()->getBuildConfiguration($build_configuration);
|
||||||
|
|
||||||
|
return array_map(static function ($file) {
|
||||||
|
return $file;
|
||||||
|
}, Functions::scanDirectory($this->getProjectSourcePath(), [], array_merge(
|
||||||
|
$configuration->getExcludeFiles(), $this->getComponentFileExtensions()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of runtime constants for the project & build configuration
|
||||||
|
*
|
||||||
|
* @param string $build_configuration
|
||||||
|
* @return array
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getRuntimeConstants(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
||||||
|
{
|
||||||
|
$configuration = $this->project_configuration->getBuild()->getBuildConfiguration($build_configuration);
|
||||||
|
|
||||||
|
/** @noinspection ArrayMergeMissUseInspection */
|
||||||
|
return array_merge(
|
||||||
|
$configuration->getDefineConstants(),
|
||||||
|
$this->project_configuration->getBuild()->getDefineConstants()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of compiler options associated with the build configuration
|
||||||
|
*
|
||||||
|
* @param string $build_configuration
|
||||||
|
* @return array
|
||||||
|
* @throws ConfigurationException
|
||||||
|
*/
|
||||||
|
public function getCompilerOptions(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
||||||
|
{
|
||||||
|
$configuration = $this->project_configuration->getBuild()->getBuildConfiguration($build_configuration);
|
||||||
|
|
||||||
|
/** @noinspection ArrayMergeMissUseInspection */
|
||||||
|
return array_merge(
|
||||||
|
$configuration->getOptions(),
|
||||||
|
$this->project_configuration->getBuild()->getOptions()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the project structure
|
* Initializes the project structure
|
||||||
*
|
*
|
||||||
|
|
|
@ -34,11 +34,12 @@
|
||||||
use ncc\Interfaces\BytecodeObjectInterface;
|
use ncc\Interfaces\BytecodeObjectInterface;
|
||||||
use ncc\Objects\Package\Component;
|
use ncc\Objects\Package\Component;
|
||||||
use ncc\Objects\Package\ExecutionUnit;
|
use ncc\Objects\Package\ExecutionUnit;
|
||||||
use ncc\Objects\Package\Header;
|
use ncc\Objects\Package\Metadata;
|
||||||
use ncc\Objects\Package\Installer;
|
use ncc\Objects\Package\Installer;
|
||||||
use ncc\Objects\Package\MagicBytes;
|
use ncc\Objects\Package\MagicBytes;
|
||||||
use ncc\Objects\Package\Resource;
|
use ncc\Objects\Package\Resource;
|
||||||
use ncc\Objects\ProjectConfiguration\Assembly;
|
use ncc\Objects\ProjectConfiguration\Assembly;
|
||||||
|
use ncc\Objects\ProjectConfiguration\Compiler;
|
||||||
use ncc\Objects\ProjectConfiguration\Dependency;
|
use ncc\Objects\ProjectConfiguration\Dependency;
|
||||||
use ncc\Utilities\Functions;
|
use ncc\Utilities\Functions;
|
||||||
use ncc\Utilities\IO;
|
use ncc\Utilities\IO;
|
||||||
|
@ -56,9 +57,9 @@
|
||||||
/**
|
/**
|
||||||
* The true header of the package
|
* The true header of the package
|
||||||
*
|
*
|
||||||
* @var Header
|
* @var Metadata
|
||||||
*/
|
*/
|
||||||
private $header;
|
private $metadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The assembly object of the package
|
* The assembly object of the package
|
||||||
|
@ -74,13 +75,6 @@
|
||||||
*/
|
*/
|
||||||
private $dependencies;
|
private $dependencies;
|
||||||
|
|
||||||
/**
|
|
||||||
* The Main Execution Policy object for the package if the package is an executable package.
|
|
||||||
*
|
|
||||||
* @var string|null
|
|
||||||
*/
|
|
||||||
private $main_execution_policy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The installer object that is used to install the package if the package is install-able
|
* The installer object that is used to install the package if the package is install-able
|
||||||
*
|
*
|
||||||
|
@ -112,11 +106,11 @@
|
||||||
/**
|
/**
|
||||||
* Public Constructor
|
* Public Constructor
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(Assembly $assembly, Compiler $compiler)
|
||||||
{
|
{
|
||||||
$this->magic_bytes = new MagicBytes();
|
$this->magic_bytes = new MagicBytes();
|
||||||
$this->header = new Header();
|
$this->metadata = new Metadata($compiler);
|
||||||
$this->assembly = new Assembly();
|
$this->assembly = $assembly;
|
||||||
$this->execution_units = [];
|
$this->execution_units = [];
|
||||||
$this->components = [];
|
$this->components = [];
|
||||||
$this->dependencies = [];
|
$this->dependencies = [];
|
||||||
|
@ -178,19 +172,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Header
|
* @return Metadata
|
||||||
*/
|
*/
|
||||||
public function getHeader(): Header
|
public function getMetadata(): Metadata
|
||||||
{
|
{
|
||||||
return $this->header;
|
return $this->metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Header $header
|
* @param Metadata $metadata
|
||||||
*/
|
*/
|
||||||
public function setHeader(Header $header): void
|
public function setMetadata(Metadata $metadata): void
|
||||||
{
|
{
|
||||||
$this->header = $header;
|
$this->metadata = $metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -273,6 +267,24 @@
|
||||||
$this->execution_units = $execution_units;
|
$this->execution_units = $execution_units;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ExecutionUnit $unit
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addExecutionUnit(ExecutionUnit $unit): void
|
||||||
|
{
|
||||||
|
foreach($this->execution_units as $exec_unit)
|
||||||
|
{
|
||||||
|
if($exec_unit->getId() === $unit->getId())
|
||||||
|
{
|
||||||
|
$this->removeExecutionUnit($exec_unit->getId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->execution_units[] = $unit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array|Resource[]
|
* @return array|Resource[]
|
||||||
*/
|
*/
|
||||||
|
@ -590,7 +602,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
($bytecode ? Functions::cbc('header') : 'header') => $this?->header?->toArray($bytecode),
|
($bytecode ? Functions::cbc('header') : 'header') => $this?->metadata?->toArray($bytecode),
|
||||||
($bytecode ? Functions::cbc('assembly') : 'assembly') => $this?->assembly?->toArray($bytecode),
|
($bytecode ? Functions::cbc('assembly') : 'assembly') => $this?->assembly?->toArray($bytecode),
|
||||||
($bytecode ? Functions::cbc('dependencies') : 'dependencies') => $_dependencies,
|
($bytecode ? Functions::cbc('dependencies') : 'dependencies') => $_dependencies,
|
||||||
($bytecode ? Functions::cbc('main_execution_policy') : 'main_execution_policy') => $this?->main_execution_policy,
|
($bytecode ? Functions::cbc('main_execution_policy') : 'main_execution_policy') => $this?->main_execution_policy,
|
||||||
|
@ -608,10 +620,10 @@
|
||||||
{
|
{
|
||||||
$object = new self();
|
$object = new self();
|
||||||
|
|
||||||
$object->header = Functions::array_bc($data, 'header');
|
$object->metadata = Functions::array_bc($data, 'header');
|
||||||
if($object->header !== null)
|
if($object->metadata !== null)
|
||||||
{
|
{
|
||||||
$object->header = Header::fromArray($object->header);
|
$object->metadata = Metadata::fromArray($object->metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
$object->assembly = Functions::array_bc($data, 'assembly');
|
$object->assembly = Functions::array_bc($data, 'assembly');
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
namespace ncc\Objects\Package;
|
namespace ncc\Objects\Package;
|
||||||
|
|
||||||
|
use ncc\Enums\ComponentDataType;
|
||||||
|
use ncc\Exceptions\ConfigurationException;
|
||||||
use ncc\Interfaces\BytecodeObjectInterface;
|
use ncc\Interfaces\BytecodeObjectInterface;
|
||||||
use ncc\Utilities\Functions;
|
use ncc\Utilities\Functions;
|
||||||
|
|
||||||
|
@ -61,46 +63,35 @@
|
||||||
/**
|
/**
|
||||||
* The raw data of the component, this is to be processed by the compiler extension
|
* The raw data of the component, this is to be processed by the compiler extension
|
||||||
*
|
*
|
||||||
* @var mixed
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $data;
|
private $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param string $data
|
||||||
|
* @param string $data_type
|
||||||
|
*/
|
||||||
|
public function __construct(string $name, string $data, string $data_type=ComponentDataType::PLAIN)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->flags = [];
|
||||||
|
$this->data_type = $data_type;
|
||||||
|
$this->data = $data;
|
||||||
|
$this->checksum = hash('sha1', $data, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the checksum of the component, returns false if the checksum or data is invalid or if the checksum
|
* Validates the checksum of the component, returns false if the checksum or data is invalid or if the checksum
|
||||||
* failed.
|
* failed.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function validate_checksum(): bool
|
public function validateChecksum(): bool
|
||||||
{
|
{
|
||||||
if($this->checksum === null)
|
|
||||||
{
|
|
||||||
return true; // Return true if the checksum is empty
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->data === null)
|
|
||||||
{
|
|
||||||
return true; // Return true if the data is null
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash_equals($this->checksum, hash('sha1', $this->data, true));
|
return hash_equals($this->checksum, hash('sha1', $this->data, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the checksum of the resource
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function updateChecksum(): void
|
|
||||||
{
|
|
||||||
$this->checksum = null;
|
|
||||||
|
|
||||||
if(is_string($this->data))
|
|
||||||
{
|
|
||||||
$this->checksum = hash('sha1', $this->data, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -148,7 +139,8 @@
|
||||||
*/
|
*/
|
||||||
public function removeFlag(string $flag): void
|
public function removeFlag(string $flag): void
|
||||||
{
|
{
|
||||||
$this->flags = array_filter($this->flags, static function($f) use ($flag) {
|
$this->flags = array_filter($this->flags, static function($f) use ($flag)
|
||||||
|
{
|
||||||
return $f !== $flag;
|
return $f !== $flag;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -161,14 +153,6 @@
|
||||||
return $this->data_type;
|
return $this->data_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $data_type
|
|
||||||
*/
|
|
||||||
public function setDataType(string $data_type): void
|
|
||||||
{
|
|
||||||
$this->data_type = $data_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -178,27 +162,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $checksum
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function setChecksum(string $checksum): void
|
public function getData(): string
|
||||||
{
|
|
||||||
$this->checksum = $checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getData(): mixed
|
|
||||||
{
|
{
|
||||||
return $this->data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $data
|
* @param mixed $data
|
||||||
|
* @param string $data_type
|
||||||
*/
|
*/
|
||||||
public function setData(mixed $data): void
|
public function setData(mixed $data, string $data_type=ComponentDataType::PLAIN): void
|
||||||
{
|
{
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
|
$this->data_type = $data_type;
|
||||||
|
$this->checksum = hash('sha1', $data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -223,16 +202,28 @@
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return Component
|
* @return Component
|
||||||
|
* @throws ConfigurationException
|
||||||
*/
|
*/
|
||||||
public static function fromArray(array $data): Component
|
public static function fromArray(array $data): Component
|
||||||
{
|
{
|
||||||
$object = new self();
|
$name = Functions::array_bc($data, 'name');
|
||||||
|
$component_data = Functions::array_bc($data, 'data');
|
||||||
|
$data_type = Functions::array_bc($data, 'data_type') ?? ComponentDataType::PLAIN;
|
||||||
|
|
||||||
|
if($name === null)
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('The component name is missing');
|
||||||
|
}
|
||||||
|
|
||||||
|
if($component_data === null)
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('The component data is missing');
|
||||||
|
}
|
||||||
|
|
||||||
|
$object = new self($name, $component_data, $data_type);
|
||||||
|
|
||||||
$object->name = Functions::array_bc($data, 'name');
|
|
||||||
$object->flags = Functions::array_bc($data, 'flags');
|
$object->flags = Functions::array_bc($data, 'flags');
|
||||||
$object->data_type = Functions::array_bc($data, 'data_type');
|
|
||||||
$object->checksum = Functions::array_bc($data, 'checksum');
|
$object->checksum = Functions::array_bc($data, 'checksum');
|
||||||
$object->data = Functions::array_bc($data, 'data');
|
|
||||||
|
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,10 @@
|
||||||
|
|
||||||
namespace ncc\Objects\Package;
|
namespace ncc\Objects\Package;
|
||||||
|
|
||||||
|
use ncc\Exceptions\ConfigurationException;
|
||||||
use ncc\Interfaces\BytecodeObjectInterface;
|
use ncc\Interfaces\BytecodeObjectInterface;
|
||||||
use ncc\Objects\ProjectConfiguration\ExecutionPolicy;
|
use ncc\Objects\ProjectConfiguration\ExecutionPolicy;
|
||||||
|
use ncc\Utilities\Base64;
|
||||||
use ncc\Utilities\Functions;
|
use ncc\Utilities\Functions;
|
||||||
|
|
||||||
class ExecutionUnit implements BytecodeObjectInterface
|
class ExecutionUnit implements BytecodeObjectInterface
|
||||||
|
@ -49,16 +51,22 @@
|
||||||
*/
|
*/
|
||||||
private $data;
|
private $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ExecutionPolicy $execution_policy
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
public function __construct(ExecutionPolicy $execution_policy, string $data)
|
||||||
|
{
|
||||||
|
$this->execution_policy = $execution_policy;
|
||||||
|
$this->id = hash('sha1', $this->execution_policy->getName());
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getId(): string
|
public function getId(): string
|
||||||
{
|
{
|
||||||
if($this->id === null)
|
|
||||||
{
|
|
||||||
$this->id = hash('sha1', $this->execution_policy->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,14 +78,6 @@
|
||||||
return $this->execution_policy;
|
return $this->execution_policy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ExecutionPolicy $execution_policy
|
|
||||||
*/
|
|
||||||
public function setExecutionPolicy(ExecutionPolicy $execution_policy): void
|
|
||||||
{
|
|
||||||
$this->execution_policy = $execution_policy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -86,14 +86,6 @@
|
||||||
return $this->data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $data
|
|
||||||
*/
|
|
||||||
public function setData(string $data): void
|
|
||||||
{
|
|
||||||
$this->data = $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
@ -101,7 +93,7 @@
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
($bytecode ? Functions::cbc('execution_policy') : 'execution_policy') => $this->execution_policy->toArray($bytecode),
|
($bytecode ? Functions::cbc('execution_policy') : 'execution_policy') => $this->execution_policy->toArray($bytecode),
|
||||||
($bytecode ? Functions::cbc('data') : 'data') => $this->data,
|
($bytecode ? Functions::cbc('data') : 'data') => Base64::encode($this->data),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,16 +102,19 @@
|
||||||
*/
|
*/
|
||||||
public static function fromArray(array $data): ExecutionUnit
|
public static function fromArray(array $data): ExecutionUnit
|
||||||
{
|
{
|
||||||
$object = new self();
|
$execution_policy = Functions::array_bc($data, 'execution_policy');
|
||||||
|
$execution_data = Functions::array_bc($data, 'data');
|
||||||
|
|
||||||
$object->execution_policy = Functions::array_bc($data, 'execution_policy');
|
if($execution_policy === null)
|
||||||
$object->data = Functions::array_bc($data, 'data');
|
|
||||||
|
|
||||||
if($object->execution_policy !== null)
|
|
||||||
{
|
{
|
||||||
$object->execution_policy = ExecutionPolicy::fromArray($object->execution_policy);
|
throw new ConfigurationException('Missing execution policy for execution unit');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $object;
|
if($execution_data === null)
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('Missing execution data for execution unit');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new self(ExecutionPolicy::fromArray($execution_policy), Base64::decode($execution_data));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,210 +0,0 @@
|
||||||
<?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\Package;
|
|
||||||
|
|
||||||
use ncc\Interfaces\BytecodeObjectInterface;
|
|
||||||
use ncc\Utilities\Functions;
|
|
||||||
|
|
||||||
class Installer implements BytecodeObjectInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* An array of execution policies to execute pre install
|
|
||||||
*
|
|
||||||
* @var string[]|null
|
|
||||||
*/
|
|
||||||
private $pre_install;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An array of execution policies to execute post install
|
|
||||||
*
|
|
||||||
* @var string[]|null
|
|
||||||
*/
|
|
||||||
private $post_install;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An array of execution policies to execute pre uninstall
|
|
||||||
*
|
|
||||||
* @var string[]|null
|
|
||||||
*/
|
|
||||||
private $pre_uninstall;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An array of execution policies to execute post uninstall
|
|
||||||
*
|
|
||||||
* @var string[]|null
|
|
||||||
*/
|
|
||||||
private $post_uninstall;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An array of execution policies to execute pre update
|
|
||||||
*
|
|
||||||
* @var string[]|null
|
|
||||||
*/
|
|
||||||
private $pre_update;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An array of execution policies to execute post update
|
|
||||||
*
|
|
||||||
* @var string[]|null
|
|
||||||
*/
|
|
||||||
private $post_update;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]|null
|
|
||||||
*/
|
|
||||||
public function getPreInstall(): ?array
|
|
||||||
{
|
|
||||||
return $this->pre_install;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[]|null $pre_install
|
|
||||||
*/
|
|
||||||
public function setPreInstall(?array $pre_install): void
|
|
||||||
{
|
|
||||||
$this->pre_install = $pre_install;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]|null
|
|
||||||
*/
|
|
||||||
public function getPostInstall(): ?array
|
|
||||||
{
|
|
||||||
return $this->post_install;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[]|null $post_install
|
|
||||||
*/
|
|
||||||
public function setPostInstall(?array $post_install): void
|
|
||||||
{
|
|
||||||
$this->post_install = $post_install;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]|null
|
|
||||||
*/
|
|
||||||
public function getPreUninstall(): ?array
|
|
||||||
{
|
|
||||||
return $this->pre_uninstall;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[]|null $pre_uninstall
|
|
||||||
*/
|
|
||||||
public function setPreUninstall(?array $pre_uninstall): void
|
|
||||||
{
|
|
||||||
$this->pre_uninstall = $pre_uninstall;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]|null
|
|
||||||
*/
|
|
||||||
public function getPostUninstall(): ?array
|
|
||||||
{
|
|
||||||
return $this->post_uninstall;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[]|null $post_uninstall
|
|
||||||
*/
|
|
||||||
public function setPostUninstall(?array $post_uninstall): void
|
|
||||||
{
|
|
||||||
$this->post_uninstall = $post_uninstall;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]|null
|
|
||||||
*/
|
|
||||||
public function getPreUpdate(): ?array
|
|
||||||
{
|
|
||||||
return $this->pre_update;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[]|null $pre_update
|
|
||||||
*/
|
|
||||||
public function setPreUpdate(?array $pre_update): void
|
|
||||||
{
|
|
||||||
$this->pre_update = $pre_update;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string[]|null
|
|
||||||
*/
|
|
||||||
public function getPostUpdate(): ?array
|
|
||||||
{
|
|
||||||
return $this->post_update;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[]|null $post_update
|
|
||||||
*/
|
|
||||||
public function setPostUpdate(?array $post_update): void
|
|
||||||
{
|
|
||||||
$this->post_update = $post_update;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function toArray(bool $bytecode=false): array
|
|
||||||
{
|
|
||||||
if(
|
|
||||||
$this->pre_install === null && $this->post_install === null &&
|
|
||||||
$this->pre_uninstall === null && $this->post_uninstall === null &&
|
|
||||||
$this->pre_update === null && $this->post_update === null
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
($bytecode ? Functions::cbc('pre_install') : 'pre_install') => $this->pre_install,
|
|
||||||
($bytecode ? Functions::cbc('post_install') : 'post_install') => $this->post_install,
|
|
||||||
($bytecode ? Functions::cbc('pre_uninstall') : 'pre_uninstall') => $this->pre_uninstall,
|
|
||||||
($bytecode? Functions::cbc('post_uninstall') : 'post_uninstall') => $this->post_uninstall,
|
|
||||||
($bytecode? Functions::cbc('pre_update') : 'pre_update') => $this->pre_update,
|
|
||||||
($bytecode? Functions::cbc('post_update') : 'post_update') => $this->post_update
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public static function fromArray(array $data): Installer
|
|
||||||
{
|
|
||||||
$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');
|
|
||||||
|
|
||||||
return $object;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,12 +24,13 @@
|
||||||
|
|
||||||
namespace ncc\Objects\Package;
|
namespace ncc\Objects\Package;
|
||||||
|
|
||||||
|
use ncc\Exceptions\ConfigurationException;
|
||||||
use ncc\Interfaces\BytecodeObjectInterface;
|
use ncc\Interfaces\BytecodeObjectInterface;
|
||||||
use ncc\Objects\ProjectConfiguration\Compiler;
|
use ncc\Objects\ProjectConfiguration\Compiler;
|
||||||
use ncc\Objects\ProjectConfiguration\UpdateSource;
|
use ncc\Objects\ProjectConfiguration\UpdateSource;
|
||||||
use ncc\Utilities\Functions;
|
use ncc\Utilities\Functions;
|
||||||
|
|
||||||
class Header implements BytecodeObjectInterface
|
class Metadata implements BytecodeObjectInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The compiler extension information that was used to build the package
|
* The compiler extension information that was used to build the package
|
||||||
|
@ -66,12 +67,23 @@
|
||||||
*/
|
*/
|
||||||
private $update_source;
|
private $update_source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
private $main_execution_policy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Installer|null
|
||||||
|
*/
|
||||||
|
private $installer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public Constructor
|
* Public Constructor
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct(Compiler $compiler)
|
||||||
{
|
{
|
||||||
$this->compiler_extension = new Compiler();
|
$this->compiler_extension = $compiler;
|
||||||
|
$this->compiler_version = NCC_VERSION_NUMBER;
|
||||||
$this->runtime_constants = [];
|
$this->runtime_constants = [];
|
||||||
$this->options = [];
|
$this->options = [];
|
||||||
}
|
}
|
||||||
|
@ -184,6 +196,38 @@
|
||||||
$this->update_source = $update_source;
|
$this->update_source = $update_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getMainExecutionPolicy(): ?string
|
||||||
|
{
|
||||||
|
return $this->main_execution_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $main_execution_policy
|
||||||
|
*/
|
||||||
|
public function setMainExecutionPolicy(?string $main_execution_policy): void
|
||||||
|
{
|
||||||
|
$this->main_execution_policy = $main_execution_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Installer|null
|
||||||
|
*/
|
||||||
|
public function getInstaller(): ?Installer
|
||||||
|
{
|
||||||
|
return $this->installer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Installer|null $installer
|
||||||
|
*/
|
||||||
|
public function setInstaller(?Installer $installer): void
|
||||||
|
{
|
||||||
|
$this->installer = $installer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
@ -201,21 +245,21 @@
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
public static function fromArray(array $data): Header
|
public static function fromArray(array $data): Metadata
|
||||||
{
|
{
|
||||||
$object = new self();
|
$compiler_extension = Functions::array_bc($data, 'compiler_extension');
|
||||||
|
if($compiler_extension === null)
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('The compiler extension information is not specified in the package header');
|
||||||
|
}
|
||||||
|
|
||||||
|
$object = new self(Compiler::fromArray($compiler_extension));
|
||||||
|
|
||||||
$object->compiler_extension = Functions::array_bc($data, 'compiler_extension');
|
|
||||||
$object->runtime_constants = Functions::array_bc($data, 'runtime_constants');
|
$object->runtime_constants = Functions::array_bc($data, 'runtime_constants');
|
||||||
$object->compiler_version = Functions::array_bc($data, 'compiler_version');
|
$object->compiler_version = Functions::array_bc($data, 'compiler_version');
|
||||||
$object->update_source = Functions::array_bc($data, 'update_source');
|
$object->update_source = Functions::array_bc($data, 'update_source');
|
||||||
$object->options = Functions::array_bc($data, 'options');
|
$object->options = Functions::array_bc($data, 'options');
|
||||||
|
|
||||||
if($object->compiler_extension !== null)
|
|
||||||
{
|
|
||||||
$object->compiler_extension = Compiler::fromArray($object->compiler_extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($object->update_source !== null)
|
if($object->update_source !== null)
|
||||||
{
|
{
|
||||||
$object->update_source = UpdateSource::fromArray($object->update_source);
|
$object->update_source = UpdateSource::fromArray($object->update_source);
|
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
namespace ncc\Objects\Package;
|
namespace ncc\Objects\Package;
|
||||||
|
|
||||||
|
use ncc\Exceptions\ConfigurationException;
|
||||||
use ncc\Interfaces\BytecodeObjectInterface;
|
use ncc\Interfaces\BytecodeObjectInterface;
|
||||||
|
use ncc\Utilities\Base64;
|
||||||
use ncc\Utilities\Functions;
|
use ncc\Utilities\Functions;
|
||||||
|
|
||||||
class Resource implements BytecodeObjectInterface
|
class Resource implements BytecodeObjectInterface
|
||||||
|
@ -51,6 +53,13 @@
|
||||||
*/
|
*/
|
||||||
private $data;
|
private $data;
|
||||||
|
|
||||||
|
public function __construct(string $name, mixed $data)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->data = $data;
|
||||||
|
$this->checksum = hash('sha1', $this->data, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the checksum of the resource, returns false if the checksum or data is invalid or if the checksum
|
* Validates the checksum of the resource, returns false if the checksum or data is invalid or if the checksum
|
||||||
* failed.
|
* failed.
|
||||||
|
@ -59,34 +68,9 @@
|
||||||
*/
|
*/
|
||||||
public function validateChecksum(): bool
|
public function validateChecksum(): bool
|
||||||
{
|
{
|
||||||
if($this->checksum === null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->data === null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash_equals($this->checksum, hash('sha1', $this->data, true));
|
return hash_equals($this->checksum, hash('sha1', $this->data, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the checksum of the resource
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function updateChecksum(): void
|
|
||||||
{
|
|
||||||
$this->checksum = null;
|
|
||||||
|
|
||||||
if(is_string($this->data))
|
|
||||||
{
|
|
||||||
$this->checksum = hash('sha1', $this->data, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -111,14 +95,6 @@
|
||||||
return $this->checksum;
|
return $this->checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $checksum
|
|
||||||
*/
|
|
||||||
public function setChecksum(string $checksum): void
|
|
||||||
{
|
|
||||||
$this->checksum = $checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -132,7 +108,8 @@
|
||||||
*/
|
*/
|
||||||
public function setData(string $data): void
|
public function setData(string $data): void
|
||||||
{
|
{
|
||||||
$this->data = $data;
|
$this->data = Base64::encode($data);
|
||||||
|
$this->checksum = hash('sha1', $this->data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,14 +126,25 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
|
* @throws ConfigurationException
|
||||||
*/
|
*/
|
||||||
public static function fromArray(array $data): self
|
public static function fromArray(array $data): self
|
||||||
{
|
{
|
||||||
$object = new self();
|
$name = Functions::array_bc($data, 'name');
|
||||||
|
$resource_data = Functions::array_bc($data, 'data');
|
||||||
|
|
||||||
$object->name = Functions::array_bc($data, 'name');
|
if($name === null)
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('Resource name is not defined');
|
||||||
|
}
|
||||||
|
|
||||||
|
if($resource_data === null)
|
||||||
|
{
|
||||||
|
throw new ConfigurationException('Resource data is not defined');
|
||||||
|
}
|
||||||
|
|
||||||
|
$object = new self($name, $resource_data);
|
||||||
$object->checksum = Functions::array_bc($data, 'checksum');
|
$object->checksum = Functions::array_bc($data, 'checksum');
|
||||||
$object->data = Functions::array_bc($data, 'data');
|
|
||||||
|
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,14 +90,14 @@
|
||||||
$package_entry = new PackageEntry();
|
$package_entry = new PackageEntry();
|
||||||
$package_entry->addVersion($package, $install_path, true);
|
$package_entry->addVersion($package, $install_path, true);
|
||||||
$package_entry->setName($package->getAssembly()->getPackage());
|
$package_entry->setName($package->getAssembly()->getPackage());
|
||||||
$package_entry->setUpdateSource($package->getHeader()->getUpdateSource());
|
$package_entry->setUpdateSource($package->getMetadata()->getUpdateSource());
|
||||||
$this->packages[$package->getAssembly()->getPackage()] = $package_entry;
|
$this->packages[$package->getAssembly()->getPackage()] = $package_entry;
|
||||||
$this->update();
|
$this->update();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->packages[$package->getAssembly()->getPackage()]->setUpdateSource($package->getHeader()->getUpdateSource());
|
$this->packages[$package->getAssembly()->getPackage()]->setUpdateSource($package->getMetadata()->getUpdateSource());
|
||||||
$this->packages[$package->getAssembly()->getPackage()]->addVersion($package, $install_path, true);
|
$this->packages[$package->getAssembly()->getPackage()]->addVersion($package, $install_path, true);
|
||||||
$this->update();
|
$this->update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@
|
||||||
|
|
||||||
$version = new VersionEntry();
|
$version = new VersionEntry();
|
||||||
$version->setVersion($package->getAssembly()->getVersion());
|
$version->setVersion($package->getAssembly()->getVersion());
|
||||||
$version->setCompiler($package->getHeader()->getCompilerExtension());
|
$version->setCompiler($package->getMetadata()->getCompilerExtension());
|
||||||
$version->setExecutionUnits($package->getExecutionUnits());
|
$version->setExecutionUnits($package->getExecutionUnits());
|
||||||
$version->main_execution_policy = $package->getMainExecutionPolicy();
|
$version->main_execution_policy = $package->getMainExecutionPolicy();
|
||||||
$version->location = $install_path;
|
$version->location = $install_path;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
namespace ncc\Objects;
|
namespace ncc\Objects;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use InvalidArgumentException;
|
||||||
use ncc\Enums\Options\BuildConfigurationValues;
|
use ncc\Enums\Options\BuildConfigurationValues;
|
||||||
use ncc\Exceptions\ConfigurationException;
|
use ncc\Exceptions\ConfigurationException;
|
||||||
use ncc\Exceptions\IOException;
|
use ncc\Exceptions\IOException;
|
||||||
|
@ -142,9 +143,9 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @return ExecutionPolicy|null
|
* @return ExecutionPolicy
|
||||||
*/
|
*/
|
||||||
private function getExecutionPolicy(string $name): ?ExecutionPolicy
|
public function getExecutionPolicy(string $name): ExecutionPolicy
|
||||||
{
|
{
|
||||||
foreach($this->execution_policies as $executionPolicy)
|
foreach($this->execution_policies as $executionPolicy)
|
||||||
{
|
{
|
||||||
|
@ -154,7 +155,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
throw new InvalidArgumentException('Execution policy \'' . $name . '\' does not exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,12 +204,12 @@
|
||||||
* Runs a check on the project configuration and determines what policies are required
|
* Runs a check on the project configuration and determines what policies are required
|
||||||
*
|
*
|
||||||
* @param string $build_configuration
|
* @param string $build_configuration
|
||||||
* @return array
|
* @return string[]
|
||||||
* @throws ConfigurationException
|
* @throws ConfigurationException
|
||||||
*/
|
*/
|
||||||
public function getRequiredExecutionPolicies(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
public function getRequiredExecutionPolicies(string $build_configuration=BuildConfigurationValues::DEFAULT): array
|
||||||
{
|
{
|
||||||
if($this->execution_policies === null || count($this->execution_policies) === 0)
|
if(count($this->execution_policies) === 0)
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -220,7 +221,6 @@
|
||||||
foreach($this->execution_policies as $execution_policy)
|
foreach($this->execution_policies as $execution_policy)
|
||||||
{
|
{
|
||||||
$defined_polices[] = $execution_policy->getName();
|
$defined_polices[] = $execution_policy->getName();
|
||||||
//$execution_policy->validate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the installer by batch
|
// Check the installer by batch
|
||||||
|
@ -249,57 +249,50 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(count($this->build->getPostBuild()) > 0)
|
foreach($this->build->getPostBuild() as $unit)
|
||||||
{
|
{
|
||||||
foreach($this->build->getPostBuild() as $unit)
|
if(!in_array($unit, $defined_polices, true))
|
||||||
{
|
{
|
||||||
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 . '\'');
|
||||||
{
|
}
|
||||||
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))
|
if(!in_array($unit, $required_policies, true))
|
||||||
{
|
{
|
||||||
$required_policies[] = $unit;
|
$required_policies[] = $unit;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(count($this->build->getPreBuild()) > 0)
|
foreach($this->build->getPreBuild() as $unit)
|
||||||
{
|
{
|
||||||
foreach($this->build->getPreBuild() as $unit)
|
if(!in_array($unit, $defined_polices, true))
|
||||||
{
|
{
|
||||||
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 . '\'');
|
||||||
{
|
}
|
||||||
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))
|
if(!in_array($unit, $required_policies, true))
|
||||||
{
|
{
|
||||||
$required_policies[] = $unit;
|
$required_policies[] = $unit;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @noinspection DegradedSwitchInspection */
|
if($this->build->getMain() !== null)
|
||||||
switch($build_configuration)
|
|
||||||
{
|
{
|
||||||
case BuildConfigurationValues::ALL:
|
if(!in_array($this->build->getMain(), $defined_polices, true))
|
||||||
/** @var BuildConfiguration $configuration */
|
{
|
||||||
foreach($this->build->getBuildConfigurations() as $configuration)
|
throw new ConfigurationException('The property \'build.main\' in the project configuration calls for an undefined execution policy \'' . $this->build->getMain() . '\'');
|
||||||
{
|
}
|
||||||
foreach($this->processBuildPolicies($configuration, $defined_polices) as $policy)
|
|
||||||
{
|
|
||||||
if(!in_array($policy, $required_policies, true))
|
|
||||||
{
|
|
||||||
$required_policies[] = $policy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if(!in_array($this->build->getMain(), $required_policies, true))
|
||||||
$configuration = $this->build->getBuildConfiguration($build_configuration);
|
{
|
||||||
|
$required_policies[] = $this->build->getMain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($build_configuration === BuildConfigurationValues::ALL)
|
||||||
|
{
|
||||||
|
/** @var BuildConfiguration $configuration */
|
||||||
|
foreach($this->build->getBuildConfigurations() as $configuration)
|
||||||
|
{
|
||||||
foreach($this->processBuildPolicies($configuration, $defined_polices) as $policy)
|
foreach($this->processBuildPolicies($configuration, $defined_polices) as $policy)
|
||||||
{
|
{
|
||||||
if(!in_array($policy, $required_policies, true))
|
if(!in_array($policy, $required_policies, true))
|
||||||
|
@ -307,52 +300,62 @@
|
||||||
$required_policies[] = $policy;
|
$required_policies[] = $policy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$configuration = $this->build->getBuildConfiguration($build_configuration);
|
||||||
|
foreach($this->processBuildPolicies($configuration, $defined_polices) as $policy)
|
||||||
|
{
|
||||||
|
if(!in_array($policy, $required_policies, true))
|
||||||
|
{
|
||||||
|
$required_policies[] = $policy;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($required_policies as $policy)
|
foreach($required_policies as $policy)
|
||||||
{
|
{
|
||||||
$execution_policy = $this->getExecutionPolicy($policy);
|
$execution_policy = $this->getExecutionPolicy($policy);
|
||||||
|
|
||||||
if($execution_policy?->getExitHandlers()->getSuccess()?->getRun() !== null)
|
if($execution_policy?->getExitHandlers()?->getSuccess()?->getRun() !== null)
|
||||||
{
|
{
|
||||||
if(!in_array($execution_policy?->getExitHandlers()->getSuccess()?->getRun(), $defined_polices, true))
|
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() . '\'');
|
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))
|
if(!in_array($execution_policy?->getExitHandlers()?->getSuccess()?->getRun(), $required_policies, true))
|
||||||
{
|
{
|
||||||
$required_policies[] = $execution_policy?->getExitHandlers()->getSuccess()?->getRun();
|
$required_policies[] = $execution_policy?->getExitHandlers()?->getSuccess()?->getRun();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($execution_policy?->getExitHandlers()->getWarning()?->getRun() !== null)
|
if($execution_policy?->getExitHandlers()?->getWarning()?->getRun() !== null)
|
||||||
{
|
{
|
||||||
if(!in_array($execution_policy?->getExitHandlers()->getWarning()?->getRun(), $defined_polices, true))
|
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() . '\'');
|
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))
|
if(!in_array($execution_policy?->getExitHandlers()?->getWarning()?->getRun(), $required_policies, true))
|
||||||
{
|
{
|
||||||
$required_policies[] = $execution_policy?->getExitHandlers()->getWarning()?->getRun();
|
$required_policies[] = $execution_policy?->getExitHandlers()?->getWarning()?->getRun();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($execution_policy?->getExitHandlers()->getError()?->getRun() !== null)
|
if($execution_policy?->getExitHandlers()?->getError()?->getRun() !== null)
|
||||||
{
|
{
|
||||||
if(!in_array($execution_policy?->getExitHandlers()->getError()?->getRun(), $defined_polices, true))
|
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() . '\'');
|
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))
|
if(!in_array($execution_policy?->getExitHandlers()?->getError()?->getRun(), $required_policies, true))
|
||||||
{
|
{
|
||||||
$required_policies[] = $execution_policy?->getExitHandlers()->getError()?->getRun();
|
$required_policies[] = $execution_policy?->getExitHandlers()?->getError()?->getRun();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $required_policies;
|
return $required_policies;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
namespace ncc\Objects\ProjectConfiguration\Build;
|
namespace ncc\Objects\ProjectConfiguration\Build;
|
||||||
|
|
||||||
|
use ncc\Enums\BuildOutputType;
|
||||||
use ncc\Exceptions\ConfigurationException;
|
use ncc\Exceptions\ConfigurationException;
|
||||||
use ncc\Interfaces\BytecodeObjectInterface;
|
use ncc\Interfaces\BytecodeObjectInterface;
|
||||||
use ncc\Objects\ProjectConfiguration\Dependency;
|
use ncc\Objects\ProjectConfiguration\Dependency;
|
||||||
|
@ -43,6 +44,11 @@
|
||||||
*/
|
*/
|
||||||
private $name;
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $build_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options to pass onto the extension compiler
|
* Options to pass onto the extension compiler
|
||||||
*
|
*
|
||||||
|
@ -99,6 +105,7 @@
|
||||||
public function __construct(string $name, string $output_path)
|
public function __construct(string $name, string $output_path)
|
||||||
{
|
{
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
$this->build_type = BuildOutputType::NCC_PACKAGE;
|
||||||
$this->output_path = $output_path;
|
$this->output_path = $output_path;
|
||||||
$this->options = [];
|
$this->options = [];
|
||||||
$this->define_constants = [];
|
$this->define_constants = [];
|
||||||
|
@ -177,6 +184,22 @@
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBuildType(): string
|
||||||
|
{
|
||||||
|
return $this->build_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $build_type
|
||||||
|
*/
|
||||||
|
public function setBuildType(string $build_type): void
|
||||||
|
{
|
||||||
|
$this->build_type = $build_type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -370,6 +393,7 @@
|
||||||
$results = [];
|
$results = [];
|
||||||
|
|
||||||
$results[($bytecode ? Functions::cbc('name') : 'name')] = $this->name;
|
$results[($bytecode ? Functions::cbc('name') : 'name')] = $this->name;
|
||||||
|
$results[($bytecode ? Functions::cbc('build_type') : 'build_type')] = $this->build_type;
|
||||||
$results[($bytecode ? Functions::cbc('output_path') : 'output_path')] = $this->output_path;
|
$results[($bytecode ? Functions::cbc('output_path') : 'output_path')] = $this->output_path;
|
||||||
|
|
||||||
if(count($this->options) > 0)
|
if(count($this->options) > 0)
|
||||||
|
@ -412,6 +436,7 @@
|
||||||
public static function fromArray(array $data): BuildConfiguration
|
public static function fromArray(array $data): BuildConfiguration
|
||||||
{
|
{
|
||||||
$name = Functions::array_bc($data, 'name');
|
$name = Functions::array_bc($data, 'name');
|
||||||
|
$build_type = Functions::array_bc($data, 'build_type');
|
||||||
$output_path = Functions::array_bc($data, 'output_path');
|
$output_path = Functions::array_bc($data, 'output_path');
|
||||||
|
|
||||||
if($name === null)
|
if($name === null)
|
||||||
|
|
|
@ -146,17 +146,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ExitHandlers
|
* @return ?ExitHandlers
|
||||||
*/
|
*/
|
||||||
public function getExitHandlers(): ExitHandlers
|
public function getExitHandlers(): ?ExitHandlers
|
||||||
{
|
{
|
||||||
return $this->exit_handlers;
|
return $this->exit_handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ExitHandlers $exit_handlers
|
* @param ExitHandlers|null $exit_handlers
|
||||||
*/
|
*/
|
||||||
public function setExitHandlers(ExitHandlers $exit_handlers): void
|
public function setExitHandlers(?ExitHandlers $exit_handlers): void
|
||||||
{
|
{
|
||||||
$this->exit_handlers = $exit_handlers;
|
$this->exit_handlers = $exit_handlers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
namespace ncc\Utilities;
|
namespace ncc\Utilities;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use FilesystemIterator;
|
||||||
use JsonException;
|
use JsonException;
|
||||||
use ncc\Enums\AuthenticationType;
|
use ncc\Enums\AuthenticationType;
|
||||||
use ncc\Enums\DefinedRemoteSourceType;
|
use ncc\Enums\DefinedRemoteSourceType;
|
||||||
|
@ -63,6 +64,7 @@
|
||||||
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
|
use ncc\ThirdParty\Symfony\Filesystem\Filesystem;
|
||||||
use ncc\ThirdParty\Symfony\Process\ExecutableFinder;
|
use ncc\ThirdParty\Symfony\Process\ExecutableFinder;
|
||||||
use ncc\ThirdParty\Symfony\Process\Process;
|
use ncc\ThirdParty\Symfony\Process\Process;
|
||||||
|
use ncc\ThirdParty\theseer\DirectoryScanner\DirectoryScanner;
|
||||||
use RecursiveDirectoryIterator;
|
use RecursiveDirectoryIterator;
|
||||||
use RecursiveIteratorIterator;
|
use RecursiveIteratorIterator;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
@ -242,8 +244,7 @@
|
||||||
$banner_version = str_pad($version, 21);
|
$banner_version = str_pad($version, 21);
|
||||||
$banner_copyright = str_pad($copyright, 30);
|
$banner_copyright = str_pad($copyright, 30);
|
||||||
|
|
||||||
$banner = str_ireplace('%A', $banner_version, $banner);
|
return str_ireplace(array('%A', '%B'), array($banner_version, $banner_copyright), $banner);
|
||||||
return str_ireplace('%B', $banner_copyright, $banner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,7 +264,7 @@
|
||||||
|
|
||||||
// Append the trailing slash if it's not already there
|
// Append the trailing slash if it's not already there
|
||||||
// "/etc/foo" becomes "/etc/foo/"
|
// "/etc/foo" becomes "/etc/foo/"
|
||||||
if(substr($base_name, -1) !== DIRECTORY_SEPARATOR)
|
if(!str_ends_with($base_name, DIRECTORY_SEPARATOR))
|
||||||
{
|
{
|
||||||
$base_name .= DIRECTORY_SEPARATOR;
|
$base_name .= DIRECTORY_SEPARATOR;
|
||||||
}
|
}
|
||||||
|
@ -280,8 +281,7 @@
|
||||||
*/
|
*/
|
||||||
public static function correctDirectorySeparator($path): string
|
public static function correctDirectorySeparator($path): string
|
||||||
{
|
{
|
||||||
$path = str_ireplace('/', DIRECTORY_SEPARATOR, $path);
|
return str_ireplace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
|
||||||
return str_ireplace('\\', DIRECTORY_SEPARATOR, $path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -805,9 +805,9 @@
|
||||||
// If the specified version is a release, download the source code
|
// If the specified version is a release, download the source code
|
||||||
if($release_results !== null)
|
if($release_results !== null)
|
||||||
{
|
{
|
||||||
$results->setReleaseName($release_results->getReleaseName() ?? null);
|
$results->setReleaseName($release_results->getReleaseName());
|
||||||
$results->setReleaseDescription($release_results->getReleaseDescription() ?? null);
|
$results->setReleaseDescription($release_results->getReleaseDescription());
|
||||||
$results->setFiles(self::mergeFilesResults($release_results->getFiles(), ($results->getFiles() ?? null)));
|
$results->setFiles(self::mergeFilesResults($release_results->getFiles(), ($results->getFiles())));
|
||||||
|
|
||||||
if($release_results->getVersion() !== null)
|
if($release_results->getVersion() !== null)
|
||||||
{
|
{
|
||||||
|
@ -829,7 +829,7 @@
|
||||||
{
|
{
|
||||||
if($results->getReleaseName() === null)
|
if($results->getReleaseName() === null)
|
||||||
{
|
{
|
||||||
$results->setReleaseName($git_results->getReleaseName() ?? null);
|
$results->setReleaseName($git_results->getReleaseName());
|
||||||
}
|
}
|
||||||
elseif($git_results->getReleaseName() !== null)
|
elseif($git_results->getReleaseName() !== null)
|
||||||
{
|
{
|
||||||
|
@ -841,7 +841,7 @@
|
||||||
|
|
||||||
if($results->getReleaseDescription() === null)
|
if($results->getReleaseDescription() === null)
|
||||||
{
|
{
|
||||||
$results->setReleaseDescription($git_results->getReleaseDescription() ?? null);
|
$results->setReleaseDescription($git_results->getReleaseDescription());
|
||||||
}
|
}
|
||||||
elseif($git_results->getReleaseDescription() !== null)
|
elseif($git_results->getReleaseDescription() !== null)
|
||||||
{
|
{
|
||||||
|
@ -853,7 +853,7 @@
|
||||||
|
|
||||||
if($results->getVersion() === null)
|
if($results->getVersion() === null)
|
||||||
{
|
{
|
||||||
$results->setVersion($git_results->getVersion() ?? null);
|
$results->setVersion($git_results->getVersion());
|
||||||
}
|
}
|
||||||
elseif($git_results->getVersion() !== null)
|
elseif($git_results->getVersion() !== null)
|
||||||
{
|
{
|
||||||
|
@ -864,7 +864,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$results->setFiles(self::mergeFilesResults($git_results->getFiles(), ($results->getFiles() ?? null)));
|
$results->setFiles(self::mergeFilesResults($git_results->getFiles(), ($results->getFiles())));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -881,7 +881,7 @@
|
||||||
{
|
{
|
||||||
if($results->getReleaseName() === null)
|
if($results->getReleaseName() === null)
|
||||||
{
|
{
|
||||||
$results->setReleaseName($ncc_package_results->getReleaseName() ?? null);
|
$results->setReleaseName($ncc_package_results->getReleaseName());
|
||||||
}
|
}
|
||||||
elseif($ncc_package_results->getReleaseName() !== null)
|
elseif($ncc_package_results->getReleaseName() !== null)
|
||||||
{
|
{
|
||||||
|
@ -893,7 +893,7 @@
|
||||||
|
|
||||||
if($results->getReleaseDescription() === null)
|
if($results->getReleaseDescription() === null)
|
||||||
{
|
{
|
||||||
$results->setReleaseDescription($ncc_package_results->getReleaseDescription() ?? null);
|
$results->setReleaseDescription($ncc_package_results->getReleaseDescription());
|
||||||
}
|
}
|
||||||
elseif($ncc_package_results->getReleaseDescription() !== null)
|
elseif($ncc_package_results->getReleaseDescription() !== null)
|
||||||
{
|
{
|
||||||
|
@ -905,7 +905,7 @@
|
||||||
|
|
||||||
if($results->getVersion() === null)
|
if($results->getVersion() === null)
|
||||||
{
|
{
|
||||||
$results->setVersion($ncc_package_results->getVersion() ?? null);
|
$results->setVersion($ncc_package_results->getVersion());
|
||||||
}
|
}
|
||||||
elseif($ncc_package_results->getVersion() !== null)
|
elseif($ncc_package_results->getVersion() !== null)
|
||||||
{
|
{
|
||||||
|
@ -916,7 +916,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$results->setFiles(self::mergeFilesResults($ncc_package_results->getFiles(), ($results->getFiles() ?? null)));
|
$results->setFiles(self::mergeFilesResults($ncc_package_results->getFiles(), ($results->getFiles())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return $results;
|
||||||
|
@ -1050,7 +1050,7 @@
|
||||||
return RuntimeCache::get('posix_isatty');
|
return RuntimeCache::get('posix_isatty');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(function_exists('posix_isatty') === false)
|
if(!function_exists('posix_isatty'))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1077,4 +1077,51 @@
|
||||||
return $input;
|
return $input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans the given directory for files and returns the found file with the given patterns
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param array $include
|
||||||
|
* @param array $exclude
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function scanDirectory(string $path, array $include=[], array $exclude=[]): array
|
||||||
|
{
|
||||||
|
$directory_scanner = new DirectoryScanner();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$directory_scanner->unsetFlag(FilesystemIterator::FOLLOW_SYMLINKS);
|
||||||
|
}
|
||||||
|
catch (\ncc\ThirdParty\theseer\DirectoryScanner\Exception $e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Cannot scan directory, unable to remove the FOLLOW_SYMLINKS flag from the iterator: ' . $e->getMessage(), $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($include) > 0)
|
||||||
|
{
|
||||||
|
$directory_scanner->setIncludes($include);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($exclude) > 0)
|
||||||
|
{
|
||||||
|
$directory_scanner->setExcludes($exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = [];
|
||||||
|
foreach($directory_scanner($path) as $item)
|
||||||
|
{
|
||||||
|
// Ignore directories, they're not important.
|
||||||
|
if(is_dir($item->getPathName()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$results[] = $item->getPathName();
|
||||||
|
Console::outVerbose(sprintf('Selected file %s', $item->getPathName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue