Last active
June 7, 2018 20:53
-
-
Save jwinett/e89e7856fe04b6f910ee7c8685738d87 to your computer and use it in GitHub Desktop.
YAF - Yet Another Framework for page rendering in PHP w/ Bootstrap 4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace KarenWare\App; | |
/** | |
* YAF - Yet Another Framework | |
* | |
* Written dozens of times by me, millions of times by others. | |
* Why? I've fiddled with Django for too many days and this needs | |
* to be did, done, over, etc. | |
* | |
* @author Joe Winett <joe@karenware.com> | |
*/ | |
abstract class Page { | |
/** | |
* | |
* @var string | |
*/ | |
protected $lang = "en"; | |
/** | |
* | |
* @var string | |
*/ | |
protected $description = ""; | |
/** | |
* | |
* @var string | |
*/ | |
protected $author = ""; | |
/** | |
* | |
* @var array | |
*/ | |
protected $keywords = []; | |
/** | |
* | |
* @var string | |
*/ | |
protected $title = ""; | |
/** | |
* | |
* @var array | |
*/ | |
protected $css_text = []; | |
/** | |
* | |
* @var array | |
*/ | |
protected $css_url = []; | |
/** | |
* | |
* @var array | |
*/ | |
protected $script_text = []; | |
/** | |
* | |
* @var array | |
*/ | |
protected $script_url = []; | |
/** | |
* | |
* @param string $description | |
*/ | |
public function SetDescription( string $description ): void { | |
$this->description = $description; | |
} | |
/** | |
* | |
* @param string $author | |
*/ | |
public function SetAuthor( string $author ): void { | |
$this->author = $author; | |
} | |
/** | |
* | |
* @param array $keywords | |
*/ | |
public function SetKeywords( array $keywords ): void { | |
$this->keywords = $keywords; | |
} | |
/** | |
* | |
* @param string $title | |
*/ | |
public function SetTitle( string $title ): void { | |
$this->title = $title; | |
} | |
/** | |
* | |
* @param string $css_text | |
*/ | |
public function AddCssText( string $css_text ): void { | |
$this->css_text[] = $css_text; | |
} | |
/** | |
* | |
* @param string $css_href | |
* @param string $css_media | |
*/ | |
public function AddCssURL( string $css_url, string $css_media = "", string $integrity = "", string $crossorigin = "" ): void { | |
$this->css_url[] = [ "href" => $css_url, "media" => $css_media, "integrity" => $integrity, "crossorigin" => $crossorigin ]; | |
} | |
/** | |
* | |
* @param string $scipt_text | |
*/ | |
public function AddScriptText( string $script_text ): void { | |
$this->script_text[] = $script_text; | |
} | |
/** | |
* | |
* @param string $script_src URL | |
*/ | |
public function AddScriptURL( string $script_url, string $integrity = "", string $crossorigin = "" ): void { | |
$this->script_url[] = [ "src" => $script_url, "integrity" => $integrity, "crossorigin" => $crossorigin ]; | |
} | |
/** | |
* | |
* @param string $title_postfix | |
* @return string | |
*/ | |
protected function Render_Title( string $title_postfix = "KarenWare.com"): string { | |
$title = $title_postfix; | |
if( !empty($this->title) ) | |
$title = $this->title . " | $title"; | |
$html = " <title>" . htmlspecialchars($title) . "</title>\n"; | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_StartHead(): string { | |
$html = "<!DOCTYPE html>\n" | |
. '<html lang="' . $this->lang . '">' . "\n" | |
. " <head>\n" | |
. ' <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">' . "\n" | |
. ' <meta name="description" content="' . $this->description . '">' . "\n" | |
. ' <meta name="author" content="' . $this->author . '">' . "\n" | |
. ' <link rel="icon" href="/favicon.ico">' . "\n" | |
. $this->Render_Title(); | |
foreach( $this->css_url as $x ) { | |
$html .= ' <link rel="stylesheet" href="' . $x["href"] . '"' | |
. ( !empty($x['media']) ? ' media="' . $x['media'] . '"' : "" ) | |
. ( !empty($x['integrity']) ? ' integrity="' . $x['integrity'] . '"' : "" ) | |
. ( !empty($x['crossorigin']) ? ' crossorigin="' . $x['crossorigin'] . '"' : "") | |
. ">\n"; | |
} | |
if( !empty($this->css_text) ) { | |
$html .= " <style>\n" | |
. implode( "\n", $this->css_text ) | |
. " </style>\n"; | |
} | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_EndHeadStartBody(): string { | |
$html = " </head>\n" | |
. " <body>\n"; | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_Body_Top(): string { | |
$html = " <h1>" . \htmlspecialchars($this->title) . "</h1>\n"; | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_Body_Content(): string { | |
$html = " <p>Body Content from " . __FILE__ . "</p>\n"; | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_Body_Bottom(): string { | |
return ""; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_EndBody(): string { | |
$html = ""; | |
foreach( $this->script_url as $x ) { | |
$html .= ' <script src="' . $x['src'] . '"' | |
. ( !empty($x['integrity']) ? ' integrity="' . $x['integrity'] . '"' : "" ) | |
. ( !empty($x['crossorigin']) ? ' crossorigin="' . $x['crossorigin'] . '"' : "") | |
. "></script>\n"; | |
} | |
if( !empty($this->script_text) ) { | |
$html .= " <script>\n" | |
. implode( "\n", $this->script_text ) | |
. " </script>\n"; | |
} | |
$html .= " </body>\n" | |
. "</html>\n"; | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
public function Render(): string { | |
$html = $this->Render_StartHead() | |
. $this->Render_EndHeadStartBody() | |
. $this->Render_Body_Top() | |
. $this->Render_Body_Content() | |
. $this->Render_EndBody(); | |
return $html; | |
} | |
protected function __construct() { | |
} | |
} | |
abstract class BootstrapPage extends Page { | |
public function __construct() { | |
parent::__construct(); | |
$this->AddScriptURL( "https://code.jquery.com/jquery-3.3.1.slim.min.js", | |
"sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo", | |
"anonymous"); | |
$this->AddScriptURL( "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js", | |
"sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49", | |
"anonymous"); | |
$this->AddScriptURL( "https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js", | |
"sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T", | |
"anonymous"); | |
$this->AddCssURL("https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css", | |
"", | |
"sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB", | |
"anonymous"); | |
$css = <<<EOT | |
body { | |
padding-top: 5rem; | |
} | |
.centered-template { | |
padding: 3rem 1.5rem; | |
text-align: center; | |
} | |
EOT; | |
$this->AddCssText( $css ); | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_Bootstrap_Nav(): string { | |
$html = <<<EOT | |
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> | |
<a class="navbar-brand" href="#">KarenWare.com</a> | |
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation"> | |
<span class="navbar-toggler-icon"></span> | |
</button> | |
<div class="collapse navbar-collapse" id="navbarsExampleDefault"> | |
<ul class="navbar-nav mr-auto"> | |
<li class="nav-item active"> | |
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> | |
</li> | |
<li class="nav-item"> | |
<a class="nav-link" href="#">Link</a> | |
</li> | |
<li class="nav-item"> | |
<a class="nav-link disabled" href="#">Disabled</a> | |
</li> | |
<li class="nav-item dropdown"> | |
<a class="nav-link dropdown-toggle" href="https://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a> | |
<div class="dropdown-menu" aria-labelledby="dropdown01"> | |
<a class="dropdown-item" href="#">Action</a> | |
<a class="dropdown-item" href="#">Another action</a> | |
<a class="dropdown-item" href="#">Something else here</a> | |
</div> | |
</li> | |
</ul> | |
<form class="form-inline my-2 my-lg-0"> | |
<input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search"> | |
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> | |
</form> | |
</div> | |
</nav> | |
EOT; | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_Body_Top(): string { | |
$html = $this->Render_Bootstrap_Nav() | |
. '<main role="main" class="container">' . "\n"; | |
return $html; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_Body_Content(): string { | |
return <<<EOT | |
<div class="centered-template"> | |
<h1>Bootstrap starter template</h1> | |
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p> | |
</div> | |
EOT; | |
} | |
/** | |
* | |
* @return string HTML | |
*/ | |
protected function Render_Body_Bottom(): string { | |
return "</main>\n"; | |
} | |
} | |
class PageTest extends BootstrapPage { | |
/** | |
* | |
* {@inheritDoc} | |
* @see \KarenWare\App\Page::Render_Body_Content() | |
*/ | |
protected function Render_Body_Content(): string { | |
return <<<EOT | |
<div class="centered-template"> | |
<h1>Hello world.</h1> | |
<p class="lead">Yay!</p> | |
</div> | |
EOT; | |
} | |
} | |
$page = new PageTest(); | |
echo $page->Render(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment