Added the ability to create new projects

This commit is contained in:
Netkas 2022-07-27 19:56:59 -04:00
parent 4a1ae8e14c
commit 1044e0cd9b
9 changed files with 279 additions and 43 deletions

View file

@ -10,8 +10,11 @@
use ncc\Exceptions\InvalidCredentialsEntryException; use ncc\Exceptions\InvalidCredentialsEntryException;
use ncc\Exceptions\InvalidPackageNameException; use ncc\Exceptions\InvalidPackageNameException;
use ncc\Exceptions\InvalidProjectConfigurationException; use ncc\Exceptions\InvalidProjectConfigurationException;
use ncc\Exceptions\InvalidProjectNameException;
use ncc\Exceptions\InvalidScopeException; use ncc\Exceptions\InvalidScopeException;
use ncc\Exceptions\InvalidVersionNumberException;
use ncc\Exceptions\MalformedJsonException; use ncc\Exceptions\MalformedJsonException;
use ncc\Exceptions\ProjectAlreadyExistsException;
use ncc\Exceptions\RuntimeException; use ncc\Exceptions\RuntimeException;
/** /**
@ -75,6 +78,21 @@
*/ */
const InvalidPackageNameException = -1710; const InvalidPackageNameException = -1710;
/**
* @see InvalidVersionNumberException
*/
const InvalidVersionNumberException = -1711;
/**
* @see InvalidProjectNameException
*/
const InvalidProjectNameException = -1712;
/**
* @see ProjectAlreadyExistsException
*/
const ProjectAlreadyExistsException = -1713;
/** /**
* All the exception codes from NCC * All the exception codes from NCC
*/ */
@ -89,6 +107,9 @@
self::InvalidCredentialsEntryException, self::InvalidCredentialsEntryException,
self::ComponentVersionNotFoundException, self::ComponentVersionNotFoundException,
self::ConstantReadonlyException, self::ConstantReadonlyException,
self::InvalidPackageNameException self::InvalidPackageNameException,
self::InvalidVersionNumberException,
self::InvalidProjectNameException,
self::ProjectAlreadyExistsException,
]; ];
} }

View file

@ -2,11 +2,14 @@
namespace ncc\CLI; namespace ncc\CLI;
use ncc\Abstracts\Scopes; use Exception;
use ncc\Exceptions\AccessDeniedException; use ncc\Exceptions\InvalidPackageNameException;
use ncc\Exceptions\InvalidProjectNameException;
use ncc\Exceptions\ProjectAlreadyExistsException;
use ncc\Managers\ProjectManager;
use ncc\Objects\CliHelpSection; use ncc\Objects\CliHelpSection;
use ncc\Objects\ProjectConfiguration\Compiler;
use ncc\Utilities\Console; use ncc\Utilities\Console;
use ncc\Utilities\Resolver;
class ProjectMenu class ProjectMenu
{ {
@ -15,7 +18,6 @@
* *
* @param $args * @param $args
* @return void * @return void
* @throws AccessDeniedException
*/ */
public static function start($args): void public static function start($args): void
{ {
@ -32,11 +34,71 @@
/** /**
* @param $args * @param $args
* @return void * @return void
* @throws AccessDeniedException
*/ */
public static function createProject($args): void public static function createProject($args): void
{ {
Console::out('end' . PHP_EOL); // First determine the source directory of the project
$src = getcwd();
if(isset($args['src']))
{
// Make sure directory separators are corrected
$args['src'] = str_ireplace('/', DIRECTORY_SEPARATOR, $args['src']);
$args['src'] = str_ireplace('\\', DIRECTORY_SEPARATOR, $args['src']);
// Remove the trailing slash
if(substr($args['src'], -1) == DIRECTORY_SEPARATOR)
{
$args['src'] = substr($args['src'], 0, -1);
}
$full_path = getcwd() . DIRECTORY_SEPARATOR . $args['src'];
if(file_exists($full_path) && is_dir($full_path))
{
$src = getcwd() . DIRECTORY_SEPARATOR . $args['src'];
}
else
{
Console::outError('The selected source directory \'' . $full_path . '\' was not found or is not a directory', true, 1);
}
}
// Fetch the rest of the information needed for the project
//$compiler_extension = Console::getOptionInput($args, 'ce', 'Compiler Extension (php, java): ');
$compiler_extension = 'php'; // Always php, for now.
$package_name = Console::getOptionInput($args, 'package', 'Package Name (com.example.foo): ');
$project_name = Console::getOptionInput($args, 'name', 'Project Name (Foo Bar Library): ');
// Create the compiler configuration
$Compiler = new Compiler();
$Compiler->Extension = $compiler_extension;
$Compiler->MaximumVersion = '8.1';
$Compiler->MinimumVersion = '7.4';
// Now create the project
$ProjectManager = new ProjectManager($src);
try
{
$ProjectManager->initializeProject($Compiler, $project_name, $package_name);
}
catch (InvalidPackageNameException $e)
{
Console::outException('The given package name is invalid, the value must follow the standard package naming convention', $e, 1);
}
catch (InvalidProjectNameException $e)
{
Console::outException('The given project name is invalid, cannot be empty or larger than 126 characters', $e, 1);
}
catch (ProjectAlreadyExistsException $e)
{
Console::outException('A project has already been initialized in \'' . $src . '\'', $e, 1);
}
catch(Exception $e)
{
Console::outException('There was an unexpected error while trying to initialize the project', $e, 1);
}
Console::out('Project successfully created');
exit(0); exit(0);
} }

View file

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

View file

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

View file

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

View file

@ -4,7 +4,9 @@
use ncc\Abstracts\Options\InitializeProjectOptions; use ncc\Abstracts\Options\InitializeProjectOptions;
use ncc\Exceptions\InvalidPackageNameException; use ncc\Exceptions\InvalidPackageNameException;
use ncc\Exceptions\InvalidProjectNameException;
use ncc\Exceptions\MalformedJsonException; use ncc\Exceptions\MalformedJsonException;
use ncc\Exceptions\ProjectAlreadyExistsException;
use ncc\Objects\ProjectConfiguration; use ncc\Objects\ProjectConfiguration;
use ncc\Objects\ProjectConfiguration\Compiler; use ncc\Objects\ProjectConfiguration\Compiler;
use ncc\Symfony\Component\Uid\Uuid; use ncc\Symfony\Component\Uid\Uuid;
@ -85,14 +87,15 @@
* Initializes the project structure * Initializes the project structure
* *
* @param Compiler $compiler * @param Compiler $compiler
* @param string $source
* @param string $name * @param string $name
* @param string $package * @param string $package
* @param array $options * @param array $options
* @throws InvalidPackageNameException * @throws InvalidPackageNameException
* @throws InvalidProjectNameException
* @throws MalformedJsonException * @throws MalformedJsonException
* @throws ProjectAlreadyExistsException
*/ */
public function initializeProject(Compiler $compiler, string $source, string $name, string $package, array $options=[]) public function initializeProject(Compiler $compiler, string $name, string $package, array $options=[])
{ {
// Validate the project information first // Validate the project information first
if(!Validate::packageName($package)) if(!Validate::packageName($package))
@ -100,6 +103,16 @@
throw new InvalidPackageNameException('The given package name \'' . $package . '\' is not a valid package name'); throw new InvalidPackageNameException('The given package name \'' . $package . '\' is not a valid package name');
} }
if(!Validate::projectName($name))
{
throw new InvalidProjectNameException('The given project name \'' . $name . '\' is not valid');
}
if(file_exists($this->ProjectPath . DIRECTORY_SEPARATOR . 'project.json'))
{
throw new ProjectAlreadyExistsException('A project has already been initialized in \'' . $this->ProjectPath . DIRECTORY_SEPARATOR . 'project.json' . '\'');
}
$Project = new ProjectConfiguration(); $Project = new ProjectConfiguration();
// Set the compiler information // Set the compiler information
@ -112,7 +125,7 @@
$Project->Assembly->UUID = Uuid::v1()->toRfc4122(); $Project->Assembly->UUID = Uuid::v1()->toRfc4122();
// Set the build information // Set the build information
$Project->Build->SourcePath = $source; $Project->Build->SourcePath = $this->SelectedDirectory;
$Project->Build->DefaultConfiguration = 'debug'; $Project->Build->DefaultConfiguration = 'debug';
// Assembly constants if the program wishes to check for this // Assembly constants if the program wishes to check for this
@ -157,7 +170,7 @@
switch($option) switch($option)
{ {
case InitializeProjectOptions::CREATE_SOURCE_DIRECTORY: case InitializeProjectOptions::CREATE_SOURCE_DIRECTORY:
if(file_exists($source) == false) if(!file_exists($source))
{ {
mkdir($source); mkdir($source);
} }

View file

@ -108,7 +108,25 @@
*/ */
public static function outWarning(string $message, bool $newline=true) public static function outWarning(string $message, bool $newline=true)
{ {
self::out(self::formatColor(ConsoleColors::Yellow, 'Warning: ') . $message, $newline); self::out(self::formatColor('Warning: ', ConsoleColors::Yellow) . $message, $newline);
}
/**
* Prints out a generic error output, optionally exits the process with an exit code.
*
* @param string $message
* @param bool $newline
* @param int|null $exit_code
* @return void
*/
public static function outError(string $message, bool $newline=true, ?int $exit_code=null)
{
self::out(self::formatColor(ConsoleColors::Red, 'Error: ') . $message, $newline);
if($exit_code !== null)
{
exit($exit_code);
}
} }
/** /**
@ -146,4 +164,73 @@
$trace_error = self::formatColor('error: ', ConsoleColors::Red); $trace_error = self::formatColor('error: ', ConsoleColors::Red);
self::out($trace_header . ' ' . $trace_error . $e->getMessage()); self::out($trace_header . ' ' . $trace_error . $e->getMessage());
} }
/**
* @param string|null $prompt
* @return string
*/
public static function getInput(?string $prompt=null): string
{
if($prompt !== null)
{
print($prompt);
}
$handle = fopen ("php://stdin","r");
return fgets($handle);
}
/**
* @param array $args
* @param string $option
* @param string $prompt
* @return string
*/
public static function getOptionInput(array $args, string $option, string $prompt): string
{
if(isset($args[$option]))
{
return $args[$option];
}
return self::getInput($prompt);
}
/**
* Prompts the user for a yes/no input
*
* @param string $prompt
* @param bool $display_options
* @return bool
*/
public static function getBooleanInput(string $prompt, bool $display_options=true): bool
{
while(true)
{
if($display_options)
{
$r = self::getInput($prompt . ' (Y/N): ', false);
}
else
{
$r = self::getInput($prompt, false);
}
if(strlen($r) > 0)
{
switch(strtoupper($r))
{
case '1':
case 'Y':
case 'YES':
return true;
case '0':
case 'N':
case 'NO':
return false;
}
}
}
}
} }

View file

@ -184,35 +184,4 @@
return $banner; return $banner;
} }
/**
* @param string|null $prompt
* @return string
*/
public static function getInput(?string $prompt=null): string
{
if($prompt !== null)
{
print($prompt);
}
$handle = fopen ("php://stdin","r");
return fgets($handle);
}
/**
* @param array $args
* @param string $option
* @param string $prompt
* @return string
*/
public static function getOptionInput(array $args, string $option, string $prompt): string
{
if(isset($args[$option]))
{
return $args[$option];
}
return self::getInput($prompt);
}
} }

View file

@ -129,4 +129,30 @@
return true; return true;
} }
/**
* Validates the name of the project
*
* @param $input
* @return bool
*/
public static function projectName($input): bool
{
if($input == null)
{
return false;
}
if(strlen($input) == 0)
{
return false;
}
if(strlen($input) > 126)
{
return false;
}
return true;
}
} }