Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

updated props & phpDoc

  • Loading branch information...
commit c13ed82c2f170f89cd380b399fe4528d50f064d7 0 parents
David Grudl dg authored
Showing with 12,953 additions and 0 deletions.
  1. +177 −0 Nette/Collections/ArrayList.php
  2. +266 −0 Nette/Collections/Collection.php
  3. +227 −0 Nette/Collections/Hashtable.php
  4. +42 −0 Nette/Collections/ICollection.php
  5. +41 −0 Nette/Collections/IList.php
  6. +42 −0 Nette/Collections/IMap.php
  7. +34 −0 Nette/Collections/ISet.php
  8. +101 −0 Nette/Collections/Set.php
  9. +334 −0 Nette/Component.php
  10. +221 −0 Nette/ComponentContainer.php
  11. +203 −0 Nette/Config.php
  12. +269 −0 Nette/ConfigAdapters.php
  13. +443 −0 Nette/Debug.php
  14. +410 −0 Nette/Environment.php
  15. +41 −0 Nette/ICausedException.php
  16. +67 −0 Nette/IComponent.php
  17. +63 −0 Nette/IComponentContainer.php
  18. +41 −0 Nette/IDebuggable.php
  19. +314 −0 Nette/IO/SafeStream.php
  20. +55 −0 Nette/IServiceLocator.php
  21. +118 −0 Nette/Loaders/AutoLoader.php
  22. +138 −0 Nette/Loaders/NetteLoader.php
  23. +275 −0 Nette/Loaders/RobotLoader.php
  24. +60 −0 Nette/Loaders/SimpleLoader.php
  25. +280 −0 Nette/Object.php
  26. +42 −0 Nette/Security/AuthenticationException.php
  27. +45 −0 Nette/Security/IAuthenticator.php
  28. +45 −0 Nette/Security/IAuthorizator.php
  29. +47 −0 Nette/Security/IIdentity.php
  30. +97 −0 Nette/Security/Identity.php
  31. +1,014 −0 Nette/Security/Permission.php
  32. +82 −0 Nette/Security/SimpleAuthenticator.php
  33. +201 −0 Nette/ServiceLocator.php
  34. +58 −0 Nette/String.php
  35. +198 −0 Nette/Tools.php
  36. +30 −0 Nette/Version.php
  37. +508 −0 Nette/Web/Html.php
  38. +677 −0 Nette/Web/HttpRequest.php
  39. +244 −0 Nette/Web/HttpResponse.php
  40. +141 −0 Nette/Web/IHttpRequest.php
  41. +72 −0 Nette/Web/IHttpResponse.php
  42. +507 −0 Nette/Web/Session.php
  43. +215 −0 Nette/Web/SessionNamespace.php
  44. +318 −0 Nette/Web/User.php
  45. +118 −0 Nette/exceptions.php
  46. +24 −0 Nette/loader.php
  47. +36 −0 Nette/templates/Debug.closepanel.phtml
  48. +38 −0 Nette/templates/Debug.openpanel.phtml
  49. +398 −0 Nette/templates/Debug.phtml
  50. +69 −0 license.cs.txt
  51. +61 −0 license.txt
  52. +19 −0 readme.txt
  53. +3 −0  tests/Collections/_test.bat
  54. +121 −0 tests/Collections/ref/test.ArrayList.php.html
  55. +58 −0 tests/Collections/ref/test.Collection.php.html
  56. +130 −0 tests/Collections/ref/test.Hashtable.php.html
  57. +86 −0 tests/Collections/ref/test.Set.php.html
  58. +247 −0 tests/Collections/test.ArrayList.php
  59. +183 −0 tests/Collections/test.Collection.php
  60. +308 −0 tests/Collections/test.Hashtable.php
  61. +192 −0 tests/Collections/test.Set.php
  62. +3 −0  tests/Debug/_test.bat
  63. +51 −0 tests/Debug/ref/test.dump.php.html
  64. +3 −0  tests/Debug/ref/test.error.php.html
  65. +431 −0 tests/Debug/ref/test.exception.html.php.html
  66. +8 −0 tests/Debug/ref/test.exception.php.html
  67. +393 −0 tests/Debug/ref/test.filter.php.html
  68. +4 −0 tests/Debug/ref/test.notice.php.html
  69. +4 −0 tests/Debug/ref/test.timer.php.html
  70. +4 −0 tests/Debug/ref/test.warning.php.html
  71. +44 −0 tests/Debug/test.dump.php
  72. +30 −0 tests/Debug/test.error.php
  73. +33 −0 tests/Debug/test.exception.html.php
  74. +30 −0 tests/Debug/test.exception.php
  75. +24 −0 tests/Debug/test.filter.php
  76. +32 −0 tests/Debug/test.notice.php
  77. +13 −0 tests/Debug/test.timer.php
  78. +32 −0 tests/Debug/test.warning.php
  79. +20 −0 tests/IO.SafeStream/demo.php
  80. +90 −0 tests/IO.SafeStream/stress.php
  81. +3 −0  tests/Loaders/_test.bat
  82. +5 −0 tests/Loaders/ref/test.NetteLoader.php.html
  83. +5 −0 tests/Loaders/ref/test.RobotLoader.php.html
  84. +5 −0 tests/Loaders/ref/test.SimpleLoader.php.html
  85. +12 −0 tests/Loaders/test.NetteLoader.php
  86. +17 −0 tests/Loaders/test.RobotLoader.php
  87. +16 −0 tests/Loaders/test.SimpleLoader.php
  88. +3 −0  tests/Object/_test.bat
  89. +14 −0 tests/Object/_testall.bat
  90. +14 −0 tests/Object/ref/test.events.php.html
  91. +8 −0 tests/Object/ref/test.extends.php.html
  92. +40 −0 tests/Object/ref/test.property.php.html
  93. +50 −0 tests/Object/ref/test.reflection.php.html
  94. +96 −0 tests/Object/test.events.php
  95. +52 −0 tests/Object/test.extends.php
  96. +139 −0 tests/Object/test.property.php
  97. +32 −0 tests/Object/test.reflection.php
  98. +3 −0  tests/Web.Html/_test.bat
  99. +22 −0 tests/Web.Html/ref/test.html.php.html
  100. +22 −0 tests/Web.Html/ref/test.xhtml.php.html
  101. +8 −0 tests/Web.Html/test.html.php
  102. +94 −0 tests/Web.Html/test.xhtml.php
  103. +5 −0 tests/Web.HttpRequest/_test.bat
  104. +49 −0 tests/Web.HttpRequest/ref/test.httpRequest.php.html
  105. +53 −0 tests/Web.HttpRequest/ref/test.httpRequest.php.wget.html
  106. +39 −0 tests/Web.HttpRequest/test.httpRequest.php
  107. +4 −0 version.txt
177 Nette/Collections/ArrayList.php
@@ -0,0 +1,177 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+require_once dirname(__FILE__) . '/../Collections/Collection.php';
+
+require_once dirname(__FILE__) . '/../Collections/IList.php';
+
+
+
+/**
+ * Provides the base class for a generic list (items can be accessed by index).
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+class ArrayList extends Collection implements IList
+{
+ /** @var int */
+ protected $base = 0;
+
+
+ /**
+ * Inserts the specified element at the specified position in this list.
+ * @param int
+ * @param mixed
+ * @return bool
+ * @throws ::ArgumentOutOfRangeException
+ */
+ public function insertAt($index, $item)
+ {
+ $index -= $this->base;
+ if ($index < 0 || $index > count($this->data)) {
+ throw new /*::*/ArgumentOutOfRangeException;
+ }
+
+ $this->beforeAdd($item);
+ array_splice($this->data, (int) $index, 0, array($item));
+ return TRUE;
+ }
+
+
+
+ /**
+ * Removes the first occurrence of the specified element.
+ * @param mixed
+ * @return bool true if this list changed as a result of the call
+ * @throws ::NotSupportedException
+ */
+ public function remove($item)
+ {
+ $this->beforeRemove();
+
+ $index = $this->search($item);
+ if ($index === FALSE) {
+ return FALSE;
+ } else {
+ array_splice($this->data, $index, 1);
+ return TRUE;
+ }
+ }
+
+
+
+ /**
+ * Returns the index of the first occurrence of the specified element,.
+ * or FALSE if this list does not contain this element.
+ * @param mixed
+ * @return int|FALSE
+ */
+ public function indexOf($item)
+ {
+ $index = $this->search($item);
+ return $index === FALSE ? FALSE : $this->base + $index;
+ }
+
+
+
+ /********************* interface ::ArrayAccess ****************d*g**/
+
+
+
+ /**
+ * Replaces (or appends) the item (::ArrayAccess implementation).
+ * @param int index
+ * @param object
+ * @return void
+ * @throws ::InvalidArgumentException, ::NotSupportedException, ::ArgumentOutOfRangeException
+ */
+ public function offsetSet($index, $item)
+ {
+ $this->beforeAdd($item);
+
+ if ($index === NULL) { // append
+ $this->data[] = $item;
+
+ } else { // replace
+ $index -= $this->base;
+ if ($index < 0 || $index >= count($this->data)) {
+ throw new /*::*/ArgumentOutOfRangeException;
+ }
+ $this->data[$index] = $item;
+ }
+ }
+
+
+
+ /**
+ * Returns item (::ArrayAccess implementation).
+ * @param int index
+ * @return mixed
+ * @throws ::ArgumentOutOfRangeException
+ */
+ public function offsetGet($index)
+ {
+ $index -= $this->base;
+ if ($index < 0 || $index >= count($this->data)) {
+ throw new /*::*/ArgumentOutOfRangeException;
+ }
+
+ return $this->data[$index];
+ }
+
+
+
+ /**
+ * Exists item? (::ArrayAccess implementation).
+ * @param int index
+ * @return bool
+ */
+ public function offsetExists($index)
+ {
+ $index -= $this->base;
+ return $index >= 0 && $index < count($this->data);
+ }
+
+
+
+ /**
+ * Removes the element at the specified position in this list.
+ * @param int index
+ * @return void
+ * @throws ::NotSupportedException, ::ArgumentOutOfRangeException
+ */
+ public function offsetUnset($index)
+ {
+ $index -= $this->base;
+ if ($index < 0 || $index >= count($this->data)) {
+ throw new /*::*/ArgumentOutOfRangeException;
+ }
+
+ $this->beforeRemove();
+ array_splice($this->data, (int) $index, 1);
+ }
+
+}
266 Nette/Collections/Collection.php
@@ -0,0 +1,266 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+require_once dirname(__FILE__) . '/../Object.php';
+
+require_once dirname(__FILE__) . '/../Collections/ICollection.php';
+
+
+
+/**
+ * Provides the base class for a generic collection.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+class Collection extends /*Nette::*/Object implements ICollection
+{
+ /** @var array of objects */
+ protected $data = array();
+
+ /** @var string type (class, interface, PHP type) */
+ protected $itemType;
+
+ /** @var string function to verify type */
+ protected $checkFunc;
+
+ /** @var bool */
+ protected $readOnly = FALSE;
+
+
+
+ /**
+ * @param array to wrap
+ * @param string class/interface name or ':type'
+ * @throws ::InvalidArgumentException
+ */
+ public function __construct($arr = NULL, $type = NULL)
+ {
+ if (substr($type, 0, 1) === ':') {
+ $this->itemType = substr($type, 1);
+ $this->checkFunc = 'is_' . $this->itemType;
+ } else {
+ $this->itemType = $type;
+ }
+
+ if ($arr !== NULL) {
+ $this->import($arr);
+ }
+ }
+
+
+
+ /**
+ * Prevent any more modifications.
+ * @return void
+ */
+ public function setReadOnly()
+ {
+ $this->readOnly = TRUE;
+ }
+
+
+
+ /**
+ * Appends the specified element to the end of this collection.
+ * @param mixed
+ * @return bool true if this collection changed as a result of the call
+ * @throws ::InvalidArgumentException, ::NotSupportedException
+ */
+ public function add($item)
+ {
+ $this->beforeAdd($item);
+ $this->data[] = $item;
+ return TRUE;
+ }
+
+
+
+ /**
+ * Removes the first occurrence of the specified element.
+ * @param mixed
+ * @return bool true if this collection changed as a result of the call
+ * @throws ::NotSupportedException
+ */
+ public function remove($item)
+ {
+ $this->beforeRemove();
+ $index = $this->search($item);
+ if ($index === FALSE) {
+ return FALSE;
+ } else {
+ unset($this->data[$index]);
+ return TRUE;
+ }
+ }
+
+
+
+ /**
+ * Returns the index of the first occurrence of the specified element,.
+ * or FALSE if this collection does not contain this element.
+ * @param mixed
+ * @return int|FALSE
+ */
+ protected function search($item)
+ {
+ return array_search($item, $this->data, TRUE);
+ }
+
+
+
+ /**
+ * Removes all of the elements from this collection.
+ * @return void
+ * @throws ::NotSupportedException
+ */
+ public function clear()
+ {
+ $this->beforeRemove();
+ $this->data = array();
+ }
+
+
+
+ /**
+ * Returns true if this collection contains the specified item.
+ * @param mixed
+ * @return bool
+ */
+ public function contains($item)
+ {
+ return $this->search($item) !== FALSE;
+ }
+
+
+
+ /**
+ * Import from array or any traversable object.
+ * @param array|Traversable
+ * @return void
+ * @throws ::InvalidArgumentException
+ */
+ public function import($arr)
+ {
+ if (is_array($arr) || $arr instanceof Traversable) {
+ foreach ($arr as $item) {
+ $this->add($item);
+ }
+ } else {
+ throw new /*::*/InvalidArgumentException("Argument must be traversable.");
+ }
+ }
+
+
+
+ /**
+ * Returns an array containing all of the elements in this collection.
+ * @return array
+ */
+ public function toArray()
+ {
+ return $this->data;
+ }
+
+
+
+ /**
+ * Returns a value indicating whether collection is read-only.
+ * @return bool
+ */
+ public function isReadOnly()
+ {
+ return $this->readOnly;
+ }
+
+
+
+ /**
+ * Returns the number of elements in collection (::Countable implementation).
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->data);
+ }
+
+
+
+ /**
+ * Returns an iterator over the elements in collection (::IteratorAggregate implementation).
+ * @return ::ArrayIterator
+ */
+ public function getIterator()
+ {
+ return new /*::*/ArrayIterator($this->toArray());
+ }
+
+
+
+ /********************* internal notifications ****************d*g**/
+
+
+
+ /**
+ * Responds when the item is about to be added to the collection.
+ * @param mixed
+ * @return void
+ * @throws ::InvalidArgumentException, ::NotSupportedException
+ */
+ protected function beforeAdd($item)
+ {
+ if ($this->readOnly) {
+ throw new /*::*/NotSupportedException('Collection is read-only.');
+ }
+
+ if ($this->itemType !== NULL) {
+ if ($this->checkFunc === NULL) {
+ if (!($item instanceof $this->itemType)) {
+ throw new /*::*/InvalidArgumentException("Item must be '$this->itemType' object.");
+ }
+ } else {
+ $fnc = $this->checkFunc;
+ if (!$fnc($item)) {
+ throw new /*::*/InvalidArgumentException("Item must be $this->itemType.");
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * Responds when an item is about to be removed from the collection.
+ * @return void
+ * @throws ::NotSupportedException
+ */
+ protected function beforeRemove()
+ {
+ if ($this->readOnly) {
+ throw new /*::*/NotSupportedException('Collection is read-only.');
+ }
+ }
+
+}
227 Nette/Collections/Hashtable.php
@@ -0,0 +1,227 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+require_once dirname(__FILE__) . '/../Collections/Collection.php';
+
+require_once dirname(__FILE__) . '/../Collections/IMap.php';
+
+
+
+/**
+ * The exception that is thrown when the key specified for accessing
+ * an element in a collection does not match any key.
+ * @package Nette::Collections
+ */
+class KeyNotFoundException extends /*::*/RuntimeException
+{
+}
+
+
+
+/**
+ * Provides the base class for a generic collection of keys and values.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+class Hashtable extends Collection implements IMap
+{
+ /** @var bool */
+ protected $strict = TRUE;
+
+
+
+ /**
+ * Inserts the specified element to the map.
+ * @param mixed
+ * @param mixed
+ * @return bool
+ * @throws ::InvalidArgumentException
+ */
+ public function add($key, $item = NULL)
+ {
+ // note: $item is nullable to be compatible with that of ICollection::add()
+ if (!is_scalar($key)) {
+ throw new /*::*/InvalidArgumentException('Key must be either a string or an integer.');
+ }
+
+ if (array_key_exists($key, $this->data)) {
+ throw new /*::*/InvalidArgumentException('An element with the same key already exists.');
+ }
+
+ $this->beforeAdd($item);
+ $this->data[$key] = $item;
+ return TRUE;
+ }
+
+
+
+ /**
+ * Returns a array of the keys contained in this map.
+ * return array
+ */
+ public function getKeys()
+ {
+ return array_keys($this->data);
+ }
+
+
+
+ /**
+ * Returns the key of the first occurrence of the specified element,.
+ * or FALSE if this map does not contain this element.
+ * @param mixed
+ * @return mixed
+ */
+ public function search($item)
+ {
+ return array_search($item, $this->data, TRUE);
+ }
+
+
+
+ /**
+ * Import from array or any traversable object.
+ * @param array|Traversable
+ * @return void
+ * @throws ::InvalidArgumentException
+ */
+ public function import($arr)
+ {
+ if (is_array($arr) || $arr instanceof Traversable) {
+ foreach ($arr as $key => $item) {
+ $this->beforeAdd($item);
+ $this->data[$key] = $item;
+ }
+ } else {
+ throw new /*::*/InvalidArgumentException("Argument must be traversable.");
+ }
+ }
+
+
+
+ /**
+ * Returns variable or $default if there is no element.
+ * @param int index
+ * @return mixed
+ * @throws ::InvalidArgumentException
+ */
+ public function get($key, $default = NULL)
+ {
+ if (!is_scalar($key)) {
+ throw new /*::*/InvalidArgumentException('Key must be either a string or an integer.');
+ }
+
+ if (array_key_exists($key, $this->data)) {
+ return $this->data[$key];
+ } else {
+ return $default;
+ }
+ }
+
+
+
+ /********************* interface ::ArrayAccess ****************d*g**/
+
+
+
+ /**
+ * Inserts (replaces) item (::ArrayAccess implementation).
+ * @param int index
+ * @param object
+ * @return void
+ * @throws ::NotSupportedException, ::InvalidArgumentException
+ */
+ public function offsetSet($key, $item)
+ {
+ if (!is_scalar($key)) { // prevents NULL
+ throw new /*::*/InvalidArgumentException('Key must be either a string or an integer.');
+ }
+
+ $this->beforeAdd($item);
+ $this->data[$key] = $item;
+ }
+
+
+
+ /**
+ * Returns item (::ArrayAccess implementation).
+ * @param int index
+ * @return mixed
+ * @throws KeyNotFoundException, ::InvalidArgumentException
+ */
+ public function offsetGet($key)
+ {
+ if (!is_scalar($key)) {
+ throw new /*::*/InvalidArgumentException('Key must be either a string or an integer.');
+ }
+
+ if (array_key_exists($key, $this->data)) {
+ return $this->data[$key];
+ }
+
+ if ($this->strict) {
+ throw new KeyNotFoundException;
+ } else {
+ return NULL;
+ }
+ }
+
+
+
+ /**
+ * Exists item? (::ArrayAccess implementation).
+ * @param int index
+ * @return bool
+ * @throws ::InvalidArgumentException
+ */
+ public function offsetExists($key)
+ {
+ if (!is_scalar($key)) {
+ throw new /*::*/InvalidArgumentException('Key must be either a string or an integer.');
+ }
+
+ return array_key_exists($key, $this->data);
+ }
+
+
+
+ /**
+ * Removes the element at the specified position in this list.
+ * @param int index
+ * @return void
+ * @throws ::NotSupportedException, ::InvalidArgumentException
+ */
+ public function offsetUnset($key)
+ {
+ if (!is_scalar($key)) {
+ throw new /*::*/InvalidArgumentException('Key must be either a string or an integer.');
+ }
+
+ $this->beforeRemove();
+ unset($this->data[$key]);
+ }
+
+}
42 Nette/Collections/ICollection.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+/**
+ * Defines methods to manipulate generic collections.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+interface ICollection extends /*::*/Countable, /*::*/IteratorAggregate
+{
+ function add($item);
+ function remove($item);
+ function clear();
+ function contains($item);
+ function toArray();
+ function isReadOnly();
+ //function IteratorAggregate::getIterator();
+ //function Countable::count();
+}
41 Nette/Collections/IList.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+/**
+ * Represents a collection of objects that can be individually.
+ * accessed by index (ordered collection)
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+interface IList extends ICollection, /*::*/ArrayAccess
+{
+ function indexOf($item);
+ function insertAt($index, $item);
+ //function ArrayAccess::offsetSet($offset, $value);
+ //function ArrayAccess::offsetGet($offset);
+ //function ArrayAccess::offsetUnset($offset);
+ //function ArrayAccess::offsetExists($offset);
+}
42 Nette/Collections/IMap.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+/**
+ * Represents a generic collection of key/value pairs.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+interface IMap extends ICollection, /*::*/ArrayAccess
+{
+ // TODO: vyresit
+ //function add($key, $value); // produces Fatal error: Can't inherit abstract function
+ function search($item);
+ function getKeys();
+ //function ArrayAccess::offsetSet($offset, $value);
+ //function ArrayAccess::offsetGet($offset);
+ //function ArrayAccess::offsetUnset($offset);
+ //function ArrayAccess::offsetExists($offset);
+}
34 Nette/Collections/ISet.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+/**
+ * A collection that contains no duplicate elements.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+interface ISet extends ICollection
+{
+}
101 Nette/Collections/Set.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette::Collections
+ */
+
+/*namespace Nette::Collections;*/
+
+
+
+require_once dirname(__FILE__) . '/../Collections/Collection.php';
+
+require_once dirname(__FILE__) . '/../Collections/ISet.php';
+
+
+
+/**
+ * Provides the base class for a collection that contains no duplicate elements.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette::Collections
+ * @version $Revision$ $Date$
+ */
+class Set extends Collection implements ISet
+{
+
+
+ /**
+ * Appends the specified element to the end of this collection.
+ * @param mixed
+ * @return bool true if this collection changed as a result of the call
+ * @throws ::InvalidArgumentException, ::NotSupportedException
+ */
+ public function add($item)
+ {
+ $this->beforeAdd($item);
+
+ if (is_object($item)) {
+ $key = spl_object_hash($item);
+ if (isset($this->data[$key])) {
+ return FALSE;
+ }
+ $this->data[$key] = $item;
+ return TRUE;
+
+ } else {
+ $key = $this->search($item);
+ if ($key === FALSE) {
+ $this->data[] = $item;
+ return TRUE;
+ }
+ return FALSE;
+ }
+ }
+
+
+
+ /**
+ * Returns the index of the first occurrence of the specified element,.
+ * or FALSE if this collection does not contain this element.
+ * @param mixed
+ * @return int|FALSE
+ * @throws ::InvalidArgumentException
+ */
+ protected function search($item)
+ {
+ if (is_object($item)) {
+ $key = spl_object_hash($item);
+ return isset($this->data[$key]) ? $key : FALSE;
+
+ } else {
+ return array_search($item, $this->data, TRUE);
+ }
+ }
+
+
+
+ /**
+ * Returns an array containing all of the elements in this collection.
+ * @return array
+ */
+ public function toArray()
+ {
+ return array_values($this->data);
+ }
+
+}
334 Nette/Component.php
@@ -0,0 +1,334 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette
+ */
+
+/*namespace Nette;*/
+
+
+require_once dirname(__FILE__) . '/IComponent.php';
+
+require_once dirname(__FILE__) . '/Object.php';
+
+
+
+/**
+ * Component is the base class for all components.
+ *
+ * Components are objects implementing IComponent. They has parent component,
+ * own name and service locator.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette
+ * @version $Revision$ $Date$
+ */
+abstract class Component extends Object implements IComponent
+{
+ const NAME_SEPARATOR = '-';
+
+ const HIERARCHY_ATTACH = 1;
+
+ const HIERARCHY_DETACH = 2;
+
+ /** @var IServiceLocator */
+ private $serviceLocator;
+
+ /** @var IComponentContainer */
+ private $parent;
+
+ /** @var string */
+ private $name;
+
+ /** @var array */
+ private $lookupCache = array();
+
+
+
+
+ /**
+ */
+ public function __construct(IComponentContainer $parent = NULL, $name = NULL)
+ {
+ if ($parent !== NULL) {
+ $parent->addComponent($this, $name);
+
+ } elseif (is_string($name)) {
+ $this->name = $name;
+ }
+
+ $this->constructed();
+ }
+
+
+
+ /**
+ * This method will be called from component constructor.
+ * @return void
+ */
+ protected function constructed()
+ {
+ }
+
+
+
+ /**
+ * Lookup hierarchy for object specified by class or interface name.
+ * @param string
+ * @return IComponent
+ */
+ public function lookup($type)
+ {
+ /**/// fix for namespaced classes/interfaces in PHP < 5.3
+ if ($a = strrpos($type, ':')) $type = substr($type, $a + 1);/**/
+
+ if (isset($this->lookupCache[$type])) {
+ return $this->lookupCache[$type][0];
+ }
+
+ $obj = $this;
+ $path = array();
+ do {
+ if ($obj instanceof $type) break;
+ array_unshift($path, $obj->getName());
+ $obj = $obj->getParent(); // IConponent::getParent()
+ if ($obj === $this) $obj = NULL; // prevent cycling
+ } while ($obj !== NULL);
+
+ $this->lookupCache[$type] = array(
+ $obj,
+ $obj === NULL ? NULL : implode(self::NAME_SEPARATOR, $path),
+ );
+
+ return $this->lookupCache[$type][0];
+ }
+
+
+
+ /**
+ * Lookup for object specified by class or interface name. Returns backtrace path.
+ * A path is the concatenation of component names separated by self::NAME_SEPARATOR.
+ * @param string
+ * @return string
+ */
+ public function lookupPath($type)
+ {
+ /**/// fix for namespaced classes/interfaces in PHP < 5.3
+ if ($a = strrpos($type, ':')) $type = substr($type, $a + 1);/**/
+
+ if (isset($this->lookupCache[$type])) {
+ return $this->lookupCache[$type][1];
+ } else {
+ $this->lookup($type);
+ return $this->lookupCache[$type][1];
+ }
+ }
+
+
+
+ /********************* interface IComponent ****************d*g**/
+
+
+
+ /**
+ * @return string
+ */
+ final public function getName()
+ {
+ return $this->name;
+ }
+
+
+
+ /**
+ * Returns the container if any.
+ * @return IComponentContainer|NULL
+ */
+ final public function getParent()
+ {
+ return $this->parent;
+ }
+
+
+
+ /**
+ * Sets the parent of this component. This method is managed by containers and should.
+ * not be called by applications
+ *
+ * @param IComponentContainer New parent or null if this component is being removed from a parent
+ * @param string
+ * @return void
+ * @throws ::InvalidStateException
+ */
+ public function setParent(IComponentContainer $parent = NULL, $name = NULL)
+ {
+ // if parent is the same parent it already has, no action occurs (even name or service change)
+ if ($this->parent === $parent) return;
+
+ // A component cannot be given a parent if it already has a parent.
+ if ($this->parent !== NULL && $parent !== NULL) {
+ throw new /*::*/InvalidStateException('Component already has a parent.');
+ }
+
+ // remove from parent?
+ if ($parent === NULL) {
+ // parent cannot be removed if is still this component contains
+ if ($this->parent->getComponent($this->name) === $this) {
+ throw new /*::*/InvalidStateException('The current parent still recognizes this component as its child.');
+ }
+
+ $this->notification($this, self::HIERARCHY_DETACH);
+ $this->parent = NULL;
+ $this->refreshCache();
+
+ } else { // add to parent
+ // Given parent container does not already recognize this component as its child.
+ if ($parent->getComponent($name) !== $this) {
+ throw new /*::*/InvalidStateException('The given parent does not recognize this component as its child.');
+ }
+
+ $this->validateParent($parent);
+
+ $this->parent = $parent;
+ if ($name !== NULL) $this->name = $name;
+ $this->refreshCache();
+ $this->notification($this, self::HIERARCHY_ATTACH);
+ }
+ }
+
+
+
+ /**
+ * Is called by a component when it is about to be set new parent. Descendant can.
+ * override this method to disallow a parent change by throwing an ::InvalidStateException
+ * @param IComponentContainer
+ * @return void
+ * @throws ::InvalidStateException
+ */
+ protected function validateParent(IComponentContainer $parent)
+ {
+ }
+
+
+
+ /**
+ * Forwards notification messages to all components in hierarchy. Do not call directly.
+ * @param IComponent
+ * @param mixed
+ * @return void
+ */
+ protected function notification(IComponent $sender, $message)
+ {
+ if ($this instanceof IComponentContainer) {
+ foreach ($this->getComponents() as $component) {
+ if ($component instanceof Component) { // or move to interface?
+ $component->notification($sender, $message);
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * Refresh lookup cache (don't call directly).
+ * @param IComponent
+ * @return void
+ */
+ private function refreshCache()
+ {
+ $this->lookupCache = array();
+
+ if ($this instanceof IComponentContainer) {
+ foreach ($this->getComponents() as $component) {
+ if ($component instanceof self) {
+ $component->refreshCache();
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * Sets the service location (experimental).
+ * @param IServiceLocator
+ * @return void
+ */
+ public function setServiceLocator(IServiceLocator $locator)
+ {
+ $this->serviceLocator = $locator;
+ }
+
+
+
+ /**
+ * Gets the service locator (experimental).
+ * @return IServiceLocator
+ */
+ final public function getServiceLocator()
+ {
+ if ($this->serviceLocator === NULL) {
+ $this->serviceLocator = $this->parent === NULL
+ ? Environment::getServiceLocator()
+ : $this->parent->getServiceLocator();
+ }
+
+ return $this->serviceLocator;
+ }
+
+
+
+ /**
+ * Gets the service (experimental).
+ * @param string
+ * @return object
+ */
+ final public function getService($type)
+ {
+ return $this->getServiceLocator()->getService($type);
+ }
+
+
+
+ /********************* cloneable, serializable ****************d*g**/
+
+
+
+ /**
+ * Object cloning.
+ */
+ public function __clone()
+ {
+ if ($this->parent !== NULL &&
+ !($this->parent instanceof ComponentContainer && $this->parent->isCloning()))
+ {
+ $this->setParent(NULL);
+ }
+ }
+
+
+
+ /**
+ * Prevents serialization.
+ */
+ final public function __sleep()
+ {
+ throw new /*::*/NotImplementedException;
+ }
+
+}
221 Nette/ComponentContainer.php
@@ -0,0 +1,221 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette
+ */
+
+/*namespace Nette;*/
+
+
+require_once dirname(__FILE__) . '/Component.php';
+
+require_once dirname(__FILE__) . '/IComponentContainer.php';
+
+
+
+/**
+ * ComponentContainer is default implementation of IComponentContainer.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette
+ * @version $Revision$ $Date$
+ */
+class ComponentContainer extends Component implements IComponentContainer
+{
+ /** @var array of IComponent */
+ private $components = array();
+
+ /** @var bool */
+ private $cloning = FALSE;
+
+
+
+ /********************* interface IComponentContainer ****************d*g**/
+
+
+
+ /**
+ * Adds the specified component to the IComponentContainer.
+ * @param IComponent
+ * @param string
+ * @return void
+ * @throws ::InvalidStateException
+ */
+ public function addComponent(IComponent $component, $name)
+ {
+ if ($name === NULL) {
+ $name = $component->getName();
+ }
+
+ if ($name == NULL) { // intentionally ==
+ throw new /*::*/InvalidArgumentException('Component name is required.');
+ }
+
+ if (!is_string($name) || !preg_match('#^[a-z0-9_]+$#', $name)) {
+ throw new /*::*/InvalidArgumentException("Component name must be non-empty alphanumeric string, '$name' is invalid.");
+ }
+
+ if (isset($this->components[$name])) {
+ throw new /*::*/InvalidStateException("Component with name '$name' already exists.");
+ }
+
+ // check infinite recursion
+ $obj = $this;
+ do {
+ if ($obj === $component) {
+ throw new /*::*/InvalidStateException("Component is (grand) parent of container.");
+ }
+ $obj = $obj->getParent();
+ } while ($obj !== NULL);
+
+ // userland checking
+ $this->validateChildComponent($component);
+
+ try {
+ $this->components[$name] = $component;
+ $component->setParent($this, $name);
+
+ } catch (Exception $e) {
+ unset($this->components[$name]); // undo
+ throw $e;
+ }
+ }
+
+
+
+ /**
+ * Removes a component from the IComponentContainer.
+ * @param IComponent
+ * @return void
+ */
+ public function removeComponent(IComponent $component)
+ {
+ $name = $component->getName();
+ if (!isset($this->components[$name]) || $this->components[$name] !== $component) {
+ throw new /*::*/InvalidArgumentException("Component is not located in this container.");
+ }
+
+ unset($this->components[$name]);
+ $component->setParent(NULL);
+ }
+
+
+
+ /**
+ * Returns single component or NULL.
+ * @param string
+ * @param bool throws exception if component didn't exist?
+ * @return IComponent|NULL
+ */
+ final public function getComponent($name, $need = FALSE)
+ {
+ if (isset($this->components[$name])) {
+ return $this->components[$name];
+ } elseif ($need) {
+ throw new /*::*/InvalidArgumentException("Component with name '$name' does not exist.");
+ } else {
+ return NULL;
+ }
+ }
+
+
+
+ /**
+ * Returns collection of all the components in the container.
+ * @return array of IComponent
+ */
+ final public function getComponents()
+ {
+ return $this->components;
+ }
+
+
+
+ /**
+ * Descendant can override this method to disallow insert a child by throwing an ::InvalidStateException.
+ * @param IComponent
+ * @return void
+ * @throws ::InvalidStateException
+ */
+ protected function validateChildComponent(IComponent $child)
+ {
+ }
+
+
+
+ /********************* hierarchy notifications ****************d*g**/
+
+
+
+ /**
+ * This helper invokes specified method of all components in IComponent & IComponentContainer hierarchy recursively.
+ * @param IComponentContainer
+ * @param string method name
+ * @param array arguments
+ * @param string class/interface name
+ * @return void
+ */
+ static public function notifyComponents(IComponentContainer $container, $method, array $args = array(), $type = 'Nette::Component')
+ {
+ /**/// fix for namespaced classes/interfaces in PHP < 5.3
+ if ($a = strrpos($type, ':')) $type = substr($type, $a + 1);/**/
+
+ foreach ($container->getComponents() as $component) {
+ if ($component instanceof $type) {
+ call_user_func_array(array($component, $method), $args);
+ }
+
+ if ($component instanceof IComponentContainer) {
+ self::notifyComponents($component, $method, $args, $type);
+ }
+ }
+ }
+
+
+
+ /********************* cloneable, serializable ****************d*g**/
+
+
+
+ /**
+ * Object cloning.
+ */
+ public function __clone()
+ {
+ parent::__clone();
+
+ if ($this->components) {
+ $oldMyself = reset($this->components)->getParent();
+ $oldMyself->cloning = TRUE;
+ foreach ($this->components as $name => $component) {
+ $this->components[$name] = clone $component;
+ }
+ $oldMyself->cloning = FALSE;
+ }
+ }
+
+
+
+ /**
+ * Is container cloning now? (for internal usage).
+ */
+ public function isCloning()
+ {
+ return $this->cloning;
+ }
+
+}
203 Nette/Config.php
@@ -0,0 +1,203 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette
+ */
+
+/*namespace Nette;*/
+
+
+require_once dirname(__FILE__) . '/Collections/Hashtable.php';
+
+
+
+/**
+ * Configuration storage.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette
+ * @version $Revision$ $Date$
+ */
+class Config extends /*Nette::Collections::*/Hashtable
+{
+ /** @var bool */
+ protected $strict = FALSE;
+
+
+
+ /********************* I/O operations ****************d*g**/
+
+
+ /**
+ * @param array to wrap
+ * @throws ::InvalidArgumentException
+ */
+ public function __construct($arr = NULL)
+ {
+ parent::__construct($arr);
+
+ if ($arr !== NULL) {
+ $this->setReadOnly();
+ }
+ }
+
+
+
+ /**
+ * Factory new configuration object from file.
+ * @param string file name
+ * @param string section to load
+ * @param bool autoexpand variables
+ * @return Config
+ */
+ public static function fromFile($file, $section = NULL, $expand = FALSE)
+ {
+ require_once dirname(__FILE__) . '/ConfigAdapters.php';
+
+ $class = /*Nette::*/'ConfigAdapter_' . strtoupper(pathinfo($file, PATHINFO_EXTENSION));
+ if (class_exists($class)) {
+ return new self(call_user_func(array($class, 'load'), $file, $section, $expand));
+
+ } else {
+ throw new /*::*/InvalidArgumentException("Unknown file '$file' extension.");
+ }
+ }
+
+
+
+ /**
+ * Save configuration to file.
+ * @param string file
+ * @param string section to write
+ * @return void
+ */
+ public function save($file, $section = NULL)
+ {
+ require_once dirname(__FILE__) . '/ConfigAdapters.php';
+
+ $class = /*Nette::*/'ConfigAdapter_' . strtoupper(pathinfo($file, PATHINFO_EXTENSION));
+ if (class_exists($class)) {
+ return call_user_func(array($class, 'save'), $this, $file, $section);
+
+ } else {
+ throw new /*::*/InvalidArgumentException("Unknown file '$file' extension.");
+ }
+ }
+
+
+
+ /********************* data access ****************d*g**/
+
+
+
+ /**
+ * Import from array or any traversable object.
+ * @param array|Traversable
+ * @return void
+ * @throws ::InvalidArgumentException
+ */
+ public function import($arr)
+ {
+ parent::import($arr);
+
+ foreach ($this->data as $key => $val) {
+ if (is_array($val)) {
+ $this->data[$key] = $obj = clone $this;
+ $obj->data = array();
+ $obj->import($val);
+ }
+ }
+ }
+
+
+
+ /**
+ * Returns an array containing all of the elements in this collection.
+ * @return array
+ */
+ public function toArray()
+ {
+ $res = $this->data;
+ foreach ($res as $key => $val) {
+ if ($val instanceof self) {
+ $res[$key] = $val->toArray();
+ }
+ }
+ return $res;
+ }
+
+
+
+ /********************* overloading ****************d*g**/
+
+
+
+ /**
+ * Returns item. Do not call directly.
+ * @param int index
+ * @return mixed
+ */
+ protected function &__get($key)
+ {
+ if (array_key_exists($key, $this->data)) {
+ return $this->data[$key];
+ }
+
+ $null = NULL;
+ return $null;
+ }
+
+
+
+ /**
+ * Inserts (replaces) item. Do not call directly.
+ * @param int index
+ * @param object
+ * @return void
+ */
+ protected function __set($key, $item)
+ {
+ $this->beforeAdd($item);
+ $this->data[$key] = $item;
+ }
+
+
+
+ /**
+ * Exists item?
+ * @param string name
+ * @return bool
+ */
+ protected function __isset($key)
+ {
+ return array_key_exists($key, $this->data);
+ }
+
+
+
+ /**
+ * Removes the element at the specified position in this list.
+ * @param string name
+ * @return void
+ */
+ protected function __unset($key)
+ {
+ $this->beforeRemove();
+ unset($this->data[$key]);
+ }
+
+}
269 Nette/ConfigAdapters.php
@@ -0,0 +1,269 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette
+ */
+
+/*namespace Nette;*/
+
+
+/**
+ * Reading and writing INI files
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette
+ * @version $Revision$ $Date$
+ */
+final class ConfigAdapter_INI
+{
+
+ /** @var string key separator (key1> key2> key3) in INI files */
+ static public $keySeparator = '> ';
+
+ /** @var string section extends mark in INI files (section < parent) */
+ static public $sectionSeparator = ' < ';
+
+
+
+ /**
+ * Static class - cannot be instantiated.
+ */
+ final public function __construct()
+ {
+ throw new /*::*/LogicException("Cannot instantiate static class " . get_class($this));
+ }
+
+
+
+ /**
+ * Reads configuration from INI file.
+ * @param string file name
+ * @param string section to load
+ * @param bool autoexpand variables
+ * @return array
+ */
+ public static function load($file, $section = NULL, $expand = FALSE)
+ {
+ if (!is_file($file) || !is_readable($file)) {
+ throw new /*::*/FileNotFoundException("File '$file' is missing or is not readable.");
+ }
+
+ $data = parse_ini_file($file, TRUE);
+
+ // init separators
+ $sectionSep = isset($data[':section']) ? $data[':section'] : trim(self::$sectionSeparator);
+ $keySep = isset($data[':key']) ? $data[':key'] : trim(self::$keySeparator);
+ unset($data[':key'], $data[':section']);
+
+ // process extends sections like [staging < production]
+ if ($sectionSep) {
+ foreach ($data as $secName => $secData) {
+ if (!is_array($secData)) continue;
+
+ $parts = explode($sectionSep, $secName);
+ if (count($parts) > 1) {
+ $child = trim($parts[0]);
+ $parent = trim($parts[1]);
+ if (isset($data[$parent])) {
+ $secData += $data[$parent];
+ }
+ $data[$child] = $secData;
+ unset($data[$secName]);
+ }
+ }
+ }
+
+ if ($section !== NULL) {
+ if (isset($data[$section])) {
+ $data = array($section => $data[$section]);
+ } else {
+ throw new Exception("There is not section '$section' in '$file'.");
+ }
+ }
+
+ // process key separators (key1> key2> key3)
+ if ($keySep) {
+ $output = array();
+ foreach ($data as $secName => $secData) {
+ $cursorS = & $output;
+ foreach (explode($keySep, $secName) as $part) {
+ $cursorS = & $cursorS[trim($part)];
+ }
+
+ if (is_array($secData)) {
+ foreach ($secData as $key => $val) {
+ $cursor = & $cursorS;
+ foreach (explode($keySep, $key) as $part) {
+ $cursor = & $cursor[trim($part)];
+ }
+ if ($expand) $val = Environment::expand($val);
+ $cursor = $val;
+ }
+ } else {
+ if ($expand) $secData = Environment::expand($secData);
+ $cursorS = $secData;
+ }
+ }
+ $data = $output;
+
+ } elseif ($expand) {
+ // TODO ...
+ }
+
+ if ($section !== NULL) {
+ $data = $data[$section];
+ }
+
+ return $data;
+ }
+
+
+
+ /**
+ * Write INI file.
+ * @param Config to save
+ * @param string file
+ * @param string section name
+ * @return void
+ */
+ public static function save($config, $file, $section = NULL)
+ {
+ $output = array();
+ $output[] = '; generated by Nette at ' . @strftime('%c');
+ $output[] = '';
+ $data = $config->toArray();
+
+ if ($section === NULL) {
+ foreach ($data as $secName => $secData) {
+ if (!is_array($secData)) {
+ throw new /*::*/InvalidStateException("Invalid section '$section'.");
+ }
+
+ $output[] = "[$secName]";
+ self::build($secData, $output, '');
+ $output[] = '';
+ }
+
+ } else {
+ $output[] = "[$section]";
+ self::build($data, $output, '');
+ $output[] = '';
+ }
+
+ if (!file_put_contents($file, implode(PHP_EOL, $output))) {
+ throw new /*::*/IOException("Cannot write file '$file'.");
+ }
+ }
+
+
+
+ /**
+ * Recursive builds INI list.
+ * @param array
+ * @param array
+ * @param string
+ * @return void
+ */
+ private static function build($input, & $output, $prefix)
+ {
+ foreach ($input as $key => $val) {
+ if (is_array($val)) {
+ self::build($val, $output, $prefix . $key . self::$keySeparator);
+
+ } elseif (is_bool($val)) {
+ $output[] = "$prefix$key = " . ($val ? 'true' : 'false');
+
+ } elseif (is_numeric($val)) {
+ $output[] = "$prefix$key = $val";
+
+ } elseif (is_string($val)) {
+ $output[] = "$prefix$key = \"$val\"";
+
+ } else {
+ throw new /*::*/InvalidArgumentException("The '$prefix$key' item must be scalar or array.");
+ }
+ }
+ }
+
+}
+
+
+
+
+
+
+/**
+ * Reading and writing XML files
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette
+ * @version $Revision$ $Date$
+ */
+final class ConfigAdapter_XML
+{
+
+ /**
+ * Static class - cannot be instantiated.
+ */
+ final public function __construct()
+ {
+ throw new /*::*/LogicException("Cannot instantiate static class " . get_class($this));
+ }
+
+
+
+ /**
+ * Reads configuration from XML file.
+ * @param string file name
+ * @param string section to load
+ * @param bool autoexpand variables
+ * @return array
+ */
+ public static function load($file, $section = NULL, $expand = FALSE)
+ {
+ throw new /*::*/NotImplementedException;
+
+ if (!is_file($file) || !is_readable($file)) {
+ throw new /*::*/FileNotFoundException("File '$file' is missing or is not readable.");
+ }
+
+ $data = new SimpleXMLElement($file, NULL, TRUE);
+
+ foreach ($data as $secName => $secData) {
+ if ($secData['extends']) {
+ // $data[$child] = $secData;
+ }
+ }
+
+ return $data;
+ }
+
+
+
+ /**
+ * Write XML file.
+ * @param Config to save
+ * @param string file
+ * @return void
+ */
+ public static function save($config, $file, $section = NULL)
+ {
+ throw new /*::*/NotImplementedException;
+ }
+
+}
443 Nette/Debug.php
@@ -0,0 +1,443 @@
+<?php
+
+/**
+ * Nette Framework
+ *
+ * Copyright (c) 2004, 2008 David Grudl (http://davidgrudl.com)
+ *
+ * This source file is subject to the "Nette license" that is bundled
+ * with this package in the file license.txt.
+ *
+ * For more information please see http://nettephp.com/
+ *
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @license http://nettephp.com/license Nette license
+ * @link http://nettephp.com/
+ * @category Nette
+ * @package Nette
+ */
+
+/*namespace Nette;*/
+
+
+
+/**
+ * Debug static class.
+ *
+ * @author David Grudl
+ * @copyright Copyright (c) 2004, 2008 David Grudl
+ * @package Nette
+ * @version $Revision$ $Date$
+ */
+final class Debug
+{
+ /** @var bool */
+ private static $enabled = FALSE;
+
+ /** @var bool format the error report as HTML? */
+ public static $html;
+
+ /** @var bool send the error report to the browser? */
+ public static $display = TRUE;
+
+ /** @var string directory where reports are written to files */
+ public static $logDir; // TODO: or $logFileMask ?
+
+ /** @var string send the error report to the e-mail? */
+ public static $email;
+
+ /** @var string e-mail subject */
+ public static $emailSubject = 'PHP error report';
+
+ /** @var array */
+ public static $keysToHide = array('password', 'passwd', 'pass', 'pwd', 'creditcard', 'credit card', 'cc', 'pin');
+
+ /** @var array (not uset yet) */
+ private static $panels = array();
+
+ /** @var array */
+ private static $colophons = array();
+
+
+
+ /**
+ * Static class - cannot be instantiated.
+ */
+ final public function __construct()
+ {
+ throw new /*::*/LogicException("Cannot instantiate static class " . get_class($this));
+ }
+
+
+
+ /**
+ * Static class constructor.
+ */
+ public static function constructStatic()
+ {
+ self::$html = PHP_SAPI !== 'cli';
+
+ if (!defined('E_RECOVERABLE_ERROR')) {
+ define('E_RECOVERABLE_ERROR', 4096);
+ }
+ }
+
+
+
+ /**
+ * Configure debugger. (EXPERIMENTAL)
+ * @param Config configuration
+ * @return void
+ */
+ public static function configure(Config $config)
+ {
+ // $config = Environment::getConfig(__CLASS__);
+ if (isset($config->level)) {
+ error_reporting($config->level);
+ }
+
+ if (isset($config->display)) {
+ self::$display = (bool) $config->display;
+ ini_set('display_errors', self::$display ? '1' : '0'); // for fatal errors
+ }
+
+ if (isset($config->html)) {
+ self::$html = (bool) $config->html;
+ }
+
+ if (isset($config->logDir)) {
+ self::$logDir = Environment::expand($config->logDir);
+ ini_set('log_errors', self::$logDir ? '1' : '0'); // for fatal errors
+ ini_set('error_log', self::$logDir . '/php.error.log');
+ }
+
+ if (isset($config->email)) {
+ self::$email = (string) $config->email;
+ }
+
+ if (isset($config->emailSubject)) {
+ self::$emailSubject = (string) $config->emailSubject;
+ }
+
+ if (self::$email || self::$display || self::$logDir) {
+ self::enable();
+ }
+ }
+
+
+
+ /********************* useful tools ****************d*g**/
+
+
+
+ /**
+ * Dumps information about a variable in readable format.
+ *
+ * @param mixed variable to dump.
+ * @param bool return output instead of printing it?
+ * @return string
+ */
+ public static function dump($var, $return = FALSE)
+ {
+ ob_start();
+ var_dump($var);
+ $output = ob_get_clean();
+
+ if (self::$html) {
+ $output = htmlspecialchars($output, ENT_NOQUOTES);
+ $output = preg_replace('#\]=&gt;\n\ +([a-z]+)#i', '] => <span>$1</span>', $output);
+ $output = preg_replace('#^([a-z]+)#i', '<span>$1</span>', $output);
+ $output = "<pre class=\"dump\">$output</pre>\n";
+ } else {
+ $output = preg_replace('#\]=>\n\ +#i', '] => ', $output) . "\n";
+ }
+
+ if (!$return) echo $output;
+
+ return $output;
+ }
+
+
+
+ /**
+ * Starts/stops stopwatch.
+ * @return elapsed seconds
+ */
+ public static function timer()
+ {
+ static $time = 0;
+ $now = microtime(TRUE);
+ $delta = $now - $time;
+ $time = $now;
+ return $delta;
+ }
+
+
+
+ /********************* error and exception reporing ****************d*g**/
+
+
+
+ /**
+ * Register error handler routine.
+ * @param int error_reporting level
+ * @return void
+ */
+ public static function enable($level = NULL)
+ {
+ /*
+ if (self::$display === NULL) {
+ require_once dirname(__FILE__) . '/Environment.php';
+ self::$display = Environment::getName() !== Environment::PRODUCTION;
+ }
+ */
+
+ if ($level !== NULL) error_reporting($level);
+ set_error_handler(array(__CLASS__, 'errorHandler'));
+ set_exception_handler(array(__CLASS__, 'exceptionHandler')); // buggy in PHP 5.2.1
+ self::$enabled = TRUE;
+ }
+
+
+
+ /**
+ * Unregister error handler routine.
+ * @return void
+ */
+ public static function disable()
+ {
+ if (self::$enabled) {
+ restore_error_handler();
+ restore_exception_handler();
+ self::$enabled = FALSE;
+ }
+ }
+
+
+
+ /**
+ * Unregister error handler routine.
+ * @return void
+ */
+ public static function isEnabled()
+ {
+ return self::$enabled;
+ }
+
+
+
+ /**
+ * Debug exception handler.
+ *
+ * @param Exception
+ * @return void
+ */
+ public static function exceptionHandler(Exception $exception)
+ {
+ self::disable();
+
+ if (self::$html) {
+ self::handleMessage(self::blueScreen($exception));
+ } else {
+ self::handleMessage($exception->__toString() . "\nPHP version " . PHP_VERSION . "\nNette Framework version 0.7\n");
+ }
+
+ exit;
+ }
+
+
+
+ /**
+ * Debug error handler.
+ *
+ * @param int level of the error raised
+ * @param string error message
+ * @param string filename that the error was raised in
+ * @param int line number the error was raised at
+ * @param array an array of variables that existed in the scope the error was triggered in
+ * @return void
+ */
+ public static function errorHandler($code, $message, $file, $line, $context)
+ {
+ $fatals = array(
+ E_ERROR => 'Fatal error', // unfortunately not catchable
+ E_CORE_ERROR => 'Fatal core rrror', // not catchable
+ E_COMPILE_ERROR => 'Fatal compile error', // unfortunately not catchable
+ E_USER_ERROR => 'Fatal error',
+ E_PARSE => 'Parse error', // unfortunately not catchable
+ E_RECOVERABLE_ERROR => 'Catchable fatal error', // since PHP 5.2
+ );
+
+ if (isset($fatals[$code])) {
+ self::disable();
+
+ $trace = debug_backtrace();
+ array_shift($trace);
+ $type = $fatals[$code];
+
+ if (self::$html) {
+ self::handleMessage(self::blueScreen(NULL, $type, $code, $message, $file, $line, $trace, $context));
+ } else {
+ self::handleMessage("$type '$message' in $file on line $line\nPHP version " . PHP_VERSION . "\nNette Framework version 0.7\n");
+ }
+
+ exit;
+ }
+
+ if (($code & error_reporting()) === $code) {
+ $types = array(
+ E_WARNING => 'Warning',
+ E_CORE_WARNING => 'Core warning', // not catchable
+ E_COMPILE_WARNING => 'Compile warning', // not catchable
+ E_USER_WARNING => 'Warning',
+ E_NOTICE => 'Notice',
+ E_USER_NOTICE => 'Notice',
+ E_STRICT => 'Strict standards',
+ );
+ $type = isset($types[$code]) ? $types[$code] : 'Unknown error';
+
+ if (self::$html) {
+ $message = "<b>$type:</b> $message in <b>$file</b> on line <b>$line</b>\n<br>";
+ } else {
+ $message = "$type: $message in $file on line $line\n";
+ }
+
+ if (self::$display) {
+ echo $message;
+ }
+
+ if (self::$logDir) {
+ error_log($message);
+ }
+ }
+ }
+
+
+
+ /**
+ * Handles error message.
+ * @param string
+ * @param bool is fatal
+ * @return void
+ */
+ private static function handleMessage($message)
+ {
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+
+ if (self::$logDir) {
+ // TODO: add configurable file mask
+ $file = self::$logDir . '/report ' . date('Y-m-d H-i-s ') . substr(microtime(FALSE), 2, 6) . (self::$html ? '.html' : '.txt');
+ file_put_contents($file, $message);
+ }
+
+ if (self::$display) {
+ while (ob_get_level() && ob_end_clean());
+
+ echo $message;
+
+ // fix for IE 6
+ if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6.0')) {
+ $s = " \t\r\n";