Skip to content

Instantly share code, notes, and snippets.

@basz
Last active August 29, 2015 14:20
Show Gist options
  • Select an option

  • Save basz/f26e005977e2ec461e4d to your computer and use it in GitHub Desktop.

Select an option

Save basz/f26e005977e2ec461e4d to your computer and use it in GitHub Desktop.
<?php
namespace Application\Navigation\Service\Factory;
use Zend\Navigation\Service\AbstractNavigationFactory;
use Zend\ServiceManager\ServiceLocatorInterface;
class FSNavigationFactory extends AbstractNavigationFactory
{
/**
* @return string
*/
protected function getName()
{
return 'apidocumentation';
}
/**
* @param ServiceLocatorInterface $serviceLocator
* @return array
* @throws \Zend\Navigation\Exception\InvalidArgumentException
*/
protected function getPages(ServiceLocatorInterface $serviceLocator)
{
if (null === $this->pages) {
$filesystem = $serviceLocator->get('BsbFlysystemManager')->get($this->getName());
$entries = $filesystem->listContents('/chapters', true);
$entries = array_filter($entries, [$this, 'filterFileEntries']);
$pathlist = array_column($entries, 'path');
$pathtree = $this->explodeTree($pathlist);
$config = $this->buildConfig($pathtree, $entries);
$pages = $this->getPagesFromConfig($config);
$this->pages = $this->preparePages($serviceLocator, $pages);
}
return $this->pages;
}
protected function buildConfig($pathtree, $entries, $slugPrepend = '')
{
$config = [];
foreach ($pathtree as $key => $value) {
$page = [];
$filename = pathinfo($key, PATHINFO_FILENAME);
if (preg_match('/^((?<order>([0-9])+) - )?(?<name>.*)$/', $filename, $matches)) {
$name = $matches['name'];
$slug = strlen($slugPrepend) ? sprintf("%s-%s", $slugPrepend,
$this->slugify($name)) : $this->slugify($name);
$page['order'] = isset($matches['order']) ? (int) $matches['order'] : 0;
$page['label'] = $name;
$page['uri'] = sprintf('/#%s', $slug);
if (is_array($value)) {
$page['pages'] = $this->buildConfig($value, $entries, $slug);
}
$config[] = $page;
}
}
return $config;
}
/**
* Utility method to explode a flat array into a tree structure
*
* Array
* (
* [chapters] => Array
* (
* [00 - Introduction] => Array
* (
* [01 - Subscription.md] => 'chapters/00 - Introduction/01 - Subscription.md'
* [02 - Api Overview.md] => 'chapters/00 - Introduction/01 - Api Overview.md'
* [03 - Maintenance Mode.md] => 'chapters/00 - Introduction/01 - Maintenance Mode.md'
* )
*
* [00 - Introduction.md] => 'chapters/00 - Introduction.md'
* [02 - Status] => Array
* (
* [Api Status.md] => 'chapters/02 - Status/Api Status.md'
* )
*
* )
*
* )
* @param array $array
* @param string $delimiter
* @return array
*/
private function explodeTree(array $array, $delimiter = DIRECTORY_SEPARATOR)
{
$tree = array();
foreach ($array as $key => $path) {
$parts = array_filter(explode($delimiter, $path));
$leafPart = array_pop($parts);
$parentArr = &$tree;
foreach ($parts as $part) {
if (!isset($parentArr[$part])) {
$parentArr[$part] = array();
} elseif (!is_array($parentArr[$part])) {
$parentArr[$part] = array();
}
$parentArr = &$parentArr[$part];
}
// Add the final part to the structure
if (empty($parentArr[$leafPart])) {
$parentArr[$leafPart] = $path; //array_search($path, $array);
}
}
return $tree;
}
/**
* Filter callback - filters out
*
* - directories or files with 'disabled' in name
* - files that do not have .md extension
* - any directory
*
* @param $entry
* @return bool
*/
private function filterFileEntries($entry)
{
if ($entry['type'] == 'dir') {
return false;
}
if (strpos($entry['path'], 'disabled') !== false) {
return false;
}
if ($entry['type'] == 'file' && pathinfo($entry['path'], PATHINFO_EXTENSION) != 'md') {
return false;
}
return true;
}
protected function slugify($string)
{
$slug = trim($string); // trim the string
$slug = preg_replace('/[^a-zA-Z0-9 -]/', '', $slug);
$slug = str_replace(' ', '-', $slug);
$slug = strtolower($slug);
return $slug;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment