summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rwxr-xr-xext/spl/config.m42
-rw-r--r--ext/spl/config.w322
-rwxr-xr-xext/spl/php_spl.c4
-rwxr-xr-xext/spl/spl.php50
-rwxr-xr-xext/spl/spl_observer.c88
-rwxr-xr-xext/spl/spl_observer.h41
-rwxr-xr-xext/spl/tests/observer_001.phpt116
7 files changed, 298 insertions, 5 deletions
diff --git a/ext/spl/config.m4 b/ext/spl/config.m4
index 4760a14203..eea8092166 100755
--- a/ext/spl/config.m4
+++ b/ext/spl/config.m4
@@ -9,6 +9,6 @@ if test "$PHP_SPL" != "no"; then
AC_MSG_ERROR(Cannot build SPL as a shared module)
fi
AC_DEFINE(HAVE_SPL, 1, [Whether you want SPL (Standard PHP Library) support])
- PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c, $ext_shared)
+ PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c spl_observer.c, $ext_shared)
PHP_ADD_EXTENSION_DEP(spl, simplexml)
fi
diff --git a/ext/spl/config.w32 b/ext/spl/config.w32
index 255a2b4eab..931a6704c7 100644
--- a/ext/spl/config.w32
+++ b/ext/spl/config.w32
@@ -7,6 +7,6 @@ if (PHP_SPL != "no") {
if (PHP_SPL_SHARED) {
ERROR("SPL cannot be compiled as a shared ext");
}
- EXTENSION("spl", "php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c");
+ EXTENSION("spl", "php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_sxe.c spl_exceptions.c spl_observer.c");
AC_DEFINE('HAVE_SPL', 1);
}
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 2486f8d3bb..d6304635c7 100755
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -33,6 +33,7 @@
#include "spl_iterators.h"
#include "spl_sxe.h"
#include "spl_exceptions.h"
+#include "spl_observer.h"
#ifdef COMPILE_DL_SPL
ZEND_GET_MODULE(spl)
@@ -95,6 +96,7 @@ PHP_MINIT_FUNCTION(spl)
PHP_MINIT(spl_directory)(INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(spl_sxe)(INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(spl_exceptions)(INIT_FUNC_ARGS_PASSTHRU);
+ PHP_MINIT(spl_observer)(INIT_FUNC_ARGS_PASSTHRU);
return SUCCESS;
}
@@ -181,6 +183,7 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(LimitIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(LogicException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(NoRewindIterator, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(Observer, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(OuterIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(OutOfRangeException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(OutOfBoundsException, z_list, sub, allow, ce_flags); \
@@ -193,6 +196,7 @@ PHP_FUNCTION(class_implements)
SPL_ADD_CLASS(RuntimeException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SeekableIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SimpleXMLIterator, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(Subject, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(UnderflowException, z_list, sub, allow, ce_flags); \
/* {{{ spl_classes */
diff --git a/ext/spl/spl.php b/ext/spl/spl.php
index c54c22a21a..49309bdf11 100755
--- a/ext/spl/spl.php
+++ b/ext/spl/spl.php
@@ -66,6 +66,9 @@
*
* - class ArrayObject implements IteratorAggregate
* - class ArrayIterator implements Iterator
+ *
+ * As the above suggest an ArrayObject creates an ArrayIterator when it comes to
+ * iteration (e.g. ArrayObject instance used inside foreach).
*
* 5) Counting
*
@@ -88,9 +91,13 @@
* - class OverflowException extends RuntimeException
* - class RangeException extends RuntimeException
* - class UnderflowException extends RuntimeException
- *
- * As the above suggest an ArrayObject creates an ArrayIterator when it comes to
- * iteration (e.g. ArrayObject instance used inside foreach).
+ *
+ * 7) Observer
+ *
+ * SPL suggests a standard way of implementing the observer pattern.
+ *
+ * - interface Observer
+ * - interface Subject
*
* A nice article about SPL can be found
* <a href="http://www.sitepoint.com/article/php5-standard-library/1">here</a>.
@@ -657,4 +664,41 @@ class SimpleXMLIterator extends SimpleXMLElement implements RecursiveIterator
function getChildren();
}
+/** @ingroup SPL
+ * @brief observer of the observer pattern
+ *
+ * For a detailed explanation see Observer pattern in
+ * <em>
+ * Gamma, Helm, Johnson, Vlissides<br />
+ * Design Patterns
+ * </em>
+ */
+interface Observer
+{
+ /** Called from the subject (i.e. when it's value has changed).
+ * @param $subject the callee
+ */
+ function update(Subject $subject);
+}
+
+/** @ingroup SPL
+ * @brief ubject to the observer pattern
+ * @see Observer
+ */
+interface Subject
+{
+ /** @param $observer new observer to attach
+ */
+ function attach(Observer $observer);
+
+ /** @param $observer existing observer to detach
+ * @note a non attached observer shouldn't result in a warning or similar
+ */
+ function detach(Observer $observer);
+
+ /** @param $ignore optional observer that should not be notified
+ */
+ function notify([Observer $ignore = NULL]);
+}
+
?>
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c
new file mode 100755
index 0000000000..9c12eb4673
--- /dev/null
+++ b/ext/spl/spl_observer.c
@@ -0,0 +1,88 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "zend_interfaces.h"
+#include "zend_exceptions.h"
+
+#include "php_spl.h"
+#include "spl_functions.h"
+#include "spl_engine.h"
+#include "spl_observer.h"
+
+SPL_METHOD(Observer, update);
+SPL_METHOD(Subject, attach);
+SPL_METHOD(Subject, detach);
+SPL_METHOD(Subject, notify);
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_Observer_update, 0)
+ ZEND_ARG_OBJ_INFO(0, subject, Subject, 0)
+ZEND_END_ARG_INFO();
+
+static zend_function_entry spl_funcs_Observer[] = {
+ SPL_ABSTRACT_ME(Observer, update, arginfo_Observer_update)
+ {NULL, NULL, NULL}
+};
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_Subject_attach, 0)
+ ZEND_ARG_OBJ_INFO(0, observer, Observer, 0)
+ZEND_END_ARG_INFO();
+
+/*static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_Subject_notify, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, ignore, Observer, 1)
+ZEND_END_ARG_INFO();*/
+
+static zend_function_entry spl_funcs_Subject[] = {
+ SPL_ABSTRACT_ME(Subject, attach, arginfo_Subject_attach)
+ SPL_ABSTRACT_ME(Subject, detach, arginfo_Subject_attach)
+ SPL_ABSTRACT_ME(Subject, notify, NULL)
+ {NULL, NULL, NULL}
+};
+
+PHPAPI zend_class_entry *spl_ce_Observer;
+PHPAPI zend_class_entry *spl_ce_Subject;
+
+/* {{{ PHP_MINIT_FUNCTION(spl_observer) */
+PHP_MINIT_FUNCTION(spl_observer)
+{
+ REGISTER_SPL_INTERFACE(Observer);
+ REGISTER_SPL_INTERFACE(Subject);
+
+ return SUCCESS;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: fdm=marker
+ * vim: noet sw=4 ts=4
+ */
diff --git a/ext/spl/spl_observer.h b/ext/spl/spl_observer.h
new file mode 100755
index 0000000000..857116ec4d
--- /dev/null
+++ b/ext/spl/spl_observer.h
@@ -0,0 +1,41 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef SPL_OBSERVER_H
+#define SPL_OBSERVER_H
+
+#include "php.h"
+#include "php_spl.h"
+
+extern PHPAPI zend_class_entry *spl_ce_Observer;
+extern PHPAPI zend_class_entry *spl_ce_Subject;
+
+PHP_MINIT_FUNCTION(spl_observer);
+
+#endif /* SPL_OBSERVER_H */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim600: fdm=marker
+ * vim: noet sw=4 ts=4
+ */
diff --git a/ext/spl/tests/observer_001.phpt b/ext/spl/tests/observer_001.phpt
new file mode 100755
index 0000000000..3b20e25bdc
--- /dev/null
+++ b/ext/spl/tests/observer_001.phpt
@@ -0,0 +1,116 @@
+--TEST--
+SPL: Observer and Subject (empty notify)
+--FILE--
+<?php
+
+class ObserverImpl implements Observer
+{
+ protected $name = '';
+
+ function __construct($name = 'obj')
+ {
+ $this->name = '$' . $name;
+ }
+
+ function update(Subject $subject)
+ {
+ echo $this->name . '->' . __METHOD__ . '(' . $subject->getName() . ");\n";
+ }
+
+ function getName()
+ {
+ return $this->name;
+ }
+}
+
+class SubjectImpl implements Subject
+{
+ protected $name = '';
+ protected $observers = array();
+
+ function __construct($name = 'sub')
+ {
+ $this->name = '$' . $name;
+ }
+
+ function attach(Observer $observer)
+ {
+ echo '$sub->' . __METHOD__ . '(' . $observer->getName() . ");\n";
+ if (!in_array($observer, $this->observers))
+ {
+ $this->observers[] = $observer;
+ }
+ }
+
+ function detach(Observer $observer)
+ {
+ echo '$sub->' . __METHOD__ . '(' . $observer->getName() . ");\n";
+ $idx = array_search($observer, $this->observers);
+ if ($idx !== false)
+ {
+ unset($this->observers[$idx]);
+ }
+ }
+
+ function notify()
+ {
+ echo '$sub->' . __METHOD__ . "();\n";
+ foreach($this->observers as $observer)
+ {
+ $observer->update($this);
+ }
+ }
+
+ function getName()
+ {
+ return $this->name;
+ }
+}
+
+$sub = new SubjectImpl;
+
+$ob1 = new ObserverImpl("ob1");
+$ob2 = new ObserverImpl("ob2");
+$ob3 = new ObserverImpl("ob3");
+
+$sub->attach($ob1);
+$sub->attach($ob1);
+$sub->attach($ob2);
+$sub->attach($ob3);
+
+$sub->notify();
+
+$sub->detach($ob3);
+
+$sub->notify();
+
+$sub->detach($ob2);
+$sub->detach($ob1);
+
+$sub->notify();
+
+$sub->attach($ob3);
+
+$sub->notify();
+?>
+===DONE===
+--EXPECT--
+$sub->SubjectImpl::attach($ob1);
+$sub->SubjectImpl::attach($ob1);
+$sub->SubjectImpl::attach($ob2);
+$sub->SubjectImpl::attach($ob3);
+$sub->SubjectImpl::notify();
+$ob1->ObserverImpl::update($sub);
+$ob2->ObserverImpl::update($sub);
+$ob3->ObserverImpl::update($sub);
+$sub->SubjectImpl::detach($ob3);
+$sub->SubjectImpl::notify();
+$ob1->ObserverImpl::update($sub);
+$ob2->ObserverImpl::update($sub);
+$sub->SubjectImpl::detach($ob2);
+$sub->SubjectImpl::detach($ob1);
+$sub->SubjectImpl::notify();
+$sub->SubjectImpl::attach($ob3);
+$sub->SubjectImpl::notify();
+$ob3->ObserverImpl::update($sub);
+===DONE===