Skip to content

Instantly share code, notes, and snippets.

@jwinett
Last active June 7, 2018 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jwinett/e89e7856fe04b6f910ee7c8685738d87 to your computer and use it in GitHub Desktop.
Save jwinett/e89e7856fe04b6f910ee7c8685738d87 to your computer and use it in GitHub Desktop.
YAF - Yet Another Framework for page rendering in PHP w/ Bootstrap 4
<?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