Compare commits

..

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

518 changed files with 12971 additions and 18096 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,219 +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
supports pulling static versions of packages from repositories. Changes include enhanced security through an updated
fetchPackage method along with improvements in dependency imports and extension registration logic for Debian packages.
Finally, bugs related to unnecessary bundling of some build artifacts and mime type errors in ncc-package.xml have
been fixed.
### Added
- Added support for importing static packages from the system, allowing you to install static packages onto your
system and import them without importing additional dependencies that isn't already included in the package.
- Added the ability to pull static versions of packages from repositories where package names ending with `-static.ncc`
or `_static.ncc` can be pulled if you use the `--prefer-static` or `--static` option when using the `package install`
command. Otherwise, the normal package will be installed, avoiding static versions.
### Changed
- Updated fetchPackage method to include authentication
- Update dependencies import in \ncc\Classes > Runtime > importFromPackage()
- Refactor ncc extension registration logic, this also allows for debian packages to install the ncc extension
automatically.
### Fixed
- Fixed issue where some build artifacts are being bundled with package builds such as `output_path` and `static`
where they should not be included in the package.
- Corrected mistakes in `ncc-package.xml` mime type
## [2.0.1] - 2023-10-11
Added a new feature in `ProjectManager.php` that allows automatic installation of a project's dependencies. The

View file

@ -65,7 +65,7 @@ RUN chmod +x /usr/local/bin/install-php-extensions && sync && \
install-php-extensions zip xsl
# Install ncc
RUN php INSTALL --auto
RUN php INSTALL --auto; cd ../; rm -rf ncc
# Finalize image
RUN mkdir /app

View file

@ -65,7 +65,7 @@ RUN chmod +x /usr/local/bin/install-php-extensions && sync && \
install-php-extensions zip xsl
# Install ncc
RUN php INSTALL --auto
RUN php INSTALL --auto; cd ../; rm -rf ncc
# Finalize image
RUN mkdir /app

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
@ -76,6 +76,7 @@ redist: autoload
cp -f $(CONFIG_PATH)/ncc.yaml $(GENERIC_BUILD_PATH)/CLI/template_config.yaml
cp -f $(CONFIG_PATH)/default_repositories.json $(GENERIC_BUILD_PATH)/default_repositories.json
cp -f $(INSTALLER_SRC_PATH)/ncc-package.xml $(GENERIC_BUILD_PATH)/ncc-package.xml
cp -f $(INSTALLER_SRC_PATH)/extension $(GENERIC_BUILD_PATH)/extension
chmod +x $(GENERIC_BUILD_PATH)/INSTALL
cp -f LICENSE $(GENERIC_BUILD_PATH)/LICENSE
cp -f README.md $(GENERIC_BUILD_PATH)/README.md
@ -153,13 +154,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.1
Maintainer: netkas <netkas@nosial.net>
Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.5.1

View file

@ -24,7 +24,7 @@
* @param array $options
* @return string
*/
function import(string $package, string $version=Versions::LATEST->value, array $options=[]): string
function import(string $package, string $version=Versions::LATEST, array $options=[]): string
{
try
{

View file

@ -41,7 +41,8 @@
'installer',
'checksum.bin',
'build_files',
'ncc.sh'
'ncc.sh',
'extension'
];
ncc\Utilities\Console::out('Creating build_files ...');

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);
}
@ -352,6 +345,83 @@
}
}
// Register the ncc extension
try
{
Console::out('Registering extension');
$extension_shortcut = str_ireplace('%ncc_install', $NCC_INSTALL_PATH, IO::fread(__DIR__ . DIRECTORY_SEPARATOR . 'extension'));
}
catch(Exception $e)
{
Console::outException(sprintf('Failed to read file \'%s\', %s', __DIR__ . DIRECTORY_SEPARATOR . 'extension', $e->getMessage()), $e, 1);
return;
}
// Remove all the old extensions first.
/**
* @param string $path
* @param Filesystem $filesystem
* @param string $extension_shortcut
* @return bool
*/
function install_extension(string $path, Filesystem $filesystem, string $extension_shortcut): bool
{
if ($filesystem->exists($path . DIRECTORY_SEPARATOR . 'ncc'))
{
$filesystem->remove($path . DIRECTORY_SEPARATOR . 'ncc');
}
try
{
IO::fwrite($path . DIRECTORY_SEPARATOR . 'ncc', $extension_shortcut);
}
catch (\ncc\Exceptions\IOException $e)
{
Console::outException($e->getMessage(), $e, 1);
return false;
}
return $filesystem->exists($path . DIRECTORY_SEPARATOR . 'ncc');
}
if(function_exists('get_include_path'))
{
$default_share = DIRECTORY_SEPARATOR . 'usr' . DIRECTORY_SEPARATOR . 'share' . DIRECTORY_SEPARATOR . 'php';
$include_paths = explode(':', get_include_path());
$extension_registered = false;
if(!in_array($default_share, $include_paths))
{
foreach($include_paths as $path)
{
if($extension_registered)
{
break;
}
switch($path)
{
// Ignore local files
case '.':
case '..':
break;
// First real include path is /usr/share/php
default:
// Install the extension
$extension_registered = install_extension($path, $NCC_FILESYSTEM, $extension_shortcut);
break;
}
}
}
else
{
// Remove the old extension
install_extension($default_share, $NCC_FILESYSTEM, $extension_shortcut);
}
}
// Backup the configuration file
$config_backup = null;

View file

@ -21,11 +21,11 @@
-->
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/ncc">
<mime-type type="application/ncc-package">
<comment>ncc package binary</comment>
<magic priority="50">
<match type="string" value="ncc_pkg" offset="0"/>
</magic>
<glob pattern="*.ncc"/>
<glob pattern="*.ncc_pkg"/>
</mime-type>
</mime-info>

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,16 @@
$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;
}
if(isset($args['prefer-static']) || isset($args['static']))
{
$options[InstallPackageOptions::PREFER_STATIC->value] = true;
$options[InstallPackageOptions::REINSTALL] = 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 +188,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 +377,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 +408,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 +444,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;
@ -564,8 +548,6 @@
new CliHelpSection(['install', '--package', '-p', '--version', '-v'], 'Installs a specified ncc package version'),
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

@ -25,7 +25,6 @@
use CurlHandle;
use Exception;
use JsonException;
use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Types\AuthenticationType;
use ncc\Enums\Types\HttpRequestType;
use ncc\Enums\Types\RepositoryResultType;
@ -39,7 +38,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 +46,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): RepositoryResult
{
try
{
@ -65,9 +63,9 @@
/**
* @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): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication);
}
/**
@ -98,21 +96,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 +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);
}
@ -193,17 +185,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 +197,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 +245,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
]);
@ -320,26 +298,19 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. An array of options to use when fetching the package
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
private static function getReleasePackage(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);
}
$endpoint = sprintf('%s://%s/api/v1/repos/%s/%s/releases/tags/%s',
$repository->isSsl() ? 'https' : 'http',
$repository->getHost(),
rawurlencode($group),
rawurlencode($project),
rawurlencode($release)
);
$endpoint = sprintf('%s://%s/api/v1/repos/%s/%s/releases/tags/%s', ($repository->isSsl() ? 'https' : 'http'), $repository->getHost(), rawurlencode($group), rawurlencode($project), rawurlencode($release));
if(RuntimeCache::exists($endpoint))
{
@ -358,62 +329,30 @@
$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
]);
Console::outDebug(sprintf('Fetching release package for %s/%s/%s from %s',
$group, $project, $release, $endpoint));
Console::outDebug(sprintf('Fetching release package for %s/%s/%s from %s', $group, $project, $release, $endpoint));
$response = self::processHttpResponse($curl, $group, $project);
if(!isset($response['assets']))
{
throw new NetworkException(sprintf('Failed to get release %s package url for %s/%s',
$release, $group, $project));
throw new NetworkException(sprintf('Failed to get release %s package url for %s/%s', $release, $group, $project));
}
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$preferred_asset = null;
$fallback_asset = null;
foreach($response['assets'] as $asset)
{
if($static_preferred && preg_match('/(_static|-static)\.ncc$/', $asset['name']))
if(isset($asset['name'], $asset['browser_download_url']) && preg_match('/\.ncc$/', $asset['name']))
{
$preferred_asset = $asset;
}
elseif(preg_match('/\.ncc$/', $asset['name']))
{
$fallback_asset = $asset;
}
}
$target_asset = $preferred_asset ?: $fallback_asset;
if($target_asset)
{
$asset_url = $target_asset['browser_download_url'] ?? null;
if($asset_url)
{
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
$result = new RepositoryResult($asset['browser_download_url'], RepositoryResultType::PACKAGE, $release);
RuntimeCache::set($endpoint, $result);
return $result;
}
throw new NetworkException(sprintf('No direct asset URL found for %s/%s/%s', $group, $project, $release));
}
throw new NetworkException(sprintf('No ncc package found for %s/%s/%s', $group, $project, $release));
@ -429,7 +368,6 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. An array of options to use when fetching the archive
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
@ -437,7 +375,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 +399,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 +411,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 +446,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 +455,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;
@ -552,14 +483,14 @@
if($response === false)
{
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $group, $project, curl_error($curl), $retry_count + 1));
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $vendor, $project, curl_error($curl), $retry_count + 1));
$retry_count++;
}
}
if($response === false)
{
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $group, $project, curl_error($curl)));
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $vendor, $project, curl_error($curl)));
}
switch(curl_getinfo($curl, CURLINFO_HTTP_CODE))

View file

@ -25,7 +25,6 @@
use CurlHandle;
use Exception;
use JsonException;
use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Types\AuthenticationType;
use ncc\Enums\Types\HttpRequestType;
use ncc\Enums\Types\RepositoryResultType;
@ -47,7 +46,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): RepositoryResult
{
try
{
@ -64,9 +63,9 @@
/**
* @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): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication);
}
/**
@ -104,7 +103,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -161,7 +160,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 +185,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 +206,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 +248,7 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -299,97 +298,14 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. An array of options to use when fetching the package
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
$endpoint = sprintf('%s://%s/repos/%s/%s/releases/tags/%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, $project, $release);
if(RuntimeCache::exists($endpoint))
{
return RuntimeCache::get($endpoint);
}
$curl = curl_init($endpoint);
$headers = [
'Accept: application/vnd.github+json',
'X-GitHub-Api-Version: 2022-11-28',
'User-Agent: ncc'
];
if($authentication !== null)
{
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
curl_setopt_array($curl, [CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value, 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);
if(!isset($response['assets']))
{
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]);
$preferred_asset = null;
$fallback_asset = null;
foreach($response['assets'] as $asset)
{
if($static_preferred && preg_match('/(_static|-static)\.ncc$/', $asset['name']))
{
$preferred_asset = $asset;
}
elseif(preg_match('/\.ncc$/', $asset['name']))
{
$fallback_asset = $asset;
}
}
$target_asset = $preferred_asset ?: $fallback_asset;
if($target_asset)
{
$asset_url = $target_asset['browser_download_url'];
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
RuntimeCache::set($endpoint, $result);
return $result;
}
throw new NetworkException(sprintf('Failed to get release package for %s/%s/%s: No assets found', $group, $project, $release));
}
/**
* Returns a downloadable archive of the specified release for the specified group and project.
* The function will try to find a .zip archive first, and if it can't find one, it will
* try to find a .tar.gz archive. If it can't find either, it will throw an exception.
*
* @param RepositoryConfiguration $repository The remote repository to make the request to
* @param string $group The group to get the release for (eg; "Nosial")
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
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 +331,76 @@
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
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);
if(!isset($response['assets']))
{
throw new NetworkException(sprintf('Failed to get release package for %s/%s/%s: No assets found', $group, $project, $release));
}
foreach($response['assets'] as $asset)
{
if(preg_match('/\.ncc$/', $asset['name']) === 1)
{
$result = new RepositoryResult($asset['browser_download_url'], RepositoryResultType::PACKAGE, $release);
RuntimeCache::set($endpoint, $result);
return $result;
}
}
throw new NetworkException(sprintf('Failed to get release package for %s/%s/%s: No assets found', $group, $project, $release));
}
/**
* Returns a downloadable archive of the specified release for the specified group and project.
* The function will try to find a .zip archive first, and if it can't find one, it will
* try to find a .tar.gz archive. If it can't find either, it will throw an exception.
*
* @param RepositoryConfiguration $repository The remote repository to make the request to
* @param string $group The group to get the release for (eg; "Nosial")
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication = null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
$endpoint = sprintf('%s://%s/repos/%s/%s/releases/tags/%s', ($repository->isSsl() ? 'https' : 'http'), $repository->getHost(), $group, $project, $release);
if(RuntimeCache::exists($endpoint))
{
return RuntimeCache::get($endpoint);
}
$curl = curl_init($endpoint);
$headers = [
'Accept: application/vnd.github+json',
'X-GitHub-Api-Version: 2022-11-28',
'User-Agent: ncc'
];
if($authentication !== null)
{
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -425,11 +410,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 +444,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 +453,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;
@ -496,14 +481,14 @@
if($response === false)
{
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $group, $project, curl_error($curl), $retry_count + 1));
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $vendor, $project, curl_error($curl), $retry_count + 1));
$retry_count++;
}
}
if($response === false)
{
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $group, $project, curl_error($curl)));
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $vendor, $project, curl_error($curl)));
}
switch (curl_getinfo($curl, CURLINFO_HTTP_CODE))

View file

@ -25,7 +25,6 @@
use CurlHandle;
use Exception;
use JsonException;
use ncc\Enums\Options\InstallPackageOptions;
use ncc\Enums\Types\AuthenticationType;
use ncc\Enums\Types\HttpRequestType;
use ncc\Enums\Types\RepositoryResultType;
@ -39,7 +38,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 +46,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): RepositoryResult
{
try
{
@ -65,9 +63,9 @@
/**
* @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): RepositoryResult
{
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication, $options);
return self::getReleasePackage($repository, $vendor, $project, $version, $authentication);
}
/**
@ -104,17 +102,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 +163,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 +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_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true
]);
@ -225,7 +209,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 +249,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
]);
@ -323,106 +300,14 @@
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @param array $options Optional. The options to use for the request
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleasePackage(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null, array $options=[]): RepositoryResult
{
if($release === Versions::LATEST->value)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
$project = str_replace('.', '/', $project);
$endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/releases/%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project), rawurlencode($release));
if(RuntimeCache::exists($endpoint))
{
return RuntimeCache::get($endpoint);
}
$curl = curl_init($endpoint);
$headers = [
'Content-Type: application/json',
'Accept: application/json',
'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_HTTPHEADER => $headers
]);
$response = self::processHttpResponse($curl, $group, $project);
$static_preferred = isset($options[InstallPackageOptions::PREFER_STATIC->value]);
$preferred_asset = null;
$fallback_asset = null;
foreach($response['assets']['links'] as $asset)
{
if($static_preferred && preg_match('/(_static|-static)\.ncc$/', $asset['name']) === 1)
{
$preferred_asset = $asset;
}
elseif(preg_match('/\.ncc$/', $asset['name']) === 1)
{
$fallback_asset = $asset;
}
}
$target_asset = $preferred_asset ?: $fallback_asset;
if ($target_asset)
{
$asset_url = $target_asset['direct_asset_url'] ?? $target_asset['url'] ?? null;
if ($asset_url)
{
$result = new RepositoryResult($asset_url, RepositoryResultType::PACKAGE->value, $release);
RuntimeCache::set($endpoint, $result);
return $result;
}
throw new NetworkException(sprintf('No direct asset URL found for %s/%s/%s', $group, $project, $release));
}
throw new NetworkException(sprintf('No ncc package found for %s/%s/%s', $group, $project, $release));
}
/**
* Returns a downloadable archive of the specified release for the specified group and project.
* The function will try to find a .zip archive first, and if it can't find one, it will
* try to find a .tar.gz archive. If it can't find either, it will throw an exception.
*
* @param RepositoryConfiguration $repository The remote repository to make the request to
* @param string $group The group to get the release for (eg; "Nosial")
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
private static function getReleasePackage(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 +332,84 @@
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
$resolved_host = Resolver::getResolveOption($endpoint);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
if($resolved_host !== null)
$response = self::processHttpResponse($curl, $group, $project);
foreach($response['assets']['links'] as $asset)
{
curl_setopt($curl, CURLOPT_RESOLVE, [$resolved_host]);
if(preg_match('/\.ncc$/', $asset['name']) === 1)
{
if(isset($asset['direct_asset_url']))
{
$result = new RepositoryResult($asset['direct_asset_url'], RepositoryResultType::PACKAGE, $release);
}
elseif(isset($asset['url']))
{
$result = new RepositoryResult($asset['url'], RepositoryResultType::PACKAGE, $release);
}
else
{
throw new NetworkException(sprintf('No direct asset URL found for %s/%s/%s', $group, $project, $release));
}
RuntimeCache::set($endpoint, $result);
return $result;
}
}
throw new NetworkException(sprintf('No ncc package found for %s/%s/%s', $group, $project, $release));
}
/**
* Returns a downloadable archive of the specified release for the specified group and project.
* The function will try to find a .zip archive first, and if it can't find one, it will
* try to find a .tar.gz archive. If it can't find either, it will throw an exception.
*
* @param RepositoryConfiguration $repository The remote repository to make the request to
* @param string $group The group to get the release for (eg; "Nosial")
* @param string $project The project to get the release for (eg; "ncc" or "libs/config")
* @param string $release The release to get the release for (eg; "v1.0.0")
* @param AuthenticationInterface|null $authentication Optional. The authentication to use. If null, No authentication will be used.
* @return RepositoryResult The URL to the archive
* @throws AuthenticationException
* @throws NetworkException
*/
private static function getReleaseArchive(RepositoryConfiguration $repository, string $group, string $project, string $release, ?AuthenticationInterface $authentication=null): RepositoryResult
{
/** @noinspection DuplicatedCode */
if($release === Versions::LATEST)
{
$release = self::getLatestRelease($repository, $group, $project, $authentication);
}
$project = str_replace('.', '/', $project); // Gitlab doesn't like dots in project names (eg; "libs/config" becomes "libs%2Fconfig")
$endpoint = sprintf('%s://%s/api/v4/projects/%s%%2F%s/releases/%s', $repository->isSsl() ? 'https' : 'http', $repository->getHost(), $group, rawurlencode($project), rawurlencode($release));
if(RuntimeCache::exists($endpoint))
{
return RuntimeCache::get($endpoint);
}
$curl = curl_init($endpoint);
$headers = [
'Content-Type: application/json',
'Accept: application/json',
'User-Agent: ncc'
];
if($authentication !== null)
{
$headers = self::injectAuthentication($authentication, $curl, $headers);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET->value,
CURLOPT_CUSTOMREQUEST => HttpRequestType::GET,
CURLOPT_HTTPHEADER => $headers
]);
@ -476,11 +429,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 +460,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;
@ -551,14 +504,14 @@
if($response === false)
{
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $group, $project, curl_error($curl), $retry_count + 1));
Console::outWarning(sprintf('HTTP request failed for %s/%s: %s, retrying (%s/3)', $vendor, $project, curl_error($curl), $retry_count + 1));
$retry_count++;
}
}
if($response === false)
{
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $group, $project, curl_error($curl)));
throw new NetworkException(sprintf('HTTP request failed for %s/%s: %s', $vendor, $project, curl_error($curl)));
}
switch (curl_getinfo($curl, CURLINFO_HTTP_CODE))

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,16 @@
* @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]))
{
$metadata->removeOption(BuildConfigurationOptions::OUTPUT_FILE->value);
}
// Strip out 'static' build artifact, PackageFlags::STATIC_DEPENDENCIES is used instead
// Making this option redundant.
if(isset($metadata->getOptions()[BuildConfigurationOptions::STATIC_DEPENDENCIES->value]))
{
$metadata->removeOption(BuildConfigurationOptions::STATIC_DEPENDENCIES->value);
}
$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,7 +29,6 @@
use ncc\Enums\Flags\PackageFlags;
use ncc\Enums\PackageDirectory;
use ncc\Exceptions\ConfigurationException;
use ncc\Exceptions\IntegrityException;
use ncc\Exceptions\IOException;
use ncc\Objects\Package\Component;
use ncc\Objects\Package\ExecutionUnit;
@ -84,11 +83,6 @@
*/
private $package_file;
/**
* @var string
*/
private $package_path;
/**
* @var array
*/
@ -107,9 +101,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 +167,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 +212,7 @@
*/
public function getFileVersion(): string
{
return $this->headers[PackageStructure::FILE_VERSION->value];
return $this->headers[PackageStructure::FILE_VERSION];
}
/**
@ -241,7 +222,7 @@
*/
public function getFlags(): array
{
return $this->headers[PackageStructure::FLAGS->value];
return $this->headers[PackageStructure::FLAGS];
}
/**
@ -252,7 +233,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 +243,7 @@
*/
public function getDirectory(): array
{
return $this->headers[PackageStructure::DIRECTORY->value];
return $this->headers[PackageStructure::DIRECTORY];
}
/**
@ -273,15 +254,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 +278,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 +295,7 @@
*/
public function exists(string $name): bool
{
return isset($this->headers[PackageStructure::DIRECTORY->value][$name]);
return isset($this->headers[PackageStructure::DIRECTORY][$name]);
}
/**
@ -335,31 +316,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,36 +341,22 @@
*
* @return Metadata
* @throws ConfigurationException
* @throws IntegrityException
*/
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);
}
foreach($this->getFlags() as $flag)
{
$metadata->setOption($flag, true);
throw new ConfigurationException('Package does not contain metadata');
}
$metadata = Metadata::fromArray(ZiProto::decode($this->get($directory)));
$this->cache[$directory] = $metadata;
return $metadata;
}
@ -407,31 +365,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 +393,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 +412,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 +430,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 +445,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 +464,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 +482,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 +497,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 +518,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 +537,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 +555,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 +568,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 +588,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 +607,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 +625,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 +729,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): 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): 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,95 +177,32 @@
self::$class_map[strtolower($class)] = $component_path;
}
if($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) !== null)
{
foreach($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES->value) as $item)
{
$required_file = $entry->getPath($version) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . $item;
self::$imported_packages[$package] = $entry->getPath($version);
// Import dependencies recursively
foreach($entry->getVersion($version)->getDependencies() as $dependency)
{
/** @noinspection UnusedFunctionResultInspection */
self::import($dependency->getName(), $dependency->getVersion());
}
if($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES) !== null)
{
foreach($entry->getMetadata($version)->getOption(BuildConfigurationOptions::REQUIRE_FILES) as $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);
throw new ImportException(sprintf('Failed to import "%s" from %s: %s', $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);
}
}
}
$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);
// 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]))
{
// Fake import the dependencies
foreach($entry->getVersion($version)->getDependencies() as $dependency)
{
self::$imported_packages[$dependency->getName()] = $entry->getPath($version);
}
}
else
{
// Import dependencies recursively
foreach($entry->getVersion($version)->getDependencies() as $dependency)
{
/** @noinspection UnusedFunctionResultInspection */
self::import($dependency->getName(), $dependency->getVersion());
}
}
@ -302,9 +215,10 @@
* @param string $package_path
* @return string
* @throws ConfigurationException
* @throws IOException
* @throws ImportException
* @throws IntegrityException
* @throws OperationException
* @throws PathNotFoundException
*/
private static function importFromPackage(string $package_path): string
{
@ -339,9 +253,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,18 +268,9 @@
}
}
if($package_reader->getFlag(PackageFlags::STATIC_DEPENDENCIES->value))
// Import dependencies recursively
if(!$package_reader->getFlag(PackageFlags::STATIC_DEPENDENCIES))
{
// Fake import the dependencies
foreach($package_reader->getDependencies() as $dependency_name)
{
$dependency = $package_reader->getDependency($dependency_name);
self::$imported_packages[$dependency->getName()] = $package_reader;
}
}
else
{
// Import dependencies recursively
foreach($package_reader->getDependencies() as $dependency)
{
$dependency = $package_reader->getDependency($dependency);
@ -421,6 +326,7 @@
if(is_string(self::$class_map[$class]) && is_file(self::$class_map[$class]))
{
require_once self::$class_map[$class];
return;
}
}
@ -436,289 +342,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,95 @@
* @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;
/**
* @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
];
}

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,11 @@
* @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';
/**
* 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 REINSTALL = 'reinstall';
}

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
];
}

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