Added classes & objects for Package Structure 1.0

This commit is contained in:
Netkas 2022-10-14 07:05:46 -04:00
parent af819913fd
commit c54ea383b9
46 changed files with 1396 additions and 93 deletions

View file

@ -1,3 +1,8 @@
# NCC Default configuration file, upon installation the installer will generate a new configuration file
# for your system or update the existing configuration file and only overwriting values that are no
# longer applicable to the current version of NCC, incorrect configuration values can cause
# unexpected behavior or bugs.
ncc: ncc:
# The default data directory that is used by NCC to store packages, # The default data directory that is used by NCC to store packages,
# cache, configuration files and other generated files. This includes # cache, configuration files and other generated files. This includes
@ -21,20 +26,12 @@ php:
# issues/backdoors, use this feature for containerized environments # issues/backdoors, use this feature for containerized environments
enable_environment_configurations: false enable_environment_configurations: false
# Enables/Disables the injection of NCC's include path
# during the initialization phase allowing you to import
# packages using the `import()` function and other ncc
# API Functions without needing to require NCC's autoloader
#
# This feature is highly recommended to be enabled
enable_include_path: true
git: git:
executable_path: "/usr/bin/git" executable_path: "/usr/bin/git"
composer: composer:
# When enabled, NCC will use it's builtin version of composer # When enabled, NCC will use it's builtin version of composer
# to execute composer tasks, if disabled it will fallback to # to execute composer tasks, if disabled it will fall back to
# the `executable_path` option and attempt to use that specified # the `executable_path` option and attempt to use that specified
# location of composer # location of composer
enable_internal_composer: true enable_internal_composer: true

View file

@ -100,6 +100,8 @@
} }
$NCC_AUTO_MODE = ($NCC_ARGS !== null && isset($NCC_ARGS['auto'])); $NCC_AUTO_MODE = ($NCC_ARGS !== null && isset($NCC_ARGS['auto']));
$NCC_BYPASS_CLI_CHECK = ($NCC_ARGS !== null && isset($NCC_ARGS['bypass-cli-check']));
$NCC_BYPASS_CHECKSUM = ($NCC_ARGS !== null && isset($NCC_ARGS['bypass-checksum']));
if(isset($NCC_ARGS['help'])) if(isset($NCC_ARGS['help']))
{ {
@ -108,6 +110,8 @@
new CliHelpSection(['--auto'], 'Automates the installation process'), new CliHelpSection(['--auto'], 'Automates the installation process'),
new CliHelpSection(['--install-composer'], 'Require composer to be installed alongside NCC'), new CliHelpSection(['--install-composer'], 'Require composer to be installed alongside NCC'),
new CliHelpSection(['--install-dir'], 'Specifies the installation directory for NCC'), new CliHelpSection(['--install-dir'], 'Specifies the installation directory for NCC'),
new CliHelpSection(['--bypass-cli-check'], 'Bypasses the check for a CLI environment'),
new CliHelpSection(['--bypass-checksum'], 'Bypasses the checksum for the installation files'),
]; ];
$options_padding = Functions::detectParametersPadding($options) + 4; $options_padding = Functions::detectParametersPadding($options) + 4;
@ -128,6 +132,8 @@
} }
// Detect the server API // Detect the server API
if(!$NCC_BYPASS_CLI_CHECK)
{
if(defined('PHP_SAPI')) if(defined('PHP_SAPI'))
{ {
if(strtolower(PHP_SAPI) !== 'cli') if(strtolower(PHP_SAPI) !== 'cli')
@ -146,9 +152,10 @@
'recommended to be running this installer in a terminal' 'recommended to be running this installer in a terminal'
); );
} }
}
// Check if running in a TTY // Check if running in a TTY
if(stream_isatty(STDERR)) if(stream_isatty(STDERR) && !$NCC_BYPASS_CLI_CHECK)
{ {
Console::outWarning('Your terminal may have some issues rendering the output of this installer'); Console::outWarning('Your terminal may have some issues rendering the output of this installer');
} }
@ -193,6 +200,8 @@
} }
// Preform the checksum validation // Preform the checksum validation
if(!$NCC_BYPASS_CHECKSUM)
{
if(!file_exists($NCC_CHECKSUM)) if(!file_exists($NCC_CHECKSUM))
{ {
Console::outWarning('The file \'checksum.bin\' was not found, the contents of the program cannot be verified to be safe'); Console::outWarning('The file \'checksum.bin\' was not found, the contents of the program cannot be verified to be safe');
@ -228,6 +237,7 @@
Console::out('Checksum passed'); Console::out('Checksum passed');
} }
} }
}
// Check for required extensions // Check for required extensions
$curl_available = true; $curl_available = true;
@ -514,7 +524,7 @@
// Verify install // Verify install
if(!$NCC_FILESYSTEM->exists([$NCC_INSTALL_PATH . DIRECTORY_SEPARATOR . 'composer.phar'])) if(!$NCC_FILESYSTEM->exists([$NCC_INSTALL_PATH . DIRECTORY_SEPARATOR . 'composer.phar']))
{ {
Console::outError("The installation exited without any issues but composer doesn't seem to be installed correctly"); Console::outError("Installation failed, the installation exited without any issues but composer doesn't seem to be installed correctly");
exit(1); exit(1);
} }

View file

@ -0,0 +1,8 @@
<?php
namespace ncc\Abstracts;
abstract class CompilerOptions
{
}

View file

@ -0,0 +1,8 @@
<?php
namespace ncc\Abstracts;
abstract class EncoderType
{
const ZiProto = '3';
}

View file

@ -3,20 +3,24 @@
namespace ncc\Abstracts; namespace ncc\Abstracts;
use ncc\Exceptions\AccessDeniedException; use ncc\Exceptions\AccessDeniedException;
use ncc\Exceptions\AutoloadGeneratorException;
use ncc\Exceptions\ComponentVersionNotFoundException; use ncc\Exceptions\ComponentVersionNotFoundException;
use ncc\Exceptions\ConstantReadonlyException; use ncc\Exceptions\ConstantReadonlyException;
use ncc\Exceptions\DirectoryNotFoundException; use ncc\Exceptions\DirectoryNotFoundException;
use ncc\Exceptions\FileNotFoundException; use ncc\Exceptions\FileNotFoundException;
use ncc\Exceptions\InvalidConstantNameException;
use ncc\Exceptions\InvalidCredentialsEntryException; use ncc\Exceptions\InvalidCredentialsEntryException;
use ncc\Exceptions\InvalidPackageException;
use ncc\Exceptions\InvalidPackageNameException; use ncc\Exceptions\InvalidPackageNameException;
use ncc\Exceptions\InvalidProjectConfigurationException; use ncc\Exceptions\InvalidProjectConfigurationException;
use ncc\Exceptions\InvalidProjectNameException; use ncc\Exceptions\InvalidProjectNameException;
use ncc\Exceptions\InvalidScopeException; use ncc\Exceptions\InvalidScopeException;
use ncc\Exceptions\InvalidVersionNumberException; use ncc\Exceptions\InvalidVersionNumberException;
use ncc\Exceptions\MalformedJsonException; use ncc\Exceptions\MalformedJsonException;
use ncc\Exceptions\MethodNotAvailableException; use ncc\Exceptions\NoUnitsFoundException;
use ncc\Exceptions\ProjectAlreadyExistsException; use ncc\Exceptions\ProjectAlreadyExistsException;
use ncc\Exceptions\RuntimeException; use ncc\Exceptions\RuntimeException;
use ncc\Exceptions\UnsupportedPackageException;
/** /**
* @author Zi Xing Narrakas * @author Zi Xing Narrakas
@ -94,6 +98,36 @@
*/ */
const ProjectAlreadyExistsException = -1713; const ProjectAlreadyExistsException = -1713;
/**
* @see AutoloadGeneratorException
*/
const AutoloadGeneratorException = -1714;
/**
* @see NoUnitsFoundException
*/
const NoUnitsFoundException = -1715;
/**
* @see UnsupportedPackageException
*/
const UnsupportedPackageException = -1716;
/**
* @see NotImplementedException
*/
const NotImplementedException = -1717;
/**
* @see InvalidPackageException
*/
const InvalidPackageException = -1718;
/**
* @see InvalidConstantNameException
*/
const InvalidConstantNameException = -1719;
/** /**
* All the exception codes from NCC * All the exception codes from NCC
*/ */
@ -112,5 +146,11 @@
self::InvalidVersionNumberException, self::InvalidVersionNumberException,
self::InvalidProjectNameException, self::InvalidProjectNameException,
self::ProjectAlreadyExistsException, self::ProjectAlreadyExistsException,
self::AutoloadGeneratorException,
self::NoUnitsFoundException,
self::UnsupportedPackageException,
self::NotImplementedException,
self::InvalidPackageException,
self::InvalidConstantNameException
]; ];
} }

View file

@ -0,0 +1,8 @@
<?php
namespace ncc\Abstracts;
abstract class PackageStandardVersions
{
const VERSION_1 = '1.0';
}

View file

@ -21,4 +21,6 @@
const UnixPath = '/^(((?:\.\/|\.\.\/|\/)?(?:\.?\w+\/)*)(\.?\w+\.?\w+))$/m'; const UnixPath = '/^(((?:\.\/|\.\.\/|\/)?(?:\.?\w+\/)*)(\.?\w+\.?\w+))$/m';
const WindowsPath = '/^(([%][^\/:*?<>""|]*[%])|([a-zA-Z][:])|(\\\\))((\\\\{1})|((\\\\{1})[^\\\\]([^\/:*?<>""|]*))+)$/m'; const WindowsPath = '/^(([%][^\/:*?<>""|]*[%])|([a-zA-Z][:])|(\\\\))((\\\\{1})|((\\\\{1})[^\\\\]([^\/:*?<>""|]*))+)$/m';
const ConstantName = '/^([^\x00-\x7F]|[\w_\ \.\+\-]){2,16}$/';
} }

View file

@ -9,4 +9,8 @@
*/ */
const CredentialsStoreVersion = '1.0.0'; const CredentialsStoreVersion = '1.0.0';
/**
* The current version of the package structure file format
*/
const PackageStructureVersion = '1.0.0';
} }

View file

@ -3,6 +3,9 @@
namespace ncc\CLI; namespace ncc\CLI;
use Exception; use Exception;
use ncc\Abstracts\NccBuildFlags;
use ncc\Exceptions\FileNotFoundException;
use ncc\Exceptions\RuntimeException;
use ncc\ncc; use ncc\ncc;
use ncc\Utilities\Console; use ncc\Utilities\Console;
use ncc\Utilities\Resolver; use ncc\Utilities\Resolver;
@ -22,7 +25,26 @@
if(isset($args['ncc-cli'])) if(isset($args['ncc-cli']))
{ {
// Initialize NCC // Initialize NCC
try
{
ncc::initialize(); ncc::initialize();
}
catch (FileNotFoundException $e)
{
Console::outException('Cannot initialize NCC, one or more files were not found.', $e, 1);
}
catch (RuntimeException $e)
{
Console::outException('Cannot initialize NCC due to a runtime error.', $e, 1);
}
// Define CLI stuff
define('NCC_CLI_MODE', 1);
if(in_array(NccBuildFlags::Unstable, NCC_VERSION_FLAGS))
{
Console::outWarning('This is an unstable build of NCC, expect some features to not work as expected');
}
try try
{ {

View file

@ -1,26 +0,0 @@
<?php
namespace ncc\Classes;
use ncc\Objects\ProjectConfiguration;
class AutoloaderGenerator
{
/**
* @var ProjectConfiguration
*/
private ProjectConfiguration $project;
/**
* @param ProjectConfiguration $project
*/
public function __construct(ProjectConfiguration $project)
{
$this->project = $project;
}
public function generateAutoload(string $src, string $output, bool $static=false)
{
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace ncc\Classes\Compilers;
use ncc\Classes\PhpExtension\AutoloaderGenerator;
use ncc\Interfaces\CompilerInterface;
use ncc\Objects\ProjectConfiguration;
class Php implements CompilerInterface
{
/**
* @var ProjectConfiguration
*/
private ProjectConfiguration $project;
/**
* @var AutoloaderGenerator
*/
private AutoloaderGenerator $autoloader;
/**
* @param ProjectConfiguration $project
*/
public function __construct(ProjectConfiguration $project)
{
$this->project = $project;
$this->autoloader = new AutoloaderGenerator($project);
}
public function prepare(array $options)
{
// TODO: Implement prepare() method.
}
public function build(array $options)
{
// TODO: Implement build() method.
}
}

View file

@ -0,0 +1,43 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Classes;
use ncc\Exceptions\FileNotFoundException;
class PackageParser
{
/**
* @var string
*/
private $PackagePath;
/**
* Package Parser public constructor.
*
* @param string $path
*/
public function __construct(string $path)
{
$this->PackagePath = $path;
$this->parseFile();
}
private function parseFile()
{
if(file_exists($this->PackagePath) == false)
{
throw new FileNotFoundException('The given package path \'' . $this->PackagePath . '\' does not exist');
}
if(is_file($this->PackagePath) == false)
{
throw new FileNotFoundException('The given package path \'' . $this->PackagePath . '\' is not a file');
}
$file_handler = fopen($this->PackagePath, 'rb');
$header = fread($file_handler, 14);
var_dump($header);
}
}

View file

@ -0,0 +1,117 @@
<?php
namespace ncc\Classes\PhpExtension;
use ArrayIterator;
use ncc\Exceptions\AutoloadGeneratorException;
use ncc\Exceptions\NoUnitsFoundException;
use ncc\Objects\ProjectConfiguration;
use ncc\ThirdParty\theseer\Autoload\CollectorException;
use ncc\ThirdParty\theseer\Autoload\CollectorResult;
use ncc\ThirdParty\theseer\Autoload\Config;
use ncc\ThirdParty\theseer\Autoload\Factory;
use ncc\ThirdParty\theseer\DirectoryScanner\Exception;
use ncc\Utilities\Console;
use SplFileInfo;
class AutoloaderGenerator
{
/**
* @var ProjectConfiguration
*/
private ProjectConfiguration $project;
/**
* @param ProjectConfiguration $project
*/
public function __construct(ProjectConfiguration $project)
{
$this->project = $project;
}
/**
* Processes the project and generates the autoloader source code.
*
* @param string $src
* @param string $output
* @param bool $static
* @return string
* @throws AutoloadGeneratorException
* @throws CollectorException
* @throws Exception
* @throws NoUnitsFoundException
*/
public function generateAutoload(string $src, string $output, bool $static=false): string
{
// Construct configuration
$configuration = new Config([$src]);
$configuration->setFollowSymlinks(false);
$configuration->setOutputFile($output);
$configuration->setTrusting(false); // Paranoid
// Construct factory
$factory = new Factory();
$factory->setConfig($configuration);
// Create Collector
$result = self::runCollector($factory, $configuration);
// Exception raises when there are no files in the project that can be processed by the autoloader
if(!$result->hasUnits())
{
throw new NoUnitsFoundException('No units were found in the project');
}
if(!$result->hasDuplicates())
{
foreach($result->getDuplicates() as $unit => $files)
{
Console::outWarning((count($files) -1). ' duplicate unit(s) detected in the project: ' . $unit);
}
}
$template = @file_get_contents($configuration->getTemplate());
if ($template === false)
{
throw new AutoloadGeneratorException("Failed to read the template file '" . $configuration->getTemplate() . "'");
}
$builder = $factory->getRenderer($result);
return $builder->render($template);
}
/**
* Iterates through the target directories through the collector and returns the collector results.
*
* @param Factory $factory
* @param Config $config
* @return CollectorResult
* @throws CollectorException
* @throws Exception
*/
private static function runCollector(Factory $factory, Config $config): CollectorResult
{
$collector = $factory->getCollector();
foreach($config->getDirectories() as $directory)
{
if(is_dir($directory))
{
$scanner = $factory->getScanner()->getIterator($directory);
$collector->processDirectory($scanner);
unset($scanner);
}
else
{
$file = new SplFileInfo($directory);
$filter = $factory->getFilter(new ArrayIterator(array($file)));
foreach($filter as $file)
{
$collector->processFile($file);
}
}
}
return $collector->getResult();
}
}

View file

@ -0,0 +1,46 @@
<?php
namespace ncc\Classes\PhpExtension;
use FilesystemIterator;
use ncc\Abstracts\CompilerOptions;
use ncc\Interfaces\CompilerInterface;
use ncc\ncc;
use ncc\Objects\ProjectConfiguration;
use ncc\ThirdParty\theseer\DirectoryScanner\DirectoryScanner;
use ncc\Utilities\Console;
class Compiler implements CompilerInterface
{
/**
* @var ProjectConfiguration
*/
private ProjectConfiguration $project;
/**
* @param ProjectConfiguration $project
*/
public function __construct(ProjectConfiguration $project)
{
$this->project = $project;
}
public function prepare(array $options)
{
if(ncc::cliMode())
{
Console::out('Building autoloader');
Console::out('theseer\DirectoryScanner - Copyright (c) 2009-2014 Arne Blankerts <arne@blankerts.de> All rights reserved.');
Console::out('theseer\Autoload - Copyright (c) 2010-2016 Arne Blankerts <arne@blankerts.de> and Contributors All rights reserved.');
}
// First scan the project files and create a file struct.
$DirectoryScanner = new DirectoryScanner();
$DirectoryScanner->unsetFlag(FilesystemIterator::FOLLOW_SYMLINKS);
}
public function build(array $options)
{
// TODO: Implement build() method.
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class AutoloadGeneratorException extends Exception
{
/**
* @param string $message
* @param Throwable|null $previous
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::AutoloadGeneratorException, $previous);
}
}

View file

@ -0,0 +1,28 @@
<?php
/** @noinspection PhpPropertyOnlyWrittenInspection */
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class InvalidConstantNameException extends Exception
{
/**
* @var Throwable|null
*/
private ?Throwable $previous;
/**
* @param string $message
* @param Throwable|null $previous
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::InvalidConstantNameException, $previous);
$this->message = $message;
$this->previous = $previous;
}
}

View file

@ -0,0 +1,25 @@
<?php
/** @noinspection PhpPropertyOnlyWrittenInspection */
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class InvalidPackageException extends Exception
{
private ?Throwable $previous;
/**
* @param string $message
* @param Throwable|null $previous
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::InvalidPackageException, $previous);
$this->message = $message;
$this->previous = $previous;
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class NoUnitsFoundException extends Exception
{
/**
* @var Throwable|null
*/
private ?Throwable $previous;
/**
* @param string $message
* @param Throwable|null $previous
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::NoUnitsFoundException, $previous);
$this->message = $message;
$this->previous = $previous;
}
}

View file

@ -0,0 +1,28 @@
<?php
/** @noinspection PhpPropertyOnlyWrittenInspection */
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class NotImplementedException extends Exception
{
/**
* @var Throwable|null
*/
private ?Throwable $previous;
/**
* @param string $message
* @param Throwable|null $previous
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::NotImplementedException, $previous);
$this->message = $message;
$this->previous = $previous;
}
}

View file

@ -0,0 +1,25 @@
<?php
/** @noinspection PhpPropertyOnlyWrittenInspection */
namespace ncc\Exceptions;
use Exception;
use ncc\Abstracts\ExceptionCodes;
use Throwable;
class UnsupportedPackageException extends Exception
{
private ?Throwable $previous;
/**
* @param string $message
* @param Throwable|null $previous
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::UnsupportedPackageException, $previous);
$this->message = $message;
$this->previous = $previous;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace ncc\Interfaces;
interface CompilerInterface
{
public function prepare(array $options);
public function build(array $options);
}

View file

@ -1,5 +1,7 @@
<?php <?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects; namespace ncc\Objects;
use ncc\Abstracts\ConsoleColors; use ncc\Abstracts\ConsoleColors;
@ -81,9 +83,11 @@
/** /**
* Returns a string representation of the object * Returns a string representation of the object
* *
* @param int $param_padding
* @param bool $basic
* @return string * @return string
*/ */
public function toString(int $param_padding=0, bool $basic=false) public function toString(int $param_padding=0, bool $basic=false): string
{ {
$out = []; $out = [];
@ -91,9 +95,10 @@
{ {
if($param_padding > 0) if($param_padding > 0)
{ {
/** @noinspection PhpRedundantOptionalArgumentInspection */
$result = str_pad(implode(' ', $this->Parameters), $param_padding, ' ', STR_PAD_RIGHT); $result = str_pad(implode(' ', $this->Parameters), $param_padding, ' ', STR_PAD_RIGHT);
if($basic == false) if(!$basic)
{ {
$result = Console::formatColor($result, ConsoleColors::Green); $result = Console::formatColor($result, ConsoleColors::Green);
} }

View file

@ -3,7 +3,6 @@
namespace ncc\Objects; namespace ncc\Objects;
use ncc\Exceptions\ConstantReadonlyException; use ncc\Exceptions\ConstantReadonlyException;
use ncc\Symfony\Component\Uid\Uuid;
use ncc\Utilities\Resolver; use ncc\Utilities\Resolver;
class Constant class Constant
@ -90,6 +89,7 @@
/** /**
* @param string $value * @param string $value
* @param bool $readonly
* @throws ConstantReadonlyException * @throws ConstantReadonlyException
*/ */
public function setValue(string $value, bool $readonly=false): void public function setValue(string $value, bool $readonly=false): void

View file

@ -1,5 +1,7 @@
<?php <?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects; namespace ncc\Objects;
class NccUpdateInformation class NccUpdateInformation

View file

@ -1,5 +1,7 @@
<?php <?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects; namespace ncc\Objects;
use ncc\Objects\NccVersionInformation\Component; use ncc\Objects\NccVersionInformation\Component;

213
src/ncc/Objects/Package.php Normal file
View file

@ -0,0 +1,213 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects;
use ncc\Exceptions\InvalidPackageException;
use ncc\Exceptions\InvalidProjectConfigurationException;
use ncc\Objects\Package\Component;
use ncc\Objects\Package\Header;
use ncc\Objects\Package\Installer;
use ncc\Objects\Package\MagicBytes;
use ncc\Objects\Package\MainExecutionPolicy;
use ncc\Objects\Package\Resource;
use ncc\Objects\ProjectConfiguration\Assembly;
use ncc\Objects\ProjectConfiguration\Dependency;
use ncc\Utilities\Functions;
class Package
{
/**
* The parsed magic bytes of the package into an object representation
*
* @var MagicBytes
*/
public $MagicBytes;
/**
* The true header of the package
*
* @var Header
*/
public $Header;
/**
* The assembly object of the package
*
* @var Assembly
*/
public $Assembly;
/**
* An array of dependencies that the package depends on
*
* @var Dependency[]
*/
public $Dependencies;
/**
* The Main Execution Policy object for the package if the package is an executable package.
*
* @var MainExecutionPolicy|null
*/
public $MainExecutionPolicy;
/**
* The installer object that is used to install the package if the package is install-able
*
* @var Installer|null
*/
public $Installer;
/**
* An array of resources that the package depends on
*
* @var Resource[]
*/
public $Resources;
/**
* An array of components for the package
*
* @var Component[]
*/
public $Components;
/**
* Public Constructor
*/
public function __construct()
{
$this->MagicBytes = new MagicBytes();
$this->Components = [];
$this->Dependencies = [];
$this->Resources = [];
}
/**
* Validates the package object and returns True if the package contains the correct information
*
* Returns false if the package contains incorrect information which can cause
* an error when compiling the package.
*
* @param bool $throw_exception
* @return bool
* @throws InvalidPackageException
* @throws InvalidProjectConfigurationException
*/
public function validate(bool $throw_exception=True): bool
{
// Validate the MagicBytes constructor
if($this->MagicBytes == null)
{
if($throw_exception)
throw new InvalidPackageException('The MagicBytes property is required and cannot be null');
return false;
}
// Validate the assembly object
if($this->Assembly == null)
{
if($throw_exception)
throw new InvalidPackageException('The Assembly property is required and cannot be null');
return false;
}
if(!$this->Assembly->validate($throw_exception))
return false;
// All checks have passed
return true;
}
/**
* Constructs an array representation of the object
*
* @param bool $bytecode
* @return array
*/
public function toArray(bool $bytecode=false): array
{
$_components = [];
/** @var Component $component */
foreach($this->Components as $component)
$_components[] = $component->toArray($bytecode);
$_dependencies = [];
/** @var Dependency $dependency */
foreach($this->Dependencies as $dependency)
$_dependencies[] = $dependency->toArray($bytecode);
$_resources = [];
/** @var Resource $resource */
foreach($this->Resources as $resource)
$_resources[] = $resource->toArray($bytecode);
return [
($bytecode ? Functions::cbc('header') : 'header') => $this->Header->toArray($bytecode),
($bytecode ? Functions::cbc('assembly') : 'assembly') => $this->Assembly->toArray($bytecode),
($bytecode ? Functions::cbc('dependencies') : 'dependencies') => $_dependencies,
($bytecode ? Functions::cbc('main_execution_policy') : 'main_execution_policy') => $this->MainExecutionPolicy->toArray($bytecode),
($bytecode ? Functions::cbc('installer') : 'installer') => $this->Installer->toArray($bytecode),
($bytecode ? Functions::cbc('resources') : 'resources') => $_resources,
($bytecode ? Functions::cbc('components') : 'components') => $_components
];
}
/**
* @param array $data
* @return Package
*/
public static function fromArray(array $data): self
{
$object = new self();
$object->Header = Functions::array_bc($data, 'header');
if($object->Header !== null)
$object->Header = Header::fromArray($object->Header);
$object->Assembly = Functions::array_bc($data, 'assembly');
if($object->Assembly !== null)
$object->Assembly = Assembly::fromArray($object->Assembly);
$object->MainExecutionPolicy = Functions::array_bc($data, 'main_execution_policy');
if($object->MainExecutionPolicy !== null)
$object->MainExecutionPolicy = MainExecutionPolicy::fromArray($object->MainExecutionPolicy);
$object->Installer = Functions::array_bc($data, 'installer');
if($object->Installer !== null)
$object->Installer = Installer::fromArray($object->Installer);
$_dependencies = Functions::array_bc($data, 'dependencies');
if($_dependencies !== null)
{
foreach($_dependencies as $dependency)
{
$object->Dependencies[] = Resource::fromArray($dependency);
}
}
$_resources = Functions::array_bc($data, 'resources');
if($_resources !== null)
{
foreach($_resources as $resource)
{
$object->Resources[] = Resource::fromArray($resource);
}
}
$_components = Functions::array_bc($data, 'components');
if($_components !== null)
{
foreach($_components as $component)
{
$object->Components[] = Component::fromArray($component);
}
}
return $object;
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace ncc\Objects\Package;
use ncc\Utilities\Functions;
class Component
{
/**
* The name of the component or the file name of the component
*
* @var string
*/
public $Name;
/**
* Flags associated with the component created by the compiler extension
*
* @var array
*/
public $Flags;
/**
* A sha1 hash checksum of the component, this will be compared against the data to determine
* the integrity of the component to ensure that the component is not corrupted.
*
* @var string
*/
public $Checksum;
/**
* The raw data of the component, this is to be processed by the compiler extension
*
* @var string
*/
public $Data;
/**
* Validates the checksum of the component, returns false if the checksum or data is invalid or if the checksum
* failed.
*
* @return bool
*/
public function validateChecksum(): bool
{
if($this->Checksum === null)
return false;
if($this->Data === null)
return false;
if(hash('sha1', $this->Data) !== $this->Checksum)
return false;
return true;
}
/**
* Returns an array representation of the component.
*
* @param bool $bytecode
* @return array
*/
public function toArray(bool $bytecode=false): array
{
return [
($bytecode ? Functions::cbc('name') : 'name') => $this->Name,
($bytecode ? Functions::cbc('flags') : 'flags') => $this->Flags,
($bytecode ? Functions::cbc('checksum') : 'checksum') => $this->Checksum,
($bytecode ? Functions::cbc('data') : 'data') => $this->Data,
];
}
/**
* Constructs a new object from an array representation
*
* @param array $data
* @return Component
*/
public static function fromArray(array $data): self
{
$Object = new self();
$Object->Name = Functions::array_bc($data, 'name');
$Object->Flags = Functions::array_bc($data, 'flags');
$Object->Checksum = Functions::array_bc($data, 'checksum');
$Object->Data = Functions::array_bc($data, 'data');
return $Object;
}
}

View file

@ -0,0 +1,73 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects\Package;
use ncc\Objects\ProjectConfiguration\Compiler;
use ncc\Utilities\Functions;
class Header
{
/**
* The compiler extension information that was used to build the package
*
* @var Compiler
*/
public $CompilerExtension;
/**
* An array of constants that are set when the package is imported or executed during runtime.
*
* @var array
*/
public $RuntimeConstants;
/**
* The version of NCC that was used to compile the package, can be used for backwards compatibility
*
* @var string
*/
public $CompilerVersion;
/**
* Public Constructor
*/
public function __construct()
{
$this->CompilerExtension = new Compiler();
$this->RuntimeConstants = [];
}
/**
* Returns an array representation of the object
*
* @param bool $bytecode
* @return array
*/
public function toArray(bool $bytecode=false): array
{
return [
($bytecode ? Functions::cbc('compiler_extension') : 'compiler_extension') => $this->CompilerExtension->toArray($bytecode),
($bytecode ? Functions::cbc('runtime_constants') : 'runtime_constants') => $this->RuntimeConstants,
($bytecode ? Functions::cbc('compiler_version') : 'compiler_version') => $this->CompilerVersion,
];
}
/**
* Constructs the object from an array representation
*
* @param array $data
* @return static
*/
public static function fromArray(array $data): self
{
$object = new self();
$object->CompilerExtension = Functions::array_bc($data, 'compiler_extension');
$object->RuntimeConstants = Functions::array_bc($data, 'runtime_constants');
$object->CompilerVersion = Functions::array_bc($data, 'compiler_version');
return $object;
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace ncc\Objects\Package;
class Installer
{
/**
* Returns an array representation of the object
*
* @param bool $bytecode
* @return array
*/
public function toArray(bool $bytecode=false): array
{
return [];
}
/**
* Constructs object from an array representation
*
* @param array $data
* @return Installer
*/
public static function fromArray(array $data): self
{
$object = new self();
return $object;
}
}

View file

@ -0,0 +1,153 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects\Package;
use ncc\Abstracts\EncoderType;
use ncc\Abstracts\Versions;
class MagicBytes
{
/**
* The version of the package structure standard that is used
*
* @var string
*/
public $PackageStructureVersion;
/**
* The type of encoder that was used to encode the package structure
*
* @var string|EncoderType
*/
public $Encoder;
/**
* Indicates whether the package structure is compressed
*
* @var bool
*/
public $IsCompressed;
/**
* Indicates whether the package structure is encrypted
*
* @var bool
*/
public $IsEncrypted;
/**
* Indicates whether the package is installable
*
* @var bool
*/
public $IsInstallable;
/**
* Indicates whether the package is a executable
*
* @var bool
*/
public $IsExecutable;
/**
* Basic Public Constructor with default values
*/
public function __construct()
{
$this->PackageStructureVersion = Versions::PackageStructureVersion;
$this->Encoder = EncoderType::ZiProto;
$this->IsCompressed = false;
$this->IsEncrypted = false;
$this->IsInstallable = false;
$this->IsExecutable = false;
}
/**
* Returns an array representation of the object
*
* @return array
*/
public function toArray(): array
{
return [
'package_structure_version' => $this->PackageStructureVersion,
'encoder' => $this->Encoder,
'is_compressed' => $this->IsCompressed,
'is_encrypted' => $this->IsEncrypted,
'is_installable' => $this->IsInstallable,
'is_executable' => $this->IsExecutable
];
}
/**
* Constructs object from an array representation
*
* @param array $data
* @return MagicBytes
*/
public static function fromArray(array $data): self
{
$Object = new self();
if(isset($data['is_executable']))
$Object->IsExecutable = (bool)$data['is_executable'];
return $Object;
}
/**
* Builds and returns the string representation of the magic bytes
*
* @return string
*/
public function toString(): string
{
// NCC_PACKAGE1.0
$magic_bytes = 'NCC_PACKAGE' . $this->PackageStructureVersion;
// NCC_PACKAGE1.03
$magic_bytes .= $this->Encoder;
if($this->IsEncrypted)
{
// NCC_PACKAGE1.031
$magic_bytes .= '1';
}
else
{
// NCC_PACKAGE1.030
$magic_bytes .= '0';
}
if($this->IsCompressed)
{
// NCC_PACKAGE1.0301
$magic_bytes .= '1';
}
else
{
// NCC_PACKAGE1.0300
$magic_bytes .= '0';
}
if($this->IsExecutable && $this->IsInstallable)
{
// NCC_PACKAGE1.030142
$magic_bytes .= '42';
}
elseif($this->IsExecutable)
{
// NCC_PACKAGE1.030141
$magic_bytes .= '41';
}
elseif($this->IsInstallable)
{
// NCC_PACKAGE1.030140
$magic_bytes .= '40';
}
return $magic_bytes;
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace ncc\Objects\Package;
class MainExecutionPolicy
{
/**
* Returns an array representation of the object
*
* @param bool $bytecode
* @return array
*/
public function toArray(bool $bytecode=false): array
{
return [];
}
/**
* Constructs object from an array representation
*
* @param array $data
* @return MainExecutionPolicy
*/
public static function fromArray(array $data): self
{
$object = new self();
return $object;
}
}

View file

@ -0,0 +1,84 @@
<?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Objects\Package;
use ncc\Utilities\Functions;
class Resource
{
/**
* The file/path name of the resource
*
* @var string
*/
public $Name;
/**
* A sha1 hash checksum of the resource, this will be compared against the data to determine
* the integrity of the resource to ensure that the resource is not corrupted.
*
* @var string
*/
public $Checksum;
/**
* The raw data of the resource
*
* @var string
*/
public $Data;
/**
* Validates the checksum of the resource, returns false if the checksum or data is invalid or if the checksum
* failed.
*
* @return bool
*/
public function validateChecksum(): bool
{
if($this->Checksum === null)
return false;
if($this->Data === null)
return false;
if(hash('sha1', $this->Data) !== $this->Checksum)
return false;
return true;
}
/**
* Returns an array representation of the resource.
*
* @param bool $bytecode
* @return array
*/
public function toArray(bool $bytecode=false): array
{
return [
($bytecode ? Functions::cbc('name') : 'name') => $this->Name,
($bytecode ? Functions::cbc('checksum') : 'checksum') => $this->Checksum,
($bytecode ? Functions::cbc('data') : 'data') => $this->Data,
];
}
/**
* Constructs a new object from an array representation
*
* @param array $data
* @return Resource
*/
public static function fromArray(array $data): self
{
$object = new self();
$object->Name = Functions::array_bc($data, 'name');
$object->Checksum = Functions::array_bc($data, 'checksum');
$object->Data = Functions::array_bc($data, 'data');
return $object;
}
}

View file

@ -85,7 +85,7 @@
*/ */
public function validate(bool $throw_exception=false): bool public function validate(bool $throw_exception=false): bool
{ {
if(preg_match(RegexPatterns::UUIDv4, $this->UUID) == false) if(!preg_match(RegexPatterns::UUIDv4, $this->UUID))
{ {
if($throw_exception) if($throw_exception)
throw new InvalidProjectConfigurationException('The UUID is not a valid v4 UUID', 'Assembly.UUID'); throw new InvalidProjectConfigurationException('The UUID is not a valid v4 UUID', 'Assembly.UUID');
@ -93,7 +93,7 @@
return false; return false;
} }
if(Validate::version($this->Version) == false) if(!Validate::version($this->Version))
{ {
if($throw_exception) if($throw_exception)
throw new InvalidProjectConfigurationException('The version number is invalid', 'Assembly.Version'); throw new InvalidProjectConfigurationException('The version number is invalid', 'Assembly.Version');
@ -101,7 +101,7 @@
return false; return false;
} }
if(preg_match(RegexPatterns::PackageNameFormat, $this->Package) == false) if(!preg_match(RegexPatterns::PackageNameFormat, $this->Package))
{ {
if($throw_exception) if($throw_exception)
throw new InvalidProjectConfigurationException('The package name is invalid', 'Assembly.Package'); throw new InvalidProjectConfigurationException('The package name is invalid', 'Assembly.Package');

View file

@ -1,10 +1,14 @@
<?php <?php
/** @noinspection PhpMissingFieldTypeInspection */
namespace ncc\Runtime; namespace ncc\Runtime;
use ncc\Exceptions\ConstantReadonlyException; use ncc\Exceptions\ConstantReadonlyException;
use ncc\Exceptions\InvalidConstantNameException;
use ncc\Objects\Constant; use ncc\Objects\Constant;
use ncc\Utilities\Resolver; use ncc\Utilities\Resolver;
use ncc\Utilities\Validate;
class Constants class Constants
{ {
@ -24,10 +28,13 @@
* @param bool $readonly Indicates if the constant cannot be changed with the registerConstant function once it's registered * @param bool $readonly Indicates if the constant cannot be changed with the registerConstant function once it's registered
* @return void * @return void
* @throws ConstantReadonlyException * @throws ConstantReadonlyException
* @throws InvalidConstantNameException
*/ */
public static function register(string $scope, string $name, string $value, bool $readonly=false) public static function register(string $scope, string $name, string $value, bool $readonly=false): void
{ {
// TODO: Add functionality to convert the constant name to be more memory-friendly with a size limit if(!Validate::constantName($name))
throw new InvalidConstantNameException('The name specified is not valid for a constant name');
$constant_hash = Resolver::resolveConstantHash($scope, $name); $constant_hash = Resolver::resolveConstantHash($scope, $name);
if(isset(self::$Constants[$constant_hash])) if(isset(self::$Constants[$constant_hash]))
@ -47,8 +54,11 @@
* @return void * @return void
* @throws ConstantReadonlyException * @throws ConstantReadonlyException
*/ */
public static function delete(string $scope, string $name) public static function delete(string $scope, string $name): void
{ {
if(!Validate::constantName($name))
return;
$constant_hash = Resolver::resolveConstantHash($scope, $name); $constant_hash = Resolver::resolveConstantHash($scope, $name);
if(isset(self::$Constants[$constant_hash]) && self::$Constants[$constant_hash]->isReadonly()) if(isset(self::$Constants[$constant_hash]) && self::$Constants[$constant_hash]->isReadonly())

8
src/ncc/ThirdParty/theseer/Autoload/.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,26 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="IncorrectHttpHeaderInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="customHeaders">
<set>
<option value="Subject" />
<option value="Reply-To" />
<option value="X-JSON-Schema" />
<option value="X-JSON-Type" />
<option value="X-JSON-Path" />
<option value="X-Java-Type" />
<option value="X-Region-Id" />
<option value="X-GraphQL-Variables" />
<option value="X-SSH-Private-Key" />
<option value="X-Args-0" />
<option value="X-Args-1" />
<option value="X-Args-2" />
<option value="X-Args-3" />
<option value="X-Args-4" />
<option value="X-Args-5" />
</set>
</option>
</inspection_tool>
</profile>
</component>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Autoload.iml" filepath="$PROJECT_DIR$/.idea/Autoload.iml" />
</modules>
</component>
</project>

6
src/ncc/ThirdParty/theseer/Autoload/.idea/php.xml generated vendored Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpProjectSharedConfiguration" php_language_level="8.0">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
</project>

6
src/ncc/ThirdParty/theseer/Autoload/.idea/vcs.xml generated vendored Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../../.." vcs="Git" />
</component>
</project>

View file

@ -29,7 +29,7 @@
*/ */
public static function cbc(string $input): int public static function cbc(string $input): int
{ {
return hexdec(hash('crc32', $input)); return hexdec(hash('crc32', $input, true));
} }
/** /**

View file

@ -187,4 +187,25 @@
return false; return false;
} }
/**
* Validates if the constant name is valid
*
* @param $input
* @return bool
*/
public static function constantName($input): bool
{
if($input == null)
{
return false;
}
if(!preg_match(RegexPatterns::ConstantName, $input))
{
return false;
}
return true;
}
} }

View file

@ -8,7 +8,7 @@
* before proceeding to improve performance. * before proceeding to improve performance.
*/ */
if(defined('NCC_INIT') == false) if(!defined('NCC_INIT'))
{ {
$third_party_path = __DIR__ . DIRECTORY_SEPARATOR . 'ThirdParty' . DIRECTORY_SEPARATOR; $third_party_path = __DIR__ . DIRECTORY_SEPARATOR . 'ThirdParty' . DIRECTORY_SEPARATOR;
$target_files = [ $target_files = [
@ -23,14 +23,28 @@
$third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Filesystem' . DIRECTORY_SEPARATOR . 'autoload_spl.php', $third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Filesystem' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Yaml' . DIRECTORY_SEPARATOR . 'autoload_spl.php', $third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Yaml' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'theseer' . DIRECTORY_SEPARATOR . 'Autoload' . DIRECTORY_SEPARATOR . 'autoload_spl.php', $third_party_path . 'theseer' . DIRECTORY_SEPARATOR . 'Autoload' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'theseer' . DIRECTORY_SEPARATOR . 'DirectoryScanner' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
]; ];
$init_success = true;
foreach($target_files as $file) foreach($target_files as $file)
{ {
if(!file_exists($file))
{
trigger_error('Cannot find file ' . $file, E_USER_WARNING);
$init_success = false;
continue;
}
require_once($file); require_once($file);
} }
if(\ncc\ncc::initialize() == false) if(!$init_success)
{
trigger_error('One or more NCC components are missing/failed to load, NCC runtime may not be stable.', E_USER_WARNING);
}
if(!\ncc\ncc::initialize())
{ {
trigger_error('NCC Failed to initialize', E_USER_WARNING); trigger_error('NCC Failed to initialize', E_USER_WARNING);
} }

View file

@ -96,6 +96,23 @@
return true; return true;
} }
/**
* Determines if NCC is currently in CLI mode or not
*
* @return bool
*/
public static function cliMode(): bool
{
// TODO: Optimize this function to reduce redundant calls
if(defined('NCC_CLI_MODE') && NCC_CLI_MODE == 1)
{
return true;
}
return false;
}
/** /**
* Returns the constants set by NCC * Returns the constants set by NCC
* *
@ -122,6 +139,9 @@
'NCC_VERSION_BRANCH' => constant('NCC_VERSION_BRANCH'), 'NCC_VERSION_BRANCH' => constant('NCC_VERSION_BRANCH'),
'NCC_VERSION_UPDATE_SOURCE' => constant('NCC_VERSION_UPDATE_SOURCE'), 'NCC_VERSION_UPDATE_SOURCE' => constant('NCC_VERSION_UPDATE_SOURCE'),
'NCC_VERSION_FLAGS' => constant('NCC_VERSION_FLAGS'), 'NCC_VERSION_FLAGS' => constant('NCC_VERSION_FLAGS'),
// Runtime Information
'NCC_CLI_MODE' => (defined('NCC_CLI_MODE') ? NCC_CLI_MODE : 0) // May not be set during runtime initialization
]; ];
} }
} }

View file

@ -6,7 +6,7 @@
if(!file_exists($BuildDirectory) || !is_dir($BuildDirectory)) if(!file_exists($BuildDirectory) || !is_dir($BuildDirectory))
throw new RuntimeException('Build directory does not exist, to run tests you must build the project.'); throw new RuntimeException('Build directory does not exist, to run tests you must build the project.');
if(!file($AutoloadPath) || is_file($AutoloadPath)) if(!file($AutoloadPath) || !is_file($AutoloadPath))
throw new RuntimeException('Autoload file does not exist in \'' . $BuildDirectory .'\', to run tests you must build the project.'); throw new RuntimeException('Autoload file does not exist in \'' . $BuildDirectory .'\', to run tests you must build the project.');
require($AutoloadPath); require($AutoloadPath);

View file

@ -0,0 +1,13 @@
<?php
require(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'autoload.php');
$Scanner = new \ncc\ThirdParty\theseer\DirectoryScanner\DirectoryScanner();
$Basedir = realpath(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..');
/** @var SplFileInfo $item */
foreach($Scanner($Basedir . DIRECTORY_SEPARATOR . 'src', true) as $item)
{
var_dump($item->getPath());
var_dump($item);
}