1
0
mirror of https://github.com/restoreddev/phpapprentice.git synced 2025-08-12 01:34:23 +02:00

Initial commit for public repo

This commit is contained in:
Andrew Davis
2018-09-02 10:57:36 -05:00
commit cb5d7c2386
79 changed files with 14644 additions and 0 deletions

22
src/App.php Normal file
View File

@@ -0,0 +1,22 @@
<?php
namespace Apprentice;
use Apprentice\Command;
use Symfony\Component\Console\Application;
class App
{
/**
* Runs cli application
*
* @return void
*/
public function main(): void
{
$cli = new Application;
$cli->add(new Command\BuildCommand);
$cli->add(new Command\ServerCommand);
$cli->run();
}
}

104
src/Build.php Normal file
View File

@@ -0,0 +1,104 @@
<?php
namespace Apprentice;
/**
* Handles building pages in public folder
* using configuration based on Page classes
*/
class Build
{
/**
* Builds all pages in config
*
* @return void
*/
public function buildAll(): void
{
$this->cleanPublicFolder();
$pages = config('pages');
foreach ($pages as $page) {
$this->buildPage($page);
}
}
/**
* Builds single page in config
*
* @param string $name Name of page to build
* @return string Contents of built page
*/
public function runSingleBuild(string $name): string
{
$pages = config('pages');
foreach ($pages as $page) {
if ($page->name == $name) {
break;
}
}
return $this->buildPage($page);
}
/**
* Deletes all html files in public folder
*
* @return void
*/
private function cleanPublicFolder(): void
{
$files = glob(config('output_dir') . '/*.html');
foreach ($files as $file) {
unlink($file);
}
}
/**
* Builds single Page into html and
* outputs to public directory
*
* @param Page $page Page from config to be built
* @return void Contents of built page
*/
private function buildPage(Page $page): string
{
if (!empty($page->code)) {
$code = file_get_contents(config('code_dir') . '/' . $page->code);
$page->variables['code'] = $code;
}
if ($page->template) {
$template = config('templates_dir') . '/' . $page->template;
} else {
$template = config('templates_dir') . '/default.phtml';
}
$output = $this->getOutput($template, $page->variables);
file_put_contents(config('output_dir') . '/' . $page->name . '.html', $output);
return $output;
}
/**
* Loads template file with scoped
* variables
*
* @param string $path Path to template in templates folder
* @param array $vars Array of variables to be loaded in template
* @return string Output of template
*/
private function getOutput(string $path, array $vars = []): string {
if ($vars) {
extract($vars);
}
ob_start();
require $path;
$output = ob_get_contents();
ob_end_clean();
return $output;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Apprentice\Command;
use Apprentice\Build;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class BuildCommand extends Command
{
protected function configure()
{
$this->setName('build')
->setDescription('Builds PHP templates into HTML files.')
->setHelp('Help!');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$build = new Build;
$build->buildAll();
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Apprentice\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ServerCommand extends Command
{
protected function configure()
{
$this->setName('server')
->setDescription('Runs PHP server that automatically builds files')
->setHelp('Help!');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('Starting development server on localhost:8080');
system('php -S localhost:8080 -t docs src/util/router.php');
}
}

77
src/Page.php Normal file
View File

@@ -0,0 +1,77 @@
<?php
namespace Apprentice;
/**
* A class representing a single page in the build process
*/
class Page
{
/**
* Name of page, used in filename
*
* @var string
*/
public $name;
/**
* Name of template to use
* If none is provided, a default will be used
*
* @var string|null
*/
public $template;
/**
* Name of code file to load as table
* Will be skipped if none is provided
*
* @var string|null
*/
public $code;
/**
* Map of data to passed to template
*
* @var array
*/
public $variables;
/**
* Creates new page
*
* @param string $name
* @param string|null $template
* @param string|null $code
* @param array $variables
*/
public function __construct(
string $name,
?string $template = null,
?string $code = null,
?array $variables = []
) {
$this->name = $name;
$this->template = $template;
$this->code = $code;
$this->variables = $variables;
}
/**
* Static constructor
*
* @param string $name
* @param string|null $template
* @param string|null $code
* @param array $variables
* @return Apprentice\Page
*/
public static function create(
string $name,
?string $template = null,
?string $code = null,
?array $variables = []
): Page {
return new static($name, $template, $code, $variables);
}
}

149
src/util/functions.php Normal file
View File

@@ -0,0 +1,149 @@
<?php
/**
* Runs a scoped require on a partial
*
* The filename must start with an underscore
* and end with .php or .phtml
*
* @param string $path Name of partial
* @param array $vars Variables to use for the partial
* @return void
*/
function partial(string $path, array $vars = []) {
$dir = config('templates_dir');
if (file_exists($dir. '/' . "_$path.php")) {
$file = $dir. '/' . "_$path.php";
} elseif (file_exists($dir . '/' . "_$path.phtml")) {
$file = $dir. '/' . "_$path.phtml";
} else {
throw new Exception('Partial could not be found: ' . $dir . '/' . "_$path.php");
}
extract($vars);
require $file;
}
/**
* Gets url path to page
*
* @param string $page Name of page
* @return string
*/
function page_path(string $page): string {
return '/' . $page . '.html';
}
/**
* Safely escapes text for display in html
*
* @param string $text
* @return string
*/
function escape(string $text): string {
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8', true);
}
/**
* Loads content of svg icon from assets folder
*
* @param string $name Name of icon without extension
* @return string Contents of file
*/
function icon(string $name): string {
$dir = config('icon_dir');
$path = $dir . '/' . $name . '.svg';
if (file_exists($path)) {
return file_get_contents($path);
}
return '';
}
/**
* Takes string of PHP code and converts it into html for display
*
* @param string $code
* @return string
*/
function code_table(string $code): string {
$tokens = token_get_all($code);
$output = '<div class="grid-code">' .
'<div class="doc"></div>' .
'<div class="code">' .
'<pre>' .
'<code class="language-php">';
$previousTokenWasComment = false;
foreach ($tokens as $token) {
if (is_string($token)) {
$output .= $token;
continue;
}
$id = $token[0];
$text = $token[1];
if ($id == T_COMMENT || $id == T_DOC_COMMENT) {
$text = htmlspecialchars(trim(str_replace('/', '', $text)));
if ($previousTokenWasComment) {
$output .= ' ' . $text;
} else {
$output .= '</code>' .
'</pre>' .
'</div>' .
'<div class="doc">' .
$text;
}
$previousTokenWasComment = true;
} else {
if ($previousTokenWasComment) {
$output .= '</div>' .
'<div class="code">' .
'<pre>' .
'<code class="language-php">';
}
$output .= htmlspecialchars($text);
$previousTokenWasComment = false;
}
}
$output .= '</code>' .
'</pre>' .
'</div>' .
'</div>';
return $output;
}
/**
* Loads config file into a global
*
* @param string $path
* @return void
*/
function load_config(string $path) {
$config = require $path;
if (!is_array($config)) {
throw new \Exception('Config file does not return an array.');
}
$GLOBALS['APPRENTICE_CONFIG'] = $config;
}
/**
* Returns config value
*
* @param string $key
* @return mixed
*/
function config(string $key) {
$config = $GLOBALS['APPRENTICE_CONFIG'] ?? [];
return $config[$key] ?? null;
}

27
src/util/router.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
/**
* Router file used for development server
* to create html files on demand
*/
require __DIR__ . '/../../vendor/autoload.php';
load_config(__DIR__ . '/../../config.php');
$uri = $_SERVER['REQUEST_URI'];
$pathinfo = pathinfo($uri);
if ($pathinfo['dirname'] == '/' && !isset($pathinfo['extension'])) {
$pathinfo['extension'] = 'html';
$pathinfo['filename'] = 'index';
}
if ($pathinfo['extension'] == 'html') {
$build = new Apprentice\Build;
$output = $build->runSingleBuild($pathinfo['filename']);
echo $output;
return true;
}
return false;