Upgrade to KH 3.3.0

This commit is contained in:
Deon George
2012-11-22 14:25:06 +11:00
parent e5e67a59bb
commit 5bd1841571
1455 changed files with 114353 additions and 9466 deletions

View File

@@ -30,42 +30,6 @@ Any images used in the userguide pages must be in `media/guide/<module>/`. For
The API browser is generated from the actual source code. The descriptions for classes, constants, properties, and methods is extracted from the comments and parsed in Markdown. For example if you look in the comment for [Kohana_Core::init](http://github.com/kohana/core/blob/c443c44922ef13421f4a/classes/kohana/core.php#L5) you can see a markdown list and table. These are parsed and show correctly in the API browser. `@param`, `@uses`, `@throws`, `@returns` and other tags are parsed as well.
## How to Contribute
### If you don't know git, or you don't feel like you are a good documentation writer:
Just submit a [bug report](http://dev.kohanaframework.org/projects/userguide3/issues/new) and explain what you think can be improved. If you are a good writer but don't know git, just provide some content in your bug report and we will merge it in.
### If you know git:
**Short version**: Create a ticket on redmine for your changes, fork the module whose docs you wish to improve (e.g. `git://github.com/kohana/orm.git` or `git://github.com/kohana/core.git`), checkout the appropriate branch, make changes, and then send a pull request with the ticket number.
**Long version:** (This still assumes you at least know your way around git, especially how submodules work.)
1. Create a ticket on redmine for your changes.
2. Fork the specific repo you want to contribute to on github. (For example go to http://github.com/kohana/core and click the fork button.)
3. Now go into the repo of the area of docs you want to contribute to and add your forked repo as a new remote, and push to it.
cd system
# make sure we are up to date
git checkout 3.1/develop
git pull
# add your repository as a new remote
git remote add <your name> git@github.com:<your name>/core.git
# (make some changes to the docs)
# now commit the changes and push to your repo
git commit
git push <your name> 3.1/develop
4. Send a pull request on github containing the ticket number, and update the ticket with a link to the pull request.
# What the userguide adds to markdown:
In addition to the features and syntax of [Markdown](http://daringfireball.net/projects/markdown/) and [Markdown Extra](http://michelf.com/projects/php-markdown/extra/) the following apply to userguide pages and api documentation:
@@ -96,10 +60,10 @@ You can make links to the api browser by wrapping any class name in brackets. Y
If you want to have parameters, only put the brackets around the class and function (not the params), and put a backslash in front of the opening parenthesis.
[Kohana::config]\('foobar','baz')
[Kohana::$config]\('foobar','baz')
### Including Views
You may include a view by putting the name of the view in double curly brackets. **If the view is not found, no exception or error will be shown!** The curly brackets and view will simply be shown an the page as is.
{{some/view}}
{{some/view}}

View File

@@ -0,0 +1,3 @@
<?php defined('SYSPATH') OR die('No direct script access.');
class Controller_Userguide extends Kohana_Controller_Userguide {}

View File

@@ -6,7 +6,7 @@
* @category Controllers
* @author Kohana Team
*/
class Controller_Userguide extends Controller_Template {
abstract class Kohana_Controller_Userguide extends Controller_Template {
public $template = 'userguide/template';
@@ -17,6 +17,8 @@ class Controller_Userguide extends Controller_Template {
public function before()
{
parent::before();
if ($this->request->action() === 'media')
{
// Do not template media files
@@ -28,28 +30,15 @@ class Controller_Userguide extends Controller_Template {
$this->media = Route::get('docs/media');
$this->guide = Route::get('docs/guide');
if (defined('MARKDOWN_PARSER_CLASS'))
{
throw new Kohana_Exception('Markdown parser already registered. Live documentation will not work in your environment.');
}
// Use customized Markdown parser
define('MARKDOWN_PARSER_CLASS', 'Kodoc_Markdown');
if ( ! class_exists('Markdown', FALSE))
{
// Load Markdown support
require Kohana::find_file('vendor', 'markdown/markdown');
}
// Set the base URL for links and images
Kodoc_Markdown::$base_url = URL::site($this->guide->uri()).'/';
Kodoc_Markdown::$image_url = URL::site($this->media->uri()).'/';
}
parent::before();
// Default show_comments to config value
$this->template->show_comments = Kohana::$config->load('userguide.show_comments');
}
// List all modules that have userguides
public function index()
{
@@ -57,32 +46,32 @@ class Controller_Userguide extends Controller_Template {
$this->template->breadcrumb = array('User Guide');
$this->template->content = View::factory('userguide/index', array('modules' => $this->_modules()));
$this->template->menu = View::factory('userguide/menu', array('modules' => $this->_modules()));
// Don't show disqus on the index page
$this->template->hide_disqus = TRUE;
$this->template->show_comments = FALSE;
}
// Display an error if a page isn't found
public function error($message)
{
$this->response->status(404);
$this->template->title = "Userguide - Error";
$this->template->content = View::factory('userguide/error',array('message' => $message));
// Don't show disqus on error pages
$this->template->hide_disqus = TRUE;
$this->template->show_comments = FALSE;
// If we are in a module and that module has a menu, show that
if ($module = $this->request->param('module') AND $menu = $this->file($module.'/menu') AND Kohana::config('userguide.modules.'.$module.'.enabled'))
if ($module = $this->request->param('module') AND $menu = $this->file($module.'/menu') AND Kohana::$config->load('userguide.modules.'.$module.'.enabled'))
{
// Namespace the markdown parser
Kodoc_Markdown::$base_url = URL::site($this->guide->uri()).'/'.$module.'/';
Kodoc_Markdown::$image_url = URL::site($this->media->uri()).'/'.$module.'/';
$this->template->menu = Markdown($this->_get_all_menu_markdown());
$this->template->menu = Kodoc_Markdown::markdown($this->_get_all_menu_markdown());
$this->template->breadcrumb = array(
$this->guide->uri() => 'User Guide',
$this->guide->uri(array('module' => $module)) => Kohana::config('userguide.modules.'.$module.'.name'),
$this->guide->uri(array('module' => $module)) => Kohana::$config->load('userguide.modules.'.$module.'.name'),
'Error'
);
}
@@ -119,19 +108,19 @@ class Controller_Userguide extends Controller_Template {
{
return $this->index();
}
// If this module's userguide pages are disabled, show the error page
if ( ! Kohana::config('userguide.modules.'.$module.'.enabled'))
if ( ! Kohana::$config->load('userguide.modules.'.$module.'.enabled'))
{
return $this->error(__('That module doesn\'t exist, or has userguide pages disabled.'));
return $this->error('That module doesn\'t exist, or has userguide pages disabled.');
}
// Prevent "guide/module" and "guide/module/index" from having duplicate content
if ( $page == 'index')
{
return $this->error(__('Userguide page not found'));
return $this->error('Userguide page not found');
}
// If a module is set, but no page was provided in the url, show the index page
if ( ! $page )
{
@@ -144,37 +133,37 @@ class Controller_Userguide extends Controller_Template {
// If it's not found, show the error page
if ( ! $file)
{
return $this->error(__('Userguide page not found'));
return $this->error('Userguide page not found');
}
// Namespace the markdown parser
Kodoc_Markdown::$base_url = URL::site($this->guide->uri()).'/'.$module.'/';
Kodoc_Markdown::$image_url = URL::site($this->media->uri()).'/'.$module.'/';
// Set the page title
$this->template->title = $page == 'index' ? Kohana::config('userguide.modules.'.$module.'.name') : $this->title($page);
$this->template->title = $page == 'index' ? Kohana::$config->load('userguide.modules.'.$module.'.name') : $this->title($page);
// Parse the page contents into the template
Kodoc_Markdown::$show_toc = true;
$this->template->content = Markdown(file_get_contents($file));
$this->template->content = Kodoc_Markdown::markdown(file_get_contents($file));
Kodoc_Markdown::$show_toc = false;
// Attach this module's menu to the template
$this->template->menu = Markdown($this->_get_all_menu_markdown());
$this->template->menu = Kodoc_Markdown::markdown($this->_get_all_menu_markdown());
// Bind the breadcrumb
$this->template->bind('breadcrumb', $breadcrumb);
// Bind the copyright
$this->template->copyright = Kohana::config('userguide.modules.'.$module.'.copyright');
$this->template->copyright = Kohana::$config->load('userguide.modules.'.$module.'.copyright');
// Add the breadcrumb trail
$breadcrumb = array();
$breadcrumb[$this->guide->uri()] = __('User Guide');
$breadcrumb[$this->guide->uri(array('module' => $module))] = Kohana::config('userguide.modules.'.$module.'.name');
$breadcrumb[$this->guide->uri()] = 'User Guide';
$breadcrumb[$this->guide->uri(array('module' => $module))] = Kohana::$config->load('userguide.modules.'.$module.'.name');
// TODO try and get parent category names (from menu). Regex magic or javascript dom stuff perhaps?
// Only add the current page title to breadcrumbs if it isn't the index, otherwise we get repeats.
if ($page != 'index')
{
@@ -194,7 +183,7 @@ class Controller_Userguide extends Controller_Template {
// If no class was passed to the url, display the API index page
if ( ! $class)
{
$this->template->title = __('Table of Contents');
$this->template->title = 'Table of Contents';
$this->template->content = View::factory('userguide/api/toc')
->set('classes', Kodoc::class_methods())
@@ -204,7 +193,7 @@ class Controller_Userguide extends Controller_Template {
{
// Create the Kodoc_Class version of this class.
$_class = Kodoc_Class::factory($class);
// If the class requested and the actual class name are different
// (different case, orm vs ORM, auth vs Auth) redirect
if ($_class->class->name != $class)
@@ -219,12 +208,12 @@ class Controller_Userguide extends Controller_Template {
// If this classes package has been disabled via the config, 404
if ( ! Kodoc::show_class($_class))
return $this->error('That class is in package that is hidden. Check the <code>api_packages</code> config setting.');
// Everything is fine, display the class.
$this->template->title = $class;
$this->template->content = View::factory('userguide/api/class')
->set('doc', Kodoc::factory($class))
->set('doc', $_class)
->set('route', $this->request->route());
}
@@ -234,12 +223,9 @@ class Controller_Userguide extends Controller_Template {
// Bind the breadcrumb
$this->template->bind('breadcrumb', $breadcrumb);
// Get the docs URI
$guide = Route::get('docs/guide');
// Add the breadcrumb
$breadcrumb = array();
$breadcrumb[$this->guide->uri(array('page' => NULL))] = __('User Guide');
$breadcrumb[$this->guide->uri(array('page' => NULL))] = 'User Guide';
$breadcrumb[$this->request->route()->uri()] = 'API Browser';
$breadcrumb[] = $this->template->title;
}
@@ -258,8 +244,8 @@ class Controller_Userguide extends Controller_Template {
if ($file = Kohana::find_file('media/guide', $file, $ext))
{
// Check if the browser sent an "if-none-match: <etag>" header, and tell if the file hasn't changed
$this->response->check_cache(sha1($this->request->uri()).filemtime($file), $this->request);
$this->check_cache(sha1($this->request->uri()).filemtime($file));
// Send the file content as the response
$this->response->body(file_get_contents($file));
@@ -307,83 +293,105 @@ class Controller_Userguide extends Controller_Template {
return parent::after();
}
/**
* Locates the appropriate markdown file for a given guide page. Page URLS
* can be specified in one of three forms:
*
* * userguide/adding
* * userguide/adding.md
* * userguide/adding.markdown
*
* In every case, the userguide will search the cascading file system paths
* for the file guide/userguide/adding.md.
*
* @param string $page The relative URL of the guide page
* @return string
*/
public function file($page)
{
// Strip optional .md or .markdown suffix from the passed filename
$info = pathinfo($page);
if (isset($info['extension'])
AND (($info['extension'] === 'md') OR ($info['extension'] === 'markdown')))
{
$page = $info['dirname'].DIRECTORY_SEPARATOR.$info['filename'];
}
return Kohana::find_file('guide', $page, 'md');
}
public function section($page)
{
$markdown = $this->_get_all_menu_markdown();
if (preg_match('~\*{2}(.+?)\*{2}[^*]+\[[^\]]+\]\('.preg_quote($page).'\)~mu', $markdown, $matches))
{
return $matches[1];
}
return $page;
}
public function title($page)
{
$markdown = $this->_get_all_menu_markdown();
if (preg_match('~\[([^\]]+)\]\('.preg_quote($page).'\)~mu', $markdown, $matches))
{
// Found a title for this link
return $matches[1];
}
return $page;
}
protected function _get_all_menu_markdown()
{
// Only do this once per request...
static $markdown = '';
if (empty($markdown))
{
// Get menu items
$file = $this->file($this->request->param('module').'/menu');
if ($file AND $text = file_get_contents($file))
{
// Add spans around non-link categories. This is a terrible hack.
//echo Kohana::debug($text);
//echo Debug::vars($text);
//$text = preg_replace('/(\s*[\-\*\+]\s*)(.*)/','$1<span>$2</span>',$text);
$text = preg_replace('/^(\s*[\-\*\+]\s*)([^\[\]]+)$/m','$1<span>$2</span>',$text);
//echo Kohana::debug($text);
//echo Debug::vars($text);
$markdown .= $text;
}
}
return $markdown;
}
// Get the list of modules from the config, and reverses it so it displays in the order the modules are added, but move Kohana to the top.
protected function _modules()
{
$modules = array_reverse(Kohana::config('userguide.modules'));
$modules = array_reverse(Kohana::$config->load('userguide.modules'));
if (isset($modules['kohana']))
{
$kohana = $modules['kohana'];
unset($modules['kohana']);
$modules = array_merge(array('kohana' => $kohana), $modules);
}
// Remove modules that have been disabled via config
foreach ($modules as $key => $value)
{
if ( ! Kohana::config('userguide.modules.'.$key.'.enabled'))
if ( ! Kohana::$config->load('userguide.modules.'.$key.'.enabled'))
{
unset($modules[$key]);
}
}
return $modules;
}

View File

@@ -5,7 +5,7 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Kodoc {
@@ -57,15 +57,6 @@ class Kohana_Kodoc {
{
$classes = Kodoc::classes();
foreach ($classes as $class)
{
if (isset($classes['kohana_'.$class]))
{
// Remove extended classes
unset($classes['kohana_'.$class]);
}
}
ksort($classes);
$menu = array();
@@ -74,6 +65,9 @@ class Kohana_Kodoc {
foreach ($classes as $class)
{
if (Kodoc::is_transparent($class, $classes))
continue;
$class = Kodoc_Class::factory($class);
// Test if we should show this class
@@ -113,9 +107,7 @@ class Kohana_Kodoc {
}
/**
* Returns an array of all the classes available, built by listing all files in the classes folder and then trying to create that class.
*
* This means any empty class files (as in complety empty) will cause an exception
* Returns an array of all the classes available, built by listing all files in the classes folder.
*
* @param array array of files, obtained using Kohana::list_files
* @return array an array of all the class names
@@ -129,19 +121,22 @@ class Kohana_Kodoc {
$classes = array();
// This will be used a lot!
$ext_length = strlen(EXT);
foreach ($list as $name => $path)
{
if (is_array($path))
{
$classes += Kodoc::classes($path);
}
else
elseif (substr($name, -$ext_length) === EXT)
{
// Remove "classes/" and the extension
$class = substr($name, 8, -(strlen(EXT)));
$class = substr($name, 8, -$ext_length);
// Convert slashes to underscores
$class = str_replace(DIRECTORY_SEPARATOR, '_', strtolower($class));
$class = str_replace(DIRECTORY_SEPARATOR, '_', $class);
$classes[$class] = $class;
}
@@ -166,13 +161,11 @@ class Kohana_Kodoc {
foreach ($list as $class)
{
$_class = new ReflectionClass($class);
if (stripos($_class->name, 'Kohana_') === 0)
{
// Skip transparent extension classes
// Skip transparent extension classes
if (Kodoc::is_transparent($class))
continue;
}
$_class = new ReflectionClass($class);
$methods = array();
@@ -180,10 +173,10 @@ class Kohana_Kodoc {
{
$declares = $_method->getDeclaringClass()->name;
if (stripos($declares, 'Kohana_') === 0)
// Remove the transparent prefix from declaring classes
if ($child = Kodoc::is_transparent($declares))
{
// Remove "Kohana_"
$declares = substr($declares, 7);
$declares = $child;
}
if ($declares === $_class->name OR $declares === "Core")
@@ -200,93 +193,149 @@ class Kohana_Kodoc {
return $classes;
}
/**
* Generate HTML for the content of a tag.
*
* @param string $tag Name of the tag without @
* @param string $text Content of the tag
* @return string HTML
*/
public static function format_tag($tag, $text)
{
if ($tag === 'license')
{
if (strpos($text, '://') !== FALSE)
return HTML::anchor($text);
}
elseif ($tag === 'link')
{
$split = preg_split('/\s+/', $text, 2);
return HTML::anchor(
$split[0],
isset($split[1]) ? $split[1] : $split[0]
);
}
elseif ($tag === 'copyright')
{
// Convert the copyright symbol
return str_replace('(c)', '&copy;', $text);
}
elseif ($tag === 'throws')
{
$route = Route::get('docs/api');
if (preg_match('/^(\w+)\W(.*)$/D', $text, $matches))
{
return HTML::anchor(
$route->uri(array('class' => $matches[1])),
$matches[1]
).' '.$matches[2];
}
return HTML::anchor(
$route->uri(array('class' => $text)),
$text
);
}
elseif ($tag === 'see' OR $tag === 'uses')
{
if (preg_match('/^'.Kodoc::$regex_class_member.'/', $text, $matches))
return Kodoc::link_class_member($matches);
}
return $text;
}
/**
* Parse a comment to extract the description and the tags
*
* @param string the comment retreived using ReflectionClass->getDocComment()
* [!!] Converting the output to HTML in this method is deprecated in 3.3
*
* @param string $comment The DocBlock to parse
* @param boolean $html Whether or not to convert the return values
* to HTML (deprecated)
* @return array array(string $description, array $tags)
*/
public static function parse($comment)
public static function parse($comment, $html = TRUE)
{
// Normalize all new lines to \n
$comment = str_replace(array("\r\n", "\n"), "\n", $comment);
// Remove the phpdoc open/close tags and split
$comment = array_slice(explode("\n", $comment), 1, -1);
// Split into lines while capturing without leading whitespace
preg_match_all('/^\s*\* ?(.*)\n/m', $comment, $lines);
// Tag content
$tags = array();
foreach ($comment as $i => $line)
/**
* Process a tag and add it to $tags
*
* @param string $tag Name of the tag without @
* @param string $text Content of the tag
* @return void
*/
$add_tag = function($tag, $text) use ($html, &$tags)
{
// Remove all leading whitespace
$line = preg_replace('/^\s*\* ?/m', '', $line);
// Search this line for a tag
if (preg_match('/^@(\S+)(?:\s*(.+))?$/', $line, $matches))
// Don't show @access lines, they are shown elsewhere
if ($tag !== 'access')
{
// This is a tag line
unset($comment[$i]);
$name = $matches[1];
$text = isset($matches[2]) ? $matches[2] : '';
switch ($name)
if ($html)
{
case 'license':
if (strpos($text, '://') !== FALSE)
{
// Convert the lincense into a link
$text = HTML::anchor($text);
}
break;
case 'link':
$text = preg_split('/\s+/', $text, 2);
$text = HTML::anchor($text[0], isset($text[1]) ? $text[1] : $text[0]);
break;
case 'copyright':
if (strpos($text, '(c)') !== FALSE)
{
// Convert the copyright sign
$text = str_replace('(c)', '&copy;', $text);
}
break;
case 'throws':
if (preg_match('/^(\w+)\W(.*)$/', $text, $matches))
{
$text = HTML::anchor(Route::get('docs/api')->uri(array('class' => $matches[1])), $matches[1]).' '.$matches[2];
}
else
{
$text = HTML::anchor(Route::get('docs/api')->uri(array('class' => $text)), $text);
}
break;
case 'uses':
if (preg_match('/^'.Kodoc::$regex_class_member.'$/i', $text, $matches))
{
$text = Kodoc::link_class_member($matches);
}
break;
// Don't show @access lines, they are shown elsewhere
case 'access':
continue 2;
$text = Kodoc::format_tag($tag, $text);
}
// Add the tag
$tags[$name][] = $text;
$tags[$tag][] = $text;
}
};
$comment = $tag = null;
$end = count($lines[1]) - 1;
foreach ($lines[1] as $i => $line)
{
// Search this line for a tag
if (preg_match('/^@(\S+)\s*(.+)?$/', $line, $matches))
{
if ($tag)
{
// Previous tag is finished
$add_tag($tag, $text);
}
$tag = $matches[1];
$text = isset($matches[2]) ? $matches[2] : '';
if ($i === $end)
{
// No more lines
$add_tag($tag, $text);
}
}
elseif ($tag)
{
// This is the continuation of the previous tag
$text .= "\n".$line;
if ($i === $end)
{
// No more lines
$add_tag($tag, $text);
}
}
else
{
// Overwrite the comment line
$comment[$i] = (string) $line;
$comment .= "\n".$line;
}
}
// Concat the comment lines back to a block of text
if ($comment = trim(implode("\n", $comment)))
$comment = trim($comment, "\n");
if ($comment AND $html)
{
// Parse the comment with Markdown
$comment = Markdown($comment);
$comment = Kodoc_Markdown::markdown($comment);
}
return array($comment, $tags);
@@ -328,7 +377,7 @@ class Kohana_Kodoc {
*/
public static function show_class(Kodoc_Class $class)
{
$api_packages = Kohana::config('userguide.api_packages');
$api_packages = Kohana::$config->load('userguide.api_packages');
// If api_packages is true, all packages should be shown
if ($api_packages === TRUE)
@@ -350,5 +399,68 @@ class Kohana_Kodoc {
return $show_this;
}
/**
* Checks whether a class is a transparent extension class or not.
*
* This method takes an optional $classes parameter, a list of all defined
* class names. If provided, the method will return false unless the extension
* class exists. If not, the method will only check known transparent class
* prefixes.
*
* Transparent prefixes are defined in the userguide.php config file:
*
* 'transparent_prefixes' => array(
* 'Kohana' => TRUE,
* );
*
* Module developers can therefore add their own transparent extension
* namespaces and exclude them from the userguide.
*
* @param string $class The name of the class to check for transparency
* @param array $classes An optional list of all defined classes
* @return false If this is not a transparent extension class
* @return string The name of the class that extends this (in the case provided)
* @throws InvalidArgumentException If the $classes array is provided and the $class variable is not lowercase
*/
public static function is_transparent($class, $classes = NULL)
{
static $transparent_prefixes = NULL;
if ( ! $transparent_prefixes)
{
$transparent_prefixes = Kohana::$config->load('userguide.transparent_prefixes');
}
// Split the class name at the first underscore
$segments = explode('_',$class,2);
if ((count($segments) == 2) AND (isset($transparent_prefixes[$segments[0]])))
{
if ($segments[1] === 'Core')
{
// Cater for Module extends Module_Core naming
$child_class = $segments[0];
}
else
{
// Cater for Foo extends Module_Foo naming
$child_class = $segments[1];
}
// It is only a transparent class if the unprefixed class also exists
if ($classes AND ! isset($classes[$child_class]))
return FALSE;
// Return the name of the child class
return $child_class;
}
else
{
// Not a transparent class
return FALSE;
}
}
} // End Kodoc

View File

@@ -5,7 +5,7 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009 Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Kodoc_Class extends Kodoc {
@@ -35,6 +35,11 @@ class Kohana_Kodoc_Class extends Kodoc {
*/
public $constants = array();
/**
* @var array Parent classes/interfaces of this class/interface
*/
public $parents = array();
/**
* Loads a class and uses [reflection](http://php.net/reflection) to parse
* the class. Reads the class modifiers, constants and comment. Parses the
@@ -52,43 +57,80 @@ class Kohana_Kodoc_Class extends Kodoc {
$this->modifiers = '<small>'.implode(' ', Reflection::getModifierNames($modifiers)).'</small> ';
}
if ($constants = $this->class->getConstants())
$this->constants = $this->class->getConstants();
// If ReflectionClass::getParentClass() won't work if the class in
// question is an interface
if ($this->class->isInterface())
{
foreach ($constants as $name => $value)
$this->parents = $this->class->getInterfaces();
}
else
{
$parent = $this->class;
while ($parent = $parent->getParentClass())
{
$this->constants[$name] = Debug::vars($value);
$this->parents[] = $parent;
}
}
$parent = $this->class;
do
if ( ! $comment = $this->class->getDocComment())
{
if ($comment = $parent->getDocComment())
foreach ($this->parents as $parent)
{
// Found a description for this class
break;
if ($comment = $parent->getDocComment())
{
// Found a description for this class
break;
}
}
}
while ($parent = $parent->getParentClass());
list($this->description, $this->tags) = Kodoc::parse($comment);
list($this->description, $this->tags) = Kodoc::parse($comment, FALSE);
}
/**
* Gets the constants of this class as HTML.
*
* @return array
*/
public function constants()
{
$result = array();
foreach ($this->constants as $name => $value)
{
$result[$name] = Debug::vars($value);
}
return $result;
}
/**
* Get the description of this class as HTML. Includes a warning when the
* class or one of its parents could not be found.
*
* @return string HTML
*/
public function description()
{
$result = $this->description;
// If this class extends Kodoc_Missing, add a warning about possible
// incomplete documentation
$parent = $this->class;
while ($parent = $parent->getParentClass())
foreach ($this->parents as $parent)
{
if ($parent->name == 'Kodoc_Missing')
{
$warning = "[!!] **This class, or a class parent, could not be
$result .= "[!!] **This class, or a class parent, could not be
found or loaded. This could be caused by a missing
module or other dependancy. The documentation for
class may not be complete!**";
$this->description = Markdown($warning).$this->description;
module or other dependancy. The documentation for
class may not be complete!**";
}
}
return Kodoc_Markdown::markdown($result);
}
/**
@@ -100,12 +142,14 @@ class Kohana_Kodoc_Class extends Kodoc {
{
$props = $this->class->getProperties();
$defaults = $this->class->getDefaultProperties();
usort($props, array($this,'_prop_sort'));
foreach ($props as $key => $property)
{
// Create Kodoc Properties for each property
$props[$key] = new Kodoc_Property($this->class->name, $property->name);
$props[$key] = new Kodoc_Property($this->class->name, $property->name, Arr::get($defaults, $property->name));
}
return $props;
@@ -174,7 +218,7 @@ class Kohana_Kodoc_Class extends Kodoc {
/*
echo kohana::debug('a is '.$a->class.'::'.$a->name,'b is '.$b->class.'::'.$b->name,
echo Debug::vars('a is '.$a->class.'::'.$a->name,'b is '.$b->class.'::'.$b->name,
'are the classes the same?', $a->class == $b->class,'if they are, the result is:',strcmp($a->name, $b->name),
'is a this class?', $a->name == $this->class->name,-1,
'is b this class?', $b->name == $this->class->name,1,
@@ -213,4 +257,23 @@ class Kohana_Kodoc_Class extends Kodoc {
return $bdepth - $adepth;
}
} // End Kodac_Class
/**
* Get the tags of this class as HTML.
*
* @return array
*/
public function tags()
{
$result = array();
foreach ($this->tags as $name => $set)
{
foreach ($set as $text)
{
$result[$name][] = Kodoc::format_tag($name, $text);
}
}
return $result;
}
}

View File

@@ -5,7 +5,7 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009 Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
@@ -38,6 +38,26 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
*/
public static $show_toc = false;
/**
* Transform some text using [Kodoc_Markdown]
*
* @see Markdown()
*
* @param string Text to parse
* @return string Transformed text
*/
public static function markdown($text)
{
static $instance;
if ($instance === NULL)
{
$instance = new Kodoc_Markdown;
}
return $instance->transform($text);
}
public function __construct()
{
// doImage is 10, add image url just before
@@ -107,7 +127,7 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
$attr = ' id="'.$this->make_heading_id($matches[2]).'"';
// Add this header to the page toc
$this->_add_to_toc($level,$matches[2],$this->make_heading_id($matches[2]));
$this->_add_to_toc($level, $matches[2], $this->make_heading_id(empty($matches[3]) ? $matches[2] : $matches[3]));
$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
@@ -152,18 +172,23 @@ class Kohana_Kodoc_Markdown extends MarkdownExtra_Parser {
{
list($search, $view) = $set;
try
if (Kohana::find_file('views', $view))
{
$replace[$search] = View::factory($view)->render();
}
catch (Exception $e)
{
ob_start();
try
{
$replace[$search] = View::factory($view)->render();
}
catch (Exception $e)
{
/**
* Capture the exception handler output and insert it instead.
*
* NOTE: Is this really the correct way to handle an exception?
*/
$response = Kohana_exception::_handler($e);
// Capture the exception handler output and insert it instead
Kohana_exception::handler($e);
$replace[$search] = ob_get_clean();
$replace[$search] = $response->body();
}
}
}

View File

@@ -68,7 +68,7 @@ class Kohana_Kodoc_Method extends Kodoc {
if (isset($tags['param'][$i]))
{
preg_match('/^(\S+)(?:\s*(?:\$'.$param->name.'\s*)?(.+))?$/', $tags['param'][$i], $matches);
preg_match('/^(\S+)(?:\s*(?:\$'.$param->name.'\s*)?(.+))?$/s', $tags['param'][$i], $matches);
$param->type = $matches[1];
@@ -138,4 +138,4 @@ class Kohana_Kodoc_Method extends Kodoc {
return $out;
}
} // End Kodoc_Method
} // End Kodoc_Method

View File

@@ -83,7 +83,7 @@ class Kohana_Kodoc_Method_Param extends Kodoc {
if ($this->description)
{
$display .= '<span class="param" title="'.$this->description.'">$'.$this->name.'</span> ';
$display .= '<span class="param" title="'.preg_replace('/\s+/', ' ', $this->description).'">$'.$this->name.'</span> ';
}
else
{

View File

@@ -5,7 +5,7 @@
* @package Kohana/Userguide
* @category Base
* @author Kohana Team
* @copyright (c) 2009 Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Kodoc_Property extends Kodoc {
@@ -30,7 +30,12 @@ class Kohana_Kodoc_Property extends Kodoc {
*/
public $value;
public function __construct($class, $property)
/**
* @var string default value of the property
*/
public $default;
public function __construct($class, $property, $default = NULL)
{
$property = new ReflectionProperty($class, $property);
@@ -45,19 +50,19 @@ class Kohana_Kodoc_Property extends Kodoc {
if (isset($tags['var']))
{
if (preg_match('/^(\S*)(?:\s*(.+?))?$/', $tags['var'][0], $matches))
if (preg_match('/^(\S*)(?:\s*(.+?))?$/s', $tags['var'][0], $matches))
{
$this->type = $matches[1];
if (isset($matches[2]))
{
$this->description = Markdown($matches[2]);
$this->description = Kodoc_Markdown::markdown($matches[2]);
}
}
}
$this->property = $property;
// Show the value of static properties, but only if they are public or we are php 5.3 or higher and can force them to be accessible
if ($property->isStatic() AND ($property->isPublic() OR version_compare(PHP_VERSION, '5.3', '>=')))
{
@@ -66,7 +71,7 @@ class Kohana_Kodoc_Property extends Kodoc {
{
$property->setAccessible(TRUE);
}
// Don't debug the entire object, just say what kind of object it is
if (is_object($property->getValue($class)))
{
@@ -77,7 +82,9 @@ class Kohana_Kodoc_Property extends Kodoc {
$this->value = Debug::vars($property->getValue($class));
}
}
// Store the defult property
$this->default = Debug::vars($default);;
}
} // End Kodoc_Property

View File

@@ -4,11 +4,14 @@ return array
(
// Enable the API browser. TRUE or FALSE
'api_browser' => TRUE,
// Enable these packages in the API browser. TRUE for all packages, or a string of comma seperated packages, using 'None' for a class with no @package
// Example: 'api_packages' => 'Kohana,Kohana/Database,Kohana/ORM,None',
'api_packages' => TRUE,
// Enables Disqus comments on the API and User Guide pages
'show_comments' => Kohana::$environment === Kohana::PRODUCTION,
// Leave this alone
'modules' => array(
@@ -25,7 +28,12 @@ return array
'description' => 'Documentation viewer and api generation.',
// Copyright message, shown in the footer for this module
'copyright' => '&copy; 20082011 Kohana Team',
'copyright' => '&copy; 20082012 Kohana Team',
)
),
// Set transparent class name segments
'transparent_prefixes' => array(
'Kohana' => TRUE,
)
);

View File

@@ -24,6 +24,20 @@ First, copy this config and place in it `<module>/config/userguide.php`, replaci
// Copyright message, shown in the footer for this module
'copyright' => '&copy; 20102011 <Your Name>',
)
),
/*
* If you use transparent extension outside the Kohana_ namespace,
* add your class prefix here. Both common Kohana naming conventions are
* excluded:
* - Modulename extends Modulename_Core
* - Foo extends Modulename_Foo
*
* For example, if you use Modulename_<class_name> for your base classes
* then you would define:
*/
'transparent_prefixes' => array(
'Modulename' => TRUE,
)
);

View File

@@ -6,17 +6,17 @@ The userguide has the following config options, available in `config/userguide.p
(
// Enable the API browser. TRUE or FALSE
'api_browser' => TRUE,
// Enable these packages in the API browser. TRUE for all packages, or a string of comma seperated packages, using 'None' for a class with no @package
// Example: 'api_packages' => 'Kohana,Kohana/Database,Kohana/ORM,None',
'api_packages' => TRUE,
);
You can enable or disabled the entire api browser, or limit it to only show certain packages. To disable a module from showing pages in the userguide, simply change that modules `enabled` option using the cascading filesystem. For example:
You can enable or disable the entire API browser, or limit it to only show certain packages. To disable a module from showing pages in the userguide, simply change that module's `enabled` option using the cascading filesystem. For example:
`application/config/userguide.php`
return array
(
'modules' => array
@@ -31,5 +31,5 @@ You can enable or disabled the entire api browser, or limit it to only show cert
)
)
)
Using this you could make the userguide only show your modules and your classes in the api browser, if you wanted to host your own documentation on your site. Feel free to change the styles and views as well, but be sure to give credit where credit is due!
Using this you could make the userguide only show your modules and classes in the API browser, if you wanted to host your own documentation on your site. Feel free to change the styles and views as well, but be sure to give credit where credit is due!

View File

@@ -1,5 +1,3 @@
[!!] When the docs get merged these images/links should be update
# Contributing
Kohana is community driven, and we rely on community contributions for the documentation.
@@ -18,7 +16,7 @@ To quickly point out something that needs improvement, report a [bug report](htt
If you want to contribute some changes, you can do so right from your browser without even knowing git!
First create an account on [Github](https://github.com/signup/free).
First create an account on [GitHub](https://github.com/signup/free).
You will need to fork the module for the area you want to improve. For example, to improve the [ORM documentation](../orm) fork <http://github.com/kohana/orm>. To improve the [Kohana documentation](../kohana), fork <http://github.com/kohana/core>, etc. So, find the module you want to improve and click on the Fork button in the top right.
@@ -36,31 +34,42 @@ After you have made your changes, send a pull request so your improvements can b
Once your pull request has been accepted, you can delete your repository if you want. Your commit will have been copied to the official branch.
## If you know git
## If you know Git
**Short version**: Create a ticket on redmine for your changes, fork the module whose docs you wish to improve (e.g. `git://github.com/kohana/orm.git` or `git://github.com/kohana/core.git`), checkout the appropriate branch, make changes, and then send a pull request with the ticket number.
### Short version
**Long version:** (This still assumes you at least know your way around git, especially how submodules work.)
Fork the module whose docs you wish to improve (e.g. `git://github.com/kohana/orm.git` or `git://github.com/kohana/core.git`), checkout the `3.2/develop` branch (for the 3.2 docs), make changes, and then send a pull request.
1. Create a ticket on redmine for your changes.
### Long version
2. Fork the specific repo you want to contribute to on github. (For example go to http://github.com/kohana/core and click the fork button.)
(This still assumes you at least know your way around Git, especially how submodules work.)
1. Fork the specific repo you want to contribute to on GitHub. (For example, go to http://github.com/kohana/core and click the fork button.)
1. Now you need to add your fork as a "git remote" to your application and ensure you are on the right branch. An example for the [ORM](../orm) module and 3.2 docs:
cd my-kohana-app/modules/orm
3. Now go into the repo of the area of docs you want to contribute to and add your forked repo as a new remote, and push to it.
cd system
# make sure we are up to date
git checkout 3.1/develop
git pull
# add your repository as a new remote
git remote add <your name> git@github.com:<your name>/core.git
# (make some changes to the docs)
# now commit the changes and push to your repo
git commit
git push <your name> 3.1/develop
git remote add <your name> git://github.com/<your name>/orm.git
4. Send a pull request on github containing the ticket number, and update the ticket with a link to the pull request.
# Get the correct branch
git checkout 3.2/develop
1. Now go into the repo of the area of docs you want to contribute to and add your forked repo as a new remote, and push to it.
cd my-kohana-app/modules/orm
# Make some changes to the docs
nano file.md
# Commit your changes - Use a descriptive commit message! If there is a redmine ticket for the changes you are making include "Fixes #XXXXX" in the commit message so its tracked.
git commit -a -m "Corrected a typo in the ORM docs. Fixes #12345."
# make sure we are up to date with the latest changes
git merge origin/3.2/develop
# Now push your changes to your fork.
git push <your name> 3.2/develop
1. Finally, send a pull request on GitHub.

View File

@@ -192,6 +192,8 @@ To link to page in a different module, prefix your url with `../` and the module
**Images are also namespaced**, using `![Alt Text](imagename.jpg)` would look for `media/guide/<modulename>/imagename.jpg`.
[!!] If you want your userguide pages to be browsable on github or similar sites outside Kohana's own userguide module, specify the optional .md file extension in your links
## API Links
You can make links to the api browser by wrapping any class name in brackets. You may also include a function name, or propery name to link to that specifically. All of the following will link to the API browser:
@@ -208,9 +210,9 @@ You can make links to the api browser by wrapping any class name in brackets. Y
If you want to have parameters and have the function be clickable, only put the brackets around the class and function (not the params), and put a backslash in front of the opening parenthesis.
[Kohana::config]\('foobar','baz')
[Kohana::$config]\('foobar','baz')
[Kohana::config]\('foobar','baz')
[Kohana::$config]\('foobar','baz')
## Notes

View File

@@ -1,6 +0,0 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array
(
'User Guide' => 'Handbuch'
);

View File

@@ -1,6 +0,0 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array
(
'User Guide' => 'Guía de Usuario'
);

View File

@@ -1,7 +0,0 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array
(
'User Guide' => 'Guide Utilisateur'
);

View File

@@ -1,6 +0,0 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array
(
'User Guide' => 'מדריך למשתמש'
);

View File

@@ -1,6 +0,0 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array
(
'User Guide' => 'Gebruiksaanwijzing'
);

View File

@@ -1,7 +0,0 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array
(
'User Guide' => 'Руководство пользователя'
);

View File

@@ -1,28 +0,0 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array
(
'User Guide' => '用户手册',
// Errors
'Error' => '错误',
'Userguide page not found' => '用户手册页面无法找到',
'API Reference: Class not found.' => 'API 参考: 没有找到此类。',
'That class is hidden' => '那个是隐藏类',
// API
'Table of Contents' => '目录',
'Available Classes' => '可用的类',
'Class Contents' => '类列表',
'Constants' => '常量',
'Properties' => '属性',
'Methods' => '方法',
'None' => '无',
'Parameters' => '参数',
'Parameter' => '参数',
'Type' => '类型',
'Description' => '描述',
'Default' => '默认',
'Return Values' => '返回值',
'Source Code' => '源代码',
);

View File

@@ -1,19 +1,19 @@
<?php defined('SYSPATH') or die('No direct script access.');
// Static file serving (CSS, JS, images)
Route::set('docs/media', 'guide/media(/<file>)', array('file' => '.+'))
Route::set('docs/media', 'guide-media(/<file>)', array('file' => '.+'))
->defaults(array(
'controller' => 'userguide',
'controller' => 'Userguide',
'action' => 'media',
'file' => NULL,
));
// API Browser, if enabled
if (Kohana::config('userguide.api_browser') === TRUE)
if (Kohana::$config->load('userguide.api_browser') === TRUE)
{
Route::set('docs/api', 'guide/api(/<class>)', array('class' => '[a-zA-Z0-9_]+'))
Route::set('docs/api', 'guide-api(/<class>)', array('class' => '[a-zA-Z0-9_]+'))
->defaults(array(
'controller' => 'userguide',
'controller' => 'Userguide',
'action' => 'api',
'class' => NULL,
));
@@ -24,7 +24,21 @@ Route::set('docs/guide', 'guide(/<module>(/<page>))', array(
'page' => '.+',
))
->defaults(array(
'controller' => 'userguide',
'controller' => 'Userguide',
'action' => 'docs',
'module' => '',
));
));
// Simple autoloader used to encourage PHPUnit to behave itself.
class Markdown_Autoloader {
public static function autoload($class)
{
if ($class == 'Markdown_Parser' OR $class == 'MarkdownExtra_Parser')
{
include_once Kohana::find_file('vendor', 'markdown/markdown');
}
}
}
// Register the autoloader
spl_autoload_register(array('Markdown_Autoloader', 'autoload'));

View File

@@ -95,48 +95,48 @@ h6:hover a.permalink {
}
#header,
#content,
#footer { float: left; clear: both; width: 100%; }
#kodoc-header,
#kodoc-content,
#kodoc-footer { float: left; clear: both; width: 100%; }
#header { padding: 58px 0 2em; background: #77c244 url(../img/header.png) center top repeat-x; }
#logo { display: block; float: left; }
#menu { float: right; margin-top: 12px; background: #113c32; -moz-border-radius: 5px; -webkit-border-radius: 5px; }
#menu ul { float: left; margin: 0; padding: 0 0.5em 0 0; }
#menu li { display: block; float: left; margin: 0; padding: 0; }
#menu li.first { padding-left: 0.5em; }
#menu li a { display: block; height: 32px; line-height: 32px; padding: 0 0.8em; border-right: solid 1px #0f362d; border-left: solid 1px #144539; letter-spacing: 0.05em; text-decoration: none; text-transform: uppercase; color: #efefef; font-size: 90%; }
#menu li.first a { border-left: 0; }
#menu li.last a { border-right: 0; }
#menu li a:hover { background: #164e41; border-left-color: #195a4b; color: #fff; text-shadow: #fff 0 0 1px; }
#kodoc-header { padding: 58px 0 2em; background: #77c244 url(../img/header.png) center top repeat-x; }
#kodoc-logo { display: block; float: left; }
#kodoc-menu { float: right; margin-top: 12px; background: #113c32; -moz-border-radius: 5px; -webkit-border-radius: 5px; }
#kodoc-menu ul { float: left; margin: 0; padding: 0 0.5em 0 0; }
#kodoc-menu li { display: block; float: left; margin: 0; padding: 0; }
#kodoc-menu li.first { padding-left: 0.5em; }
#kodoc-menu li a { display: block; height: 32px; line-height: 32px; padding: 0 0.8em; border-right: solid 1px #0f362d; border-left: solid 1px #144539; letter-spacing: 0.05em; text-decoration: none; text-transform: uppercase; color: #efefef; font-size: 90%; }
#kodoc-menu li.first a { border-left: 0; }
#kodoc-menu li.last a { border-right: 0; }
#kodoc-menu li a:hover { background: #164e41; border-left-color: #195a4b; color: #fff; text-shadow: #fff 0 0 1px; }
#content { background: #f1f8db url(../img/content.png) center top repeat-x; }
#content .wrapper { min-height: 390px; padding: 1em 0; background: transparent url(../img/wrapper.png) center top no-repeat; }
#content div.page-toc { float: right; margin: 1em; margin-top: 0; padding: 1em; background: #fff; border: solid 0.1em #e8efcf; border-radius: 0.6em; }
#content p.intro { padding: 1em 20px; padding-left: 20px; margin: 0 -20px; font-size: 1.2em; }
#content a { color: #004352; }
#content a:hover { color: #00758f; }
#content a:active { text-decoration: none; }
#kodoc-content { background: #f1f8db url(../img/content.png) center top repeat-x; }
#kodoc-content .wrapper { min-height: 390px; padding: 1em 0; background: transparent url(../img/wrapper.png) center top no-repeat; }
#kodoc-content div.page-toc { float: right; margin: 1em; margin-top: 0; padding: 1em; background: #fff; border: solid 0.1em #e8efcf; border-radius: 0.6em; }
#kodoc-content p.intro { padding: 1em 20px; padding-left: 20px; margin: 0 -20px; font-size: 1.2em; }
#kodoc-content a { color: #004352; }
#kodoc-content a:hover { color: #00758f; }
#kodoc-content a:active { text-decoration: none; }
#breadcrumb { margin: 0 0 1em; padding: 0 0 0.5em; list-style: none; border-bottom: solid 1px #e8efcf; }
#breadcrumb li { display: inline-block; margin: 0; padding: 0 0.4em 0 0; text-transform: uppercase; font-size: 11px; }
#breadcrumb li:before { content: '»'; padding-right: 0.4em; }
#breadcrumb li a { color: #999; text-decoration: none; }
#kodoc-breadcrumb { margin: 0 0 1em; padding: 0 0 0.5em; list-style: none; border-bottom: solid 1px #e8efcf; }
#kodoc-breadcrumb li { display: inline-block; margin: 0; padding: 0 0.4em 0 0; text-transform: uppercase; font-size: 11px; }
#kodoc-breadcrumb li:before { content: '»'; padding-right: 0.4em; }
#kodoc-breadcrumb li a { color: #999; text-decoration: none; }
#topics { }
#topics ul,
#topics ol { list-style-type:none; margin: 0; padding: 0;}
#topics ul li,
#topics ol li { margin:0; padding: 0; margin-left: 1em; }
#topics ul li a.current,
#topics ol li a.current { font-weight: bold; }
#topics span,
#topics a { display: block; padding: 0; margin: 0; }
#topics span { cursor: pointer; }
#topics span.toggle { display: block; float: left; width: 1em; padding-right: 0.4em; margin-left: -1.4em; text-align: center; }
#kodoc-topics { }
#kodoc-topics ul,
#kodoc-topics ol { list-style-type:none; margin: 0; padding: 0;}
#kodoc-topics ul li,
#kodoc-topics ol li { margin:0; padding: 0; margin-left: 1em; }
#kodoc-topics ul li a.current,
#kodoc-topics ol li a.current { font-weight: bold; }
#kodoc-topics span,
#kodoc-topics a { display: block; padding: 0; margin: 0; }
#kodoc-topics span { cursor: pointer; }
#kodoc-topics span.toggle { display: block; float: left; width: 1em; padding-right: 0.4em; margin-left: -1.4em; text-align: center; }
#topics li span { cursor:pointer; }
#kodoc-topics li span { cursor:pointer; }
#footer { padding: 1em 0; background: #00262f; color: #405c63; text-shadow: #00262f 0.1em 0.1em 1px; font-size: 0.9em; }
#footer a { color: #809397; }
#footer div.last { text-align: right; }
#kodoc-footer { padding: 1em 0; background: #00262f; color: #405c63; text-shadow: #00262f 0.1em 0.1em 1px; font-size: 0.9em; }
#kodoc-footer a { color: #809397; }
#kodoc-footer div.last { text-align: right; }

View File

@@ -17,10 +17,10 @@ $(document).ready(function()
$('a[href="'+ window.location.pathname +'"]').addClass('current');
// Breadcrumbs magic
$('#breadcrumb li.last').each(function()
$('#kodoc-breadcrumb li.last').each(function()
{
var $this = $(this);
var $topics = $('#topics li').has('a.current').slice(0, -1);
var $topics = $('#kodoc-topics li').has('a.current').slice(0, -1);
$topics.each(function()
{
@@ -33,7 +33,7 @@ $(document).ready(function()
});
// Collapsing menus
$('#topics li:has(li)').each(function()
$('#kodoc-topics li:has(li)').each(function()
{
var $this = $(this);
var toggle = $('<span class="toggle"></span>');
@@ -88,7 +88,7 @@ $(document).ready(function()
});
// "Link to this" link that appears when you hover over a header
$('#body')
$('#kodoc-body')
.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]')
.append(function(){
var $this = $(this);

View File

@@ -0,0 +1,368 @@
<?php
/**
* @group kohana
* @group kohana.userguide
*
* @package Kohana/Userguide
* @author Kohana Team
* @copyright (c) 2012 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_KodocTest extends PHPUnit_Framework_TestCase
{
public function provider_parse_basic()
{
return array(
array(
<<<'COMMENT'
/**
* Description
*/
COMMENT
,
array("<p>Description</p>\n", array()),
),
array(
<<<'COMMENT'
/**
* Description spanning
* multiple lines
*/
COMMENT
,
array("<p>Description spanning\nmultiple lines</p>\n", array()),
),
array(
<<<'COMMENT'
/**
* Description including
*
* a code block
*/
COMMENT
,
array("<p>Description including</p>\n\n<pre><code>a code block\n</code></pre>\n", array()),
),
array(
<<<'COMMENT'
/**
* Indented
*/
COMMENT
,
array("<p>Indented</p>\n", array()),
),
array(
<<<'COMMENT'
/**
* @tag Content
*/
COMMENT
,
array('', array('tag' => array('Content'))),
),
array(
<<<'COMMENT'
/**
* @tag Multiple
* @tag Tags
*/
COMMENT
,
array('', array('tag' => array('Multiple', 'Tags'))),
),
array(
<<<'COMMENT'
/**
* Description with tag
* @tag Content
*/
COMMENT
,
array(
"<p>Description with tag</p>\n",
array('tag' => array('Content')),
),
),
array(
<<<'COMMENT'
/**
* @trailingspace
*/
COMMENT
,
array('', array('trailingspace' => array(''))),
),
array(
<<<'COMMENT'
/**
* @tag Content that spans
* multiple lines
*/
COMMENT
,
array(
'',
array('tag' => array("Content that spans\nmultiple lines")),
),
),
array(
<<<'COMMENT'
/**
* @tag Content that spans
* multiple lines indented
*/
COMMENT
,
array(
'',
array('tag' => array("Content that spans\n multiple lines indented")),
),
),
);
}
/**
* @covers Kohana_Kodoc::parse
*
* @dataProvider provider_parse_basic
*
* @param string $comment Argument to the method
* @param array $expected Expected result
*/
public function test_parse_basic($comment, $expected)
{
$this->assertSame($expected, Kodoc::parse($comment));
}
public function provider_parse_tags()
{
$route_api = Route::get('docs/api');
return array(
array(
<<<'COMMENT'
/**
* @access public
*/
COMMENT
,
array('', array()),
),
array(
<<<'COMMENT'
/**
* @copyright Some plain text
*/
COMMENT
,
array('', array('copyright' => array('Some plain text'))),
),
array(
<<<'COMMENT'
/**
* @copyright (c) 2012 Kohana Team
*/
COMMENT
,
array('', array('copyright' => array('&copy; 2012 Kohana Team'))),
),
array(
<<<'COMMENT'
/**
* @license Kohana
*/
COMMENT
,
array('', array('license' => array('Kohana'))),
),
array(
<<<'COMMENT'
/**
* @license http://kohanaframework.org/license
*/
COMMENT
,
array('', array('license' => array('<a href="http://kohanaframework.org/license">http://kohanaframework.org/license</a>'))),
),
array(
<<<'COMMENT'
/**
* @link http://kohanaframework.org
*/
COMMENT
,
array('', array('link' => array('<a href="http://kohanaframework.org">http://kohanaframework.org</a>'))),
),
array(
<<<'COMMENT'
/**
* @link http://kohanaframework.org Description
*/
COMMENT
,
array('', array('link' => array('<a href="http://kohanaframework.org">Description</a>'))),
),
array(
<<<'COMMENT'
/**
* @see MyClass
*/
COMMENT
,
array(
'',
array(
'see' => array(
'<a href="'.URL::site(
$route_api->uri(array('class' => 'MyClass'))
).'">MyClass</a>',
),
),
),
),
array(
<<<'COMMENT'
/**
* @see MyClass::method()
*/
COMMENT
,
array(
'',
array(
'see' => array(
'<a href="'.URL::site(
$route_api->uri(array('class' => 'MyClass')).'#method'
).'">MyClass::method()</a>',
),
),
),
),
array(
<<<'COMMENT'
/**
* @throws Exception
*/
COMMENT
,
array(
'',
array(
'throws' => array(
'<a href="'.URL::site(
$route_api->uri(array('class' => 'Exception'))
).'">Exception</a>',
),
),
),
),
array(
<<<'COMMENT'
/**
* @throws Exception During failure
*/
COMMENT
,
array(
'',
array(
'throws' => array(
'<a href="'.URL::site(
$route_api->uri(array('class' => 'Exception'))
).'">Exception</a> During failure',
),
),
),
),
array(
<<<'COMMENT'
/**
* @uses MyClass
*/
COMMENT
,
array(
'',
array(
'uses' => array(
'<a href="'.URL::site(
$route_api->uri(array('class' => 'MyClass'))
).'">MyClass</a>',
),
),
),
),
array(
<<<'COMMENT'
/**
* @uses MyClass::method()
*/
COMMENT
,
array(
'',
array(
'uses' => array(
'<a href="'.URL::site(
$route_api->uri(array('class' => 'MyClass')).'#method'
).'">MyClass::method()</a>',
),
),
),
),
);
}
/**
* @covers Kohana_Kodoc::format_tag
* @covers Kohana_Kodoc::parse
*
* @dataProvider provider_parse_tags
*
* @param string $comment Argument to the method
* @param array $expected Expected result
*/
public function test_parse_tags($comment, $expected)
{
$this->assertSame($expected, Kodoc::parse($comment));
}
/**
* Provides test data for test_transparent_classes
* @return array
*/
public function provider_transparent_classes()
{
return array(
// Kohana_Core is a special case
array('Kohana','Kohana_Core',NULL),
array('Controller_Template','Kohana_Controller_Template',NULL),
array('Controller_Template','Kohana_Controller_Template',
array('Kohana_Controller_Template'=>'Kohana_Controller_Template',
'Controller_Template'=>'Controller_Template')
),
array(FALSE,'Kohana_Controller_Template',
array('Kohana_Controller_Template'=>'Kohana_Controller_Template')),
array(FALSE,'Controller_Template',NULL),
);
}
/**
* Tests Kodoc::is_transparent
*
* Checks that a selection of transparent and non-transparent classes give expected results
*
* @group kohana.userguide.3529-configurable-transparent-classes
* @dataProvider provider_transparent_classes
* @param mixed $expected
* @param string $class
* @param array $classes
*/
public function test_transparent_classes($expected, $class, $classes)
{
$result = Kodoc::is_transparent($class, $classes);
$this->assertSame($expected,$result);
}
}

View File

@@ -0,0 +1,45 @@
<?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
/**
* Unit tests for internal methods of userguide controller
*
* @group kohana
* @group kohana.userguide
* @group kohana.userguide.controller
*
* @package Kohana/Userguide
* @category Tests
* @author Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaframework.org/license
*/
class Userguide_ControllerTest extends Unittest_TestCase
{
public function provider_file_finds_markdown_files()
{
return array(
array('userguide/adding', 'guide/userguide/adding.md'),
array('userguide/adding.md', 'guide/userguide/adding.md'),
array('userguide/adding.markdown', 'guide/userguide/adding.md'),
array('userguide/does_not_exist.md', FALSE)
);
}
/**
* @dataProvider provider_file_finds_markdown_files
* @param string $page Page name passed in the URL
* @param string $expected_file Expected result from Controller_Userguide::file
*/
public function test_file_finds_markdown_files($page, $expected_file)
{
$controller = $this->getMock('Controller_Userguide', array('__construct'), array(), '', FALSE);
$path = $controller->file($page);
// Only verify trailing segments to avoid problems if file overwritten in CFS
$expected_len = strlen($expected_file);
$file = substr($path, -$expected_len, $expected_len);
$this->assertEquals($expected_file, $file);
}
}

View File

@@ -1,16 +1,34 @@
<h1>
<?php echo $doc->modifiers, $doc->class->name ?>
<?php $parent = $doc->class; ?>
<?php while ($parent = $parent->getParentClass()): ?>
<?php foreach ($doc->parents as $parent): ?>
<br/><small>extends <?php echo HTML::anchor($route->uri(array('class' => $parent->name)), $parent->name, NULL, NULL, TRUE) ?></small>
<?php endwhile ?>
<?php endforeach; ?>
</h1>
<?php echo $doc->description ?>
<?php if ($interfaces = $doc->class->getInterfaceNames()): ?>
<p class="interfaces"><small>
Implements:
<?php
for ($i = 0, $split = FALSE, $count = count($interfaces); $i < $count; $i++, $split = " | ")
{
echo $split . HTML::anchor($route->uri(array('class' => $interfaces[$i])), $interfaces[$i], NULL, NULL, TRUE);
}
?></small>
</p>
<?php endif; ?>
<?php if ($child = $doc->is_transparent($doc->class->name)):?>
<p class="note">
This class is a transparent base class for <?php echo HTML::anchor($route->uri(array('class'=>$child)),$child) ?> and
should not be accessed directly.
</p>
<?php endif;?>
<?php echo $doc->description() ?>
<?php if ($doc->tags): ?>
<dl class="tags">
<?php foreach ($doc->tags as $name => $set): ?>
<?php foreach ($doc->tags() as $name => $set): ?>
<dt><?php echo $name ?></dt>
<?php foreach ($set as $tag): ?>
<dd><?php echo $tag ?></dd>
@@ -29,38 +47,38 @@ Class is not declared in a file, it is probably an internal <?php echo html::anc
<div class="toc">
<div class="constants">
<h3><?php echo __('Constants'); ?></h3>
<h3><?php echo 'Constants'; ?></h3>
<ul>
<?php if ($doc->constants): ?>
<?php foreach ($doc->constants as $name => $value): ?>
<li><a href="#constant:<?php echo $name ?>"><?php echo $name ?></a></li>
<?php endforeach ?>
<?php else: ?>
<li><em><?php echo __('None'); ?></em></li>
<li><em><?php echo 'None'; ?></em></li>
<?php endif ?>
</ul>
</div>
<div class="properties">
<h3><?php echo __('Properties'); ?></h3>
<h3><?php echo 'Properties'; ?></h3>
<ul>
<?php if ($properties = $doc->properties()): ?>
<?php foreach ($properties as $prop): ?>
<li><a href="#property:<?php echo $prop->property->name ?>">$<?php echo $prop->property->name ?></a></li>
<?php endforeach ?>
<?php else: ?>
<li><em><?php echo __('None'); ?></em></li>
<li><em><?php echo 'None'; ?></em></li>
<?php endif ?>
</ul>
</div>
<div class="methods">
<h3><?php echo __('Methods'); ?></h3>
<h3><?php echo 'Methods'; ?></h3>
<ul>
<?php if ($methods = $doc->methods()): ?>
<?php foreach ($methods as $method): ?>
<li><a href="#<?php echo $method->method->name ?>"><?php echo $method->method->name ?>()</a></li>
<?php endforeach ?>
<?php else: ?>
<li><em><?php echo __('None'); ?></em></li>
<li><em><?php echo 'None'; ?></em></li>
<?php endif ?>
</ul>
</div>
@@ -70,9 +88,9 @@ Class is not declared in a file, it is probably an internal <?php echo html::anc
<?php if ($doc->constants): ?>
<div class="constants">
<h1 id="constants"><?php echo __('Constants'); ?></h1>
<h1 id="constants"><?php echo 'Constants'; ?></h1>
<dl>
<?php foreach ($doc->constants as $name => $value): ?>
<?php foreach ($doc->constants() as $name => $value): ?>
<dt><h4 id="constant:<?php echo $name ?>"><?php echo $name ?></h4></dt>
<dd><?php echo $value ?></dd>
<?php endforeach; ?>
@@ -81,20 +99,23 @@ Class is not declared in a file, it is probably an internal <?php echo html::anc
<?php endif ?>
<?php if ($properties = $doc->properties()): ?>
<h1 id="properties"><?php echo __('Properties'); ?></h1>
<h1 id="properties"><?php echo 'Properties'; ?></h1>
<div class="properties">
<dl>
<?php foreach ($properties as $prop): ?>
<dt><h4 id="property:<?php echo $prop->property->name ?>"><?php echo $prop->modifiers ?> <code><?php echo $prop->type ?></code> $<?php echo $prop->property->name ?></h4></dt>
<dd><?php echo $prop->description ?></dd>
<dd><?php echo $prop->value ?></dd>
<?php if ($prop->default !== $prop->value): ?>
<dd><small><?php echo __('Default value:') ?></small><br/><?php echo $prop->default ?></dd>
<?php endif ?>
<?php endforeach ?>
</dl>
</div>
<?php endif ?>
<?php if ($methods = $doc->methods()): ?>
<h1 id="methods"><?php echo __('Methods'); ?></h1>
<h1 id="methods"><?php echo 'Methods'; ?></h1>
<div class="methods">
<?php foreach ($methods as $method): ?>
<?php echo View::factory('userguide/api/method')->set('doc', $method)->set('route', $route) ?>

View File

@@ -27,7 +27,7 @@
<?php if ($doc->tags) echo View::factory('userguide/api/tags')->set('tags', $doc->tags) ?>
<?php if ($doc->return): ?>
<h4><?php echo __('Return Values'); ?></h4>
<h4><?php echo 'Return Values'; ?></h4>
<ul class="return">
<?php foreach ($doc->return as $set): list($type, $text) = $set; ?>
<li><code><?php echo HTML::chars($type) ?></code><?php if ($text) echo ' - '.HTML::chars(ucfirst($text)) ?></li>
@@ -37,7 +37,7 @@
<?php if ($doc->source): ?>
<div class="method-source">
<h4><?php echo __('Source Code'); ?></h4>
<h4><?php echo 'Source Code'; ?></h4>
<pre><code><?php echo HTML::chars($doc->source) ?></code></pre>
</div>
<?php endif ?>

View File

@@ -1,62 +1,56 @@
<h1><?php echo __('Available Classes') ?></h1>
<h1><?php echo 'Available Classes' ?></h1>
<label>Filter:</label>
<input type="text" id="api-filter-box" />
<input type="text" id="kodoc-api-filter-box" />
<script type="text/javascript">
(function($) {
$.fn.extend({
filter_content: function(search){
var search_regex = new RegExp(search,'gi');
// Run through each .class definition
$('.class', this).each(function(k, container){
if (search == '') {
// If search box is empty show everything without doing any regex
$(container).show();
$('li', container).show();
// Continue
return true;
}
// Run through every anchor
$('a', $(container)).each(function(k, anchor){
// Keep track of the li
var $parent = $(anchor).closest('li');
if ($(anchor).text().match(search_regex)) {
// Show the li and .class parent if its a match
$parent.show();
$(container).show();
} else {
// Otherwise we can only assume to hide the li
$parent.hide();
}
});
if ($('li:visible', $(container)).length == 0) {
// If there are not any visible li's, the entire .class section needs to hide
$(container).hide();
} else {
// Otherwise show the .class container
$(container).show();
}
});
},
api_filter: function(api_container_selector){
$(this).keyup(function(){
// Run the filter method on this value
$(api_container_selector).filter_content($(this).val());
});
}
})
})(jQuery);
var $api_container = $(api_container_selector);
var $this = this;
$(document).ready(function(){
$('#api-filter-box').api_filter('#kodoc-main');
});
if ($api_container.length) {
var $classes = $('.class', $api_container);
var $methods = $('.methods li', $classes);
var text = $methods.map(function(){ return $(this).text(); });
var timeout = null;
this.keyup(function(){
clearTimeout(timeout);
timeout = setTimeout(filter_content, 300);
});
filter_content();
}
function filter_content(){
var search = $this.val();
var search_regex = new RegExp(search,'gi');
if (search == '') {
$methods.show();
$classes.show();
} else {
$classes.hide();
$methods.hide();
text.each(function(i){
if (this.match(search_regex)) {
$($methods[i]).show().closest('.class').show();
}
});
}
}
return this;
}
});
$(document).ready(function(){
$('#kodoc-api-filter-box').api_filter('#kodoc-body').focus();
});
})(jQuery);
</script>
<div class="class-list">

View File

@@ -1,3 +1,3 @@
<h1>Kodoc - <?php echo __('Error'); ?></h1>
<h1>Kodoc - <?php echo 'Error'; ?></h1>
<p><?php echo $message ?></p>

View File

@@ -1,9 +1,9 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $l = substr(I18n::$lang, 0, 2) ?>" lang="<?php echo $l ?>">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title><?php echo $title ?> | Kohana <?php echo __('User Guide'); ?></title>
<title><?php echo $title ?> | Kohana <?php echo 'User Guide'; ?></title>
<?php foreach ($styles as $style => $media) echo HTML::style($style, array('media' => $media), NULL, TRUE), "\n" ?>
@@ -15,29 +15,31 @@
</head>
<body>
<div id="header">
<div id="kodoc-header">
<div class="container">
<a href="http://kohanaframework.org/" id="logo">
<a href="http://kohanaframework.org/" id="kodoc-logo">
<img src="<?php echo Route::url('docs/media', array('file' => 'img/kohana.png')) ?>" />
</a>
<div id="menu">
<div id="kodoc-menu">
<ul>
<li class="guide first">
<a href="<?php echo Route::url('docs/guide') ?>"><?php echo __('User Guide') ?></a>
<a href="<?php echo Route::url('docs/guide') ?>">User Guide</a>
</li>
<?php if (Kohana::$config->load('userguide.api_browser')): ?>
<li class="api">
<a href="<?php echo Route::url('docs/api') ?>"><?php echo __('API Browser') ?></a>
<a href="<?php echo Route::url('docs/api') ?>">API Browser</a>
</li>
<?php endif ?>
</ul>
</div>
</div>
</div>
<div id="content">
<div id="kodoc-content">
<div class="wrapper">
<div class="container">
<div class="span-22 prefix-1 suffix-1">
<ul id="breadcrumb">
<ul id="kodoc-breadcrumb">
<?php foreach ($breadcrumb as $link => $title): ?>
<?php if (is_string($link)): ?>
<li><?php echo HTML::anchor($link, $title, NULL, NULL, TRUE) ?></li>
@@ -48,14 +50,14 @@
</ul>
</div>
<div class="span-6 prefix-1">
<div id="topics">
<div id="kodoc-topics">
<?php echo $menu ?>
</div>
</div>
<div id="body" class="span-16 suffix-1 last">
<div id="kodoc-body" class="span-16 suffix-1 last">
<?php echo $content ?>
<?php if (Kohana::$environment === Kohana::PRODUCTION AND empty($hide_disqus)): ?>
<?php if ($show_comments): ?>
<div id="disqus_thread" class="clear"></div>
<script type="text/javascript">
var disqus_identifier = '<?php echo HTML::chars(Request::current()->uri()) ?>';
@@ -65,7 +67,7 @@
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript><?php echo __('Please enable JavaScript to view the :anchor_open comments powered by Disqus.:anchor_close', array(':anchor_open' => '<a href="http://disqus.com/?ref_noscript=kohana">', ':anchor_close' => '</a>')); ?></noscript>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript=kohana">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">Documentation comments powered by <span class="logo-disqus">Disqus</span></a>
<?php endif ?>
</div>
@@ -73,7 +75,7 @@
</div>
</div>
<div id="footer">
<div id="kodoc-footer">
<div class="container">
<div class="span-12">
<?php if (isset($copyright)): ?>