Renderer.php 5.67 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
	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...');
Alexander Mohorev committed
63
		foreach ($this->extensions as $ext) {
64 65 66 67 68 69 70 71
			$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
	/**
	 * Renders a given [[Context]].
	 *
	 * @param Controller $controller the apidoc controller instance. Can be used to control output.
	 */
139
	public function renderMarkdownFiles($controller)
140
	{
141
		$files = $this->markDownFiles;
142 143 144 145 146
		$dir = Yii::getAlias($this->targetDir);
		if (!is_dir($dir)) {
			mkdir($dir, 0777, true);
		}

147
		ApiMarkdown::$renderer = $this;
148 149 150 151 152 153

		$fileCount = count($files) + 1;
		Console::startProgress(0, $fileCount, 'Rendering markdown files: ', false);
		$done = 0;
		$fileData = [];
		$headlines = [];
Alexander Mohorev committed
154
		foreach ($files as $file) {
155 156 157 158 159 160 161 162 163 164 165
			$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);
			}
		}

Alexander Mohorev committed
166
		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
			$output = $this->fixMarkdownLinks($output);
			if ($this->guideLayout !== false) {
				$params = [
					'headlines' => $headlines,
					'currentFile' => $file,
					'content' => $output,
				];
				$output = $this->getView()->renderFile($this->guideLayout, $params, $this);
			}
177
			$fileName = $this->generateGuideFileName($file);
178 179 180 181 182 183 184 185
			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);
	}

186 187 188 189 190 191 192 193
	protected function generateGuideFileName($file)
	{
		return 'guide_' . basename($file, '.md') . '.html';
	}

	public function getGuideReferences()
	{
		$refs = [];
Alexander Mohorev committed
194
		foreach ($this->markDownFiles as $file) {
195 196 197 198 199 200
			$refName = 'guide-' . basename($file, '.md');
			$refs[$refName] = ['url' => $this->generateGuideFileName($file)];
		}
		return $refs;
	}

201 202
	protected function fixMarkdownLinks($content)
	{
203
		$content = preg_replace('/href\s*=\s*"([^"\/]+)\.md(#.*)?"/i', 'href="guide_\1.html\2"', $content);
204 205
		return $content;
	}
206
}