New documentation tool.
This commit is contained in:
parent
813886a086
commit
5f0198a407
5
manual/new/.htaccess
Normal file
5
manual/new/.htaccess
Normal file
@ -0,0 +1,5 @@
|
||||
# RewriteEngine on
|
||||
|
||||
# RewriteRule ^chapter/(.*)/(.*)$ index.php [r=404]
|
||||
# RewriteRule ^chapter/(.*)$ index.php?chapter=$1
|
||||
# RewriteRule ^one-page$ index.php?one-page=1
|
257
manual/new/DocTool.php
Normal file
257
manual/new/DocTool.php
Normal file
@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
require_once("highlight.php");
|
||||
require_once('Text/Wiki.php');
|
||||
|
||||
class DocTool
|
||||
{
|
||||
private $_wiki;
|
||||
private $_toc;
|
||||
private $_options = array('max-level' => 1,
|
||||
'lang' => 'en',
|
||||
'default-lang' => 'en',
|
||||
'one-page' => false,
|
||||
'section' => null,
|
||||
'clean-url' => false,
|
||||
'base-url' => '');
|
||||
private $_lang = array();
|
||||
|
||||
public function __construct($filename)
|
||||
{
|
||||
$this->_wiki = new Text_Wiki();
|
||||
$this->_wiki->disableRule('Wikilink');
|
||||
$this->_toc = new Sensei_Doc_Toc($filename);
|
||||
}
|
||||
|
||||
public function getOption($option)
|
||||
{
|
||||
return $this->_options[$option];
|
||||
}
|
||||
|
||||
public function setOption($option, $value)
|
||||
{
|
||||
switch ($option) {
|
||||
case 'max-level':
|
||||
if (!is_int($value)) {
|
||||
throw new Exception('Value must be an integer.');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'one-page':
|
||||
case 'clean-url':
|
||||
if (!is_bool($value)) {
|
||||
throw new Exception('Value must be a boolean.');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'locale':
|
||||
case 'base-url':
|
||||
if (!is_string($value)) {
|
||||
throw new Exception('Value must be a string.');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'section':
|
||||
if (! $value instanceof Sensei_Doc_Section) {
|
||||
throw new Exception('Value must be an instance of Sensei_Doc_Section.');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown option.');
|
||||
}
|
||||
|
||||
$this->_options[$option] = $value;
|
||||
}
|
||||
|
||||
public function addLanguage(array $translations, $lang)
|
||||
{
|
||||
$this->_lang[$lang] = $translations;
|
||||
}
|
||||
|
||||
public function translate($string)
|
||||
{
|
||||
$language = $this->getOption('lang');
|
||||
|
||||
if (array_key_exists($language, $this->_lang)
|
||||
&& array_key_exists($string, $this->_lang[language])) {
|
||||
return $this->_lang[$language][$string];
|
||||
} else {
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
public function renderToc($toc = null)
|
||||
{
|
||||
if (!$toc) {
|
||||
$toc = $this->_toc;
|
||||
}
|
||||
|
||||
$classes = array();
|
||||
|
||||
if ($toc instanceof Sensei_Doc_Toc) {
|
||||
|
||||
$class = '';
|
||||
if ($this->getOption('one-page')) {
|
||||
$class = ' class="one-page"';
|
||||
}
|
||||
|
||||
echo '<div' . $class . ' id="table-of-contents">' . "\n";
|
||||
echo '<h1>Table of Contents</h1>' . "\n";
|
||||
|
||||
$classes[] = 'tree';
|
||||
|
||||
} else {
|
||||
|
||||
$isParent = false;
|
||||
$section = $this->getOption('section');
|
||||
|
||||
if ($section !== null) {
|
||||
$current = $section;
|
||||
do {
|
||||
if ($current === $toc) {
|
||||
$isParent = true;
|
||||
break;
|
||||
}
|
||||
} while (($current = $current->getParent()) !== null);
|
||||
}
|
||||
|
||||
if (! $isParent) {
|
||||
$classes[] = 'closed';
|
||||
}
|
||||
}
|
||||
|
||||
$classes = implode(' ', $classes);
|
||||
|
||||
if ($classes === '') {
|
||||
echo "<ul>\n";
|
||||
} else {
|
||||
echo "<ul class=\"$classes\">\n";
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $toc->count(); $i++) {
|
||||
$child = $toc->getChild($i);
|
||||
|
||||
if ($child === $this->getOption('section')) {
|
||||
echo '<li class="current">';
|
||||
} else {
|
||||
echo '<li>';
|
||||
}
|
||||
|
||||
echo '<a href="' . $this->makeUrl($child->getPath()) . '">';
|
||||
echo $child->getIndex() . ' ' . $child->getName() . '</a>';
|
||||
|
||||
if ($child->count() > 0) {
|
||||
echo "\n";
|
||||
$this->renderToc($child);
|
||||
}
|
||||
|
||||
echo '</li>' . "\n";
|
||||
}
|
||||
|
||||
echo '</ul>' . "\n";
|
||||
|
||||
if ($toc instanceof Sensei_Doc_Toc) {
|
||||
echo '</div>' . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public function makeUrl($path)
|
||||
{
|
||||
$prefix = $this->getOption('base-url');
|
||||
|
||||
if (!$this->getOption('one-page')) {
|
||||
if ($this->getOption('clean-url')) {
|
||||
$prefix .= 'chapter/';
|
||||
} else {
|
||||
$prefix .= '?chapter=';
|
||||
}
|
||||
}
|
||||
|
||||
$parts = explode(':', $path);
|
||||
$firstPath = array_slice($parts, 0, $this->getOption('max-level'));
|
||||
|
||||
$href = $prefix . implode(':', $firstPath);
|
||||
|
||||
$anchorName = $this->makeAnchor($path);
|
||||
if (!empty($anchorName)) {
|
||||
$href .= '#' . $anchorName;
|
||||
}
|
||||
|
||||
return $href;
|
||||
}
|
||||
|
||||
public function makeAnchor($path)
|
||||
{
|
||||
$pathParts = explode(':', $path);
|
||||
$anchorParts = array_slice($pathParts, $this->getOption('max-level'));
|
||||
$anchorName = implode(':', $anchorParts);
|
||||
return $anchorName;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
if ($this->getOption('one-page')) {
|
||||
|
||||
for ($i = 0; $i < count($this->_toc); $i++) {
|
||||
$this->renderSection($this->_toc->getChild($i));
|
||||
}
|
||||
|
||||
} else {
|
||||
$section = $this->getOption('section');
|
||||
|
||||
if (!$section) {
|
||||
throw new Exception('Section has not been set.');
|
||||
} else {
|
||||
$this->renderSection($section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function renderSection($section)
|
||||
{
|
||||
$level = $section->getLevel();
|
||||
$name = $section->getName();
|
||||
$index = $section->getIndex();
|
||||
|
||||
if ($section->getLevel() == 1) {
|
||||
echo '<div class="chapter">' . "\n";
|
||||
echo "<h$level>Chapter $index ";
|
||||
} else {
|
||||
echo '<div class="section">' . "\n";
|
||||
echo "<h$level>$index ";
|
||||
}
|
||||
|
||||
if ($section->getLevel() > $this->getOption('max-level')) {
|
||||
echo '<a id="' . $this->makeAnchor($section->getPath()) . '">';
|
||||
echo $name;
|
||||
echo '</a>';
|
||||
} else {
|
||||
echo $name;
|
||||
}
|
||||
|
||||
echo "</h$level>\n";
|
||||
|
||||
if ($level === 1 && !$this->getOption('one-page')) {
|
||||
//$this->renderToc($this->_toc);
|
||||
}
|
||||
|
||||
echo $this->_wiki->transform($section->getText());
|
||||
|
||||
for ($i = 0; $i < count($section); $i++) {
|
||||
$this->renderSection($section->getChild($i));
|
||||
}
|
||||
|
||||
echo '</div>' . "\n";
|
||||
}
|
||||
|
||||
public function findByPath($path)
|
||||
{
|
||||
return $this->_toc->findByPath($path);
|
||||
}
|
||||
|
||||
public function findByIndex($index)
|
||||
{
|
||||
return $this->_toc->findByIndex($index);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
Doctrine allows you to bind connections to components (= your ActiveRecord classes). This means everytime a component issues a query or data is being fetched from the table the component is pointing at Doctrine will use the bound connection.
|
||||
|
||||
<code type="php">
|
||||
$conn = $manager->openConnection(new PDO('dsn','username','password'), 'connection 1');
|
||||
|
||||
$conn2 = $manager->openConnection(new PDO('dsn2','username2','password2'), 'connection 2');
|
||||
|
||||
$manager->bindComponent('User', 'connection 1');
|
||||
|
||||
$manager->bindComponent('Group', 'connection 2');
|
||||
|
||||
$q = new Doctrine_Query();
|
||||
|
||||
// Doctrine uses 'connection 1' for fetching here
|
||||
$users = $q->from('User u')->where('u.id IN (1,2,3)')->execute();
|
||||
|
||||
// Doctrine uses 'connection 2' for fetching here
|
||||
$groups = $q->from('Group g')->where('g.id IN (1,2,3)')->execute();
|
||||
</code>
|
||||
|
@ -0,0 +1,106 @@
|
||||
In order to connect to a database through Doctrine, you have to create a valid DSN - data source name.
|
||||
|
||||
Doctrine supports both PEAR DB/MDB2 like data source names as well as PDO style data source names. The following section deals with PEAR like data source names. If you need more info about the PDO-style data source names see http://www.php.net/manual/en/function.PDO-construct.php.
|
||||
|
||||
The DSN consists in the following parts:
|
||||
|
||||
**phptype**: Database backend used in PHP (i.e. mysql , pgsql etc.)
|
||||
**dbsyntax**: Database used with regards to SQL syntax etc.
|
||||
**protocol**: Communication protocol to use ( i.e. tcp, unix etc.)
|
||||
**hostspec**: Host specification (hostname[:port])
|
||||
**database**: Database to use on the DBMS server
|
||||
**username**: User name for login
|
||||
**password**: Password for login
|
||||
**proto_opts**: Maybe used with protocol
|
||||
**option**: Additional connection options in URI query string format. options get separated by &. The Following table shows a non complete list of options:
|
||||
|
||||
|
||||
**List of options**
|
||||
|
||||
||~ Name ||~ Description ||
|
||||
|| charset || Some backends support setting the client charset.||
|
||||
|| new_link || Some RDBMS do not create new connections when connecting to the same host multiple times. This option will attempt to force a new connection. ||
|
||||
|
||||
The DSN can either be provided as an associative array or as a string. The string format of the supplied DSN is in its fullest form:
|
||||
`` phptype(dbsyntax)://username:password@protocol+hostspec/database?option=value ``
|
||||
|
||||
|
||||
|
||||
Most variations are allowed:
|
||||
|
||||
|
||||
phptype://username:password@protocol+hostspec:110//usr/db_file.db
|
||||
phptype://username:password@hostspec/database
|
||||
phptype://username:password@hostspec
|
||||
phptype://username@hostspec
|
||||
phptype://hostspec/database
|
||||
phptype://hostspec
|
||||
phptype:///database
|
||||
phptype:///database?option=value&anotheroption=anothervalue
|
||||
phptype(dbsyntax)
|
||||
phptype
|
||||
|
||||
|
||||
|
||||
The currently supported database backends are:
|
||||
||//fbsql//|| -> FrontBase ||
|
||||
||//ibase//|| -> InterBase / Firebird (requires PHP 5) ||
|
||||
||//mssql//|| -> Microsoft SQL Server (NOT for Sybase. Compile PHP --with-mssql) ||
|
||||
||//mysql//|| -> MySQL ||
|
||||
||//mysqli//|| -> MySQL (supports new authentication protocol) (requires PHP 5) ||
|
||||
||//oci8 //|| -> Oracle 7/8/9/10 ||
|
||||
||//pgsql//|| -> PostgreSQL ||
|
||||
||//querysim//|| -> QuerySim ||
|
||||
||//sqlite//|| -> SQLite 2 ||
|
||||
|
||||
|
||||
|
||||
A second DSN format is supported phptype(syntax)://user:pass@protocol(proto_opts)/database
|
||||
|
||||
|
||||
|
||||
If your database, option values, username or password contain characters used to delineate DSN parts, you can escape them via URI hex encodings:
|
||||
``: = %3a``
|
||||
``/ = %2f``
|
||||
``@ = %40``
|
||||
``+ = %2b``
|
||||
``( = %28``
|
||||
``) = %29``
|
||||
``? = %3f``
|
||||
``= = %3d``
|
||||
``& = %26``
|
||||
|
||||
|
||||
|
||||
|
||||
Warning
|
||||
Please note, that some features may be not supported by all database backends.
|
||||
|
||||
|
||||
Example
|
||||
**Example 1.** Connect to database through a socket
|
||||
|
||||
mysql://user@unix(/path/to/socket)/pear
|
||||
|
||||
|
||||
**Example 2.** Connect to database on a non standard port
|
||||
|
||||
pgsql://user:pass@tcp(localhost:5555)/pear
|
||||
|
||||
|
||||
**Example 3.** Connect to SQLite on a Unix machine using options
|
||||
|
||||
sqlite:////full/unix/path/to/file.db?mode=0666
|
||||
|
||||
|
||||
**Example 4.** Connect to SQLite on a Windows machine using options
|
||||
|
||||
sqlite:///c:/full/windows/path/to/file.db?mode=0666
|
||||
|
||||
|
||||
**Example 5.** Connect to MySQLi using SSL
|
||||
|
||||
mysqli://user:pass@localhost/pear?key=client-key.pem&cert=client-cert.pem
|
||||
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
Lazy-connecting to database is handled via Doctrine_Db wrapper. When using Doctrine_Db instead of PDO / Doctrine_Adapter, lazy-connecting to database is being performed (that means Doctrine will only connect to database when needed).
|
||||
|
||||
This feature can be very useful when using for example page caching, hence not actually needing a database connection on every request. Remember connecting to database is an expensive operation.
|
||||
|
||||
<code type="php">
|
||||
// we may use PDO / PEAR like DSN
|
||||
// here we use PEAR like DSN
|
||||
$dbh = new Doctrine_Db('mysql://username:password@localhost/test');
|
||||
// !! no actual database connection yet !!
|
||||
|
||||
// initalize a new Doctrine_Connection
|
||||
$conn = Doctrine_Manager::connection($dbh);
|
||||
// !! no actual database connection yet !!
|
||||
|
||||
// connects database and performs a query
|
||||
$conn->query('FROM User u');
|
||||
</code>
|
@ -0,0 +1,54 @@
|
||||
From the start Doctrine has been designed to work with multiple connections. Unless separately specified Doctrine always uses the current connection for executing the queries. The following example uses {{openConnection()}} second argument as an optional connection alias.
|
||||
|
||||
<code type="php">
|
||||
// Doctrine_Manager controls all the connections
|
||||
|
||||
$manager = Doctrine_Manager::getInstance();
|
||||
|
||||
// open first connection
|
||||
|
||||
$conn = $manager->openConnection(new PDO('dsn','username','password'), 'connection 1');
|
||||
</code>
|
||||
|
||||
For convenience {{Doctrine_Manager}} provides static method {{connection()}} which opens new connection when arguments are given to it and returns the current connection when no arguments have been speficied.
|
||||
|
||||
<code type="php">
|
||||
// open first connection
|
||||
|
||||
$conn = Doctrine_Manager::connection(new PDO('dsn','username','password'), 'connection 1');
|
||||
|
||||
$conn2 = Doctrine_Manager::connection();
|
||||
|
||||
// $conn2 == $conn
|
||||
</code>
|
||||
|
||||
The current connection is the lastly opened connection.
|
||||
|
||||
<code type="php">
|
||||
// open second connection
|
||||
|
||||
$conn2 = $manager->openConnection(new PDO('dsn2','username2','password2'), 'connection 2');
|
||||
|
||||
$manager->getCurrentConnection(); // $conn2
|
||||
</code>
|
||||
|
||||
You can change the current connection by calling {{setCurrentConnection()}}.
|
||||
|
||||
<code type="php">
|
||||
$manager->setCurrentConnection('connection 1');
|
||||
|
||||
$manager->getCurrentConnection(); // $conn
|
||||
</code>
|
||||
|
||||
You can iterate over the opened connection by simple passing the manager object to foreach clause. This is possible since {{Doctrine_Manager}} implements special {{IteratorAggregate}} interface.
|
||||
|
||||
|
||||
|
||||
<code type="php">
|
||||
// iterating through connections
|
||||
|
||||
foreach($manager as $conn) {
|
||||
|
||||
}
|
||||
</code>
|
||||
|
@ -0,0 +1,44 @@
|
||||
|
||||
Opening a new database connection in Doctrine is very easy. If you wish to use PDO (www.php.net/PDO) you can just initalize a new PDO object:
|
||||
|
||||
|
||||
|
||||
<code type="php">
|
||||
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
|
||||
$user = 'dbuser';
|
||||
$password = 'dbpass';
|
||||
|
||||
try {
|
||||
$dbh = new PDO($dsn, $user, $password);
|
||||
} catch (PDOException $e) {
|
||||
echo 'Connection failed: ' . $e->getMessage();
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
|
||||
If your database extension isn't supported by PDO you can use special Doctrine_Adapter class (if availible). The following example uses db2 adapter:
|
||||
|
||||
|
||||
|
||||
<code type="php">
|
||||
$dsn = 'db2:dbname=testdb;host=127.0.0.1';
|
||||
$user = 'dbuser';
|
||||
$password = 'dbpass';
|
||||
|
||||
try {
|
||||
$dbh = Doctrine_Adapter::connect($dsn, $user, $password);
|
||||
} catch (PDOException $e) {
|
||||
echo 'Connection failed: ' . $e->getMessage();
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
|
||||
The next step is opening a new Doctrine_Connection.
|
||||
|
||||
|
||||
|
||||
<code type="php">
|
||||
$conn = Doctrine_Manager::connection($dbh);
|
||||
</code>
|
11
manual/new/docs/en/getting-started/compiling.txt
Normal file
11
manual/new/docs/en/getting-started/compiling.txt
Normal file
@ -0,0 +1,11 @@
|
||||
Doctrine is quite big framework and usually dozens of files are being included on each request. This brings a lot of overhead. In fact these file operations are as time consuming as sending multiple queries to database server. The clean separation of class per file works well in developing environment, however when project goes commercial distribution the speed overcomes the clean separation of class per file -convention.
|
||||
|
||||
Doctrine offers method called compile() to solve this issue. The compile method makes a single file of most used Doctrine components which can then be included on top of your script. By default the file is created into Doctrine root by the name Doctrine.compiled.php.
|
||||
|
||||
Compiling is a method for making a single file of most used doctrine runtime components including the compiled file instead of multiple files (in worst cases dozens of files) can improve performance by an order of magnitude. In cases where this might fail, a Doctrine_Exception is throw detailing the error.
|
||||
|
||||
<code type='php'>
|
||||
Doctrine::compile();
|
||||
// on some other script:
|
||||
require_once('path_to_doctrine/Doctrine.compiled.php');
|
||||
</code>
|
18
manual/new/docs/en/getting-started/exporting-classes.txt
Normal file
18
manual/new/docs/en/getting-started/exporting-classes.txt
Normal file
@ -0,0 +1,18 @@
|
||||
+++ Introduction
|
||||
|
||||
+++ Export options
|
||||
|
||||
<code type='php'>
|
||||
// export everything, table definitions and constraints
|
||||
|
||||
$manager->setAttribute(Doctrine::ATTR_EXPORT, Doctrine::EXPORT_ALL);
|
||||
|
||||
// export classes without constraints
|
||||
|
||||
$manager->setAttribute(Doctrine::ATTR_EXPORT, Doctrine::EXPORT_TABLES ^
|
||||
Doctrine::EXPORT_CONSTRAINTS);
|
||||
|
||||
// turn off exporting
|
||||
|
||||
$manager->setAttribute(Doctrine::ATTR_EXPORT, Doctrine::EXPORT_NONE);
|
||||
</code>
|
38
manual/new/docs/en/getting-started/installation.txt
Normal file
38
manual/new/docs/en/getting-started/installation.txt
Normal file
@ -0,0 +1,38 @@
|
||||
The installation of doctrine is very easy. Just get the latest revision of Doctrine from http://doctrine.pengus.net/svn/trunk.
|
||||
|
||||
You need a SVN(Subversion) client for downloading Doctrine.
|
||||
|
||||
In order to check out Doctrine in the current directory using the **svn** command line tool use the following code:
|
||||
<code type="bash">
|
||||
svn co http://doctrine.pengus.net/svn/trunk .
|
||||
</code>
|
||||
|
||||
If you do not have a SVN client, chose one from the list below. Find the **Checkout** option and enter http://doctrine.pengus.net/svn/trunk in the **path** or **repository url** parameter. There is no need for a username or password to check out Doctrine.
|
||||
|
||||
* [http://tortoisesvn.tigris.org/ TortoiseSVN] a Windows application that integrates into Windows Explorer
|
||||
* [http://www.apple.com/downloads/macosx/development_tools/svnx.html svnx] a Mac OS X GUI svn application
|
||||
* Eclipse has SVN integration through the [http://subclipse.tigris.org/ subeclipse] plugin
|
||||
|
||||
+++ Include and autoload
|
||||
|
||||
In order to use Doctrine in your project it must first be included.
|
||||
|
||||
<code type='php'>
|
||||
require_once('path-to-doctrine/lib/Doctrine.php');
|
||||
</code>
|
||||
|
||||
Doctrine support [http://www.php.net/autoload Autoloading] for including files so that you do not have to include anything more then the base file. There are two different strategies that can be used to do this:
|
||||
|
||||
If you do use the **__autoload** function for your own logic you can use it.
|
||||
|
||||
<code type='php'>
|
||||
function __autoload($class) {
|
||||
Doctrine::autoload($class);
|
||||
}
|
||||
</code>
|
||||
|
||||
If your project uses autoload and/or you have other libraries that use it you could use [http://www.php.net/manual/en/function.spl-autoload-register.php spl_autoload_register] to register more then one autoloading function.
|
||||
|
||||
<code type="php">
|
||||
spl_autoload_register(array('Doctrine', 'autoload'));
|
||||
</code>
|
2
manual/new/docs/en/getting-started/requirements.txt
Normal file
2
manual/new/docs/en/getting-started/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Doctrine requires PHP >= 5.1. it doesn't require any external libraries. For database abstraction Doctrine uses PDO which is bundled with php by default. Doctrine also requires a little adodb-hack for table creation, which comes with doctrine.
|
||||
|
27
manual/new/docs/en/getting-started/starting-new-project.txt
Normal file
27
manual/new/docs/en/getting-started/starting-new-project.txt
Normal file
@ -0,0 +1,27 @@
|
||||
Doctrine_Record is the basic component of every doctrine-based project. There should be atleast one Doctrine_Record for each of your database tables. Doctrine_Record follows the [http://www.martinfowler.com/eaaCatalog/activeRecord.html Active Record pattern]
|
||||
|
||||
Doctrine auto-creates database tables and always adds a primary key column named 'id' to tables that doesn't have any primary keys specified. Only thing you need to for creating database tables is defining a class which extends Doctrine_Record and setting a setTableDefinition method with hasColumn() method calls.
|
||||
|
||||
An short example:
|
||||
|
||||
We want to create a database table called 'user' with columns id(primary key), name, username, password and created. Provided that you have already installed Doctrine these few lines of code are all you need:
|
||||
|
||||
<code type='php'>
|
||||
require_once('lib/Doctrine.php');
|
||||
|
||||
spl_autoload_register(array('Doctrine', 'autoload'));
|
||||
|
||||
class User extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
// set 'user' table columns, note that
|
||||
// id column is always auto-created
|
||||
|
||||
$this->hasColumn('name','string',30);
|
||||
$this->hasColumn('username','string',20);
|
||||
$this->hasColumn('password','string',16);
|
||||
$this->hasColumn('created','integer',11);
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
We now have a user model that supports basic CRUD opperations!
|
@ -0,0 +1,69 @@
|
||||
+++ Introduction
|
||||
|
||||
A common case when looking for ORM tools like Doctrine is that the database and the code that access it is growing large/complex. A more substantial tool is needed then manual SQL code.
|
||||
|
||||
Doctrine has support for generating Doctrine_Record classes from your existing database. There is no need for you to manually write all the Doctrine_Record classes for your domain model.
|
||||
|
||||
+++ Making the first import
|
||||
|
||||
Let's consider we have a mysql database called test with a single table called 'file'.
|
||||
|
||||
The file table has been created with the following sql statement:
|
||||
|
||||
<code type="sql">
|
||||
CREATE TABLE file (
|
||||
id INT UNSIGNED AUTO_INCREMENT NOT NULL,
|
||||
name VARCHAR(150),
|
||||
size BIGINT,
|
||||
modified BIGINT,
|
||||
type VARCHAR(10),
|
||||
content TEXT,
|
||||
path TEXT,
|
||||
PRIMARY KEY(id))
|
||||
</code>
|
||||
|
||||
Now we would like to convert it into Doctrine record class. It can be achieved easily with the following code snippet:
|
||||
|
||||
<code type='php'>
|
||||
require_once('lib/Doctrine.php');
|
||||
|
||||
spl_autoload_register(array('Doctrine', 'autoload'));
|
||||
|
||||
$conn = Doctrine_Manager::connection(new Doctrine_Db('mysql://root:dc34@localhost/test'));
|
||||
|
||||
// import method takes one parameter: the import directory (the directory where
|
||||
// the generated record files will be put in
|
||||
$conn->import->import('myrecords');
|
||||
</code>
|
||||
|
||||
That's it! Now there should be a file called File.php in your myrecords directory. The file should look like:
|
||||
|
||||
<code type='php'>
|
||||
/**
|
||||
* This class has been auto-generated by the Doctrine ORM Framework
|
||||
* Created: Saturday 10th of February 2007 01:03:15 PM
|
||||
*/
|
||||
class File extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('id', 'integer', 4, array('notnull' => true,
|
||||
'primary' => true,
|
||||
'unsigned' > true,
|
||||
'autoincrement' => true));
|
||||
$this->hasColumn('name', 'string', 150);
|
||||
$this->hasColumn('size', 'integer', 8);
|
||||
$this->hasColumn('modified', 'integer', 8);
|
||||
$this->hasColumn('type', 'string', 10);
|
||||
$this->hasColumn('content', 'string', null);
|
||||
$this->hasColumn('path', 'string', null);
|
||||
}
|
||||
public function setUp()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
+++ Import options
|
||||
|
5
manual/new/docs/en/object-relational-mapping/columns.txt
Normal file
5
manual/new/docs/en/object-relational-mapping/columns.txt
Normal file
@ -0,0 +1,5 @@
|
||||
+++ Column naming
|
||||
+++ Column aliases
|
||||
+++ Default values
|
||||
+++ Data types
|
||||
+++ About type conversion
|
@ -0,0 +1,15 @@
|
||||
Doctrine offers a way of setting column aliases. This can be very useful when you want to keep the application logic separate from the
|
||||
database logic. For example if you want to change the name of the database field all you need to change at your application is the column definition.
|
||||
|
||||
<code type="php">
|
||||
class Book extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('bookName as name', 'string');
|
||||
}
|
||||
}
|
||||
$book = new Book();
|
||||
$book->name = 'Some book';
|
||||
$book->save();
|
||||
</code>
|
@ -0,0 +1,8 @@
|
||||
One problem with database compatibility is that many databases differ in their behaviour of how the result set of a query is returned. MySQL leaves the field names unchanged, which means if you issue a query of the form "SELECT myField FROM ..." then the result set will contain the field 'myField'.
|
||||
|
||||
Unfortunately, this is just the way MySql and some other databases do it. Postgres for example returns all field names in lowercase whilst Oracle returns all field names in uppercase. "So what? In what way does this influence me when using Doctrine?", you may ask. Fortunately, you don't have to bother about that issue at all.
|
||||
|
||||
Doctrine takes care of this problem transparently. That means if you define a derived Record class and define a field called 'myField' you will always access it through $record->myField (or $record['myField'], whatever you prefer) no matter whether you're using MySQL or Postgres or Oracle etc.
|
||||
|
||||
In short: You can name your fields however you want, using under_scores, camelCase or whatever you prefer.
|
||||
|
@ -0,0 +1,261 @@
|
||||
++++ Introduction
|
||||
|
||||
All DBMS provide multiple choice of data types for the information that can be stored in their database table fields. However, the set of data types made available varies from DBMS to DBMS.
|
||||
|
||||
To simplify the interface with the DBMS supported by Doctrine, it was defined a base set of data types that applications may access independently of the underlying DBMS.
|
||||
|
||||
The Doctrine applications programming interface takes care of mapping data types when managing database options. It is also able to convert that is sent to and received from the underlying DBMS using the respective driver.
|
||||
|
||||
The following data type examples should be used with Doctrine's createTable() method. The example array at the end of the data types section may be used with createTable() to create a portable table on the DBMS of choice (please refer to the main Doctrine documentation to find out what DBMS back ends are properly supported). It should also be noted that the following examples do not cover the creation and maintenance of indices, this chapter is only concerned with data types and the proper usage thereof.
|
||||
|
||||
It should be noted that the length of the column affects in database level type as well as application level validated length (the length that is validated with Doctrine validators).
|
||||
|
||||
Example 1. Column named 'content' with type 'string' and length 3000 results in database type 'TEXT' of which has database level length of 4000. However when the record is validated it is only allowed to have 'content' -column with maximum length of 3000.
|
||||
|
||||
Example 2. Column with type 'integer' and length 1 results in 'TINYINT' on many databases.
|
||||
|
||||
In general Doctrine is smart enough to know which integer/string type to use depending on the specified length.
|
||||
|
||||
|
||||
++++ Type modifiers
|
||||
|
||||
Within the Doctrine API there are a few modifiers that have been designed to aid in optimal table design. These are:
|
||||
|
||||
* The notnull modifiers
|
||||
* The length modifiers
|
||||
* The default modifiers
|
||||
* unsigned modifiers for some field definitions, although not all DBMS's support this modifier for integer field types.
|
||||
* zerofill modifiers (not supported by all drivers)
|
||||
* collation modifiers (not supported by all drivers)
|
||||
* fixed length modifiers for some field definitions.
|
||||
|
||||
Building upon the above, we can say that the modifiers alter the field definition to create more specific field types for specific usage scenarios. The notnull modifier will be used in the following way to set the default DBMS NOT NULL Flag on the field to true or false, depending on the DBMS's definition of the field value: In PostgreSQL the "NOT NULL" definition will be set to "NOT NULL", whilst in MySQL (for example) the "NULL" option will be set to "NO". In order to define a "NOT NULL" field type, we simply add an extra parameter to our definition array (See the examples in the following section)
|
||||
|
||||
<?php
|
||||
'sometime' = array(
|
||||
'type' = 'time',
|
||||
'default' = '12:34:05',
|
||||
'notnull' = true,
|
||||
),
|
||||
?>
|
||||
|
||||
Using the above example, we can also explore the default field operator. Default is set in the same way as the notnull operator to set a default value for the field. This value may be set in any character set that the DBMS supports for text fields, and any other valid data for the field's data type. In the above example, we have specified a valid time for the "Time" data type, '12:34:05'. Remember that when setting default dates and times, as well as datetimes, you should research and stay within the epoch of your chosen DBMS, otherwise you will encounter difficult to diagnose errors!
|
||||
|
||||
<?php
|
||||
'sometext' = array(
|
||||
'type' = 'text',
|
||||
'length' = 12,
|
||||
),
|
||||
?>
|
||||
|
||||
The above example will create a character varying field of length 12 characters in the database table. If the length definition is left out, Doctrine will create a length of the maximum allowable length for the data type specified, which may create a problem with some field types and indexing. Best practice is to define lengths for all or most of your fields.
|
||||
|
||||
|
||||
++++ Boolean
|
||||
|
||||
The boolean data type represents only two values that can be either 1 or 0.
|
||||
Do not assume that these data types are stored as integers because some DBMS drivers may implement this
|
||||
type with single character text fields for a matter of efficiency.
|
||||
Ternary logic is possible by using null as the third possible value that may be assigned to fields of this type.
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('booltest', 'boolean');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Integer
|
||||
|
||||
The integer type is the same as integer type in PHP. It may store integer values as large as each DBMS may handle.
|
||||
|
||||
Fields of this type may be created optionally as unsigned integers but not all DBMS support it.
|
||||
Therefore, such option may be ignored. Truly portable applications should not rely on the availability of this option.
|
||||
|
||||
The integer type maps to different database type depending on the column length.
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('integertest', 'integer', 4, array('unsigned' => true));
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Float
|
||||
|
||||
The float data type may store floating point decimal numbers. This data type is suitable for representing numbers within a large scale range that do not require high accuracy. The scale and the precision limits of the values that may be stored in a database depends on the DBMS that it is used.
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('floattest', 'float');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ String
|
||||
|
||||
The text data type is available with two options for the length: one that is explicitly length limited and another of undefined length that should be as large as the database allows.
|
||||
|
||||
The length limited option is the most recommended for efficiency reasons. The undefined length option allows very large fields but may prevent the use of indexes, nullability and may not allow sorting on fields of its type.
|
||||
|
||||
The fields of this type should be able to handle 8 bit characters. Drivers take care of DBMS specific escaping of characters of special meaning with the values of the strings to be converted to this type.
|
||||
|
||||
By default Doctrine will use variable length character types. If fixed length types should be used can be controlled via the fixed modifier.
|
||||
|
||||
<code type='php'>
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('stringtest', 'string', 200, array('fixed' => true));
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Array
|
||||
|
||||
This is the same as 'array' type in PHP.
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('arraytest', 'array', 10000);
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Object
|
||||
|
||||
Doctrine supports objects as column types. Basically you can set an object to a field and Doctrine handles automatically the serialization / unserialization of that object.
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('objecttest', 'object');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Blob
|
||||
|
||||
Blob (Binary Large OBject) data type is meant to store data of undefined length that may be too large to store in text fields, like data that is usually stored in files.
|
||||
|
||||
Blob fields are usually not meant to be used as parameters of query search clause (WHERE) unless the underlying DBMS supports a feature usually known as "full text search"
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('blobtest', 'blob');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Clob
|
||||
|
||||
Clob (Character Large OBject) data type is meant to store data of undefined length that may be too large to store in text fields, like data that is usually stored in files.
|
||||
|
||||
Clob fields are meant to store only data made of printable ASCII characters whereas blob fields are meant to store all types of data.
|
||||
|
||||
Clob fields are usually not meant to be used as parameters of query search clause (WHERE) unless the underlying DBMS supports a feature usually known as "full text search"
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('clobtest', 'clob');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Timestamp
|
||||
|
||||
The timestamp data type is a mere combination of the date and the time of the day data types.
|
||||
The representation of values of the time stamp type is accomplished by joining the date and time
|
||||
string values in a single string joined by a space. Therefore, the format template is YYYY-MM-DD HH:MI:SS. The represented values obey the same rules and ranges described for the date and time data types
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('timestamptest', 'timestamp');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Time
|
||||
|
||||
The time data type may represent the time of a given moment of the day. DBMS independent representation of the time of the day is also accomplished by using text strings formatted according to the ISO-8601 standard.
|
||||
|
||||
The format defined by the ISO-8601 standard for the time of the day is HH:MI:SS where HH is the number of hour the day from 00 to 23 and MI and SS are respectively the number of the minute and of the second from 00 to 59. Hours, minutes and seconds numbered below 10 should be padded on the left with 0.
|
||||
|
||||
Some DBMS have native support for time of the day formats, but for others the DBMS driver may have to represent them as integers or text values. In any case, it is always possible to make comparisons between time values as well sort query results by fields of this type.
|
||||
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('timetest', 'time');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Date
|
||||
|
||||
The date data type may represent dates with year, month and day. DBMS independent representation of dates is accomplished by using text strings formatted according to the IS0-8601 standard.
|
||||
|
||||
The format defined by the ISO-8601 standard for dates is YYYY-MM-DD where YYYY is the number of the year (Gregorian calendar), MM is the number of the month from 01 to 12 and DD is the number of the day from 01 to 31. Months or days numbered below 10 should be padded on the left with 0.
|
||||
|
||||
Some DBMS have native support for date formats, but for others the DBMS driver may have to represent them as integers or text values. In any case, it is always possible to make comparisons between date values as well sort query results by fields of this type.
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('datetest', 'date');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Enum
|
||||
|
||||
Doctrine has a unified enum type. Enum typed columns automatically convert the string values into index numbers and vice versa. The possible values for the column can be specified with Doctrine_Record::setEnumValues(columnName, array values).
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('enumtest', 'enum', 4,
|
||||
array(
|
||||
'values' => array(
|
||||
'php',
|
||||
'java',
|
||||
'python'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
++++ Gzip
|
||||
|
||||
Gzip datatype is the same as string except that its automatically compressed when persisted and uncompressed when fetched. This datatype can be useful when storing data with a large compressibility ratio, such as bitmap images.
|
||||
|
||||
<code type="php">
|
||||
class Test extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('gziptest', 'gzip');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
Doctrine supports default values for all data types. When default value is attached to a record column this means two of things.
|
||||
First this value is attached to every newly created Record.
|
||||
|
||||
<code type="php">
|
||||
class User extends Doctrine_record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn('name', 'string', 50, array('default' => 'default name'));
|
||||
}
|
||||
}
|
||||
$user = new User();
|
||||
print $user->name; // default name
|
||||
</code>
|
||||
|
||||
Also when exporting record class to database DEFAULT //value// is attached to column definition statement.
|
@ -0,0 +1,117 @@
|
||||
+++ Introduction
|
||||
|
||||
//From [http://www.postgresql.org/docs/8.2/static/ddl-constraints.html PostgreSQL Documentation]://
|
||||
|
||||
> Data types are a way to limit the kind of data that can be stored in a table. For many applications, however, the constraint they provide is too coarse. For example, a column containing a product price should probably only accept positive values. But there is no standard data type that accepts only positive numbers. Another issue is that you might want to constrain column data with respect to other columns or rows. For example, in a table containing product information, there should be only one row for each product number.
|
||||
|
||||
Doctrine allows you to define *portable* constraints on columns and tables. Constraints give you as much control over the data in your tables as you wish. If a user attempts to store data in a column that would violate a constraint, an error is raised. This applies even if the value came from the default value definition.
|
||||
|
||||
Doctrine constraints act as database level constraints as well as application level validators. This means double security: the database doesn't allow wrong kind of values and neither does the application.
|
||||
|
||||
|
||||
+++ Notnull
|
||||
|
||||
A not-null constraint simply specifies that a column must not assume the null value. A not-null constraint is always written as a column constraint.
|
||||
|
||||
The following definition uses a notnull constraint for column {{name}}. This means that the specified column doesn't accept null values.
|
||||
|
||||
<code type='php'>
|
||||
class User extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('name', 'string', 200, array('notnull' => true,
|
||||
'primary' => true));
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
When this class gets exported to database the following SQL statement would get executed (in MySQL):
|
||||
|
||||
<code type="sql">
|
||||
CREATE TABLE user (name VARCHAR(200) NOT NULL, PRIMARY KEY(name))
|
||||
</code>
|
||||
|
||||
The notnull constraint also acts as an application level validator. This means that if Doctrine validators are turned on, Doctrine will automatically check that specified columns do not contain null values when saved.
|
||||
|
||||
If those columns happen to contain null values {{Doctrine_Validator_Exception}} is raised.
|
||||
|
||||
|
||||
+++ Unique
|
||||
|
||||
Unique constraints ensure that the data contained in a column or a group of columns is unique with respect to all the rows in the table.
|
||||
|
||||
In general, a unique constraint is violated when there are two or more rows in the table where the values of all of the columns included in the constraint are equal. However, two null values are not considered equal in this comparison. That means even in the presence of a unique constraint it is possible to store duplicate rows that contain a null value in at least one of the constrained columns. This behavior conforms to the SQL standard, but some databases do not follow this rule. So be careful when developing applications that are intended to be portable.
|
||||
|
||||
The following definition uses a unique constraint for column {{name}}.
|
||||
|
||||
<code type='php'>
|
||||
class User extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('name', 'string', 200, array('unique' => true));
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
>> Note: You should only use unique constraints for other than primary key columns. Primary key columns are always unique.
|
||||
|
||||
The following definition adds a unique constraint for columns {{name}} and {{age}}.
|
||||
|
||||
<code type='php'>
|
||||
class User extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('name', 'string', 200);
|
||||
$this->hasColumn('age', 'integer', 2);
|
||||
|
||||
$this->unique(array('name', 'age'));
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
|
||||
+++ Check
|
||||
|
||||
Doctrine check constraints act as database level constraints as well as application level validators. When a record with check validators is exported additional CHECK constraints are being added to CREATE TABLE statement.
|
||||
|
||||
Doctrine provides the following simple check operators:
|
||||
|
||||
||~ Operator ||~ Description ||
|
||||
|| {{gt}} || greater than constraint ( > ) ||
|
||||
|| {{lt}} || less than constraint ( < ) ||
|
||||
|| {{gte}} || greater than or equal to constraint ( >= ) ||
|
||||
|| {{lte}} || less than or equal to constraint ( <= ) ||
|
||||
|
||||
Consider the following example:
|
||||
|
||||
<code type='php'>
|
||||
class Product extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('id', 'integer', 4, 'primary');
|
||||
$this->hasColumn('price', 'decimal', 18, array('gt' => 0);
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
When exported the given class definition would execute the following statement (in pgsql):
|
||||
|
||||
<code type="sql">
|
||||
CREATE TABLE product (
|
||||
id INTEGER,
|
||||
price NUMERIC CHECK (price > 0)
|
||||
PRIMARY KEY(id))
|
||||
</code>
|
||||
|
||||
So Doctrine optionally ensures even at the database level that the price of any product cannot be below zero.
|
||||
|
||||
> NOTE: some databases don't support CHECK constraints. When this is the case Doctrine simple skips the creation of check constraints.
|
||||
|
||||
If the Doctrine validators are turned on the given definition would also ensure that when a record is being saved its price is always greater than zero.
|
||||
|
||||
If some of the prices of the saved products within a transaction is below zero, Doctrine throws Doctrine_Validator_Exception and automatically rolls back the transaction.
|
||||
|
@ -0,0 +1,41 @@
|
||||
Doctrine_Record::hasColumn() takes 4 arguments:
|
||||
|
||||
# **column name**
|
||||
# **column type**
|
||||
# **column length**
|
||||
# **column constraints and validators**
|
||||
|
||||
<code type='php'>
|
||||
class Email extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
// setting custom table name:
|
||||
$this->setTableName('emails');
|
||||
|
||||
$this->hasColumn('address', // name of the column
|
||||
'string', // column type
|
||||
'200', // column length
|
||||
array('notblank' => true,
|
||||
'email' => true // validators / constraints
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$this->hasColumn('address2', // name of the column
|
||||
'string', // column type
|
||||
'200', // column length
|
||||
// validators / constraints without arguments can be
|
||||
// specified also as as string with | separator
|
||||
'notblank|email'
|
||||
);
|
||||
|
||||
// Doctrine even supports the following format for
|
||||
// validators / constraints which have no arguments:
|
||||
|
||||
$this->hasColumn('address3', // name of the column
|
||||
'string', // column type
|
||||
'200', // column length
|
||||
array('notblank', 'email')
|
||||
);
|
||||
}
|
||||
}
|
||||
</code>
|
@ -0,0 +1,12 @@
|
||||
Doctrine automatically creates table names from the record class names. For this reason, it is recommended to name your record classes using the following rules:
|
||||
|
||||
* Use {{CamelCase}} naming
|
||||
* Underscores are allowed
|
||||
* The first letter must be capitalized
|
||||
* The class name cannot be one of the following (these keywords are reserved in DQL API):
|
||||
* {{ALL}}, {{AND}}, {{ANY}}, {{AS}}, {{ASC}}, {{AVG}}, {{BETWEEN}}, {{BIT_LENGTH}}, {{BY}}, {{CHARACTER_LENGTH}}, {{CHAR_LENGTH}}, {{COUNT}}, {{CURRENT_DATE}}, {{CURRENT_TIME}}, {{CURRENT_TIMESTAMP}}, {{DELETE}}, {{DESC}}, {{DISTINCT}}, {{EMPTY}}, {{EXISTS}}, {{FALSE}}, {{FETCH}}, {{FROM}}, {{GROUP}}, {{HAVING}}, {{IN}}, {{INNER}}, {{IS}}, {{JOIN}}, {{LEFT}}, {{LIKE}}, {{LOWER}}, {{MAX}}, {{MEMBER}}, {{MIN}}, {{MOD}}, {{NEW}}, {{NOT}}, {{NULL}}, {{OBJECT}}, {{OF}}, {{OR}}, {{ORDER}}, {{OUTER}}, {{POSITION}}, {{SELECT}}, {{SOME}}, {{SUM}}, {{TRIM}}, {{TRUE}}, {{UNKNOWN}}, {{UPDATE}}, {{UPPER}} and {{WHERE}}.
|
||||
|
||||
**Example:** {{My_PerfectClass}}
|
||||
|
||||
If you need to use a different naming schema, you can override this using the {{setTableName()}} method in the {{setTableDefinition()}} method.
|
||||
|
@ -0,0 +1,30 @@
|
||||
Doctrine offers various table options. All table options can be set via {{Doctrine_Record::option($optionName, $value)}}.
|
||||
|
||||
For example if you are using MySQL and want to use INNODB tables it can be done as follows:
|
||||
|
||||
<code type="php">
|
||||
class MyInnoDbRecord extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('name', 'string');
|
||||
|
||||
$this->option('type', 'INNODB');
|
||||
}
|
||||
}
|
||||
</code>
|
||||
|
||||
In the following example we set the collate and character set options:
|
||||
|
||||
<code type="php">
|
||||
class MyCustomOptionRecord extends Doctrine_Record
|
||||
{
|
||||
public function setTableDefinition()
|
||||
{
|
||||
$this->hasColumn('name', 'string');
|
||||
|
||||
$this->option('collate', 'utf8_unicode_ci');
|
||||
$this->option('charset', 'utf8');
|
||||
}
|
||||
}
|
||||
</code>
|
1
manual/new/docs/en/real-world-examples/album-lister.txt
Normal file
1
manual/new/docs/en/real-world-examples/album-lister.txt
Normal file
@ -0,0 +1 @@
|
||||
|
53
manual/new/docs/en/real-world-examples/forum-application.txt
Normal file
53
manual/new/docs/en/real-world-examples/forum-application.txt
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
<code type="php">
|
||||
class Forum_Category extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("root_category_id", "integer", 10);
|
||||
$this->hasColumn("parent_category_id", "integer", 10);
|
||||
$this->hasColumn("name", "string", 50);
|
||||
$this->hasColumn("description", "string", 99999);
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasMany("Forum_Category as Subcategory", "Subcategory.parent_category_id");
|
||||
$this->hasOne("Forum_Category as Rootcategory", "Forum_Category.root_category_id");
|
||||
}
|
||||
}
|
||||
class Forum_Board extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("category_id", "integer", 10);
|
||||
$this->hasColumn("name", "string", 100);
|
||||
$this->hasColumn("description", "string", 5000);
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasOne("Forum_Category as Category", "Forum_Board.category_id");
|
||||
$this->ownsMany("Forum_Thread as Threads", "Forum_Thread.board_id");
|
||||
}
|
||||
}
|
||||
|
||||
class Forum_Entry extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("author", "string", 50);
|
||||
$this->hasColumn("topic", "string", 100);
|
||||
$this->hasColumn("message", "string", 99999);
|
||||
$this->hasColumn("parent_entry_id", "integer", 10);
|
||||
$this->hasColumn("thread_id", "integer", 10);
|
||||
$this->hasColumn("date", "integer", 10);
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasOne("Forum_Entry as Parent", "Forum_Entry.parent_entry_id");
|
||||
$this->hasOne("Forum_Thread as Thread", "Forum_Entry.thread_id");
|
||||
}
|
||||
}
|
||||
|
||||
class Forum_Thread extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("board_id", "integer", 10);
|
||||
$this->hasColumn("updated", "integer", 10);
|
||||
$this->hasColumn("closed", "integer", 1);
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasOne("Forum_Board as Board", "Forum_Thread.board_id");
|
||||
$this->ownsMany("Forum_Entry as Entries", "Forum_Entry.thread_id");
|
||||
}
|
||||
}
|
||||
</code>
|
@ -0,0 +1,91 @@
|
||||
In the following example we make a user management system where
|
||||
|
||||
# Each user and group are entities
|
||||
# User is an entity of type 0
|
||||
# Group is an entity of type 1
|
||||
# Each entity (user/group) has 0-1 email
|
||||
# Each entity has 0-* phonenumbers
|
||||
# If an entity is saved all its emails and phonenumbers are also saved
|
||||
# If an entity is deleted all its emails and phonenumbers are also deleted
|
||||
# When an entity is created and saved a current timestamp will be assigned to 'created' field
|
||||
# When an entity is updated a current timestamp will be assigned to 'updated' field
|
||||
# Entities will always be fetched in batches
|
||||
|
||||
<code type="php">
|
||||
class Entity extends Doctrine_Record {
|
||||
public function setUp() {
|
||||
$this->ownsOne("Email","Entity.email_id");
|
||||
$this->ownsMany("Phonenumber","Phonenumber.entity_id");
|
||||
$this->setAttribute(Doctrine::ATTR_FETCHMODE,Doctrine::FETCH_BATCH);
|
||||
$this->setAttribute(Doctrine::ATTR_LISTENER,new EntityListener());
|
||||
}
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name","string",50);
|
||||
$this->hasColumn("loginname","string",20);
|
||||
$this->hasColumn("password","string",16);
|
||||
$this->hasColumn("type","integer",1);
|
||||
$this->hasColumn("created","integer",11);
|
||||
$this->hasColumn("updated","integer",11);
|
||||
$this->hasColumn("email_id","integer");
|
||||
}
|
||||
}
|
||||
class Group extends Entity {
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->hasMany("User","Groupuser.user_id");
|
||||
$this->setInheritanceMap(array("type"=>1));
|
||||
}
|
||||
}
|
||||
class User extends Entity {
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->hasMany("Group","Groupuser.group_id");
|
||||
$this->setInheritanceMap(array("type"=>0));
|
||||
}
|
||||
}
|
||||
class Groupuser extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("group_id","integer");
|
||||
$this->hasColumn("user_id","integer");
|
||||
}
|
||||
}
|
||||
|
||||
class Phonenumber extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("phonenumber","string",20);
|
||||
$this->hasColumn("entity_id","integer");
|
||||
}
|
||||
}
|
||||
class Email extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("address","string",150,"email|unique");
|
||||
}
|
||||
}
|
||||
class EntityListener extends Doctrine_EventListener {
|
||||
public function onPreUpdate(Doctrine_Record $record) {
|
||||
$record->updated = time();
|
||||
}
|
||||
public function onPreInsert(Doctrine_Record $record) {
|
||||
$record->created = time();
|
||||
}
|
||||
}
|
||||
|
||||
// USER MANAGEMENT SYSTEM IN ACTION:
|
||||
|
||||
$manager = Doctrine_Manager::getInstance();
|
||||
|
||||
$conn = $manager->openConnection(new PDO("DSN","username","password"));
|
||||
|
||||
$user = new User();
|
||||
|
||||
$user->name = "Jack Daniels";
|
||||
$user->Email->address = "jackdaniels@drinkmore.info";
|
||||
$user->Phonenumber[0]->phonenumber = "123 123";
|
||||
$user->Phonenumber[1]->phonenumber = "133 133";
|
||||
$user->save();
|
||||
|
||||
$user->Group[0]->name = "beer lovers";
|
||||
$user->Group[0]->Email->address = "beerlovers@drinkmore.info";
|
||||
$user->Group[0]->save();
|
||||
|
||||
</code>
|
328
manual/new/docs/en/root.txt
Normal file
328
manual/new/docs/en/root.txt
Normal file
@ -0,0 +1,328 @@
|
||||
+ Getting started
|
||||
++ Requirements
|
||||
++ Installation
|
||||
++ Compiling
|
||||
++ Starting new project
|
||||
++ Working with existing databases
|
||||
++ Exporting classes
|
||||
|
||||
+ Connection management
|
||||
++ DSN, the Data Source Name
|
||||
++ Opening a new connection
|
||||
++ Lazy-connecting to database
|
||||
++ Managing connections
|
||||
++ Connection-component binding
|
||||
|
||||
+ Object relational mapping
|
||||
++ Introduction
|
||||
++ Table and class naming
|
||||
++ Table options
|
||||
++ Columns
|
||||
++ Constraints and validators
|
||||
++ Record identifiers
|
||||
+++ Introduction
|
||||
+++ Autoincremented
|
||||
+++ Natural
|
||||
+++ Composite
|
||||
+++ Sequence
|
||||
++ Indexes
|
||||
+++ Introduction
|
||||
+++ Adding indexes
|
||||
+++ Index options
|
||||
+++ Special indexes
|
||||
++ Relations
|
||||
+++ Introduction
|
||||
+++ Relation aliases
|
||||
+++ Foreign key associations
|
||||
++++ One-to-One
|
||||
++++ One-to-Many, Many-to-One
|
||||
++++ Tree structure
|
||||
+++ Join table associations
|
||||
++++ One-to-One
|
||||
++++ One-to-Many, Many-to-One
|
||||
++++ Many-to-Many
|
||||
++++ Self-referencing
|
||||
+++ Inheritance
|
||||
++++ One table many classes
|
||||
++++ One table one class
|
||||
++++ Column aggregation
|
||||
+++ Foreign key constraints
|
||||
++++ Introduction
|
||||
++++ Constraint actions
|
||||
++ Hierarchical data
|
||||
+++ Introduction
|
||||
++++ About
|
||||
++++ Setting up
|
||||
++++ Node interface
|
||||
++++ Tree interface
|
||||
++++ Traversing or Walking Trees
|
||||
++++ Read me
|
||||
+++ Adjacency list
|
||||
++++ Introduction
|
||||
+++ Nested set
|
||||
++++ Introduction
|
||||
++++ Setting up
|
||||
++++ Tree options
|
||||
++++ Node support
|
||||
++++ Tree support
|
||||
++++ Read me
|
||||
+++ Materialized path
|
||||
++++ Introduction
|
||||
+++ Examples
|
||||
|
||||
+ Working with objects
|
||||
++ Dealing with relations
|
||||
+++ Creating related records
|
||||
+++ Retrieving related records
|
||||
+++ Updating related records
|
||||
+++ Deleting related records
|
||||
+++ Working with associations
|
||||
++ Component overview
|
||||
+++ Manager
|
||||
++++ Introduction
|
||||
++++ Opening a new connection
|
||||
++++ Managing connections
|
||||
+++ Connection
|
||||
++++ Introduction
|
||||
++++ Available drivers
|
||||
++++ Getting a table object
|
||||
++++ Flushing the connection
|
||||
++++ Querying the database
|
||||
++++ Getting connection state
|
||||
+++ Record
|
||||
++++ Introduction
|
||||
++++ Creating new records
|
||||
++++ Retrieving existing records
|
||||
++++ Accessing properties
|
||||
++++ Updating records
|
||||
++++ Deleting records
|
||||
++++ Getting record state
|
||||
++++ Getting object copy
|
||||
++++ Serializing
|
||||
++++ Checking Existence
|
||||
++++ Callbacks
|
||||
+++ Collection
|
||||
++++ Introduction
|
||||
++++ Accessing elements
|
||||
++++ Adding new elements
|
||||
++++ Getting collection count
|
||||
++++ Saving the collection
|
||||
++++ Deleting collection
|
||||
++++ Key mapping
|
||||
++++ Loading related records
|
||||
++++ Collection expanding
|
||||
+++ Table
|
||||
++++ Introduction
|
||||
++++ Getting table information
|
||||
++++ Finder methods
|
||||
++++ Custom table classes
|
||||
++++ Custom finders
|
||||
++++ Getting relation objects
|
||||
++ Fetching objects
|
||||
|
||||
+ Configuration
|
||||
++ Introduction
|
||||
++ Levels of configuration
|
||||
++ Setting attributes
|
||||
+++ Portability
|
||||
+++ Identifier quoting
|
||||
+++ Table creation
|
||||
+++ Fetching strategy
|
||||
+++ Batch size
|
||||
+++ Session lockmode
|
||||
+++ Event listener
|
||||
+++ Validation
|
||||
+++ Offset collection limit
|
||||
+ Advanced components
|
||||
++ Eventlisteners
|
||||
+++ Introduction
|
||||
+++ Creating new listener
|
||||
+++ List of events
|
||||
+++ Listening events
|
||||
+++ Chaining
|
||||
+++ AccessorInvoker
|
||||
+++ Creating a logger
|
||||
++ Validators
|
||||
+++ Introduction
|
||||
+++ More Validation
|
||||
+++ Valid or Not Valid
|
||||
+++ List of predefined validators
|
||||
++ View
|
||||
+++ Intoduction
|
||||
+++ Managing views
|
||||
+++ Using views
|
||||
++ Cache
|
||||
+++ Introduction
|
||||
+++ Query cache
|
||||
++ Locking Manager
|
||||
+++ Introduction
|
||||
+++ Examples
|
||||
+++ Planned
|
||||
+++ Technical Details
|
||||
+++ Maintainer
|
||||
++ Db_Profiler
|
||||
+++ Introduction
|
||||
+++ Basic usage
|
||||
+++ Advanced usage
|
||||
++ Hook
|
||||
+++ Introduction
|
||||
+++ Building queries
|
||||
+++ List of parsers
|
||||
++ Query
|
||||
+++ Introduction
|
||||
+++ selecting tables
|
||||
+++ limiting the query results
|
||||
+++ setting query conditions
|
||||
+++ HAVING conditions
|
||||
+++ sorting query results
|
||||
++ RawSql
|
||||
+++ Introduction
|
||||
+++ Using SQL
|
||||
+++ Adding components
|
||||
+++ Method overloading
|
||||
++ Db
|
||||
+++ Introduction
|
||||
+++ Connecting to a database
|
||||
+++ Using event listeners
|
||||
+++ Chaining listeners
|
||||
++ Exceptions
|
||||
+++ Overview
|
||||
+++ List of exceptions
|
||||
+ DQL (Doctrine Query Language)
|
||||
++ Introduction
|
||||
++ SELECT queries
|
||||
+++ DISTINCT keyword
|
||||
+++ Aggregate values
|
||||
++ UPDATE queries
|
||||
++ DELETE queries
|
||||
++ FROM clause
|
||||
++ WHERE clause
|
||||
++ Conditional expressions
|
||||
+++ Literals
|
||||
+++ Input parameters
|
||||
+++ Operators and operator precedence
|
||||
+++ Between expressions
|
||||
+++ In expressions
|
||||
+++ Like Expressions
|
||||
+++ Null Comparison Expressions
|
||||
+++ Empty Collection Comparison Expressions
|
||||
+++ Collection Member Expressions
|
||||
+++ Exists Expressions
|
||||
+++ All and Any Expressions
|
||||
+++ Subqueries
|
||||
++ Functional Expressions
|
||||
+++ String functions
|
||||
+++ Arithmetic functions
|
||||
+++ Datetime functions
|
||||
+++ Collection functions
|
||||
++ Subqueries
|
||||
+++ Introduction
|
||||
+++ Comparisons using subqueries
|
||||
+++ Conditional expressions
|
||||
++++ ANY, IN and SOME
|
||||
++++ ALL
|
||||
++++ EXISTS and NOT EXISTS
|
||||
+++ Correlated subqueries
|
||||
+++ Subqueries in FROM clause
|
||||
++ GROUP BY, HAVING clauses
|
||||
++ ORDER BY clause
|
||||
+++ Introduction
|
||||
+++ Sorting by an aggregate value
|
||||
+++ Using random order
|
||||
++ LIMIT and OFFSET clauses
|
||||
+++ Introduction
|
||||
+++ Driver portability
|
||||
+++ The limit-subquery-algorithm
|
||||
++ Examples
|
||||
++ BNF
|
||||
|
||||
+ Native SQL
|
||||
++ Scalar queries
|
||||
++ Component queries
|
||||
++ Fetching multiple components
|
||||
|
||||
+ Transactions
|
||||
++ Introduction
|
||||
++ Unit of work
|
||||
++ Nesting
|
||||
++ Savepoints
|
||||
++ Locking strategies
|
||||
+++ Pessimistic locking
|
||||
+++ Optimistic locking
|
||||
++ Lock modes
|
||||
++ Isolation levels
|
||||
++ Deadlocks
|
||||
|
||||
+ Caching
|
||||
++ Introduction
|
||||
++ Availible options
|
||||
++ Drivers
|
||||
+++ Memcache
|
||||
+++ APC
|
||||
+++ Sqlite
|
||||
|
||||
+ Database abstraction
|
||||
++ Modules
|
||||
+++ Export
|
||||
++++ Introduction
|
||||
++++ Creating new table
|
||||
++++ Altering table
|
||||
+++ Import
|
||||
++++ Introduction
|
||||
++++ Getting table info
|
||||
++++ Getting foreign key info
|
||||
++++ Getting view info
|
||||
+++ Util
|
||||
++++ Using explain
|
||||
+++ DataDict
|
||||
++++ Getting portable type
|
||||
++++ Getting database declaration
|
||||
++++ Reserved keywords
|
||||
++ Drivers
|
||||
+++ Oracle
|
||||
++++ Making unsuported functions work
|
||||
+++ Mysql
|
||||
++++ Tips and tricks
|
||||
|
||||
+ Technology
|
||||
++ Architecture
|
||||
++ Design patterns used
|
||||
++ Speed
|
||||
++ Internal optimizations
|
||||
+++ DELETE
|
||||
+++ INSERT
|
||||
+++ UPDATE
|
||||
|
||||
+ Real world examples
|
||||
++ User management system
|
||||
++ Forum application
|
||||
++ Album lister
|
||||
|
||||
+ Coding standards
|
||||
++ Overview
|
||||
+++ Scope
|
||||
+++ Goals
|
||||
++ PHP File Formatting
|
||||
+++ General
|
||||
+++ Indentation
|
||||
+++ Maximum line length
|
||||
+++ Line termination
|
||||
++ Naming Conventions
|
||||
+++ Classes
|
||||
+++ Interfaces
|
||||
+++ Filenames
|
||||
+++ Functions and methods
|
||||
+++ Variables
|
||||
+++ Constants
|
||||
+++ Record columns
|
||||
++ Coding Style
|
||||
+++ PHP code demarcation
|
||||
+++ Strings
|
||||
+++ Arrays
|
||||
+++ Classes
|
||||
+++ Functions and methods
|
||||
+++ Control statements
|
||||
+++ Inline documentation
|
||||
++ Testing
|
||||
+++ Writing tests
|
||||
|
568
manual/new/highlight.php
Normal file
568
manual/new/highlight.php
Normal file
@ -0,0 +1,568 @@
|
||||
<?php
|
||||
/**
|
||||
* Define constants for PHP 4 / PHP 5 compatability
|
||||
*
|
||||
* The source of this file can be found at:
|
||||
* http://cvs.php.net/co.php/pear/PHP_Compat/Compat/Constant/T.php?r=HEAD
|
||||
*
|
||||
* It is part of the PEAR PHP_Compat package:
|
||||
* http://pear.php.net/package/PHP_Compat
|
||||
*/
|
||||
//require_once 'PHP/Compat/Constant/T.php';
|
||||
|
||||
|
||||
/**
|
||||
* Improved PHP syntax highlighting.
|
||||
*
|
||||
* Generates valid XHTML output with function referencing
|
||||
* and line numbering.
|
||||
*
|
||||
* Four output methods provide maximum flexibility.
|
||||
* * toHTML => Formatted HTML
|
||||
* * toHtmlComment => Formatted HTML, specifically for comments on messageboards
|
||||
* * toList => Ordered lists
|
||||
* * toArray => Associative array
|
||||
*
|
||||
* Highlighting can be inline (with styles), or the same as
|
||||
* highlight_file() where colors are taken from php.ini.
|
||||
*
|
||||
* @author Aidan Lister <aidan@php.net>
|
||||
* @author Based on an idea by Matthew Harris <shugotenshi@gmail.com>
|
||||
* @version 1.3.0
|
||||
* @link http://aidanlister.com/repos/v/PHP_Highlight.php
|
||||
*/
|
||||
if (!defined('T_ML_COMMENT')) {
|
||||
define('T_ML_COMMENT', T_COMMENT);
|
||||
} else {
|
||||
define('T_DOC_COMMENT', T_ML_COMMENT);
|
||||
}
|
||||
class PHP_Highlight
|
||||
{
|
||||
/**
|
||||
* Hold highlight colors
|
||||
*
|
||||
* Contains an associative array of token types and colours.
|
||||
* By default, it contains the colours as specified by php.ini
|
||||
*
|
||||
* For example, to change the colour of strings, use something
|
||||
* simular to $h->highlight['string'] = 'blue';
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $highlight;
|
||||
|
||||
/**
|
||||
* Things to be replaced for formatting or otherwise reasons
|
||||
*
|
||||
* The first element contains the match array, the second the replace
|
||||
* array.
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $replace = array(
|
||||
0 => array("\t", ' '),
|
||||
1 => array(' ', ' '));
|
||||
|
||||
/**
|
||||
* Format of the link to the PHP manual page
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $manual = '<a href="http://www.php.net/function.%s">%s</a>';
|
||||
|
||||
/**
|
||||
* Format of the span tag to be wrapped around each token
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $span;
|
||||
|
||||
/**
|
||||
* Hold the source
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $_source = false;
|
||||
|
||||
/**
|
||||
* Hold plaintext keys
|
||||
*
|
||||
* An array of lines which are plaintext
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $_plaintextkeys = array();
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Populates highlight array
|
||||
*
|
||||
* @param bool $inline If inline styles rather than colors are to be used
|
||||
* @param bool $plaintext Do not format code outside PHP tags
|
||||
*/
|
||||
function PHP_Highlight($inline = false)
|
||||
{
|
||||
// Inline
|
||||
if ($inline === false) {
|
||||
// Default colours from php.ini
|
||||
/**
|
||||
$this->highlight = array(
|
||||
'string' => ini_get('highlight.string'),
|
||||
'comment' => ini_get('highlight.comment'),
|
||||
'keyword' => ini_get('highlight.keyword'),
|
||||
'bg' => ini_get('highlight.bg'),
|
||||
'default' => ini_get('highlight.default'),
|
||||
'html' => ini_get('highlight.html')
|
||||
);
|
||||
*/
|
||||
$this->highlight = array(
|
||||
'string' => "#cb0864",
|
||||
'comment' => "#888888",
|
||||
'keyword' => "#118994",
|
||||
'bg' => "#222222",
|
||||
'default' => "#000000",
|
||||
'html' => ini_get('highlight.html')
|
||||
);
|
||||
$this->span = '<span style="color: %s;">%s</span>';
|
||||
} else {
|
||||
// Basic styles
|
||||
$this->highlight = array(
|
||||
'string' => 'string',
|
||||
'comment' => 'comment',
|
||||
'keyword' => 'keyword',
|
||||
'bg' => 'bg',
|
||||
'default' => 'default',
|
||||
'html' => 'html'
|
||||
);
|
||||
$this->span = '<span class="%s">%s</span>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load a file
|
||||
*
|
||||
* @access public
|
||||
* @param string $file The file to load
|
||||
* @return bool Returns TRUE
|
||||
*/
|
||||
function loadFile($file)
|
||||
{
|
||||
$this->_source = file_get_contents($file);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load a string
|
||||
*
|
||||
* @access public
|
||||
* @param string $string The string to load
|
||||
* @return bool Returns TRUE
|
||||
*/
|
||||
function loadString($string)
|
||||
{
|
||||
$this->_source = $string;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the loaded string into an array
|
||||
* Source is returned with the element key corresponding to the line number
|
||||
*
|
||||
* @access public
|
||||
* @param bool $funcref Reference functions to the PHP manual
|
||||
* @param bool $blocks Whether to ignore processing plaintext
|
||||
* @return array An array of highlighted source code
|
||||
*/
|
||||
function toArray($funcref = true, $blocks = false)
|
||||
{
|
||||
// Ensure source has been loaded
|
||||
if ($this->_source == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init
|
||||
$tokens = token_get_all($this->_source);
|
||||
$manual = $this->manual;
|
||||
$span = $this->span;
|
||||
$i = 0;
|
||||
$out = array();
|
||||
$out[$i] = '';
|
||||
|
||||
// Loop through each token
|
||||
foreach ($tokens as $j => $token) {
|
||||
// Single char
|
||||
if (is_string($token)) {
|
||||
// Skip token2color check for speed
|
||||
$out[$i] .= sprintf($span, $this->highlight['keyword'], htmlspecialchars($token));
|
||||
|
||||
// Heredocs behave strangely
|
||||
list($tb) = isset($tokens[$j - 1]) ? $tokens[$j - 1] : false;
|
||||
if ($tb === T_END_HEREDOC) {
|
||||
$out[++$i] = '';
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Proper token
|
||||
list ($token, $value) = $token;
|
||||
|
||||
// Make the value safe
|
||||
$value = htmlspecialchars($value);
|
||||
$value = str_replace($this->replace[0], $this->replace[1], $value);
|
||||
|
||||
// Process
|
||||
if ($value === "\n") {
|
||||
// End this line and start the next
|
||||
$out[++$i] = '';
|
||||
} else {
|
||||
// Function linking
|
||||
if ($funcref === true && $token === T_STRING) {
|
||||
// Look ahead 1, look ahead 2, and look behind 3
|
||||
if ((isset($tokens[$j + 1]) && $tokens[$j + 1] === '(' ||
|
||||
isset($tokens[$j + 2]) && $tokens[$j + 2] === '(') &&
|
||||
isset($tokens[$j - 3][0]) && $tokens[$j - 3][0] !== T_FUNCTION
|
||||
&& function_exists($value)) {
|
||||
|
||||
// Insert the manual link
|
||||
$value = sprintf($manual, $value, $value);
|
||||
}
|
||||
}
|
||||
|
||||
// Explode token block
|
||||
$lines = explode("\n", $value);
|
||||
foreach ($lines as $jj => $line) {
|
||||
$line = trim($line);
|
||||
if ($line !== '') {
|
||||
// This next line is helpful for debugging
|
||||
//$out[$i] .= token_name($token);
|
||||
|
||||
// Check for plaintext
|
||||
if ($blocks === true && $token === T_INLINE_HTML) {
|
||||
$this->_plaintextkeys[] = $i;
|
||||
$out[$i] .= $line;
|
||||
} else {
|
||||
$out[$i] .= sprintf($span, $this->_token2color($token), $line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Start a new line
|
||||
if (isset($lines[$jj + 1])) {
|
||||
$out[++$i] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the source to an ordered list.
|
||||
* Each line is wrapped in <li> tags.
|
||||
*
|
||||
* @access public
|
||||
* @param bool $return Return rather than print the results
|
||||
* @param bool $funcref Reference functions to the PHP manual
|
||||
* @param bool $blocks Whether to use code blocks around plaintext
|
||||
* @return string A HTML ordered list
|
||||
*/
|
||||
function toList($return = false, $funcref = true, $blocks = true)
|
||||
{
|
||||
// Ensure source has been loaded
|
||||
if ($this->_source == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Format list
|
||||
$source = $this->toArray($funcref, $blocks);
|
||||
$out = "<ol>\n";
|
||||
foreach ($source as $i => $line) {
|
||||
$out .= " <li>";
|
||||
|
||||
// Some extra juggling for lines which are not code
|
||||
if (empty($line)) {
|
||||
$out .= ' ';
|
||||
} elseif ($blocks === true && in_array($i, $this->_plaintextkeys)) {
|
||||
$out .= $line;
|
||||
} else {
|
||||
$out .= "$line";
|
||||
}
|
||||
|
||||
$out .= "</li>\n";
|
||||
}
|
||||
$out .= "</ol>\n";
|
||||
|
||||
if ($return === true) {
|
||||
return $out;
|
||||
} else {
|
||||
echo $out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the source to formatted HTML.
|
||||
* Each line ends with <br />.
|
||||
*
|
||||
* @access public
|
||||
* @param bool $return Return rather than print the results
|
||||
* @param bool $linenum Display line numbers
|
||||
* @param string $format Specify format of line numbers displayed
|
||||
* @param bool $funcref Reference functions to the PHP manual
|
||||
* @return string A HTML block of code
|
||||
*/
|
||||
function toHtml($return = false, $linenum = false, $format = null, $funcref = true)
|
||||
{
|
||||
// Ensure source has been loaded
|
||||
if ($this->_source == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Line numbering
|
||||
if ($linenum === true && $format === null) {
|
||||
$format = '<span>%02d</span> ';
|
||||
}
|
||||
|
||||
// Format code
|
||||
$source = $this->toArray($funcref);
|
||||
$out = "<pre>";
|
||||
foreach ($source as $i => $line) {
|
||||
if ($linenum === true) {
|
||||
$out .= sprintf($format, $i);
|
||||
}
|
||||
|
||||
$out .= $line;
|
||||
$out .= "\n";
|
||||
}
|
||||
$out .= "</pre>\n";
|
||||
|
||||
if ($return === true) {
|
||||
return $out;
|
||||
} else {
|
||||
echo $out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the source to formatted HTML blocks.
|
||||
* Each line ends with <br />.
|
||||
*
|
||||
* This method ensures only PHP is between <code> blocks.
|
||||
*
|
||||
* @access public
|
||||
* @param bool $return Return rather than print the results
|
||||
* @param bool $linenum Display line numbers
|
||||
* @param string $format Specify format of line numbers displayed
|
||||
* @param bool $reset Reset the line numbering each block
|
||||
* @param bool $funcref Reference functions to the PHP manual
|
||||
* @return string A HTML block of code
|
||||
*/
|
||||
function toHtmlBlocks($return = false, $linenum = false, $format = null, $reset = true, $funcref = true)
|
||||
{
|
||||
// Ensure source has been loaded
|
||||
if ($this->_source == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Default line numbering
|
||||
if ($linenum === true && $format === null) {
|
||||
$format = '<span>%03d</span> ';
|
||||
}
|
||||
|
||||
// Init
|
||||
$source = $this->toArray($funcref, true);
|
||||
$out = '';
|
||||
$wasplain = true;
|
||||
$k = 0;
|
||||
|
||||
// Loop through each line and decide which block to use
|
||||
foreach ($source as $i => $line) {
|
||||
// Empty line
|
||||
if (empty($line)) {
|
||||
if ($wasplain === true) {
|
||||
$out .= ' ';
|
||||
} else {
|
||||
if (in_array($i+1, $this->_plaintextkeys)) {
|
||||
$out .= "</code>\n";
|
||||
|
||||
// Reset line numbers
|
||||
if ($reset === true) {
|
||||
$k = 0;
|
||||
}
|
||||
} else {
|
||||
$out .= ' ';
|
||||
// Add line number
|
||||
if ($linenum === true) {
|
||||
$out .= sprintf($format, ++$k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Plain text
|
||||
} elseif (in_array($i, $this->_plaintextkeys)) {
|
||||
if ($wasplain === false) {
|
||||
$out .= "</code>\n";
|
||||
|
||||
// Reset line numbers
|
||||
if ($reset === true) {
|
||||
$k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$wasplain = true;
|
||||
$out .= str_replace(' ', ' ', $line);
|
||||
|
||||
// Code
|
||||
} else {
|
||||
if ($wasplain === true) {
|
||||
$out .= "<code>\n";
|
||||
}
|
||||
$wasplain = false;
|
||||
|
||||
$out .= ' ';
|
||||
// Add line number
|
||||
if ($linenum === true) {
|
||||
$out .= sprintf($format, ++$k);
|
||||
}
|
||||
$out .= $line;
|
||||
}
|
||||
|
||||
$out .= "<br />\n";
|
||||
}
|
||||
|
||||
// Add final code tag
|
||||
if ($wasplain === false) {
|
||||
$out .= "</code>\n";
|
||||
}
|
||||
|
||||
// Output method
|
||||
if ($return === true) {
|
||||
return $out;
|
||||
} else {
|
||||
echo $out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assign a color based on the name of a token
|
||||
*
|
||||
* @access private
|
||||
* @param int $token The token
|
||||
* @return string The color of the token
|
||||
*/
|
||||
function _token2color($token)
|
||||
{
|
||||
|
||||
switch ($token):
|
||||
case T_CONSTANT_ENCAPSED_STRING:
|
||||
return $this->highlight['string'];
|
||||
break;
|
||||
|
||||
case T_INLINE_HTML:
|
||||
return $this->highlight['html'];
|
||||
break;
|
||||
|
||||
case T_COMMENT:
|
||||
case T_DOC_COMMENT:
|
||||
//case T_ML_COMMENT:
|
||||
return $this->highlight['comment'];
|
||||
break;
|
||||
|
||||
case T_ABSTRACT:
|
||||
case T_ARRAY:
|
||||
case T_ARRAY_CAST:
|
||||
case T_AS:
|
||||
case T_BOOLEAN_AND:
|
||||
case T_BOOLEAN_OR:
|
||||
case T_BOOL_CAST:
|
||||
case T_BREAK:
|
||||
case T_CASE:
|
||||
case T_CATCH:
|
||||
case T_CLASS:
|
||||
case T_CLONE:
|
||||
case T_CONCAT_EQUAL:
|
||||
case T_CONTINUE:
|
||||
case T_DEFAULT:
|
||||
case T_DOUBLE_ARROW:
|
||||
case T_DOUBLE_CAST:
|
||||
case T_ECHO:
|
||||
case T_ELSE:
|
||||
case T_ELSEIF:
|
||||
case T_EMPTY:
|
||||
case T_ENDDECLARE:
|
||||
case T_ENDFOR:
|
||||
case T_ENDFOREACH:
|
||||
case T_ENDIF:
|
||||
case T_ENDSWITCH:
|
||||
case T_ENDWHILE:
|
||||
case T_END_HEREDOC:
|
||||
case T_EXIT:
|
||||
case T_EXTENDS:
|
||||
case T_FINAL:
|
||||
case T_FOREACH:
|
||||
case T_FUNCTION:
|
||||
case T_GLOBAL:
|
||||
case T_IF:
|
||||
case T_INC:
|
||||
case T_INCLUDE:
|
||||
case T_INCLUDE_ONCE:
|
||||
case T_INSTANCEOF:
|
||||
case T_INT_CAST:
|
||||
case T_ISSET:
|
||||
case T_IS_EQUAL:
|
||||
case T_IS_IDENTICAL:
|
||||
case T_IS_NOT_IDENTICAL:
|
||||
case T_IS_SMALLER_OR_EQUAL:
|
||||
case T_NEW:
|
||||
case T_OBJECT_CAST:
|
||||
case T_OBJECT_OPERATOR:
|
||||
case T_PAAMAYIM_NEKUDOTAYIM:
|
||||
case T_PRIVATE:
|
||||
case T_PROTECTED:
|
||||
case T_PUBLIC:
|
||||
case T_REQUIRE:
|
||||
case T_REQUIRE_ONCE:
|
||||
case T_RETURN:
|
||||
case T_SL:
|
||||
case T_SL_EQUAL:
|
||||
case T_SR:
|
||||
case T_SR_EQUAL:
|
||||
case T_START_HEREDOC:
|
||||
case T_STATIC:
|
||||
case T_STRING_CAST:
|
||||
case T_THROW:
|
||||
case T_TRY:
|
||||
case T_UNSET_CAST:
|
||||
case T_VAR:
|
||||
case T_WHILE:
|
||||
return $this->highlight['keyword'];
|
||||
break;
|
||||
|
||||
case T_CLOSE_TAG:
|
||||
case T_OPEN_TAG:
|
||||
case T_OPEN_TAG_WITH_ECHO:
|
||||
default:
|
||||
return $this->highlight['default'];
|
||||
|
||||
endswitch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
BIN
manual/new/images/quotation-mark.png
Normal file
BIN
manual/new/images/quotation-mark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 502 B |
53
manual/new/index.php
Normal file
53
manual/new/index.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$includePath = dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'vendor';
|
||||
|
||||
set_include_path($includePath);
|
||||
|
||||
require_once('Sensei/Sensei.php');
|
||||
require_once('DocTool.php');
|
||||
|
||||
spl_autoload_register(array('Sensei', 'autoload'));
|
||||
|
||||
$tool = new DocTool('docs/en/root.txt');
|
||||
// $tool->setOption('clean-url', true);
|
||||
|
||||
$supportedLangs = array('en', 'fi');
|
||||
foreach ($supportedLangs as $language) {
|
||||
include "lang/$language.php";
|
||||
$tool->addLanguage($lang[$language], $language);
|
||||
}
|
||||
|
||||
$baseUrl = '';
|
||||
$title = 'Doctrine Documentation';
|
||||
$section = null;
|
||||
|
||||
if (isset($_GET['chapter'])) {
|
||||
$section = $tool->findByPath($_GET['chapter']);
|
||||
if ($tool->getOption('clean-url')) {
|
||||
$baseUrl = '../';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['one-page'])) {
|
||||
$tool->setOption('one-page', true);
|
||||
$tool->setOption('max-level', 0);
|
||||
$section = null;
|
||||
$baseUrl = '';
|
||||
}
|
||||
|
||||
if ($section) {
|
||||
while ($section->getLevel() > 1) {
|
||||
$section = $section->getParent();
|
||||
}
|
||||
|
||||
$tool->setOption('section', $section);
|
||||
$title .= ' - Chapter ' . $section->getIndex() . ' ' . $section->getName();
|
||||
}
|
||||
|
||||
if ($tool->getOption('clean-url')) {
|
||||
$tool->setOption('base-url', $baseUrl);
|
||||
}
|
||||
|
||||
include 'template.php';
|
6
manual/new/lang/en.php
Normal file
6
manual/new/lang/en.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
$lang['en'] = array(
|
||||
'Chapter %s' => 'Chapter %s',
|
||||
'Contents' => 'Contents'
|
||||
);
|
9
manual/new/lang/fi.php
Normal file
9
manual/new/lang/fi.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
$lang['fi'] = array(
|
||||
'Table of Contents' => 'Sisällysluettelo',
|
||||
'Contents' => 'Sisältö',
|
||||
'List of Chapters' => 'Luvut',
|
||||
'Previous' => 'Edellinen',
|
||||
'Next' => 'Seuraava'
|
||||
);
|
248
manual/new/scripts/tree.js
Normal file
248
manual/new/scripts/tree.js
Normal file
@ -0,0 +1,248 @@
|
||||
var symbolClosed = '+';
|
||||
var symbolOpen = '-';
|
||||
//var symbolClosed = '▹';
|
||||
//var symbolOpen = '▿';
|
||||
|
||||
function Tree_AutoInit()
|
||||
{
|
||||
var candidates = document.getElementsByTagName('ul');
|
||||
|
||||
for (i in candidates) {
|
||||
if (HasClassName(candidates[i], 'tree')) {
|
||||
Tree_Init(candidates[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Tree_Init(element)
|
||||
{
|
||||
for (var i in element.childNodes) {
|
||||
|
||||
var li = element.childNodes[i];
|
||||
|
||||
if (li.tagName && li.tagName.toLowerCase() == 'li') {
|
||||
|
||||
var subTree = Tree_FindChild(li, 'ul');
|
||||
|
||||
if (subTree) {
|
||||
var expander = document.createElement('a');
|
||||
|
||||
expander.className = 'expander';
|
||||
expander.href = 'javascript:void(0);';
|
||||
expander.onclick = Tree_Toggle;
|
||||
|
||||
if (HasClassName(subTree, 'closed')) {
|
||||
expander.innerHTML = symbolClosed;
|
||||
} else {
|
||||
expander.innerHTML = symbolOpen;
|
||||
}
|
||||
|
||||
li.insertBefore(expander, li.firstChild);
|
||||
|
||||
Tree_Init(subTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Tree_FindChild(element, childTag)
|
||||
{
|
||||
for (i in element.childNodes) {
|
||||
child = element.childNodes[i];
|
||||
if (child.tagName && child.tagName.toLowerCase() == childTag) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function Tree_Toggle()
|
||||
{
|
||||
expander = this;
|
||||
li = expander.parentNode;
|
||||
subTree = Tree_FindChild(li, 'ul');
|
||||
|
||||
if (HasClassName(subTree, 'closed')) {
|
||||
RemoveClassName(subTree, 'closed');
|
||||
expander.innerHTML = symbolOpen;
|
||||
} else {
|
||||
AddClassName(subTree, 'closed');
|
||||
expander.innerHTML = symbolClosed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// HasClassName
|
||||
//
|
||||
// Description : returns boolean indicating whether the object has the class name
|
||||
// built with the understanding that there may be multiple classes
|
||||
//
|
||||
// Arguments:
|
||||
// objElement - element to manipulate
|
||||
// strClass - class name to add
|
||||
//
|
||||
function HasClassName(objElement, strClass)
|
||||
{
|
||||
|
||||
// if there is a class
|
||||
if ( objElement.className )
|
||||
{
|
||||
|
||||
// the classes are just a space separated list, so first get the list
|
||||
var arrList = objElement.className.split(' ');
|
||||
|
||||
// get uppercase class for comparison purposes
|
||||
var strClassUpper = strClass.toUpperCase();
|
||||
|
||||
// find all instances and remove them
|
||||
for ( var i = 0; i < arrList.length; i++ )
|
||||
{
|
||||
|
||||
// if class found
|
||||
if ( arrList[i].toUpperCase() == strClassUpper )
|
||||
{
|
||||
|
||||
// we found it
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if we got here then the class name is not there
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// AddClassName
|
||||
//
|
||||
// Description : adds a class to the class attribute of a DOM element
|
||||
// built with the understanding that there may be multiple classes
|
||||
//
|
||||
// Arguments:
|
||||
// objElement - element to manipulate
|
||||
// strClass - class name to add
|
||||
//
|
||||
function AddClassName(objElement, strClass, blnMayAlreadyExist)
|
||||
{
|
||||
// if there is a class
|
||||
if (objElement.className) {
|
||||
|
||||
// the classes are just a space separated list, so first get the list
|
||||
var arrList = objElement.className.split(' ');
|
||||
|
||||
// if the new class name may already exist in list
|
||||
if (blnMayAlreadyExist) {
|
||||
|
||||
// get uppercase class for comparison purposes
|
||||
var strClassUpper = strClass.toUpperCase();
|
||||
|
||||
// find all instances and remove them
|
||||
for (var i = 0; i < arrList.length; i++) {
|
||||
|
||||
// if class found
|
||||
if (arrList[i].toUpperCase() == strClassUpper) {
|
||||
|
||||
// remove array item
|
||||
arrList.splice(i, 1);
|
||||
|
||||
// decrement loop counter as we have adjusted the array's contents
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the new class to end of list
|
||||
arrList[arrList.length] = strClass;
|
||||
|
||||
// add the new class to beginning of list
|
||||
//arrList.splice(0, 0, strClass);
|
||||
|
||||
// assign modified class name attribute
|
||||
objElement.className = arrList.join(' ');
|
||||
|
||||
// if there was no class
|
||||
} else {
|
||||
// assign modified class name attribute
|
||||
objElement.className = strClass;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// RemoveClassName
|
||||
//
|
||||
// Description : removes a class from the class attribute of a DOM element
|
||||
// built with the understanding that there may be multiple classes
|
||||
//
|
||||
// Arguments:
|
||||
// objElement - element to manipulate
|
||||
// strClass - class name to remove
|
||||
//
|
||||
function RemoveClassName(objElement, strClass)
|
||||
{
|
||||
|
||||
// if there is a class
|
||||
if ( objElement.className )
|
||||
{
|
||||
|
||||
// the classes are just a space separated list, so first get the list
|
||||
var arrList = objElement.className.split(' ');
|
||||
|
||||
// get uppercase class for comparison purposes
|
||||
var strClassUpper = strClass.toUpperCase();
|
||||
|
||||
// find all instances and remove them
|
||||
for ( var i = 0; i < arrList.length; i++ )
|
||||
{
|
||||
|
||||
// if class found
|
||||
if ( arrList[i].toUpperCase() == strClassUpper )
|
||||
{
|
||||
|
||||
// remove array item
|
||||
arrList.splice(i, 1);
|
||||
|
||||
// decrement loop counter as we have adjusted the array's contents
|
||||
i--;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// assign modified class name attribute
|
||||
objElement.className = arrList.join(' ');
|
||||
|
||||
}
|
||||
// if there was no class
|
||||
// there is nothing to remove
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handlers for automated loading
|
||||
*/
|
||||
_LOADERS = Array();
|
||||
|
||||
function callAllLoaders() {
|
||||
var i, loaderFunc;
|
||||
for(i=0;i<_LOADERS.length;i++) {
|
||||
loaderFunc = _LOADERS[i];
|
||||
if(loaderFunc != callAllLoaders) loaderFunc();
|
||||
}
|
||||
}
|
||||
|
||||
function appendLoader(loaderFunc) {
|
||||
if(window.onload && window.onload != callAllLoaders)
|
||||
_LOADERS[_LOADERS.length] = window.onload;
|
||||
|
||||
window.onload = callAllLoaders;
|
||||
|
||||
_LOADERS[_LOADERS.length] = loaderFunc;
|
||||
}
|
||||
|
||||
appendLoader(Tree_AutoInit);
|
217
manual/new/styles/basic.css
Normal file
217
manual/new/styles/basic.css
Normal file
@ -0,0 +1,217 @@
|
||||
body, html
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Arial", sans-serif;
|
||||
font-size: 11pt;
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
font-family: "Lucida Bright", "Times New Roman", serif;
|
||||
}
|
||||
|
||||
h1
|
||||
{
|
||||
text-align: center;
|
||||
font-size: 24pt;
|
||||
}
|
||||
|
||||
h2, #table-of-contents h1 {
|
||||
font-size: 18pt;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
p, ul, ol
|
||||
{
|
||||
line-height: 1.5em;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
ul ul, ol ol {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border: 1px solid #aaaaaa;
|
||||
border-collapse: collapse;
|
||||
margin: 0.5em 0;
|
||||
font-size: 11pt;
|
||||
background-color: #f9f9f9;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
td, th
|
||||
{
|
||||
padding: 0.2em;
|
||||
border: 1px solid #aaaaaa;
|
||||
}
|
||||
|
||||
th
|
||||
{
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
blockquote
|
||||
{
|
||||
background-image: url("../images/quotation-mark.png");
|
||||
background-position: top left;
|
||||
background-repeat: no-repeat;
|
||||
padding-left: 2.5em;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
|
||||
/*** Code blocks and highlighting**********************************************/
|
||||
|
||||
pre, tt
|
||||
{
|
||||
font-family: "Bitstream Vera Sans Mono", monospace;
|
||||
}
|
||||
|
||||
tt
|
||||
{
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
pre
|
||||
{
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
padding: 1em;
|
||||
margin: 1em;
|
||||
line-height: 1.2em;
|
||||
background-color: #f6f6f6;
|
||||
border: 1px solid #cccccc;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
pre .default
|
||||
{
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
pre .keyword
|
||||
{
|
||||
color: #3465a4;
|
||||
}
|
||||
|
||||
pre .string
|
||||
{
|
||||
color: #ef2929;
|
||||
}
|
||||
|
||||
pre .comment
|
||||
{
|
||||
color: #888a85;
|
||||
}
|
||||
|
||||
a:link
|
||||
{
|
||||
color: #3465a4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: #75507b;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:link:hover, a:link:active
|
||||
{
|
||||
text-decoration: underline;
|
||||
color: #729fcf;
|
||||
}
|
||||
|
||||
a:visited:hover, a:visited:active
|
||||
{
|
||||
text-decoration: underline;
|
||||
color: #ad7fa8;
|
||||
}
|
||||
|
||||
#table-of-contents {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 20em;
|
||||
overflow: auto;
|
||||
border: 1px solid #cccccc;
|
||||
background-color: #f6f6f6;
|
||||
padding: 0 1em;
|
||||
margin: 1em;
|
||||
max-height: 95%;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 23em;
|
||||
margin: 0;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
ul.tree, ul.tree ul {
|
||||
list-style-type: none;
|
||||
padding-left: 2em;
|
||||
text-align: left;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Tree specific styles ******************************************************/
|
||||
|
||||
.tree a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tree .expander {
|
||||
color: black;
|
||||
display: block;
|
||||
float: left;
|
||||
height: auto;
|
||||
margin-left: -1.25em;
|
||||
padding-left: 0;
|
||||
text-align: center;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
.tree .expander:link,
|
||||
.tree .expander:visited,
|
||||
.tree .expander:active,
|
||||
.tree .expander:hover {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tree ul.closed {
|
||||
display: none;
|
||||
}
|
6
manual/new/styles/iefix.css
Normal file
6
manual/new/styles/iefix.css
Normal file
@ -0,0 +1,6 @@
|
||||
#sidebar {
|
||||
/* IE5.5+/Win - this is more specific than the IE 5.0 version */
|
||||
left: auto; bottom: auto;
|
||||
right: expression( ( 20 + ( ignoreMe2 = document.documentElement.scrollRight ? document.documentElement.scrollRight : document.body.scrollRight ) ) + 'px' );
|
||||
top: expression( ( 10 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
|
||||
}
|
63
manual/new/styles/print.css
Normal file
63
manual/new/styles/print.css
Normal file
@ -0,0 +1,63 @@
|
||||
body {
|
||||
font-family: "Arial", sans-serif;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.chapter, #table-of-contents {
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "Lucida Bright", serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
p, ul, ol {
|
||||
text-align: justify;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
pre, tt {
|
||||
font-family: "Bitstream Vera Sans Mono", monospace;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
table {
|
||||
border: thin solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: thin solid black;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.expander {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#table-of-contents {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.one-page#table-of-contents {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#table-of-contents ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
33
manual/new/styles/tree.css
Normal file
33
manual/new/styles/tree.css
Normal file
@ -0,0 +1,33 @@
|
||||
ul.tree, ul.tree ul {
|
||||
list-style-type: none;
|
||||
padding-left: 2em;
|
||||
text-align: left;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.tree a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tree .expander {
|
||||
color: black;
|
||||
display: block;
|
||||
float: left;
|
||||
height: auto;
|
||||
margin-left: -1.25em;
|
||||
padding-left: 0;
|
||||
text-align: center;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
.tree .expander:link,
|
||||
.tree .expander:visited,
|
||||
.tree .expander:active,
|
||||
.tree .expander:hover {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tree ul.closed {
|
||||
display: none;
|
||||
}
|
56
manual/new/template.php
Normal file
56
manual/new/template.php
Normal file
@ -0,0 +1,56 @@
|
||||
<!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="en" lang="en">
|
||||
|
||||
<head>
|
||||
|
||||
<title><?php echo $title; ?></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="<?php echo $baseUrl; ?>styles/basic.css" media="screen"/>
|
||||
<link rel="stylesheet" type="text/css" href="<?php echo $baseUrl; ?>styles/print.css" media="print"/>
|
||||
|
||||
<!--[if gte IE 5.5]>
|
||||
<![if lt IE 7]>
|
||||
<link rel="stylesheet" type="text/css" href="<?php echo $baseUrl; ?>styles/iefix.css"/>
|
||||
<![endif]>
|
||||
<![endif]-->
|
||||
|
||||
<script type="text/javascript" src="<?php echo $baseUrl; ?>scripts/tree.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="wrap">
|
||||
|
||||
<div id="sidebar">
|
||||
<?php $tool->renderToc(); ?>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<?php
|
||||
|
||||
try {
|
||||
$tool->render();
|
||||
} catch (Exception $e) {
|
||||
?>
|
||||
|
||||
<h1>Doctrine Documentation</h1>
|
||||
|
||||
<p>You can view this documentation as
|
||||
<ul>
|
||||
<li><a href="<?php echo $tool->getOption('clean-url') ? "${baseUrl}one-page" : '?one-page=1'; ?>">everything on a single page</a>, or</li>
|
||||
<li><a href="<?php echo $tool->makeUrl($tool->findByIndex('1.')->getPath()); ?>">one chapter per page</a>.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
136
vendor/Sensei/Sensei.php
vendored
Normal file
136
vendor/Sensei/Sensei.php
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.com>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sensei
|
||||
*
|
||||
* @package Sensei
|
||||
* @category Core
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL
|
||||
* @link http://sourceforge.net/projects/sensei
|
||||
* @author Janne Vanhala <jpvanhal@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @version $Revision$
|
||||
* @since 1.0
|
||||
*/
|
||||
final class Sensei {
|
||||
/**
|
||||
* @var string $path doctrine root directory
|
||||
*/
|
||||
private static $path;
|
||||
/**
|
||||
* getPath
|
||||
* returns the doctrine root
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getPath()
|
||||
{
|
||||
if (! self::$path) {
|
||||
self::$path = dirname(__FILE__);
|
||||
}
|
||||
return self::$path;
|
||||
}
|
||||
/**
|
||||
* simple autoload function
|
||||
* returns true if the class was loaded, otherwise false
|
||||
*
|
||||
* @param string $classname
|
||||
* @return boolean
|
||||
*/
|
||||
public static function autoload($classname)
|
||||
{
|
||||
if (class_exists($classname, false)) {
|
||||
return false;
|
||||
}
|
||||
if ( ! self::$path) {
|
||||
self::$path = dirname(__FILE__);
|
||||
}
|
||||
$class = self::$path . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $classname) . '.php';
|
||||
|
||||
if ( ! file_exists($class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require_once($class);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a given class: a file name is acquired by naively transforming
|
||||
* underscores into directory separators and appending the .php suffix.
|
||||
*
|
||||
* The file is searched for in every directory in the include path.
|
||||
*
|
||||
* @param string class name
|
||||
* @param boolean allow class to be autoloaded before attempt
|
||||
* @return true
|
||||
* @throws Xi_Exception if the class could not be loaded
|
||||
*/
|
||||
public static function loadClass($className)
|
||||
{
|
||||
if (class_exists($className, false)) {
|
||||
return false;
|
||||
}
|
||||
if (! self::$path) {
|
||||
self::$path = dirname(__FILE__);
|
||||
}
|
||||
$class = self::$path . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
|
||||
|
||||
if ( ! file_exists($class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require_once($class);
|
||||
|
||||
throw new Sensei_Exception('Class ' . $className . ' does not exist and could not '
|
||||
. 'be loaded.');
|
||||
}
|
||||
/**
|
||||
* Create a new instance of a class.
|
||||
*
|
||||
* @param string class name
|
||||
* @param array constructor arguments, optional
|
||||
* @return object
|
||||
*/
|
||||
public static function create($class, array $args = array())
|
||||
{
|
||||
/**
|
||||
* An arbitrary amount of constructor arguments can be achieved using
|
||||
* reflection, but it's slower by an order of magnitude. Manually handle
|
||||
* instantiation for up to three arguments.
|
||||
*/
|
||||
switch (count($args)) {
|
||||
case 0:
|
||||
return new $class;
|
||||
case 1:
|
||||
return new $class($args[0]);
|
||||
case 2:
|
||||
return new $class($args[0], $args[1]);
|
||||
case 3:
|
||||
return new $class($args[0], $args[1], $args[2]);
|
||||
default:
|
||||
return call_user_func_array(array(new ReflectionClass($class),'newInstance'),
|
||||
$args);
|
||||
}
|
||||
}
|
||||
}
|
384
vendor/Sensei/Sensei/Doc/Section.php
vendored
Normal file
384
vendor/Sensei/Sensei/Doc/Section.php
vendored
Normal file
@ -0,0 +1,384 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://sourceforge.net/projects/sensei>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sensei_Doc_Section
|
||||
*
|
||||
* @package Sensei_Doc
|
||||
* @category Documentation
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL
|
||||
* @link http://sourceforge.net/projects/sensei
|
||||
* @author Janne Vanhala <jpvanhal@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @version $Revision$
|
||||
* @since 1.0
|
||||
*/
|
||||
class Sensei_Doc_Section implements Countable
|
||||
{
|
||||
/**
|
||||
* Name of the section
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_name;
|
||||
|
||||
/**
|
||||
* The index of this section among the subsections of its parent. The index
|
||||
* ranges from 0 to the number of subsections the parent has minus one.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_index;
|
||||
|
||||
/**
|
||||
* Array containing the subsections of this section.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_children = array();
|
||||
|
||||
/**
|
||||
* The parent of this section.
|
||||
*
|
||||
* @var Sensei_Doc_Section
|
||||
*/
|
||||
private $_parent;
|
||||
|
||||
/**
|
||||
* Level of this section in section hierarchy.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $_level = 0;
|
||||
|
||||
/**
|
||||
* Text contents of this section.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_text = '';
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new section.
|
||||
*
|
||||
* @param string $name name of the section
|
||||
* @param Sensei_Doc_Section $parent parent of the section
|
||||
*/
|
||||
public function __construct($name = null, $parent = null)
|
||||
{
|
||||
$this->_name = $name;
|
||||
$this->_parent = $parent;
|
||||
|
||||
if ($parent !== null) {
|
||||
$this->_parent->addChild($this);
|
||||
$this->_level = $this->_parent->_level + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a subsection to this section.
|
||||
*
|
||||
* @param Sensei_Doc_Section $child
|
||||
*/
|
||||
protected function addChild(Sensei_Doc_Section $child)
|
||||
{
|
||||
$child->_index = count($this);
|
||||
$this->_children[] = $child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of this section.
|
||||
*
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
public function getIndex($separator = '.')
|
||||
{
|
||||
if ($this->_parent->_name !== null) {
|
||||
return $this->_parent->getIndex($separator) . ($this->_index + 1) . $separator;
|
||||
} else {
|
||||
return ($this->_index + 1) . $separator;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of this section.
|
||||
*
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
public function getPath($short = false, $separator = ':')
|
||||
{
|
||||
if ( ! $short && ! $this->_parent->isRoot()) {
|
||||
return $this->_parent->getPath($short, $separator) . $separator . $this->getPath(true);
|
||||
} else {
|
||||
$patterns = array('/\s/', '/[^a-z0-9-]/');
|
||||
$replacements = array('-', '');
|
||||
|
||||
$path = preg_replace($patterns, $replacements, strtolower($this->_name));
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this section.
|
||||
*
|
||||
* @param boolean $full
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
public function getName($full = false, $separator = ' - ')
|
||||
{
|
||||
if ($full && ! $this->_parent->isRoot()) {
|
||||
return $this->_parent->getName($full, $separator) . $separator . $this->_name;
|
||||
} else {
|
||||
return $this->_name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many subsections this section has.
|
||||
*
|
||||
* @return int number of subsections
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->_children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subsection that has the given index.
|
||||
*
|
||||
* The index ranges from 0 to the number of subsections this section has
|
||||
* minus one.
|
||||
*
|
||||
* @param int $index index of the subsection
|
||||
* @return Sensei_Doc_Section The subsection with given index.
|
||||
*/
|
||||
public function getChild($index)
|
||||
{
|
||||
return $this->_children[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent of this section.
|
||||
*
|
||||
* @return Sensei_Doc_Section
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
if ($this->_parent->isRoot()) {
|
||||
return null;
|
||||
} else {
|
||||
return $this->_parent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next section.
|
||||
*
|
||||
* If this section has subsections and their level is at most the specified
|
||||
* maximum level, the next section is the first subsection of this section.
|
||||
*
|
||||
* If this section is not the last subsection of its parent and level of
|
||||
* this section is at most the specified maximum level, the next section is
|
||||
* the next section at the same level as this.
|
||||
*
|
||||
* Otherwise the next section is the next section of the parent that is on
|
||||
* the same level as the parent.
|
||||
*
|
||||
* @param int $maxLevel The maximum level that the next section can have.
|
||||
* If maximum level is 0 (default), this parameter is
|
||||
* discarded.
|
||||
*
|
||||
* @return Sensei_Doc_Section|null The next section, or null if not
|
||||
* available.
|
||||
*/
|
||||
public function next($maxLevel = 0)
|
||||
{
|
||||
if ($this->isRoot()) {
|
||||
|
||||
return null;
|
||||
|
||||
} else {
|
||||
|
||||
if ((!$maxLevel || ($this->_level < $maxLevel))
|
||||
&& (count($this) > 0)) {
|
||||
return $this->getChild(0);
|
||||
}
|
||||
|
||||
if ((!$maxLevel || ($this->_level <= $maxLevel) )
|
||||
&& ($this->_index < count($this->_parent) - 1)) {
|
||||
return $this->_parent->getChild($this->_index + 1);
|
||||
}
|
||||
|
||||
return $this->_parent->next($this->_parent->_level);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous section.
|
||||
*
|
||||
* @return Sensei_Doc_Section
|
||||
*/
|
||||
public function previous($maxLevel = 0)
|
||||
{
|
||||
if ($maxLevel > 0 && $this->_level > $maxLevel) {
|
||||
$previous = $this;
|
||||
while ($previous->_level > $maxLevel) {
|
||||
$previous = $previous->getParent();
|
||||
}
|
||||
return $previous;
|
||||
}
|
||||
|
||||
if ($this->_index === 0) {
|
||||
return $this->getParent();
|
||||
} else {
|
||||
$previousSibling = $this->_parent->getChild($this->_index - 1);
|
||||
return $previousSibling->findLastChild($maxLevel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the last child or grand child of this section.
|
||||
*
|
||||
* If this section has no children, this section is returned.
|
||||
*
|
||||
* @param int $maxLevel Specifies the maximum level that the algorithm will
|
||||
* traverse to. If maximum level is 0 (default), the
|
||||
* algorithm will go as deep as possible.
|
||||
* @return Sensei_Doc_Section
|
||||
*/
|
||||
public function findLastChild($maxLevel = 0)
|
||||
{
|
||||
if ((!$maxLevel || $this->_level < $maxLevel) && count($this) > 0) {
|
||||
return $this->getChild(count($this) - 1)->findLastChild();
|
||||
} else {
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if this section is the root section.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRoot()
|
||||
{
|
||||
return $this->_parent === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the level of this section in section hierarchy.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLevel()
|
||||
{
|
||||
return $this->_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text contents of this section.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->_text;
|
||||
}
|
||||
|
||||
public function parse($path, $filename)
|
||||
{
|
||||
$file = file($path . DIRECTORY_SEPARATOR . $filename);
|
||||
$current = $this;
|
||||
|
||||
foreach ($file as $lineNum => $line) {
|
||||
|
||||
// Checks if the line is a heading
|
||||
if (preg_match('/^(\+{1,6}) (.*)/', trim($line), $matches)) {
|
||||
|
||||
$level = strlen($matches[1]);
|
||||
$heading = $matches[2];
|
||||
|
||||
if (($level > $this->getLevel()) && ($level <= $current->getLevel() + 1)) {
|
||||
|
||||
// The current section did not have any text in this file.
|
||||
// Let's assume that the text is defined in another file.
|
||||
if (!$current->isRoot() && $current->_text === '') {
|
||||
|
||||
$otherFilename = $current->getPath(false, DIRECTORY_SEPARATOR) . '.txt';
|
||||
|
||||
if (($filename !== $otherFilename)
|
||||
&& (file_exists($path . DIRECTORY_SEPARATOR . $otherFilename))) {
|
||||
$current->parse($path, $otherFilename);
|
||||
}
|
||||
}
|
||||
|
||||
$parent = $current;
|
||||
|
||||
while ($parent->getLevel() >= $level) {
|
||||
$parent = $parent->_parent;
|
||||
}
|
||||
|
||||
$current = new Sensei_Doc_Section($heading, $parent);
|
||||
|
||||
} else {
|
||||
|
||||
$format = 'Section has no direct parent, or level of the '
|
||||
. 'heading is not greater than the level of the '
|
||||
. 'file in "%s" on line %d';
|
||||
|
||||
$message = sprintf($format, $filename, $lineNum);
|
||||
|
||||
throw new Sensei_Exception($message);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ($current->_text === '') {
|
||||
if (trim($line) !== '') {
|
||||
$current->_text = $line;
|
||||
}
|
||||
} else {
|
||||
$current->_text .= $line;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// The last section did not have any text in this file.
|
||||
// Let's assume that the text is defined in another file.
|
||||
if (!$current->isRoot() && $current->_text === '') {
|
||||
|
||||
$otherFilename = $current->getPath() . '.php';
|
||||
|
||||
if (($filename !== $otherFilename)
|
||||
&& (file_exists($path . DIRECTORY_SEPARATOR . $otherFilename))) {
|
||||
$current->parse($path, $otherFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
132
vendor/Sensei/Sensei/Doc/Toc.php
vendored
Normal file
132
vendor/Sensei/Sensei/Doc/Toc.php
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://sourceforge.net/projects/sensei>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sensei_Doc_Toc
|
||||
*
|
||||
* @package Sensei_Doc
|
||||
* @category Documentation
|
||||
* @license http://www.gnu.org/licenses/lgpl.txt LGPL
|
||||
* @link http://sourceforge.net/projects/sensei
|
||||
* @author Janne Vanhala <jpvanhal@cc.hut.fi>
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @version $Revision$
|
||||
* @since 1.0
|
||||
*/
|
||||
class Sensei_Doc_Toc implements Countable
|
||||
{
|
||||
/**
|
||||
* An empty (root) section that contains all other sections.
|
||||
*
|
||||
* @var Sensei_Doc_Section
|
||||
*/
|
||||
private $_toc;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new table of contents from a file
|
||||
*
|
||||
* @param string $filename Name of the file that contains the section
|
||||
* structure.
|
||||
*/
|
||||
public function __construct($filename)
|
||||
{
|
||||
$this->_toc = new Sensei_Doc_Section();
|
||||
$this->_toc->parse(dirname($filename), basename($filename));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the section that matches the given path.
|
||||
*
|
||||
* The path consists of section names, where spaces are replaced by
|
||||
* underscores, and which separated by '/' (default).
|
||||
*
|
||||
* @param string $path Path
|
||||
* @param string $separator A string that separates section names in path.
|
||||
* @return Sensei_Doc_Section|null A section that matches the given path, or
|
||||
* null if no matching section was found.
|
||||
*/
|
||||
public function findByPath($path, $separator = ':')
|
||||
{
|
||||
$sectionPaths = explode($separator, $path);
|
||||
$currentSection = $this->_toc;
|
||||
|
||||
foreach ($sectionPaths as $sectionPath) {
|
||||
|
||||
$found = false;
|
||||
|
||||
for ($i = 0; $i < $currentSection->count(); $i++) {
|
||||
if ($currentSection->getChild($i)->getPath(true, $separator) === $sectionPath) {
|
||||
$currentSection = $currentSection->getChild($i);
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $found) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return $currentSection;
|
||||
}
|
||||
|
||||
public function findByIndex($index, $separator = '.')
|
||||
{
|
||||
$indexes = explode($separator, $index);
|
||||
$currentSection = $this->_toc;
|
||||
|
||||
if (end($indexes) === '') {
|
||||
array_pop($indexes);
|
||||
}
|
||||
|
||||
foreach ($indexes as $i) {
|
||||
try {
|
||||
$currentSection = $currentSection->getChild((int) $i - 1);
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return $currentSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a root section with the given index.
|
||||
*
|
||||
* @param int $index
|
||||
* @return Sensei_Doc_Section
|
||||
*/
|
||||
public function getChild($index)
|
||||
{
|
||||
return $this->_toc->getChild($index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of sections (excluding their subsections).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->_toc->count();
|
||||
}
|
||||
}
|
4
vendor/Text/Wiki/Render/Xhtml/Bold.php
vendored
4
vendor/Text/Wiki/Render/Xhtml/Bold.php
vendored
@ -46,11 +46,11 @@ class Text_Wiki_Render_Xhtml_Bold extends Text_Wiki_Render {
|
||||
{
|
||||
if ($options['type'] == 'start') {
|
||||
$css = $this->formatConf(' class="%s"', 'css');
|
||||
return "<b$css>";
|
||||
return "<strong$css>";
|
||||
}
|
||||
|
||||
if ($options['type'] == 'end') {
|
||||
return '</b>';
|
||||
return '</strong>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
41
vendor/Text/Wiki/Render/Xhtml/Code.php
vendored
41
vendor/Text/Wiki/Render/Xhtml/Code.php
vendored
@ -59,38 +59,39 @@ class Text_Wiki_Render_Xhtml_Code extends Text_Wiki_Render {
|
||||
$css_filename = $this->formatConf(' class="%s"', 'css_filename');
|
||||
|
||||
if ($type == 'php') {
|
||||
|
||||
if (substr($options['text'], 0, 5) != '<?php') {
|
||||
// PHP code example:
|
||||
// add the PHP tags
|
||||
$text = "<?php
|
||||
" . $options['text'] . "\n?>"; // <?php
|
||||
$text = "<?php \n"
|
||||
. $options['text'] . "\n\n"
|
||||
. "?>";
|
||||
}
|
||||
|
||||
// convert tabs to four spaces
|
||||
$text = str_replace("\t", " %nbsp; ", $text);
|
||||
$text = str_replace("\t", " ", $text);
|
||||
|
||||
// colorize the code block (also converts HTML entities and adds
|
||||
// <code>...</code> tags)
|
||||
$h = new PHP_Highlight;
|
||||
$h = new PHP_Highlight(true);
|
||||
$h->loadString($text);
|
||||
$text = $h->toHtml(true);
|
||||
|
||||
|
||||
// replace <br /> tags with simple newlines.
|
||||
// replace non-breaking space with simple spaces.
|
||||
// translate HTML <font> and color to XHTML <span> and style.
|
||||
// courtesy of research by A. Kalin :-).
|
||||
/**
|
||||
|
||||
$map = array(
|
||||
'<br />' => "\n",
|
||||
' ' => ' ',
|
||||
"\n" => "<br \>",
|
||||
'<font' => '<span',
|
||||
'</font>' => '</span>',
|
||||
'color="' => 'style="color:'
|
||||
' ' => ' '
|
||||
//'<br />' => "\n",
|
||||
//"\n" => "<br \>",
|
||||
//'<font' => '<span',
|
||||
//'</font>' => '</span>',
|
||||
//'color="' => 'style="color:'
|
||||
);
|
||||
|
||||
|
||||
$text = strtr($text, $map);
|
||||
*/
|
||||
|
||||
// get rid of the last newline inside the code block
|
||||
// (becuase higlight_string puts one there)
|
||||
@ -104,10 +105,10 @@ class Text_Wiki_Render_Xhtml_Code extends Text_Wiki_Render {
|
||||
}
|
||||
|
||||
// done
|
||||
$text = "<table border=1 class='dashed' cellpadding=0 cellspacing=0>
|
||||
/*$text = "<table border=1 class='dashed' cellpadding=0 cellspacing=0>
|
||||
<tr><td><b>$text
|
||||
</b></td></tr>
|
||||
</table>";
|
||||
</table>";*/
|
||||
|
||||
} elseif ($type == 'html' || $type == 'xhtml') {
|
||||
|
||||
@ -116,9 +117,9 @@ class Text_Wiki_Render_Xhtml_Code extends Text_Wiki_Render {
|
||||
// convert tabs to four spaces,
|
||||
// convert entities.
|
||||
$text = str_replace("\t", " ", $text);
|
||||
$text = "<html>\n$text\n</html>";
|
||||
//$text = "<html>\n$text\n</html>";
|
||||
$text = $this->textEncode($text);
|
||||
$text = "<pre$css><code$css_html>$text</code></pre>";
|
||||
$text = "<pre$css>$text</pre>";
|
||||
|
||||
} elseif ($type == 'sql') {
|
||||
// HTML code example:
|
||||
@ -127,14 +128,14 @@ class Text_Wiki_Render_Xhtml_Code extends Text_Wiki_Render {
|
||||
// convert entities.
|
||||
$text = str_replace("\t", " ", $text);
|
||||
$text = $this->textEncode($text);
|
||||
$text = "<div class='sql'>$text</div>";
|
||||
$text = "<pre class=\"sql\">$text</pre>";
|
||||
} else {
|
||||
// generic code example:
|
||||
// convert tabs to four spaces,
|
||||
// convert entities.
|
||||
$text = str_replace("\t", " ", $text);
|
||||
$text = $this->textEncode($text);
|
||||
$text = "<pre$css><code$css_code>$text</code></pre>";
|
||||
$text = "<pre$css>$text</pre>";
|
||||
}
|
||||
|
||||
if ($css_filename && isset($attr['filename'])) {
|
||||
|
4
vendor/Text/Wiki/Render/Xhtml/Italic.php
vendored
4
vendor/Text/Wiki/Render/Xhtml/Italic.php
vendored
@ -46,11 +46,11 @@ class Text_Wiki_Render_Xhtml_Italic extends Text_Wiki_Render {
|
||||
{
|
||||
if ($options['type'] == 'start') {
|
||||
$css = $this->formatConf(' class="%s"', 'css');
|
||||
return "<i$css>";
|
||||
return "<em$css>";
|
||||
}
|
||||
|
||||
if ($options['type'] == 'end') {
|
||||
return '</i>';
|
||||
return '</em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
vendor/Text/Wiki/Render/Xhtml/Underline.php
vendored
4
vendor/Text/Wiki/Render/Xhtml/Underline.php
vendored
@ -46,11 +46,11 @@ class Text_Wiki_Render_Xhtml_Underline extends Text_Wiki_Render {
|
||||
{
|
||||
if ($options['type'] == 'start') {
|
||||
$css = $this->formatConf(' class="%s"', 'css');
|
||||
return "<u$css>";
|
||||
return "<span style=\"text-decoration: underline;\"$css>";
|
||||
}
|
||||
|
||||
if ($options['type'] == 'end') {
|
||||
return '</u>';
|
||||
return '</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
vendor/Text/Wiki/Render/Xhtml/Url.php
vendored
2
vendor/Text/Wiki/Render/Xhtml/Url.php
vendored
@ -93,6 +93,7 @@ class Text_Wiki_Render_Xhtml_Url extends Text_Wiki_Render {
|
||||
$css = $this->formatConf(' class="%s"', "css_$type");
|
||||
$output = "<a$css href=\"$href\"";
|
||||
|
||||
/*
|
||||
if ($target) {
|
||||
// use a "popup" window. this is XHTML compliant, suggested by
|
||||
// Aaron Kalin. uses the $target as the new window name.
|
||||
@ -100,6 +101,7 @@ class Text_Wiki_Render_Xhtml_Url extends Text_Wiki_Render {
|
||||
$output .= " onclick=\"window.open(this.href, '$target');";
|
||||
$output .= " return false;\"";
|
||||
}
|
||||
*/
|
||||
|
||||
// finish up output
|
||||
$output .= ">$text</a>";
|
||||
|
Loading…
Reference in New Issue
Block a user