@@ -735,10 +735,11 @@ static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args,
735735 zend_class_entry * ce ;
736736 zval * retval ;
737737 char * class_name , * prop_name ;
738+
738739 zend_property_info * pptr = (zend_property_info * ) pDest ;
739740 APPLY_TSRMLS_FETCH ();
740741
741- if (! (pptr -> flags & ZEND_ACC_PUBLIC ) || (pptr -> flags & ZEND_ACC_STATIC )) {
742+ if ((pptr -> flags & ZEND_ACC_PRIVATE ) || (pptr -> flags & ZEND_ACC_STATIC )) {
742743 return 0 ;
743744 }
744745
@@ -752,6 +753,7 @@ static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args,
752753#endif
753754
754755 add_assoc_string (retval , prop_name , prop_name , 1 );
756+ add_assoc_string (retval , TWIG_DECAMELIZE (prop_name ), prop_name , 1 );
755757
756758 return 0 ;
757759}
@@ -771,6 +773,7 @@ static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name
771773 array_init (class_properties );
772774 // add all methods to self::cache[$class]['methods']
773775 zend_hash_apply_with_arguments (& class_ce -> function_table APPLY_TSRMLS_CC , twig_add_method_to_class , 1 , class_methods );
776+ // add all properties to self::cache[$class]['properties']
774777 zend_hash_apply_with_arguments (& class_ce -> properties_info APPLY_TSRMLS_CC , twig_add_property_to_class , 2 , & class_ce , class_properties );
775778
776779 add_assoc_zval (class_info , "methods" , class_methods );
@@ -815,14 +818,46 @@ PHP_FUNCTION(twig_template_get_attributes)
815818 type = "any" ;
816819 }
817820
821+ /*
822+ if (is_object($object)) {
823+ $class = get_class($object);
824+ if (!isset(self::$cache[$class])) {
825+ self::$cache[$class] = $this->getCacheForClass($class);
826+ }
827+ }
828+ */
829+ if (Z_TYPE_P (object ) == IS_OBJECT ) {
830+ class_name = TWIG_GET_CLASS_NAME (object TSRMLS_CC );
831+ tmp_self_cache = TWIG_GET_STATIC_PROPERTY (template , "cache" TSRMLS_CC );
832+ tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
833+
834+ if (!tmp_class ) {
835+ twig_add_class_to_cache (tmp_self_cache , object , class_name TSRMLS_CC );
836+ tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
837+ }
838+ efree (class_name );
839+ }
840+
818841/*
819842 // array
820843 if (Twig_Template::METHOD_CALL !== $type) {
821844 $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
845+ $hasArrayItem = false;
846+
847+ if (is_array($object) && array_key_exists($arrayItem, $object)) {
848+ $hasArrayItem = true;
849+ } elseif ($object instanceof ArrayAccess) {
850+ if (isset($object[$arrayItem])) {
851+ $hasArrayItem = true;
852+ } elseif (isset(self::$cache[$class]['properties'][$arrayItem])
853+ && isset($object[self::$cache[$class]['properties'][$arrayItem]])
854+ ) {
855+ $arrayItem = self::$cache[$class]['properties'][$arrayItem];
856+ $hasArrayItem = true;
857+ }
858+ }
822859
823- if ((is_array($object) && array_key_exists($arrayItem, $object))
824- || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
825- ) {
860+ if ($hasArrayItem) {
826861 if ($isDefinedTest) {
827862 return true;
828863 }
@@ -833,15 +868,30 @@ PHP_FUNCTION(twig_template_get_attributes)
833868
834869
835870 if (strcmp ("method" , type ) != 0 ) {
836- if ((TWIG_ARRAY_KEY_EXISTS (object , zitem ))
837- || (TWIG_INSTANCE_OF (object , zend_ce_arrayaccess TSRMLS_CC ) && TWIG_ISSET_ARRAYOBJECT_ELEMENT (object , zitem TSRMLS_CC ))
838- ) {
871+ zval * tmp_properties , * tmp_item = NULL ;
872+
873+ if (TWIG_ARRAY_KEY_EXISTS (object , zitem )) {
874+ tmp_item = zitem ;
875+ } else if (TWIG_INSTANCE_OF (object , zend_ce_arrayaccess TSRMLS_CC )) {
876+ if (TWIG_ISSET_ARRAYOBJECT_ELEMENT (object , zitem TSRMLS_CC )) {
877+ tmp_item = zitem ;
878+ } else {
879+ tmp_properties = TWIG_GET_ARRAY_ELEMENT (tmp_class , "properties" , strlen ("properties" ) TSRMLS_CC );
880+ if ((tmp_item = TWIG_GET_ARRAY_ELEMENT (tmp_properties , item , item_len TSRMLS_CC ))
881+ && !TWIG_ISSET_ARRAYOBJECT_ELEMENT (object , tmp_item TSRMLS_CC )
882+ ) {
883+ tmp_item = NULL ;
884+ }
885+ }
886+ }
887+
888+ if (tmp_item ) {
839889
840890 if (isDefinedTest ) {
841891 RETURN_TRUE ;
842892 }
843893
844- ret = TWIG_GET_ARRAY_ELEMENT_ZVAL (object , zitem TSRMLS_CC );
894+ ret = TWIG_GET_ARRAY_ELEMENT_ZVAL (object , tmp_item TSRMLS_CC );
845895
846896 if (!ret ) {
847897 ret = & EG (uninitialized_zval );
@@ -932,24 +982,21 @@ PHP_FUNCTION(twig_template_get_attributes)
932982
933983 return ;
934984 }
935- /*
936- $class = get_class($object);
937- */
938-
939- class_name = TWIG_GET_CLASS_NAME (object TSRMLS_CC );
940- tmp_self_cache = TWIG_GET_STATIC_PROPERTY (template , "cache" TSRMLS_CC );
941- tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
942-
943- if (!tmp_class ) {
944- twig_add_class_to_cache (tmp_self_cache , object , class_name TSRMLS_CC );
945- tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
946- }
947- efree (class_name );
948985
949986/*
950987 // object property
951988 if (Twig_Template::METHOD_CALL !== $type) {
989+ $property = null;
990+
952991 if (isset($object->$item) || array_key_exists((string) $item, $object)) {
992+ $property = $item;
993+ } elseif (isset(self::$cache[$class]['properties'][$item])
994+ && isset($object->{self::$cache[$class]['properties'][$item]})
995+ ) {
996+ $property = self::$cache[$class]['properties'][$item];
997+ }
998+
999+ if (null !== $property) {
9531000 if ($isDefinedTest) {
9541001 return true;
9551002 }
@@ -963,23 +1010,30 @@ PHP_FUNCTION(twig_template_get_attributes)
9631010 }
9641011*/
9651012 if (strcmp ("method" , type ) != 0 ) {
966- zval * tmp_properties , * tmp_item ;
1013+ zval * tmp_properties , * tmp_item = NULL ;
9671014
9681015 tmp_properties = TWIG_GET_ARRAY_ELEMENT (tmp_class , "properties" , strlen ("properties" ) TSRMLS_CC );
969- tmp_item = TWIG_GET_ARRAY_ELEMENT (tmp_properties , item , item_len TSRMLS_CC );
9701016
971- if (tmp_item || TWIG_HAS_PROPERTY (object , zitem TSRMLS_CC ) || TWIG_HAS_DYNAMIC_PROPERTY (object , item , item_len TSRMLS_CC )) {
1017+ if (TWIG_HAS_PROPERTY (object , zitem TSRMLS_CC ) || TWIG_HAS_DYNAMIC_PROPERTY (object , item , item_len TSRMLS_CC )) {
1018+ tmp_item = zitem ;
1019+ } else if (tmp_item = TWIG_GET_ARRAY_ELEMENT (tmp_properties , item , item_len TSRMLS_CC )) {
1020+ if (!TWIG_HAS_PROPERTY (object , tmp_item TSRMLS_CC ) && !TWIG_HAS_DYNAMIC_PROPERTY (object , Z_STRVAL_P (tmp_item ), strlen (tmp_item ) TSRMLS_CC )) {
1021+ tmp_item = NULL ;
1022+ }
1023+ }
1024+
1025+ if (tmp_item ) {
9721026 if (isDefinedTest ) {
9731027 RETURN_TRUE ;
9741028 }
9751029 if (TWIG_CALL_SB (TWIG_PROPERTY_CHAR (template , "env" TSRMLS_CC ), "hasExtension" , "sandbox" TSRMLS_CC )) {
976- TWIG_CALL_ZZ (TWIG_CALL_S (TWIG_PROPERTY_CHAR (template , "env" TSRMLS_CC ), "getExtension" , "sandbox" TSRMLS_CC ), "checkPropertyAllowed" , object , zitem TSRMLS_CC );
1030+ TWIG_CALL_ZZ (TWIG_CALL_S (TWIG_PROPERTY_CHAR (template , "env" TSRMLS_CC ), "getExtension" , "sandbox" TSRMLS_CC ), "checkPropertyAllowed" , object , tmp_item TSRMLS_CC );
9771031 }
9781032 if (EG (exception )) {
9791033 return ;
9801034 }
9811035
982- ret = TWIG_PROPERTY (object , zitem TSRMLS_CC );
1036+ ret = TWIG_PROPERTY (object , tmp_item TSRMLS_CC );
9831037 RETURN_ZVAL (ret , 1 , 0 );
9841038 }
9851039 }
0 commit comments