@@ -1320,20 +1320,53 @@ zend_object_iterator *ClassImpl::getIterator(zend_class_entry *entry, zval *obje
13201320 */
13211321int ClassImpl::serialize (zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data)
13221322{
1323- // get the serializable object
1324- Serializable *serializable = dynamic_cast <Serializable*>(ObjectImpl::find (object)->object ());
1325-
13261323 // user may throw an exception in the serialize() function
13271324 try
13281325 {
1329- // call the serialize method on the object
1330- auto value = serializable->serialize ();
1331-
1332- // allocate the buffer, and copy the data into it (the zend engine will
1333- // (hopefully) clean up the data for us - the default serialize method does
1334- // it like this too)
1335- *buffer = (unsigned char *)estrndup (value.c_str (), value.size ());
1336- *buf_len = value.size ();
1326+ // get the base object
1327+ Base *base = dynamic_cast <Base*>(ObjectImpl::find (object)->object ());
1328+
1329+ // get the class-entry
1330+ zend_class_entry *ce = Z_OBJCE_P (object);
1331+
1332+ // we are going to check if the serialize method was overridden in user-space
1333+ zend_function *func = (zend_function *)zend_hash_str_find_ptr (&ce->function_table , " serialize" , sizeof (" serialize" )-1 );
1334+
1335+ // do we have a user-space alternative?
1336+ if (func && func->type == ZEND_USER_FUNCTION)
1337+ {
1338+ // construct object to make the call
1339+ Php::Object self (ce, base);
1340+
1341+ // get the serialized string
1342+ auto value = self.call (" serialize" );
1343+
1344+ // make sure the returned value is indeed a string
1345+ value.setType (Type::String);
1346+
1347+ // allocate the buffer, and copy the data into it (the zend engine will
1348+ // (hopefully) clean up the data for us - the default serialize method does
1349+ // it like this too)
1350+ *buffer = (unsigned char *)estrndup (value.rawValue (), value.size ());
1351+ *buf_len = value.size ();
1352+ }
1353+ else
1354+ {
1355+ // get the base object
1356+ Serializable *serializable = dynamic_cast <Serializable*>(base);
1357+
1358+ // call the serialize method on the object
1359+ auto value = serializable->serialize ();
1360+
1361+ // allocate the buffer, and copy the data into it (the zend engine will
1362+ // (hopefully) clean up the data for us - the default serialize method does
1363+ // it like this too)
1364+ *buffer = (unsigned char *)estrndup (value.c_str (), value.size ());
1365+ *buf_len = value.size ();
1366+ }
1367+
1368+ // done
1369+ return SUCCESS;
13371370 }
13381371 catch (Throwable &throwable)
13391372 {
@@ -1343,9 +1376,6 @@ int ClassImpl::serialize(zval *object, unsigned char **buffer, size_t *buf_len,
13431376 // unreachable
13441377 return FAILURE;
13451378 }
1346-
1347- // done
1348- return SUCCESS;
13491379}
13501380
13511381/* *
@@ -1358,17 +1388,38 @@ int ClassImpl::serialize(zval *object, unsigned char **buffer, size_t *buf_len,
13581388 */
13591389int ClassImpl::unserialize (zval *object, zend_class_entry *entry, const unsigned char *buffer, size_t buf_len, zend_unserialize_data *data)
13601390{
1361- // create the PHP object
1362- object_init_ex (object, entry);
1363-
1364- // turn this into a serializale
1365- Serializable *serializable = dynamic_cast <Serializable*>(ObjectImpl::find (object)->object ());
1366-
1367- // user may throw an exception in the serialize() function
1391+ // user may throw an exception in the unserialize() function
13681392 try
13691393 {
1370- // call the unserialize method on it
1371- serializable->unserialize ((const char *)buffer, buf_len);
1394+ // create the PHP object
1395+ object_init_ex (object, entry);
1396+
1397+ // get the base object
1398+ Base *base = dynamic_cast <Base*>(ObjectImpl::find (object)->object ());
1399+
1400+ // we are going to check if the unserialize method was overridden in user-space
1401+ zend_function *func = (zend_function *)zend_hash_str_find_ptr (&entry->function_table , " unserialize" , sizeof (" unserialize" )-1 );
1402+
1403+ // do we have a user-space alternative?
1404+ if (func && func->type == ZEND_USER_FUNCTION)
1405+ {
1406+ // construct object to make the call
1407+ Php::Object self (entry, base);
1408+
1409+ // make the unserialize call
1410+ self.call (" unserialize" , Php::Value ((const char *)buffer, buf_len));
1411+ }
1412+ else
1413+ {
1414+ // turn this into a serializale
1415+ Serializable *serializable = dynamic_cast <Serializable*>(base);
1416+
1417+ // call the unserialize method on it
1418+ serializable->unserialize ((const char *)buffer, buf_len);
1419+ }
1420+
1421+ // done
1422+ return SUCCESS;
13721423 }
13731424 catch (Throwable &throwable)
13741425 {
@@ -1380,9 +1431,6 @@ int ClassImpl::unserialize(zval *object, zend_class_entry *entry, const unsigned
13801431 // unreachable
13811432 return FAILURE;
13821433 }
1383-
1384- // done
1385- return SUCCESS;
13861434}
13871435
13881436/* *
0 commit comments