Implement director-disown for PHP
diff --git a/Lib/php/director.swg b/Lib/php/director.swg
index 7a81cd5..ead731a 100644
--- a/Lib/php/director.swg
+++ b/Lib/php/director.swg
@@ -8,6 +8,8 @@
 #ifndef SWIG_DIRECTOR_PHP_HEADER_
 #define SWIG_DIRECTOR_PHP_HEADER_
 
+#define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG)
+
 #include <string>
 #include <exception>
 #include <map>
@@ -76,16 +78,34 @@
   };
 
   class Director {
+    private:
+      /* flag indicating whether the object is owned by PHP or C++ */
+      mutable bool swig_disown_flag;
+
     protected:
       // "mutable" so we can get a non-const pointer to it in const methods.
       mutable zval swig_self;
       typedef std::map<void *, GCItem_var> swig_ownership_map;
       mutable swig_ownership_map swig_owner;
+
     public:
-      Director(zval *self) {
+      Director(zval *self) : swig_disown_flag(false) {
         ZVAL_COPY_VALUE(&swig_self, self);
       }
 
+      ~Director() {
+        if (swig_disown_flag) {
+          Z_DELREF(swig_self);
+	}
+      }
+
+      void swig_disown() const {
+        if (!swig_disown_flag) {
+          swig_disown_flag = true;
+          Z_ADDREF(swig_self);
+        }
+      }
+
       static bool swig_is_overridden_method(const char *cname, zval *z) {
         zend_string * cname_str = zend_string_init(cname, strlen(cname), 0);
         zend_class_entry *ce = zend_lookup_class(cname_str);
diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
index 9e52400..79c2bd5 100644
--- a/Source/Modules/php.cxx
+++ b/Source/Modules/php.cxx
@@ -110,7 +110,8 @@
   membervar,
   staticmembervar,
   constructor,
-  directorconstructor
+  directorconstructor,
+  directordisown
 } wrapperType = standard;
 
 extern "C" {
@@ -904,7 +905,7 @@
     return false;
   }
 
-  void generate_magic_property_methods(String *baseClassExtend) {
+  void generate_magic_property_methods(Node *class_node, String *baseClassExtend) {
     if (Cmp(baseClassExtend, "Exception") == 0 || !is_class_wrapped(baseClassExtend)) {
       baseClassExtend = NULL;
     }
@@ -944,8 +945,14 @@
       Append(f->code, magic_set);
     }
     Printf(f->code, "\nelse if (strcmp(ZSTR_VAL(arg2),\"thisown\") == 0) {\n");
-    Printf(f->code, "arg->newobject = zval_get_long(&args[1]);\n}\n\n");
-    Printf(f->code, "else {\n");
+    Printf(f->code, "arg->newobject = zval_get_long(&args[1]);\n");
+    if (Swig_directorclass(class_node)) {
+      Printv(f->code, "if (arg->newobject == 0) {\n",
+		      "  Swig::Director *director = SWIG_DIRECTOR_CAST((", Getattr(class_node, "classtypeobj"), "*)(arg->ptr));\n",
+		      "  if (director) director->swig_disown();\n",
+		      "}\n", NIL);
+    }
+    Printf(f->code, "} else {\n");
     if (baseClassExtend) {
       Printf(f->code, "PHP_MN(%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", baseClassExtend);
     } else {
@@ -1074,6 +1081,10 @@
   }
 
   virtual int functionWrapper(Node *n) {
+    if (wrapperType == directordisown) {
+      // Handled via __set magic method - no explicit wrapper method wanted.
+      return SWIG_OK;
+    }
     String *name = GetChar(n, "name");
     String *iname = GetChar(n, "sym:name");
     SwigType *d = Getattr(n, "type");
@@ -1673,7 +1684,7 @@
     Language::classHandler(n);
 
     print_creation_free_wrapper(n);
-    generate_magic_property_methods(baseClassExtend);
+    generate_magic_property_methods(n, baseClassExtend);
     Printf(all_cs_entry, " ZEND_FE_END\n};\n\n");
 
     class_name = NULL;
@@ -2190,8 +2201,11 @@
     return status;
   }
 
-  int classDirectorDisown(Node *) {
-    return SWIG_OK;
+  int classDirectorDisown(Node *n) {
+    wrapperType = directordisown;
+    int result = Language::classDirectorDisown(n);
+    wrapperType = standard;
+    return result;
   }
 };				/* class PHP */