Renderer.php 5.39 KB
Newer Older
1 2 3 4 5 6 7 8
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\apidoc\templates\bootstrap;
9
use yii\apidoc\helpers\ApiMarkdown;
10 11 12 13 14 15 16 17 18 19 20 21
use yii\apidoc\models\Context;
use yii\console\Controller;
use Yii;
use yii\helpers\Console;

/**
 *
 * @author Carsten Brandt <mail@cebe.cc>
 * @since 2.0
 */
class Renderer extends \yii\apidoc\templates\html\Renderer
{
22 23
	public $apiLayout = '@yii/apidoc/templates/bootstrap/layouts/api.php';
	public $guideLayout = '@yii/apidoc/templates/bootstrap/layouts/guide.php';
24 25
	public $indexView = '@yii/apidoc/templates/bootstrap/views/index.php';

26 27 28 29
	public $pageTitle = 'Yii Framework 2.0 Documentation';

	public $guideUrl;

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
	public $extensions = [
		'apidoc',
		'authclient',
		'bootstrap',
		'codeception',
		'composer',
		'debug',
		'elasticsearch',
		'faker',
		'gii',
		'imagine',
		'jui',
		'mongodb',
		'redis',
		'smarty',
		'sphinx',
		'swiftmailer',
		'twig',
	];

	/**
	 * Renders a given [[Context]].
	 *
	 * @param Context $context the api documentation context to render.
	 * @param Controller $controller the apidoc controller instance. Can be used to control output.
	 */
	public function renderApi($context, $controller)
	{
		parent::renderApi($context, $controller);
		$dir = Yii::getAlias($this->targetDir);
		$types = array_merge($context->classes, $context->interfaces, $context->traits);

		$controller->stdout('generating extension index files...');
		foreach($this->extensions as $ext) {
			$readme = @file_get_contents("https://raw.github.com/yiisoft/yii2-$ext/master/README.md");
			$indexFileContent = $this->renderWithLayout($this->indexView, [
				'docContext' => $context,
				'types' => $this->filterTypes($types, $ext),
				'readme' => $readme ?: null,
			]);
			file_put_contents($dir . "/ext_{$ext}_index.html", $indexFileContent);
		}
72 73 74 75 76 77 78
		$readme = @file_get_contents("https://raw.github.com/yiisoft/yii2-framework/master/README.md");
		$indexFileContent = $this->renderWithLayout($this->indexView, [
			'docContext' => $context,
			'types' => $this->filterTypes($types, 'yii'),
			'readme' => $readme ?: null,
		]);
		file_put_contents($dir . '/index.html', $indexFileContent);
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
		$controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
	}

	public function getNavTypes($type, $types)
	{
		if ($type === null) {
			return $types;
		}
		$extensions = $this->extensions;
		$navClasses = 'app';
		if (isset($type)) {
			if ($type->name == 'Yii') {
				$navClasses = 'yii';
			} elseif (strncmp($type->name, 'yii\\', 4) == 0) {
				$subName = substr($type->name, 4);
				if (($pos = strpos($subName, '\\')) !== false) {
					$subNamespace = substr($subName, 0, $pos);
					if (in_array($subNamespace, $extensions)) {
						$navClasses = $subNamespace;
					} else {
						$navClasses = 'yii';
					}
				}
			}
		}
		return $this->filterTypes($types, $navClasses);
	}

	protected function filterTypes($types, $navClasses)
	{
		switch ($navClasses)
		{
			case 'app':
				$types = array_filter($types, function($val) {
					return strncmp($val->name, 'yii\\', 4) !== 0;
				});
				break;
			case 'yii':
				$self = $this;
				$types = array_filter($types, function($val) use ($self) {
					if (strlen($val->name) < 5) {
						return false;
					}
					$subName = substr($val->name, 4, strpos($val->name, '\\', 5) - 4);
					return strncmp($val->name, 'yii\\', 4) === 0 && !in_array($subName, $self->extensions);
				});
				break;
			default:
				$types = array_filter($types, function($val) use ($navClasses) {
					return strncmp($val->name, "yii\\$navClasses\\", strlen("yii\\$navClasses\\")) === 0;
				});
		}
		return $types;
	}

134 135 136 137 138 139 140 141 142 143 144 145 146
	/**
	 * Renders a given [[Context]].
	 *
	 * @param Context $context the api documentation context to render.
	 * @param Controller $controller the apidoc controller instance. Can be used to control output.
	 */
	public function renderMarkdownFiles($files, $controller)
	{
		$dir = Yii::getAlias($this->targetDir);
		if (!is_dir($dir)) {
			mkdir($dir, 0777, true);
		}

147
		ApiMarkdown::$renderer = $this;
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

		$fileCount = count($files) + 1;
		Console::startProgress(0, $fileCount, 'Rendering markdown files: ', false);
		$done = 0;
		$fileData = [];
		$headlines = [];
		foreach($files as $file) {
			$fileData[$file] = file_get_contents($file);
			if (basename($file) == 'index.md') {
				continue; // to not add index file to nav
			}
			if (preg_match("/^(.*)\n=+/", $fileData[$file], $matches)) {
				$headlines[$file] = $matches[1];
			} else {
				$headlines[$file] = basename($file);
			}
		}

		foreach($fileData as $file => $content) {
167
			$output = ApiMarkdown::process($content); // TODO generate links to yiiframework.com by default
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
			$output = $this->fixMarkdownLinks($output);
			if ($this->guideLayout !== false) {
				$params = [
					'headlines' => $headlines,
					'currentFile' => $file,
					'content' => $output,
				];
				$output = $this->getView()->renderFile($this->guideLayout, $params, $this);
			}
			$fileName = 'guide_' . str_replace('.md', '.html', basename($file));
			file_put_contents($dir . '/' . $fileName, $output);
			Console::updateProgress(++$done, $fileCount);
		}
		Console::updateProgress(++$done, $fileCount);
		Console::endProgress(true);
		$controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
	}

	protected function fixMarkdownLinks($content)
	{
188
		$content = preg_replace('/href\s*=\s*"([^"\/]+)\.md(#.*)?"/i', 'href="guide_\1.html\2"', $content);
189 190
		return $content;
	}
191
}