"email": "mike@php.net"
}
],
-
+ "bin": ["bin/ref2stub"],
"autoload": {
"psr-4": {
"mdref\\": "mdref/"
}
+ },
+ "require": {
+ "php": "^7.3",
+ "ext-ctype": "^7.3",
+ "ext-http": "^3.2",
+ "ext-filter": "^7.3",
+ "ext-pcre": "^7.3"
+ },
+ "suggests": {
+ "ext-discount": "A Markdown renderer is needed, this is the preferred one.",
+ "ext-cmark": "A Markdown renderer is needed, this is the fallback one."
}
}
use http\Env\Request;
use http\Env\Response;
use http\Message\Body;
+use stdClass;
+use function file_get_contents;
+use function htmlspecialchars;
+use function ob_start;
+use const ROOT;
/**
* Request handler
private $reference;
/**
- * @var \http\Request
+ * @var \http\Env\Request
*/
private $request;
/**
- * @var \http\Response
+ * @var \http\Env\Response
*/
private $response;
ob_start($res);
}
- function esc($txt) {
+ /**
+ * Shorthand for \htmlspecialchars()
+ * @param $txt string
+ * @return string
+ */
+ function esc(string $txt) : string {
return htmlspecialchars($txt);
}
/**
* Create the view payload
- * @param \http\Controller $ctl
* @return \stdClass
*/
- private function createPayload() {
- $pld = new \stdClass;
+ private function createPayload() : object {
+ $pld = new stdClass;
$pld->esc = "htmlspecialchars";
$pld->anchor = [$this->reference, "formatAnchor"];
}
/**
- * Redirect to canononical url
+ * Redirect to canonical url
* @param string $cnn
*/
- private function serveCanonical($cnn) {
+ private function serveCanonical(string $cnn) : void {
$this->response->setHeader("Location", $this->baseUrl->mod(["path" => $cnn]));
$this->response->setResponseCode(301);
$this->response->send();
/**
* Serve index.css
*/
- private function serveStylesheet() {
+ private function serveStylesheet() : void {
$this->response->setHeader("Content-Type", "text/css");
- $this->response->setBody(new \http\Message\Body(fopen(ROOT."/public/index.css", "r")));
+ $this->response->setBody(new Body(\fopen(ROOT."/public/index.css", "r")));
$this->response->send();
}
/**
* Serve index.js
*/
- private function serveJavascript() {
+ private function serveJavascript() : void {
$this->response->setHeader("Content-Type", "application/javascript");
- $this->response->setBody(new \http\Message\Body(fopen(ROOT."/public/index.js", "r")));
+ $this->response->setBody(new Body(\fopen(ROOT."/public/index.js", "r")));
$this->response->send();
}
/**
* Server a PHP stub
+ * @throws Exception
+ *
*/
- private function serveStub() {
+ private function serveStub() : void {
$name = $this->request->getQuery("ref", "s");
$repo = $this->reference->getRepoForEntry($name);
if (!$repo->hasStub($stub)) {
}
$this->response->setHeader("Content-Type", "application/x-php");
$this->response->setContentDisposition(["attachment" => ["filename" => "$name.stub.php"]]);
- $this->response->setBody(new Body(fopen($stub, "r")));
+ $this->response->setBody(new Body(\fopen($stub, "r")));
$this->response->send();
}
/**
* Serve a preset
- * @param \stdClass $pld
+ * @param object $pld
* @return true to continue serving the payload
* @throws Exception
*/
- private function servePreset($pld) {
+ private function servePreset(object $pld) : bool {
switch ($pld->ref) {
case "AUTHORS":
case "LICENSE":
return false;
}
- private function serve() {
+ /**
+ * Serve a payload
+ */
+ private function serve() : void {
extract((array) func_get_arg(0));
include ROOT."/views/layout.phtml";
+ $this->response->addHeader("Link", "<" . $this->baseUrl->path . "index.css>; rel=preload; as=style");
+ $this->response->addHeader("Link", "<" . $this->baseUrl->path . "index.js>; rel=preload; as=script");
$this->response->send();
}
- public function handle() {
+ /**
+ * Request handler
+ */
+ public function handle() : void {
try {
-
$pld = $this->createPayload();
if (strlen($pld->ref)) {
if (($repo = $this->reference->getRepoForEntry($pld->ref, $cnn))) {
if (strlen($cnn)) {
/* redirect */
- return $this->serveCanonical($cnn);
+ $this->serveCanonical($cnn);
+ return;
} else {
/* direct match */
$pld->entry = $repo->getEntry($pld->ref);
namespace mdref;
use http\Url;
+use function dirname;
+use function filter_input;
+use function strlen;
+use function substr;
+use function urldecode;
+use const FILTER_VALIDATE_BOOLEAN;
+use const INPUT_SERVER;
-class BaseUrl extends Url {
+class BaseUrl extends Url
+{
/**
* Create base URL
+ *
* @param mixed $url
*/
function __construct($url = null) {
- $self = array(
- "scheme" => filter_input(INPUT_SERVER, "HTTPS", FILTER_VALIDATE_BOOLEAN) ? "https":"http",
- "path" => dirname(filter_input(INPUT_SERVER, "SCRIPT_NAME"))."/"
- );
+ $self = [
+ "scheme" => filter_input(INPUT_SERVER, "HTTPS", FILTER_VALIDATE_BOOLEAN)
+ ? "https"
+ : "http",
+ "path" => dirname(filter_input(INPUT_SERVER, "SCRIPT_NAME")) . "/",
+ ];
parent::__construct($self, $url,
- self::JOIN_PATH |
- self::SANITIZE_PATH |
- self::STRIP_QUERY |
- self::STRIP_AUTH |
- self::FROM_ENV
+ self::JOIN_PATH |
+ self::SANITIZE_PATH |
+ self::STRIP_QUERY |
+ self::STRIP_AUTH |
+ self::FROM_ENV
);
}
+
/**
* Extract path info
*
* @param mixed $url full request url
* @return string
*/
- function pathinfo($url) {
+ function pathinfo($url) : string {
$url = new Url($this, $url, Url::FROM_ENV | Url::STRIP_QUERY);
$info = substr($url, strlen($this));
return urldecode($info);
namespace mdref;
+use IteratorAggregate;
+use function array_pop;
+use function count;
+use function ctype_lower;
+use function ctype_upper;
+use function dirname;
+use function end;
+use function explode;
+use function implode;
+use function strlen;
+use function strtr;
+use function substr;
+use function trim;
+
/**
* A single reference entry
*/
-class Entry implements \IteratorAggregate {
+class Entry implements IteratorAggregate {
/**
* Compound name
* @var string
/**
* The file path, if the refentry exists
- * @var type
+ * @var ?string
*/
private $path;
/**
* @param string $name the compound name of the ref entry, e.g. "pq/Connection/exec"
- * @param \mdref\Repo $repo the containing repository
+ * @param Repo $repo the containing repository
*/
- public function __construct($name, Repo $repo) {
+ public function __construct(string $name, Repo $repo) {
$this->repo = $repo;
$this->name = $name;
$this->list = explode("/", $name);
* Get the compound name, e.g. "pq/Connection/exec"
* @return string
*/
- public function getName() {
+ public function getName() : string {
return $this->name;
}
* Get the containing repository
* @return \mdref\Repo
*/
- public function getRepo() {
+ public function getRepo() : Repo {
return $this->repo;
}
* Get the file path, if any
* @return string
*/
- public function getPath() {
+ public function getPath() : ?string {
return $this->path;
}
/**
* Get the file instance of this entry
+ *
* @return \mdref\File
+ * @throws Exception
*/
- public function getFile() {
+ public function getFile() : File {
if (!$this->file) {
$this->file = new File($this->path);
}
* Get edit URL
* @return string
*/
- public function getEditUrl() {
+ public function getEditUrl() : string {
return $this->repo->getEditUrl($this->name);
}
/**
* Read the title of the ref entry file
+ *
* @return string
+ * @throws Exception
*/
- public function getTitle() {
+ public function getTitle() : string {
if ($this->isFile()) {
return trim($this->getFile()->readTitle());
}
/**
* Read the first line of the description of the ref entry file
+ *
* @return string
+ * @throws Exception
*/
- public function getDescription() {
+ public function getDescription() : string {
if ($this->isFile()) {
return trim($this->getFile()->readDescription());
}
/**
* Read the full description of the ref entry file
+ *
* @return string
+ * @throws Exception
*/
- public function getFullDescription() {
+ public function getFullDescription() : string {
if ($this->isFile()) {
return trim($this->getFile()->readFullDescription());
}
/**
* Read the intriductory section of the refentry file
+ *
* @return string
+ * @throws Exception
*/
- public function getIntro() {
+ public function getIntro() : string {
if ($this->isFile()) {
return trim($this->getFile()->readIntro());
}
* Check if the refentry exists
* @return bool
*/
- public function isFile() {
+ public function isFile() : bool {
return strlen($this->path) > 0;
}
* Check if this is the first entry of the reference tree
* @return bool
*/
- public function isRoot() {
+ public function isRoot() : bool {
return count($this->list) === 1;
}
* Get the parent ref entry
* @return \mdref\Entry
*/
- public function getParent() {
+ public function getParent() : ?Entry {
switch ($dirn = dirname($this->name)) {
case ".":
case "/":
- break;
+ return null;
default:
return $this->repo->getEntry($dirn);
}
* Get the list of parents up-down
* @return array
*/
- public function getParents() {
+ public function getParents() : array {
$parents = array();
for ($parent = $this->getParent(); $parent; $parent = $parent->getParent()) {
array_unshift($parents, $parent);
* Guess whether this ref entry is about a function or method
* @return bool
*/
- public function isFunction() {
+ public function isFunction() : bool {
$base = end($this->list);
return $base{0} === "_" || ctype_lower($base{0});
}
* Guess whether this ref entry is about a namespace, interface or class
* @return bool
*/
- public function isNsClass() {
+ public function isNsClass() : bool {
$base = end($this->list);
return ctype_upper($base{0});
}
+ /**
+ * @return mixed
+ */
public function getEntryName() {
return end($this->list);
}
- public function getNsName() {
+ /**
+ * Get namespaced name
+ * @return string
+ */
+ public function getNsName() : string {
if ($this->isRoot()) {
return $this->getName();
} elseif ($this->isFunction()) {
* Display name
* @return string
*/
- public function __toString() {
+ public function __toString() : string {
$parts = explode("/", trim($this->getName(), "/"));
$myself = array_pop($parts);
if (!$parts) {
}
/**
- * Get the base name of this ref entry
+ * Get the dirname for child entries
* @return string
*/
- public function getBasename() {
+ public function getNextDirname() : string {
return dirname($this->path) . "/" . basename($this->path, ".md");
}
/**
* Guess whether there are any child nodes
* @param string $glob
- * @return boolean
+ * @param bool $loose
+ * @return bool
*/
- function hasIterator($glob = null, $loose = false) {
+ function hasIterator(?string $glob = null, bool $loose = false) : bool {
if (strlen($glob)) {
- return glob($this->getBasename() . "/$glob") ||
- ($loose && glob($this->getBasename() . "/*/$glob"));
+ return glob($this->getNextDirname() . "/$glob") ||
+ ($loose && glob($this->getNextDirname() . "/*/$glob"));
} elseif ($this->isRoot()) {
return true;
- } elseif ($this->getBasename() !== "/") {
- return is_dir($this->getBasename());
+ } elseif ($this->getNextDirname() !== "/") {
+ return is_dir($this->getNextDirname());
} else {
return false;
}
* Guess whether there are namespace/interface/class child nodes
* @return bool
*/
- function hasNsClasses() {
+ function hasNsClasses() : bool {
return $this->hasIterator("/[A-Z]*.md", true);
}
* Guess whether there are function/method child nodes
* @return bool
*/
- function hasFunctions() {
+ function hasFunctions() : bool {
return $this->hasIterator("/[a-z_]*.md");
}
/**
- * Implements \IteratorAggregate
- * @return \mdref\Tree child nodes
+ * Implements IteratorAggregate
+ * @return Tree child nodes
*/
- function getIterator() {
- return new Tree($this->getBasename(), $this->repo);
+ function getIterator() : Tree {
+ return new Tree($this->getNextDirname(), $this->repo);
}
- function getStructure() {
+ /**
+ * Get the structure of the refentry
+ * @return Structure
+ */
+ function getStructure() : Structure {
return new Structure($this);
}
}
namespace mdref;
-use http\Response;
+use http\Env\Response;
+use http\Message\Body;
class Exception extends \Exception
{
- function __construct($code, $message) {
+ /**
+ * Exception constructor with reversed arguments
+ *
+ * @param int $code HTTP code
+ * @param string $message reason message
+ */
+ function __construct(int $code, ?string $message = null) {
parent::__construct($message, $code);
}
- function send(Response $res) {
+ /**
+ * Construct an Exception from error_get_last()'s message and code 500
+ * @return Exception
+ */
+ static function fromLastError() : Exception {
+ return new static(500, error_get_last()["message"]);
+ }
+
+ /**
+ * Send the error response
+ * @param Response $res
+ */
+ function send(Response $res) : void {
$res->setResponseCode($this->code);
- $res->setBody(new http\Message\Body);
+ $res->setBody(new Body);
$res->getBody()->append($this->message);
}
}
namespace mdref;
-use http\Env as HTTP;
+use http\Env;
+use function debug_print_backtrace;
+use function error_get_last;
+use function headers_sent;
+use function implode;
+use function ob_end_clean;
+use function ob_get_clean;
+use function ob_get_level;
+use function ob_start;
+use function register_shutdown_function;
+use function set_error_handler;
+use function set_exception_handler;
+use function sprintf;
+use const E_COMPILE_ERROR;
+use const E_CORE_ERROR;
+use const E_ERROR;
+use const E_PARSE;
+use const E_USER_ERROR;
/**
* Exception and error handler
/**
* Set up error/exception/shutdown handler
+ * @param Env\Response $r
*/
- public function __construct(\http\Env\Response $r) {
+ public function __construct(Env\Response $r) {
$this->response = $r;
set_exception_handler($this);
set_error_handler($this);
register_shutdown_function($this);
}
- private static function cleanBuffers() {
+ /**
+ * Clean output buffers
+ */
+ private static function cleanBuffers() : void {
while (ob_get_level()) {
if (!@ob_end_clean()) {
break;
/**
* The exception/error/shutdown handler callback
+ *
+ * @param \Throwable|string $e
+ * @param ?string $msg
+ * @throws \Exception
*/
- public function __invoke($e = null, $msg = null) {
- if ($e instanceof \Exception || $e instanceof \Throwable) {
+ public function __invoke($e = null, ?string $msg = null) : void {
+ if ($e instanceof \Throwable) {
try {
self::cleanBuffers();
echo static::htmlException($e);
} catch (\Exception $ignore) {
- headers_sent() or HTTP::setResponseCode(500);
+ headers_sent() or Env::setResponseCode(500);
die("FATAL ERROR:\n$e\n$ignore");
}
} elseif (isset($e, $msg)) {
/**
* Format an exception as HTML and send appropriate exception info as HTTP headers
- * @param Throwable $e
+ * @param \Throwable $e
* @param array $title_tag
* @param array $message_tag
* @param array $trace_tag
* @return string
*/
- public static function htmlException(/*\Throwable*/ $e, array $title_tag = ["h1"], array $message_tag = ["p"], array $trace_tag = ["pre", "style='font-size:smaller;overflow-x:scroll'"]) {
+ public static function htmlException(\Throwable $e, array $title_tag = ["h1"], array $message_tag = ["p"],
+ array $trace_tag = ["pre", "style='font-size:smaller;overflow-x:scroll'"]) : string {
if ($e instanceof Exception) {
$code = $e->getCode() ?: 500;
} else {
}
for ($html = ""; $e; $e = $e->getPrevious()) {
- $html .= static::htmlError(HTTP::getResponseStatusForCode($code),
+ $html .= static::htmlError(Env::getResponseStatusForCode($code),
$e->getMessage(), $code, $e->getTraceAsString(),
$title_tag, $message_tag, $trace_tag);
}
* @param array $trace_tag
* @return string
*/
- public static function htmlError($title, $message, $code, $trace = null, array $title_tag = ["h1"], array $message_tag = ["p"], array $trace_tag = ["pre", "style='font-size:smaller;overflow-x:scroll'"]) {
- HTTP::setResponseCode($code);
+ public static function htmlError($title, $message, $code, $trace = null, array $title_tag = ["h1"],
+ array $message_tag = ["p"], array $trace_tag = ["pre", "style='font-size:smaller;overflow-x:scroll'"]) : string {
+ Env::setResponseCode($code);
$html = sprintf("<%s>%s</%s>\n<%s>%s</%s>\n",
implode(" ", $title_tag), $title, $title_tag[0],
namespace mdref;
+use function feof;
+use function fgets;
+use function fopen;
+use function fseek;
+use function strncmp;
+use function substr;
+use const SEEK_SET;
+
/**
* A ref entry file
*/
/**
* Open the file
+ *
* @param string $path
+ * @throws Exception
*/
- public function __construct($path) {
- $this->fd = fopen($path, "rb");
+ public function __construct(string $path) {
+ if (!$this->fd = fopen($path, "rb")) {
+ throw Exception::fromLastError();
+ }
}
/**
* Read the title of the refentry
+ *
* @return string
+ * @throws Exception
*/
- public function readTitle() {
+ public function readTitle() : string {
if ($this->rewind(1)) {
return fgets($this->fd);
}
+ throw Exception::fromLastError();
}
/**
* Read the description (first line) of the refentry
+ *
* @return string
+ * @throws Exception
*/
- public function readDescription() {
- if ($this->rewind()
- && (false !== fgets($this->fd))
+ public function readDescription() : ?string {
+ if (!$this->rewind()) {
+ throw Exception::fromLastError();
+ }
+ if (false !== fgets($this->fd)
&& (false !== fgets($this->fd))) {
return fgets($this->fd);
}
+ return null;
}
/**
* Read the full description (first section) of the refentry
+ *
* @return string
+ * @throws Exception
*/
- public function readFullDescription() {
+ public function readFullDescription() : ?string {
$desc = $this->readDescription();
while (false !== ($line = fgets($this->fd))) {
if ($line{0} === "#") {
* Read the first subsection of a global refentry
* @return string
*/
- public function readIntro() {
+ public function readIntro() : string {
$intro = "";
if ($this->rewind()) {
$header = false;
return $intro;
}
- public function readSection($title) {
+ /**
+ * Read section of $title
+ *
+ * @param $title
+ * @return string
+ */
+ public function readSection(string $title) : string {
$section = "";
if ($this->rewind()) {
while (!feof($this->fd)) {
return $section;
}
- private function rewind($offset = 0) {
+ /**
+ * @param int $offset
+ * @return bool
+ */
+ private function rewind(int $offset = 0) : bool {
return 0 === fseek($this->fd, $offset, SEEK_SET);
}
- private function isHeading($line, $title = null) {
+ /**
+ * @param string $line
+ * @param string $title
+ * @return bool
+ */
+ private function isHeading(string $line, ?string $title = null) : bool {
if ("## " !== substr($line, 0, 3)) {
return false;
}
namespace mdref;
+use ArrayIterator;
+use Iterator;
+use IteratorAggregate;
+use function is_numeric;
+use function preg_replace;
+
/**
* The complete available reference
*/
-class Reference implements \IteratorAggregate {
+class Reference implements IteratorAggregate {
/**
* List of mdref repositories
- * @var array
+ * @var Repo[]
*/
private $repos = array();
/**
* Lookup the repo containing a ref entry
* @param string $entry requested reference entry, e.g. "pq/Connection/exec"
- * @param type $canonical
+ * @param string $canonical
* @return \mdref\Repo|NULL
*/
- public function getRepoForEntry($entry, &$canonical = null) {
+ public function getRepoForEntry(string $entry, string &$canonical = null) : ?Repo {
foreach ($this->repos as $repo) {
/** @var $repo Repo */
if ($repo->hasEntry($entry, $canonical)) {
return $repo;
}
}
+ return null;
}
/**
- * Implements \IteratorAggregate
- * @return \ArrayIterator repository list
+ * Implements IteratorAggregate
+ * @return ArrayIterator repository list
*/
- public function getIterator() {
- return new \ArrayIterator($this->repos);
+ public function getIterator() : Iterator {
+ return new ArrayIterator($this->repos);
}
- public function formatAnchor($anchor) {
+ /**
+ * @param string $anchor
+ * @return string
+ */
+ public function formatAnchor(string $anchor) : string {
if (is_numeric($anchor)) {
return "L$anchor";
}
return preg_replace("/[^[:alnum:]\.:_]/", ".", $anchor);
}
- public function formatString($string) {
+ /**
+ * @param string $string
+ * @return string
+ * @throws \Exception
+ */
+ public function formatString(string $string) : string {
if (extension_loaded("discount")) {
$md = \MarkdownDocument::createFromString($string);
$md->compile(\MarkdownDocument::AUTOLINK);
throw new \Exception("No Markdown implementation found");
}
- public function formatFile($file) {
+ /**
+ * @param string $file
+ * @return string
+ * @throws \Exception
+ */
+ public function formatFile(string $file) : string {
if (extension_loaded("discount")) {
$fd = fopen($file, "r");
$md = \MarkdownDocument::createFromStream($fd);
namespace mdref;
+use InvalidArgumentException;
+use IteratorAggregate;
+use function basename;
+use function current;
+use function file_get_contents;
+use function glob;
+use function is_file;
+use function realpath;
+use function rtrim;
+use function sprintf;
+use function trim;
+
/**
* A reference repo
*/
-class Repo implements \IteratorAggregate {
+class Repo implements IteratorAggregate {
/**
* The name of the repository
* @var string
* @param string $path
* @throws \InvalidArgumentException
*/
- public function __construct($path) {
+ public function __construct(string $path) {
if (!($mdref = current(glob("$path/*.mdref")))) {
- throw new \InvalidArgumentException(
- sprintf("Not a reference, could not find '*.mdref': '%s'",
- $path));
+ throw new InvalidArgumentException(
+ sprintf("Not a reference, could not find '*.mdref': '%s'", $path));
}
$this->path = realpath($path);
* Get the repository's name
* @return string
*/
- public function getName() {
+ public function getName() : string {
return $this->name;
}
* @param string $file
* @return string
*/
- public function getPath($file = "") {
+ public function getPath(string $file = "") : string {
return $this->path . "/$file";
}
* @param string $entry
* @return string
*/
- public function getEditUrl($entry) {
+ public function getEditUrl(string $entry) : string {
return sprintf($this->edit, $entry);
}
/**
* Get the file path of an entry in this repo
+ *
* @param string $entry
+ * @param string|null $canonical
* @return string file path
*/
- public function hasEntry($entry, &$canonical = null) {
+ public function hasEntry(string $entry, ?string &$canonical = null) : ?string {
$trim = rtrim($entry, "/");
$file = $this->getPath("$trim.md");
if (is_file($file)) {
$canonical = $this->getName() . "/" . $entry;
return $file;
}
+ return null;
}
/**
* @param string $file
* @return string entry
*/
- public function hasFile($file) {
+ public function hasFile(string $file) : ?string {
if (($file = realpath($file))) {
$path = $this->getPath();
$plen = strlen($path);
return $dirname . "/". $basename;
}
}
+ return null;
}
- public function hasStub(&$path = null) {
+ /**
+ * Check whether the repo has a stub file to serve
+ * @param string|null $path receives the path if there's a stub
+ * @return bool
+ */
+ public function hasStub(string &$path = null) : bool {
$path = $this->getPath($this->getName() . ".stub.php");
return is_file($path) && is_readable($path);
}
* @return \mdref\Entry
* @throws \OutOfBoundsException
*/
- public function getEntry($entry) {
+ public function getEntry(string $entry) : Entry {
return new Entry($entry, $this);
}
* Get the root Entry instance
* @return \mdref\Entry
*/
- public function getRootEntry() {
+ public function getRootEntry() : Entry {
return new Entry($this->name, $this);
}
* Implements \IteratorAggregate
* @return \mdref\Tree
*/
- public function getIterator() {
+ public function getIterator() : Tree {
return new Tree($this->path, $this);
}
}
namespace mdref;
-class Tree implements \RecursiveIterator {
+use Iterator;
+use RecursiveIterator;
+use function array_filter;
+use function array_search;
+use function basename;
+use function current;
+use function dirname;
+use function glob;
+use function is_dir;
+use function key;
+use function next;
+use function pathinfo;
+use function preg_match;
+use function reset;
+use function strcmp;
+use function usort;
+
+class Tree implements RecursiveIterator {
/**
* The repository
* @var \mdref\Repo
* @param string $path
* @param \mdref\Repo $repo
*/
- public function __construct($path, Repo $repo) {
+ public function __construct(string $path, Repo $repo) {
if (realpath($path)."/" === $repo->getPath()) {
$list = [$path ."/". $repo->getName() .".md"];
} elseif (!($list = glob("$path/*.md"))) {
* @param array $list
* @return callable
*/
- private function generateFilter(array $list) {
+ private function generateFilter(array $list) : \Closure {
return function($v) use($list) {
if ($v{0} === ".") {
return false;
/**
* @return callable
*/
- private function generateSorter() {
+ private function generateSorter() : \Closure {
return function($a, $b) {
$ab = basename($a, ".md");
$bb = basename($b, ".md");
* Implements \Iterator
* @return \mdref\Entry
*/
- public function current() {
+ public function current() : Entry {
return $this->repo->getEntry($this->repo->hasFile(current($this->iter)));
}
/**
* Implements \Iterator
*/
- public function next() {
+ public function next() : void {
next($this->iter);
}
* Implements \Iterator
* @return int
*/
- public function key() {
+ public function key() : int {
return key($this->iter);
}
/**
* Implements \Iterator
*/
- public function rewind() {
+ public function rewind() : void {
$this->iter = $this->list;
reset($this->iter);
}
* Implements \Iterator
* @return bool
*/
- public function valid() {
+ public function valid() : bool {
return null !== key($this->iter);
}
* Implements \RecursiveIterator
* @return bool
*/
- public function hasChildren() {
+ public function hasChildren() : bool {
return $this->current()->hasIterator();
}
* Implements \RecursiveIterator
* @return \mdref\Tree
*/
- public function getChildren() {
+ public function getChildren() : Iterator {
return $this->current()->getIterator();
}
}
<?php
-use mdref\Action;
-use mdref\BaseUrl;
-use mdref\Reference;
-use mdref\ExceptionHandler;
+namespace mdref;
use http\Env\Request;
use http\Env\Response;
+use function ini_get;
+use function ini_set;
+use function spl_autoload_register;
+use function strncmp;
+use function strtr;
+use const GLOB_ONLYDIR;
+use const PATH_SEPARATOR;
+use const REFS;
+use const ROOT;
define("ROOT", dirname(__DIR__));
define("REFS", getenv("REFPATH") ?: implode(PATH_SEPARATOR, glob(ROOT."/refs/*", GLOB_ONLYDIR)));