From a45cd5aabfdf823b48e0ea5bcbd1b42eee82cb38 Mon Sep 17 00:00:00 2001 From: Rich Lott / Artful Robot Date: Sat, 18 Apr 2020 08:55:51 +0100 Subject: [PATCH] dev-core/1719: replace xml encoding function in CaseType --- CRM/Case/BAO/CaseType.php | 149 +- tests/phpunit/CRM/Case/BAO/CaseTypeTest.php | 13 + tests/phpunit/CRM/Case/BAO/xml/empty-defn.xml | 2 +- .../phpunit/CRM/Case/BAO/xml/empty-lists.xml | 2 +- .../CRM/Case/BAO/xml/empty-node-text.xml | 2 +- tests/phpunit/CRM/Case/BAO/xml/forkable-0.xml | 2 +- tests/phpunit/CRM/Case/BAO/xml/forkable-1.xml | 2 +- .../CRM/Case/BAO/xml/one-item-in-each.xml | 2 +- tests/phpunit/CRM/Case/BAO/xml/statuses.xml | 14 + .../CRM/Case/BAO/xml/two-items-in-each.xml | 2 +- .../Incremental/php/FiveTwentyTest.php | 1204 ++++++++--------- 11 files changed, 729 insertions(+), 665 deletions(-) create mode 100644 tests/phpunit/CRM/Case/BAO/xml/statuses.xml diff --git a/CRM/Case/BAO/CaseType.php b/CRM/Case/BAO/CaseType.php index 9937c5627257..e10c70da07e0 100644 --- a/CRM/Case/BAO/CaseType.php +++ b/CRM/Case/BAO/CaseType.php @@ -96,50 +96,87 @@ protected function assignTestValue($fieldName, &$fieldDef, $counter) { * XML */ public static function convertDefinitionToXML($name, $definition) { - $xmlFile = '' . "\n\n\n"; - $xmlFile .= "" . self::encodeXmlString($name) . "\n"; + + $xw = new XMLWriter(); + $xw->openMemory(); + $xw->setIndent(TRUE); + $xw->setIndentString(' '); + $xw->startDocument("1.0", 'UTF-8'); + + $xw->startElement('CaseType'); + + $xw->startElement('name'); + $xw->text($name); + $xw->fullEndElement(); if (array_key_exists('forkable', $definition)) { - $xmlFile .= "" . ((int) $definition['forkable']) . "\n"; + $xw->startElement('forkable'); + $xw->text((int) $definition['forkable']); + $xw->fullEndElement(); } if (isset($definition['activityTypes'])) { - $xmlFile .= "\n"; + $xw->startElement('ActivityTypes'); + foreach ($definition['activityTypes'] as $values) { - $xmlFile .= "\n"; + $xw->startElement('ActivityType'); foreach ($values as $key => $value) { - $xmlFile .= "<{$key}>" . self::encodeXmlString($value) . "\n"; + $xw->startElement($key); + $xw->text($value); + $xw->fullEndElement(); } - $xmlFile .= "\n"; + // ActivityType + $xw->fullEndElement(); } - $xmlFile .= "\n"; + // ActivityTypes + $xw->fullEndElement(); } if (!empty($definition['statuses'])) { - $xmlFile .= "\n"; + $xw->startElement('Statuses'); + foreach ($definition['statuses'] as $value) { - $xmlFile .= "$value\n"; + $xw->startElement('Status'); + $xw->text($value); + $xw->fullEndElement(); } - $xmlFile .= "\n"; + // Statuses + $xw->fullEndElement(); } if (isset($definition['activitySets'])) { - $xmlFile .= "\n"; + + $xw->startElement('ActivitySets'); foreach ($definition['activitySets'] as $k => $val) { - $xmlFile .= "\n"; + + $xw->startElement('ActivitySet'); foreach ($val as $index => $setVal) { switch ($index) { case 'activityTypes': if (!empty($setVal)) { - $xmlFile .= "\n"; + $xw->startElement('ActivityTypes'); foreach ($setVal as $values) { - $xmlFile .= "\n"; + $xw->startElement('ActivityType'); foreach ($values as $key => $value) { - $xmlFile .= "<{$key}>" . self::encodeXmlString($value) . "\n"; + // Some parameters here may be arrays of values. + // Also, the tests expect an empty array to be represented as an empty value. + $value = (array) $value; + if (count($value) === 0) { + // Create an empty value. + $value[] = ''; + } + + foreach ($value as $val) { + $xw->startElement($key); + $xw->text($val); + $xw->fullEndElement(); + } } - $xmlFile .= "\n"; + // ActivityType + $xw->fullEndElement(); } - $xmlFile .= "\n"; + // ActivityTypes + $xw->fullEndElement(); } break; @@ -147,68 +184,68 @@ public static function convertDefinitionToXML($name, $definition) { case 'sequence': case 'timeline': if ($setVal) { - $xmlFile .= "<{$index}>true\n"; + $xw->startElement($index); + $xw->text('true'); + $xw->fullEndElement(); } break; default: - $xmlFile .= "<{$index}>" . self::encodeXmlString($setVal) . "\n"; + $xw->startElement($index); + $xw->text($setVal); + $xw->fullEndElement(); } } - - $xmlFile .= "\n"; + // ActivitySet + $xw->fullEndElement(); } - - $xmlFile .= "\n"; + // ActivitySets + $xw->fullEndElement(); } if (isset($definition['caseRoles'])) { - $xmlFile .= "\n"; + $xw->startElement('CaseRoles'); foreach ($definition['caseRoles'] as $values) { - $xmlFile .= "\n"; + $xw->startElement('RelationshipType'); foreach ($values as $key => $value) { - $xmlFile .= "<{$key}>" . ($key == 'groups' ? implode(',', array_map(['\CRM_Case_BAO_CaseType', 'encodeXmlString'], (array) $value)) : self::encodeXmlString($value)) . "\n"; + $xw->startElement($key); + if ($key == 'groups') { + $xw->text(implode(',', (array) $value)); + } + else { + $xw->text($value); + } + // $key + $xw->fullEndElement(); } - $xmlFile .= "\n"; + // RelationshipType + $xw->fullEndElement(); } - $xmlFile .= "\n"; + // CaseRoles + $xw->fullEndElement(); } if (array_key_exists('restrictActivityAsgmtToCmsUser', $definition)) { - $xmlFile .= "" . $definition['restrictActivityAsgmtToCmsUser'] . "\n"; + $xw->startElement('RestrictActivityAsgmtToCmsUser'); + $xw->text($definition['restrictActivityAsgmtToCmsUser']); + $xw->fullEndElement(); } - if (!empty($definition['activityAsgmtGrps'])) { - $xmlFile .= "\n"; + $xw->startElement('ActivityAsgmtGrps'); foreach ((array) $definition['activityAsgmtGrps'] as $value) { - $xmlFile .= "$value\n"; + $xw->startElement('Group'); + $xw->text($value); + $xw->fullEndElement(); } - $xmlFile .= "\n"; + // ActivityAsgmtGrps + $xw->fullEndElement(); } - $xmlFile .= ''; - - return $xmlFile; - } + // CaseType + $xw->fullEndElement(); + $xw->endDocument(); - /** - * Ugh. This shouldn't exist. Use a real XML-encoder. - * - * Escape a string for use in XML. - * - * @param string $str - * A string which should outputted to XML. - * @return string - * @deprecated - */ - protected static function encodeXmlString($str) { - // PHP 5.4: return htmlspecialchars($str, ENT_XML1, 'UTF-8') - if (is_scalar($str)) { - return htmlspecialchars($str); - } - else { - return NULL; - } + return $xw->outputMemory(); } /** diff --git a/tests/phpunit/CRM/Case/BAO/CaseTypeTest.php b/tests/phpunit/CRM/Case/BAO/CaseTypeTest.php index 54514f9bbe34..b93ce0629cdc 100644 --- a/tests/phpunit/CRM/Case/BAO/CaseTypeTest.php +++ b/tests/phpunit/CRM/Case/BAO/CaseTypeTest.php @@ -28,6 +28,18 @@ public function definitionProvider() { 'xml' => file_get_contents(__DIR__ . '/xml/empty-lists.xml'), ]; + $fixtures['statuses'] = [ + 'json' => json_encode([ + 'activitySets' => [], + 'activityTypes' => [], + 'caseRoles' => [], + 'statuses' => ['Ongoing', 'Completed', 'This & That'], + //'statuses' => ['Ongoing', 'Completed'], + 'timelineActivityTypes' => [], + ]), + 'xml' => file_get_contents(__DIR__ . '/xml/statuses.xml'), + ]; + $fixtures['one-item-in-each'] = [ 'json' => json_encode([ 'activityTypes' => [ @@ -177,6 +189,7 @@ public function definitionProvider() { 'two-items-in-each', 'forkable-0', 'forkable-1', + 'statuses', ] as $key) { $cases[] = [$key, $fixtures[$key]['json'], $fixtures[$key]['xml']]; } diff --git a/tests/phpunit/CRM/Case/BAO/xml/empty-defn.xml b/tests/phpunit/CRM/Case/BAO/xml/empty-defn.xml index 575aaa42269b..e94ac3542354 100644 --- a/tests/phpunit/CRM/Case/BAO/xml/empty-defn.xml +++ b/tests/phpunit/CRM/Case/BAO/xml/empty-defn.xml @@ -1,4 +1,4 @@ - + Housing Support diff --git a/tests/phpunit/CRM/Case/BAO/xml/empty-lists.xml b/tests/phpunit/CRM/Case/BAO/xml/empty-lists.xml index 768b6cdb2c38..9c671a37ba71 100644 --- a/tests/phpunit/CRM/Case/BAO/xml/empty-lists.xml +++ b/tests/phpunit/CRM/Case/BAO/xml/empty-lists.xml @@ -1,4 +1,4 @@ - + Housing Support diff --git a/tests/phpunit/CRM/Case/BAO/xml/empty-node-text.xml b/tests/phpunit/CRM/Case/BAO/xml/empty-node-text.xml index 48c116b52351..b36d991bd40c 100644 --- a/tests/phpunit/CRM/Case/BAO/xml/empty-node-text.xml +++ b/tests/phpunit/CRM/Case/BAO/xml/empty-node-text.xml @@ -1,4 +1,4 @@ - + Housing Support diff --git a/tests/phpunit/CRM/Case/BAO/xml/forkable-0.xml b/tests/phpunit/CRM/Case/BAO/xml/forkable-0.xml index a6e6ed1b36c8..49fb5126737f 100644 --- a/tests/phpunit/CRM/Case/BAO/xml/forkable-0.xml +++ b/tests/phpunit/CRM/Case/BAO/xml/forkable-0.xml @@ -1,4 +1,4 @@ - + Housing Support 0 diff --git a/tests/phpunit/CRM/Case/BAO/xml/forkable-1.xml b/tests/phpunit/CRM/Case/BAO/xml/forkable-1.xml index e1427534a725..a483592ebfef 100644 --- a/tests/phpunit/CRM/Case/BAO/xml/forkable-1.xml +++ b/tests/phpunit/CRM/Case/BAO/xml/forkable-1.xml @@ -1,4 +1,4 @@ - + Housing Support 1 diff --git a/tests/phpunit/CRM/Case/BAO/xml/one-item-in-each.xml b/tests/phpunit/CRM/Case/BAO/xml/one-item-in-each.xml index 24452737619d..1822f84645f7 100644 --- a/tests/phpunit/CRM/Case/BAO/xml/one-item-in-each.xml +++ b/tests/phpunit/CRM/Case/BAO/xml/one-item-in-each.xml @@ -1,4 +1,4 @@ - + Housing Support diff --git a/tests/phpunit/CRM/Case/BAO/xml/statuses.xml b/tests/phpunit/CRM/Case/BAO/xml/statuses.xml new file mode 100644 index 000000000000..d32b57db7bc4 --- /dev/null +++ b/tests/phpunit/CRM/Case/BAO/xml/statuses.xml @@ -0,0 +1,14 @@ + + + + Housing Support + + + Ongoing + Completed + This & That + + + + + diff --git a/tests/phpunit/CRM/Case/BAO/xml/two-items-in-each.xml b/tests/phpunit/CRM/Case/BAO/xml/two-items-in-each.xml index 313c6652bf02..82f678636763 100644 --- a/tests/phpunit/CRM/Case/BAO/xml/two-items-in-each.xml +++ b/tests/phpunit/CRM/Case/BAO/xml/two-items-in-each.xml @@ -1,4 +1,4 @@ - + Housing Support diff --git a/tests/phpunit/CRM/Upgrade/Incremental/php/FiveTwentyTest.php b/tests/phpunit/CRM/Upgrade/Incremental/php/FiveTwentyTest.php index fe01cc3ca5d5..14aa68c27f20 100644 --- a/tests/phpunit/CRM/Upgrade/Incremental/php/FiveTwentyTest.php +++ b/tests/phpunit/CRM/Upgrade/Incremental/php/FiveTwentyTest.php @@ -54,111 +54,111 @@ public function testChangeCaseTypeAutoassignee() { * don't get borked. */ $newCaseTypeXml = << - + -test_type - - -Open Case -1 - - -Email - - -Follow up - - -Meeting - - -Phone Call - - -давид - - - -standard_timeline - -true - - -Open Case -Completed - -1 - - - - -timeline_1 - -true - - -Follow up - -Scheduled -Open Case -7 -newest -2 -{$relationshipTypeNames['Senior Services Coordinator']}_b_a - - - -Follow up - -Scheduled -Open Case -14 -newest -2 -{$relationshipTypeNames['Benefits Specialist']}_a_b - - - -Follow up - -Scheduled -Open Case -21 -newest -2 -{$relationshipTypeNames['Spouse of']}_a_b - - - -Follow up - -Scheduled -Open Case -28 -newest -2 -{$relationshipTypeNames['Spouse of']}_b_a - - - - - - - -Senior Services Coordinator -1 -1 - - -Spouse of - - -Benefits Specialist is - - -0 - + test_type + + + Open Case + 1 + + + Email + + + Follow up + + + Meeting + + + Phone Call + + + давид + + + + standard_timeline + + true + + + Open Case + Completed + + 1 + + + + + timeline_1 + + true + + + Follow up + + Scheduled + Open Case + 7 + newest + 2 + {$relationshipTypeNames['Senior Services Coordinator']}_b_a + + + + Follow up + + Scheduled + Open Case + 14 + newest + 2 + {$relationshipTypeNames['Benefits Specialist']}_a_b + + + + Follow up + + Scheduled + Open Case + 21 + newest + 2 + {$relationshipTypeNames['Spouse of']}_a_b + + + + Follow up + + Scheduled + Open Case + 28 + newest + 2 + {$relationshipTypeNames['Spouse of']}_b_a + + + + + + + + Senior Services Coordinator + 1 + 1 + + + Spouse of + + + Benefits Specialist is + + + 0 + + ENDXML; $dao = new CRM_Case_DAO_CaseType(); @@ -344,173 +344,173 @@ private function createCaseTypes($relationshipTypeNames, $stage) { switch ($stage) { case 1: $newCaseTypeXml = << - + -simple - - -Open Case -1 - - -Email - - -Follow up - - -Meeting - - -Phone Call - - - - -standard_timeline - -true - - -Open Case -Completed - -1 - - - - -timeline_1 - -true - - -Follow up - -Scheduled -Open Case -7 -newest -2 -{$relationshipTypeNames['Senior Services Coordinator']}_b_a - - - - - - - -Senior Services Coordinator -1 -1 - - -Spouse of - - -Benefits Specialist is - - -is Wallet Inspector of - - -has as Wallet Inspector - - -абвгде - - -αβγδ changed - - -0 + simple + + + Open Case + 1 + + + Email + + + Follow up + + + Meeting + + + Phone Call + + + + + standard_timeline + + true + + + Open Case + Completed + + 1 + + + + + timeline_1 + + true + + + Follow up + + Scheduled + Open Case + 7 + newest + 2 + {$relationshipTypeNames['Senior Services Coordinator']}_b_a + + + + + + + + Senior Services Coordinator + 1 + 1 + + + Spouse of + + + Benefits Specialist is + + + is Wallet Inspector of + + + has as Wallet Inspector + + + абвгде + + + αβγδ changed + + + 0 + ENDXMLSIMPLE; $expectedCaseTypeXml = << - + -simple - - -Open Case -1 - - -Email - - -Follow up - - -Meeting - - -Phone Call - - - - -standard_timeline - -true - - -Open Case -Completed - -1 - - - - -timeline_1 - -true - - -Follow up - -Scheduled -Open Case -7 -newest -2 -{$relationshipTypeNames['Senior Services Coordinator']}_b_a - - - - - - - -Senior Services Coordinator -1 -1 - - -Spouse of - - -Benefits Specialist is - - -Wallet Inspector - - -Wallet Inspector is - - -абвгде - - -αβγδ - - -0 + simple + + + Open Case + 1 + + + Email + + + Follow up + + + Meeting + + + Phone Call + + + + + standard_timeline + + true + + + Open Case + Completed + + 1 + + + + + timeline_1 + + true + + + Follow up + + Scheduled + Open Case + 7 + newest + 2 + {$relationshipTypeNames['Senior Services Coordinator']}_b_a + + + + + + + + Senior Services Coordinator + 1 + 1 + + + Spouse of + + + Benefits Specialist is + + + Wallet Inspector + + + Wallet Inspector is + + + абвгде + + + αβγδ + + + 0 + ENDXMLSIMPLEEXPECTED; $caseTypeId = $this->addCaseType('simple', $newCaseTypeXml); @@ -525,185 +525,185 @@ private function createCaseTypes($relationshipTypeNames, $stage) { // unchanged if they choose to continue with the upgrade. $newCaseTypeXml = << - + -mixedup - - -Open Case -1 - - -Email - - -Follow up - - -Meeting - - -Phone Call - - - - -standard_timeline - -true - - -Open Case -Completed - -1 - - - - -timeline_1 - -true - - -Follow up - -Scheduled -Open Case -7 -newest -2 -{$relationshipTypeNames['Senior Services Coordinator']}_b_a - - - - - - - -Senior Services Coordinator -1 -1 - - -Spouse of - - -Benefits Specialist is - - -is Wallet Inspector of - - -has as Wallet Inspector - - -абвгде - - -αβγδ changed - - -Benefits Specialist - - -Mythical Unicorn - - -0 + mixedup + + + Open Case + 1 + + + Email + + + Follow up + + + Meeting + + + Phone Call + + + + + standard_timeline + + true + + + Open Case + Completed + + 1 + + + + + timeline_1 + + true + + + Follow up + + Scheduled + Open Case + 7 + newest + 2 + {$relationshipTypeNames['Senior Services Coordinator']}_b_a + + + + + + + + Senior Services Coordinator + 1 + 1 + + + Spouse of + + + Benefits Specialist is + + + is Wallet Inspector of + + + has as Wallet Inspector + + + абвгде + + + αβγδ changed + + + Benefits Specialist + + + Mythical Unicorn + + + 0 + ENDXMLMIXEDUP; $expectedCaseTypeXml = << - + -mixedup - - -Open Case -1 - - -Email - - -Follow up - - -Meeting - - -Phone Call - - - - -standard_timeline - -true - - -Open Case -Completed - -1 - - - - -timeline_1 - -true - - -Follow up - -Scheduled -Open Case -7 -newest -2 -{$relationshipTypeNames['Senior Services Coordinator']}_b_a - - - - - - - -Senior Services Coordinator -1 -1 - - -Spouse of - - -Benefits Specialist is - - -Wallet Inspector - - -Wallet Inspector is - - -абвгде - - -αβγδ - - -Benefits Specialist - - -Mythical Unicorn - - -0 + mixedup + + + Open Case + 1 + + + Email + + + Follow up + + + Meeting + + + Phone Call + + + + + standard_timeline + + true + + + Open Case + Completed + + 1 + + + + + timeline_1 + + true + + + Follow up + + Scheduled + Open Case + 7 + newest + 2 + {$relationshipTypeNames['Senior Services Coordinator']}_b_a + + + + + + + + Senior Services Coordinator + 1 + 1 + + + Spouse of + + + Benefits Specialist is + + + Wallet Inspector + + + Wallet Inspector is + + + абвгде + + + αβγδ + + + Benefits Specialist + + + Mythical Unicorn + + + 0 + ENDXMLMIXEDUPEXPECTED; $caseTypeId = $this->addCaseType('mixedup', $newCaseTypeXml); @@ -713,179 +713,179 @@ private function createCaseTypes($relationshipTypeNames, $stage) { ]; $newCaseTypeXml = << - + -diffname - - -Open Case -1 - - -Email - - -Follow up - - -Meeting - - -Phone Call - - - - -standard_timeline - -true - - -Open Case -Completed - -1 - - - - -timeline_1 - -true - - -Follow up - -Scheduled -Open Case -7 -newest -2 -{$relationshipTypeNames['Senior Services Coordinator']}_b_a - - - - - - - -Senior Services Coordinator -1 -1 - - -Spouse of - - -Benefits Specialist is - - -is Wallet Inspector of - - -has as Wallet Inspector - - -абвгде - - -αβγδ changed - - -Archenemy of - - -0 + diffname + + + Open Case + 1 + + + Email + + + Follow up + + + Meeting + + + Phone Call + + + + + standard_timeline + + true + + + Open Case + Completed + + 1 + + + + + timeline_1 + + true + + + Follow up + + Scheduled + Open Case + 7 + newest + 2 + {$relationshipTypeNames['Senior Services Coordinator']}_b_a + + + + + + + + Senior Services Coordinator + 1 + 1 + + + Spouse of + + + Benefits Specialist is + + + is Wallet Inspector of + + + has as Wallet Inspector + + + абвгде + + + αβγδ changed + + + Archenemy of + + + 0 + ENDXMLDIFFNAME; $expectedCaseTypeXml = << - + -diffname - - -Open Case -1 - - -Email - - -Follow up - - -Meeting - - -Phone Call - - - - -standard_timeline - -true - - -Open Case -Completed - -1 - - - - -timeline_1 - -true - - -Follow up - -Scheduled -Open Case -7 -newest -2 -{$relationshipTypeNames['Senior Services Coordinator']}_b_a - - - - - - - -Senior Services Coordinator -1 -1 - - -Spouse of - - -Benefits Specialist is - - -Wallet Inspector - - -Wallet Inspector is - - -абвгде - - -αβγδ - - -Archenemy of - - -0 + diffname + + + Open Case + 1 + + + Email + + + Follow up + + + Meeting + + + Phone Call + + + + + standard_timeline + + true + + + Open Case + Completed + + 1 + + + + + timeline_1 + + true + + + Follow up + + Scheduled + Open Case + 7 + newest + 2 + {$relationshipTypeNames['Senior Services Coordinator']}_b_a + + + + + + + + Senior Services Coordinator + 1 + 1 + + + Spouse of + + + Benefits Specialist is + + + Wallet Inspector + + + Wallet Inspector is + + + абвгде + + + αβγδ + + + Archenemy of + + + 0 + ENDXMLDIFFNAMEEXPECTED; $caseTypeId = $this->addCaseType('diffname', $newCaseTypeXml);