First import
authorRaphaël Gertz <git@rapsys.eu>
Tue, 26 Jun 2018 07:06:28 +0000 (09:06 +0200)
committerRaphaël Gertz <git@rapsys.eu>
Tue, 26 Jun 2018 07:06:28 +0000 (09:06 +0200)
.gitignore [new file with mode: 0644]
CREDITS [new file with mode: 0644]
bbcode.c [new file with mode: 0644]
config.m4 [new file with mode: 0644]
config.w32 [new file with mode: 0644]
php_bbcode.h [new file with mode: 0644]
test.php [new file with mode: 0644]
tests/001.phpt [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..f195b60
--- /dev/null
@@ -0,0 +1,35 @@
+.deps
+*.lo
+*.la
+.libs
+acinclude.m4
+aclocal.m4
+autom4te.cache
+build
+config.guess
+config.h
+config.h.in
+config.log
+config.nice
+config.status
+config.sub
+configure
+configure.ac
+include
+install-sh
+libtool
+ltmain.sh
+Makefile
+Makefile.fragments
+Makefile.global
+Makefile.objects
+missing
+mkinstalldirs
+modules
+run-tests.php
+tests/*/*.diff
+tests/*/*.out
+tests/*/*.php
+tests/*/*.exp
+tests/*/*.log
+tests/*/*.sh
diff --git a/CREDITS b/CREDITS
new file mode 100644 (file)
index 0000000..7410ff6
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,3 @@
+bbcode
+Xavier De Cock
+Raphaël Gertz
diff --git a/bbcode.c b/bbcode.c
new file mode 100644 (file)
index 0000000..3a9ac76
--- /dev/null
+++ b/bbcode.c
@@ -0,0 +1,356 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "Zend/zend_exceptions.h"
+#include "php_bbcode.h"
+
+/* If you declare any globals in php_bbcode.h uncomment this:
+ZEND_DECLARE_MODULE_GLOBALS(bbcode)
+*/
+
+typedef struct _bbcode_object {
+       /*zval *tag;
+       zval *smiley;
+       zval *flag;*/
+       zend_long flag;
+       zend_object_handlers bbcode_handlers;
+       zend_object std;
+} bbcode_object;
+
+/* True global resources - no need for thread safety here */
+/* BBCode object */
+zend_class_entry *bbcode_ce;
+
+/* BBCode exception object */
+zend_class_entry *bbcode_exception_ce;
+
+/* Define all constants */
+#define BBCODE_DEF(GEN) \
+       /* Types */ \
+       GEN(TYPE_ARG) /*BBCODE_TYPE_ARG*/\
+       GEN(TYPE_NOARG) /*BBCODE_TYPE_NOARG*/\
+       GEN(TYPE_SINGLE) /*BBCODE_TYPE_SINGLE*/\
+       GEN(TYPE_OPTARG) /*BBCODE_TYPE_OPTARG*/\
+       GEN(TYPE_ROOT) /*BBCODE_TYPE_ROOT*/\
+       \
+       /* Quotes */ \
+       GEN(QUOTE_DOUBLE) /*BBCODE_ARG_DOUBLE_QUOTE*/\
+       GEN(QUOTE_SIMPLE) /*BBCODE_ARG_SINGLE_QUOTE*/\
+       GEN(QUOTE_HTML) /*BBCODE_ARG_HTML_QUOTE*/\
+       GEN(QUOTE_ESCAPE) /*BBCODE_ARG_QUOTE_ESCAPING*/\
+       \
+       /* Corrections */ \
+       GEN(CORRECT_AUTO) /*BBCODE_AUTO_CORRECT*/\
+       GEN(CORRECT_REOPEN) /*BBCODE_CORRECT_REOPEN_TAGS*/\
+       GEN(CORRECT_NOTREE) /*BBCODE_DISABLE_TREE_BUILD*/\
+       \
+       /* Smileys */ \
+       GEN(SMILEY_ON) /*BBCODE_DEFAULT_SMILEYS_ON*/\
+       GEN(SMILEY_CI) /*BBCODE_SMILEYS_CASE_INSENSITIVE*/\
+       \
+       /* Flags */ \
+       GEN(CLOSE_AUTO) /*BBCODE_FLAGS_ONE_OPEN_PER_LEVEL*/\
+       GEN(REMOVE_EMPTY) /*BBCODE_FLAGS_REMOVE_IF_EMPTY*/\
+       GEN(REMOVE_CONTENT) /*BBCODE_FLAGS_CDATA_NOT_ALLOWED*/\
+       GEN(REMOVE_REOPEN) /*BBCODE_FLAGS_DENY_REOPEN_CHILD*/
+
+
+/* Generate enum version */
+#define BBCODE_GEN_ENUM(NAME) BBCODE_ ## NAME,
+
+/* Generate zend const version */
+#define BBCODE_GEN_CONST(NAME) zend_declare_class_constant_long(bbcode_ce, #NAME, sizeof(#NAME) - 1, BBCODE_ ## NAME TSRMLS_CC);
+
+/* All flags enum set */
+enum {
+       BBCODE_DEF(BBCODE_GEN_ENUM)
+};
+
+/* Set default flag 
+ * TODO: Set it in an ini ? */
+#define BBCODE_DEFAULT_FLAG BBCODE_QUOTE_DOUBLE|BBCODE_QUOTE_SIMPLE|BBCODE_QUOTE_ESCAPE|BBCODE_CORRECT_AUTO|BBCODE_CORRECT_REOPEN|BBCODE_SMILEY_ON|BBCODE_CLOSE_AUTO|BBCODE_REMOVE_EMPTY
+
+static void bbcode_destroy(bbcode_object *obj TSRMLS_DC);
+static void bbcode_free(bbcode_object *obj TSRMLS_DC);
+static zend_object *bbcode_clone(zval *obj TSRMLS_DC);
+static zend_object *bbcode_create(zend_class_entry *ce TSRMLS_DC);
+
+/* BBCode object destroy call */
+static void bbcode_destroy(bbcode_object *obj TSRMLS_DC) {
+       //zend_objects_destroy_object(&obj->std);
+       zend_objects_destroy_object((zend_object *)obj);
+
+       //zend_object_std_dtor(&obj->std TSRMLS_CC);
+
+       /*if (obj->flag) {
+               efree(obj->flag);
+       }*/
+
+       //efree(obj);
+}
+
+/* BBCode object free call */
+static void bbcode_free(bbcode_object *obj TSRMLS_DC) {
+
+       /*if (obj->flag) {
+               efree(obj->flag);
+       }*/
+
+       //efree(obj);
+       zend_object_std_dtor((zend_object *)obj);
+}
+
+static zend_object *bbcode_clone(zval *obj TSRMLS_DC) {
+
+       bbcode_object *oldobj = (bbcode_object *)((char *)obj - XtOffsetOf(bbcode_object, std));
+
+       bbcode_object *newobj = ecalloc(1, sizeof(bbcode_object) + zend_object_properties_size(Z_OBJCE_P(obj)));
+
+       zend_object_std_init(&newobj->std, Z_OBJCE_P(obj) TSRMLS_CC);
+       object_properties_init(&newobj->std, Z_OBJCE_P(obj) TSRMLS_CC);
+
+       memcpy(&newobj->bbcode_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+       newobj->bbcode_handlers.offset = XtOffsetOf(bbcode_object, std);
+       newobj->bbcode_handlers.dtor_obj = (zend_object_dtor_obj_t) bbcode_destroy;
+       newobj->bbcode_handlers.free_obj = (zend_object_free_obj_t) bbcode_free;
+       newobj->bbcode_handlers.clone_obj = (zend_object_clone_obj_t) bbcode_clone;
+
+       newobj->std.handlers = &(newobj->bbcode_handlers);
+
+       zend_objects_clone_members(&newobj->std, &oldobj->std);
+
+#if 0
+       bbcode_object *oldobj = (bbcode_object *)((char *)obj - XtOffsetOf(bbcode_object, std));
+       zend_object *newobj_val = bbcode_create(Z_OBJCE_P(obj) TSRMLS_CC);
+       bbcode_object *newobj = (bbcode_object *)((char *)newobj_val - XtOffsetOf(bbcode_object, std));
+
+       zend_objects_clone_members(&newobj->std, &oldobj->std);
+#endif
+
+       /*XXX: clone flag member*/
+       newobj->flag = oldobj->flag;
+
+       /* TODO: clone the members of bbcode_object
+       newobj->buffer = oldobj->buffer;
+       newobj->length = oldobj->length;
+
+       if (oldobj->flag) {
+               newobj->buffer = emalloc(oldobj->length);
+               memcpy(newobj->buffer, oldobj->buffer, oldobj->length);
+       }*/
+
+       return &newobj->std;
+}
+
+#if 0
+static zend_object_value bbcode_clone(zval *obj TSRMLS_DC)
+{
+       bbcode_object *oldobj = zend_object_store_get_object(obj TSRMLS_CC);
+       zend_object_value newobj_val = array_buffer_create_object(Z_OBJCE_P(obj) TSRMLS_CC);
+       bbcode_object *newobj = zend_object_store_get_object_by_handle(newobj_val.handle TSRMLS_CC);
+
+       zend_objects_clone_members(&newobj->std, &oldobj->std);
+
+       /* TODO: clone the members of bbcode_object
+       newobj->buffer = oldobj->buffer;
+       newobj->length = oldobj->length;
+
+       if (oldobj->flag) {
+               newobj->buffer = emalloc(oldobj->length);
+               memcpy(newobj->buffer, oldobj->buffer, oldobj->length);
+       }*/
+
+       return newobj_val;
+}
+#endif
+
+static zend_object *bbcode_create(zend_class_entry *ce TSRMLS_DC) {
+       bbcode_object *obj = ecalloc(1, sizeof(bbcode_object) + zend_object_properties_size(ce));//emalloc(sizeof(bbcode_object));
+       obj->flag = 0;
+       //memset(obj, 0, sizeof(bbcode_object));
+
+       zend_object_std_init(&obj->std, ce TSRMLS_CC);
+       object_properties_init(&obj->std, ce TSRMLS_CC);
+
+       /**/
+
+       memcpy(&obj->bbcode_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+       obj->bbcode_handlers.offset = XtOffsetOf(bbcode_object, std);
+       obj->bbcode_handlers.dtor_obj = (zend_object_dtor_obj_t) bbcode_destroy;
+       obj->bbcode_handlers.free_obj = (zend_object_free_obj_t) bbcode_free;
+       obj->bbcode_handlers.clone_obj = (zend_object_clone_obj_t) bbcode_clone;
+       //bbcode_handlers.offset = XtOffsetOf(bbcode_object, std);
+       //bbcode_handlers.dtor_obj = (zend_object_dtor_obj_t) bbcode_destroy;
+       //bbcode_handlers.free_obj = (zend_object_free_obj_t) bbcode_free;
+       //bbcode_handlers.clone_obj = (zend_object_clone_obj_t) bbcode_clone;
+
+
+       /*retval.handle = zend_object_store_put(
+                       obj,
+                       (zend_objects_store_dtor_t) zend_objects_destroy_object,
+                       (zend_objects_free_object_storage_t) bbcode_free,
+                       NULL TSRMLS_CC
+                       );
+       retval.handlers = &bbcode_handlers;
+
+       return retval;*/
+
+       obj->std.handlers = &(obj->bbcode_handlers);
+
+       return &obj->std;
+}
+
+static inline bbcode_object* bbcode_fetch(zend_object *obj) {
+      return (bbcode_object *)((char *)obj - XtOffsetOf(bbcode_object, std));
+}
+
+/* {{{ PHP_METHOD(BBCode::__construct) {
+ */
+ZEND_BEGIN_ARG_INFO_EX(bbcode_construct_arginfo, 0, 0, 1)
+       ZEND_ARG_ARRAY_INFO(0, tag, 1)
+       ZEND_ARG_ARRAY_INFO(0, smiley, 1)
+       ZEND_ARG_INFO(0, flag)
+ZEND_END_ARG_INFO()
+
+
+PHP_METHOD(BBCode, __construct) {
+       zend_array *tag;
+       zend_array *smiley;
+       zend_long flag = BBCODE_DEFAULT_FLAG;
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|al", &tag, &smiley, &flag) == FAILURE) {
+               return;
+       }
+
+       bbcode_object *obj = bbcode_fetch(Z_OBJ_P(getThis()));
+       assert(obj != NULL);
+
+       if (flag) {
+               obj->flag = (zend_long) flag;
+       }
+
+       //obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+       //if (error) {
+       //ZVAL_NULL(this);
+       //}
+}
+/* }}} */
+
+/* {{{ PHP_METHOD(BBCode, __destruct) {
+ */
+PHP_METHOD(BBCode, __destruct) {
+}
+/* }}} */
+
+/* {{{ PHP_METHOD(BBCode, __toString) {
+ */
+PHP_METHOD(BBCode, __toString) {
+       //TODO:
+}
+/* }}} */
+
+/* {{{ bbcode_methods[]
+ *
+ * Every BBCode visible function must have an entry in bbcode_methods[].
+ */
+const zend_function_entry bbcode_methods[] = {
+       PHP_ME(BBCode, __construct, bbcode_construct_arginfo, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+       PHP_ME(BBCode, __destruct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
+       PHP_ME(BBCode, __toString, NULL, ZEND_ACC_PUBLIC)
+       PHP_FE_END
+};
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(bbcode)
+{
+       /* If you have INI entries, uncomment these lines
+       REGISTER_INI_ENTRIES();
+       */
+
+       /* Tmp zend class entry*/
+       zend_class_entry tmp_ce;
+
+       /* Init BBCode class entry */
+       INIT_CLASS_ENTRY(tmp_ce, "BBCode", bbcode_methods);
+
+       /* Register BBCode class entry */
+       bbcode_ce = zend_register_internal_class(&tmp_ce TSRMLS_CC);
+       bbcode_ce->create_object = bbcode_create;
+
+       /* Generate const */
+       BBCODE_DEF(BBCODE_GEN_CONST)
+
+       /* Init BBCodeException class entry */
+       INIT_CLASS_ENTRY(tmp_ce, "BBCodeException", NULL);
+
+       /* Register BBCodeException class entry */
+       bbcode_exception_ce = zend_register_internal_class_ex(&tmp_ce, zend_exception_get_default(TSRMLS_C) TSRMLS_CC);
+
+       return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(bbcode)
+{
+       /* uncomment this line if you have INI entries
+       UNREGISTER_INI_ENTRIES();
+       */
+       return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(bbcode)
+{
+       php_info_print_table_start();
+       php_info_print_table_header(2, PHP_BBCODE_NAME " support", "enabled");
+       php_info_print_table_row(2, "Extension version", PHP_BBCODE_VERSION);
+       php_info_print_table_end();
+
+       /* Remove comments if you have entries in php.ini
+       DISPLAY_INI_ENTRIES();
+       */
+}
+/* }}} */
+
+/* {{{ bbcode_module_entry
+ */
+zend_module_entry bbcode_module_entry = {
+       STANDARD_MODULE_HEADER,
+       PHP_BBCODE_NAME,
+       NULL, /*bbcode_functions,*/
+       PHP_MINIT(bbcode),
+       PHP_MSHUTDOWN(bbcode),
+       NULL,
+       NULL,
+       PHP_MINFO(bbcode),
+       PHP_BBCODE_VERSION,
+       STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_BBCODE
+#ifdef ZTS
+ZEND_TSRMLS_CACHE_DEFINE()
+#endif
+ZEND_GET_MODULE(bbcode)
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/config.m4 b/config.m4
new file mode 100644 (file)
index 0000000..e0089b6
--- /dev/null
+++ b/config.m4
@@ -0,0 +1,72 @@
+dnl $Id$
+dnl config.m4 for extension bbcode
+
+PHP_ARG_ENABLE(bbcode, whether to enable bbcode support,
+[  --enable-bbcode           Enable bbcode support])
+
+if test "$PHP_BBCODE" != "no"; then
+  dnl Write more examples of tests here...
+
+  dnl # get library FOO build options from pkg-config output
+  dnl AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+  dnl AC_MSG_CHECKING(for libfoo)
+  dnl if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists foo; then
+  dnl   if $PKG_CONFIG foo --atleast-version 1.2.3; then
+  dnl     LIBFOO_CFLAGS=`$PKG_CONFIG foo --cflags`
+  dnl     LIBFOO_LIBDIR=`$PKG_CONFIG foo --libs`
+  dnl     LIBFOO_VERSON=`$PKG_CONFIG foo --modversion`
+  dnl     AC_MSG_RESULT(from pkgconfig: version $LIBFOO_VERSON)
+  dnl   else
+  dnl     AC_MSG_ERROR(system libfoo is too old: version 1.2.3 required)
+  dnl   fi
+  dnl else
+  dnl   AC_MSG_ERROR(pkg-config not found)
+  dnl fi
+  dnl PHP_EVAL_LIBLINE($LIBFOO_LIBDIR, BBCODE_SHARED_LIBADD)
+  dnl PHP_EVAL_INCLINE($LIBFOO_CFLAGS)
+
+  dnl # --with-bbcode -> check with-path
+  dnl SEARCH_PATH="/usr/local /usr"     # you might want to change this
+  dnl SEARCH_FOR="/include/bbcode.h"  # you most likely want to change this
+  dnl if test -r $PHP_BBCODE/$SEARCH_FOR; then # path given as parameter
+  dnl   BBCODE_DIR=$PHP_BBCODE
+  dnl else # search default path list
+  dnl   AC_MSG_CHECKING([for bbcode files in default path])
+  dnl   for i in $SEARCH_PATH ; do
+  dnl     if test -r $i/$SEARCH_FOR; then
+  dnl       BBCODE_DIR=$i
+  dnl       AC_MSG_RESULT(found in $i)
+  dnl     fi
+  dnl   done
+  dnl fi
+  dnl
+  dnl if test -z "$BBCODE_DIR"; then
+  dnl   AC_MSG_RESULT([not found])
+  dnl   AC_MSG_ERROR([Please reinstall the bbcode distribution])
+  dnl fi
+
+  dnl # --with-bbcode -> add include path
+  dnl PHP_ADD_INCLUDE($BBCODE_DIR/include)
+
+  dnl # --with-bbcode -> check for lib and symbol presence
+  dnl LIBNAME=bbcode # you may want to change this
+  dnl LIBSYMBOL=bbcode # you most likely want to change this 
+
+  dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+  dnl [
+  dnl   PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $BBCODE_DIR/$PHP_LIBDIR, BBCODE_SHARED_LIBADD)
+  dnl   AC_DEFINE(HAVE_BBCODELIB,1,[ ])
+  dnl ],[
+  dnl   AC_MSG_ERROR([wrong bbcode lib version or lib not found])
+  dnl ],[
+  dnl   -L$BBCODE_DIR/$PHP_LIBDIR -lm
+  dnl ])
+  dnl
+  dnl PHP_SUBST(BBCODE_SHARED_LIBADD)
+
+  dnl PHP_REQUIRE_CXX()
+  dnl PHP_ADD_LIBRARY(stdc++,,BBCODE_SHARED_LIBADD)
+  dnl AC_DEFINE(HAVE_PARLE,1,[ ])
+  dnl PHP_SUBST(BBCODE_SHARED_LIBADD)
+  PHP_NEW_EXTENSION(bbcode, bbcode.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
+fi
diff --git a/config.w32 b/config.w32
new file mode 100644 (file)
index 0000000..3b9fbcb
--- /dev/null
@@ -0,0 +1,13 @@
+// $Id$
+// vim:ft=javascript
+
+// If your extension references something external, use ARG_WITH
+// ARG_WITH("bbcode", "for bbcode support", "no");
+
+// Otherwise, use ARG_ENABLE
+// ARG_ENABLE("bbcode", "enable bbcode support", "no");
+
+if (PHP_BBCODE != "no") {
+       EXTENSION("bbcode", "bbcode.cpp", PHP_BBCODE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
+}
+
diff --git a/php_bbcode.h b/php_bbcode.h
new file mode 100644 (file)
index 0000000..6fc454c
--- /dev/null
@@ -0,0 +1,44 @@
+
+#ifndef PHP_BBCODE_H
+#define PHP_BBCODE_H
+
+extern zend_module_entry bbcode_module_entry;
+#define phpext_bbcode_ptr &bbcode_module_entry
+
+#define PHP_BBCODE_NAME "BBCode"
+#define PHP_BBCODE_VERSION "2.0.0"
+
+#ifdef PHP_WIN32
+#      define PHP_BBCODE_API __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+#      define PHP_BBCODE_API __attribute__ ((visibility("default")))
+#else
+#      define PHP_BBCODE_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+/*
+       Declare any global variables you may need between the BEGIN
+       and END macros here:
+
+ZEND_BEGIN_MODULE_GLOBALS(bbcode)
+       zend_long  global_value;
+       char *global_string;
+ZEND_END_MODULE_GLOBALS(bbcode)
+*/
+
+/* Always refer to the globals in your function as BBCODE_G(variable).
+   You are encouraged to rename these macros something shorter, see
+   examples in any other php module directory.
+*/
+#define BBCODE_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(bbcode, v)
+
+#if defined(ZTS) && defined(COMPILE_DL_BBCODE)
+ZEND_TSRMLS_CACHE_EXTERN()
+#endif
+
+#endif /* PHP_BBCODE_H */
+
diff --git a/test.php b/test.php
new file mode 100644 (file)
index 0000000..4e9f290
--- /dev/null
+++ b/test.php
@@ -0,0 +1,171 @@
+<?php
+$br = (php_sapi_name() == "cli")? "":"<br>";
+
+if(!extension_loaded('bbcode')) {
+       dl('bbcode.' . PHP_SHLIB_SUFFIX);
+}
+$module = 'bbcode';
+$functions = get_extension_funcs($module);
+/*echo "Functions available in the test extension:$br\n";
+foreach($functions as $func) {
+    echo $func."$br\n";
+}*/
+echo "$br\n";
+$function = 'confirm_' . $module . '_compiled';
+if (extension_loaded($module)) {
+       $obj = new $module(
+               [
+                       '' => [
+                               'type' => BBCODE::TYPE_ROOT,
+                               'childs' => ['ul','url','img','b','i']
+                       ],
+                       'i' => [
+                               'type' => BBCODE::TYPE_NOARG
+                               //TODO: by default open tag = <KEY> and close tag = </KEY>
+                       ],
+                       'b' => [
+                               'type' => BBCODE::TYPE_NOARG
+                       ],
+                       'ul' => [
+                               'type' => BBCODE::TYPE_NOARG,
+                               'childs' => [ 'li' ]
+                       ],
+                       'li' => [
+                               'type' => BBCODE::TYPE_NOARG,
+                               'parent' => 'ul',
+                               'childs' => ['url','img','b','i']
+                       ],
+                       'url' => [
+                               'type' => BBCODE::TYPE_OPTARG,
+                               'open_tag' => '<a href="{PARAM}">',
+                               'close_tag' => '</a>',
+                               'default_arg' => '{CONTENT}',
+                               'parent' => [ '', 'li', 'b', 'i' ]
+                       ]
+               ],
+               [
+                       ':)' => '<img src="smiley.gif" alt=":)" />',
+                       ':(' => '<img src="sad.gif" alt=":(" />',
+                       ':D' => '<img src="happy.gif" alt=":D" />',
+                       ':p' => '<img src="tong.gif" alt=":p" />',
+                       ':|' => '<img src="special.gif" alt=":|" />',
+                       ':6:' => '<img src="six.gif" alt=":6:" />'
+               ],
+               BBCode::REMOVE_EMPTY
+       );
+       var_dump($obj);
+       $obj2 = new $module(
+               [
+                       '' => [
+                               'type' => BBCODE::TYPE_ROOT,
+                               'childs' => ['ul','url','img','b','i']
+                       ],
+                       'i' => [
+                               'type' => BBCODE::TYPE_NOARG
+                               //TODO: by default open tag = <KEY> and close tag = </KEY>
+                       ],
+                       'b' => [
+                               'type' => BBCODE::TYPE_NOARG
+                       ],
+                       'ul' => [
+                               'type' => BBCODE::TYPE_NOARG,
+                               'childs' => [ 'li' ]
+                       ],
+                       'li' => [
+                               'type' => BBCODE::TYPE_NOARG,
+                               'parent' => 'ul',
+                               'childs' => ['url','img','b','i']
+                       ],
+                       'url' => [
+                               'type' => BBCODE::TYPE_OPTARG,
+                               'open_tag' => '<a href="{PARAM}">',
+                               'close_tag' => '</a>',
+                               'default_arg' => '{CONTENT}',
+                               'parent' => [ '', 'li', 'b', 'i' ]
+                       ]
+               ],
+               [
+                       ':)' => '<img src="smiley.gif" alt=":)" />',
+                       ':(' => '<img src="sad.gif" alt=":(" />',
+                       ':D' => '<img src="happy.gif" alt=":D" />',
+                       ':p' => '<img src="tong.gif" alt=":p" />',
+                       ':|' => '<img src="special.gif" alt=":|" />',
+                       ':6:' => '<img src="six.gif" alt=":6:" />'
+               ],
+               BBCode::REMOVE_EMPTY
+       );
+       $obj3 = new $module(
+               [
+                       '' => [
+                               'type' => BBCODE::TYPE_ROOT,
+                               'childs' => ['ul','url','img','b','i']
+                       ],
+                       'i' => [
+                               'type' => BBCODE::TYPE_NOARG
+                               //TODO: by default open tag = <KEY> and close tag = </KEY>
+                       ],
+                       'b' => [
+                               'type' => BBCODE::TYPE_NOARG
+                       ],
+                       'ul' => [
+                               'type' => BBCODE::TYPE_NOARG,
+                               'childs' => [ 'li' ]
+                       ],
+                       'li' => [
+                               'type' => BBCODE::TYPE_NOARG,
+                               'parent' => 'ul',
+                               'childs' => ['url','img','b','i']
+                       ],
+                       'url' => [
+                               'type' => BBCODE::TYPE_OPTARG,
+                               'open_tag' => '<a href="{PARAM}">',
+                               'close_tag' => '</a>',
+                               'default_arg' => '{CONTENT}',
+                               'parent' => [ '', 'li', 'b', 'i' ]
+                       ]
+               ],
+               [
+                       ':)' => '<img src="smiley.gif" alt=":)" />',
+                       ':(' => '<img src="sad.gif" alt=":(" />',
+                       ':D' => '<img src="happy.gif" alt=":D" />',
+                       ':p' => '<img src="tong.gif" alt=":p" />',
+                       ':|' => '<img src="special.gif" alt=":|" />',
+                       ':6:' => '<img src="six.gif" alt=":6:" />'
+               ],
+               BBCode::REMOVE_EMPTY
+       );
+       $obj3 = null;
+       unset($obj2);
+       $obj2 = clone $obj;
+       #var_dump(clone $obj);
+       //var_dump(new $module(BBCode::TYPE_ARG, 'tutu'));
+       exit;
+       //$str = $function($module);
+} else {
+       $str = "Module $module is not compiled into PHP";
+}
+echo "$str\n";
+
+       /*
+               array(
+                       'b' => array(
+                               'type'=>BBCODE_TYPE_NOARG,
+                               'open_tag'=>'<b class="sub">',
+                               'close_tag'=>'</b>',
+                               'flags'=>BBCODE_FLAGS_REMOVE_IF_EMPTY
+                       ),
+                       'u' => array(
+                               'type'=>BBCODE_TYPE_NOARG,
+                               'open_tag'=>'<u>',
+                               'close_tag'=>'</u>',
+                               'flags'=>BBCODE_FLAGS_SMILEYS_OFF | BBCODE_FLAGS_REMOVE_IF_EMPTY | BBCODE_FLAGS_SMILEYS_OFF
+                       ),
+                       'i' => array(
+                               'type'=>BBCODE_TYPE_NOARG,
+                               'open_tag'=>'<i>',
+                               'close_tag'=>'</i>',
+                               'flags'=>BBCODE_FLAGS_REMOVE_IF_EMPTY
+                       )
+               ),
+        */
+
diff --git a/tests/001.phpt b/tests/001.phpt
new file mode 100644 (file)
index 0000000..1abb88f
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Check for bbcode presence
+--SKIPIF--
+<?php if (!extension_loaded("bbcode")) print "skip"; ?>
+--FILE--
+<?php 
+echo "bbcode extension is available";
+/*
+       you can add regression tests for your extension here
+
+  the output of your test code has to be equal to the
+  text in the --EXPECT-- section below for the tests
+  to pass, differences between the output and the
+  expected text are interpreted as failure
+
+       see php7/README.TESTING for further information on
+  writing regression tests
+*/
+?>
+--EXPECT--
+bbcode extension is available