0ce23593d8a1ebd53a10295186c7b2e1061618cb
Author: chawbacca
Date: 2009-02-04 16:50:05 -0600
diff --git a/.gitignore b/.gitignore
index 30cbe32..cdc7698 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,9 @@
.DS_Store
-api_config.ini
\ No newline at end of file
+api_config.ini
+errors.err
+*.swp
+*.swo
+*~
+config/core.php
+config/database.php
+tmp/*
\ No newline at end of file
diff --git a/config/sql/api_generator.php b/config/sql/api_generator.php
index 33ea2b5..2e2f0b5 100644
--- a/config/sql/api_generator.php
+++ b/config/sql/api_generator.php
@@ -20,8 +20,8 @@
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
* @package cake
* @subpackage cake.api_generator.config
- * @since
- * @version
+ * @since
+ * @version
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
/**
@@ -40,7 +40,8 @@ class ApiGeneratorSchema extends CakeSchema {
'name' => array('type' => 'string', 'length' => 200, 'null' => false),
'slug' => array('type' => 'string', 'length' => 200, 'null' => false),
'file_name' => array('type' => 'text'),
- 'search_index' => array('type' => 'text'),
+ 'method_index' => array('type' => 'text'),
+ 'property_index' => array('type' => 'text'),
'flags' => array('type' => 'integer', 'default' => 0, 'length' => 5),
'created' => array('type' => 'datetime'),
'modified' => array('type' => 'datetime'),
diff --git a/controllers/api_generator_controller.php b/controllers/api_generator_controller.php
index 3b351f0..2fafdae 100644
--- a/controllers/api_generator_controller.php
+++ b/controllers/api_generator_controller.php
@@ -37,7 +37,7 @@ class ApiGeneratorController extends ApiGeneratorAppController {
*
* @var array
*/
- public $uses = array('ApiGenerator.ApiFile');
+ public $uses = array('ApiGenerator.ApiFile', 'ApiGenerator.ApiClass');
/**
* Components array
*
@@ -49,7 +49,7 @@ class ApiGeneratorController extends ApiGeneratorAppController {
*
* @var array
**/
- public $helpers = array('ApiGenerator.ApiDoc', 'ApiGenerator.ApiUtils', 'Html', 'Javascript');
+ public $helpers = array('ApiGenerator.ApiDoc', 'ApiGenerator.ApiUtils', 'Html', 'Javascript', 'Text');
/**
* Browse application files and find things you would like to generate API docs for.
*
@@ -97,7 +97,6 @@ class ApiGeneratorController extends ApiGeneratorAppController {
* @return void
**/
public function classes() {
- $this->ApiClass = ClassRegistry::init('ApiGenerator.ApiClass');
$classIndex = $this->ApiClass->getClassIndex();
$this->set('classIndex', $classIndex);
}
@@ -121,7 +120,7 @@ class ApiGeneratorController extends ApiGeneratorAppController {
} catch(Exception $e) {
$this->_notFound($e->getMessage());
}
- $classIndex = ClassRegistry::init('ApiGenerator.ApiClass')->getClassIndex();
+ $classIndex = $this->ApiClass->getClassIndex();
list($dirs, $files) = $this->ApiFile->read($this->path . $previousPath);
if (!empty($docs)) {
@@ -144,7 +143,6 @@ class ApiGeneratorController extends ApiGeneratorAppController {
$this->Session->setFlash(__('No class name was given', true));
$this->redirect($this->referer());
}
- $this->ApiClass = ClassRegistry::init('ApiGenerator.ApiClass');
$classInfo = $this->ApiClass->findBySlug($classSlug);
if (empty($classInfo['ApiClass']['file_name'])) {
$this->_notFound(__('No class exists in the index with that name', true));
@@ -171,7 +169,6 @@ class ApiGeneratorController extends ApiGeneratorAppController {
* @return void
**/
public function view_source($classSlug = null) {
- $this->ApiClass = ClassRegistry::init('ApiGenerator.ApiClass');
$classInfo = $this->ApiClass->findBySlug($classSlug);
if (empty($classInfo['ApiClass']['file_name'])) {
@@ -186,19 +183,93 @@ class ApiGeneratorController extends ApiGeneratorAppController {
*
* @return void
**/
- public function search() {
- $this->ApiClass = ClassRegistry::init('ApiGenerator.ApiClass');
+ public function search($term = null) {
+ $conditions = array();
+ if (!empty($this->params['url']['query'])) {
+ $term = $this->params['url']['query'];
+ return $this->redirect(array($term));
+ }
+ $term = trim($term);
+ $terms = explode(' ', $term);
$conditions = array();
- if (isset($this->params['url']['query'])) {
- $query = $this->params['url']['query'];
- $conditions = array('ApiClass.search_index LIKE' => '%' . $query . '%');
+ $match = false;
+ foreach ($terms as $i => $j) {
+ if (trim($j) === '') {
+ unset ($terms[$i]);
+ }
+ }
+ foreach ($terms as $i => $class) {
+ $slug = str_replace('_', '-', Inflector::slug(Inflector::underscore($class)));
+ if ($this->ApiClass->find('count', array('conditions' => array('slug like' => $slug . '%')))) {
+ $match = $class;
+ break;
+ }
+ }
+ $fields = array('DISTINCT ApiClass.name', 'ApiClass.method_index', 'ApiClass.property_index', 'file_name');
+ $order = 'ApiClass.name';
+ if ($match) {
+ $conditions['ApiClass.slug like'] = $slug . '%';
+ $results = $this->ApiClass->find('all', compact('conditions', 'order', 'fields'));
+ } else {
+ $results = array();
+ }
+ $conditions = array();
+ foreach ($terms as $term) {
+ $conditions['NOT']['ApiClass.id'] = Set::extract($results, '/ApiClass/id');
+ $conditions['OR'][] = array('OR' => array(
+ 'ApiClass.method_index LIKE' => '% ' . $term . '%',
+ ));
+ }
+ $results = am($results, $this->ApiClass->find('all', compact('conditions', 'order', 'fields')));
+ $conditions = array();
+ foreach ($terms as $term) {
+ $conditions['NOT']['ApiClass.id'] = Set::extract($results, '/ApiClass/id');
+ $conditions['OR'][] = array('OR' => array(
+ 'ApiClass.property_index LIKE' => '% ' . $term . '%',
+ ));
+ }
+ $results = am($results, $this->ApiClass->find('all', compact('conditions', 'order', 'fields')));
+ $docs = array();
+ foreach ($results as $i => $result) {
+ $docs[$i] = $this->ApiFile->loadFile($result['ApiClass']['file_name'], array('useIndex' => true));
+ foreach ($docs[$i]['class'] as $name => &$obj) {
+ foreach ($obj->properties as $j => $prop) {
+ $delete = true;
+ foreach($terms as $term) {
+ if (strpos($prop['name'], $term) !== false) {
+ $delete = false;
+ break;
+ }
+ }
+ if ($delete) {
+ unset ($obj->properties[$j]);
+ }
+ }
+ foreach ($obj->methods as $j => $method) {
+ $delete = true;
+ foreach($terms as $term) {
+ if (strpos($method['name'], $term) !== false) {
+ $delete = false;
+ break;
+ }
+ }
+ if ($delete) {
+ unset ($obj->methods[$j]);
+ }
+ }
+ if (!$match && !$obj->methods && !$obj->properties) {
+ unset($docs[$i]['class']);
+ }
+ }
+ if (!$docs[$i]['function']) {
+ unset ($docs[$i]['function']);
+ }
+ if (!$docs[$i]) {
+ unset ($docs[$i]);
+ }
}
- $this->paginate['fields'] = array('DISTINCT ApiClass.name', 'ApiClass.search_index');
- $this->paginate['order'] = 'ApiClass.name ASC';
- $results = $this->paginate($this->ApiClass, $conditions);
$classIndex = $this->ApiClass->getClassIndex();
- $this->helpers[] = 'Text';
- $this->set(compact('results', 'classIndex'));
+ $this->set(compact('classIndex', 'terms', 'class', 'docs'));
}
/**
* Extract all the useful config info out of the ApiConfig.
diff --git a/models/api_class.php b/models/api_class.php
index 01e92ef..a318214 100644
--- a/models/api_class.php
+++ b/models/api_class.php
@@ -76,7 +76,8 @@ class ApiClass extends ApiGeneratorAppModel {
'name' => $classDoc->name,
'slug' => $slug,
'file_name' => $classDoc->classInfo['fileName'],
- 'search_index' => $this->_generateSearchIndex($classDoc),
+ 'method_index' => $this->_generateIndex($classDoc, 'methods'),
+ 'property_index' => $this->_generateIndex($classDoc, 'properties'),
);
$this->set($new);
return $this->save();
@@ -90,32 +91,23 @@ class ApiClass extends ApiGeneratorAppModel {
public function getClassIndex() {
return $this->find('list', array('fields' => array('slug', 'name'), 'order' => 'ApiClass.name ASC'));
}
-
/**
- * Generate a search index from all the properties and methods
- * in a ClassDocumentor Object
+ * Generate a search index of methods or properties for the ClassDocumentor Object
*
- * @return string
- **/
- protected function _generateSearchIndex($classDoc) {
- $index = '';
- $index .= $classDoc->classInfo['comment']['description'];
- foreach ((array)$classDoc->properties as $prop) {
- if ($prop['declaredInClass'] != $classDoc->classInfo['name']) {
- continue;
- }
- $index .= ' ' . $prop['comment']['description'];
- }
- foreach ((array)$classDoc->methods as $method) {
- if ($method['declaredInClass'] != $classDoc->classInfo['name']) {
+ * @param mixed $classDoc
+ * @param string $what
+ * @return void
+ * @access protected
+ */
+ protected function _generateIndex(&$classDoc, $what = 'methods') {
+ $index = array();
+ foreach ((array)$classDoc->$what as $result) {
+ if ($result['declaredInClass'] != $classDoc->classInfo['name']) {
continue;
}
- $description = str_replace("\n", ' ', $method['comment']['description']);
- $index .= ' ' . $description;
- foreach ($method['args'] as $argument) {
- $index .= ' ' . $argument['comment'];
- }
+ $index[] = $result['name'];
}
- return strtolower($index);
+ return strtolower(implode($index, ' '));
}
-}
\ No newline at end of file
+}
+?>
\ No newline at end of file
diff --git a/tests/cases/vendors/introspector.test.php b/tests/cases/vendors/introspector.test.php
index 573911c..7960fc7 100644
--- a/tests/cases/vendors/introspector.test.php
+++ b/tests/cases/vendors/introspector.test.php
@@ -127,6 +127,23 @@ EOD;
*
* This is my long description
*
+ * @return string This is a longer doc string
+ * for the return string
+ * more lines
+ * more lines.
+ */
+EOD;
+ $result = Introspector::parseDocBlock($comment);
+ $expected = 'string This is a longer doc string for the return string more lines more lines.';
+ $this->assertEqual($result['tags']['return'], $expected, 'parsing n-line tags failed %s');
+
+
+ $comment = <<<EOD
+ /**
+ * This is the title
+ *
+ * This is my long description
+ *
* @param string \$foo Foo is an input
* @param int \$bar Bar is also an input
* @param int \$baz Baz is also an input
diff --git a/vendors/css/base.css b/vendors/css/base.css
index e27ed29..c19b2d8 100644
--- a/vendors/css/base.css
+++ b/vendors/css/base.css
@@ -229,7 +229,8 @@ Documentation Page Styles
.class-info {
margin:3em 0 0;
}
-.class-info .doc-head h2 {
+.class-info .doc-head h2,
+.class-info .doc-head h3 {
font-size: 28px;
line-height: 32px;
}
@@ -244,7 +245,8 @@ Documentation Page Styles
right:10px;
top:8px;
}
-.doc-head h2 {
+.doc-head h2,
+.doc-head h3 {
color: #333348;
border-left:7px solid #fff;
margin:0;
@@ -531,9 +533,22 @@ ol.code li code {
padding: 4px 0;
}
#search-results li {
- margin: 20px 10px;
+ margin: 30px 10px;
font-size: 140%;
}
+#search-results .doc-head {
+ border: 0;
+}
+#search-results h3 {
+ font-size: 18px;
+}
+#search-results .doc-body {
+ padding-bottom: 0;
+ padding-top: 5px;
+}
+#search-results .doc-body table {
+ margin: 0;
+}
#search-results .highlight {
background: #C9E2E6;
}
diff --git a/vendors/introspector.php b/vendors/introspector.php
index 360668d..9840301 100644
--- a/vendors/introspector.php
+++ b/vendors/introspector.php
@@ -99,9 +99,16 @@ class Introspector {
if (preg_match('/@([a-z0-9_-]+)\s(.*)$/i', $tmp[$i], $parsedTag)) {
// capture continued lines. (indented with 3 spaces or 1 tab)
- if (isset($tmp[$i + 1]) && preg_match('/^(?: {1,3}|\t)([^\t]*)$/i', $tmp[$i + 1], $nextLine)) {
- $parsedTag[2] .= ' ' . trim($nextLine[1]);
- $preprocessed[$i + 1] = true;
+ $done = false;
+ $next = $i + 1;
+ while (!$done) {
+ if (isset($tmp[$next]) && preg_match('/^(?: {1,3}|\t)([^\t]*)$/i', $tmp[$next], $nextLine)) {
+ $parsedTag[2] .= ' ' . trim($nextLine[1]);
+ $preprocessed[$next] = true;
+ $next++;
+ } else {
+ $done = true;
+ }
}
if (isset($tags[$parsedTag[1]]) && !is_array($tags[$parsedTag[1]])) {
$tags[$parsedTag[1]] = (array)$tags[$parsedTag[1]];
diff --git a/vendors/shells/api_index.php b/vendors/shells/api_index.php
index e5646d4..66a3bd4 100644
--- a/vendors/shells/api_index.php
+++ b/vendors/shells/api_index.php
@@ -305,34 +305,6 @@ class ApiIndexShell extends Shell {
}
$this->hr();
- $this->out('Usually we can find the dependencies, but ');
- $this->out('sometimes we miss. If you have files that are not generating properly');
- $this->out('Input a comma separated list for multiple options');
- $this->out('to continue, just answer "n"');
- $this->hr();
-
- $dependencies = null;
- while($dependencies == null && $dependencies != 'n') {
- $class = $this->in('Class with dependancies', '', 'n');
- if ($class == 'n') {
- $dependencies = 'n';
- } else {
- $parent = null;
- while($parent == null && $parent != 'n') {
- $parent = $this->in('Enter the dependencies for ' . $class, '');
- if ($parent != 'n') {
- $dependencies = true;
- $config['dependencies'][$class] = $parent;
- }
- }
- $stop = $this->in('Add another dependency?', array('y', 'n', 'q'), 'n');
- if ($stop == 'y') {
- $dependencies = null;
- }
- }
- }
-
- $this->hr();
$this->out('Verify the config');
$this->hr();
$string = $this->ApiConfig->toString($config);
@@ -363,7 +335,6 @@ class ApiIndexShell extends Shell {
$this->out(' Clear the existing class index and regenerate it.');
$this->out(' set_routes');
$this->out(' Add routes for Api generator to your routes file.');
-
}
}
diff --git a/views/api_generator/search.ctp b/views/api_generator/search.ctp
index 1adbef6..89e3a83 100644
--- a/views/api_generator/search.ctp
+++ b/views/api_generator/search.ctp
@@ -3,28 +3,30 @@
* Api Search results
*
*/
-
$apiDoc->setClassIndex($classIndex);
-
?>
-<h1><?php __('Search Results'); ?></h1>
-<?php if (empty($results)): ?>
+<h1><?php echo sprintf(__('Search Results for "%s"', true), $this->passedArgs[0]); ?></h1>
+<?php if (empty($docs)): ?>
<p class="error"><?php __('Your search returned no results'); ?></p>
-<?php else: ?>
+<?php return;
+endif; ?>
+
<ul id="search-results">
- <?php foreach ($results as $result): ?>
- <li><h4><?php echo $apiDoc->classLink($result['ApiClass']['name']); ?></h4>
- <?php $excerpt = $text->excerpt(strip_tags($result['ApiClass']['search_index']), $this->params['url']['query']); ?>
- <p><?php echo $text->highlight($excerpt, strtolower($this->params['url']['query'])); ?></p>
+<?php foreach ($docs as $result):
+ foreach ($result['class'] as $name => $doc): ?>
+ <li class="doc-block class-info">
+ <h2><?php echo $apiDoc->classLink($doc->name, array(), array('class' => false)); ?></h2><?php
+ if ($doc->properties):
+ echo $this->element('properties', array('doc' => $doc, 'isSearch' => true));
+ endif;
+
+ if ($doc->methods):
+ echo $this->element('method_summary', array('doc' => $doc, 'isSearch' => true));
+ endif;
+?>
</li>
- <?php endforeach;?>
-</ul>
-<?php endif; ?>
-<?php
-$paginator->options(array(
- 'url' => array(
- '?' => array('query' => $this->params['url']['query'])
- )
-));
+<?php
+ endforeach;
+endforeach;
?>
-<?php echo $this->element('paging'); ?>
\ No newline at end of file
+</ul>
\ No newline at end of file
diff --git a/views/elements/class_info.ctp b/views/elements/class_info.ctp
index 00d9a63..5b994fd 100644
--- a/views/elements/class_info.ctp
+++ b/views/elements/class_info.ctp
@@ -37,7 +37,11 @@
<dl>
<?php foreach ($doc->classInfo['comment']['tags'] as $name => $value): ?>
<dt><?php echo $name; ?></dt>
- <dd><?php echo h($value); ?></dd>
+ <?php if (strtolower($name) == 'link'):
+ echo '<dd>' . $text->autoLink(h($value)) . '</dd>';
+ else:
+ echo '<dd>' . h($value) . '</dd>';
+ endif; ?>
<?php endforeach; ?>
</dl>
</div>
diff --git a/views/elements/header_search.ctp b/views/elements/header_search.ctp
index 26d010d..9253adf 100644
--- a/views/elements/header_search.ctp
+++ b/views/elements/header_search.ctp
@@ -1,21 +1,27 @@
<?php
/**
- * Header search form
+ * Header search form
*
*/
?>
<div id="header-search">
<?php echo $form->create('ApiClass', array(
'url' => array(
- 'plugin' => 'api_generator', 'controller' => 'api_generator',
+ 'plugin' => 'api_generator', 'controller' => 'api_generator',
'action' => 'search'
- ),
+ ),
'type' => 'get',
)); ?>
<fieldset id="search-bar">
- <?php
+<?php
+ if ($this->action === 'search' && !empty($this->passedArgs[0])) {
+ $value = $this->passedArgs[0];
+ } else {
+ $value = '';
+ }
echo $form->text('Search.query', array(
- 'class' => 'query'
+ 'class' => 'query',
+ 'value' => $value
)); ?>
<?php echo $form->submit(__('Search', true), array('div' => false, 'class' => 'submit')); ?>
</fieldset>
diff --git a/views/elements/method_detail.ctp b/views/elements/method_detail.ctp
index 7e3216c..da16170 100644
--- a/views/elements/method_detail.ctp
+++ b/views/elements/method_detail.ctp
@@ -62,7 +62,11 @@
<dt>
<?php foreach ($method['comment']['tags'] as $name => $value): ?>
<dt><?php echo $name; ?></dt>
- <dd><?php echo h($value); ?></dd>
+ <?php if (strtolower($name) == 'link'):
+ echo '<dd>' . $text->autoLink(h($value)) . '</dd>';
+ else:
+ echo '<dd>' . h($value) . '</dd>';
+ endif; ?>
<?php endforeach; ?>
</dt>
</div>
diff --git a/views/elements/method_summary.ctp b/views/elements/method_summary.ctp
index 3ec269e..ed75afd 100644
--- a/views/elements/method_summary.ctp
+++ b/views/elements/method_summary.ctp
@@ -4,19 +4,23 @@
*
*/
-$apiUtils->sortByName($doc->methods); ?>
+$apiUtils->sortByName($doc->methods);
+$title = (empty($isSearch)) ? __('Method Summary:', true) : __('Methods:', true);
+?>
<div class="doc-block">
<a id="top-<?php echo $doc->name; ?>"></a>
- <div class="doc-head"><h2><?php __('Method Summary:'); ?></h2></div>
+ <div class="doc-head"><h3><?php echo $title; ?></h3></div>
<div class="doc-body">
+<?php if (empty($isSearch)): ?>
<span class="doc-controls">
<a href="#" id="hide-parent-methods"><?php __('Show/Hide parent methods'); ?></a>
</span>
+<?php endif; ?>
<table class="summary">
<tbody>
<?php $i = 0; ?>
<?php foreach ($doc->methods as $method): ?>
- <?php
+ <?php
if ($apiDoc->excluded($method['access'], 'method')) :
continue;
endif;
@@ -26,10 +30,18 @@ $apiUtils->sortByName($doc->methods); ?>
<td class="access <?php echo $method['access']; ?>"><span><?php echo $method['access']; ?></span></td>
<td>
<?php
- echo $html->link($method['signature'],
- '#method-' . $doc->name . $method['name'],
- array('class' => 'scroll-link')
- );
+ if (empty($isSearch)):
+ echo $html->link($method['signature'],
+ '#method-' . $doc->name . $method['name'],
+ array('class' => 'scroll-link')
+ );
+ else:
+ echo $html->link($method['signature'],
+ array('action' => 'view_class', $apiDoc->slugClassName($doc->name),
+ '#' => 'method-' . $doc->name . $method['name']),
+ array('class' => 'scroll-link')
+ );
+ endif;
?>
</td>
</tr>
diff --git a/views/elements/properties.ctp b/views/elements/properties.ctp
index 1b0825e..9aaf1ab 100644
--- a/views/elements/properties.ctp
+++ b/views/elements/properties.ctp
@@ -3,19 +3,21 @@
* Properties Element
*
*/
-
-$apiUtils->sortByName($doc->properties); ?>
+$apiUtils->sortByName($doc->properties);
+?>
<div class="doc-block">
- <div class="doc-head"><h2><?php __('Properties:'); ?></h2></div>
+ <div class="doc-head"><h3><?php __('Properties:'); ?></h3></div>
<div class="doc-body">
<?php if (!empty($doc->properties)): ?>
+<?php if (empty($isSearch)): ?>
<span class="doc-controls">
<a href="#" id="hide-parent-properties"><?php __('Show/Hide parent properties'); ?></a>
</span>
+<?php endif; ?>
<table>
<?php $i = 0; ?>
<?php foreach ($doc->properties as $prop): ?>
- <?php
+ <?php
if ($apiDoc->excluded($prop['access'], 'property')) :
continue;
endif;
