Skip to content

Commit

Permalink
Generate more helpers: 'script.php', 'run.php' and 'run.sh'
Browse files Browse the repository at this point in the history
If want to open up a generated-project in an IDE (eg for debugging), then it
helps for the project to have some references for running the original script.

Before: Generated project-dir contains *only* downloaded dependencies
After: Generated project-dir contains downloaded dependencies as well as:

- A symlink to the script ('script.php')
- A helper to run the script ('run.php' or 'run.sh')
  • Loading branch information
totten committed Nov 5, 2022
1 parent 814a318 commit 66c0bb6
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/Command/PharCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Pogo\Command;

use Pogo\FilteredDirectoryIterator;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
Expand Down Expand Up @@ -55,7 +56,14 @@ protected function execute(InputInterface $input, OutputInterface $output) {
$phar = new \Phar($pharTmp);

$phar->setStub($this->createStub($logicalPhar, $mainFile));
$phar->buildFromDirectory($project->path);
$fileIter = new FilteredDirectoryIterator($project->path, function(string $relPath, \SplFileInfo $file) {
// These are debug-files. Not needed in the PHAR.
$ignore = ['run.php', 'run.sh', 'script.php'];
$result = !in_array($relPath, $ignore) && !$file->isDir();
return $result;
});

$phar->buildFromIterator($fileIter, $project->path);
$phar->compressFiles(\Phar::GZ);
$fs->chmod($pharTmp, 0777);

Expand Down
33 changes: 33 additions & 0 deletions src/FilteredDirectoryIterator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
namespace Pogo;

use Symfony\Component\Filesystem\Filesystem;

class FilteredDirectoryIterator extends \FilterIterator {

protected $basedir;

/**
* @var callable
* function(string $relPath, SplFileInfo $file): bool;
*/
protected $filter;

public function __construct(string $basedir, callable $filter) {
$this->basedir = $basedir;
$this->filter = $filter;
$dirIter = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($basedir,
\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS
));
parent::__construct($dirIter);
}

public function accept(): bool {
$fs = new Filesystem();
$current = $this->current();
$fullPath = $current->getPath() . DIRECTORY_SEPARATOR . $current->getFilename();
$relPath = rtrim($fs->makePathRelative($fullPath, $this->basedir), DIRECTORY_SEPARATOR);
return call_user_func($this->filter, $relPath, $current);
}

}
16 changes: 16 additions & 0 deletions src/Php.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ public static function iniToArgv($ini) {
return $buf;
}

/**
* Convert a list of PHP INI values to PHP code.
*
* @param array $ini
* Ex: ['memory_limit'=>'256m']
* @return string
* Ex: 'ini_set("memory_limit", "256m");'
*/
public static function iniToCode($ini) {
$buf = '';
foreach ($ini as $k => $v) {
$buf .= sprintf("ini_set(%s, %s);\n", var_export($k, TRUE), var_export($v, TRUE));
}
return $buf;
}

/**
* @param array $ini
* Ex: ['memory_limit'=>'256m']
Expand Down
49 changes: 49 additions & 0 deletions src/PogoProject.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,43 @@ public function buildHelpers() {
foreach (['pogolib'] as $helper) {
file_put_contents("$path/.{$helper}.php", file_get_contents(dirname(__DIR__) . "/templates/{$helper}.php"));
}

$realScript = realpath($this->scriptMetadata->file);
$this->createLinkOrCopy($realScript, "$path/script.php");

file_put_contents("$path/run.sh", implode("\n", [
'#!/usr/bin/env bash',
'export POGO_SCRIPT=' . escapeshellarg($realScript),
'export POGO_AUTOLOAD=' . escapeshellarg($this->getAutoloader()),
'export POGO_STDIN=',
sprintf('[ -e %s ] && RUN_SCRIPT=%s || RUN_SCRIPT="$POGO_SCRIPT"', escapeshellarg("$path/script.php"), escapeshellarg("$path/script.php")),
sprintf('exec php %s "$RUN_SCRIPT" "$@"',
\Pogo\Php::iniToArgv($this->scriptMetadata->ini + ['auto_prepend_file' => $this->getAutoloader()])
),
'',
]));
chmod("$path/run.sh", 0755);

file_put_contents("$path/run.php", implode("\n", [
'#!/usr/bin/env php',
'<' . '?php',
$this->scriptMetadata->ini ? ('/' . '/ WARNING: ini_set() may not work with all variables') : '',
\Pogo\Php::iniToCode($this->scriptMetadata->ini),
sprintf('$_SERVER["POGO_SCRIPT"] = $_ENV["POGO_SCRIPT"] = %s;', var_export($realScript, TRUE)),
'putenv("POGO_SCRIPT=" . $_ENV["POGO_SCRIPT"]);',
'',
'$_SERVER["POGO_AUTOLOAD"] = $_ENV["POGO_AUTOLOAD"] = __DIR__ . "/vendor/autoload.php";',
'putenv("POGO_AUTOLOAD=" . $_ENV["POGO_AUTOLOAD"]);',
'',
'unset($_SERVER["POGO_STDIN"]);',
'unset($_ENV["POGO_STDIN"]);',
'putenv("POGO_STDIN");',
'',
'require_once __DIR__ . "/vendor/autoload.php";',
'require_once file_exists(__DIR__ . "/script.php") ? __DIR__ . "/script.php" : $_ENV["POGO_SCRIPT"];',
'',
]));
chmod("$path/run.php", 0755);
}

public function buildComposer() {
Expand All @@ -109,4 +146,16 @@ public function getAutoloader() {
return $this->path . '/vendor/autoload.php';
}

private function createLinkOrCopy($in, $out) {
if (file_exists($out)) {
unlink($out);
}
if (preg_match('/(linux|darwin)/i', php_uname())) {
symlink($in, $out);
}
else {
copy($in, $out);
}
}

}

0 comments on commit 66c0bb6

Please sign in to comment.