-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Builtin dependencies #318
Comments
Solution inside PHP code
DeclarationA <?php namespace com\example;
from('xp-framework/rdbms', ['rdbms\{DriverManager, ResultSet}']);
from('xp-framework/logging', ['util\log\*']);
from('xp-framework/command', ['util\cmd\Command']);
/**
* Performs an SQL query
*/
class Query extends Command {
// ...
} ...or at the top of the script ageindays.script.php: <?php namespace ageindays;
from('xp-framework/core', ['util\{Date, DateUtil}', 'util\cmd\Console']);
$span= DateUtil::timespanBetween(new Date($argv[1]), Date::now());
Console::writeLine('Hey, you are ', $span->getDays(), ' days old'); All other places still import types using Implementation(Uses Composer global modules, Windows only, not much error handling, goes inside lang.base.php) function from($module, $imports, $namespace= null) {
static $modules= ['php' => true, 'xp-framework/core' => true];
if (null === $namespace) {
$file= debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'];
$ns= \lang\ClassLoader::findUri($file)->path;
$namespace= rtrim(dirname(substr($file, strlen($ns))), '.');
}
if (!isset($modules[$module])) {
$base= getenv('APPDATA').'\\Composer\\vendor\\'.strtr($module, ['/' => '\\']).'\\';
foreach (glob($base.'\\*.pth') as $file) {
foreach (file($file) as $line) {
$path= trim($line);
if ('' === $path || '#' === $path{0}) {
continue;
} else if ('!' === $path{0}) {
\lang\ClassLoader::registerPath($base.strtr(substr($path, 1), ['/' => '\\']), true);
} else {
\lang\ClassLoader::registerPath($base.strtr($path, ['/' => '\\']));
}
}
}
$modules[$module]= true;
$composer= file_get_contents($base.'composer.json');
foreach (json_decode($composer, true)['require'] as $depend => $_) {
from($depend, [], $namespace);
}
}
foreach ($imports as $import) {
if ($p= strpos($import, '{')) {
$base= substr($import, 0, $p);
foreach (explode(', ', substr($import, $p + 1, -1)) as $type) {
class_alias($base.$type, $namespace.'\\'.$type);
}
} else {
class_alias($import, $namespace.substr($import, strrpos($import, '\\')));
}
}
} Also requires a small patch to xp\runtime\Code: diff --git a/src/main/php/xp/runtime/Code.class.php b/src/main/php/xp/runtime/Code.class.php
index 8507651..ee44154 100755
--- a/src/main/php/xp/runtime/Code.class.php
+++ b/src/main/php/xp/runtime/Code.class.php
@@ -8,6 +8,7 @@
*/
class Code {
private $fragment, $imports;
+ private $namespace= null;
/**
* Creates a new code instance
@@ -27,6 +28,13 @@ class Code {
}
$this->fragment= trim($input, "\r\n\t ;").';';
+
+ if (0 === strncmp($this->fragment, 'namespace', 9)) {
+ $length= strcspn($this->fragment, ';', 10);
+ $this->namespace= substr($this->fragment, 10, $length);
+ $this->fragment= substr($this->fragment, 10 + $length);
+ }
+
$this->imports= [];
while (0 === strncmp($this->fragment, 'use ', 4)) {
$delim= strpos($this->fragment, ';');
@@ -53,7 +61,15 @@ class Code {
/** @return string */
public function head() {
- return empty($this->imports) ? '' : 'use '.implode(', ', $this->imports).';';
+ if ($this->namespace) {
+ $head= 'namespace '.$this->namespace.';';
+ $head.= 'function from($module, $imports) { \from($module, $imports, __NAMESPACE__); }';
+ } else {
+ $head= '';
+ }
+
+ $head.= empty($this->imports) ? '' : 'use '.implode(', ', $this->imports).';';
+ return $head;
} |
Solution inside XP Runners
This would revive the search for an IPC mechanism - but all that just for reusing the simple-to-implement Composer module logic? Doesn't seem worth it... |
Standalone usecaseIn a script or class with nothing alongside it, the dependencies should be loaded from Composer's global project (COMPOSER_HOME). Usecase inside a projectAlthough typically not useful as the generated autoloader takes care of loading classes, we also want the following scenario to work along the principile of least surprise:
When running |
The Api.class.php<?php namespace de\thekid\shorturl;
from('xp-framework/scriptlet', 'xp\scriptlet\WebApplication');
class Api implements \xp\scriptlet\WebLayout {
public function mappedApplications($profile= null) {
$injector= new Injector(new Bindings());
// ^^^^^^^^^^^^^^
// Loads Bindings class - see below
return ['/' => $injector->get(WebApplication::class)];
}
} Bindings.class.php<?php namespace de\thekid\shorturl;
use xp\scriptlet\WebApplication;
class Bindings extends \inject\Bindings {
public function configure($injector) {
$injector->bind(WebApplication::class, new ShortUrlApplication());
}
} ResultCompile error: Cannot use xp\scriptlet\WebApplication as WebApplication because the name is already in use. Hrm...Unfortunately we cannot work around this - _maybe |
If so, we could create our own syntax, e.g. use text\json\StreamInput from 'xp-forge/json';
use webservices\rest\{Endpoint, Links} from 'xp-framework/rest'; This is similar to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import |
Rewrote the RFC to use // Original proposal, no longer works!!!
from('xp-forge/json', ['text\json\StreamInput']);
from('xp-forge/sequence', ['util\data\*']);
from('xp-framework/core', ['util\cmd\Console']);
from('xp-framework/logging', ['util\log\*']);
from('xp-framework/rest', ['webservices\rest\{Endpoint, Links}']); |
Scope of Change
Usecase: Standalone scripts.
Rationale
If not inside a directory where we've configured and run Composer, we will need to type
xp -m /path/to/rdbms/module query.script.php ...
(and figure out transitive dependencies) ourselves.Functionality
The class or script needs to be able to declare what modules it requires. These could be loaded via the composer global project (with all its downsides)
Security considerations
Speed impact
Dependencies
-cp
/-m
.Related documents
TypeScript modules / import and export:
Groovy
Composer global downsides / discussion:
The text was updated successfully, but these errors were encountered: