Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
ActionObjectExtractor.php
Go to the documentation of this file.
1 <?php
8 
15 
20 {
21  const TEST_ACTION_BEFORE = 'before';
22  const TEST_ACTION_AFTER = 'after';
23  const TEST_STEP_MERGE_KEY = 'stepKey';
24  const ACTION_GROUP_TAG = 'actionGroup';
25  const ACTION_GROUP_REF = 'ref';
26  const ACTION_GROUP_ARGUMENTS = 'arguments';
27  const ACTION_GROUP_ARG_VALUE = 'value';
28  const BEFORE_AFTER_ERROR_MSG = "Merge Error - Steps cannot have both before and after attributes.\tStepKey='%s'";
29  const STEP_KEY_BLACKLIST_ERROR_MSG = "StepKeys cannot contain non alphanumeric characters.\tStepKey='%s'";
30  const STEP_KEY_EMPTY_ERROR_MSG = "StepKeys cannot be empty.\tAction='%s'";
33  const ACTION_OBJECT_PERSISTENCE_FIELDS = 'customFields';
34  const ACTION_OBJECT_USER_INPUT = 'userInput';
35  const DATA_PERSISTENCE_ACTIONS = ['createData', 'deleteData', 'updateData'];
36 
40  public function __construct()
41  {
42  //public constructor
43  }
44 
55  public function extractActions($testActions, $testName = null)
56  {
57  $actions = [];
58  $stepKeyRefs = [];
59 
60  foreach ($testActions as $actionName => $actionData) {
61  $stepKey = $actionData[self::TEST_STEP_MERGE_KEY];
62  $actionType = $actionData[self::NODE_NAME];
63 
64  if (empty($stepKey)) {
65  throw new XmlException(sprintf(self::STEP_KEY_EMPTY_ERROR_MSG, $actionData['nodeName']));
66  }
67 
68  if (preg_match('/[^a-zA-Z0-9_]/', $stepKey)) {
69  throw new XmlException(sprintf(self::STEP_KEY_BLACKLIST_ERROR_MSG, $actionName));
70  }
71 
72  $actionAttributes = $this->stripDescriptorTags(
73  $actionData,
74  self::TEST_STEP_MERGE_KEY,
75  self::NODE_NAME
76  );
77 
78  // Flatten AssertSorted "array" element to parameterArray
79  if (isset($actionData["array"])) {
80  $actionAttributes['parameterArray'] = $actionData['array']['value'];
81  }
82 
83  $actionAttributes = $this->processActionGroupArgs($actionType, $actionAttributes);
84  $linkedAction = $this->processLinkedActions($actionName, $actionData);
85  $actions = $this->extractFieldActions($actionData, $actions);
86  $actionAttributes = $this->extractFieldReferences($actionData, $actionAttributes);
87 
88  if ($linkedAction['stepKey'] != null) {
89  $stepKeyRefs[$linkedAction['stepKey']][] = $stepKey;
90  }
91 
92  // TODO this is to be implemented later. Currently the schema does not use or need return var.
93  /*if (array_key_exists(ActionGroupObjectHandler::TEST_ACTION_RETURN_VARIABLE, $actionData)) {
94  $returnVariable = $actionData[ActionGroupObjectHandler::TEST_ACTION_RETURN_VARIABLE];
95  }*/
96 
97  $actions[$stepKey] = new ActionObject(
98  $stepKey,
99  $actionType,
100  $actionAttributes,
101  $linkedAction['stepKey'],
102  $linkedAction['order']
103  );
104  }
105 
106  $this->auditMergeSteps($stepKeyRefs, $testName);
107 
108  return $actions;
109  }
110 
120  private function processLinkedActions($actionName, $actionData)
121  {
122  $linkedAction =['stepKey' => null, 'order' => null];
123  if (array_key_exists(self::TEST_ACTION_BEFORE, $actionData)
124  and array_key_exists(self::TEST_ACTION_AFTER, $actionData)) {
125  throw new XmlException(sprintf(self::BEFORE_AFTER_ERROR_MSG, $actionName));
126  }
127 
128  if (array_key_exists(self::TEST_ACTION_BEFORE, $actionData)) {
129  $linkedAction['stepKey'] = $actionData[self::TEST_ACTION_BEFORE];
130  $linkedAction['order'] = self::TEST_ACTION_BEFORE;
131  } elseif (array_key_exists(self::TEST_ACTION_AFTER, $actionData)) {
132  $linkedAction['stepKey'] = $actionData[self::TEST_ACTION_AFTER];
133  $linkedAction['order'] = self::TEST_ACTION_AFTER;
134  }
135 
136  return $linkedAction;
137  }
138 
147  private function processActionGroupArgs($actionType, $actionAttributeData)
148  {
149  if ($actionType !== self::ACTION_GROUP_TAG) {
150  return $actionAttributeData;
151  }
152 
153  $actionAttributeArgData = [];
154  foreach ($actionAttributeData as $attributeDataKey => $attributeDataValues) {
155  if ($attributeDataKey == self::ACTION_GROUP_REF) {
156  $actionAttributeArgData[self::ACTION_GROUP_REF] = $attributeDataValues;
157  continue;
158  }
159 
160  $actionAttributeArgData[self::ACTION_GROUP_ARGUMENTS][$attributeDataKey] =
161  $attributeDataValues[self::ACTION_GROUP_ARG_VALUE] ?? null;
162  }
163 
164  return $actionAttributeArgData;
165  }
166 
178  private function extractFieldActions($actionData, $actions)
179  {
180  if (!in_array($actionData[self::NODE_NAME], self::DATA_PERSISTENCE_ACTIONS)) {
181  return $actions;
182  }
183 
184  $fieldActions = [];
185  foreach ($actionData as $type => $data) {
186  // determine if field type is entity passed in
187  if (!is_array($data) || $data[self::NODE_NAME] != self::DATA_PERSISTENCE_CUSTOM_FIELD) {
188  continue;
189  }
190 
191  // must append stepKey and userInput to resolve fields passed in properly via extractActions method
192  $fieldData = $data;
193  $fieldData[self::TEST_STEP_MERGE_KEY] = $actionData[self::TEST_STEP_MERGE_KEY]
194  . ucfirst($fieldData[self::DATA_PERSISTENCE_CUSTOM_FIELD_KEY]);
195  $fieldData[self::ACTION_OBJECT_USER_INPUT] = $fieldData['value'];
196  $fieldActions[] = $fieldData;
197  }
198 
199  // merge resolved actions with those psased in and return
200  return array_merge($actions, $this->extractActions($fieldActions));
201  }
202 
212  private function extractFieldReferences($actionData, $actionAttributes)
213  {
214  if (!in_array($actionData[self::NODE_NAME], self::DATA_PERSISTENCE_ACTIONS)) {
215  return $actionAttributes;
216  }
217 
218  $attributes = [];
219  foreach ($actionAttributes as $attributeName => $attributeValue) {
220  if (!is_array($attributeValue) || $attributeValue[self::NODE_NAME] != self::DATA_PERSISTENCE_CUSTOM_FIELD) {
221  $attributes[$attributeName] = $attributeValue;
222  continue;
223  }
224 
226  }
227 
228  if (array_key_exists(self::ACTION_OBJECT_PERSISTENCE_FIELDS, $attributes)) {
230  }
231 
232  return $attributes;
233  }
234 
243  private function auditMergeSteps($stepKeyRefs, $testName)
244  {
245  if (empty($stepKeyRefs)) {
246  return;
247  }
248 
249  // check for step keys which are referencing themselves as before/after
250  $invalidStepRef = array_filter($stepKeyRefs, function ($value, $key) {
251  return in_array($key, $value);
252  }, ARRAY_FILTER_USE_BOTH);
253 
254  if (!empty($invalidStepRef)) {
255  throw new TestReferenceException(
256  "Invalid ordering configuration in test",
257  ['test' => $testName, 'stepKey' => array_keys($invalidStepRef)]
258  );
259  }
260 
261  // check for ambiguous references to step keys (multiple refs across test merges).
262  $atRiskStepRef = array_filter($stepKeyRefs, function ($value) {
263  return count($value) > 1;
264  });
265 
266  foreach ($atRiskStepRef as $stepKey => $stepRefs) {
267  LoggingUtil::getInstance()->getLogger(ActionObjectExtractor::class)->warn(
268  'multiple actions referencing step key',
269  ['test' => $testName, 'stepKey' => $stepKey, 'ref' => $stepRefs]
270  );
271  }
272  }
273 }
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
$type
Definition: item.phtml:13
$value
Definition: gender.phtml:16
$attributes
Definition: matrix.phtml:13