88namespace Magento \QuoteGraphQl \Plugin ;
99
1010use Magento \Catalog \Model \ResourceModel \Product \Attribute \CollectionFactory as AttributeCollectionFactory ;
11- use Magento \Eav \Model \Validator \Attribute \Code ;
12- use Magento \Framework \App \ObjectManager ;
1311use Magento \Framework \GraphQl \Query \Fields ;
12+ use Magento \Framework \Validator \StringLength ;
1413use Magento \Framework \Validator \ValidateException ;
14+ use Magento \Framework \Validator \ValidatorChain ;
1515use Magento \Quote \Model \Quote \Config as QuoteConfig ;
1616
1717/**
1818 * Class for extending product attributes for quote.
1919 */
2020class ProductAttributesExtender
2121{
22+ /**
23+ * Validation pattern for attribute code
24+ */
25+ private const VALIDATION_RULE_PATTERN = '/^[a-zA-Z]+[a-zA-Z0-9_]*$/u ' ;
26+
27+ private const ATTRIBUTE_CODE_MAX_LENGTH = 60 ;
28+
29+ private const ATTRIBUTE_CODE_MIN_LENGTH = 1 ;
30+
2231 /**
2332 * @var Fields
2433 */
@@ -30,27 +39,29 @@ class ProductAttributesExtender
3039 private $ attributeCollectionFactory ;
3140
3241 /**
33- * @var Code
42+ * @var string
43+ */
44+ private $ fieldsHash = '' ;
45+
46+ /**
47+ * @var array
3448 */
35- private Code $ attributeCodeValidator ;
49+ private $ attributes ;
3650
3751 /**
3852 * @param Fields $fields
3953 * @param AttributeCollectionFactory $attributeCollectionFactory
40- * @param Code|null $attributeCodeValidator
4154 */
4255 public function __construct (
4356 Fields $ fields ,
44- AttributeCollectionFactory $ attributeCollectionFactory ,
45- Code $ attributeCodeValidator = null
57+ AttributeCollectionFactory $ attributeCollectionFactory
4658 ) {
4759 $ this ->fields = $ fields ;
4860 $ this ->attributeCollectionFactory = $ attributeCollectionFactory ;
49- $ this ->attributeCodeValidator = $ attributeCodeValidator ?? ObjectManager::getInstance ()->get (Code::class);
5061 }
5162
5263 /**
53- * Get only attribute code that pass validation
64+ * Get only attribute codes that pass validation
5465 *
5566 * @return array
5667 */
@@ -60,31 +71,66 @@ private function getValidatedAttributeCodes(): array
6071 }
6172
6273 /**
63- * @param string|int $code
74+ * Validate attribute code
75+ *
76+ * @param string|int $attributeCode
6477 * @return bool
6578 * @throws ValidateException
6679 */
67- private function validateAttributeCode (string |int $ code )
80+ private function validateAttributeCode (string |int $ attributeCode ): bool
6881 {
69- return $ this ->attributeCodeValidator ->isValid ((string )$ code );
82+ $ attributeCode = trim ((string )$ attributeCode );
83+ if (strlen ($ attributeCode ) > 0
84+ && !preg_match (self ::VALIDATION_RULE_PATTERN , $ attributeCode )
85+ ) {
86+ return false ;
87+ }
88+
89+ $ minLength = self ::ATTRIBUTE_CODE_MIN_LENGTH ;
90+ $ maxLength = self ::ATTRIBUTE_CODE_MAX_LENGTH ;
91+ $ isAllowedLength = ValidatorChain::is (
92+ $ attributeCode ,
93+ StringLength::class,
94+ ['min ' => $ minLength , 'max ' => $ maxLength ]
95+ );
96+ if (!$ isAllowedLength ) {
97+ return false ;
98+ }
99+
100+ return true ;
70101 }
71102
72103 /**
73- * Add requested product attributes.
104+ * Get attributes collection based on validated codes
74105 *
75- * @param QuoteConfig $subject
76- * @param array $result
77106 * @return array
78- * @SuppressWarnings(PHPMD.UnusedFormalParameter)
79107 */
80- public function afterGetProductAttributes ( QuoteConfig $ subject , array $ result ): array
108+ private function getAttributeCollection ()
81109 {
82110 $ attributeCollection = $ this ->attributeCollectionFactory ->create ()
83111 ->removeAllFieldsFromSelect ()
84112 ->addFieldToSelect ('attribute_code ' )
85113 ->setCodeFilter ($ this ->getValidatedAttributeCodes ())
86114 ->load ();
87- $ attributes = $ attributeCollection ->getColumnValues ('attribute_code ' );
115+ return $ attributeCollection ->getColumnValues ('attribute_code ' );
116+ }
117+
118+ /**
119+ * Add requested product attributes.
120+ *
121+ * @param QuoteConfig $subject
122+ * @param array $result
123+ * @return array
124+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
125+ */
126+ public function afterGetProductAttributes (QuoteConfig $ subject , array $ result ): array
127+ {
128+ $ hash = hash ('sha256 ' , json_encode ($ this ->fields ->getFieldsUsedInQuery ()));
129+ if (!$ this ->fieldsHash || $ this ->fieldsHash !== $ hash ) {
130+ $ this ->fieldsHash = hash ('sha256 ' , json_encode ($ this ->fields ->getFieldsUsedInQuery ()));
131+ $ this ->attributes = $ this ->getAttributeCollection ();
132+ }
133+ $ attributes = $ this ->attributes ;
88134
89135 return array_unique (array_merge ($ result , $ attributes ));
90136 }
0 commit comments