Compare commits

..

No commits in common. "master" and "2.0.2" have entirely different histories.

514 changed files with 12741 additions and 17736 deletions

View file

@ -1,136 +0,0 @@
name: CI Pipeline
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
release:
types:
- created
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: mbstring, ctype, common, zip
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y git libpq-dev libzip-dev zip make wget gnupg
- name: Install Phive
run: |
wget -O phive.phar https://phar.io/releases/phive.phar
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
gpg --verify phive.phar.asc phive.phar
chmod +x phive.phar
sudo mv phive.phar /usr/local/bin/phive
- name: Install PHPAB
run: sudo phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
- name: Build project
run: make redist
- name: Find NCC build directory
id: find-ncc-dir
run: echo "NCC_DIR=$(find build/ -type d -name 'ncc_*' | head -n 1)" >> $GITHUB_ENV
- name: Upload NCC build directory
uses: actions/upload-artifact@v3
with:
name: ncc-build
path: ${{ env.NCC_DIR }}
- name: Create redist.zip
run: zip -r redist.zip ${{ env.NCC_DIR }}
- name: Upload redist.zip
uses: actions/upload-artifact@v3
with:
name: redist-zip
path: redist.zip
- name: Build Debian package
run: make deb
- name: Find Debian package
id: find-deb
run: echo "DEB_FILE=$(find build/ -type f -name '*.deb' | head -n 1)" >> $GITHUB_ENV
- name: Upload Debian package
uses: actions/upload-artifact@v3
with:
name: ncc-deb
path: ${{ env.DEB_FILE }}
test-install:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download NCC build directory
uses: actions/download-artifact@v3
with:
name: ncc-build
path: build
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: mbstring, ctype, common, zip
- name: Test NCC installation
run: |
ls -l build
sudo php build/INSTALL --auto
upload-release:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'release' && github.event.action == 'created'
permissions: write-all
steps:
- name: Download redist.zip
uses: actions/download-artifact@v3
with:
name: redist-zip
path: .
- name: Download Debian package
uses: actions/download-artifact@v3
with:
name: ncc-deb
path: .
- name: Set DEB_FILE environment variable
run: echo "DEB_FILE=$(find . -type f -name '*.deb' | head -n 1)" >> $GITHUB_ENV
- name: Upload redist.zip to release
uses: softprops/action-gh-release@v1
with:
files: redist.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload ncc.deb to release
uses: softprops/action-gh-release@v1
with:
files: ${{ env.DEB_FILE }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

5
.gitignore vendored
View file

@ -8,7 +8,7 @@
build
# Autoload files
src/ncc/ThirdParty/composer/Semver/autoload_spl.php
src/ncc/ThirdParty/composer/semver/autoload_spl.php
src/ncc/ThirdParty/defuse/php-encryption/autoload_spl.php
src/ncc/ThirdParty/jelix/version/autoload_spl.php
src/ncc/ThirdParty/nikic/PhpParser/autoload_spl.php
@ -29,6 +29,3 @@ src/ncc/autoload.php
tests/example_project/project.json
tests/example_project/ncc
tests/example_project/build
/.phpunit.result.cache
/.idea/php-test-framework.xml
/.idea/gbrowser_project.xml

View file

@ -1,7 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<ScalaCodeStyleSettings>
<option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" />
</ScalaCodeStyleSettings>
</code_scheme>
</component>

8
.idea/php.xml generated
View file

@ -12,9 +12,10 @@
<component name="PhpIncludePathManager">
<include_path>
<path value="/usr/share/php" />
<path value="$PROJECT_DIR$/../loglib" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.3">
<component name="PhpProjectSharedConfiguration" php_language_level="8.2">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpRuntimeConfiguration">
@ -25,11 +26,6 @@
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings load_method="PHPUNIT_PHAR" custom_loader_path="" phpunit_phar_path="$USER_HOME$/phpunit.phar" />
</phpunit_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>

View file

@ -5,192 +5,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.1.6] - 2024-10-29
This update introduces critical bug fixes
### Fixed
- Validate package instance before checking execution policy
## [2.1.5] - 2024-10-14
This update introduces a critical bug fix
## [2.1.4] - 2024-10-13
This update introduces minor bug fixes & improvements
### Added
- Added new constant `%DEFAULT_BUILD_CONFIGURATION%` which points to the project's default build configuration
- Added new dynamic constant `%BUILD_OUTPUT_PATH%` which can be used as `%BUILD_OUTPUT_PATH%:release` to show the
output path of a specific build configuration
- Refactor CI templates to support dynamic build targets
- Added template `phpexe` & `phpgz` for generating executable binaries and compressed executables for the project
### Changed
- Refactor phpmake template to support dynamic build targets
### Fixed
- ncc will now correctly handle package execution where the main unit is not defined in the package instead of
throwing an exception.
- Executable Compiler will now correctly create a directory if it does not exist when compiling a package using gcc
## [2.1.3] - 2024-09-27
This update introduces bug fixes
### Fixed
- Null-pointer fix
## [2.1.2] - 2024-09-27
This update introduces bug fixes
### Added
- Add getter methods for installation lifecycle steps
- Added pre-install & post-install execution unit handling
### Changed
- Updated DocStrings in PackageManager
### Fixed
- Fixed incorrect enum usage in RepositoryMenu
## [2.1.1] - 2024-09-24
This update introduces a couple of new features and quality of life improvements
### Added
- Added new PHP template `phpunit` for generating PhpUnit tests for the project
- Added new PHP template `phpmake` for generating a Makefile for the project
- Added new PHP template `phplib_full` That combines `phplib`, `phpmake` and `phpunit` templates
- Added new PHP template `phpcli_full` That combines `phpcli`, `phplib`, `phpmake` and `phpunit` templates
- Added new PHP template `phpci_github` that generates a Github CI workflow for the project
### Changed
- The template `phpcli` no longer includes a Makefile, instead use `phpmake` to generate a Makefile for the project
### Fixed
- Fixed incorrect enum usage with a logging method call.
## [2.1.0] - 2024-09-20
This update introduces a refactored code-base, code quality improvements, and better exception handling.
### Added
- Added Test unit tests/ncc/Objects/Package/ComponentTest.php
- Added Test unit tests/ncc/Utilities/ResolverTest.php
- Added Test unit tests/ncc/Utilities/SecurityTest.php
- Added Test unit tests/ncc/Utilities/ValidateTest.php
- Add support for runtime constants
### Changed
- Convert Versions constants to enum cases
- Update Scopes to enum and adjust scope checks
- Convert Runners class to enum with string cases
- Convert RegexPatterns constants to enum cases
- Convert ProjectTemplates constants to enum cases
- Convert PackageStructureVersions constants to enum cases
- Convert PackageStructure constants to enum cases
- Convert PackageDirectory constants to enum cases
- Convert LogLevel constants to enum cases
- Convert FileDescriptor constants to enum cases
- Convert ExceptionCodes constants to enum cases
- Convert ConsoleColors constants to enum cases
- Convert CompilerExtensions constants to enum cases
- Convert RepositoryType constants to enum cases
- Convert RepositoryResultType constants to enum cases
- Convert ProjectType constants to enum cases
- Convert HttpRequestType constants to enum cases
- Convert ComposerStabilityTypes constants to enum cases
- Convert ComposerPackageTypes constants to enum cases
- Convert ComponentDataType constants to enum cases
- Convert BuildOutputType constants to enum cases
- Convert AuthenticationType constants to enum cases
- Convert RuntimeConstants constants to enum cases
- Convert InstallConstants constants to enum cases
- Convert DateTimeConstants constants to enum cases
- Convert BuildConstants constants to enum cases
- Convert AssemblyConstants constants to enum cases
- Convert ProjectOptions constants to enum cases
- Convert InstallPackageOptions constants to enum cases
- Convert InitializeProjectOptions constants to enum cases
- Convert ComponentDecodeOptions constants to enum cases
- Convert BuildConfigurationValues constants to enum cases
- Convert BuildConfigurationOptions constants to enum cases
- Convert CompressionOptions constants to enum cases
- Convert PackageFlags constants to enum cases
- Convert NccBuildFlags constants to enum cases
- Convert ComponentFlags constants to enum cases
- Refactor flag handling to use PackageFlags enum directly
- Refactor checkLogLevel to correctly utilize LogLevel cases
- Refactor code to improve readability in Resolver.php
- Update PHP include paths in project configuration
- Refactor logging level checks to use LogLevel enum directly
- Refactor log level parsing with enum method
- Refactor log level checking to enum method
- Updated Symfony/Filesystem from version 6.3.1 to 7.1.2
- Refactor ProjectType handling
- Validate and enforce repository type enum usage
- Updated Composer/Semver to 3.4.3
- Rename 'semver' directory to 'Semver' in composer package
- Refactor project constants handling in NccCompiler
- Updated Symfony/Yaml to version 7.1.4
- Updated Symfony/Uid to version 7.1.4
- Updated Symfony/Process to version 7.1.3
- Updated Symfony/polyfill-ctype to version 1.31.0
- Updated Symfony/polyfill-mbstring to version 1.31.0
- Updated Symfony/polyfill-uuid to version 1.31.0
- Updated nikic/PhpParser to version 5.2.0
### Fixed
- Fixed Division by zero in PackageManager
- Fixed runner argument passing for ExecCommand
### Removed
- Removed EncoderType enum file, unused.
- Removed PackageStandardVersions.php
- Removed ConstantReferences.php
- Removed HttpStatusCodes.php
- Removed CompilerExtensionDefaultVersions.php
- Removed RemoteSourceType
- Removed DependencySourceType
- Removed BuiltinRemoteSourceType
- Removed RuntimeImportOptions
- Remove ComponentFileExtensions enum
- Remove unused import and redundant scope validation method
## [2.0.3] - 2023-10-17
This update includes enhanced support for PHP statements in AST traversal, a friendly CLI Progress Bar, and fixes
related to package version searching, ncc's extension registration, and error handling in PackageManagerMenu.
The changes improve the system's efficiency, error resilience, and user experience.
### Added
- Implemented support in the AST traversal for the PHP statements `include`, `include_once`, `require`, and
`require_once`. These statements are transformed into function calls. With this change, ncc can correctly handle and
import files from system packages or direct binary package files.
- Added new `ConsoleProgressBar` class for UI improvement, imrpoved the CLI Progress Bar inspired by
[pacman](https://wiki.archlinux.org/title/pacman)
### Fixed
- When finding package versions in the package lock, ncc will try to find a satisfying version rather than the exact
version, this is to prevent[CHANGELOG.md](CHANGELOG.md) errors when the package lock contains a version that is not available in the repository.
- Fixed issue when registering ncc's extension, when using the INSTALLER, the installation path used in the process
appears to be incorrect, added a optional parameter to the `registerExtension` method to allow the installer to pass
the correct installation path.
- Add error handling for unspecified package in PackageManagerMenu
## [2.0.2] - 2023-10-13
In this new update, the software introduces a feature for importing static packages without extra dependencies and

View file

@ -18,23 +18,23 @@ DEBIAN_PACKAGE_BUILD_PATH := $(BUILD_PATH)/ncc_$(BUILD_VERSION)_all.deb
# List of paths for autoloading
AUTOLOAD_PATHS := $(addprefix $(SRC_PATH)/ncc/ThirdParty/, \
composer/Semver \
defuse/php-encryption \
jelix/version \
nikic/PhpParser \
Symfony/polyfill_ctype \
Symfony/polyfill_mbstring \
Symfony/polyfill_uuid \
Symfony/Process \
Symfony/Uid \
Symfony/Filesystem \
Symfony/Yaml \
theseer/DirectoryScanner \
composer/semver \
defuse/php-encryption \
jelix/version \
nikic/PhpParser \
Symfony/polyfill_ctype \
Symfony/polyfill_mbstring \
Symfony/polyfill_uuid \
Symfony/Process \
Symfony/Uid \
Symfony/Filesystem \
Symfony/Yaml \
theseer/DirectoryScanner \
)
# Check for necessary binaries
ifndef PHPCC
$(error "PHP binary not found. Please install PHP or check your PATH")
$(error "PHP binary not found. Please install PHP or check your PATH")
endif
# Check if phpab is installed
@ -153,13 +153,13 @@ clean:
.PHONY: help
help:
@echo "Available commands:"
@echo " make autoload - Generate autoload files"
@echo " make redist - Prepare the project for redistribution"
@echo " make install - Installs ncc on the system (requires root privileges & php)"
@echo " make tar - Package the project into a tarball (Generic installer, requires php)"
@echo " make deb - Package the project into a Debian package"
@echo " make docker-debian - Build a Debian Docker image"
@echo " make autoload - Generate autoload files"
@echo " make redist - Prepare the project for redistribution"
@echo " make install - Installs ncc on the system (requires root privileges & php)"
@echo " make tar - Package the project into a tarball (Generic installer, requires php)"
@echo " make deb - Package the project into a Debian package"
@echo " make docker-debian - Build a Debian Docker image"
@echo " make docker-debian-run - Run the Debian Docker image"
@echo " make docker-alpine - Build an Alpine Docker image"
@echo " make docker-alpine - Build an Alpine Docker image"
@echo " make docker-alpine-run - Run the Alpine Docker image"
@echo " make clean - Clean the build artifacts"
@echo " make clean - Clean the build artifacts"

View file

@ -1,9 +0,0 @@
<?php
$autoload_path = __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'ncc' . DIRECTORY_SEPARATOR . 'autoload.php';
if(!file_exists($autoload_path))
{
throw new Exception("Autoload file not found");
}
require $autoload_path;

View file

@ -1,11 +0,0 @@
<phpunit bootstrap="bootstrap.php">
<testsuites>
<testsuite name="ncc Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<ini name="error_reporting" value="-1"/>
<server name="KERNEL_DIR" value="app/"/>
</php>
</phpunit>

View file

@ -13,7 +13,7 @@
$third_party_path = __DIR__ . DIRECTORY_SEPARATOR . 'ThirdParty' . DIRECTORY_SEPARATOR;
$target_files = [
__DIR__ . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'composer' . DIRECTORY_SEPARATOR . 'Semver' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'composer' . DIRECTORY_SEPARATOR . 'semver' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'defuse' . DIRECTORY_SEPARATOR . 'php-encryption' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'jelix' . DIRECTORY_SEPARATOR . 'version' . DIRECTORY_SEPARATOR . 'autoload_spl.php',
$third_party_path . 'nikic' . DIRECTORY_SEPARATOR . 'PhpParser' . DIRECTORY_SEPARATOR . 'autoload_spl.php',

View file

@ -2,7 +2,7 @@ Package: ncc
Source: ncc
Section: devel
Priority: optional
Version: 2.0.4
Version: 2.0.2
Maintainer: netkas <netkas@nosial.net>
Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.5.1

View file

@ -242,6 +242,23 @@
$NCC_FILESYSTEM->mkdir($NCC_INSTALL_PATH, 0755);
try
{
if(is_file(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json'))
{
Functions::initializeFiles(Functions::loadJsonFile(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json', Functions::FORCE_ARRAY));
}
else
{
Functions::initializeFiles();
}
}
catch(Exception $e)
{
Console::outException('Cannot initialize NCC files, ' . $e->getMessage(), $e, 1);
return;
}
// Copy files to the installation path
try
{
@ -255,12 +272,10 @@
}
$total_items = count($build_files);
//$processed_items = 1;
$progress_bar = new \ncc\Utilities\ConsoleProgressBar('Installing ncc', $total_items);
$processed_items = 1;
foreach ($build_files as $item)
{
$progress_bar->setMiscText($item, true);
$source = __DIR__ . DIRECTORY_SEPARATOR . $item;
$destination = $NCC_INSTALL_PATH . DIRECTORY_SEPARATOR . $item;
@ -283,30 +298,8 @@
}
}
//++$processed_items;
//Console::inlineProgressBar($processed_items, $total_items);
$progress_bar->increaseValue(1, true);
}
$progress_bar->setMiscText('done', true);
unset($progress_bar);
// Initialize ncc's files
try
{
if(is_file(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json'))
{
Functions::initializeFiles($NCC_INSTALL_PATH, Functions::loadJsonFile(__DIR__ . DIRECTORY_SEPARATOR . 'default_repositories.json', Functions::FORCE_ARRAY));
}
else
{
Functions::initializeFiles($NCC_INSTALL_PATH);
}
}
catch(Exception $e)
{
Console::outException('Cannot initialize NCC files, ' . $e->getMessage(), $e, 1);
return;
++$processed_items;
Console::inlineProgressBar($processed_items, $total_items);
}

View file

@ -75,7 +75,7 @@
if($output_path !== null)
{
$options[BuildConfigurationOptions::OUTPUT_FILE->value] = $output_path;
$options[BuildConfigurationOptions::OUTPUT_FILE] = $output_path;
}
// Load the project
@ -92,7 +92,7 @@
// Build the project
try
{
$build_configuration = $args['config'] ?? $args['c'] ?? BuildConfigurationValues::DEFAULT->value;
$build_configuration = $args['config'] ?? $args['c'] ?? BuildConfigurationValues::DEFAULT;
$output = $project_manager->build($build_configuration, $options);
}
catch (Exception $e)

View file

@ -24,11 +24,9 @@
use Exception;
use ncc\Classes\Runtime;
use ncc\CLI\Main;
use ncc\Objects\CliHelpSection;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
use ncc\Utilities\Resolver;
class ExecCommand
{
@ -42,12 +40,6 @@
{
$package = $args['package'] ?? null;
$version = $args['exec-version'] ?? 'latest';
$program_arguments = [];
if(isset($args['exec-args']))
{
$program_arguments = Resolver::splitArguments(Main::getRawArgs(), '--exec-args');
}
if($package === null)
{
@ -66,7 +58,7 @@
try
{
return Runtime::execute($package_name, $program_arguments);
return Runtime::execute($package_name);
}
catch(Exception $e)
{

View file

@ -58,7 +58,7 @@
try
{
Functions::initializeFiles(null, $default_repositories);
Functions::initializeFiles($default_repositories);
}
catch(Exception $e)
{

View file

@ -50,12 +50,7 @@
private static $args;
/**
* @var array
*/
private static $raw_args;
/**
* @var LogLevel|null
* @var string|null
*/
private static $log_level;
@ -68,7 +63,6 @@
public static function start(array $argv): int
{
self::$args = Resolver::parseArguments(implode(' ', $argv));
self::$raw_args = $argv;
if(!isset(self::$args['ncc-cli']))
{
@ -97,14 +91,30 @@
if(isset(self::$args['l']) || isset(self::$args['log-level']))
{
self::$log_level = LogLevel::fromOrDefault(strtolower(self::$args['l'] ?? self::$args['log-level']));
switch(strtolower(self::$args['l'] ?? self::$args['log-level']))
{
case LogLevel::SILENT:
case LogLevel::FATAL:
case LogLevel::ERROR:
case LogLevel::WARNING:
case LogLevel::INFO:
case LogLevel::DEBUG:
case LogLevel::VERBOSE:
self::$log_level = strtolower(self::$args['l'] ?? self::$args['log-level']);
break;
default:
Console::outWarning('Unknown log level: ' . (self::$args['l'] ?? self::$args['log-level']) . ', using \'info\'');
self::$log_level = LogLevel::INFO;
break;
}
}
else
{
self::$log_level = LogLevel::INFO;
}
if(self::$log_level->checkLogLevel(LogLevel::DEBUG))
if(Resolver::checkLogLevel(self::$log_level, LogLevel::DEBUG))
{
Console::outDebug('Debug logging enabled');
@ -115,12 +125,12 @@
Console::outDebug(sprintf('args: %s', json_encode(self::$args, JSON_UNESCAPED_SLASHES)));
}
if(in_array(NccBuildFlags::UNSTABLE->value, NCC_VERSION_FLAGS, true))
if(in_array(NccBuildFlags::UNSTABLE, NCC_VERSION_FLAGS, true))
{
Console::outWarning('This is an unstable build of ncc, expect some features to not work as expected');
}
if(in_array(NccBuildFlags::BETA->value, NCC_VERSION_FLAGS, true))
if(in_array(NccBuildFlags::BETA, NCC_VERSION_FLAGS, true))
{
Console::outWarning('This is a beta build of ncc, expect some features to not work as expected');
}
@ -220,19 +230,9 @@
}
/**
* Returns the raw arguments passed to ncc
*
* @return array
* @return string
*/
public static function getRawArgs(): array
{
return self::$raw_args;
}
/**
* @return LogLevel
*/
public static function getLogLevel(): LogLevel
public static function getLogLevel(): string
{
if(self::$log_level === null)
{

View file

@ -101,7 +101,7 @@
if(isset($args['v']))
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('Insufficient permissions, cannot modify configuration values', true, 1);
return 1;

View file

@ -187,7 +187,7 @@
{
$ResolvedScope = Resolver::resolveScope();
if($ResolvedScope !== Scopes::SYSTEM->value)
if($ResolvedScope !== Scopes::SYSTEM)
{
Console::outError('Insufficient permissions to add entries');
}
@ -313,7 +313,7 @@
{
$ResolvedScope = Resolver::resolveScope();
if($ResolvedScope !== Scopes::SYSTEM->value)
if($ResolvedScope !== Scopes::SYSTEM)
{
Console::outError('Insufficient permissions to remove entries');
}

View file

@ -132,7 +132,7 @@
*/
private static function installPackage(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('You cannot install packages in a user scope, please run this command as root', true, 1);
return 1;
@ -145,32 +145,21 @@
$repository_manager = new RepositoryManager();
$package_manager = new PackageManager();
if($package === null)
{
Console::outError('No package specified', true, 1);
return 1;
}
$options = [];
if(isset($args['reinstall']))
{
$options[InstallPackageOptions::REINSTALL->value] = true;
$options[InstallPackageOptions::REINSTALL] = true;
}
if(isset($args['prefer-static']) || isset($args['static']))
{
$options[InstallPackageOptions::PREFER_STATIC->value] = true;
$options[InstallPackageOptions::PREFER_STATIC] = true;
}
if(isset($args['skip-dependencies']))
{
$options[InstallPackageOptions::SKIP_DEPENDENCIES->value] = true;
}
if(isset($args['build-source']))
{
$options[InstallPackageOptions::BUILD_SOURCE->value] = true;
$options[InstallPackageOptions::SKIP_DEPENDENCIES] = true;
}
if($authentication !== null)
@ -204,7 +193,7 @@
$authentication_entry = $entry->getPassword();
}
if(preg_match(RegexPatterns::REMOTE_PACKAGE->value, $package) === 1)
if(preg_match(RegexPatterns::REMOTE_PACKAGE, $package) === 1)
{
$package_input = RemotePackageInput::fromString($package);
@ -393,7 +382,7 @@
*/
private static function uninstallPackage($args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('You cannot uninstall packages in a user scope, please run this command as root', true, 1);
return 1;
@ -424,7 +413,7 @@
*/
private static function uninstallAllPackages(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('You cannot uninstall all packages in a user scope, please run this command as root', true, 1);
return 1;
@ -460,7 +449,7 @@
*/
private static function fixBrokenPackages(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('You cannot fix broken packages in a user scope, please run this command as root', true, 1);
return 1;
@ -565,7 +554,6 @@
new CliHelpSection(['install', '-p', '--skip-dependencies'], 'Installs a specified ncc package but skips the installation of dependencies'),
new CliHelpSection(['install', '-p', '--reinstall'], 'Installs a specified ncc package, reinstall if already installed'),
new CliHelpSection(['install', '--prefer-static', '--static'], 'Installs a static version of the package from the remote repository if available'),
new CliHelpSection(['install', '--build-source'], 'Forces ncc to build the packages from source rather than trying to use a pre-built binary'),
new CliHelpSection(['uninstall', '--package', '-p'], 'Uninstalls a specified ncc package'),
new CliHelpSection(['uninstall', '--package', '-p', '--version', '-v'], 'Uninstalls a specified ncc package version'),
new CliHelpSection(['uninstall-all'], 'Uninstalls all packages'),

View file

@ -23,7 +23,6 @@
namespace ncc\CLI\Management;
use Exception;
use ncc\Enums\CompilerExtensions;
use ncc\Enums\ProjectTemplates;
use ncc\Enums\Scopes;
use ncc\Managers\CredentialManager;
@ -103,12 +102,7 @@
if(isset($args['ext']))
{
$compiler_extension = CompilerExtensions::tryFrom($args['ext']);
if($compiler_extension === null)
{
Console::outError('Invalid compiler extension, please specify a valid compiler extension', true, 1);
return 1;
}
$compiler_extension = $args['ext'];
}
else
{
@ -140,7 +134,7 @@
*/
private static function installProject(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('You cannot install packages in a user scope, please run this command as root', true, 1);
return 1;
@ -298,9 +292,9 @@
}
Console::out(PHP_EOL . 'Available Templates:');
foreach(ProjectTemplates::cases() as $template)
foreach(ProjectTemplates::ALL as $template)
{
Console::out(' ' . $template->value);
Console::out(' ' . $template);
}
return 0;

View file

@ -25,7 +25,6 @@
use Exception;
use ncc\Enums\ConsoleColors;
use ncc\Enums\Scopes;
use ncc\Enums\Types\RepositoryType;
use ncc\Managers\RepositoryManager;
use ncc\Objects\CliHelpSection;
use ncc\Objects\RepositoryConfiguration;
@ -119,7 +118,7 @@
$output = sprintf('%s (%s) [%s]',
$source->getName(),
Console::formatColor($source->getHost(), ConsoleColors::GREEN),
Console::formatColor($source->getType()->value, ConsoleColors::YELLOW)
Console::formatColor($source->getType(), ConsoleColors::YELLOW)
);
if(!$source->isSsl())
@ -142,7 +141,7 @@
*/
private static function addEntry(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('You must be running as root to add a new repository', true, 1);
return 1;
@ -165,13 +164,6 @@
return 1;
}
$parsed_type = RepositoryType::tryFrom($type);
if($parsed_type === null)
{
Console::outError(sprintf('Unknown repository type \'%s\'.', $type), true, 1);
return 1;
}
if($host === null)
{
Console::outError(sprintf('Missing required argument \'%s\'.', 'host'), true, 1);
@ -180,7 +172,7 @@
try
{
(new RepositoryManager())->addRepository(new RepositoryConfiguration($name, $host, $parsed_type, $ssl));
(new RepositoryManager())->addRepository(new RepositoryConfiguration($name, $host, $type, $ssl));
}
catch(Exception $e)
{
@ -238,7 +230,7 @@
*/
private static function removeEntry(array $args): int
{
if(Resolver::resolveScope() !== Scopes::SYSTEM->value)
if(Resolver::resolveScope() !== Scopes::SYSTEM)
{
Console::outError('You must be running as root to remove a repository', true, 1);
return 1;

View file

@ -31,7 +31,6 @@
use ncc\Classes\PhpExtension\PhpRunner;
use ncc\Enums\Runners;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException;
use ncc\Exceptions\OperationException;
@ -55,11 +54,11 @@
{
$bin = match($unit->getExecutionPolicy()->getRunner())
{
Runners::PHP->value => (new ExecutableFinder())->find('php'),
Runners::BASH->value => (new ExecutableFinder())->find('bash'),
Runners::PYTHON->value => (new ExecutableFinder())->find('python'),
Runners::LUA->value => (new ExecutableFinder())->find('lua'),
Runners::PERL->value => (new ExecutableFinder())->find('perl'),
Runners::PHP => (new ExecutableFinder())->find('php'),
Runners::BASH => (new ExecutableFinder())->find('bash'),
Runners::PYTHON => (new ExecutableFinder())->find('python'),
Runners::LUA => (new ExecutableFinder())->find('lua'),
Runners::PERL => (new ExecutableFinder())->find('perl'),
default => throw new NotSupportedException(sprintf('The execution policy %s is not supported because it uses the %s runner', $unit->getExecutionPolicy()->getName(), $unit->getExecutionPolicy()->getRunner()))
};
@ -77,19 +76,11 @@
{
$process->setTimeout($unit->getExecutionPolicy()->getExecute()->getTimeout());
}
else
{
$process->setTimeout(null);
}
if($unit->getExecutionPolicy()->getExecute()->getIdleTimeout() !== null)
{
$process->setIdleTimeout($unit->getExecutionPolicy()->getExecute()->getIdleTimeout());
}
else
{
$process->setIdleTimeout(null);
}
return $process;
}
@ -118,8 +109,8 @@
$execution_unit = ExecutionUnit::fromArray(ZiProto::decode(IO::fread($unit_path)));
return match ($execution_unit->getExecutionPolicy()->getRunner())
{
Runners::PHP->value => PhpRunner::executeUnit($execution_unit, $args),
Runners::BASH->value => BashRunner::executeUnit($execution_unit, $args),
Runners::PHP => PhpRunner::executeUnit($execution_unit, $args),
Runners::BASH => BashRunner::executeUnit($execution_unit, $args),
default => throw new NotSupportedException(sprintf('The execution policy %s is not supported because it uses the %s runner', $execution_unit->getExecutionPolicy()->getName(), $execution_unit->getExecutionPolicy()->getRunner())),
};
}
@ -138,7 +129,6 @@
* @return int
* @throws ConfigurationException
* @throws OperationException
* @throws IntegrityException
*/
public static function executeFromPackage(PackageReader $package_reader, string $policy_name, array $args=[]): int
{
@ -148,8 +138,8 @@
{
return match ($execution_unit->getExecutionPolicy()->getRunner())
{
Runners::PHP->value => PhpRunner::executeUnit($execution_unit, $args, false),
Runners::BASH->value => BashRunner::executeUnit($execution_unit, $args),
Runners::PHP => PhpRunner::executeUnit($execution_unit, $args, false),
Runners::BASH => BashRunner::executeUnit($execution_unit, $args),
default => throw new NotSupportedException(sprintf('The execution policy %s is not supported because it uses the %s runner', $execution_unit->getExecutionPolicy()->getName(), $execution_unit->getExecutionPolicy()->getRunner())),
};
}

View file

@ -39,7 +39,6 @@
use ncc\Objects\Vault\Password\AccessToken;
use ncc\Objects\Vault\Password\UsernamePassword;
use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use RuntimeException;
@ -48,7 +47,7 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
try
{
@ -65,7 +64,7 @@
/**
* @inheritDoc
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
}
@ -98,21 +97,15 @@
'User-Agent: ncc'
];
if($authentication !== null)
{
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -169,7 +162,7 @@
*/
private static function getTagArchive(RepositoryConfiguration $repository, string $group, string $project, string $tag, ?AuthenticationInterface $authentication=null): RepositoryResult
{
if($tag === Versions::LATEST->value)
if($tag === Versions::LATEST)
{
$tag = self::getLatestTag($repository, $group, $project, $authentication);
}
@ -193,17 +186,10 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -212,11 +198,11 @@
if(isset($response['zipball_url']))
{
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE->value, $tag);
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE, $tag);
}
elseif(isset($response['tarball_url']))
{
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE->value, $tag);
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE, $tag);
}
else
{
@ -260,17 +246,10 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -328,7 +307,7 @@
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST->value)
if($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -358,17 +337,10 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -383,7 +355,7 @@
$release, $group, $project));
}
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC]);
$preferred_asset = null;
$fallback_asset = null;
@ -407,7 +379,7 @@
if($asset_url)
{
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE, $release);
RuntimeCache::set($endpoint, $result);
return $result;
@ -437,7 +409,7 @@
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if ($release === Versions::LATEST->value)
if ($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -461,17 +433,10 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -480,11 +445,11 @@
if(isset($response['zipball_url']))
{
$results = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE->value, $release);
$results = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE, $release);
}
elseif(isset($response['tarball_url']))
{
$results = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE->value, $release);
$results = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE, $release);
}
else
{
@ -515,7 +480,7 @@
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()->value));
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()));
case AuthenticationType::USERNAME_PASSWORD:
if($authentication instanceof UsernamePassword)
@ -524,7 +489,7 @@
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()->value));
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()));
}
return $headers;

View file

@ -47,7 +47,7 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
try
{
@ -64,7 +64,7 @@
/**
* @inheritDoc
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST->value, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
}
@ -104,7 +104,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -161,7 +161,7 @@
*/
private static function getTagArchive(RepositoryConfiguration $repository, string $group, string $project, string $tag, ?AuthenticationInterface $authentication = null): RepositoryResult
{
if($tag === Versions::LATEST->value)
if($tag === Versions::LATEST)
{
$tag = self::getLatestTag($repository, $group, $project, $authentication);
}
@ -186,7 +186,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true
]);
@ -207,7 +207,7 @@
throw new NetworkException(sprintf('Server responded with HTTP code %s when getting tag archive for %s/%s/%s', $http_code, $group, $project, $tag));
}
$result = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE->value, $tag);
$result = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE, $tag);
curl_close($curl);
RuntimeCache::set($endpoint, $result);
@ -249,7 +249,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -307,7 +307,7 @@
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST->value)
if($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -331,7 +331,7 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
curl_setopt_array($curl, [CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, CURLOPT_HTTPHEADER => $headers]);
curl_setopt_array($curl, [CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET, CURLOPT_HTTPHEADER => $headers]);
Console::outDebug(sprintf('Fetching release package for %s/%s/%s from %s', $group, $project, $release, $endpoint));
$response = self::processHttpResponse($curl, $group, $project);
@ -341,7 +341,7 @@
throw new NetworkException(sprintf('Failed to get release package for %s/%s/%s: No assets found', $group, $project, $release));
}
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC]);
$preferred_asset = null;
$fallback_asset = null;
@ -363,7 +363,7 @@
{
$asset_url = $target_asset['browser_download_url'];
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE, $release);
RuntimeCache::set($endpoint, $result);
return $result;
@ -389,7 +389,7 @@
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication = null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST->value)
if($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -415,7 +415,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -425,11 +425,11 @@
if(isset($response['zipball_url']))
{
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE->value, $release);
$result = new RepositoryResult($response['zipball_url'], RepositoryResultType::SOURCE, $release);
}
elseif(isset($response['tarball_url']))
{
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE->value, $release);
$result = new RepositoryResult($response['tarball_url'], RepositoryResultType::SOURCE, $release);
}
else
{
@ -459,7 +459,7 @@
$headers[] = 'Authorization: Bearer ' . $authentication->getAccessToken();
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()->value));
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()));
case AuthenticationType::USERNAME_PASSWORD:
if($authentication instanceof UsernamePassword)
@ -468,7 +468,7 @@
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()->value));
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()));
}
return $headers;

View file

@ -39,7 +39,6 @@
use ncc\Objects\Vault\Password\AccessToken;
use ncc\Objects\Vault\Password\UsernamePassword;
use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use RuntimeException;
@ -48,7 +47,7 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
try
{
@ -65,7 +64,7 @@
/**
* @inheritDoc
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST->value, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version=Versions::LATEST, ?AuthenticationType $authentication=null, array $options=[]): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
}
@ -104,17 +103,10 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_URL => $endpoint,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -172,7 +164,7 @@
*/
private static function getTagArchive(RepositoryConfiguration $repository, string $group, string $project, string $tag, ?AuthenticationInterface $authentication=null): RepositoryResult
{
if($tag === Versions::LATEST->value)
if($tag === Versions::LATEST)
{
$tag = self::getLatestTag($repository, $group, $project, $authentication);
}
@ -195,17 +187,10 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true
]);
@ -225,7 +210,7 @@
throw new NetworkException(sprintf('Server responded with HTTP code %s when getting tag archive for %s/%s/%s', $http_code, $group, $project, $tag));
}
$results = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE->value, $tag);
$results = new RepositoryResult(curl_getinfo($curl, CURLINFO_EFFECTIVE_URL), RepositoryResultType::SOURCE, $tag);
RuntimeCache::set($endpoint, $results);
return $results;
@ -265,16 +250,9 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -330,7 +308,7 @@
*/
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
{
if($release === Versions::LATEST->value)
if($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -355,21 +333,14 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
$response = self::processHttpResponse($curl, $group, $project);
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC]);
$preferred_asset = null;
$fallback_asset = null;
@ -393,7 +364,7 @@
if ($asset_url)
{
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE, $release);
RuntimeCache::set($endpoint, $result);
return $result;
@ -422,7 +393,7 @@
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST->value)
if($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
@ -447,16 +418,9 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -476,11 +440,11 @@
if($asset['format'] === 'zip')
{
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE->value, $release);
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE, $release);
}
elseif($asset['format'] === 'tar')
{
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE->value, $release);
$results = new RepositoryResult($asset['url'], RepositoryResultType::SOURCE, $release);
}
else
{
@ -507,23 +471,23 @@
{
switch($authentication->getAuthenticationType())
{
case AuthenticationType::ACCESS_TOKEN->value:
case AuthenticationType::ACCESS_TOKEN:
if($authentication instanceof AccessToken)
{
$headers[] = 'Private-Token: ' . $authentication->getAccessToken();
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()->value));
throw new AuthenticationException(sprintf('Invalid authentication type for Access Token, got %s instead', $authentication->getAuthenticationType()));
case AuthenticationType::USERNAME_PASSWORD->value:
case AuthenticationType::USERNAME_PASSWORD:
if($authentication instanceof UsernamePassword)
{
curl_setopt($curl, CURLOPT_USERPWD, $authentication->getUsername() . ':' . $authentication->getPassword());
break;
}
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()->value));
throw new AuthenticationException(sprintf('Invalid authentication type for Username/Password, got %s instead', $authentication->getAuthenticationType()));
}
return $headers;

View file

@ -22,10 +22,8 @@
namespace ncc\Classes\NccExtension;
use InvalidArgumentException;
use ncc\Enums\SpecialConstants\BuildConstants;
use ncc\Enums\SpecialConstants\DateTimeConstants;
use ncc\Enums\SpecialConstants\GeneralConstants;
use ncc\Enums\SpecialConstants\InstallConstants;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\SpecialConstants\RuntimeConstants;
@ -49,67 +47,6 @@
$input = self::compileBuildConstants($input);
$input = self::compileDateTimeConstants($input, time());
$input = self::compileRuntimeConstants($input);
$input = self::compileGeneralConstants($input, $project_configuration);
return $input;
}
/**
* Compiles general constants from the given input string based on the provided project configuration.
*
* @param string|null $input The input string containing constants to be compiled.
* @param ProjectConfiguration $project_configuration The project configuration used to resolve constants.
* @return string|null The input string with constants replaced, or null if the input was null.
*/
public static function compileGeneralConstants(?string $input, ProjectConfiguration $project_configuration): ?string
{
if ($input === null)
{
return null;
}
// Replace %DEFAULT_BUILD_CONFIGURATION%
$input = str_replace(
[
GeneralConstants::DEFAULT_BUILD_CONFIGURATION->value
],
[
$project_configuration->getBuild()->getDefaultConfiguration()
],
$input
);
if (str_starts_with($input, GeneralConstants::BUILD_OUTPUT_PATH->value))
{
$build_name = null;
if (preg_match('/' . preg_quote(GeneralConstants::BUILD_OUTPUT_PATH->value, '/') . ':(\S+)/', $input, $matches))
{
$build_name = $matches[1];
}
if ($build_name === null)
{
Console::outWarning(sprintf("Cannot compile constant %s because it's not valid, usage: %%CONSTANT%%:<name>", $input));
}
else
{
try
{
$output_path = $project_configuration->getBuild()->getBuildConfiguration($build_name)->getOutput();
$input = preg_replace(
'/' . preg_quote(GeneralConstants::BUILD_OUTPUT_PATH->value, '/') . ':\S+/',
$output_path,
$input,
1
);
}
catch (InvalidArgumentException $e)
{
Console::outError(sprintf("Cannot compile constant %s because it does not point to an existing build configuration name", $input));
}
}
}
return $input;
}
@ -130,10 +67,10 @@
$input = str_replace(
[
AssemblyConstants::ASSEMBLY_NAME->value,
AssemblyConstants::ASSEMBLY_PACKAGE->value,
AssemblyConstants::ASSEMBLY_VERSION->value,
AssemblyConstants::ASSEMBLY_UID->value,
AssemblyConstants::ASSEMBLY_NAME,
AssemblyConstants::ASSEMBLY_PACKAGE,
AssemblyConstants::ASSEMBLY_VERSION,
AssemblyConstants::ASSEMBLY_UID
],
[
$assembly->getName(),
@ -144,27 +81,27 @@
if($assembly->getDescription() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_DESCRIPTION->value, $assembly->getDescription(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_DESCRIPTION, $assembly->getDescription(), $input);
}
if($assembly->getCompany() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_COMPANY->value, $assembly->getCompany(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_COMPANY, $assembly->getCompany(), $input);
}
if($assembly->getProduct() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_PRODUCT->value, $assembly->getProduct(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_PRODUCT, $assembly->getProduct(), $input);
}
if($assembly->getCopyright() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_COPYRIGHT->value, $assembly->getCopyright(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_COPYRIGHT, $assembly->getCopyright(), $input);
}
if($assembly->getTrademark() !== null)
{
$input = str_replace(AssemblyConstants::ASSEMBLY_TRADEMARK->value, $assembly->getTrademark(), $input);
$input = str_replace(AssemblyConstants::ASSEMBLY_TRADEMARK, $assembly->getTrademark(), $input);
}
return $input;
}
@ -184,10 +121,10 @@
return str_replace(
[
BuildConstants::COMPILE_TIMESTAMP->value,
BuildConstants::NCC_BUILD_VERSION->value,
BuildConstants::NCC_BUILD_FLAGS->value,
BuildConstants::NCC_BUILD_BRANCH->value
BuildConstants::COMPILE_TIMESTAMP,
BuildConstants::NCC_BUILD_VERSION,
BuildConstants::NCC_BUILD_FLAGS,
BuildConstants::NCC_BUILD_BRANCH
],
[
time(),
@ -213,10 +150,10 @@
return str_replace(
[
InstallConstants::INSTALL_PATH->value,
InstallConstants::INSTALL_PATH_BIN->value,
InstallConstants::INSTALL_PATH_SRC->value,
InstallConstants::INSTALL_PATH_DATA->value
InstallConstants::INSTALL_PATH,
InstallConstants::INSTALL_PATH_BIN,
InstallConstants::INSTALL_PATH_SRC,
InstallConstants::INSTALL_PATH_DATA
],
[
$installation_paths->getInstallationpath(),
@ -241,36 +178,36 @@
}
return str_replace([
DateTimeConstants::d->value,
DateTimeConstants::D->value,
DateTimeConstants::j->value,
DateTimeConstants::l->value,
DateTimeConstants::N->value,
DateTimeConstants::S->value,
DateTimeConstants::w->value,
DateTimeConstants::z->value,
DateTimeConstants::W->value,
DateTimeConstants::F->value,
DateTimeConstants::m->value,
DateTimeConstants::M->value,
DateTimeConstants::n->value,
DateTimeConstants::t->value,
DateTimeConstants::L->value,
DateTimeConstants::o->value,
DateTimeConstants::Y->value,
DateTimeConstants::y->value,
DateTimeConstants::a->value,
DateTimeConstants::A->value,
DateTimeConstants::B->value,
DateTimeConstants::g->value,
DateTimeConstants::G->value,
DateTimeConstants::h->value,
DateTimeConstants::H->value,
DateTimeConstants::i->value,
DateTimeConstants::s->value,
DateTimeConstants::c->value,
DateTimeConstants::r->value,
DateTimeConstants::u->value
DateTimeConstants::d,
DateTimeConstants::D,
DateTimeConstants::j,
DateTimeConstants::l,
DateTimeConstants::N,
DateTimeConstants::S,
DateTimeConstants::w,
DateTimeConstants::z,
DateTimeConstants::W,
DateTimeConstants::F,
DateTimeConstants::m,
DateTimeConstants::M,
DateTimeConstants::n,
DateTimeConstants::t,
DateTimeConstants::L,
DateTimeConstants::o,
DateTimeConstants::Y,
DateTimeConstants::y,
DateTimeConstants::a,
DateTimeConstants::A,
DateTimeConstants::B,
DateTimeConstants::g,
DateTimeConstants::G,
DateTimeConstants::h,
DateTimeConstants::H,
DateTimeConstants::i,
DateTimeConstants::s,
DateTimeConstants::c,
DateTimeConstants::r,
DateTimeConstants::u
],
[
date('d', $timestamp),
@ -320,7 +257,7 @@
if(function_exists('getcwd'))
{
$input = str_replace(RuntimeConstants::CWD->value, getcwd(), $input);
$input = str_replace(RuntimeConstants::CWD, getcwd(), $input);
}
else
{
@ -329,7 +266,7 @@
if(function_exists('getmypid'))
{
$input = str_replace(RuntimeConstants::PID->value, getmypid(), $input);
$input = str_replace(RuntimeConstants::PID, getmypid(), $input);
}
else
{
@ -338,7 +275,7 @@
if(function_exists('getmyuid'))
{
$input = str_replace(RuntimeConstants::UID->value, getmyuid(), $input);
$input = str_replace(RuntimeConstants::UID, getmyuid(), $input);
}
else
{
@ -347,7 +284,7 @@
if(function_exists('getmygid'))
{
$input = str_replace(RuntimeConstants::GID->value, getmygid(), $input);
$input = str_replace(RuntimeConstants::GID, getmygid(), $input);
}
else
{
@ -356,7 +293,7 @@
if(function_exists('get_current_user'))
{
$input = str_replace(RuntimeConstants::USER->value, get_current_user(), $input);
$input = str_replace(RuntimeConstants::USER, get_current_user(), $input);
}
else
{

View file

@ -47,7 +47,6 @@
use ncc\Objects\ProjectConfiguration\Dependency;
use ncc\Utilities\Base64;
use ncc\Utilities\Console;
use ncc\Utilities\ConsoleProgressBar;
use ncc\Utilities\Functions;
use ncc\Utilities\IO;
use ncc\Utilities\Resolver;
@ -59,17 +58,11 @@
*/
private $project_manager;
/**
* @var array
*/
private $merged_dependencies;
/**
* @param ProjectManager $project_manager
*/
public function __construct(ProjectManager $project_manager)
{
$this->merged_dependencies = [];
$this->project_manager = $project_manager;
}
@ -93,17 +86,16 @@
* @throws PathNotFoundException
* @noinspection UnusedFunctionResultInspection
*/
public function build(string $build_configuration=BuildConfigurationValues::DEFAULT->value, array $options=[]): string
public function build(string $build_configuration=BuildConfigurationValues::DEFAULT, array $options=[]): string
{
$this->merged_dependencies = [];
$configuration = $this->project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
$configuration->setOptions(array_merge($configuration->getOptions(), $options));
$static_dependencies = isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES->value]);
$static_dependencies = isset($configuration->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES]);
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]))
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
{
$package_path = ConstantCompiler::compileConstants(
$this->project_manager->getProjectConfiguration(), $configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]
$this->project_manager->getProjectConfiguration(), $configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]
);
}
else
@ -111,15 +103,15 @@
$package_path = ConstantCompiler::compileConstants($this->project_manager->getProjectConfiguration(), $configuration->getOutput());
}
//$progress = 0;
$progress = 0;
$steps =
count($this->project_manager->getProjectConfiguration()->getExecutionPolicies()) +
count($this->project_manager->getComponents($build_configuration)) +
count($this->project_manager->getResources($build_configuration));
$progress_bar = new ConsoleProgressBar(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()), $steps);
$package_writer = $this->createPackageWriter($package_path, $configuration);
Console::outVerbose(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()));
Console::out(sprintf('Building project \'%s\'', $this->project_manager->getProjectConfiguration()->getAssembly()->getName()));
if($static_dependencies)
{
@ -129,7 +121,7 @@
}
// Debugging information
if(LogLevel::DEBUG->checkLogLevel(Main::getLogLevel()))
if(Resolver::checkLogLevel(LogLevel::DEBUG, Main::getLogLevel()))
{
foreach($this->project_manager->getProjectConfiguration()->getAssembly()->toArray() as $prop => $value)
{
@ -163,51 +155,39 @@
if(count($execution_units) === 0)
{
//$progress = count($this->project_manager->getProjectConfiguration()->getExecutionPolicies());
//Console::inlineProgressBar($progress, $steps);
$progress_bar->increaseValue(count($this->project_manager->getProjectConfiguration()->getExecutionPolicies()), true);
$progress = count($this->project_manager->getProjectConfiguration()->getExecutionPolicies());
Console::inlineProgressBar($progress, $steps);
Console::outWarning('The project contains execution policies but none of them are used');
}
foreach($execution_units as $unit)
{
$progress_bar->setMiscText(basename($unit->getExecutionPolicy()->getName()));
//$progress++;
//Console::inlineProgressBar($progress, $steps);
$progress++;
Console::inlineProgressBar($progress, $steps);
$package_writer->addExecutionUnit($unit);
$progress_bar->increaseValue(1, true);
}
}
// Compile package components
foreach($this->project_manager->getComponents($build_configuration) as $component)
{
//$progress++;
//Console::inlineProgressBar($progress, $steps);
$progress_bar->setMiscText(basename($component));
$progress++;
Console::inlineProgressBar($progress, $steps);
Console::outVerbose(sprintf('Compiling \'%s\'', $component));
$this->processComponent($package_writer, $component);
$progress_bar->increaseValue(1, true);
}
// Compile package resources
foreach($this->project_manager->getResources($build_configuration) as $resource)
{
//$progress++;
//Console::inlineProgressBar($progress, $steps);
$progress_bar->setMiscText(basename($resource));
$progress++;
Console::inlineProgressBar($progress, $steps);
Console::outVerbose(sprintf('Processing \'%s\'', $resource));
$this->processResource($package_writer, $resource);
$progress_bar->increaseValue(1, true);
}
$progress_bar->setMiscText('done', true);
unset($progress_bar);
Console::out(sprintf('Processing dependencies...'));
// Add the project dependencies
foreach($this->project_manager->getProjectConfiguration()->getBuild()->getDependencies() as $dependency)
{
@ -231,7 +211,6 @@
* @param Dependency $dependency
* @param bool $static
* @return void
* @throws ConfigurationException
* @throws IOException
*/
private function processDependency(PackageWriter $package_writer, Dependency $dependency, bool $static=false): void
@ -241,14 +220,13 @@
/** @noinspection UnusedFunctionResultInspection */
$package_writer->addDependencyConfiguration($dependency);
if(!$static || in_array($dependency->getName(), $this->merged_dependencies, true))
if(!$static)
{
return;
}
$entry = (new PackageManager())->getPackageLock()->getVersionEntry($dependency->getName(), $dependency->getVersion());
$package_writer->merge((new PackageReader($entry->getShadowPackagePath($dependency->getName()))));
$this->merged_dependencies[] = $dependency->getName();
foreach($entry->getDependencies() as $sub_dependency)
{
@ -269,25 +247,25 @@
{
$package_writer = new PackageWriter($path);
if(isset($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]))
if(isset($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION]))
{
$package_writer->addFlag(PackageFlags::COMPRESSION);
switch(strtolower($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]))
switch(strtolower($build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION]))
{
case BuildConfigurationOptions\CompressionOptions::HIGH->value:
case BuildConfigurationOptions\CompressionOptions::HIGH:
$package_writer->addFlag(PackageFlags::HIGH_COMPRESSION);
break;
case BuildConfigurationOptions\CompressionOptions::MEDIUM->value:
case BuildConfigurationOptions\CompressionOptions::MEDIUM:
$package_writer->addFlag(PackageFlags::MEDIUM_COMPRESSION);
break;
case BuildConfigurationOptions\CompressionOptions::LOW->value:
case BuildConfigurationOptions\CompressionOptions::LOW:
$package_writer->addFlag(PackageFlags::LOW_COMPRESSION);
break;
default:
throw new NotSupportedException(sprintf('The compression level \'%s\' is not supported', $build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]));
throw new NotSupportedException(sprintf('The compression level \'%s\' is not supported', $build_configuration->getOptions()[BuildConfigurationOptions::COMPRESSION]));
}
}
@ -335,38 +313,29 @@
* @param string $build_configuration
* @return void
*/
public function processMetadata(PackageWriter $package_writer, string $build_configuration=BuildConfigurationValues::DEFAULT->value): void
public function processMetadata(PackageWriter $package_writer, string $build_configuration=BuildConfigurationValues::DEFAULT): void
{
$metadata = new Metadata($this->project_manager->getProjectConfiguration()->getProject()->getCompiler());
$metadata->addOptions($this->project_manager->getProjectConfiguration()->getBuild()->getOptions($build_configuration));
$metadata->addOptions($this->project_manager->getProjectConfiguration()->getProject()->getOptions());
$metadata->addConstants($this->project_manager->getConstants($build_configuration));
$metadata->setUpdateSource($this->project_manager->getProjectConfiguration()->getProject()->getUpdateSource());
$metadata->setMainExecutionPolicy($this->project_manager->getProjectConfiguration()->getBuild()->getMain());
$metadata->setInstaller($this->project_manager->getProjectConfiguration()->getInstaller());
// Strip out 'output_file' build artifact.
if(isset($metadata->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]))
if(isset($metadata->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
{
$metadata->removeOption(BuildConfigurationOptions::OUTPUT_FILE->value);
$metadata->removeOption(BuildConfigurationOptions::OUTPUT_FILE);
}
// Strip out 'static' build artifact, PackageFlags::STATIC_DEPENDENCIES is used instead
// Making this option redundant.
if(isset($metadata->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES->value]))
if(isset($metadata->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES]))
{
$metadata->removeOption(BuildConfigurationOptions::STATIC_DEPENDENCIES->value);
$metadata->removeOption(BuildConfigurationOptions::STATIC_DEPENDENCIES);
}
$compiled_constants = [];
foreach($this->project_manager->getConstants() as $constant => $value)
{
$compiled_constants[$constant] = ConstantCompiler::compileConstants($this->project_manager->getProjectConfiguration(), $value);
}
$metadata->addConstants($compiled_constants);
/** @noinspection UnusedFunctionResultInspection */
$package_writer->setMetadata($metadata);
}

View file

@ -29,8 +29,8 @@
use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\PackageDirectory;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException;
use ncc\Objects\Package\Component;
use ncc\Objects\Package\ExecutionUnit;
use ncc\Objects\Package\Metadata;
@ -84,11 +84,6 @@
*/
private $package_file;
/**
* @var string
*/
private $package_path;
/**
* @var array
*/
@ -107,9 +102,7 @@
throw new IOException(sprintf('File \'%s\' does not exist', $file_path));
}
$this->package_path = $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));
@ -175,38 +168,27 @@
throw new IOException(sprintf('File \'%s\' is not a valid package file (corrupted header)', $file_path), $e);
}
if(!isset($this->headers[PackageStructure::FILE_VERSION->value]))
if(!isset($this->headers[PackageStructure::FILE_VERSION]))
{
throw new IOException(sprintf('File \'%s\' is not a valid package file (invalid header)', $file_path));
}
// Seek the data until the end of the package (FF AA 55 F0)
fseek($this->package_file, $this->data_offset);
$buffer = '';
while(!feof($this->package_file))
{
$current_chunk = fread($this->package_file, 1024);
$this->data_length += strlen($current_chunk);
$buffer .= $current_chunk;
$buffer = fread($this->package_file, 1024);
$this->data_length += strlen($buffer);
// If we detect the end-of-data byte sequence
if (($position = strpos($buffer, "\xFF\xAA\x55\xF0")) !== false)
{
$this->data_length -= strlen($buffer) - $position;
$this->package_length += $this->data_length + 4;
break;
}
// Check if the buffer is 1MB or larger
if(strlen($buffer) > 1048576)
{
// Remove the first 512kb of the buffer
$buffer = substr($buffer, 512000);
}
}
if($this->data_length === null || $this->data_length === 0)
if($this->data_length === null)
{
throw new IOException(sprintf('File \'%s\' is not a valid package file (missing end of package)', $file_path));
}
@ -231,7 +213,7 @@
*/
public function getFileVersion(): string
{
return $this->headers[PackageStructure::FILE_VERSION->value];
return $this->headers[PackageStructure::FILE_VERSION];
}
/**
@ -241,7 +223,7 @@
*/
public function getFlags(): array
{
return $this->headers[PackageStructure::FLAGS->value];
return $this->headers[PackageStructure::FLAGS];
}
/**
@ -252,7 +234,7 @@
*/
public function getFlag(string $name): bool
{
return in_array($name, $this->headers[PackageStructure::FLAGS->value], true);
return in_array($name, $this->headers[PackageStructure::FLAGS], true);
}
/**
@ -262,7 +244,7 @@
*/
public function getDirectory(): array
{
return $this->headers[PackageStructure::DIRECTORY->value];
return $this->headers[PackageStructure::DIRECTORY];
}
/**
@ -273,15 +255,15 @@
*/
public function get(string $name): string
{
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
if(!isset($this->headers[PackageStructure::DIRECTORY][$name]))
{
throw new RuntimeException(sprintf('File \'%s\' not found in package \'%s\'', $name, $this->package_path));
throw new RuntimeException(sprintf('File \'%s\' not found in package', $name));
}
$location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
$location = explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
fseek($this->package_file, ($this->data_offset + (int)$location[0]));
if(in_array(PackageFlags::COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
if(in_array(PackageFlags::COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
{
return gzuncompress(fread($this->package_file, (int)$location[1]));
}
@ -297,12 +279,12 @@
*/
public function getPointer(string $name): array
{
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
if(!isset($this->headers[PackageStructure::DIRECTORY][$name]))
{
throw new RuntimeException(sprintf('Resource \'%s\' not found in package \'%s\'', $name, $this->package_path));
throw new RuntimeException(sprintf('Resource \'%s\' not found in package', $name));
}
$location = explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
$location = explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
return [(int)$location[0], (int)$location[1]];
}
@ -314,7 +296,7 @@
*/
public function exists(string $name): bool
{
return isset($this->headers[PackageStructure::DIRECTORY->value][$name]);
return isset($this->headers[PackageStructure::DIRECTORY][$name]);
}
/**
@ -335,31 +317,22 @@
*
* @return Assembly
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getAssembly(): Assembly
{
$directory = sprintf('@%s', PackageDirectory::ASSEMBLY->value);
$directory = sprintf('@%s', PackageDirectory::ASSEMBLY);
if(isset($this->cache[$directory]))
{
return $this->cache[$directory];
}
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
if(!isset($this->headers[PackageStructure::DIRECTORY][$directory]))
{
throw new ConfigurationException(sprintf('Assembly object not found in package \'%s\'', $this->package_path));
}
try
{
$assembly = Assembly::fromArray(ZiProto::decode($this->get($directory)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode assembly from package \'%s\' using ZiProto: %s', $this->package_path, $e->getMessage()), $e);
throw new ConfigurationException('Package does not contain an assembly');
}
$assembly = Assembly::fromArray(ZiProto::decode($this->get($directory)));
$this->cache[$directory] = $assembly;
return $assembly;
}
@ -369,31 +342,23 @@
*
* @return Metadata
* @throws ConfigurationException
* @throws IntegrityException
* @throws NotSupportedException
*/
public function getMetadata(): Metadata
{
$directory = sprintf('@%s', PackageDirectory::METADATA->value);
$directory = sprintf('@%s', PackageDirectory::METADATA);
if(isset($this->cache[$directory]))
{
return $this->cache[$directory];
}
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
if(!isset($this->headers[PackageStructure::DIRECTORY][$directory]))
{
throw new ConfigurationException(sprintf('Metadata object not found in package \'%s\'', $this->package_path));
}
try
{
$metadata = Metadata::fromArray(ZiProto::decode($this->get($directory)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode metadata from package \'%s\' using ZiProto: %s', $this->package_path, $e->getMessage()), $e);
throw new ConfigurationException('Package does not contain metadata');
}
$metadata = Metadata::fromArray(ZiProto::decode($this->get($directory)));
foreach($this->getFlags() as $flag)
{
$metadata->setOption($flag, true);
@ -407,31 +372,22 @@
* Optional. Returns the package's installer
*
* @return Installer|null
* @throws IntegrityException
*/
public function getInstaller(): ?Installer
{
$directory = sprintf('@%s', PackageDirectory::INSTALLER->value);
$directory = sprintf('@%s', PackageDirectory::INSTALLER);
if(isset($this->cache[$directory]))
{
return $this->cache[$directory];
}
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$directory]))
if(!isset($this->headers[PackageStructure::DIRECTORY][$directory]))
{
return null;
}
try
{
$installer = Installer::fromArray(ZiProto::decode($this->get($directory)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode installer from package \'%s\' using ZiProto: %s', $this->package_path, $e->getMessage()), $e);
}
$installer = Installer::fromArray(ZiProto::decode($this->get($directory)));
$this->cache[$directory] = $installer;
return $installer;
}
@ -444,9 +400,9 @@
public function getDependencies(): array
{
$dependencies = [];
$directory = sprintf('@%s:', PackageDirectory::DEPENDENCIES->value);
$directory = sprintf('@%s:', PackageDirectory::DEPENDENCIES);
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -463,24 +419,16 @@
* @param string $name
* @return Dependency
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getDependency(string $name): Dependency
{
$dependency_name = sprintf('@%s:%s', PackageDirectory::DEPENDENCIES->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$dependency_name]))
$dependency_name = sprintf('@%s:%s', PackageDirectory::DEPENDENCIES, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$dependency_name]))
{
throw new ConfigurationException(sprintf('Dependency \'%s\' not found in package \'%s\'', $name, $this->package_path));
throw new ConfigurationException(sprintf('Dependency \'%s\' not found in package', $name));
}
try
{
return Dependency::fromArray(ZiProto::decode($this->get($dependency_name)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode dependency \'%s\' from package \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
return Dependency::fromArray(ZiProto::decode($this->get($dependency_name)));
}
/**
@ -489,18 +437,11 @@
* @param int $pointer
* @param int $length
* @return Dependency
* @throws IntegrityException
* @throws ConfigurationException
*/
public function getDependencyByPointer(int $pointer, int $length): Dependency
{
try
{
return Dependency::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode dependency from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
return Dependency::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
/**
@ -511,9 +452,9 @@
public function getExecutionUnits(): array
{
$execution_units = [];
$directory = sprintf('@%s:', PackageDirectory::EXECUTION_UNITS->value);
$directory = sprintf('@%s:', PackageDirectory::EXECUTION_UNITS);
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -530,35 +471,16 @@
* @param string $name
* @return ExecutionUnit
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getExecutionUnit(string $name): ExecutionUnit
{
$execution_unit_name = sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$execution_unit_name]))
$execution_unit_name = sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$execution_unit_name]))
{
throw new ConfigurationException(sprintf('Execution unit \'%s\' not found in package \'%s\'', $name, $this->package_path));
throw new ConfigurationException(sprintf('Execution unit \'%s\' not found in package', $name));
}
try
{
return ExecutionUnit::fromArray(ZiProto::decode($this->get($execution_unit_name)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode execution unit \'%s\' from package file \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
}
/**
* Checks if an execution unit with the specified name exists in the package.
*
* @param string $name The name of the execution unit to check.
* @return bool True if the execution unit exists, false otherwise.
*/
public function executionUnitExists(string $name): bool
{
return isset($this->headers[PackageStructure::DIRECTORY->value][sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $name)]);
return ExecutionUnit::fromArray(ZiProto::decode($this->get($execution_unit_name)));
}
/**
@ -567,18 +489,11 @@
* @param int $pointer
* @param int $length
* @return ExecutionUnit
* @throws IntegrityException
* @throws ConfigurationException
*/
public function getExecutionUnitByPointer(int $pointer, int $length): ExecutionUnit
{
try
{
return ExecutionUnit::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode execution unit from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
return ExecutionUnit::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
/**
@ -589,9 +504,9 @@
public function getComponents(): array
{
$components = [];
$directory = sprintf('@%s:', PackageDirectory::COMPONENTS->value);
$directory = sprintf('@%s:', PackageDirectory::COMPONENTS);
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -610,9 +525,9 @@
public function getClassMap(): array
{
$class_map = [];
$directory = sprintf('@%s:', PackageDirectory::CLASS_POINTER->value);
$directory = sprintf('@%s:', PackageDirectory::CLASS_POINTER);
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -629,24 +544,16 @@
* @param string $name
* @return Component
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getComponent(string $name): Component
{
$component_name = sprintf('@%s:%s', PackageDirectory::COMPONENTS->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$component_name]))
$component_name = sprintf('@%s:%s', PackageDirectory::COMPONENTS, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$component_name]))
{
throw new ConfigurationException(sprintf('Component \'%s\' not found in package \'%s\'', $name, $this->package_path));
throw new ConfigurationException(sprintf('Component \'%s\' not found in package', $name));
}
try
{
return Component::fromArray(ZiProto::decode($this->get($component_name)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode component \'%s\' from package \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
return Component::fromArray(ZiProto::decode($this->get($component_name)));
}
/**
@ -655,18 +562,11 @@
* @param int $pointer
* @param int $length
* @return Component
* @throws IntegrityException
* @throws ConfigurationException
*/
public function getComponentByPointer(int $pointer, int $length): Component
{
try
{
return Component::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode component from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
return Component::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
/**
@ -675,24 +575,16 @@
* @param string $class
* @return Component
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getComponentByClass(string $class): Component
{
$class_name = sprintf('@%s:%s', PackageDirectory::CLASS_POINTER->value, $class);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$class_name]))
$class_name = sprintf('@%s:%s', PackageDirectory::CLASS_POINTER, $class);
if(!isset($this->headers[PackageStructure::DIRECTORY][$class_name]))
{
throw new ConfigurationException(sprintf('Class map \'%s\' not found in package \'%s\'', $class, $this->package_path));
throw new ConfigurationException(sprintf('Class map \'%s\' not found in package', $class));
}
try
{
return Component::fromArray(ZiProto::decode($this->get($class_name)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode component from class pointer \'%s\' from package \'%s\' using ZiProto: %s', $class, $this->package_path, $e->getMessage()), $e);
}
return Component::fromArray(ZiProto::decode($this->get($class_name)));
}
/**
@ -703,9 +595,9 @@
public function getResources(): array
{
$resources = [];
$directory = sprintf('@%s:', PackageDirectory::RESOURCES->value);
$directory = sprintf('@%s:', PackageDirectory::RESOURCES);
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
foreach($this->headers[PackageStructure::DIRECTORY] as $name => $location)
{
if(str_starts_with($name, $directory))
{
@ -722,24 +614,16 @@
* @param string $name
* @return Resource
* @throws ConfigurationException
* @throws IntegrityException
*/
public function getResource(string $name): Resource
{
$resource_name = sprintf('@%s:%s', PackageDirectory::RESOURCES->value, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY->value][$resource_name]))
$resource_name = sprintf('@%s:%s', PackageDirectory::RESOURCES, $name);
if(!isset($this->headers[PackageStructure::DIRECTORY][$resource_name]))
{
throw new ConfigurationException(sprintf('Resource \'%s\' not found in package \'%s\'', $name, $this->package_path));
throw new ConfigurationException(sprintf('Resource \'%s\' not found in package', $name));
}
try
{
return Resource::fromArray(ZiProto::decode($this->get($resource_name)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode resource \'%s\' from package \'%s\' using ZiProto: %s', $name, $this->package_path, $e->getMessage()), $e);
}
return Resource::fromArray(ZiProto::decode($this->get($resource_name)));
}
/**
@ -748,37 +632,11 @@
* @param int $pointer
* @param int $length
* @return Resource
* @throws IntegrityException
* @throws ConfigurationException
*/
public function getResourceByPointer(int $pointer, int $length): Resource
{
try
{
return Resource::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
catch(Exception $e)
{
throw new IntegrityException(sprintf('Failed to decode resource from pointer \'%s\' with length \'%s\' from package \'%s\' using ZiProto: %s', $pointer, $length, $this->package_path, $e->getMessage()), $e);
}
}
/**
* Searches the package's directory for a file that matches the given filename
*
* @param string $filename
* @return string|false
*/
public function find(string $filename): string|false
{
foreach($this->headers[PackageStructure::DIRECTORY->value] as $name => $location)
{
if(str_ends_with($name, $filename))
{
return $name;
}
}
return false;
return Resource::fromArray(ZiProto::decode($this->getByPointer($pointer, $length)));
}
/**
@ -878,7 +736,7 @@
fseek($this->package_file, $this->package_offset);
$remaining_bytes = $this->package_length;
while($remaining_bytes > 0)
while ($remaining_bytes > 0)
{
$bytes_to_read = min($remaining_bytes, 4096);
$data = fread($this->package_file, $bytes_to_read);

View file

@ -25,12 +25,10 @@
namespace ncc\Classes;
use InvalidArgumentException;
use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\PackageDirectory;
use ncc\Enums\PackageStructure;
use ncc\Enums\PackageStructureVersions;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IOException;
use ncc\Objects\Package\Component;
use ncc\Objects\Package\ExecutionUnit;
@ -41,7 +39,6 @@
use ncc\Objects\ProjectConfiguration\Installer;
use ncc\Extensions\ZiProto\ZiProto;
use ncc\Utilities\Console;
use ncc\Utilities\ConsoleProgressBar;
class PackageWriter
{
@ -109,9 +106,9 @@
$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->value => PackageStructureVersions::_2_0->value,
PackageStructure::FLAGS->value => [],
PackageStructure::DIRECTORY->value => []
PackageStructure::FILE_VERSION => PackageStructureVersions::_2_0,
PackageStructure::FLAGS => [],
PackageStructure::DIRECTORY => []
];
if($this->temp_file === false || $this->package_file === false)
@ -127,7 +124,7 @@
*/
public function getFileVersion(): string
{
return (string)$this->headers[PackageStructure::FILE_VERSION->value];
return (string)$this->headers[PackageStructure::FILE_VERSION];
}
/**
@ -138,7 +135,7 @@
*/
public function setFileVersion(string $version): void
{
$this->headers[PackageStructure::FILE_VERSION->value] = $version;
$this->headers[PackageStructure::FILE_VERSION] = $version;
}
/**
@ -148,13 +145,13 @@
*/
public function getFlags(): array
{
return (array)$this->headers[PackageStructure::FLAGS->value];
return (array)$this->headers[PackageStructure::FLAGS];
}
/**
* Sets the package flags
*
* @param string[]|PackageFlags[] $flags
* @param array $flags
* @return void
* @throws IOException
*/
@ -165,47 +162,26 @@
throw new IOException('Cannot set flags after data has been written to the package');
}
foreach($flags as $flag)
{
if(is_string($flag))
{
$flag = PackageFlags::tryFrom($flag);
if($flag === null)
{
throw new InvalidArgumentException(sprintf('Unexpected flag: %s', $flag));
}
}
$this->headers[PackageStructure::FLAGS->value] = $flag->value;
}
$this->headers[PackageStructure::FLAGS] = $flags;
}
/**
* Adds a flag to the package
*
* @param PackageFlags|string $flag
* @param string $flag
* @return void
* @throws IOException
*/
public function addFlag(PackageFlags|string $flag): void
public function addFlag(string $flag): void
{
if(is_string($flag))
{
$flag = PackageFlags::tryFrom($flag);
if($flag === null)
{
throw new InvalidArgumentException(sprintf('Unexpected flag: %s', $flag));
}
}
if($this->data_written)
{
throw new IOException('Cannot add a flag after data has been written to the package');
}
if(!in_array($flag, $this->headers[PackageStructure::FLAGS->value], true))
if(!in_array($flag, $this->headers[PackageStructure::FLAGS], true))
{
$this->headers[PackageStructure::FLAGS->value][] = $flag->value;
$this->headers[PackageStructure::FLAGS][] = $flag;
}
}
@ -216,23 +192,14 @@
* @return void
* @throws IOException
*/
public function removeFlag(PackageFlags|string $flag): void
public function removeFlag(string $flag): void
{
if(is_string($flag))
{
$flag = PackageFlags::tryFrom($flag);
if($flag === null)
{
throw new InvalidArgumentException(sprintf('Unexpected flag: %s', $flag));
}
}
if($this->data_written)
{
throw new IOException('Cannot remove a flag after data has been written to the package');
}
$this->headers[PackageStructure::FLAGS->value] = array_diff($this->headers[PackageStructure::FLAGS->value], [$flag->value]);
$this->headers[PackageStructure::FLAGS] = array_diff($this->headers[PackageStructure::FLAGS], [$flag]);
}
/**
@ -244,22 +211,22 @@
*/
public function add(string $name, string $data): array
{
if(isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
if(isset($this->headers[PackageStructure::DIRECTORY][$name]))
{
return explode(':', $this->headers[PackageStructure::DIRECTORY->value][$name]);
return explode(':', $this->headers[PackageStructure::DIRECTORY][$name]);
}
if(in_array(PackageFlags::COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
if(in_array(PackageFlags::COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
{
if(in_array(PackageFlags::LOW_COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
if(in_array(PackageFlags::LOW_COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
{
$data = gzcompress($data, 1);
}
else if(in_array(PackageFlags::MEDIUM_COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
else if(in_array(PackageFlags::MEDIUM_COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
{
$data = gzcompress($data, 6);
}
else if(in_array(PackageFlags::HIGH_COMPRESSION->value, $this->headers[PackageStructure::FLAGS->value], true))
else if(in_array(PackageFlags::HIGH_COMPRESSION, $this->headers[PackageStructure::FLAGS], true))
{
$data = gzcompress($data, 9);
}
@ -270,7 +237,7 @@
}
$pointer = sprintf("%d:%d", ftell($this->temp_file), strlen($data));
$this->headers[PackageStructure::DIRECTORY->value][$name] = $pointer;
$this->headers[PackageStructure::DIRECTORY][$name] = $pointer;
$this->data_written = true;
fwrite($this->temp_file, $data);
@ -287,12 +254,12 @@
*/
public function addPointer(string $name, int $offset, int $length): void
{
if(isset($this->headers[PackageStructure::DIRECTORY->value][$name]))
if(isset($this->headers[PackageStructure::DIRECTORY][$name]))
{
return;
}
$this->headers[PackageStructure::DIRECTORY->value][$name] = sprintf("%d:%d", $offset, $length);
$this->headers[PackageStructure::DIRECTORY][$name] = sprintf("%d:%d", $offset, $length);
}
/**
@ -303,7 +270,7 @@
*/
public function setAssembly(Assembly $assembly): array
{
return $this->add(sprintf('@%s', PackageDirectory::ASSEMBLY->value), ZiProto::encode($assembly->toArray(true)));
return $this->add(sprintf('@%s', PackageDirectory::ASSEMBLY), ZiProto::encode($assembly->toArray(true)));
}
/**
@ -314,7 +281,7 @@
*/
public function setMetadata(Metadata $metadata): array
{
return $this->add(sprintf('@%s', PackageDirectory::METADATA->value), ZiProto::encode($metadata->toArray(true)));
return $this->add(sprintf('@%s', PackageDirectory::METADATA), ZiProto::encode($metadata->toArray(true)));
}
/**
@ -325,7 +292,7 @@
*/
public function setInstaller(Installer $installer): array
{
return $this->add(sprintf('@%s', PackageDirectory::INSTALLER->value), ZiProto::encode($installer->toArray(true)));
return $this->add(sprintf('@%s', PackageDirectory::INSTALLER), ZiProto::encode($installer->toArray(true)));
}
/**
@ -336,7 +303,7 @@
*/
public function addDependencyConfiguration(Dependency $dependency): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::DEPENDENCIES->value, $dependency->getName()), ZiProto::encode($dependency->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::DEPENDENCIES, $dependency->getName()), ZiProto::encode($dependency->toArray(true)));
}
/**
@ -347,7 +314,7 @@
*/
public function addExecutionUnit(ExecutionUnit $unit): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS->value, $unit->getExecutionPolicy()->getName()), ZiProto::encode($unit->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::EXECUTION_UNITS, $unit->getExecutionPolicy()->getName()), ZiProto::encode($unit->toArray(true)));
}
/**
@ -358,7 +325,7 @@
*/
public function addComponent(Component $component): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::COMPONENTS->value, $component->getName()), ZiProto::encode($component->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::COMPONENTS, $component->getName()), ZiProto::encode($component->toArray(true)));
}
/**
@ -369,7 +336,7 @@
*/
public function addResource(Resource $resource): array
{
return $this->add(sprintf('@%s:%s', PackageDirectory::RESOURCES->value, $resource->getName()), ZiProto::encode($resource->toArray(true)));
return $this->add(sprintf('@%s:%s', PackageDirectory::RESOURCES, $resource->getName()), ZiProto::encode($resource->toArray(true)));
}
/**
@ -382,7 +349,7 @@
*/
public function mapClass(string $class, int $offset, int $length): void
{
$this->addPointer(sprintf('@%s:%s', PackageDirectory::CLASS_POINTER->value, $class), $offset, $length);
$this->addPointer(sprintf('@%s:%s', PackageDirectory::CLASS_POINTER, $class), $offset, $length);
}
/**
@ -390,23 +357,19 @@
*
* @param PackageReader $reader
* @return void
* @throws ConfigurationException
*/
public function merge(PackageReader $reader): void
{
$progress_bar = new ConsoleProgressBar(sprintf('Merging %s', $reader->getAssembly()->getPackage()), count($reader->getDirectory()));
$processed_resources = [];
foreach($reader->getDirectory() as $name => $pointer)
{
$progress_bar->setMiscText($name, true);
switch((int)substr(explode(':', $name, 2)[0], 1))
{
case PackageDirectory::METADATA->value:
case PackageDirectory::ASSEMBLY->value:
case PackageDirectory::INSTALLER->value:
case PackageDirectory::EXECUTION_UNITS->value:
case PackageDirectory::METADATA:
case PackageDirectory::ASSEMBLY:
case PackageDirectory::INSTALLER:
case PackageDirectory::EXECUTION_UNITS:
Console::outDebug(sprintf('Skipping %s', $name));
break;
@ -420,13 +383,9 @@
Console::outDebug(sprintf('Merging %s', $name));
$processed_resources[$pointer] = $this->add($name, $reader->get($name));
}
$progress_bar->increaseValue(1, true);
}
$progress_bar->setMiscText('done', true);
unset($progress_bar);
}
/**

View file

@ -35,10 +35,9 @@
use ncc\Interfaces\RepositoryInterface;
use ncc\Objects\RepositoryConfiguration;
use ncc\Objects\RepositoryResult;
use ncc\ThirdParty\composer\semver\Comparator;
use ncc\ThirdParty\composer\semver\Semver;
use ncc\ThirdParty\composer\Semver\Comparator;
use ncc\ThirdParty\composer\Semver\Semver;
use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use RuntimeException;
@ -47,9 +46,9 @@
/**
* @inheritDoc
*/
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST->value, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
public static function fetchSourceArchive(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
{
if($version === Versions::LATEST->value)
if($version === Versions::LATEST)
{
$version = self::getLatestVersion($repository, $vendor, $project);
}
@ -71,16 +70,9 @@
'User-Agent: ncc'
];
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -99,14 +91,14 @@
throw new NetworkException(sprintf('Invalid response from %s/%s, version %s does not have a dist URL', $vendor, $project, $version));
}
return new RepositoryResult($response['package']['versions'][$version]['dist']['url'], RepositoryResultType::SOURCE->value, $version);
return new RepositoryResult($response['package']['versions'][$version]['dist']['url'], RepositoryResultType::SOURCE, $version);
}
/**
* @inheritDoc
* @throws NotSupportedException
*/
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST->value, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
public static function fetchPackage(RepositoryConfiguration $repository, string $vendor, string $project, string $version = Versions::LATEST, ?AuthenticationType $authentication = null, array $options=[]): RepositoryResult
{
throw new NotSupportedException('Fetching ncc packages from Packagist is not supported');
}
@ -138,16 +130,9 @@
'User-Agent: ncc'
];
$resolved_host = Resolver::getResolveOption($endpoint);
if($resolved_host !== null)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -178,21 +163,23 @@
{
$versions = self::getVersions($repository, $vendor, $project);
// Filter out pre-release versions such as alpha, beta, rc, dev
/** @noinspection KeysFragmentationWithArrayFunctionsInspection */
$versions = array_filter($versions, static function($version)
{
return !preg_match('/-alpha|-beta|-rc|dev/i', $version);
});
// Sort versions in descending order using Semver::rsort
$versions = Semver::rsort($versions);
usort($versions, static function($a, $b)
{
return Comparator::lessThanOrEqualTo($a, $b) ? 1 : -1;
});
if (!isset($versions[0]))
if($versions[0] === null)
{
throw new NetworkException(sprintf('Failed to resolve latest version for %s/%s', $vendor, $project));
}
return $versions[0]; // The first version in the sorted array is the latest
return $versions[0];
}
/**

View file

@ -24,13 +24,33 @@
use ncc\ThirdParty\nikic\PhpParser\Comment;
use ncc\ThirdParty\nikic\PhpParser\Node;
use ncc\ThirdParty\nikic\PhpParser\NodeTraverser;
use ReflectionClass;
use ReflectionException;
use RuntimeException;
class AstWalker
{
/**
* Returns an array representation of the node recursively
*
* @param array|Node $node
* @return array
*/
public static function serialize(array|Node $node): array
{
if(is_array($node))
{
$serialized = [];
foreach($node as $sub_node)
{
$serialized[] = $sub_node->jsonSerialize();
}
return $serialized;
}
return $node->jsonSerialize();
}
/**
* Returns an array of classes associated with the node recursively
*
@ -40,10 +60,9 @@
*/
public static function extractClasses(Node|array $node, string $prefix=''): array
{
$classes = [];
if(is_array($node))
{
$classes = [];
foreach($node as $sub_node)
{
/** @noinspection SlowArrayOperationsInLoopInspection */
@ -52,6 +71,8 @@
return $classes;
}
$classes = [];
if ($node instanceof Node\Stmt\ClassLike)
{
$classes[] = $prefix . $node->name;
@ -59,9 +80,9 @@
if ($node instanceof Node\Stmt\Namespace_)
{
if ($node->name && $node->name->getParts())
if ($node->name && $node->name->parts)
{
$prefix .= implode('\\', $node->name->getParts()) . '\\';
$prefix .= implode('\\', $node->name->parts) . '\\';
}
else
{
@ -91,4 +112,146 @@
return $classes;
}
/**
* Reconstructs nodes from an array representation recursively
*
* @param $value
* @return array|Comment|Node
* @noinspection PhpMissingReturnTypeInspection
* @throws ReflectionException
*/
public static function decodeRecursive($value)
{
if (is_array($value))
{
if (isset($value['nodeType']))
{
if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc')
{
return self::decodeComment($value);
}
return self::decodeNode($value);
}
return self::decodeArray($value);
}
return $value;
}
/**
* Decodes an array by recursively decoding each value
*
* @param array $array
* @return array
* @throws ReflectionException
*/
private static function decodeArray(array $array) : array
{
$decoded_array = [];
foreach ($array as $key => $value)
{
$decoded_array[$key] = self::decodeRecursive($value);
}
return $decoded_array;
}
/**
* Returns the node from the node type
*
* @param array $value
* @return Node
* @throws ReflectionException
*/
private static function decodeNode(array $value) : Node
{
$node_type = $value['nodeType'];
if (!is_string($node_type))
{
throw new RuntimeException('Node type must be a string');
}
/** @var Node $node */
$node = self::reflectionClassFromNodeType($node_type)->newInstanceWithoutConstructor();
if (isset($value['attributes'])) {
if (!is_array($value['attributes']))
{
throw new RuntimeException('Attributes must be an array');
}
$node->setAttributes(self::decodeArray($value['attributes']));
}
foreach ($value as $name => $sub_node) {
if ($name === 'nodeType' || $name === 'attributes')
{
continue;
}
$node->$name = self::decodeRecursive($sub_node);
}
return $node;
}
/**
* Returns the comment from the node type
*
* @param array $value
* @return Comment
*/
private static function decodeComment(array $value): Comment
{
$class_name = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
if (!isset($value['text']))
{
throw new RuntimeException('Comment must have text');
}
return new $class_name(
$value['text'],
$value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1,
$value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1
);
}
/**
* Returns the reflection class from the node type
*
* @param string $node_type
* @return ReflectionClass
* @throws ReflectionException
*/
private static function reflectionClassFromNodeType(string $node_type): ReflectionClass
{
return new ReflectionClass(self::classNameFromNodeType($node_type));
}
/**
* Returns the class name from the node type
*
* @param string $nodeType
* @return string
*/
private static function classNameFromNodeType(string $nodeType): string
{
$class_name = 'ncc\\ThirdParty\\nikic\\PhpParser\\Node\\' . str_replace('_', '\\', $nodeType);
if (class_exists($class_name))
{
return $class_name;
}
$class_name .= '_';
if (class_exists($class_name))
{
return $class_name;
}
throw new RuntimeException("Unknown node type \"$nodeType\"");
}
}

View file

@ -31,7 +31,6 @@
use ncc\ThirdParty\Symfony\Process\ExecutableFinder;
use ncc\ThirdParty\Symfony\Process\Process;
use ncc\Utilities\Console;
use ncc\Utilities\ConsoleProgressBar;
use ncc\Utilities\Functions;
use ncc\Utilities\PathFinder;
@ -41,7 +40,7 @@
* @inheritDoc
* @throws BuildException
*/
public function build(string $build_configuration = BuildConfigurationValues::DEFAULT->value, array $options=[]): string
public function build(string $build_configuration = BuildConfigurationValues::DEFAULT, array $options=[]): string
{
$configuration = $this->getProjectManager()->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
@ -50,14 +49,14 @@
$configuration->setOptions(array_merge($configuration->getOptions(), $options));
}
if(!isset($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION->value]))
if(!isset($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION]))
{
throw new BuildException(sprintf("Unable to compile the binary, the build configuration '%s' does not have a ncc_configuration.", $build_configuration));
}
// Build the ncc package first
Console::outVerbose('Building ncc package.');
$ncc_package = parent::build($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION->value]);
$ncc_package = parent::build($configuration->getOptions()[BuildConfigurationOptions::NCC_CONFIGURATION]);
// Prepare the ncc package for compilation
$hex_dump_file = PathFinder::getCachePath() . DIRECTORY_SEPARATOR . $this->getProjectManager()->getProjectConfiguration()->getAssembly()->getName() . '.c';
@ -72,11 +71,11 @@
// Prepare the gcc command
$gcc_path = (new ExecutableFinder())->find('gcc');
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]))
if(isset($configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]))
{
$binary_path = ConstantCompiler::compileConstants(
$this->getProjectManager()->getProjectConfiguration(),
$configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE->value]
$configuration->getOptions()[BuildConfigurationOptions::OUTPUT_FILE]
);
}
else
@ -84,12 +83,6 @@
$binary_path = ConstantCompiler::compileConstants($this->getProjectManager()->getProjectConfiguration(), $configuration->getOutput());
}
// Create the directory recursively if it does not exist
if(!is_dir(dirname($binary_path)))
{
mkdir(dirname($binary_path), 0777, true);
}
if($gcc_path === null)
{
throw new BuildException("Unable to find gcc executable, please make sure it is installed and in your PATH environment variable.");
@ -175,35 +168,32 @@
*/
private function hexDump(string $input_path, string $output_path, string $variable_name): void
{
Console::outVerbose(sprintf('Processing %s to hex dump', $input_path));
Console::out(sprintf('Processing %s to hex dump', $input_path));
$input = fopen($input_path, 'rb');
$output = fopen($output_path, 'wb');
$byte_count = 0;
$progress_bar = new ConsoleProgressBar(sprintf('HexDump %s', $input_path), filesize($input_path));
$total_bytes = filesize($input_path);
fwrite($output, sprintf("unsigned char %s[] = {\n", Functions::toSnakeCase($variable_name)));
// Convert the binary data to hex and write it to the output file using chunks
// Convert the binary data to hex and write it to the output file
while (!feof($input))
{
$bytes = fread($input, 5026);
$len = strlen($bytes);
Console::inlineProgressBar(ftell($input), $total_bytes);
for ($i = 0; $i < $len; $i++)
$byte = fread($input, 1);
if (strlen($byte) === 1)
{
fwrite($output, sprintf(" 0x%02x,", ord($bytes[$i])));
fwrite($output, sprintf(" 0x%02x,", ord($byte)));
$byte_count++;
// Write 12 bytes per line or when reaching the end of the file
if ($byte_count === 12 || ($i == $len - 1 && feof($input)))
{
fwrite($output, "\n");
$byte_count = 0;
}
}
$progress_bar->increaseValue($len, true);
$progress_bar->setMiscText(sprintf('Processed (%d/%d)', $progress_bar->getValue(), $progress_bar->getMaxValue()));
// Write 12 bytes per line or when reaching the end of the file
if ($byte_count === 12 || feof($input))
{
fwrite($output, "\n");
$byte_count = 0;
}
}
// Close the output file
@ -214,9 +204,5 @@
// Finally, close the input and output files
fclose($input);
fclose($output);
// Close the progress bar
$progress_bar->setMiscText('done', true);
unset($progress_bar);
}
}

View file

@ -1,74 +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\PhpExtension;
use ncc\ThirdParty\nikic\PhpParser\Node;
use ncc\ThirdParty\nikic\PhpParser\NodeVisitorAbstract;
use ncc\Utilities\Console;
class ExpressionTraverser extends NodeVisitorAbstract
{
/**
* @var string|null
*/
private ?string $package;
/**
* ExpressionTraverser constructor.
*
* @param string|null $package
*/
public function __construct(?string $package)
{
$this->package = $package;
}
/**
* @param Node $node
* @return array|int|Node|null
*/
public function leaveNode(Node $node): array|int|Node|null
{
if($node instanceof Node\Expr\Include_)
{
Console::outDebug(sprintf('Processing ExpressionTraverser on: %s', $node->getType()));
$args = [$node->expr];
if(!is_null($this->package))
{
$args[] = new Node\Arg(new Node\Scalar\String_($this->package));
}
$types = [
Node\Expr\Include_::TYPE_INCLUDE => '\ncc\Classes\Runtime::runtimeInclude',
Node\Expr\Include_::TYPE_INCLUDE_ONCE => '\ncc\Classes\Runtime::runtimeIncludeOnce',
Node\Expr\Include_::TYPE_REQUIRE => '\ncc\Classes\Runtime::runtimeRequire',
Node\Expr\Include_::TYPE_REQUIRE_ONCE => '\ncc\Classes\Runtime::runtimeRequireOnce',
];
return new Node\Expr\FuncCall(new Node\Name($types[$node->type]), $args);
}
return null;
}
}

View file

@ -30,9 +30,7 @@
use ncc\Exceptions\PathNotFoundException;
use ncc\Extensions\ZiProto\ZiProto;
use ncc\Objects\Package\Component;
use ncc\ThirdParty\nikic\PhpParser\NodeDumper;
use ncc\ThirdParty\nikic\PhpParser\ParserFactory;
use ncc\ThirdParty\nikic\PhpParser\PhpVersion;
use ncc\Utilities\Base64;
use ncc\Utilities\Console;
use ncc\Utilities\Functions;
@ -54,9 +52,10 @@
try
{
$stmts = ((new ParserFactory())->createForNewestSupportedVersion())->parse(IO::fread($file_path));
$component = new Component($component_name, ZiProto::encode(Serializer::nodesToArray($stmts)), ComponentDataType::AST);
$component->addFlag(ComponentFlags::PHP_AST->value);
$stmts = (new ParserFactory())->create(ParserFactory::PREFER_PHP7)->parse(IO::fread($file_path));
$component = new Component($component_name, ZiProto::encode($stmts), ComponentDataType::AST);
$component->addFlag(ComponentFlags::PHP_AST);
$pointer = $package_writer->addComponent($component);
foreach(AstWalker::extractClasses($stmts) as $class)
@ -72,7 +71,7 @@
}
$component = new Component($component_name, Base64::encode(IO::fread($file_path)), ComponentDataType::BASE64_ENCODED);
$component->addFlag(ComponentFlags::PHP_B64->value);
$component->addFlag(ComponentFlags::PHP_B64);
$package_writer->addComponent($component);
}
}

View file

@ -44,7 +44,7 @@
*/
public static function executeUnit(ExecutionUnit $unit, array $args=[], bool $local=true): int
{
if($unit->getExecutionPolicy()->getRunner() !== Runners::PHP->value)
if($unit->getExecutionPolicy()->getRunner() !== Runners::PHP)
{
throw new InvalidArgumentException(sprintf('The execution unit %s is not a php execution unit', $unit->getExecutionPolicy()->getName()));
}

View file

@ -1,151 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, 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 ncc\ThirdParty\nikic\PhpParser\Comment;
use ncc\ThirdParty\nikic\PhpParser\Node;
use ncc\ThirdParty\nikic\PhpParser\NodeAbstract;
use ReflectionClass;
use RuntimeException;
use function is_array;
use function is_string;
class Serializer
{
/** @var ReflectionClass<Node>[] Node type to reflection class map */
private static array $reflectionClassCache;
/**
* @param NodeAbstract[] $nodeAbstracts
* @return array
*/
public static function nodesToArray(array $nodeAbstracts): array
{
$serialized = [];
foreach ($nodeAbstracts as $nodeAbstract)
{
$serialized[] = $nodeAbstract->jsonSerialize();
}
return $serialized;
}
/**
* @param array $nodeAbstracts
* @return NodeAbstract[]
*/
public static function arrayToNodes(array $nodeAbstracts): array
{
return self::decodeRecursive($nodeAbstracts);
}
/**
* @param mixed $value
* @return mixed
*/
private static function decodeRecursive($value) {
if (is_array($value)) {
if (isset($value['nodeType'])) {
if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {
return self::decodeComment($value);
}
return self::decodeNode($value);
}
return self::decodeArray($value);
}
return $value;
}
private static function decodeArray(array $array): array {
$decodedArray = [];
foreach ($array as $key => $value) {
$decodedArray[$key] = self::decodeRecursive($value);
}
return $decodedArray;
}
private static function decodeNode(array $value): Node {
$nodeType = $value['nodeType'];
if (!is_string($nodeType)) {
throw new RuntimeException('Node type must be a string');
}
$reflectionClass = self::reflectionClassFromNodeType($nodeType);
$node = $reflectionClass->newInstanceWithoutConstructor();
if (isset($value['attributes'])) {
if (!is_array($value['attributes'])) {
throw new RuntimeException('Attributes must be an array');
}
$node->setAttributes(self::decodeArray($value['attributes']));
}
foreach ($value as $name => $subNode) {
if ($name === 'nodeType' || $name === 'attributes') {
continue;
}
$node->$name = self::decodeRecursive($subNode);
}
return $node;
}
private static function decodeComment(array $value): Comment {
$className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
if (!isset($value['text'])) {
throw new RuntimeException('Comment must have text');
}
return new $className(
$value['text'],
$value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1,
$value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1
);
}
private static function reflectionClassFromNodeType(string $nodeType): ReflectionClass {
if (!isset(self::$reflectionClassCache[$nodeType])) {
$className = self::classNameFromNodeType($nodeType);
self::$reflectionClassCache[$nodeType] = new ReflectionClass($className);
}
return self::$reflectionClassCache[$nodeType];
}
/** @return class-string<Node> */
private static function classNameFromNodeType(string $nodeType): string {
$className = '\\ncc\\ThirdParty\\nikic\\PhpParser\\Node\\' . strtr($nodeType, '_', '\\');
if (class_exists($className)) {
return $className;
}
$className .= '_';
if (class_exists($className)) {
return $className;
}
throw new RuntimeException("Unknown node type \"$nodeType\"");
}
}

View file

@ -49,31 +49,32 @@
public static function applyTemplate(ProjectManager $project_manager): void
{
$project_manager->getProjectConfiguration()->addExecutionPolicy(
new ExecutionPolicy('main_policy', Runners::PHP->value, new ExecutionPolicy\Execute('main'))
new ExecutionPolicy('main_policy', Runners::PHP, new ExecutionPolicy\Execute('main'))
);
$project_manager->getProjectConfiguration()->getBuild()->setMain('main_policy');
$project_manager->getProjectConfiguration()->getProject()->addOption(ProjectOptions::CREATE_SYMLINK->value, true);
$project_manager->getProjectConfiguration()->getProject()->addOption(ProjectOptions::CREATE_SYMLINK, true);
// Create the release build configuration
$release_executable = new BuildConfiguration('release_executable',
'build' . DIRECTORY_SEPARATOR . 'release' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME->value
'build' . DIRECTORY_SEPARATOR . 'release' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME
);
$release_executable->setBuildType(BuildOutputType::EXECUTABLE->value);
$release_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION->value, 'release');
$release_executable->setBuildType(BuildOutputType::EXECUTABLE);
$release_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION, 'release');
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($release_executable);
// Create the debug build configuration
$debug_executable = new BuildConfiguration('debug_executable',
'build' . DIRECTORY_SEPARATOR . 'debug' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME->value
'build' . DIRECTORY_SEPARATOR . 'debug' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_NAME
);
$debug_executable->setDefinedConstant('DEBUG', '1');
$debug_executable->setBuildType(BuildOutputType::EXECUTABLE->value);
$debug_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION->value, 'debug');
$debug_executable->setBuildType(BuildOutputType::EXECUTABLE);
$debug_executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION, 'debug');
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($debug_executable);
self::writeProgramTemplate($project_manager);
self::writeMainEntryTemplate($project_manager);
self::writeMakefileTemplate($project_manager);
$project_manager->save();
}
@ -113,4 +114,22 @@
)
);
}
/**
* Writes the Makefile to the project directory
*
* @param ProjectManager $project_manager
* @return void
* @throws IOException
* @throws PathNotFoundException
*/
private static function writeMakefileTemplate(ProjectManager $project_manager): void
{
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'Makefile',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'Makefile.tpl')
)
);
}
}

View file

@ -1,61 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, 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\Templates;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\Types\BuildOutputType;
use ncc\Exceptions\IOException;
use ncc\Interfaces\TemplateInterface;
use ncc\Managers\ProjectManager;
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
class CompressedTemplate implements TemplateInterface
{
/**
* @inheritDoc
* @throws IOException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
// Create the release build configuration
$release_compressed = new BuildConfiguration('release-compressed',
'build' . DIRECTORY_SEPARATOR . 'release' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_PACKAGE->value . '.gz.ncc'
);
$release_compressed->setBuildType(BuildOutputType::NCC_PACKAGE->value);
$release_compressed->setOption(BuildConfigurationOptions::COMPRESSION->value, BuildConfigurationOptions\CompressionOptions::HIGH->value);
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($release_compressed);
// Create the debug build configuration
$debug_compressed = new BuildConfiguration('debug-compressed',
'build' . DIRECTORY_SEPARATOR . 'debug' . DIRECTORY_SEPARATOR . AssemblyConstants::ASSEMBLY_PACKAGE->value . '.gz.ncc'
);
$debug_compressed->setBuildType(BuildOutputType::NCC_PACKAGE->value);
$debug_compressed->setOption(BuildConfigurationOptions::COMPRESSION->value, BuildConfigurationOptions\CompressionOptions::HIGH->value);
$debug_compressed->setDefinedConstant('DEBUG', '1');
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($debug_compressed);
$project_manager->save();
}
}

View file

@ -1,77 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, 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\Templates;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\Types\BuildOutputType;
use ncc\Exceptions\IOException;
use ncc\Interfaces\TemplateInterface;
use ncc\Managers\ProjectManager;
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
class ExecutableTemplate implements TemplateInterface
{
/**
* @inheritDoc
* @throws IOException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
foreach($project_manager->getProjectConfiguration()->getBuild()->getBuildConfigurations() as $build_configuration)
{
$executable_name = sprintf('%s-executable', $build_configuration);
$configuration = $project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_configuration);
// Skip if the executable version of the build configuration already exists
if($project_manager->getProjectConfiguration()->getBuild()->buildConfigurationExists($executable_name))
{
continue;
}
// Skip if the build configuration is not an ncc package that the executable can be based on
if($configuration->getBuildType() !== BuildOutputType::NCC_PACKAGE->value)
{
continue;
}
if(isset($configuration->getOptions()[BuildConfigurationOptions::COMPRESSION->value]))
{
$output = dirname($configuration->getOutput()) . DIRECTORY_SEPARATOR . str_replace('-', '_', $executable_name);
}
else
{
$output = dirname($configuration->getOutput()) . DIRECTORY_SEPARATOR . str_replace('-', '_', $executable_name) . '_gz';
}
// Create the executable build configuration
$executable = new BuildConfiguration($executable_name, $output);
$executable->setBuildType(BuildOutputType::EXECUTABLE->value);
$executable->setOption(BuildConfigurationOptions::NCC_CONFIGURATION->value, $configuration->getName());
$project_manager->getProjectConfiguration()->getBuild()->addBuildConfiguration($executable);
}
$project_manager->save();
}
}

View file

@ -1,117 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, 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\Templates;
use ncc\Classes\NccExtension\ConstantCompiler;
use ncc\Exceptions\IOException;
use ncc\Exceptions\PathNotFoundException;
use ncc\Managers\ProjectManager;
use ncc\Utilities\IO;
class GitHubWorkflowTemplate
{
/**
* @inheritDoc
* @param ProjectManager $project_manager
* @throws IOException
* @throws PathNotFoundException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
self::writeCiTemplate($project_manager);
}
/**
* Writes the Makefile to the project directory
*
* @param ProjectManager $project_manager
* @return void
* @throws IOException
* @throws PathNotFoundException
*/
private static function writeCiTemplate(ProjectManager $project_manager): void
{
$ci_dir = $project_manager->getProjectPath() . DIRECTORY_SEPARATOR . '.github' . DIRECTORY_SEPARATOR . 'workflows';
if(!file_exists($ci_dir))
{
mkdir($ci_dir, 0777, true);
}
$template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'github_ci.yml.tpl');
$default_configuration = $project_manager->getProjectConfiguration()->getBuild()->getDefaultConfiguration();
$builds = [];
$releases = [];
$downloads = [];
foreach($project_manager->getProjectConfiguration()->getBuild()->getBuildConfigurations() as $build_name)
{
$build_template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'github_ci_build.yml.tpl');
$build_template = str_replace('%TPL_BUILD_NAME%', $build_name, $build_template);
$build_template = str_replace('%TPL_BUILD_OUTPUT%',
$project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_name)->getOutput(),
$build_template
);
$builds[$build_name] = $build_template;
$download_template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'github_ci_download.yml.tpl');
$download_template = str_replace('%TPL_BUILD_NAME%', $build_name, $download_template);
$downloads[$build_name] = $download_template;
$release_template = str_repeat(' ', 12) . $build_name . DIRECTORY_SEPARATOR . basename(
$project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($build_name)->getOutput()
);
$releases[$build_name] = $release_template;
}
$build_jobs = '';
foreach($builds as $name => $build_template)
{
$build_jobs .= $build_template . PHP_EOL;
}
$download_jobs = '';
foreach($downloads as $name => $download_template)
{
$download_jobs .= $download_template . PHP_EOL;
}
$release_jobs = '';
foreach($releases as $name => $release_template)
{
$release_jobs .= $release_template . PHP_EOL;
}
$template = str_replace('%TPL_BUILDS%', $build_jobs, $template);
$template = str_replace('%TPL_DOWNLOAD_ARTIFACTS%', $download_jobs, $template);
$template = str_replace('%TPL_ARTIFACT_FILES%', $release_jobs, $template);
$template = str_replace('%TPL_BUILD_NAMES%', implode(', ', array_keys($builds)), $template);
$template = str_replace('%TPL_DEFAULT_BUILD_CONFIGURATION%', $default_configuration, $template);
$template = str_replace('%TPL_DEFAULT_ARTIFACT_BUILD_OUTPUT%', $default_configuration . DIRECTORY_SEPARATOR . basename(
$project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($default_configuration)->getOutput()
), $template);
IO::fwrite($ci_dir . DIRECTORY_SEPARATOR . 'ncc_workflow.yml',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(), $template)
);
}
}

View file

@ -48,14 +48,8 @@
*/
private static function createClassTemplate(ProjectManager $project_manager): void
{
$class_directory = $project_manager->getProjectSourcePath() . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName();
if(!file_exists($class_directory))
{
mkdir($class_directory, 0777, true);
}
IO::fwrite(
$class_directory . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName() . '.php',
$project_manager->getProjectSourcePath() . DIRECTORY_SEPARATOR . $project_manager->getProjectConfiguration()->getAssembly()->getName() . '.php',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'class.php.tpl')
)

View file

@ -1,21 +1,20 @@
# Variables
DEFAULT_CONFIGURATION ?= %TPL_DEFAULT_BUILD_CONFIGURATION%
CONFIG ?= release
LOG_LEVEL = debug
OUTDIR = build/$(CONFIG)
PACKAGE = $(OUTDIR)/%ASSEMBLY.PACKAGE%.ncc
# Default Target
all: %TPL_BUILD_NAMES%
all: build
# Build Steps
%TPL_BUILDS%
build:
ncc build --config=$(CONFIG) --log-level $(LOG_LEVEL)
install: %TPL_DEFAULT_BUILD_CONFIGURATION%
ncc package install --package=%TPL_DEFAULT_BUILD_PATH% --skip-dependencies --build-source --reinstall -y --log-level $(LOG_LEVEL)
test: %TPL_DEFAULT_BUILD_CONFIGURATION%
[ -f phpunit.xml ] || { echo "phpunit.xml not found"; exit 1; }
phpunit
install:
ncc package install --package=$(PACKAGE) --skip-dependencies --reinstall -y --log-level $(LOG_LEVEL)
clean:
rm -rf build
.PHONY: all install test clean %TPL_BUILD_NAMES%
.PHONY: all build install clean

View file

@ -1,78 +0,0 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, 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\Templates;
use ncc\Classes\NccExtension\ConstantCompiler;
use ncc\Exceptions\IOException;
use ncc\Exceptions\PathNotFoundException;
use ncc\Managers\ProjectManager;
use ncc\Utilities\IO;
class MakefileTemplate
{
/**
* @inheritDoc
* @param ProjectManager $project_manager
* @throws IOException
* @throws PathNotFoundException
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
self::writeMakefileTemplate($project_manager);
}
/**
* Writes the Makefile template for the given project.
*
* @param ProjectManager $project_manager The project manager containing project configurations.
* @throws IOException If there is an error reading or writing files.
* @throws PathNotFoundException If a required file path is not found.
*/
private static function writeMakefileTemplate(ProjectManager $project_manager): void
{
$makefile_template = IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'Makefile.tpl');
$builds = [];
foreach($project_manager->getProjectConfiguration()->getBuild()->getBuildConfigurations() as $build_name)
{
$builds[$build_name] = str_replace('%TPL_BUILD_NAME%', $build_name, IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'make_build.tpl'));
}
$default_build = $project_manager->getProjectConfiguration()->getBuild()->getDefaultConfiguration();
$makefile_template = str_replace('%TPL_DEFAULT_BUILD_CONFIGURATION%', $default_build, $makefile_template);
$makefile_template = str_replace('%TPL_DEFAULT_BUILD_PATH%', $project_manager->getProjectConfiguration()->getBuild()->getBuildConfiguration($default_build)->getOutput(), $makefile_template);
$makefile_template = str_replace('%TPL_BUILD_NAMES%', implode(' ', array_keys($builds)), $makefile_template);
$build_template = '';
foreach($builds as $name => $template)
{
$build_template .= $template . PHP_EOL;
}
$makefile_template = str_replace('%TPL_BUILDS%', $build_template, $makefile_template);
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'Makefile',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(), $makefile_template)
);
}
}

View file

@ -1,93 +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\PhpExtension\Templates;
use ncc\Classes\NccExtension\ConstantCompiler;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\Options\ProjectOptions;
use ncc\Enums\Runners;
use ncc\Enums\SpecialConstants\AssemblyConstants;
use ncc\Enums\Types\BuildOutputType;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\PathNotFoundException;
use ncc\Interfaces\TemplateInterface;
use ncc\Managers\ProjectManager;
use ncc\Objects\ProjectConfiguration\Build\BuildConfiguration;
use ncc\Objects\ProjectConfiguration\ExecutionPolicy;
use ncc\Utilities\IO;
class PhpUnitTemplate implements TemplateInterface
{
/**
* Applies the necessary templates for the given project.
*
* @param ProjectManager $project_manager Manager responsible for handling project-related tasks.
*
* @return void
*/
public static function applyTemplate(ProjectManager $project_manager): void
{
self::createPhpUnitBootstrapTemplate($project_manager);
self::createPhpUnitTemplate($project_manager);
}
/**
* Creates a PHPUnit template in the specified project directory.
*
* @param ProjectManager $project_manager The project manager instance containing project configuration and path details.
* @return void
* @throws IOException
* @throws PathNotFoundException
*/
private static function createPhpUnitTemplate(ProjectManager $project_manager): void
{
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'phpunit.xml',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'phpunit.xml.tpl')
)
);
if(!file_exists($project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'tests'))
{
mkdir($project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'tests');
}
}
/**
* Creates the PHPUnit bootstrap template file for the given project.
*
* @param ProjectManager $project_manager The project manager instance handling project configuration and paths.
* @return void
*/
private static function createPhpUnitBootstrapTemplate(ProjectManager $project_manager): void
{
IO::fwrite(
$project_manager->getProjectPath() . DIRECTORY_SEPARATOR . 'bootstrap.php',
ConstantCompiler::compileConstants($project_manager->getProjectConfiguration(),
IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php.tpl')
)
);
}
}

View file

@ -1,3 +0,0 @@
<?php
require 'ncc';
import('%ASSEMBLY.PACKAGE%');

View file

@ -1,187 +0,0 @@
name: CI
on:
push:
branches:
- '**'
release:
types: [created]
workflow_dispatch:
jobs:
%TPL_BUILDS%
# Checking for phpunit.xml
check-phpunit:
runs-on: ubuntu-latest
outputs:
phpunit-exists: ${{ steps.check.outputs.phpunit-exists }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check for phpunit.xml
id: check
run: |
if [ -f phpunit.xml ]; then
echo "phpunit-exists=true" >> $GITHUB_OUTPUT
else
echo "phpunit-exists=false" >> $GITHUB_OUTPUT
fi
# Checking for phpdoc.dist.xml
check-phpdoc:
runs-on: ubuntu-latest
outputs:
phpdoc-exists: ${{ steps.check.outputs.phpdoc-exists }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check for phpdoc.dist.xml
id: check
run: |
if [ -f phpdoc.dist.xml ]; then
echo "phpdoc-exists=true" >> $GITHUB_OUTPUT
else
echo "phpdoc-exists=false" >> $GITHUB_OUTPUT
fi
generate-phpdoc:
needs: [%TPL_DEFAULT_BUILD_CONFIGURATION%, check-phpdoc]
runs-on: ubuntu-latest
container:
image: php:8.3
if: needs.check-phpdoc.outputs.phpdoc-exists == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
apt update -yqq
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
- name: Download PHPDocumentor
run: |
wget https://phpdoc.org/phpDocumentor.phar
chmod +x phpDocumentor.phar
- name: Generate PHPDoc
run: |
php phpDocumentor.phar -d src -t docs
- name: Archive PHPDoc
run: |
zip -r docs.zip docs
- name: Upload PHPDoc
uses: actions/upload-artifact@v4
with:
name: documentation
path: docs.zip
test:
needs: [%TPL_BUILD_NAMES%, check-phpunit]
runs-on: ubuntu-latest
container:
image: php:8.3
if: needs.check-phpunit.outputs.phpunit-exists == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: %TPL_DEFAULT_BUILD_CONFIGURATION%
path: %TPL_DEFAULT_BUILD_CONFIGURATION%
- name: Install dependencies
run: |
apt update -yqq
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
curl -sSLf -o /usr/local/bin/install-php-extensions https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions
chmod +x /usr/local/bin/install-php-extensions
install-php-extensions zip
- name: Install phive
run: |
wget -O phive.phar https://phar.io/releases/phive.phar
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
gpg --verify phive.phar.asc phive.phar
chmod +x phive.phar
mv phive.phar /usr/local/bin/phive
- name: Install phab
run: |
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
- name: Install latest version of NCC
run: |
git clone https://git.n64.cc/nosial/ncc.git
cd ncc
make redist
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
if [ -z "$NCC_DIR" ]; then
echo "NCC build directory not found"
exit 1
fi
php "$NCC_DIR/INSTALL" --auto
cd .. && rm -rf ncc
- name: Install NCC packages
run: |
ncc package install --package="%TPL_DEFAULT_ARTIFACT_BUILD_OUTPUT%" --build-source --reinstall -y --log-level debug
- name: Run PHPUnit tests
run: |
wget https://phar.phpunit.de/phpunit-11.3.phar
php phpunit-11.3.phar --configuration phpunit.xml --log-junit reports/junit.xml --log-teamcity reports/teamcity --testdox-html reports/testdox.html --testdox-text reports/testdox.txt
- name: Upload test reports
uses: actions/upload-artifact@v4
with:
name: reports
path: reports
release-documentation:
needs: generate-phpdoc
permissions: write-all
runs-on: ubuntu-latest
container:
image: php:8.3
if: github.event_name == 'release'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download documentation artifact
uses: actions/download-artifact@v4
with:
name: documentation
path: documentation
- name: Upload documentation artifact
uses: softprops/action-gh-release@v1
with:
files: |
documentation/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
release-artifacts:
needs: [%TPL_BUILD_NAMES%]
permissions: write-all
runs-on: ubuntu-latest
container:
image: php:8.3
if: github.event_name == 'release'
steps:
- name: Checkout repository
uses: actions/checkout@v4
%TPL_DOWNLOAD_ARTIFACTS%

View file

@ -1,49 +0,0 @@
%TPL_BUILD_NAME%:
runs-on: ubuntu-latest
container:
image: php:8.3
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
apt update -yqq
apt install git libpq-dev libzip-dev zip make wget gnupg -yqq
- name: Install phive
run: |
wget -O phive.phar https://phar.io/releases/phive.phar
wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc
gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79
gpg --verify phive.phar.asc phive.phar
chmod +x phive.phar
mv phive.phar /usr/local/bin/phive
- name: Install phab
run: |
phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C
- name: Install latest version of NCC
run: |
git clone https://git.n64.cc/nosial/ncc.git
cd ncc
make redist
NCC_DIR=$(find build/ -type d -name "ncc_*" | head -n 1)
if [ -z "$NCC_DIR" ]; then
echo "NCC build directory not found"
exit 1
fi
php "$NCC_DIR/INSTALL" --auto
cd .. && rm -rf ncc
- name: Build project
run: |
ncc build --config %TPL_BUILD_NAME% --build-source --log-level debug
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: %TPL_BUILD_NAME%
path: %TPL_BUILD_OUTPUT%

View file

@ -1,12 +0,0 @@
- name: Download %TPL_BUILD_NAME% artifact
uses: actions/download-artifact@v4
with:
name: %TPL_BUILD_NAME%
path: %TPL_BUILD_NAME%
- name: Upload %TPL_BUILD_NAME% artifact to release
uses: softprops/action-gh-release@v1
with:
files: |
%TPL_BUILD_NAME%/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,2 +0,0 @@
%TPL_BUILD_NAME%:
ncc build --config=%TPL_BUILD_NAME% --log-level $(LOG_LEVEL)

View file

@ -1,11 +0,0 @@
<phpunit bootstrap="bootstrap.php">
<testsuites>
<testsuite name="%ASSEMBLY.NAME% Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<ini name="error_reporting" value="-1"/>
<server name="KERNEL_DIR" value="app/"/>
</php>
</phpunit>

View file

@ -29,12 +29,9 @@
use ncc\Enums\FileDescriptor;
use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\Options\BuildConfigurationOptions;
use ncc\Enums\Options\ComponentDecodeOptions;
use ncc\Enums\PackageDirectory;
use ncc\Enums\Versions;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\ImportException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException;
use ncc\Exceptions\NotSupportedException;
use ncc\Exceptions\OperationException;
@ -42,14 +39,8 @@
use ncc\Extensions\ZiProto\ZiProto;
use ncc\Managers\PackageManager;
use ncc\Objects\Package\Metadata;
use ncc\Utilities\Console;
use ncc\Utilities\IO;
use ncc\Utilities\Resolver;
use ncc\Utilities\RuntimeCache;
use ncc\Utilities\Validate;
use RuntimeException;
use Throwable;
use function trigger_error;
class Runtime
{
@ -68,26 +59,19 @@
*/
private static $package_manager;
/**
* @var array
*/
private static $included_files = [];
/**
* Executes the main execution point of an imported package and returns the evaluated result
* This method may exit the program without returning a value
*
* @param string $package
* @param array $arguments
* @return mixed
* @throws ConfigurationException
* @throws IOException
* @throws IntegrityException
* @throws NotSupportedException
* @throws OperationException
* @throws PathNotFoundException
* @throws OperationException
*/
public static function execute(string $package, array $arguments=[]): int
public static function execute(string $package): int
{
if(!self::isImported($package))
{
@ -96,12 +80,6 @@
if(self::$imported_packages[$package] instanceof PackageReader)
{
if(self::$imported_packages[$package]?->getMetadata()?->getMainExecutionPolicy() === null)
{
Console::out('The package does not have a main execution policy, skipping execution');
return 0;
}
return ExecutionUnitRunner::executeFromPackage(
self::$imported_packages[$package],
self::$imported_packages[$package]->getMetadata()->getMainExecutionPolicy()
@ -110,7 +88,7 @@
if(is_string(self::$imported_packages[$package]))
{
$metadata_path = self::$imported_packages[$package] . DIRECTORY_SEPARATOR . FileDescriptor::METADATA->value;
$metadata_path = self::$imported_packages[$package] . DIRECTORY_SEPARATOR . FileDescriptor::METADATA;
if(!is_file($metadata_path))
{
@ -119,8 +97,7 @@
return ExecutionUnitRunner::executeFromSystem(
self::$imported_packages[$package],
Metadata::fromArray(ZiProto::decode(IO::fread($metadata_path)))->getMainExecutionPolicy(),
$arguments
Metadata::fromArray(ZiProto::decode(IO::fread($metadata_path)))->getMainExecutionPolicy()
);
}
@ -133,7 +110,7 @@
* @return string
* @throws ImportException
*/
public static function import(string $package, string $version=Versions::LATEST->value): string
public static function import(string $package, string $version=Versions::LATEST): string
{
if(self::isImported($package))
{
@ -172,7 +149,7 @@
}
}
throw new RuntimeException(sprintf('Failed to import package "%s" because it does not exist', $package));
throw new RuntimeException('Importing from a package name is not supported yet');
}
/**
@ -185,7 +162,7 @@
* @throws NotSupportedException
* @throws PathNotFoundException
*/
private static function importFromSystem(string $package, string $version=Versions::LATEST->value): string
private static function importFromSystem(string $package, string $version=Versions::LATEST): string
{
if(!self::getPackageManager()->getPackageLock()->entryExists($package))
{
@ -193,7 +170,6 @@
}
$entry = self::getPackageManager()->getPackageLock()->getEntry($package);
self::$imported_packages[$package] = $entry->getPath($version);
foreach($entry->getClassMap($version) as $class => $component_name)
{
@ -201,81 +177,29 @@
self::$class_map[strtolower($class)] = $component_path;
}
if($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) !== null)
if($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES) !== null)
{
foreach($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) as $item)
foreach($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES) as $item)
{
$required_file = $entry->getPath($version) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . $item;
try
{
if(!file_exists($required_file))
{
throw new PathNotFoundException($required_file);
}
// Get the file contents and prepare it
$evaluated_code = IO::fread($required_file);
$required_file = IO::fread($entry->getPath($version) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . $item);
$required_file = preg_replace('/^<\?php|<\?PHP/', '', $required_file, 1);
// Remove the PHP tags
$evaluated_code = preg_replace('/^<\?php|<\?PHP/', '', $evaluated_code, 1);
// Replace __DIR__ with the actual directory that the file is in
$evaluated_code = str_replace('__DIR__', sprintf('"%s"', dirname($required_file)), $evaluated_code);
set_error_handler(function ($error_number, $message, $file, $line) use ($item, $package)
{
throw new ImportException(sprintf('Fatal Evaluation Error: Failed to import "%s" from %s on %s:%s: %s', $item, $package, $file, $line, $message));
});
// Evaluate the code
eval($evaluated_code);
restore_error_handler();
unset($evaluated_code);
eval($required_file);
unset($required_file);
}
catch (ConfigurationException $e)
catch(ConfigurationException $e)
{
throw new ImportException(sprintf('%s: Failed to import "%s" from %s: %s', $required_file, $item, $package, $e->getMessage()), $e);
}
catch(ImportException $e)
{
throw $e;
}
catch (Throwable $e)
{
throw new ImportException(sprintf('%s: Failed to import "%s" from %s: %s', $required_file, $item, $package, $e->getMessage()), $e);
throw new ImportException(sprintf('Failed to import "%s" from %s: %s', $item, $package, $e->getMessage()), $e);
}
}
}
$safe_package_name = strtoupper($entry->getAssembly($version)->getName());
foreach($entry->getMetadata($version)->getConstants() as $constant => $value)
{
$constant_full_name = sprintf("%s_%s", $safe_package_name, $constant);
self::$imported_packages[$package] = $entry->getPath($version);
// Skip if already defined.
if(defined($constant_full_name))
{
if(RuntimeCache::get(sprintf("defined_%s", $constant_full_name)))
{
continue;
}
trigger_error(sprintf('Cannot define constant %s from package %s because the constant is already defined', $constant_full_name, $package), E_USER_WARNING);
continue;
}
if(!Validate::constantName($constant_full_name))
{
// trigger warning only
trigger_error(sprintf('Cannot define constant %s from package %s because the constant name is invalid', $constant_full_name, $package), E_USER_WARNING);
continue;
}
RuntimeCache::set(sprintf("defined_%s", $constant_full_name), true);
define($constant_full_name, $value);
}
if(isset($entry->getMetadata($version)->getOptions()[PackageFlags::STATIC_DEPENDENCIES->value]))
if(isset($entry->getMetadata($version)->getOptions()[PackageFlags::STATIC_DEPENDENCIES]))
{
// Fake import the dependencies
foreach($entry->getVersion($version)->getDependencies() as $dependency)
@ -303,7 +227,7 @@
* @return string
* @throws ConfigurationException
* @throws ImportException
* @throws IntegrityException
* @throws NotSupportedException
* @throws OperationException
*/
private static function importFromPackage(string $package_path): string
@ -339,9 +263,9 @@
}
// Import the required files
if($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) !== null)
if($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES) !== null)
{
foreach($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) as $item)
foreach($package_reader->getMetadata()->getOption(BuildConfigurationOptions::REQUIRE_FILES) as $item)
{
try
{
@ -354,7 +278,7 @@
}
}
if($package_reader->getFlag(PackageFlags::STATIC_DEPENDENCIES->value))
if($package_reader->getFlag(PackageFlags::STATIC_DEPENDENCIES))
{
// Fake import the dependencies
foreach($package_reader->getDependencies() as $dependency_name)
@ -421,6 +345,7 @@
if(is_string(self::$class_map[$class]) && is_file(self::$class_map[$class]))
{
require_once self::$class_map[$class];
return;
}
}
@ -436,289 +361,4 @@
return self::$package_manager;
}
/**
* Returns an array of included files both from the php runtime and ncc runtime
*
* @return array
*/
public static function runtimeGetIncludedFiles(): array
{
return array_merge(get_included_files(), self::$included_files);
}
/**
* Evaluates and executes PHP code with error handling, this function
* gracefully handles <?php ?> tags and exceptions the same way as the
* require/require_once/include/include_once expressions
*
* @param string $code The PHP code to be executed
*/
public static function extendedEvaluate(string $code): void
{
if(ob_get_level() > 0)
{
ob_clean();
}
$exceptions = [];
$code = preg_replace_callback('/<\?php(.*?)\?>/s', static function ($matches) use (&$exceptions)
{
ob_start();
try
{
eval($matches[1]);
}
catch (Throwable $e)
{
$exceptions[] = $e;
}
return ob_get_clean();
}, $code);
ob_start();
try
{
eval('?>' . $code);
}
catch (Throwable $e)
{
$exceptions[] = $e;
}
if (!empty($exceptions))
{
print(ob_get_clean());
$exception_stack = null;
foreach ($exceptions as $e)
{
if($exception_stack === null)
{
$exception_stack = $e;
}
else
{
$exception_stack = new Exception($exception_stack->getMessage(), $exception_stack->getCode(), $e);
}
}
throw new RuntimeException('An exception occurred while evaluating the code', 0, $exception_stack);
}
print(ob_get_clean());
}
/**
* Returns the content of the aquired file
*
* @param string $path
* @param string|null $package
* @return string
* @throws ConfigurationException
* @throws IOException
* @throws OperationException
* @throws PathNotFoundException
* @throws IntegrityException
*/
private static function acquireFile(string $path, ?string $package=null): string
{
$cwd_checked = false; // sanity check to prevent checking the cwd twice
// Check if the file is absolute
if(is_file($path))
{
Console::outDebug(sprintf('Acquired file "%s" from absolute path', $path));
return IO::fread($path);
}
// Since $package is not null, let's try to acquire the file from the package
if($package !== null && isset(self::$imported_packages[$package]))
{
$base_path = basename($path);
if(self::$imported_packages[$package] instanceof PackageReader)
{
$acquired_file = self::$imported_packages[$package]->find($base_path);
Console::outDebug(sprintf('Acquired file "%s" from package "%s"', $path, $package));
return match (Resolver::componentType($acquired_file))
{
PackageDirectory::RESOURCES->value => self::$imported_packages[$package]->getResource(Resolver::componentName($acquired_file))->getData(),
PackageDirectory::COMPONENTS->value => self::$imported_packages[$package]->getComponent(Resolver::componentName($acquired_file))->getData([ComponentDecodeOptions::AS_FILE->value]),
default => throw new IOException(sprintf('Unable to acquire file "%s" from package "%s" because it is not a resource or component', $path, $package)),
};
}
if(is_dir(self::$imported_packages[$package]))
{
$base_path = basename($path);
foreach(IO::scan(self::$imported_packages[$package]) as $file)
{
if(str_ends_with($file, $base_path))
{
Console::outDebug(sprintf('Acquired file "%s" from package "%s"', $path, $package));
return IO::fread($file);
}
}
}
}
// If not, let's try the include_path
foreach(explode(PATH_SEPARATOR, get_include_path()) as $file_path)
{
if($file_path === '.' && !$cwd_checked)
{
$cwd_checked = true;
$file_path = getcwd();
}
if(is_file($file_path . DIRECTORY_SEPARATOR . $path))
{
Console::outDebug(sprintf('Acquired file "%s" from include_path', $path));
return IO::fread($file_path . DIRECTORY_SEPARATOR . $path);
}
if(is_file($file_path . DIRECTORY_SEPARATOR . basename($path)))
{
Console::outDebug(sprintf('Acquired file "%s" from include_path (using basename)', $path));
return IO::fread($file_path . DIRECTORY_SEPARATOR . basename($path));
}
}
// Check the current working directory
if(!$cwd_checked)
{
if(is_file(getcwd() . DIRECTORY_SEPARATOR . $path))
{
Console::outDebug(sprintf('Acquired file "%s" from current working directory', $path));
return IO::fread(getcwd() . DIRECTORY_SEPARATOR . $path);
}
if(is_file(getcwd() . DIRECTORY_SEPARATOR . basename($path)))
{
Console::outDebug(sprintf('Acquired file "%s" from current working directory (using basename)', $path));
return IO::fread(getcwd() . DIRECTORY_SEPARATOR . basename($path));
}
}
// Check the calling script's directory
$called_script_directory = dirname(debug_backtrace()[0]['file']);
$file_path = $called_script_directory . DIRECTORY_SEPARATOR . $path;
if(is_file($file_path))
{
Console::outDebug(sprintf('Acquired file "%s" from calling script\'s directory', $path));
return IO::fread($file_path);
}
throw new IOException(sprintf('Unable to acquire file "%s" because it does not exist', $path));
}
/**
* Includes a file at runtime
*
* @param string $path
* @param string|null $package
* @return void
*/
public static function runtimeInclude(string $path, ?string $package=null): void
{
try
{
$acquired_file = self::acquireFile($path, $package);
}
catch(Exception $e)
{
$package ?
Console::outWarning(sprintf('Failed to acquire file "%s" from package "%s" at runtime: %s', $path, $package, $e->getMessage())) :
Console::outWarning(sprintf('Failed to acquire file "%s" at runtime: %s', $path, $e->getMessage()));
return;
}
$acquired_name = $path;
if(!is_file($path))
{
$acquired_name = hash('crc32', $acquired_file);
}
if(!in_array($acquired_name, self::$included_files, true))
{
self::$included_files[] = sprintf('virtual(%s)', $acquired_name);
}
self::extendedEvaluate($acquired_file);
}
/**
* Includes a file at runtime if it's not already included
*
* @param string $path
* @param string|null $package
* @return void
*/
public static function runtimeIncludeOnce(string $path, ?string $package=null): void
{
if(in_array($path, self::runtimeGetIncludedFiles(), true))
{
return;
}
self::runtimeInclude($path, $package);
}
/**
* Requires a file at runtime, throws an exception if the file failed to require
*
* @param string $path
* @param string|null $package
* @return void
*/
public static function runtimeRequire(string $path, ?string $package=null): void
{
try
{
$acquired_file = self::acquireFile($path, $package);
}
catch(Exception $e)
{
$package ?
throw new RuntimeException(sprintf('Failed to acquire file "%s" from package "%s" at runtime: %s', $path, $package, $e->getMessage()), $e->getCode(), $e) :
throw new RuntimeException(sprintf('Failed to acquire file "%s" at runtime: %s', $path, $e->getMessage()), $e->getCode(), $e);
}
$acquired_name = $path;
if(!is_file($path))
{
$acquired_name = hash('crc32', $acquired_file);
}
if(!in_array($acquired_name, self::$included_files, true))
{
self::$included_files[] = sprintf('virtual(%s)', $acquired_name);
}
self::extendedEvaluate($acquired_file);
}
/**
* Requires a file at runtime if it's not already required
*
* @param string $path
* @return void
*/
public static function runtimeRequireOnce(string $path): void
{
if(in_array($path, self::runtimeGetIncludedFiles(), true))
{
return;
}
self::runtimeRequire($path);
}
}

View file

@ -0,0 +1,33 @@
<?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 CompilerExtensionDefaultVersions
{
// ----------------------------------------------------------------
// [0] = MinimumVersion
// [1] = MaximumVersion
// ----------------------------------------------------------------
public const PHP = ['8.0', '8.2'];
}

View file

@ -24,6 +24,5 @@
final class CompilerExtensionSupportedVersions
{
// TODO: Cannot convert this to enum, try another way
public const PHP = ['8.0', '8.1', '8.2'];
}

View file

@ -22,7 +22,11 @@
namespace ncc\Enums;
enum CompilerExtensions : string
final class CompilerExtensions
{
case PHP = 'php';
public const PHP = 'php';
public const ALL = [
CompilerExtensions::PHP
];
}

View file

@ -0,0 +1,33 @@
<?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 ComponentFileExtensions
{
/**
* The file extensions that the PHP compiler extension will accept as components.
*
* @var array
*/
public const PHP = ['*.php', '*.php3', '*.php4', '*.php5', '*.phtml'];
}

View file

@ -22,39 +22,39 @@
namespace ncc\Enums;
enum ConsoleColors : string
final class ConsoleColors
{
case DEFAULT = "\e[39m";
public const DEFAULT = "\e[39m";
case BLACK = "\e[30m";
public const BLACK = "\e[30m";
case RED = "\e[31m";
public const RED = "\e[31m";
case GREEN = "\e[32m";
public const GREEN = "\e[32m";
case YELLOW = "\e[33m";
public const YELLOW = "\e[33m";
case BLUE = "\e[34m";
public const BLUE = "\e[34m";
case MAGENTA = "\e[35m";
public const MAGENTA = "\e[35m";
case CYAN = "\e[36m";
public const CYAN = "\e[36m";
case LIGHT_GREY = "\e[37m";
public const LIGHT_GREY = "\e[37m";
case DARK_GREY = "\e[90m";
public const DARK_GREY = "\e[90m";
case LIGHT_RED = "\e[91m";
public const LIGHT_RED = "\e[91m";
case LIGHT_GREEN = "\e[92m";
public const LIGHT_GREEN = "\e[92m";
case LIGHT_YELLOW = "\e[93m";
public const LIGHT_YELLOW = "\e[93m";
case LIGHT_BLUE = "\e[94m";
public const LIGHT_BLUE = "\e[94m";
case LIGHT_MAGENTA = "\e[95m";
public const LIGHT_MAGENTA = "\e[95m";
case LIGHT_CYAN = "\e[96m";
public const LIGHT_CYAN = "\e[96m";
case WHITE = "\e[97m";
public const WHITE = "\e[97m";
}

View file

@ -0,0 +1,36 @@
<?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 ConstantReferences
{
public const ASSEMBLY = 'assembly';
public const BUILD = 'build';
public const DATE_TIME = 'date_time';
public const INSTALL = 'install';
public const RUNTIME = 'runtime';
}

View file

@ -26,80 +26,98 @@
* @author Zi Xing Narrakas
* @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved.
*/
enum ExceptionCodes : int
final class ExceptionCodes
{
/**
* @see RuntimeException
*/
case RUNTIME = -1706;
public const RUNTIME = -1706;
/**
* @see BuildException
*/
case BUILD_EXCEPTION = -1727;
public const BUILD_EXCEPTION = -1727;
/**
* @see IOException
*/
case IO_EXCEPTION = -1735;
public const IO_EXCEPTION = -1735;
/**
* @see ComposerException
*/
case COMPOSER_EXCEPTION = -1749;
public const COMPOSER_EXCEPTION = -1749;
/**
* @see AuthenticationException
*/
case AUTHENTICATION_EXCEPTION = -1760;
public const AUTHENTICATION_EXCEPTION = -1760;
/**
* @see NotSupportedException
*/
case NOT_SUPPORTED_EXCEPTION = -1761;
public const NOT_SUPPORTED_EXCEPTION = -1761;
/**
* @see ArchiveException
*/
case ARCHIVE_EXCEPTION = -1764;
public const ARCHIVE_EXCEPTION = -1764;
/**
* @see PathNotFoundException
*/
case PATH_NOT_FOUND = -1769;
public const PATH_NOT_FOUND = -1769;
/**
* @see GitException
*/
case GIT_EXCEPTION = -1770;
public const GIT_EXCEPTION = -1770;
/**
* @see ConfigurationException
*/
case CONFIGURATION_EXCEPTION = -1772;
public const CONFIGURATION_EXCEPTION = -1772;
/**
* @see PackageException
*/
case PACKAGE_EXCEPTION = -1773;
public const PACKAGE_EXCEPTION = -1773;
/**
* @see NetworkException
*/
case NETWORK_EXCEPTION = -1774;
public const NETWORK_EXCEPTION = -1774;
/**
* @see IntegrityException
*/
case INTEGRITY_EXCEPTION = -1775;
public const INTEGRITY_EXCEPTION = -1775;
/**
* @see OperationException
*/
case OPERATION_EXCEPTION = -1776;
public const OPERATION_EXCEPTION = -1776;
public const IMPORT_EXCEPTION = -1777;
/**
* @see ImportException
* All the exception codes from NCC
*/
case IMPORT_EXCEPTION = -1777;
public const All = [
self::RUNTIME,
self::BUILD_EXCEPTION,
self::IO_EXCEPTION,
self::COMPOSER_EXCEPTION,
self::AUTHENTICATION_EXCEPTION,
self::NOT_SUPPORTED_EXCEPTION,
self::ARCHIVE_EXCEPTION,
self::PATH_NOT_FOUND,
self::GIT_EXCEPTION,
self::CONFIGURATION_EXCEPTION,
self::PACKAGE_EXCEPTION,
self::NETWORK_EXCEPTION,
self::INTEGRITY_EXCEPTION,
self::OPERATION_EXCEPTION,
self::IMPORT_EXCEPTION
];
}

View file

@ -22,17 +22,17 @@
namespace ncc\Enums;
enum FileDescriptor : string
final class FileDescriptor
{
case ASSEMBLY = 'ASSEMBLY';
public const ASSEMBLY = 'ASSEMBLY';
case METADATA = 'METADATA';
public const METADATA = 'METADATA';
case INSTALLER = 'INSTALLER';
public const INSTALLER = 'INSTALLER';
case CLASS_MAP = 'CLASS_MAP';
public const CLASS_MAP = 'CLASS_MAP';
case UPDATE = 'UPDATE';
public const UPDATE = 'UPDATE';
case SHADOW_PACKAGE = 'SHADOW_PKG';
public const SHADOW_PACKAGE = 'SHADOW_PKG';
}

View file

@ -22,15 +22,23 @@
namespace ncc\Enums\Flags;
enum ComponentFlags : string
final class ComponentFlags
{
/**
* Indicates that the component is the AST of a PHP file encoded with msgpack.
*/
case PHP_AST = 'php_ast';
public const PHP_AST = 'php_ast';
/**
* Indicates that the component is a PHP file encoded with base64.
*/
case PHP_B64 = 'php_b64';
public const PHP_B64 = 'php_b64';
/**
* All the possible flags of a component
*/
public const ALL = [
self::PHP_AST,
self::PHP_B64
];
}

View file

@ -22,16 +22,16 @@
namespace ncc\Enums\Flags;
enum NccBuildFlags : string
final class NccBuildFlags
{
/**
* Indicates if the build is currently unstable and some features may not work correctly
* and can cause errors
*/
case UNSTABLE = 'unstable';
public const UNSTABLE = 'unstable';
/**
* Indicates if the build is currently in beta testing phase
*/
case BETA = 'beta';
public const BETA = 'beta';
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Flags;
enum PackageFlags : string
final class PackageFlags
{
case COMPRESSION = 'gzip';
public const COMPRESSION = 'gzip';
case LOW_COMPRESSION = 'low_gz`';
public const LOW_COMPRESSION = 'low_gz`';
case MEDIUM_COMPRESSION = 'medium_gz';
public const MEDIUM_COMPRESSION = 'medium_gz';
case HIGH_COMPRESSION = 'high_gz';
public const HIGH_COMPRESSION = 'high_gz';
case STATIC_DEPENDENCIES = 'static_dependencies';
public const STATIC_DEPENDENCIES = 'static_dependencies';
}

View file

@ -0,0 +1,124 @@
<?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 HttpStatusCodes
{
public const OK = 200;
public const CREATED = 201;
public const ACCEPTED = 202;
public const NO_CONTENT = 204;
public const MOVED_PERMANENTLY = 301;
public const FOUND = 302;
public const SEE_OTHER = 303;
public const NOT_MODIFIED = 304;
public const TEMPORARY_REDIRECT = 307;
public const PERMANENT_REDIRECT = 308;
public const BAD_REQUEST = 400;
public const UNAUTHORIZED = 401;
public const FORBIDDEN = 403;
public const NOT_FOUND = 404;
public const METHOD_NOT_ALLOWED = 405;
public const NOT_ACCEPTABLE = 406;
public const REQUEST_TIMEOUT = 408;
public const CONFLICT = 409;
public const GONE = 410;
public const LENGTH_REQUIRED = 411;
public const PRECONDITION_FAILED = 412;
public const PAYLOAD_TOO_LARGE = 413;
public const URI_TOO_LONG = 414;
public const UNSUPPORTED_MEDIA_TYPE = 415;
public const RANGE_NOT_SATISFIABLE = 416;
public const EXPECTATION_FAILED = 417;
public const IM_A_TEAPOT = 418;
public const MISDIRECTED_REQUEST = 421;
public const UNPROCESSABLE_ENTITY = 422;
public const LOCKED = 423;
public const FAILED_DEPENDENCY = 424;
public const UPGRADE_REQUIRED = 426;
public const PRECONDITION_REQUIRED = 428;
public const TOO_MANY_REQUESTS = 429;
public const REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
public const UNAVAILABLE_FOR_LEGAL_REASONS = 451;
public const INTERNAL_SERVER_ERROR = 500;
public const NOT_IMPLEMENTED = 501;
public const BAD_GATEWAY = 502;
public const SERVICE_UNAVAILABLE = 503;
public const GATEWAY_TIMEOUT = 504;
public const HTTP_VERSION_NOT_SUPPORTED = 505;
public const VARIANT_ALSO_NEGOTIATES = 506;
public const INSUFFICIENT_STORAGE = 507;
public const LOOP_DETECTED = 508;
public const NOT_EXTENDED = 510;
public const NETWORK_AUTHENTICATION_REQUIRED = 511;
public const ALL = [
self::OK,
self::CREATED,
self::ACCEPTED,
self::NO_CONTENT,
self::MOVED_PERMANENTLY,
self::FOUND,
self::SEE_OTHER,
self::NOT_MODIFIED,
self::TEMPORARY_REDIRECT,
self::PERMANENT_REDIRECT,
self::BAD_REQUEST,
self::UNAUTHORIZED,
self::FORBIDDEN,
self::NOT_FOUND,
self::METHOD_NOT_ALLOWED,
self::NOT_ACCEPTABLE,
self::REQUEST_TIMEOUT,
self::CONFLICT,
self::GONE,
self::LENGTH_REQUIRED,
self::PRECONDITION_FAILED,
self::PAYLOAD_TOO_LARGE,
self::URI_TOO_LONG,
self::UNSUPPORTED_MEDIA_TYPE,
self::RANGE_NOT_SATISFIABLE,
self::EXPECTATION_FAILED,
self::IM_A_TEAPOT,
self::MISDIRECTED_REQUEST,
self::UNPROCESSABLE_ENTITY,
self::LOCKED,
self::FAILED_DEPENDENCY,
self::UPGRADE_REQUIRED,
self::PRECONDITION_REQUIRED,
self::TOO_MANY_REQUESTS,
self::REQUEST_HEADER_FIELDS_TOO_LARGE,
self::UNAVAILABLE_FOR_LEGAL_REASONS,
self::INTERNAL_SERVER_ERROR,
self::NOT_IMPLEMENTED,
self::BAD_GATEWAY,
self::SERVICE_UNAVAILABLE,
self::GATEWAY_TIMEOUT,
self::HTTP_VERSION_NOT_SUPPORTED,
self::VARIANT_ALSO_NEGOTIATES,
self::INSUFFICIENT_STORAGE,
self::LOOP_DETECTED,
self::NOT_EXTENDED,
self::NETWORK_AUTHENTICATION_REQUIRED
];
}

View file

@ -22,65 +22,29 @@
namespace ncc\Enums;
use ncc\Utilities\Validate;
enum LogLevel : string
final class LogLevel
{
case SILENT = 'silent';
public const SILENT = 'silent';
case VERBOSE = 'verbose';
public const VERBOSE = 'verbose';
case DEBUG = 'debug';
public const DEBUG = 'debug';
case INFO = 'info';
public const INFO = 'info';
case WARNING = 'warn';
public const WARNING = 'warn';
case ERROR = 'error';
public const ERROR = 'error';
case FATAL = 'fatal';
public const FATAL = 'fatal';
/**
* Checks if the current log level permits logging at the specified level.
*
* @param LogLevel|null $current_level The log level to be checked. If null, the method returns false.
* @return bool Returns true if logging is permitted at the specified level, otherwise false.
*/
public function checkLogLevel(?LogLevel $current_level): bool
{
if ($current_level === null)
{
return false;
}
return match ($current_level)
{
LogLevel::DEBUG => in_array($this, [LogLevel::DEBUG, LogLevel::VERBOSE, LogLevel::INFO, LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::VERBOSE => in_array($this, [LogLevel::VERBOSE, LogLevel::INFO, LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::INFO => in_array($this, [LogLevel::INFO, LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::WARNING => in_array($this, [LogLevel::WARNING, LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::ERROR => in_array($this, [LogLevel::FATAL, LogLevel::ERROR], true),
LogLevel::FATAL => $this === LogLevel::FATAL,
default => false,
};
}
/**
* Converts the given string input to a LogLevel.
* If the input is invalid or not found, it defaults to LogLevel::INFO.
*
* @param string $input The input string to be converted to a LogLevel.
* @return LogLevel Returns the corresponding LogLevel for the input string or LogLevel::INFO if not found.
*/
public static function fromOrDefault(string $input): LogLevel
{
$value = self::tryFrom($input);
if($value === null)
{
return self::INFO;
}
return $value;
}
public const ALL = [
self::SILENT,
self::VERBOSE,
self::DEBUG,
self::INFO,
self::WARNING,
self::ERROR,
self::FATAL,
];
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Options;
enum BuildConfigurationOptions : string
final class BuildConfigurationOptions
{
case COMPRESSION = 'compression';
public const COMPRESSION = 'compression';
case REQUIRE_FILES = 'require_files';
public const REQUIRE_FILES = 'require_files';
case NCC_CONFIGURATION = 'ncc_configuration';
public const NCC_CONFIGURATION = 'ncc_configuration';
case OUTPUT_FILE = 'output_file';
public const OUTPUT_FILE = 'output_file';
case STATIC_DEPENDENCIES = 'static';
public const STATIC_DEPENDENCIES = 'static';
}

View file

@ -22,11 +22,11 @@
namespace ncc\Enums\Options\BuildConfigurationOptions;
enum CompressionOptions : string
final class CompressionOptions
{
case HIGH = 'high';
public const HIGH = 'high';
case MEDIUM = 'medium';
public const MEDIUM = 'medium';
case LOW = 'low';
public const LOW = 'low';
}

View file

@ -22,9 +22,9 @@
namespace ncc\Enums\Options;
enum BuildConfigurationValues : string
final class BuildConfigurationValues
{
case DEFAULT = 'default';
public const DEFAULT = 'default';
case ALL = 'all';
public const ALL = 'all';
}

View file

@ -22,7 +22,7 @@
namespace ncc\Enums\Options;
enum ComponentDecodeOptions : string
final class ComponentDecodeOptions
{
case AS_FILE = 'as_file';
public const AS_FILE = 'as_file';
}

View file

@ -22,25 +22,25 @@
namespace ncc\Enums\Options;
enum InitializeProjectOptions : string
final class InitializeProjectOptions
{
/**
* A custom path to the project's source directory
*/
case PROJECT_SRC_PATH = 'PROJECT_SRC_PATH';
public const PROJECT_SRC_PATH = 'PROJECT_SRC_PATH';
/**
* A boolean option that indicates whether to overwrite the project file if it already exists
*/
case OVERWRITE_PROJECT_FILE = 'OVERWRITE_PROJECT_FILE';
public const OVERWRITE_PROJECT_FILE = 'OVERWRITE_PROJECT_FILE';
/**
* Composer Only, used to define the package's real version
*/
case COMPOSER_PACKAGE_VERSION = 'COMPOSER_PACKAGE_VERSION';
public const COMPOSER_PACKAGE_VERSION = 'COMPOSER_PACKAGE_VERSION';
/**
* Composer Only, used to define the package's update source
*/
case COMPOSER_REMOTE_SOURCE = 'COMPOSER_REMOTE_SOURCE';
public const COMPOSER_REMOTE_SOURCE = 'COMPOSER_REMOTE_SOURCE';
}

View file

@ -22,7 +22,7 @@
namespace ncc\Enums\Options;
enum InstallPackageOptions : string
final class InstallPackageOptions
{
/**
* Skips the installation of dependencies of the package
@ -30,23 +30,17 @@
* @warning This will cause the package to fail to import of
* the dependencies are not met
*/
case SKIP_DEPENDENCIES = 'skip-dependencies';
public const SKIP_DEPENDENCIES = 'skip_dependencies';
/**
* Reinstall all packages if they are already installed,
* Including dependencies if they are being processed.
*/
case REINSTALL = 'reinstall';
public const REINSTALL = 'reinstall';
/**
* Installs a static version of the package if it's available
* otherwise it will install non-static version
*/
case PREFER_STATIC = 'prefer-static';
/**
* Forces ncc to build packages from source rather than trying to obtain
* a pre-built version of the package
*/
case BUILD_SOURCE = 'build-source';
public const PREFER_STATIC = 'prefer_static';
}

View file

@ -22,7 +22,7 @@
namespace ncc\Enums\Options;
enum ProjectOptions : string
final class ProjectOptions
{
case CREATE_SYMLINK = 'create_symlink';
public const CREATE_SYMLINK = 'create_symlink';
}

View file

@ -0,0 +1,38 @@
<?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\Options;
final class RuntimeImportOptions
{
/**
* Indicates if the import should require PHP's autoload.php file
* for the package (Only applies to PHP packages)
*/
public const IMPORT_AUTOLOADER = 'import_autoloader';
/**
* Indicates if the import should require all static files
* for the package (Only applies to PHP packages)
*/
public const IMPORT_STATIC_FILES = 'import_static_files';
}

View file

@ -22,21 +22,21 @@
namespace ncc\Enums;
enum PackageDirectory : int
final class PackageDirectory
{
case ASSEMBLY = 0x61737365;
public const ASSEMBLY = 0x61737365;
case METADATA = 0x6D657461;
public const METADATA = 0x6D657461;
case INSTALLER = 0x696E7374;
public const INSTALLER = 0x696E7374;
case DEPENDENCIES = 0x64657065;
public const DEPENDENCIES = 0x64657065;
case EXECUTION_UNITS = 0x65786563;
public const EXECUTION_UNITS = 0x65786563;
case COMPONENTS = 0x636F6D70;
public const COMPONENTS = 0x636F6D70;
case RESOURCES = 0x7265736F;
public const RESOURCES = 0x7265736F;
case CLASS_POINTER = 0x636C6173;
public const CLASS_POINTER = 0x636C6173;
}

View 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 PackageStandardVersions
{
public const VERSION_1 = '1.0';
}

View file

@ -22,11 +22,11 @@
namespace ncc\Enums;
enum PackageStructure : int
final class PackageStructure
{
case FILE_VERSION = 0x73746669;
public const FILE_VERSION = 0x73746669;
case FLAGS = 0x73736166;
public const FLAGS = 0x73736166;
case DIRECTORY = 0x6f746365;
public const DIRECTORY = 0x6f746365;
}

View file

@ -1,36 +1,44 @@
<?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.
*
*/
/*
* 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;
namespace ncc\Enums;
enum PackageStructureVersions : string
final class PackageStructureVersions
{
/**
* ncc 1.0.0 to 1.0.3
*/
case _1_0 = '1.0';
public const _1_0 = '1.0';
/**
* ncc 1.0.4 and above
*/
case _2_0 = '2.0';
public const _2_0 = '2.0';
/**
* All supported versions
*/
public const ALL = [
self::_1_0,
self::_2_0
];
}

View file

@ -22,81 +22,23 @@
namespace ncc\Enums;
enum ProjectTemplates : string
final class ProjectTemplates
{
/**
* A template that is used to create a PHP library project
*/
case PHP_LIBRARY = 'phplib';
public const PHP_LIBRARY = 'phplib';
/**
* A template that is used to create a PHP CLI application project
*/
case PHP_CLI = 'phpcli';
public const PHP_CLI = 'phpcli';
/**
* A template for generating a Makefile for the PHP project
* An array of all the available project templates
*/
case PHP_MAKE = 'phpmake';
/**
* A template used for creating PHP Unit testing bootstrap
*/
case PHP_UNIT = 'phpunit';
/**
* A template that is used to create a PHP executable project
*/
case PHP_COMPRESSED = 'phpgz';
/**
* A template that is used to create a PHP executable project
*/
case PHP_EXECUTABLE = 'phpexe';
/**
* Template that combines PHP_LIBRARY, PHP_MAKE and PHP_UNIT in one
*/
case PHP_LIBRARY_FULL = 'phplib_full';
/**
* Template that combines PHP_LIBRARY, PHP_MAKE, PHP_UNIT and PHP_CLI in one
*/
case PHP_CLI_FULL = 'phpcli_full';
/**
* Template that applies a GitHub workflow CI that builds the project, tests the project and creates
* automatic builds for releases
*/
case PHP_GITHUB_CI = 'phpci_github';
/**
* Suggests the closest matching `ProjectTemplates` instance based on the given input string.
*
* @param string $input The input string to compare against.
* @return ProjectTemplates|null The closest matching `ProjectTemplates` instance, or null if no close match is found.
*/
public static function suggest(string $input): ?ProjectTemplates
{
$closest = null;
$shortest_distance = -1;
foreach (self::cases() as $case)
{
$distance = levenshtein($input, $case->value);
if ($distance === 0)
{
return $case;
}
if ($shortest_distance === -1 || $distance < $shortest_distance)
{
$closest = $case;
$shortest_distance = $distance;
}
}
return $closest ?: null;
}
public const ALL = [
self::PHP_LIBRARY,
self::PHP_CLI
];
}

View file

@ -26,27 +26,27 @@
* @author Zi Xing Narrakas
* @copyright Copyright (C) 2022-2023. Nosial - All Rights Reserved.
*/
enum RegexPatterns : string
final class RegexPatterns
{
case UUID = '{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di';
public const UUID = '{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di';
case PACKAGE_NAME_FORMAT = '/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+[0-9a-z_]$/';
public const PACKAGE_NAME_FORMAT = '/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+[0-9a-z_]$/';
case COMPOSER_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
public const COMPOSER_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
case PYTHON_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
public const PYTHON_VERSION_FORMAT = '/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?$/';
case SEMANTIC_VERSIONING_2 = '/^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/m';
public const SEMANTIC_VERSIONING_2 = '/^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/m';
case UNIX_PATH = '/^(((?:\.\/|\.\.\/|\/)?(?:\.?\w+\/)*)(\.?\w+\.?\w+))$/m';
public const UNIX_PATH = '/^(((?:\.\/|\.\.\/|\/)?(?:\.?\w+\/)*)(\.?\w+\.?\w+))$/m';
case CONSTANT_NAME = '/^([^\x00-\x7F]|[\w_.+]){2,64}$/';
public const CONSTANT_NAME = '/^([^\x00-\x7F]|[\w_\ \.\+\-]){2,64}$/';
case EXECUTION_POLICY_NAME = '/^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/m';
public const EXECUTION_POLICY_NAME = '/^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/m';
/**
* @author <purplex>
*/
case REMOTE_PACKAGE = '/^(?<vendor>[^\/\n]+)\/(?<package>[^:=\n@]+)(?:=(?<version>[^:@\n]+))?(?::(?<branch>[^@\n]+))?@(?<source>.*)$/m';
public const REMOTE_PACKAGE = '/^(?<vendor>[^\/\n]+)\/(?<package>[^:=\n@]+)(?:=(?<version>[^:@\n]+))?(?::(?<branch>[^@\n]+))?@(?<source>.*)$/m';
}

View file

@ -22,15 +22,25 @@
namespace ncc\Enums;
enum Runners : string
final class Runners
{
case PHP = 'php';
public const PHP = 'php';
case BASH = 'bash';
public const BASH = 'bash';
case PYTHON = 'python';
public const PYTHON = 'python';
case PERL = 'perl';
public const PERL = 'perl';
case LUA = 'lua';
public const LUA = 'lua';
public const ALL = [
self::PHP,
self::BASH,
self::PYTHON,
self::PYTHON_3,
self::PYTHON_2,
self::PERL,
self::LUA
];
}

View file

@ -22,9 +22,9 @@
namespace ncc\Enums;
enum Scopes : string
final class Scopes
{
case USER = 'USER';
public const USER = 'USER';
case SYSTEM = 'SYSTEM';
public const SYSTEM = 'SYSTEM';
}

View file

@ -22,50 +22,50 @@
namespace ncc\Enums\SpecialConstants;
enum AssemblyConstants : string
final class AssemblyConstants
{
/**
* Assembly's Name Property
*/
case ASSEMBLY_NAME = '%ASSEMBLY.NAME%';
public const ASSEMBLY_NAME = '%ASSEMBLY.NAME%';
/**
* Assembly's Package Property
*/
case ASSEMBLY_PACKAGE = '%ASSEMBLY.PACKAGE%';
public const ASSEMBLY_PACKAGE = '%ASSEMBLY.PACKAGE%';
/**
* Assembly's Description Property
*/
case ASSEMBLY_DESCRIPTION = '%ASSEMBLY.DESCRIPTION%';
public const ASSEMBLY_DESCRIPTION = '%ASSEMBLY.DESCRIPTION%';
/**
* Assembly's Company Property
*/
case ASSEMBLY_COMPANY = '%ASSEMBLY.COMPANY%';
public const ASSEMBLY_COMPANY = '%ASSEMBLY.COMPANY%';
/**
* Assembly's Product Property
*/
case ASSEMBLY_PRODUCT = '%ASSEMBLY.PRODUCT%';
public const ASSEMBLY_PRODUCT = '%ASSEMBLY.PRODUCT%';
/**
* Assembly's Copyright Property
*/
case ASSEMBLY_COPYRIGHT = '%ASSEMBLY.COPYRIGHT%';
public const ASSEMBLY_COPYRIGHT = '%ASSEMBLY.COPYRIGHT%';
/**
* Assembly's Trademark Property
*/
case ASSEMBLY_TRADEMARK = '%ASSEMBLY.TRADEMARK%';
public const ASSEMBLY_TRADEMARK = '%ASSEMBLY.TRADEMARK%';
/**
* Assembly's Version Property
*/
case ASSEMBLY_VERSION = '%ASSEMBLY.VERSION%';
public const ASSEMBLY_VERSION = '%ASSEMBLY.VERSION%';
/**
* Assembly's UUID property
*/
case ASSEMBLY_UID = '%ASSEMBLY.UID%';
public const ASSEMBLY_UID = '%ASSEMBLY.UID%';
}

View file

@ -22,25 +22,25 @@
namespace ncc\Enums\SpecialConstants;
enum BuildConstants : string
final class BuildConstants
{
/**
* The Unix Timestamp for when the package was compiled
*/
case COMPILE_TIMESTAMP = '%COMPILE_TIMESTAMP%';
public const COMPILE_TIMESTAMP = '%COMPILE_TIMESTAMP%';
/**
* The version of NCC that was used to compile the package
*/
case NCC_BUILD_VERSION = '%NCC_BUILD_VERSION%';
public const NCC_BUILD_VERSION = '%NCC_BUILD_VERSION%';
/**
* NCC Build Flags exploded into spaces
*/
case NCC_BUILD_FLAGS = '%NCC_BUILD_FLAGS%';
public const NCC_BUILD_FLAGS = '%NCC_BUILD_FLAGS%';
/**
* NCC Build Branch
*/
case NCC_BUILD_BRANCH = '%NCC_BUILD_BRANCH%';
public const NCC_BUILD_BRANCH = '%NCC_BUILD_BRANCH%';
}

View file

@ -22,49 +22,49 @@
namespace ncc\Enums\SpecialConstants;
enum DateTimeConstants : string
final class DateTimeConstants
{
// Day Format
/**
* Day of the month, 2 digits with leading zeros
*/
case d = '%d%'; // 01 through 31
public const d = '%d%'; // 01 through 31
/**
* A textual representation of a day, three letters
*/
case D = '%D%'; // Mon through Sun
public const D = '%D%'; // Mon through Sun
/**
* Day of the month without leading zeros
*/
case j = '%j%'; // 1 through 31
public const j = '%j%'; // 1 through 31
/**
* A full textual representation of the day of the week
*/
case l = '%l%'; // Sunday through Saturday
public const l = '%l%'; // Sunday through Saturday
/**
* ISO 8601 numeric representation of the day of the week
*/
case N = '%N%'; // 1 (Monday) to 7 (Sunday)
public const N = '%N%'; // 1 (Monday) to 7 (Sunday)
/**
* English ordinal suffix for the day of the month, 2 characters
*/
case S = '%S%'; // st, nd, rd, th
public const S = '%S%'; // st, nd, rd, th
/**
* Numeric representation of the day of the week
*/
case w = '%w%'; // 0 (sunday) through 6 (Saturday)
public const w = '%w%'; // 0 (sunday) through 6 (Saturday)
/**
* The day of the year (starting from 0)
*/
case z = '%z%'; // 0 through 365
public const z = '%z%'; // 0 through 365
@ -73,7 +73,7 @@
/**
* ISO 8601 week number of year, weeks starting on Monday
*/
case W = '%W%'; // 42 (42nd week in year)
public const W = '%W%'; // 42 (42nd week in year)
@ -82,27 +82,27 @@
/**
* A full textual representation of a month, such as January or March
*/
case F = '%F%'; // January through December
public const F = '%F%'; // January through December
/**
* Numeric representation of a month, with leading zeros
*/
case m = '%m%'; // 01 through 12
public const m = '%m%'; // 01 through 12
/**
* A short textual representation of a month, three letters
*/
case M = '%M%'; // Jan through Dec
public const M = '%M%'; // Jan through Dec
/**
* Numeric representation of a month, without leading zeros
*/
case n = '%n%'; // 1 through 12
public const n = '%n%'; // 1 through 12
/**
* Number of days in the given month
*/
case t = '%t%'; // 28 through 31
public const t = '%t%'; // 28 through 31
@ -110,73 +110,73 @@
/**
* Whether it's a leap year
*/
case L = '%L%'; // 1 (leap year), 0 otherwise
public const L = '%L%'; // 1 (leap year), 0 otherwise
/**
* ISO 8601 week-numbering year. This has the same value as Y,
* except that if the ISO week number (W) belongs to the previous
* or next year, that year is used instead.
*/
case o = '%o%'; // Same as Y, except that it use week number to decide which year it falls onto
public const o = '%o%'; // Same as Y, except that it use week number to decide which year it falls onto
/**
* A full numeric representation of a year, at least 4 digits, with - for years BCE.
*/
case Y = '%Y%'; // 1991, 2012, 2014, ...
public const Y = '%Y%'; // 1991, 2012, 2014, ...
/**
* A two digit representation of a year
*/
case y = '%y%'; // 91, 12, 14, ...
public const y = '%y%'; // 91, 12, 14, ...
// Time Format
/**
* Lowercase Ante meridiem and Post meridiem
*/
case a = '%a%'; // am or pm
public const a = '%a%'; // am or pm
/**
* Uppercase Ante meridiem and Post meridiem
*/
case A = '%A%'; // AM or PM
public const A = '%A%'; // AM or PM
/**
* Swatch Internet time
*/
case B = '%B%'; // 000 through 999
public const B = '%B%'; // 000 through 999
/**
* 12-hour format of an hour without leading zeros
*/
case g = '%g%'; // 1 through 12
public const g = '%g%'; // 1 through 12
/**
* 24-hour format of an hour without leading zeros
*/
case G = '%G%'; // 0 through 23
public const G = '%G%'; // 0 through 23
/**
* 12-hour format of an hour with leading zeros
*/
case h = '%h%'; // 01 through 12
public const h = '%h%'; // 01 through 12
/**
* 24-hour format of an hour with leading zeros
*/
case H = '%H%'; // 01 through 23
public const H = '%H%'; // 01 through 23
/**
* Minutes with leading zeros
*/
case i = '%i%'; // 01 through 59
public const i = '%i%'; // 01 through 59
/**
* Seconds with leading zeros
*/
case s = '%s%'; // 00 through 59
public const s = '%s%'; // 00 through 59
// DateTime format
case c = '%c%'; // 2004-02-12T15:19:21
case r = '%r%'; // Thu, 21 Dec 2000 16:01:07
case u = '%u%'; // Unix Timestamp (seconds since Jan 1 1970 00:00:00)
public const c = '%c%'; // 2004-02-12T15:19:21
public const r = '%r%'; // Thu, 21 Dec 2000 16:01:07
public const u = '%u%'; // Unix Timestamp (seconds since Jan 1 1970 00:00:00)
}

View file

@ -22,13 +22,13 @@
namespace ncc\Enums\SpecialConstants;
enum InstallConstants : string
final class InstallConstants
{
case INSTALL_PATH = '%INSTALL_PATH%';
public const INSTALL_PATH = '%INSTALL_PATH%';
case INSTALL_PATH_BIN = '%INSTALL_PATH.BIN%';
public const INSTALL_PATH_BIN = '%INSTALL_PATH.BIN%';
case INSTALL_PATH_SRC = '%INSTALL_PATH.SRC%';
public const INSTALL_PATH_SRC = '%INSTALL_PATH.SRC%';
case INSTALL_PATH_DATA = '%INSTALL_PATH.DATA%';
public const INSTALL_PATH_DATA = '%INSTALL_PATH.DATA%';
}

View file

@ -22,11 +22,11 @@
namespace ncc\Enums\SpecialConstants;
enum RuntimeConstants : string
final class RuntimeConstants
{
case CWD = '%CWD%';
case PID = '%PID%';
case UID = '%UID%';
case GID = '%GID%';
case USER = '%USER%';
public const CWD = '%CWD%';
public const PID = '%PID%';
public const UID = '%UID%';
public const GID = '%GID%';
public const USER = '%USER%';
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Types;
enum AuthenticationType : int
final class AuthenticationType
{
/**
* A combination of a username and password is used for authentication
*/
case USERNAME_PASSWORD = 1;
public const USERNAME_PASSWORD = 1;
/**
* A single private access token is used for authentication
*/
case ACCESS_TOKEN = 2;
public const ACCESS_TOKEN = 2;
}

View file

@ -22,8 +22,8 @@
namespace ncc\Enums\Types;
enum BuildOutputType : string
final class BuildOutputType
{
case NCC_PACKAGE = 'ncc';
case EXECUTABLE = 'executable';
public const NCC_PACKAGE = 'ncc';
public const EXECUTABLE = 'executable';
}

View file

@ -1,6 +1,6 @@
<?php
/*
* Copyright (c) Nosial 2022-2024, 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
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
@ -20,18 +20,18 @@
*
*/
namespace ncc\Enums\SpecialConstants;
namespace ncc\Enums\Types;
enum GeneralConstants : string
final class BuiltinRemoteSourceType
{
/**
* The project's default build configuration
* The remote source indicates the package is to be
* fetched using the composer utility.
*/
case DEFAULT_BUILD_CONFIGURATION = '%DEFAULT_BUILD_CONFIGURATION%';
public const COMPOSER = 'composer';
/**
* Configurable build output path
*/
case BUILD_OUTPUT_PATH = '%BUILD_OUTPUT_PATH%';
public const ALL = [
self::COMPOSER
];
}

View file

@ -22,25 +22,35 @@
namespace ncc\Enums\Types;
enum ComponentDataType : string
final class ComponentDataType
{
/**
* Indicates whether the component is represented as an AST representation
*/
case AST = 'ast';
public const AST = 'ast';
/**
* Indicates whether the component is represented as plaintext
*/
case PLAIN = 'plain';
public const PLAIN = 'plain';
/**
* Indicates whether the component is represented as binary or executable
*/
case BINARY = 'binary';
public const BINARY = 'binary';
/**
* Indicates whether the component is represented as as a base64 encoded string (Raw bytes' representation)
*/
case BASE64_ENCODED = 'b64enc';
public const BASE64_ENCODED = 'b64enc';
/**
* All the possible data types of a component
*/
public const ALL = [
self::AST,
self::PLAIN,
self::BINARY,
self::BASE64_ENCODED
];
}

View file

@ -22,12 +22,12 @@
namespace ncc\Enums\Types;
enum ComposerPackageTypes : string
final class ComposerPackageTypes
{
/**
* This is the default. It will copy the files to `vendor`
*/
case LIBRARY = 'library';
public const LIBRARY = 'library';
/**
* This denotes a project rather than a library. For example
@ -37,7 +37,7 @@
* to provide listings of projects to initialize when creating
* a new workspace.
*/
case PROJECT = 'project';
public const PROJECT = 'project';
/**
* An empty package that contains requirements and will trigger
@ -45,11 +45,11 @@
* anything to the filesystem. As such, it does not require a
* a dist or source key to be installable
*/
case METAPACKAGE = 'metapackage';
public const METAPACKAGE = 'metapackage';
/**
* A package of type `composer-plugin` may provide an installer
* for other packages that have a custom type.
*/
case COMPOSER_PLUGIN = 'composer-plugin';
public const COMPOSER_PLUGIN = 'composer-plugin';
}

View file

@ -22,15 +22,15 @@
namespace ncc\Enums\Types;
enum ComposerStabilityTypes : string
final class ComposerStabilityTypes
{
case DEV = 'dev';
public const DEV = 'dev';
case ALPHA = 'alpha';
public const ALPHA = 'alpha';
case BETA = 'beta';
public const BETA = 'beta';
case RC = 'rc';
public const RC = 'rc';
case STABLE ='stable';
public const STABLE ='stable';
}

View file

@ -0,0 +1,49 @@
<?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\Types;
final class DependencySourceType
{
/**
* The dependency pointer does not point to a package
*/
public const NONE = 'none';
/**
* Indicates if the dependency is statically linked and the
* reference points to the compiled package of the dependency
*/
public const STATIC = 'static';
/**
* Indicates if the pointer reference points to a remote source
* to fetch the dependency from
*/
public const REMOTE = 'remote';
/**
* Indicates if the pointer reference points to a relative file with the
* filename format "{package_name}=={version}.ncc" to fetch the dependency from
*/
public const LOCAL = 'local';
}

View 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\Types;
final class EncoderType
{
public const ZI_PROTO = '3';
}

View file

@ -22,10 +22,10 @@
namespace ncc\Enums\Types;
enum HttpRequestType : string
final class HttpRequestType
{
case GET = 'GET';
case POST = 'POST';
case PUT = 'PUT';
case DELETE = 'DELETE';
public const GET = 'GET';
public const POST = 'POST';
public const PUT = 'PUT';
public const DELETE = 'DELETE';
}

View file

@ -22,9 +22,14 @@
namespace ncc\Enums\Types;
enum ProjectType : string
final class ProjectType
{
case COMPOSER = 'composer';
public const COMPOSER = 'composer';
case NCC = 'ncc';
public const NCC = 'ncc';
public const ALL = [
self::COMPOSER,
self::NCC,
];
}

View file

@ -0,0 +1,56 @@
<?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\Types;
final class RemoteSourceType
{
/**
* A builtin source type is not defined by the user but handled by
* an extension built into NCC
*/
public const BUILTIN = 'builtin';
/**
* A defined source type is defined by the user in the remote sources file
* and handled by an extension designed by passing on the information of
* the source to the extension
*/
public const DEFINED = 'defined';
/**
* Unsupported or invalid source type
*/
public const UNKNOWN = 'unknown';
/**
* No remote source type
*/
public const NONE = 'none';
public const All = [
self::BUILTIN,
self::DEFINED,
self::UNKNOWN,
self::NONE
];
}

View file

@ -22,9 +22,9 @@
namespace ncc\Enums\Types;
enum RepositoryResultType : string
final class RepositoryResultType
{
case SOURCE = 'source';
public const SOURCE = 'source';
case PACKAGE = 'package';
public const PACKAGE = 'package';
}

View file

@ -22,13 +22,20 @@
namespace ncc\Enums\Types;
enum RepositoryType : string
final class RepositoryType
{
case GITLAB = 'gitlab';
public const GITLAB = 'gitlab';
case GITHUB = 'github';
public const GITHUB = 'github';
case GITEA = 'gitea';
public const GITEA = 'gitea';
case PACKAGIST = 'packagist';
public const PACKAGIST = 'packagist';
public const ALL = [
self::GITLAB,
self::GITHUB,
self::GITEA,
self::PACKAGIST
];
}

View file

@ -22,15 +22,25 @@
namespace ncc\Enums;
enum Versions : string
final class Versions
{
/**
* The current version of the credentials store file format
*/
case CREDENTIALS_STORE_VERSION = '1.0.0';
public const CREDENTIALS_STORE_VERSION = '1.0.0';
/**
* The current version of the package structure file format
*/
public const PACKAGE_STRUCTURE_VERSION = '2.0';
/**
* The current version of the package lock structure file format
*/
public const PACKAGE_LOCK_VERSION = '2.0.0';
/**
* Generic version of the package structure file format (latest)
*/
case LATEST = 'latest';
public const LATEST = 'latest';
}

View file

@ -34,6 +34,6 @@
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::ARCHIVE_EXCEPTION->value, $previous);
parent::__construct($message, ExceptionCodes::ARCHIVE_EXCEPTION, $previous);
}
}

View file

@ -34,6 +34,6 @@
*/
public function __construct(string $message = "", ?Throwable $previous = null)
{
parent::__construct($message, ExceptionCodes::AUTHENTICATION_EXCEPTION->value, $previous);
parent::__construct($message, ExceptionCodes::AUTHENTICATION_EXCEPTION, $previous);
}
}

Some files were not shown because too many files have changed in this diff Show more