@@ -605,12 +605,123 @@ NR_PHP_WRAPPER(nr_drupal94_invoke_all_with_clean) {
605
605
NR_PHP_WRAPPER_END
606
606
#endif // OAPI
607
607
608
+ /*
609
+ * Purpose: Instrument Drupal Attribute Hooks for Drupal 11.1+
610
+ *
611
+ * Params: 1. A zval pointer to the moduleHandler instance in use by Drupal.
612
+ *
613
+ * Return: bool
614
+ *
615
+ */
616
+ static bool nr_drupal_hook_attribute_instrument (zval * module_handler ) {
617
+ zval * hook_implementation_map = NULL ;
618
+
619
+ nr_php_string_hash_key_t * hook_key = NULL ;
620
+ zval * hook_val = NULL ;
621
+ nr_php_string_hash_key_t * class_key = NULL ;
622
+ zval * class_val = NULL ;
623
+ nr_php_string_hash_key_t * method_key = NULL ;
624
+ zval * module_val = NULL ;
625
+ zend_ulong key_num = 0 ;
626
+
627
+ char * hook_str = NULL ;
628
+ char * class_str = NULL ;
629
+ char * method_str = NULL ;
630
+ char * module_str = NULL ;
631
+ char * hookpath = NULL ;
632
+
633
+ hook_implementation_map = nr_php_get_zval_object_property (
634
+ module_handler , "hookImplementationsMap" );
635
+ if (hook_implementation_map ) {
636
+ if (nr_php_is_zval_valid_array (hook_implementation_map )) {
637
+ ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P (hook_implementation_map ), key_num ,
638
+ hook_key , hook_val ) {
639
+ (void )key_num ;
640
+ if ((NULL == hook_key ) || (0 == nr_php_is_zval_valid_array (hook_val ))) {
641
+ nrl_warning (NRL_FRAMEWORK ,
642
+ "hookImplementationsMap[hook = %s]: invalid value" ,
643
+ NRSAFESTR (ZEND_STRING_VALUE (hook_key )));
644
+ return false;
645
+ }
646
+
647
+ ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P (hook_val ), key_num , class_key ,
648
+ class_val ) {
649
+ (void )key_num ;
650
+ if ((NULL == class_key )
651
+ || (0 == nr_php_is_zval_valid_array (class_val ))) {
652
+ nrl_warning (NRL_FRAMEWORK ,
653
+ "hookImplementationsMap[class = %s]: invalid value" ,
654
+ NRSAFESTR (ZEND_STRING_VALUE (class_key )));
655
+ return false;
656
+ }
657
+
658
+ ZEND_HASH_FOREACH_KEY_VAL (Z_ARRVAL_P (class_val ), key_num , method_key ,
659
+ module_val ) {
660
+ (void )key_num ;
661
+
662
+ nr_free (hook_str );
663
+ nr_free (class_str );
664
+ nr_free (method_str );
665
+ nr_free (module_str );
666
+ nr_free (hookpath );
667
+
668
+ if ((NULL == method_key )
669
+ || (0 == nr_php_is_zval_valid_string (module_val ))) {
670
+ nrl_warning (NRL_FRAMEWORK ,
671
+ "hookImplementationsMap[method = %s]: invalid value" ,
672
+ NRSAFESTR (ZEND_STRING_VALUE (method_key )));
673
+ return false;
674
+ }
675
+
676
+ hook_str = nr_strdup (ZEND_STRING_VALUE (hook_key ));
677
+ class_str = nr_strdup (ZEND_STRING_VALUE (class_key ));
678
+ method_str = nr_strdup (ZEND_STRING_VALUE (method_key ));
679
+ module_str = nr_strdup (Z_STRVAL_P (module_val ));
680
+
681
+ if (0
682
+ == nr_stricmp (ZEND_STRING_VALUE (class_key ),
683
+ "Drupal\\Core\\Extension\\ProceduralCall" )) {
684
+ hookpath = nr_formatf ("%s" , method_str );
685
+ } else {
686
+ hookpath = nr_formatf ("%s::%s" , class_str , method_str );
687
+ }
688
+
689
+ nr_php_wrap_user_function_drupal (hookpath , nr_strlen (hookpath ),
690
+ module_str , nr_strlen (module_str ),
691
+ hook_str , nr_strlen (hook_str ));
692
+ }
693
+ ZEND_HASH_FOREACH_END ();
694
+ }
695
+ ZEND_HASH_FOREACH_END ();
696
+ }
697
+ ZEND_HASH_FOREACH_END ();
698
+
699
+ } else {
700
+ nrl_warning (NRL_FRAMEWORK ,
701
+ "hookImplementationsMap property not a valid array" );
702
+ return false;
703
+ }
704
+ } else {
705
+ nrl_warning (NRL_FRAMEWORK , "NULL hookImplementationsMap object property" );
706
+ return false;
707
+ }
708
+
709
+ nr_free (hook_str );
710
+ nr_free (class_str );
711
+ nr_free (method_str );
712
+ nr_free (module_str );
713
+ nr_free (hookpath );
714
+
715
+ return true;
716
+ }
717
+
608
718
/*
609
719
* Purpose : Wrap the invoke() method of the module handler instance in use.
610
720
*/
611
721
NR_PHP_WRAPPER (nr_drupal8_module_handler ) {
612
722
zend_class_entry * ce = NULL ;
613
723
zval * * retval_ptr = NR_GET_RETURN_VALUE_PTR ;
724
+ bool hook_attribute_instrumentation = false;
614
725
615
726
NR_UNUSED_SPECIALFN ;
616
727
(void )wraprec ;
@@ -632,20 +743,26 @@ NR_PHP_WRAPPER(nr_drupal8_module_handler) {
632
743
633
744
ce = Z_OBJCE_P (* retval_ptr );
634
745
635
- nr_drupal8_add_method_callback (ce , NR_PSTR ("getimplementations" ),
636
- nr_drupal8_post_get_implementations TSRMLS_CC );
637
- nr_drupal8_add_method_callback (ce , NR_PSTR ("implementshook" ),
638
- nr_drupal8_post_implements_hook TSRMLS_CC );
639
- /* Drupal 9.4 introduced a replacement method for getImplentations */
746
+ hook_attribute_instrumentation
747
+ = nr_drupal_hook_attribute_instrument (* retval_ptr );
748
+
749
+ if (!hook_attribute_instrumentation ) {
750
+ nr_drupal8_add_method_callback (
751
+ ce , NR_PSTR ("getimplementations" ),
752
+ nr_drupal8_post_get_implementations TSRMLS_CC );
753
+ nr_drupal8_add_method_callback (ce , NR_PSTR ("implementshook" ),
754
+ nr_drupal8_post_implements_hook TSRMLS_CC );
755
+ /* Drupal 9.4 introduced a replacement method for getImplentations */
640
756
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO \
641
757
&& !defined OVERWRITE_ZEND_EXECUTE_DATA
642
- nr_drupal8_add_method_callback_before_after_clean (
643
- ce , NR_PSTR ("invokeallwith" ), nr_drupal94_invoke_all_with ,
644
- nr_drupal94_invoke_all_with_after , nr_drupal94_invoke_all_with_clean );
758
+ nr_drupal8_add_method_callback_before_after_clean (
759
+ ce , NR_PSTR ("invokeallwith" ), nr_drupal94_invoke_all_with ,
760
+ nr_drupal94_invoke_all_with_after , nr_drupal94_invoke_all_with_clean );
645
761
#else
646
- nr_drupal8_add_method_callback (ce , NR_PSTR ("invokeallwith" ),
647
- nr_drupal94_invoke_all_with TSRMLS_CC );
762
+ nr_drupal8_add_method_callback (ce , NR_PSTR ("invokeallwith" ),
763
+ nr_drupal94_invoke_all_with TSRMLS_CC );
648
764
#endif
765
+ }
649
766
}
650
767
NR_PHP_WRAPPER_END
651
768
0 commit comments