@@ -733,10 +733,11 @@ static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args,
733733 zend_class_entry * ce ;
734734 zval * retval ;
735735 char * class_name , * prop_name ;
736+
736737 zend_property_info * pptr = (zend_property_info * ) pDest ;
737738 APPLY_TSRMLS_FETCH ();
738739
739- if (! (pptr -> flags & ZEND_ACC_PUBLIC ) || (pptr -> flags & ZEND_ACC_STATIC )) {
740+ if ((pptr -> flags & ZEND_ACC_PRIVATE ) || (pptr -> flags & ZEND_ACC_STATIC )) {
740741 return 0 ;
741742 }
742743
@@ -750,6 +751,7 @@ static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args,
750751#endif
751752
752753 add_assoc_string (retval , prop_name , prop_name , 1 );
754+ add_assoc_string (retval , TWIG_DECAMELIZE (prop_name ), prop_name , 1 );
753755
754756 return 0 ;
755757}
@@ -769,6 +771,7 @@ static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name
769771 array_init (class_properties );
770772 // add all methods to self::cache[$class]['methods']
771773 zend_hash_apply_with_arguments (& class_ce -> function_table APPLY_TSRMLS_CC , twig_add_method_to_class , 1 , class_methods );
774+ // add all properties to self::cache[$class]['properties']
772775 zend_hash_apply_with_arguments (& class_ce -> properties_info APPLY_TSRMLS_CC , twig_add_property_to_class , 2 , & class_ce , class_properties );
773776
774777 add_assoc_zval (class_info , "methods" , class_methods );
@@ -813,14 +816,46 @@ PHP_FUNCTION(twig_template_get_attributes)
813816 type = "any" ;
814817 }
815818
819+ /*
820+ if (is_object($object)) {
821+ $class = get_class($object);
822+ if (!isset(self::$cache[$class])) {
823+ self::$cache[$class] = $this->getCacheForClass($class);
824+ }
825+ }
826+ */
827+ if (Z_TYPE_P (object ) == IS_OBJECT ) {
828+ class_name = TWIG_GET_CLASS_NAME (object TSRMLS_CC );
829+ tmp_self_cache = TWIG_GET_STATIC_PROPERTY (template , "cache" TSRMLS_CC );
830+ tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
831+
832+ if (!tmp_class ) {
833+ twig_add_class_to_cache (tmp_self_cache , object , class_name TSRMLS_CC );
834+ tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
835+ }
836+ efree (class_name );
837+ }
838+
816839/*
817840 // array
818841 if (Twig_Template::METHOD_CALL !== $type) {
819842 $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
843+ $hasArrayItem = false;
844+
845+ if (is_array($object) && array_key_exists($arrayItem, $object)) {
846+ $hasArrayItem = true;
847+ } elseif ($object instanceof ArrayAccess) {
848+ if (isset($object[$arrayItem])) {
849+ $hasArrayItem = true;
850+ } elseif (isset(self::$cache[$class]['properties'][$arrayItem])
851+ && isset($object[self::$cache[$class]['properties'][$arrayItem]])
852+ ) {
853+ $arrayItem = self::$cache[$class]['properties'][$arrayItem];
854+ $hasArrayItem = true;
855+ }
856+ }
820857
821- if ((is_array($object) && array_key_exists($arrayItem, $object))
822- || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
823- ) {
858+ if ($hasArrayItem) {
824859 if ($isDefinedTest) {
825860 return true;
826861 }
@@ -831,15 +866,29 @@ PHP_FUNCTION(twig_template_get_attributes)
831866
832867
833868 if (strcmp ("method" , type ) != 0 ) {
834- if ((TWIG_ARRAY_KEY_EXISTS (object , zitem ))
835- || (TWIG_INSTANCE_OF (object , zend_ce_arrayaccess TSRMLS_CC ) && TWIG_ISSET_ARRAYOBJECT_ELEMENT (object , zitem TSRMLS_CC ))
836- ) {
869+ zval * tmp_properties , * tmp_item = NULL ;
870+
871+ if (TWIG_ARRAY_KEY_EXISTS (object , zitem )) {
872+ tmp_item = zitem ;
873+ } else if (TWIG_INSTANCE_OF (object , zend_ce_arrayaccess TSRMLS_CC )) {
874+ if (TWIG_ISSET_ARRAYOBJECT_ELEMENT (object , zitem TSRMLS_CC )) {
875+ tmp_item = zitem ;
876+ } else {
877+ tmp_properties = TWIG_GET_ARRAY_ELEMENT (tmp_class , "properties" , strlen ("properties" ) TSRMLS_CC );
878+ if ((tmp_item = TWIG_GET_ARRAY_ELEMENT (tmp_properties , item , item_len TSRMLS_CC ))
879+ && !TWIG_ISSET_ARRAYOBJECT_ELEMENT (object , tmp_item TSRMLS_CC )
880+ ) {
881+ tmp_item = NULL ;
882+ }
883+ }
884+ }
837885
886+ if (tmp_item ) {
838887 if (isDefinedTest ) {
839888 RETURN_TRUE ;
840889 }
841890
842- ret = TWIG_GET_ARRAY_ELEMENT_ZVAL (object , zitem TSRMLS_CC );
891+ ret = TWIG_GET_ARRAY_ELEMENT_ZVAL (object , tmp_item TSRMLS_CC );
843892
844893 if (!ret ) {
845894 ret = & EG (uninitialized_zval );
@@ -856,7 +905,7 @@ PHP_FUNCTION(twig_template_get_attributes)
856905 return false;
857906 }
858907 if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
859- return null ;
908+ return;
860909 }
861910*/
862911 if (strcmp ("array" , type ) == 0 || Z_TYPE_P (object ) != IS_OBJECT ) {
@@ -924,8 +973,9 @@ PHP_FUNCTION(twig_template_get_attributes)
924973 }
925974/*
926975 if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
927- return null ;
976+ return;
928977 }
978+
929979 throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
930980 }
931981*/
@@ -943,65 +993,64 @@ PHP_FUNCTION(twig_template_get_attributes)
943993
944994 return ;
945995 }
946- /*
947- $class = get_class($object);
948- */
949-
950- class_name = TWIG_GET_CLASS_NAME (object TSRMLS_CC );
951- tmp_self_cache = TWIG_GET_STATIC_PROPERTY (template , "cache" TSRMLS_CC );
952- tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
953-
954- if (!tmp_class ) {
955- twig_add_class_to_cache (tmp_self_cache , object , class_name TSRMLS_CC );
956- tmp_class = TWIG_GET_ARRAY_ELEMENT (tmp_self_cache , class_name , strlen (class_name ) TSRMLS_CC );
957- }
958- efree (class_name );
959996
960997/*
961998 // object property
962999 if (Twig_Template::METHOD_CALL !== $type) {
1000+ $property = null;
1001+
9631002 if (isset($object->$item) || array_key_exists((string) $item, $object)) {
1003+ $property = $item;
1004+ } elseif (isset(self::$cache[$class]['properties'][$item])
1005+ && isset($object->{self::$cache[$class]['properties'][$item]})
1006+ ) {
1007+ $property = self::$cache[$class]['properties'][$item];
1008+ }
1009+
1010+ if (null !== $property) {
9641011 if ($isDefinedTest) {
9651012 return true;
9661013 }
9671014
9681015 if ($this->env->hasExtension('sandbox')) {
969- $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item );
1016+ $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $property );
9701017 }
9711018
972- return $object->$item ;
1019+ return $object->$property ;
9731020 }
9741021 }
9751022*/
9761023 if (strcmp ("method" , type ) != 0 ) {
977- zval * tmp_properties , * tmp_item ;
1024+ zval * tmp_properties , * tmp_item = NULL ;
9781025
9791026 tmp_properties = TWIG_GET_ARRAY_ELEMENT (tmp_class , "properties" , strlen ("properties" ) TSRMLS_CC );
980- tmp_item = TWIG_GET_ARRAY_ELEMENT (tmp_properties , item , item_len TSRMLS_CC );
9811027
982- if (tmp_item || TWIG_HAS_PROPERTY (object , zitem TSRMLS_CC ) || TWIG_HAS_DYNAMIC_PROPERTY (object , item , item_len TSRMLS_CC )) {
1028+ if (TWIG_HAS_PROPERTY (object , zitem TSRMLS_CC ) || TWIG_HAS_DYNAMIC_PROPERTY (object , item , item_len TSRMLS_CC )) {
1029+ tmp_item = zitem ;
1030+ } else if (tmp_item = TWIG_GET_ARRAY_ELEMENT (tmp_properties , item , item_len TSRMLS_CC )) {
1031+ if (!TWIG_HAS_PROPERTY (object , tmp_item TSRMLS_CC ) && !TWIG_HAS_DYNAMIC_PROPERTY (object , Z_STRVAL_P (tmp_item ), strlen (tmp_item ) TSRMLS_CC )) {
1032+ tmp_item = NULL ;
1033+ }
1034+ }
1035+
1036+ if (tmp_item ) {
9831037 if (isDefinedTest ) {
9841038 RETURN_TRUE ;
9851039 }
9861040 if (TWIG_CALL_SB (TWIG_PROPERTY_CHAR (template , "env" TSRMLS_CC ), "hasExtension" , "sandbox" TSRMLS_CC )) {
987- TWIG_CALL_ZZ (TWIG_CALL_S (TWIG_PROPERTY_CHAR (template , "env" TSRMLS_CC ), "getExtension" , "sandbox" TSRMLS_CC ), "checkPropertyAllowed" , object , zitem TSRMLS_CC );
1041+ TWIG_CALL_ZZ (TWIG_CALL_S (TWIG_PROPERTY_CHAR (template , "env" TSRMLS_CC ), "getExtension" , "sandbox" TSRMLS_CC ), "checkPropertyAllowed" , object , tmp_item TSRMLS_CC );
9881042 }
9891043 if (EG (exception )) {
9901044 return ;
9911045 }
9921046
993- ret = TWIG_PROPERTY (object , zitem TSRMLS_CC );
1047+ ret = TWIG_PROPERTY (object , tmp_item TSRMLS_CC );
9941048 RETURN_ZVAL (ret , 1 , 0 );
9951049 }
9961050 }
9971051/*
9981052 // object method
999- if (!isset(self::$cache[$class]['methods'])) {
1000- self::$cache[$class] = $this->getCacheForClass($class);
1001- }
1002-
10031053 $call = false;
1004- $lcItem = strtolower($item);
10051054 if (isset(self::$cache[$class]['methods'][$item])) {
10061055 $method = self::$cache[$class]['methods'][$item];
10071056 } elseif (($lcItem = strtolower($item)) && isset(self::$cache[$class]['methods'][$lcItem])) {
@@ -1031,7 +1080,7 @@ PHP_FUNCTION(twig_template_get_attributes)
10311080 }
10321081
10331082 if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
1034- return null ;
1083+ return;
10351084 }
10361085
10371086 throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
@@ -1076,7 +1125,7 @@ PHP_FUNCTION(twig_template_get_attributes)
10761125 $ret = call_user_func_array(array($object, $method), $arguments);
10771126 } catch (BadMethodCallException $e) {
10781127 if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
1079- return null ;
1128+ return;
10801129 }
10811130 throw $e;
10821131 }
0 commit comments