From fb5d93e1d8c409e8d6391ae1b46f2ef91ad6ea69 Mon Sep 17 00:00:00 2001
From: Kevin Cristiano <kcristiano@kcristiano.com>
Date: Thu, 2 Jul 2020 07:22:54 -0400
Subject: [PATCH] civicrm release

---
 README.md                                     |   11 +-
 civicrm.php                                   |    6 +-
 civicrm/CRM/ACL/API.php                       |    8 +-
 civicrm/CRM/Activity/BAO/Activity.php         |   24 +-
 civicrm/CRM/Activity/Form/ActivityLinks.php   |    2 +-
 civicrm/CRM/Activity/Page/AJAX.php            |    8 +-
 civicrm/CRM/Admin/Form/MessageTemplates.php   |    1 +
 .../CRM/Admin/Form/Preferences/Mailing.php    |    2 +
 .../CRM/Admin/Form/Setting/Localization.php   |   36 +-
 civicrm/CRM/Admin/Form/Setting/Url.php        |    1 +
 civicrm/CRM/Admin/Page/APIExplorer.php        |   13 +-
 civicrm/CRM/Admin/Page/Admin.php              |   54 +-
 civicrm/CRM/Admin/Page/ConfigTaskList.php     |    2 +-
 civicrm/CRM/Admin/Page/Job.php                |    2 +-
 civicrm/CRM/Admin/Page/JobLog.php             |    2 +-
 civicrm/CRM/Admin/Page/PaymentProcessor.php   |    4 +-
 civicrm/CRM/Batch/BAO/Batch.php               |   14 +-
 civicrm/CRM/Campaign/BAO/Campaign.php         |   25 +-
 civicrm/CRM/Campaign/BAO/Survey.php           |   31 +-
 civicrm/CRM/Campaign/Form/Search.php          |    2 +-
 civicrm/CRM/Campaign/Page/DashBoard.php       |   15 +-
 civicrm/CRM/Campaign/xml/Menu/Campaign.xml    |    4 -
 civicrm/CRM/Case/BAO/Case.php                 |    2 +-
 civicrm/CRM/Case/BAO/CaseContact.php          |    9 +-
 civicrm/CRM/Case/Form/Activity.php            |   22 +
 civicrm/CRM/Case/Form/AddToCaseAsRole.php     |    5 +-
 civicrm/CRM/Case/Info.php                     |    5 +-
 civicrm/CRM/Case/Page/Tab.php                 |    2 +-
 civicrm/CRM/Case/XMLProcessor/Process.php     |   33 +-
 civicrm/CRM/Case/XMLProcessor/Report.php      |   42 +-
 civicrm/CRM/Case/xml/Menu/Case.xml            |    5 -
 civicrm/CRM/Contact/BAO/Contact.php           |   12 +-
 civicrm/CRM/Contact/BAO/ContactType.php       |   95 +-
 civicrm/CRM/Contact/BAO/GroupContact.php      |    9 +-
 civicrm/CRM/Contact/BAO/Query.php             |   33 +-
 civicrm/CRM/Contact/BAO/Relationship.php      |   14 +-
 civicrm/CRM/Contact/BAO/RelationshipType.php  |   10 +-
 civicrm/CRM/Contact/Form/CustomData.php       |    7 -
 civicrm/CRM/Contact/Form/Edit/Individual.php  |    1 -
 civicrm/CRM/Contact/Form/Inline.php           |    2 +-
 civicrm/CRM/Contact/Form/Inline/Address.php   |    6 +-
 .../CRM/Contact/Form/Inline/CustomData.php    |    6 +-
 civicrm/CRM/Contact/Form/Search/Advanced.php  |    8 +
 civicrm/CRM/Contact/Form/Search/Criteria.php  |    9 +-
 civicrm/CRM/Contact/Form/Search/Custom.php    |    2 +-
 .../CRM/Contact/Form/Search/Custom/Base.php   |    4 +-
 .../CRM/Contact/Form/Search/Custom/Group.php  |    4 +-
 .../Contact/Form/Search/Custom/PriceSet.php   |    2 +-
 civicrm/CRM/Contact/Form/Task/Batch.php       |    2 +-
 civicrm/CRM/Contact/Form/Task/Delete.php      |    4 +-
 civicrm/CRM/Contact/Form/Task/EmailTrait.php  |  246 +--
 civicrm/CRM/Contact/Form/Task/Map.php         |    2 +-
 .../Contact/Form/Task/SaveSearch/Update.php   |    2 +-
 civicrm/CRM/Contact/Import/Form/Preview.php   |   63 +-
 civicrm/CRM/Contact/Import/ImportJob.php      |   19 +-
 civicrm/CRM/Contact/Import/Parser.php         |    6 +
 civicrm/CRM/Contact/Import/Parser/Contact.php |   24 +-
 civicrm/CRM/Contact/Page/Inline/Actions.php   |    2 +-
 civicrm/CRM/Contact/Page/Inline/Address.php   |    6 +-
 .../CRM/Contact/Page/Inline/ContactInfo.php   |    2 +-
 .../CRM/Contact/Page/Inline/ContactName.php   |    2 +-
 .../CRM/Contact/Page/Inline/CustomData.php    |    8 +-
 .../CRM/Contact/Page/Inline/Demographics.php  |    2 +-
 civicrm/CRM/Contact/Page/Inline/Email.php     |    2 +-
 civicrm/CRM/Contact/Page/Inline/IM.php        |    2 +-
 .../CRM/Contact/Page/View/Relationship.php    |    2 +-
 civicrm/CRM/Contact/Page/View/Summary.php     |    8 +-
 civicrm/CRM/Contact/Selector.php              |    1 +
 civicrm/CRM/Contact/Task.php                  |    4 +-
 civicrm/CRM/Contribute/BAO/Contribution.php   |   15 +-
 .../CRM/Contribute/BAO/ContributionRecur.php  |   94 +-
 civicrm/CRM/Contribute/BAO/Query.php          |    3 +-
 civicrm/CRM/Contribute/DAO/Contribution.php   |    5 +-
 .../CRM/Contribute/DAO/ContributionRecur.php  |    6 +-
 .../Contribute/Form/AbstractEditPayment.php   |    8 -
 .../Contribute/Form/CancelSubscription.php    |   25 +-
 civicrm/CRM/Contribute/Form/Contribution.php  |   34 +-
 .../CRM/Contribute/Form/Contribution/Main.php |    6 +-
 .../CRM/Contribute/Form/ContributionBase.php  |   43 +-
 civicrm/CRM/Contribute/Form/Task/Status.php   |    9 +-
 civicrm/CRM/Contribute/Form/UpdateBilling.php |   16 +-
 .../Contribute/Form/UpdateSubscription.php    |    2 +-
 .../CRM/Contribute/Page/ContributionPage.php  |   18 +-
 .../CRM/Contribute/xml/Menu/Contribute.xml    |    6 -
 civicrm/CRM/Contribute/xml/Menu/PCP.xml       |    1 -
 civicrm/CRM/Core/Action.php                   |    4 +-
 civicrm/CRM/Core/BAO/ActionLog.php            |   25 +-
 civicrm/CRM/Core/BAO/ActionSchedule.php       |    3 +-
 civicrm/CRM/Core/BAO/Address.php              |    2 +-
 civicrm/CRM/Core/BAO/Block.php                |    3 +-
 civicrm/CRM/Core/BAO/Cache.php                |    3 +-
 civicrm/CRM/Core/BAO/CustomField.php          |  104 +-
 civicrm/CRM/Core/BAO/CustomGroup.php          |    2 +-
 civicrm/CRM/Core/BAO/CustomOption.php         |   16 +-
 civicrm/CRM/Core/BAO/CustomValue.php          |   12 +
 civicrm/CRM/Core/BAO/CustomValueTable.php     |    7 +-
 civicrm/CRM/Core/BAO/Discount.php             |    3 +-
 civicrm/CRM/Core/BAO/Domain.php               |   23 +
 civicrm/CRM/Core/BAO/File.php                 |   22 +-
 civicrm/CRM/Core/BAO/Job.php                  |   10 +-
 civicrm/CRM/Core/BAO/LabelFormat.php          |    2 +-
 civicrm/CRM/Core/BAO/Location.php             |    3 +-
 civicrm/CRM/Core/BAO/Mapping.php              |    4 +-
 civicrm/CRM/Core/BAO/Note.php                 |    8 +-
 civicrm/CRM/Core/BAO/PaperSize.php            |   10 +-
 civicrm/CRM/Core/BAO/PdfFormat.php            |   10 +-
 civicrm/CRM/Core/BAO/Phone.php                |   10 +-
 civicrm/CRM/Core/BAO/PreferencesDate.php      |    6 +-
 civicrm/CRM/Core/BAO/RecurringEntity.php      |   10 +-
 civicrm/CRM/Core/BAO/SchemaHandler.php        |    6 +-
 civicrm/CRM/Core/BAO/Setting.php              |    2 +-
 civicrm/CRM/Core/BAO/StatusPreference.php     |    5 +-
 civicrm/CRM/Core/BAO/Tag.php                  |   33 +-
 civicrm/CRM/Core/BAO/UFGroup.php              |    3 +-
 civicrm/CRM/Core/BAO/UFMatch.php              |    4 +-
 civicrm/CRM/Core/BAO/WordReplacement.php      |    3 +-
 civicrm/CRM/Core/Block.php                    |   24 +-
 civicrm/CRM/Core/CommunityMessages.php        |    7 +-
 civicrm/CRM/Core/Component.php                |    4 +-
 civicrm/CRM/Core/Controller.php               |    4 +-
 civicrm/CRM/Core/DAO.php                      |   14 +-
 civicrm/CRM/Core/DAO/AllCoreTables.php        |   83 +-
 civicrm/CRM/Core/DAO/CustomField.php          |   23 +-
 civicrm/CRM/Core/DAO/Factory.php              |    4 +-
 civicrm/CRM/Core/DAO/OptionValue.php          |    4 +-
 civicrm/CRM/Core/Error.php                    |   61 +-
 civicrm/CRM/Core/Form.php                     |    6 +-
 civicrm/CRM/Core/Form/Renderer.php            |    7 +-
 civicrm/CRM/Core/I18n.php                     |   48 +-
 civicrm/CRM/Core/I18n/Form.php                |    4 +-
 civicrm/CRM/Core/I18n/SchemaStructure.php     |    6 +-
 civicrm/CRM/Core/Invoke.php                   |    6 +-
 civicrm/CRM/Core/Menu.php                     |   47 +-
 civicrm/CRM/Core/OptionGroup.php              |   13 +-
 civicrm/CRM/Core/Page.php                     |   54 +
 civicrm/CRM/Core/Page/Redirect.php            |    4 +-
 civicrm/CRM/Core/Payment.php                  |   28 +-
 civicrm/CRM/Core/Payment/AuthorizeNet.php     |   64 +-
 civicrm/CRM/Core/Payment/BaseIPN.php          |   11 +-
 civicrm/CRM/Core/Payment/Dummy.php            |   97 +-
 civicrm/CRM/Core/Payment/Elavon.php           |   13 +-
 civicrm/CRM/Core/Payment/FirstData.php        |   12 +-
 civicrm/CRM/Core/Payment/Manual.php           |   13 +
 civicrm/CRM/Core/Payment/PayJunction.php      |    9 -
 civicrm/CRM/Core/Payment/PayPalIPN.php        |    5 +-
 civicrm/CRM/Core/Payment/PayPalImpl.php       |   15 +-
 civicrm/CRM/Core/Payment/PayPalProIPN.php     |    6 +-
 civicrm/CRM/Core/Payment/PayflowPro.php       |   13 +-
 civicrm/CRM/Core/Payment/PaymentExpress.php   |   15 +-
 .../CRM/Core/Payment/PaymentExpressIPN.php    |   20 +-
 civicrm/CRM/Core/Payment/ProcessorForm.php    |    4 +-
 civicrm/CRM/Core/Payment/Realex.php           |    9 -
 civicrm/CRM/Core/Payment/eWAY.php             |   13 +-
 civicrm/CRM/Core/Permission/Base.php          |    6 +-
 civicrm/CRM/Core/PseudoConstant.php           |    4 +-
 civicrm/CRM/Core/Region.php                   |    4 +-
 civicrm/CRM/Core/SelectValues.php             |   19 +-
 civicrm/CRM/Core/ShowHideBlocks.php           |  130 --
 civicrm/CRM/Core/Smarty.php                   |    4 +-
 .../Core/Smarty/plugins/block.crmButton.php   |   16 +-
 .../Core/Smarty/plugins/block.crmScope.php    |    4 +-
 .../CRM/Core/Smarty/plugins/block.icon.php    |   43 +
 .../Core/Smarty/plugins/function.copyIcon.php |   34 +
 .../Smarty/plugins/function.crmVersion.php    |    4 +-
 .../Smarty/plugins/function.privacyFlag.php   |   56 +
 civicrm/CRM/Core/TemporaryErrorScope.php      |    4 +-
 civicrm/CRM/Core/Transaction.php              |    4 +-
 civicrm/CRM/Core/xml/Menu/Admin.xml           |   55 -
 civicrm/CRM/Core/xml/Menu/Contact.xml         |    1 -
 civicrm/CRM/Core/xml/Menu/Tag.xml             |    1 -
 civicrm/CRM/Custom/Form/Field.php             |   25 +-
 civicrm/CRM/Dedupe/MergeHandler.php           |    6 +-
 civicrm/CRM/Dedupe/Merger.php                 |  138 +-
 civicrm/CRM/Event/BAO/Event.php               |   49 +-
 civicrm/CRM/Event/Cart/BAO/MerParticipant.php |    2 +-
 civicrm/CRM/Event/Controller/Registration.php |    6 +-
 civicrm/CRM/Event/Controller/Search.php       |   10 +-
 .../CRM/Event/Form/ManageEvent/TabHeader.php  |    5 +-
 civicrm/CRM/Event/Form/Registration.php       |   36 +-
 .../CRM/Event/Form/Registration/Confirm.php   |   24 +-
 .../CRM/Event/Form/Registration/Register.php  |   19 +-
 .../CRM/Event/Form/Registration/ThankYou.php  |    2 +
 civicrm/CRM/Event/Form/Task/Batch.php         |   45 +-
 civicrm/CRM/Event/Import/Form/MapField.php    |   20 +-
 civicrm/CRM/Event/Page/DashBoard.php          |   12 +-
 civicrm/CRM/Event/Page/EventInfo.php          |    7 +-
 civicrm/CRM/Event/Page/ManageEvent.php        |    4 +-
 .../CRM/Event/StateMachine/Registration.php   |   13 +-
 civicrm/CRM/Event/StateMachine/Search.php     |    8 +-
 civicrm/CRM/Event/xml/Menu/Event.xml          |    6 -
 civicrm/CRM/Event/xml/Menu/PCP.xml            |    1 -
 civicrm/CRM/Extension/Browser.php             |   12 +-
 civicrm/CRM/Extension/ClassLoader.php         |    7 +-
 civicrm/CRM/Extension/Container/Default.php   |    2 +-
 civicrm/CRM/Extension/Downloader.php          |    2 +-
 civicrm/CRM/Financial/BAO/FinancialItem.php   |    4 +-
 civicrm/CRM/Financial/BAO/Payment.php         |   33 +-
 civicrm/CRM/Financial/Form/PaymentEdit.php    |   31 +-
 civicrm/CRM/Financial/Form/SalesTaxTrait.php  |    6 +-
 civicrm/CRM/Grant/BAO/Grant.php               |   36 +-
 civicrm/CRM/Grant/BAO/Query.php               |    6 +-
 civicrm/CRM/Grant/Form/Grant.php              |    8 -
 civicrm/CRM/Grant/Form/Task.php               |    8 -
 civicrm/CRM/Group/Form/Edit.php               |   14 +-
 civicrm/CRM/Import/Form/Preview.php           |   44 +-
 civicrm/CRM/Invoicing/Utils.php               |    3 +-
 civicrm/CRM/Logging/Schema.php                |    3 +
 civicrm/CRM/Mailing/BAO/Mailing.php           |    5 +-
 civicrm/CRM/Mailing/BAO/MailingAB.php         |   49 +-
 civicrm/CRM/Mailing/BAO/Query.php             |    2 +-
 civicrm/CRM/Mailing/BAO/TrackableURL.php      |    4 +-
 civicrm/CRM/Mailing/DAO/MailingAB.php         |    3 +-
 civicrm/CRM/Mailing/Event/BAO/Bounce.php      |    2 +-
 civicrm/CRM/Mailing/Form/Search.php           |   38 +-
 civicrm/CRM/Mailing/Form/Unsubscribe.php      |    8 +
 civicrm/CRM/Mailing/Page/Browse.php           |   24 +-
 civicrm/CRM/Mailing/Page/Common.php           |    8 +-
 civicrm/CRM/Mailing/Page/Open.php             |   58 +
 civicrm/CRM/Mailing/Page/Url.php              |  104 +
 civicrm/CRM/Mailing/xml/Menu/Mailing.xml      |   14 +-
 civicrm/CRM/Member/BAO/MembershipType.php     |    5 +-
 civicrm/CRM/Member/DAO/MembershipType.php     |    3 +-
 civicrm/CRM/Member/Form.php                   |   19 +-
 civicrm/CRM/Member/Form/Membership.php        |   24 +-
 civicrm/CRM/Member/Form/MembershipRenewal.php |  203 +-
 civicrm/CRM/Member/Import/Form/MapField.php   |   24 +-
 civicrm/CRM/Member/Page/DashBoard.php         |    2 +-
 civicrm/CRM/Member/xml/Menu/Member.xml        |    2 -
 civicrm/CRM/Pledge/BAO/Pledge.php             |   40 +-
 civicrm/CRM/Pledge/BAO/PledgeBlock.php        |   66 +-
 civicrm/CRM/Pledge/BAO/PledgePayment.php      |   26 +-
 civicrm/CRM/Price/BAO/LineItem.php            |    2 +-
 civicrm/CRM/Price/BAO/PriceField.php          |   14 +-
 civicrm/CRM/Price/BAO/PriceFieldValue.php     |   39 +-
 civicrm/CRM/Price/BAO/PriceSet.php            |   18 +-
 civicrm/CRM/Price/DAO/PriceField.php          |    3 +-
 civicrm/CRM/Price/DAO/PriceFieldValue.php     |    4 +-
 civicrm/CRM/Price/Page/Field.php              |    2 +-
 civicrm/CRM/Price/Page/Option.php             |    8 +-
 civicrm/CRM/Queue/ErrorPolicy.php             |    4 +-
 civicrm/CRM/Queue/Service.php                 |    4 +-
 civicrm/CRM/Report/Form.php                   |   15 +-
 .../Report/Form/Campaign/SurveyDetails.php    |   40 +-
 civicrm/CRM/Report/Form/Contact/Summary.php   |    4 +-
 civicrm/CRM/Report/Form/Contribute/Detail.php |    3 +-
 civicrm/CRM/Report/Form/Contribute/Repeat.php |   14 +-
 .../Report/Form/Event/ParticipantListing.php  |   12 +-
 civicrm/CRM/Report/Utils/Report.php           |    2 +-
 civicrm/CRM/Report/xml/Menu/Report.xml        |    3 -
 civicrm/CRM/SMS/Page/Provider.php             |    2 +-
 civicrm/CRM/SMS/Provider.php                  |    6 +-
 civicrm/CRM/Upgrade/Form.php                  |    6 +-
 .../Incremental/php/FiveTwentySeven.php       |  109 +
 .../Upgrade/Incremental/sql/5.26.0.mysql.tpl  |    1 -
 .../Upgrade/Incremental/sql/5.26.2.mysql.tpl  |    1 -
 .../Upgrade/Incremental/sql/5.27.0.mysql.tpl  |    1 +
 ...5.26.1.mysql.tpl => 5.27.alpha1.mysql.tpl} |    5 +
 .../Incremental/sql/5.27.beta1.mysql.tpl      |    8 +
 civicrm/CRM/Utils/API/MatchOption.php         |    4 +-
 civicrm/CRM/Utils/API/ReloadOption.php        |    4 +-
 civicrm/CRM/Utils/Address/USPS.php            |   20 +-
 civicrm/CRM/Utils/AutoClean.php               |    8 +-
 civicrm/CRM/Utils/Cache/SqlGroup.php          |   22 +-
 civicrm/CRM/Utils/Check/Component/Env.php     |   20 +-
 civicrm/CRM/Utils/Check/Component/Schema.php  |   15 +-
 civicrm/CRM/Utils/ConsoleTee.php              |    4 +-
 civicrm/CRM/Utils/FakeObject.php              |    4 +-
 civicrm/CRM/Utils/Geocode/Google.php          |    7 +-
 civicrm/CRM/Utils/GlobalStack.php             |    4 +-
 civicrm/CRM/Utils/Hook.php                    |   19 +-
 civicrm/CRM/Utils/Migrate/Export.php          |    4 +-
 civicrm/CRM/Utils/PagerAToZ.php               |    4 +-
 civicrm/CRM/Utils/SQL/BaseParamQuery.php      |    8 +-
 civicrm/CRM/Utils/SQL/Delete.php              |    8 +-
 civicrm/CRM/Utils/SQL/Select.php              |    8 +-
 civicrm/CRM/Utils/Signer.php                  |    4 +-
 civicrm/CRM/Utils/String.php                  |   36 +-
 civicrm/CRM/Utils/System.php                  |   35 +
 civicrm/CRM/Utils/System/Drupal.php           |   13 +
 civicrm/CRM/Utils/System/Drupal8.php          |    4 +-
 civicrm/CRM/Utils/System/WordPress.php        |   81 +
 civicrm/CRM/Utils/Time.php                    |   67 +-
 civicrm/CRM/Utils/Url.php                     |    4 +-
 civicrm/Civi.php                              |    8 +-
 civicrm/Civi/API/Request.php                  |    2 +-
 civicrm/Civi/API/SelectQuery.php              |    6 +-
 .../Civi/API/Subscriber/ChainSubscriber.php   |    4 +-
 .../API/Subscriber/DynamicFKAuthorization.php |    5 +-
 civicrm/Civi/API/WhitelistRule.php            |    4 +-
 .../Event/MailingQueryEvent.php               |    8 +-
 .../Civi/ActionSchedule/RecipientBuilder.php  |    4 +-
 civicrm/Civi/Angular/AngularLoader.php        |    4 +-
 .../Api4/Action/CustomValue/GetFields.php     |    8 -
 civicrm/Civi/Api4/Action/Entity/GetLinks.php  |    6 +-
 civicrm/Civi/Api4/Action/GetActions.php       |    9 -
 .../Civi/Api4/Action/GroupContact/Save.php    |    9 -
 civicrm/Civi/Api4/Action/Relationship/Get.php |    8 -
 .../Action/Setting/AbstractSettingAction.php  |    8 -
 civicrm/Civi/Api4/Action/Setting/Get.php      |    8 -
 .../Civi/Api4/Action/Setting/GetFields.php    |    8 -
 civicrm/Civi/Api4/Action/Setting/Revert.php   |    8 -
 civicrm/Civi/Api4/Action/Setting/Set.php      |    8 -
 civicrm/Civi/Api4/Action/System/Check.php     |    8 -
 civicrm/Civi/Api4/Action/System/Flush.php     |    8 -
 civicrm/Civi/Api4/Contribution.php            |    7 -
 civicrm/Civi/Api4/ContributionPage.php        |    7 -
 civicrm/Civi/Api4/ContributionRecur.php       |   22 +
 civicrm/Civi/Api4/Event/Events.php            |   11 +-
 .../Subscriber/ContactSchemaMapSubscriber.php |   73 -
 .../Subscriber/PostSelectQuerySubscriber.php  |  335 ---
 civicrm/Civi/Api4/Generic/AbstractEntity.php  |    5 +-
 civicrm/Civi/Api4/Generic/BasicGetAction.php  |    2 +-
 civicrm/Civi/Api4/Generic/DAOEntity.php       |   13 +-
 civicrm/Civi/Api4/Generic/DAOGetAction.php    |   35 +
 .../Generic/Traits/CustomValueActionTrait.php |    2 +-
 .../Api4/Generic/Traits/DAOActionTrait.php    |   31 +-
 civicrm/Civi/Api4/LocationType.php            |    9 -
 civicrm/Civi/Api4/MembershipType.php          |   22 +
 civicrm/Civi/Api4/PriceField.php              |   22 +
 civicrm/Civi/Api4/PriceFieldValue.php         |   22 +
 civicrm/Civi/Api4/PriceSet.php                |   22 +
 civicrm/Civi/Api4/Query/Api4SelectQuery.php   |  289 ++-
 civicrm/Civi/Api4/Query/SqlExpression.php     |   12 +-
 civicrm/Civi/Api4/Result/ReplaceResult.php    |   11 +-
 .../Schema/Joinable/CustomGroupJoinable.php   |   33 +-
 .../Schema/Joinable/OptionValueJoinable.php   |   80 -
 civicrm/Civi/Api4/Service/Schema/Joiner.php   |   27 +-
 .../Api4/Service/Schema/SchemaMapBuilder.php  |   65 +-
 .../ContactTypeCreationSpecProvider.php       |   14 +-
 .../ContributionCreationSpecProvider.php      |   14 +-
 .../ContributionRecurCreationSpecProvider.php |   39 +
 .../Provider/DomainCreationSpecProvider.php   |    9 -
 .../PriceFieldValueCreationSpecProvider.php}  |   33 +-
 .../Civi/Api4/Service/Spec/SpecFormatter.php  |   13 +-
 .../Civi/Api4/Service/Spec/SpecGatherer.php   |   20 +-
 .../Civi/Api4/Utils/ArrayInsertionUtil.php    |   12 +-
 civicrm/Civi/Api4/Utils/CoreUtil.php          |   28 +-
 civicrm/Civi/Api4/Utils/FormattingUtil.php    |   26 +-
 civicrm/Civi/Api4/services.xml                |    8 +-
 civicrm/Civi/Core/AssetBuilder.php            |    8 +-
 civicrm/Civi/Core/CiviEventDispatcher.php     |   32 +-
 civicrm/Civi/Core/CiviEventInspector.php      |    4 +-
 civicrm/Civi/Core/Container.php               |   53 +-
 civicrm/Civi/Core/Event/GenericHookEvent.php  |    8 +-
 civicrm/Civi/Core/Paths.php                   |   23 +-
 civicrm/Civi/Core/Resolver.php                |    4 +-
 civicrm/Civi/Core/Themes.php                  |    6 +-
 civicrm/Civi/Payment/PropertyBag.php          |   46 +-
 civicrm/Civi/Test.php                         |   16 +-
 civicrm/Civi/Test/Api3TestTrait.php           |   23 +-
 civicrm/Civi/Test/DbTestTrait.php             |    2 +-
 civicrm/Civi/Test/GenericAssertionsTrait.php  |    4 +-
 civicrm/Civi/Test/GuzzleTestTrait.php         |  191 ++
 civicrm/Civi/Test/HookInterface.php           |    4 +-
 civicrm/Civi/Test/MailingTestTrait.php        |    2 +-
 .../Civi/Token/Event/TokenRegisterEvent.php   |    4 +-
 civicrm/Civi/Token/Event/TokenValueEvent.php  |    2 +-
 civicrm/Civi/Token/TokenRow.php               |   12 +-
 civicrm/ang/api4Explorer/Clause.html          |    4 +-
 civicrm/ang/api4Explorer/Explorer.html        |   37 +-
 civicrm/ang/api4Explorer/Explorer.js          |   16 +-
 civicrm/ang/crmCaseType.js                    |    6 +-
 .../ang/crmCaseType/activityTypesTable.html   |    4 +-
 civicrm/ang/crmCaseType/list.html             |    2 +-
 civicrm/ang/crmCaseType/sequenceTable.html    |    4 +-
 civicrm/ang/crmCaseType/statusTable.html      |    2 +-
 civicrm/ang/crmCaseType/timelineTable.html    |    4 +-
 civicrm/ang/crmCxn/ManageCtrl.html            |    2 +-
 civicrm/ang/crmMailing.css                    |    4 -
 civicrm/ang/crmMailing/BlockPreview.js        |    2 +-
 .../ang/crmMailing/EditMailingCtrl/2step.html |    4 +-
 .../crmMailing/EditMailingCtrl/wizard.html    |    4 +-
 .../crmMailing/EditMailingCtrl/workflow.html  |    8 +-
 .../crmMailing/EmailBodyCtrl/tokenAlert.html  |   10 +-
 civicrm/ang/crmMailing/Recipients.js          |    2 +-
 civicrm/ang/crmMailingAB/EditCtrl/edit.html   |    4 +-
 civicrm/ang/crmMailingAB/ListCtrl.html        |    4 +-
 civicrm/ang/crmStatusPage/StatusPage.html     |    2 +-
 civicrm/ang/crmUi.js                          |   10 +-
 civicrm/ang/crmUi/tabset.html                 |    2 +-
 civicrm/ang/crmUi/wizard.html                 |    2 +-
 civicrm/ang/exportui/exportField.html         |    2 +-
 civicrm/api/api.php                           |   24 +-
 civicrm/api/class.api.php                     |   32 +-
 civicrm/api/v3/Activity.php                   |    9 +-
 civicrm/api/v3/Attachment.php                 |   12 +-
 civicrm/api/v3/Case.php                       |    8 +-
 civicrm/api/v3/Contribution.php               |    9 +
 civicrm/api/v3/CustomField.php                |   27 +-
 civicrm/api/v3/CustomValue.php                |    4 +-
 civicrm/api/v3/Generic.php                    |    1 +
 civicrm/api/v3/Generic/Getlist.php            |    2 +-
 civicrm/api/v3/GroupContact.php               |    8 +-
 civicrm/api/v3/Mailing.php                    |    4 +-
 civicrm/api/v3/MailingAB.php                  |    1 +
 civicrm/api/v3/Payment.php                    |   16 +
 civicrm/api/v3/Setting.php                    |   11 +-
 .../api/v3/examples/Setting/GetFields.ex.php  |    2 +-
 civicrm/api/v3/utils.php                      |    4 +-
 civicrm/civicrm-version.php                   |    2 +-
 civicrm/composer.json                         |   14 +-
 civicrm/composer.lock                         |  232 ++-
 civicrm/css/admin.css                         |   16 +
 civicrm/css/civicrm.css                       |  185 +-
 civicrm/css/contactSummary.css                |    6 -
 civicrm/css/dashboard.css                     |   19 -
 civicrm/i/TreeMinus.gif                       |  Bin 67 -> 0 bytes
 civicrm/i/TreeMinusWhite.gif                  |  Bin 67 -> 0 bytes
 civicrm/i/TreePlus.gif                        |  Bin 70 -> 0 bytes
 civicrm/i/TreePlusWhite.gif                   |  Bin 70 -> 0 bytes
 civicrm/i/admin/01.png                        |  Bin 3059 -> 0 bytes
 civicrm/i/admin/02.png                        |  Bin 2761 -> 0 bytes
 civicrm/i/admin/03.png                        |  Bin 1945 -> 0 bytes
 civicrm/i/admin/04.png                        |  Bin 2442 -> 0 bytes
 civicrm/i/admin/05.png                        |  Bin 2261 -> 0 bytes
 civicrm/i/admin/06.png                        |  Bin 3067 -> 0 bytes
 civicrm/i/admin/07.png                        |  Bin 1369 -> 0 bytes
 civicrm/i/admin/08.png                        |  Bin 2812 -> 0 bytes
 civicrm/i/admin/09.png                        |  Bin 2591 -> 0 bytes
 civicrm/i/admin/10.png                        |  Bin 2449 -> 0 bytes
 civicrm/i/admin/11.png                        |  Bin 1944 -> 0 bytes
 civicrm/i/admin/12.png                        |  Bin 2597 -> 0 bytes
 civicrm/i/admin/13.png                        |  Bin 2385 -> 0 bytes
 civicrm/i/admin/14.png                        |  Bin 2516 -> 0 bytes
 civicrm/i/admin/36.png                        |  Bin 1880 -> 0 bytes
 civicrm/i/admin/DataStore.gif                 |  Bin 1172 -> 0 bytes
 civicrm/i/admin/PayPal_mark_37x23.gif         |  Bin 402 -> 0 bytes
 civicrm/i/admin/Premiums.png                  |  Bin 2403 -> 0 bytes
 civicrm/i/admin/Profile.png                   |  Bin 2860 -> 0 bytes
 civicrm/i/admin/Synch_user.png                |  Bin 2320 -> 0 bytes
 civicrm/i/admin/accepted_creditcards.png      |  Bin 2128 -> 0 bytes
 civicrm/i/admin/communication.png             |  Bin 1545 -> 0 bytes
 civicrm/i/admin/contribution_types.png        |  Bin 2860 -> 0 bytes
 civicrm/i/admin/custm_data.png                |  Bin 2182 -> 0 bytes
 civicrm/i/admin/domain.png                    |  Bin 1268 -> 0 bytes
 civicrm/i/admin/duplicate_matching.png        |  Bin 3202 -> 0 bytes
 civicrm/i/admin/event_manage.png              |  Bin 2805 -> 0 bytes
 civicrm/i/admin/event_type.png                |  Bin 2706 -> 0 bytes
 civicrm/i/admin/import_export_map.png         |  Bin 3182 -> 0 bytes
 civicrm/i/admin/membership_status.png         |  Bin 2502 -> 0 bytes
 civicrm/i/admin/membership_type.png           |  Bin 2666 -> 0 bytes
 civicrm/i/admin/online_contribution_pages.png |  Bin 2779 -> 0 bytes
 civicrm/i/admin/option.png                    |  Bin 3251 -> 0 bytes
 civicrm/i/admin/parti_role.png                |  Bin 897 -> 0 bytes
 civicrm/i/admin/parti_status.png              |  Bin 857 -> 0 bytes
 civicrm/i/admin/payment_instruments.png       |  Bin 2850 -> 0 bytes
 civicrm/i/admin/price_sets.png                |  Bin 2095 -> 0 bytes
 civicrm/i/admin/rela_type.png                 |  Bin 3101 -> 0 bytes
 civicrm/i/admin/small/01.png                  |  Bin 1746 -> 0 bytes
 civicrm/i/admin/small/02.png                  |  Bin 1721 -> 0 bytes
 civicrm/i/admin/small/03.png                  |  Bin 1635 -> 0 bytes
 civicrm/i/admin/small/04.png                  |  Bin 1740 -> 0 bytes
 civicrm/i/admin/small/05.png                  |  Bin 2033 -> 0 bytes
 civicrm/i/admin/small/06.png                  |  Bin 1919 -> 0 bytes
 civicrm/i/admin/small/07.png                  |  Bin 1385 -> 0 bytes
 civicrm/i/admin/small/08.png                  |  Bin 1896 -> 0 bytes
 civicrm/i/admin/small/09.png                  |  Bin 1808 -> 0 bytes
 civicrm/i/admin/small/10.png                  |  Bin 1658 -> 0 bytes
 civicrm/i/admin/small/11.png                  |  Bin 1484 -> 0 bytes
 civicrm/i/admin/small/12.png                  |  Bin 1544 -> 0 bytes
 civicrm/i/admin/small/13.png                  |  Bin 1503 -> 0 bytes
 civicrm/i/admin/small/36.png                  |  Bin 1427 -> 0 bytes
 civicrm/i/admin/small/Premiums.png            |  Bin 1947 -> 0 bytes
 civicrm/i/admin/small/Profile.png             |  Bin 1589 -> 0 bytes
 civicrm/i/admin/small/Synch_user.png          |  Bin 1649 -> 0 bytes
 .../i/admin/small/accepted_creditcards.png    |  Bin 1237 -> 0 bytes
 civicrm/i/admin/small/case_type.gif           |  Bin 320 -> 0 bytes
 civicrm/i/admin/small/case_type.png           |  Bin 1008 -> 0 bytes
 civicrm/i/admin/small/communication.png       |  Bin 1314 -> 0 bytes
 civicrm/i/admin/small/contribution_types.png  |  Bin 1833 -> 0 bytes
 civicrm/i/admin/small/custm_data.png          |  Bin 1498 -> 0 bytes
 civicrm/i/admin/small/domain.png              |  Bin 1277 -> 0 bytes
 civicrm/i/admin/small/duplicate_matching.png  |  Bin 1803 -> 0 bytes
 civicrm/i/admin/small/event_manage.png        |  Bin 1796 -> 0 bytes
 civicrm/i/admin/small/event_type.png          |  Bin 1770 -> 0 bytes
 civicrm/i/admin/small/grant_type.png          |  Bin 635 -> 0 bytes
 civicrm/i/admin/small/import_export_map.png   |  Bin 1901 -> 0 bytes
 civicrm/i/admin/small/membership_status.png   |  Bin 1826 -> 0 bytes
 civicrm/i/admin/small/membership_type.png     |  Bin 1866 -> 0 bytes
 .../admin/small/online_contribution_pages.png |  Bin 1856 -> 0 bytes
 civicrm/i/admin/small/option.png              |  Bin 1861 -> 0 bytes
 civicrm/i/admin/small/parti_role.png          |  Bin 1210 -> 0 bytes
 civicrm/i/admin/small/parti_status.png        |  Bin 1153 -> 0 bytes
 civicrm/i/admin/small/payment_instruments.png |  Bin 1680 -> 0 bytes
 civicrm/i/admin/small/price_sets.png          |  Bin 1641 -> 0 bytes
 civicrm/i/admin/small/redaction_type.png      |  Bin 1138 -> 0 bytes
 civicrm/i/admin/small/rela_type.png           |  Bin 1917 -> 0 bytes
 civicrm/i/admin/small/report_list.gif         |  Bin 828 -> 0 bytes
 civicrm/i/admin/small/report_template.gif     |  Bin 833 -> 0 bytes
 civicrm/i/admin/small/soft_credit_type.png    |  Bin 489 -> 0 bytes
 civicrm/i/admin/small/template.png            |  Bin 1248 -> 0 bytes
 civicrm/i/admin/small/title.png               |  Bin 1712 -> 0 bytes
 civicrm/i/admin/small/updatepath.png          |  Bin 3218 -> 0 bytes
 civicrm/i/admin/template.png                  |  Bin 1617 -> 0 bytes
 civicrm/i/admin/title.png                     |  Bin 2300 -> 0 bytes
 civicrm/i/check.gif                           |  Bin 519 -> 0 bytes
 civicrm/i/copy.png                            |  Bin 471 -> 0 bytes
 civicrm/i/feed-icon.png                       |  Bin 1300 -> 0 bytes
 civicrm/i/geotag_16.png                       |  Bin 894 -> 0 bytes
 civicrm/i/grippie.png                         |  Bin 162 -> 0 bytes
 civicrm/i/group.png                           |  Bin 678 -> 0 bytes
 civicrm/i/ical_feed.gif                       |  Bin 683 -> 0 bytes
 civicrm/i/office-calendar.png                 |  Bin 807 -> 0 bytes
 civicrm/i/stop-icon.png                       |  Bin 595 -> 0 bytes
 civicrm/i/tel.gif                             |  Bin 617 -> 0 bytes
 civicrm/install/civicrm.php                   |    2 +-
 civicrm/js/Common.js                          |   35 +-
 civicrm/js/crm.datepicker.js                  |    2 +-
 civicrm/js/crm.drupal7.js                     |   18 +
 civicrm/js/crm.menubar.js                     |   16 +-
 civicrm/js/jquery/jquery.crmEditable.js       |    6 +-
 civicrm/js/jquery/jquery.crmIconPicker.js     |    2 +-
 civicrm/js/jquery/jquery.dashboard.js         |    2 +-
 civicrm/js/view/crm.designer.js               |    2 +-
 civicrm/package.json                          |    2 +-
 civicrm/packages/HTTP/Request.php             | 1521 --------------
 civicrm/packages/HTTP/Request/Listener.php    |  106 -
 civicrm/packages/VERSIONS.php                 |    1 -
 civicrm/release-notes.md                      |   13 +-
 civicrm/release-notes/5.26.2.md               |    4 +-
 civicrm/release-notes/5.27.0.md               |  885 ++++++++
 civicrm/settings/Core.setting.php             |   28 +-
 civicrm/settings/Mailing.setting.php          |   28 +
 civicrm/settings/Search.setting.php           |    2 +-
 .../BootstrapCivi.civi-setup.php              |   26 +-
 .../InstallSchema.civi-setup.php              |   10 -
 .../installDatabase/Preboot.civi-setup.php    |   49 +
 civicrm/sql/civicrm.mysql                     |   13 +-
 civicrm/sql/civicrm_data.mysql                |    3 +-
 civicrm/sql/civicrm_generated.mysql           |    2 +-
 civicrm/templates/CRM/ACL/Page/ACLBasic.tpl   |    2 +-
 .../templates/CRM/Activity/Form/Activity.tpl  |   10 +-
 .../CRM/Activity/Form/ActivityLinks.tpl       |    2 +-
 .../CRM/Activity/Form/ActivityView.tpl        |    7 +-
 .../CRM/Activity/Form/Task/Batch.tpl          |    2 +-
 .../CRM/Activity/Import/Form/Preview.tpl      |    2 +-
 civicrm/templates/CRM/Admin/Form/Options.tpl  |    2 +-
 .../CRM/Admin/Form/Preferences/Display.tpl    |    2 +-
 .../CRM/Admin/Form/Setting/Miscellaneous.tpl  |    6 +-
 .../templates/CRM/Admin/Form/Setting/Smtp.tpl |    2 +-
 .../templates/CRM/Admin/Form/Setting/Url.hlp  |   10 +
 .../templates/CRM/Admin/Form/Setting/Url.tpl  |    9 +
 .../CRM/Admin/Form/WordReplacements.tpl       |    2 +-
 .../templates/CRM/Admin/Page/APIExplorer.js   |    6 +-
 .../templates/CRM/Admin/Page/APIExplorer.tpl  |   28 +-
 civicrm/templates/CRM/Admin/Page/Access.tpl   |    8 +-
 civicrm/templates/CRM/Admin/Page/Admin.tpl    |   65 +-
 .../CRM/Admin/Page/CKEditorConfig.tpl         |    4 +-
 civicrm/templates/CRM/Admin/Page/Job.tpl      |    2 +-
 civicrm/templates/CRM/Admin/Page/JobLog.tpl   |    4 +-
 .../templates/CRM/Admin/Page/LabelFormats.tpl |    3 +-
 .../templates/CRM/Admin/Page/LocationType.tpl |    2 +-
 .../templates/CRM/Admin/Page/Navigation.tpl   |    2 +-
 .../templates/CRM/Admin/Page/OptionGroup.tpl  |    2 +-
 civicrm/templates/CRM/Admin/Page/Options.tpl  |    6 +-
 .../CRM/Admin/Page/ParticipantStatusType.tpl  |    4 +-
 .../CRM/Admin/Page/PaymentProcessor.tpl       |    3 +-
 .../CRM/Admin/Page/PaymentProcessorType.tpl   |    4 +-
 .../templates/CRM/Admin/Page/PdfFormats.tpl   |    2 +-
 civicrm/templates/CRM/Admin/Page/Setting.tpl  |   28 +-
 civicrm/templates/CRM/Badge/Form/Layout.tpl   |    4 +-
 civicrm/templates/CRM/Badge/Page/Layout.tpl   |    5 +-
 civicrm/templates/CRM/Batch/Form/Entry.tpl    |    7 +-
 .../CRM/Campaign/Form/ResultOptions.tpl       |    4 +-
 .../CRM/Campaign/Form/Search/Petition.tpl     |    1 +
 .../CRM/Campaign/Form/Search/Survey.tpl       |    1 +
 .../CRM/Campaign/Form/Task/Interview.tpl      |   12 +-
 .../templates/CRM/Campaign/Page/Petition.tpl  |    6 +-
 civicrm/templates/CRM/Case/Form/Activity.tpl  |    8 +-
 .../templates/CRM/Case/Form/ActivityTab.tpl   |   72 +-
 .../CRM/Case/Form/ActivityToCase.tpl          |    2 +-
 .../templates/CRM/Case/Form/ActivityView.tpl  |    6 +-
 civicrm/templates/CRM/Case/Form/CaseView.tpl  |   22 +-
 civicrm/templates/CRM/Case/Form/Selector.tpl  |    2 +-
 civicrm/templates/CRM/Case/Page/DashBoard.tpl |    4 +-
 .../CRM/Case/Page/DashboardSelector.tpl       |    1 -
 civicrm/templates/CRM/Case/Page/Tab.tpl       |    2 +-
 .../templates/CRM/Contact/Form/Contact.tpl    |    2 +-
 civicrm/templates/CRM/Contact/Form/Domain.tpl |    2 +-
 .../CRM/Contact/Form/Edit/Address.tpl         |    2 +-
 civicrm/templates/CRM/Contact/Form/Merge.tpl  |   10 +-
 .../Contact/Form/Search/AdvancedCriteria.tpl  |    4 +-
 .../Form/Search/Criteria/Fields/sort_name.tpl |   39 +
 .../Form/Search/Criteria/SearchSettings.tpl   |    2 +-
 .../Form/Search/Custom/EventDetails.tpl       |   73 +-
 .../Contact/Form/Search/Custom/FullText.tpl   |   14 +-
 .../CRM/Contact/Form/Search/Intro.tpl         |    4 +-
 .../CRM/Contact/Form/Search/ResultTasks.tpl   |    8 +-
 .../CRM/Contact/Form/Search/table.tpl         |    2 +-
 .../templates/CRM/Contact/Form/Selector.tpl   |   16 +-
 .../templates/CRM/Contact/Form/Task/Batch.tpl |    3 +-
 .../templates/CRM/Contact/Form/Task/Email.tpl |    4 +-
 .../CRM/Contact/Import/Form/Preview.tpl       |    4 +-
 .../CRM/Contact/Import/Form/Summary.tpl       |    9 +-
 .../CRM/Contact/Page/CustomSearch.tpl         |    2 +-
 .../CRM/Contact/Page/DashBoardDashlet.tpl     |    4 +-
 .../templates/CRM/Contact/Page/Dashlet.tpl    |    6 +-
 .../CRM/Contact/Page/DedupeException.tpl      |    4 +-
 .../templates/CRM/Contact/Page/DedupeFind.tpl |   16 +-
 .../CRM/Contact/Page/Inline/Address.tpl       |    6 +-
 .../Page/Inline/CommunicationPreferences.tpl  |    2 +-
 .../CRM/Contact/Page/Inline/ContactInfo.tpl   |    2 +-
 .../CRM/Contact/Page/Inline/ContactName.tpl   |    2 +-
 .../CRM/Contact/Page/Inline/Demographics.tpl  |    2 +-
 .../CRM/Contact/Page/Inline/Email.tpl         |    6 +-
 .../templates/CRM/Contact/Page/Inline/IM.tpl  |    2 +-
 .../CRM/Contact/Page/Inline/OpenID.tpl        |    2 +-
 .../CRM/Contact/Page/Inline/Phone.tpl         |    8 +-
 .../CRM/Contact/Page/Inline/Website.tpl       |    2 +-
 .../Contact/Page/View/CustomDataFieldView.tpl |    2 +-
 .../templates/CRM/Contact/Page/View/Note.tpl  |    8 +-
 .../Contact/Page/View/RelationshipPerm.tpl    |    7 +-
 .../CRM/Contact/Page/View/Summary.tpl         |    2 +-
 .../CRM/Contribute/Form/AdditionalPayment.tpl |    2 +-
 .../Contribute/Form/CancelSubscription.tpl    |    2 +-
 .../CRM/Contribute/Form/Contribution.tpl      |    8 +-
 .../Form/Contribution/PreviewHeader.tpl       |    2 +-
 .../Contribute/Form/Contribution/ThankYou.tpl |    4 +-
 .../Contribute/Form/ContributionPage/Tab.hlp  |   22 +-
 .../Form/ContributionPage/Widget.tpl          |    2 +-
 .../CRM/Contribute/Form/ContributionView.tpl  |   16 +-
 .../CRM/Contribute/Form/PCP/PCPAccount.tpl    |    2 +-
 .../CRM/Contribute/Form/PaymentInfoBlock.tpl  |    2 +-
 .../CRM/Contribute/Form/Search/Common.tpl     |    3 +
 .../CRM/Contribute/Form/SoftCredit.tpl        |    2 +-
 .../CRM/Contribute/Form/Task/Batch.tpl        |    2 +-
 .../CRM/Contribute/Page/ContributionPage.tpl  |    2 +-
 .../CRM/Contribute/Page/ContributionRecur.tpl |  143 +-
 .../CRM/Contribute/Page/DashBoard.tpl         |    2 +-
 .../templates/CRM/Contribute/Page/Premium.tpl |    2 +-
 civicrm/templates/CRM/Contribute/Page/Tab.tpl |    8 +-
 .../CRM/Contribute/Page/UserDashboard.tpl     |    2 +-
 .../templates/CRM/Core/Form/Task/Batch.tpl    |    2 +-
 civicrm/templates/CRM/Core/I18n/Dialog.tpl    |    2 +-
 .../CRM/Core/Page/RecurringEntityPreview.tpl  |    2 +-
 .../CRM/Custom/Form/Edit/CustomData.tpl       |    2 +-
 civicrm/templates/CRM/Custom/Form/Field.tpl   |   10 +-
 .../CRM/Custom/Form/Optionfields.tpl          |    4 +-
 .../CRM/Custom/Page/CustomDataView.tpl        |    4 +-
 civicrm/templates/CRM/Custom/Page/Option.tpl  |    4 +-
 civicrm/templates/CRM/Dashlet/Page/Blog.tpl   |    2 +-
 .../CRM/Dashlet/Page/CaseDashboard.tpl        |    8 +-
 .../CRM/Event/Cart/Page/ViewCart.tpl          |    4 +-
 .../templates/CRM/Event/Form/EventFees.tpl    |    2 +-
 .../Form/ManageEvent/ConfirmRepeatMode.tpl    |    2 +-
 .../CRM/Event/Form/ManageEvent/EventInfo.tpl  |    2 +-
 .../CRM/Event/Form/ManageEvent/Fee.tpl        |    4 +-
 .../Event/Form/ManageEvent/Registration.tpl   |   16 +-
 .../CRM/Event/Form/ManageEvent/Tab.hlp        |   22 +-
 .../templates/CRM/Event/Form/Participant.tpl  |    4 +-
 .../Event/Form/ParticipantFeeSelection.tpl    |    4 +-
 .../CRM/Event/Form/ParticipantView.tpl        |   14 +-
 .../Event/Form/Registration/PreviewHeader.tpl |    2 +-
 .../CRM/Event/Form/Registration/ThankYou.tpl  |    8 +-
 civicrm/templates/CRM/Event/Form/Selector.tpl |    4 +-
 .../templates/CRM/Event/Form/Task/Batch.tpl   |    2 +-
 .../templates/CRM/Event/Page/DashBoard.tpl    |   18 +-
 .../templates/CRM/Event/Page/EventInfo.tpl    |   11 +-
 civicrm/templates/CRM/Event/Page/List.tpl     |    4 +-
 .../templates/CRM/Event/Page/ManageEvent.tpl  |   12 +-
 civicrm/templates/CRM/Event/Page/Tab.tpl      |    4 +-
 .../templates/CRM/Event/Page/iCalLinks.tpl    |   13 +-
 .../templates/CRM/Financial/Form/Search.tpl   |    2 +-
 .../CRM/Financial/Page/FinancialAccount.tpl   |    6 +-
 civicrm/templates/CRM/Form/attachment.tpl     |    6 +-
 civicrm/templates/CRM/Form/body.tpl           |    2 +-
 civicrm/templates/CRM/Friend/Form.tpl         |    2 +-
 .../templates/CRM/Grant/Form/GrantView.tpl    |    8 +-
 civicrm/templates/CRM/Grant/Form/Selector.tpl |    2 +-
 civicrm/templates/CRM/Grant/Page/Tab.tpl      |    2 +-
 civicrm/templates/CRM/Group/Form/Edit.tpl     |    8 +-
 civicrm/templates/CRM/Group/Page/Group.tpl    |    4 +-
 .../templates/CRM/Logging/ReportDetail.tpl    |    4 +-
 .../CRM/Mailing/Form/ForwardMailing.tpl       |    5 +-
 .../templates/CRM/Mailing/Page/Component.tpl  |    2 +-
 civicrm/templates/CRM/Mailing/Page/Event.tpl  |    2 +-
 civicrm/templates/CRM/Mailing/Page/Report.tpl |   11 +-
 .../templates/CRM/Member/Form/Membership.tpl  |    4 +-
 .../CRM/Member/Form/MembershipView.tpl        |    8 +-
 .../templates/CRM/Member/Form/Selector.tpl    |    4 +-
 .../templates/CRM/Member/Form/Task/Batch.tpl  |    2 +-
 .../CRM/Member/Import/Form/Preview.tpl        |    4 +-
 .../CRM/Member/Import/Form/Summary.tpl        |    2 +-
 .../Member/Page/RecurringContributions.tpl    |    2 +-
 civicrm/templates/CRM/Member/Page/Tab.tpl     |   12 +-
 civicrm/templates/CRM/PCP/Form/PCPAccount.tpl |    2 +-
 civicrm/templates/CRM/PCP/Page/PCPInfo.tpl    |    4 +-
 .../templates/CRM/Pledge/Form/Selector.tpl    |    2 +-
 civicrm/templates/CRM/Pledge/Page/Payment.tpl |    2 +-
 civicrm/templates/CRM/Pledge/Page/Tab.tpl     |    2 +-
 .../templates/CRM/Price/Form/OptionFields.tpl |    4 +-
 civicrm/templates/CRM/Price/Page/Option.tpl   |    2 +-
 .../templates/CRM/Profile/Form/Dynamic.tpl    |   10 +-
 .../templates/CRM/Profile/Page/Listings.tpl   |    2 +-
 .../Page/MultipleRecordFieldsListing.tpl      |    4 +-
 civicrm/templates/CRM/Profile/Page/View.tpl   |    4 +-
 civicrm/templates/CRM/Report/Form/Actions.tpl |    4 +-
 .../CRM/Report/Form/Tabs/OrderBy.tpl          |    4 +-
 .../CRM/Report/Page/InstanceList.tpl          |    6 +-
 civicrm/templates/CRM/Report/Page/Options.tpl |    4 +-
 .../CRM/Report/Page/TemplateList.tpl          |    2 +-
 civicrm/templates/CRM/Tag/Form/Tag.tpl        |    2 +-
 civicrm/templates/CRM/Tag/Page/Tag.tpl        |   34 +-
 civicrm/templates/CRM/UF/Page/Group.tpl       |    8 +-
 .../CRM/UF/Page/ProfileTemplates.tpl          |   10 +-
 civicrm/templates/CRM/common/CMSPrint.tpl     |    2 +-
 .../CRM/common/civicrm.settings.php.template  |   19 +
 .../templates/CRM/common/contactFooter.tpl    |    2 +-
 civicrm/templates/CRM/common/fatal.tpl        |    2 +-
 civicrm/templates/CRM/common/formButtons.tpl  |    4 +-
 civicrm/templates/CRM/common/jcalendar.tpl    |    2 +-
 civicrm/templates/CRM/common/joomla.tpl       |    2 +-
 .../templates/CRM/common/navigation.js.tpl    |    4 -
 civicrm/templates/CRM/common/status.tpl       |    2 +-
 civicrm/templates/CRM/common/success.tpl      |    4 +-
 civicrm/vendor/autoload.php                   |    2 +-
 civicrm/vendor/composer/autoload_classmap.php |    1 +
 .../vendor/composer/autoload_namespaces.php   |    1 -
 civicrm/vendor/composer/autoload_psr4.php     |    1 +
 civicrm/vendor/composer/autoload_real.php     |   14 +-
 civicrm/vendor/composer/autoload_static.php   |   22 +-
 civicrm/vendor/composer/installed.json        |  245 ++-
 civicrm/vendor/pear/log/.travis.yml           |   22 +-
 civicrm/vendor/pear/log/composer.json         |    2 +-
 civicrm/vendor/pear/log/package.xml           |   21 +-
 civicrm/vendor/pear/log/phpdoc.sh             |    3 -
 .../vendor/pear/pear_exception/composer.json  |    4 +-
 civicrm/vendor/psr/container/.gitignore       |    3 +
 civicrm/vendor/psr/container/LICENSE          |   21 +
 civicrm/vendor/psr/container/README.md        |    5 +
 civicrm/vendor/psr/container/composer.json    |   27 +
 .../src/ContainerExceptionInterface.php       |   13 +
 .../psr/container/src/ContainerInterface.php  |   37 +
 .../src/NotFoundExceptionInterface.php        |   13 +
 civicrm/vendor/symfony/config/CHANGELOG.md    |   34 +-
 civicrm/vendor/symfony/config/ConfigCache.php |   27 +-
 .../symfony/config/Definition/ArrayNode.php   |   38 +-
 .../symfony/config/Definition/BaseNode.php    |   76 +-
 .../Builder/ArrayNodeDefinition.php           |  119 +-
 .../Builder/BooleanNodeDefinition.php         |   19 +-
 .../config/Definition/Builder/ExprBuilder.php |   29 +-
 .../config/Definition/Builder/NodeBuilder.php |   18 +-
 .../Definition/Builder/NodeDefinition.php     |   20 +-
 .../Builder/NormalizationBuilder.php          |    6 +-
 .../Builder/NumericNodeDefinition.php         |   12 +-
 .../config/Definition/Builder/TreeBuilder.php |    4 +
 .../Definition/Builder/ValidationBuilder.php  |    2 +-
 .../Builder/VariableNodeDefinition.php        |    1 +
 .../Definition/Dumper/XmlReferenceDumper.php  |   28 +-
 .../Definition/Dumper/YamlReferenceDumper.php |  107 +-
 .../symfony/config/Definition/EnumNode.php    |    2 +-
 .../symfony/config/Definition/Processor.php   |    6 +-
 .../config/Definition/PrototypedArrayNode.php |   60 +-
 .../config/Definition/ReferenceDumper.php     |   24 -
 .../DependencyInjection/ConfigCachePass.php   |   52 +
 .../Exception/FileLoaderLoadException.php     |   12 +-
 .../FileLocatorFileNotFoundException.php      |   34 +
 civicrm/vendor/symfony/config/FileLocator.php |   12 +-
 .../symfony/config/FileLocatorInterface.php   |    5 +-
 civicrm/vendor/symfony/config/LICENSE         |    2 +-
 .../config/Loader/DelegatingLoader.php        |    2 +-
 .../symfony/config/Loader/FileLoader.php      |   88 +-
 .../symfony/config/Loader/GlobFileLoader.php  |   36 +
 .../vendor/symfony/config/Loader/Loader.php   |    2 +-
 .../symfony/config/Loader/LoaderResolver.php  |    4 +-
 civicrm/vendor/symfony/config/README.md       |    2 +-
 .../Resource/BCResourceInterfaceChecker.php   |   36 -
 .../Resource/ClassExistenceResource.php       |  233 +++
 .../config/Resource/ComposerResource.php      |   84 +
 .../config/Resource/DirectoryResource.php     |   20 +-
 .../config/Resource/FileExistenceResource.php |    8 +-
 .../symfony/config/Resource/FileResource.php  |   22 +-
 .../symfony/config/Resource/GlobResource.php  |  159 ++
 .../Resource/ReflectionClassResource.php      |  250 +++
 .../config/Resource/ResourceInterface.php     |   25 -
 .../config/ResourceCheckerConfigCache.php     |   73 +-
 .../ResourceCheckerConfigCacheFactory.php     |    9 +-
 .../Util/Exception/InvalidXmlException.php    |   21 +
 .../Util/Exception/XmlParsingException.php    |   21 +
 .../vendor/symfony/config/Util/XmlUtils.php   |   81 +-
 civicrm/vendor/symfony/config/composer.json   |   15 +-
 .../symfony/dependency-injection/Alias.php    |   38 +-
 .../Argument/ArgumentInterface.php            |   27 +
 .../Argument/BoundArgument.php                |   46 +
 .../Argument/IteratorArgument.php             |   55 +
 .../Argument/RewindableGenerator.php          |   46 +
 .../Argument/ServiceClosureArgument.php       |   50 +
 .../Argument/TaggedIteratorArgument.php       |   37 +
 .../symfony/dependency-injection/CHANGELOG.md |   59 +
 .../dependency-injection/ChildDefinition.php  |  126 ++
 .../Compiler/AbstractRecursivePass.php        |  174 ++
 .../Compiler/AnalyzeServiceReferencesPass.php |  165 +-
 .../Compiler/AutoAliasServicePass.php         |    2 +-
 .../Compiler/AutowireExceptionPass.php        |   74 +
 .../Compiler/AutowirePass.php                 |  555 +++--
 .../Compiler/AutowireRequiredMethodsPass.php  |   70 +
 .../Compiler/CheckArgumentsValidityPass.php   |   87 +
 .../Compiler/CheckCircularReferencesPass.php  |    8 +-
 .../Compiler/CheckDefinitionValidityPass.php  |   45 +-
 ...xceptionOnInvalidReferenceBehaviorPass.php |   43 +-
 .../Compiler/CheckReferenceValidityPass.php   |  130 +-
 .../Compiler/Compiler.php                     |   72 +-
 .../Compiler/DecoratorServicePass.php         |   31 +-
 .../Compiler/DefinitionErrorExceptionPass.php |   39 +
 .../Compiler/FactoryReturnTypePass.php        |  112 +
 .../Compiler/InlineServiceDefinitionsPass.php |  141 +-
 .../Compiler/LoggingFormatter.php             |    9 +
 .../MergeExtensionConfigurationPass.php       |  158 +-
 .../Compiler/PassConfig.php                   |  149 +-
 .../Compiler/PriorityTaggedServiceTrait.php   |   54 +
 .../Compiler/RegisterEnvVarProcessorsPass.php |   78 +
 .../RegisterServiceSubscribersPass.php        |  101 +
 .../RemoveAbstractDefinitionsPass.php         |    5 +-
 .../Compiler/RemovePrivateAliasesPass.php     |    7 +-
 .../Compiler/RemoveUnusedDefinitionsPass.php  |   23 +-
 .../ReplaceAliasByActualDefinitionPass.php    |   91 +-
 .../Compiler/ResolveBindingsPass.php          |  180 ++
 .../Compiler/ResolveChildDefinitionsPass.php  |  198 ++
 .../Compiler/ResolveClassPass.php             |   56 +
 .../ResolveDefinitionTemplatesPass.php        |  206 +-
 .../Compiler/ResolveEnvPlaceholdersPass.php   |   44 +
 .../Compiler/ResolveFactoryClassPass.php      |   38 +
 .../Compiler/ResolveHotPathPass.php           |   71 +
 .../ResolveInstanceofConditionalsPass.php     |  156 ++
 .../Compiler/ResolveInvalidReferencesPass.php |  110 +-
 .../Compiler/ResolveNamedArgumentsPass.php    |  102 +
 .../ResolveParameterPlaceHoldersPass.php      |   85 +-
 .../Compiler/ResolvePrivatesPass.php          |   40 +
 .../ResolveReferencesToAliasesPass.php        |   83 +-
 .../ResolveServiceSubscribersPass.php         |   51 +
 .../ResolveTaggedIteratorArgumentPass.php     |   38 +
 .../Compiler/ServiceLocatorTagPass.php        |  126 ++
 .../Compiler/ServiceReferenceGraph.php        |   18 +-
 .../Compiler/ServiceReferenceGraphEdge.php    |   45 +-
 .../Compiler/ServiceReferenceGraphNode.php    |   16 +-
 .../Config/AutowireServiceResource.php        |   88 +
 .../Config/ContainerParametersResource.php    |   64 +
 .../ContainerParametersResourceChecker.php    |   52 +
 .../dependency-injection/Container.php        |  528 +++--
 .../dependency-injection/ContainerAware.php   |   35 -
 .../dependency-injection/ContainerBuilder.php | 1017 +++++++---
 .../ContainerInterface.php                    |   77 +-
 .../dependency-injection/Definition.php       |  432 ++--
 .../DefinitionDecorator.php                   |  214 +-
 .../Dumper/DumperInterface.php                |    6 +-
 .../Dumper/GraphvizDumper.php                 |   74 +-
 .../dependency-injection/Dumper/PhpDumper.php | 1804 +++++++++++------
 .../dependency-injection/Dumper/XmlDumper.php |   88 +-
 .../Dumper/YamlDumper.php                     |   94 +-
 .../dependency-injection/EnvVarProcessor.php  |  163 ++
 .../EnvVarProcessorInterface.php              |   40 +
 .../Exception/AutowiringFailedException.php   |   32 +
 .../Exception/EnvNotFoundException.php        |   25 +
 .../Exception/EnvParameterException.php       |   25 +
 .../Exception/ExceptionInterface.php          |    4 +-
 .../Exception/InactiveScopeException.php      |   41 -
 .../Exception/ParameterNotFoundException.php  |   17 +-
 .../ScopeCrossingInjectionException.php       |   65 -
 .../ScopeWideningInjectionException.php       |   64 -
 .../Exception/ServiceNotFoundException.php    |   17 +-
 .../ExpressionLanguage.php                    |    8 +-
 .../ExpressionLanguageProvider.php            |   13 +-
 .../Extension/Extension.php                   |   43 +-
 .../Extension/ExtensionInterface.php          |    2 +-
 .../IntrospectableContainerInterface.php      |   32 -
 .../symfony/dependency-injection/LICENSE      |    2 +-
 .../Instantiator/RealServiceInstantiator.php  |    2 +-
 .../LazyProxy/PhpDumper/DumperInterface.php   |    5 +-
 .../LazyProxy/PhpDumper/NullDumper.php        |    4 +-
 .../LazyProxy/ProxyHelper.php                 |   64 +
 .../Configurator/AbstractConfigurator.php     |   87 +
 .../AbstractServiceConfigurator.php           |  117 ++
 .../Loader/Configurator/AliasConfigurator.php |   30 +
 .../Configurator/ContainerConfigurator.php    |  135 ++
 .../Configurator/DefaultsConfigurator.php     |   68 +
 .../InlineServiceConfigurator.php             |   36 +
 .../Configurator/InstanceofConfigurator.php   |   43 +
 .../Configurator/ParametersConfigurator.php   |   57 +
 .../Configurator/PrototypeConfigurator.php    |   87 +
 .../Configurator/ReferenceConfigurator.php    |   66 +
 .../Configurator/ServiceConfigurator.php      |   70 +
 .../Configurator/ServicesConfigurator.php     |  160 ++
 .../Configurator/Traits/AbstractTrait.php     |   33 +
 .../Configurator/Traits/ArgumentTrait.php     |   44 +
 .../Traits/AutoconfigureTrait.php             |   37 +
 .../Configurator/Traits/AutowireTrait.php     |   29 +
 .../Loader/Configurator/Traits/BindTrait.php  |   43 +
 .../Loader/Configurator/Traits/CallTrait.php  |   34 +
 .../Loader/Configurator/Traits/ClassTrait.php |   32 +
 .../Configurator/Traits/ConfiguratorTrait.php |   29 +
 .../Configurator/Traits/DecorateTrait.php     |   35 +
 .../Configurator/Traits/DeprecateTrait.php    |   33 +
 .../Configurator/Traits/FactoryTrait.php      |   37 +
 .../Loader/Configurator/Traits/FileTrait.php  |   29 +
 .../Loader/Configurator/Traits/LazyTrait.php  |   29 +
 .../Configurator/Traits/ParentTrait.php       |   55 +
 .../Configurator/Traits/PropertyTrait.php     |   30 +
 .../Configurator/Traits/PublicTrait.php       |   39 +
 .../Loader/Configurator/Traits/ShareTrait.php |   29 +
 .../Configurator/Traits/SyntheticTrait.php    |   30 +
 .../Loader/Configurator/Traits/TagTrait.php   |   42 +
 .../Loader/DirectoryLoader.php                |    4 +-
 .../Loader/FileLoader.php                     |  143 ++
 .../Loader/GlobFileLoader.php                 |   40 +
 .../Loader/IniFileLoader.php                  |   53 +-
 .../Loader/PhpFileLoader.php                  |   32 +-
 .../Loader/XmlFileLoader.php                  |  401 ++--
 .../Loader/YamlFileLoader.php                 |  604 +++++-
 .../schema/dic/services/services-1.0.xsd      |   86 +-
 .../EnvPlaceholderParameterBag.php            |  123 ++
 .../ParameterBag/FrozenParameterBag.php       |    2 +-
 .../ParameterBag/ParameterBag.php             |   96 +-
 .../ParameterBag/ParameterBagInterface.php    |    7 +
 .../symfony/dependency-injection/README.md    |    2 +-
 .../dependency-injection/Reference.php        |   25 +-
 .../symfony/dependency-injection/Scope.php    |   41 -
 .../dependency-injection/ScopeInterface.php   |   26 -
 .../dependency-injection/ServiceLocator.php   |  146 ++
 .../ServiceSubscriberInterface.php            |   50 +
 .../dependency-injection/SimpleXMLElement.php |  116 --
 .../dependency-injection/TypedReference.php   |   51 +
 .../dependency-injection/composer.json        |   24 +-
 .../symfony/event-dispatcher/CHANGELOG.md     |   19 +
 .../ContainerAwareEventDispatcher.php         |   45 +-
 .../Debug/TraceableEventDispatcher.php        |  197 +-
 .../TraceableEventDispatcherInterface.php     |    2 +
 .../Debug/WrappedListener.php                 |   58 +-
 .../RegisterListenersPass.php                 |   97 +-
 .../vendor/symfony/event-dispatcher/Event.php |   62 -
 .../event-dispatcher/EventDispatcher.php      |   98 +-
 .../EventDispatcherInterface.php              |   28 +-
 .../EventSubscriberInterface.php              |    8 +-
 .../symfony/event-dispatcher/GenericEvent.php |    6 +-
 .../vendor/symfony/event-dispatcher/LICENSE   |    2 +-
 .../vendor/symfony/event-dispatcher/README.md |    2 +-
 .../symfony/event-dispatcher/composer.json    |   15 +-
 .../vendor/symfony/filesystem/CHANGELOG.md    |   20 +
 .../Exception/IOExceptionInterface.php        |    2 +-
 .../vendor/symfony/filesystem/Filesystem.php  |  232 ++-
 civicrm/vendor/symfony/filesystem/LICENSE     |    2 +-
 .../vendor/symfony/filesystem/LockHandler.php |    6 +
 civicrm/vendor/symfony/filesystem/README.md   |    2 +-
 .../vendor/symfony/filesystem/composer.json   |    4 +-
 .../finder/Adapter/AbstractAdapter.php        |  240 ---
 .../finder/Adapter/AbstractFindAdapter.php    |  325 ---
 .../finder/Adapter/AdapterInterface.php       |  124 --
 .../symfony/finder/Adapter/BsdFindAdapter.php |  107 -
 .../symfony/finder/Adapter/GnuFindAdapter.php |  108 -
 .../symfony/finder/Adapter/PhpAdapter.php     |  101 -
 civicrm/vendor/symfony/finder/CHANGELOG.md    |   16 +
 .../symfony/finder/Comparator/Comparator.php  |    2 +-
 .../Exception/AdapterFailureException.php     |   47 -
 .../finder/Exception/ExceptionInterface.php   |    2 +
 .../OperationNotPermitedException.php         |   23 -
 .../ShellCommandFailureException.php          |   41 -
 .../symfony/finder/Expression/Expression.php  |  148 --
 .../vendor/symfony/finder/Expression/Glob.php |  108 -
 .../symfony/finder/Expression/Regex.php       |  321 ---
 .../finder/Expression/ValueInterface.php      |   62 -
 civicrm/vendor/symfony/finder/Finder.php      |  267 +--
 civicrm/vendor/symfony/finder/Glob.php        |   28 +-
 .../finder/Iterator/CustomFilterIterator.php  |    2 +-
 .../Iterator/DateRangeFilterIterator.php      |    2 +-
 .../ExcludeDirectoryFilterIterator.php        |    8 +-
 .../finder/Iterator/FilePathsIterator.php     |  135 --
 .../finder/Iterator/FilterIterator.php        |    2 +
 .../Iterator/MultiplePcreFilterIterator.php   |    6 +-
 .../Iterator/RecursiveDirectoryIterator.php   |   10 +-
 .../Iterator/SizeRangeFilterIterator.php      |    2 +-
 .../finder/Iterator/SortableIterator.php      |   14 +-
 civicrm/vendor/symfony/finder/LICENSE         |    2 +-
 .../vendor/symfony/finder/Shell/Command.php   |  278 ---
 civicrm/vendor/symfony/finder/Shell/Shell.php |  101 -
 civicrm/vendor/symfony/finder/composer.json   |    4 +-
 .../symfony/polyfill-ctype/bootstrap.php      |   20 +
 .../symfony/polyfill-ctype/composer.json      |    2 +-
 .../vendor/symfony/polyfill-iconv/README.md   |    4 +-
 .../Resources/charset/translit.php            |  129 ++
 .../symfony/polyfill-iconv/bootstrap.php      |   46 +-
 .../symfony/polyfill-iconv/composer.json      |    2 +-
 civicrm/vendor/symfony/process/CHANGELOG.md   |   17 +
 .../symfony/process/ExecutableFinder.php      |   18 +-
 .../vendor/symfony/process/InputStream.php    |   92 +
 civicrm/vendor/symfony/process/LICENSE        |    2 +-
 .../symfony/process/PhpExecutableFinder.php   |    6 +-
 civicrm/vendor/symfony/process/PhpProcess.php |   20 +-
 .../symfony/process/Pipes/AbstractPipes.php   |   64 +-
 .../symfony/process/Pipes/PipesInterface.php  |    7 +
 .../symfony/process/Pipes/UnixPipes.php       |   67 +-
 .../symfony/process/Pipes/WindowsPipes.php    |   77 +-
 civicrm/vendor/symfony/process/Process.php    |  476 +++--
 .../vendor/symfony/process/ProcessBuilder.php |   35 +-
 .../vendor/symfony/process/ProcessUtils.php   |   25 +-
 civicrm/vendor/symfony/process/composer.json  |    4 +-
 .../xml/schema/Contribute/Contribution.xml    |    3 +
 .../schema/Contribute/ContributionRecur.xml   |    2 +-
 civicrm/xml/schema/Core/CustomField.xml       |   11 +
 civicrm/xml/schema/Core/OptionValue.xml       |    2 +-
 civicrm/xml/schema/Mailing/MailingAB.xml      |    1 +
 civicrm/xml/schema/Member/MembershipType.xml  |    1 +
 civicrm/xml/schema/Price/PriceField.xml       |    1 +
 civicrm/xml/schema/Price/PriceFieldValue.xml  |    2 +
 .../xml/templates/civicrm_state_province.tpl  |    1 +
 civicrm/xml/version.xml                       |    2 +-
 readme.txt                                    |   18 +-
 wp-rest/Civi/Mailing-Hooks.php                |    2 +
 1006 files changed, 19223 insertions(+), 13221 deletions(-)
 create mode 100644 civicrm/CRM/Core/Smarty/plugins/block.icon.php
 create mode 100644 civicrm/CRM/Core/Smarty/plugins/function.copyIcon.php
 create mode 100644 civicrm/CRM/Core/Smarty/plugins/function.privacyFlag.php
 create mode 100644 civicrm/CRM/Mailing/Page/Open.php
 create mode 100644 civicrm/CRM/Mailing/Page/Url.php
 create mode 100644 civicrm/CRM/Upgrade/Incremental/php/FiveTwentySeven.php
 delete mode 100644 civicrm/CRM/Upgrade/Incremental/sql/5.26.0.mysql.tpl
 delete mode 100644 civicrm/CRM/Upgrade/Incremental/sql/5.26.2.mysql.tpl
 create mode 100644 civicrm/CRM/Upgrade/Incremental/sql/5.27.0.mysql.tpl
 rename civicrm/CRM/Upgrade/Incremental/sql/{5.26.1.mysql.tpl => 5.27.alpha1.mysql.tpl} (60%)
 create mode 100644 civicrm/CRM/Upgrade/Incremental/sql/5.27.beta1.mysql.tpl
 create mode 100644 civicrm/Civi/Api4/ContributionRecur.php
 delete mode 100644 civicrm/Civi/Api4/Event/Subscriber/ContactSchemaMapSubscriber.php
 delete mode 100644 civicrm/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php
 create mode 100644 civicrm/Civi/Api4/MembershipType.php
 create mode 100644 civicrm/Civi/Api4/PriceField.php
 create mode 100644 civicrm/Civi/Api4/PriceFieldValue.php
 create mode 100644 civicrm/Civi/Api4/PriceSet.php
 delete mode 100644 civicrm/Civi/Api4/Service/Schema/Joinable/OptionValueJoinable.php
 create mode 100644 civicrm/Civi/Api4/Service/Spec/Provider/ContributionRecurCreationSpecProvider.php
 rename civicrm/Civi/Api4/{Event/GetSpecEvent.php => Service/Spec/Provider/PriceFieldValueCreationSpecProvider.php} (50%)
 create mode 100644 civicrm/Civi/Test/GuzzleTestTrait.php
 delete mode 100644 civicrm/i/TreeMinus.gif
 delete mode 100644 civicrm/i/TreeMinusWhite.gif
 delete mode 100644 civicrm/i/TreePlus.gif
 delete mode 100644 civicrm/i/TreePlusWhite.gif
 delete mode 100644 civicrm/i/admin/01.png
 delete mode 100644 civicrm/i/admin/02.png
 delete mode 100644 civicrm/i/admin/03.png
 delete mode 100644 civicrm/i/admin/04.png
 delete mode 100644 civicrm/i/admin/05.png
 delete mode 100644 civicrm/i/admin/06.png
 delete mode 100644 civicrm/i/admin/07.png
 delete mode 100644 civicrm/i/admin/08.png
 delete mode 100644 civicrm/i/admin/09.png
 delete mode 100644 civicrm/i/admin/10.png
 delete mode 100644 civicrm/i/admin/11.png
 delete mode 100644 civicrm/i/admin/12.png
 delete mode 100644 civicrm/i/admin/13.png
 delete mode 100644 civicrm/i/admin/14.png
 delete mode 100644 civicrm/i/admin/36.png
 delete mode 100644 civicrm/i/admin/DataStore.gif
 delete mode 100644 civicrm/i/admin/PayPal_mark_37x23.gif
 delete mode 100644 civicrm/i/admin/Premiums.png
 delete mode 100644 civicrm/i/admin/Profile.png
 delete mode 100644 civicrm/i/admin/Synch_user.png
 delete mode 100644 civicrm/i/admin/accepted_creditcards.png
 delete mode 100644 civicrm/i/admin/communication.png
 delete mode 100644 civicrm/i/admin/contribution_types.png
 delete mode 100644 civicrm/i/admin/custm_data.png
 delete mode 100644 civicrm/i/admin/domain.png
 delete mode 100644 civicrm/i/admin/duplicate_matching.png
 delete mode 100644 civicrm/i/admin/event_manage.png
 delete mode 100644 civicrm/i/admin/event_type.png
 delete mode 100644 civicrm/i/admin/import_export_map.png
 delete mode 100644 civicrm/i/admin/membership_status.png
 delete mode 100644 civicrm/i/admin/membership_type.png
 delete mode 100644 civicrm/i/admin/online_contribution_pages.png
 delete mode 100644 civicrm/i/admin/option.png
 delete mode 100644 civicrm/i/admin/parti_role.png
 delete mode 100644 civicrm/i/admin/parti_status.png
 delete mode 100644 civicrm/i/admin/payment_instruments.png
 delete mode 100644 civicrm/i/admin/price_sets.png
 delete mode 100644 civicrm/i/admin/rela_type.png
 delete mode 100644 civicrm/i/admin/small/01.png
 delete mode 100644 civicrm/i/admin/small/02.png
 delete mode 100644 civicrm/i/admin/small/03.png
 delete mode 100644 civicrm/i/admin/small/04.png
 delete mode 100644 civicrm/i/admin/small/05.png
 delete mode 100644 civicrm/i/admin/small/06.png
 delete mode 100644 civicrm/i/admin/small/07.png
 delete mode 100644 civicrm/i/admin/small/08.png
 delete mode 100644 civicrm/i/admin/small/09.png
 delete mode 100644 civicrm/i/admin/small/10.png
 delete mode 100644 civicrm/i/admin/small/11.png
 delete mode 100644 civicrm/i/admin/small/12.png
 delete mode 100644 civicrm/i/admin/small/13.png
 delete mode 100644 civicrm/i/admin/small/36.png
 delete mode 100644 civicrm/i/admin/small/Premiums.png
 delete mode 100644 civicrm/i/admin/small/Profile.png
 delete mode 100644 civicrm/i/admin/small/Synch_user.png
 delete mode 100644 civicrm/i/admin/small/accepted_creditcards.png
 delete mode 100644 civicrm/i/admin/small/case_type.gif
 delete mode 100644 civicrm/i/admin/small/case_type.png
 delete mode 100644 civicrm/i/admin/small/communication.png
 delete mode 100644 civicrm/i/admin/small/contribution_types.png
 delete mode 100644 civicrm/i/admin/small/custm_data.png
 delete mode 100644 civicrm/i/admin/small/domain.png
 delete mode 100644 civicrm/i/admin/small/duplicate_matching.png
 delete mode 100644 civicrm/i/admin/small/event_manage.png
 delete mode 100644 civicrm/i/admin/small/event_type.png
 delete mode 100644 civicrm/i/admin/small/grant_type.png
 delete mode 100644 civicrm/i/admin/small/import_export_map.png
 delete mode 100644 civicrm/i/admin/small/membership_status.png
 delete mode 100644 civicrm/i/admin/small/membership_type.png
 delete mode 100644 civicrm/i/admin/small/online_contribution_pages.png
 delete mode 100644 civicrm/i/admin/small/option.png
 delete mode 100644 civicrm/i/admin/small/parti_role.png
 delete mode 100644 civicrm/i/admin/small/parti_status.png
 delete mode 100644 civicrm/i/admin/small/payment_instruments.png
 delete mode 100644 civicrm/i/admin/small/price_sets.png
 delete mode 100644 civicrm/i/admin/small/redaction_type.png
 delete mode 100644 civicrm/i/admin/small/rela_type.png
 delete mode 100644 civicrm/i/admin/small/report_list.gif
 delete mode 100644 civicrm/i/admin/small/report_template.gif
 delete mode 100644 civicrm/i/admin/small/soft_credit_type.png
 delete mode 100644 civicrm/i/admin/small/template.png
 delete mode 100644 civicrm/i/admin/small/title.png
 delete mode 100644 civicrm/i/admin/small/updatepath.png
 delete mode 100644 civicrm/i/admin/template.png
 delete mode 100644 civicrm/i/admin/title.png
 delete mode 100644 civicrm/i/check.gif
 delete mode 100644 civicrm/i/copy.png
 delete mode 100644 civicrm/i/feed-icon.png
 delete mode 100644 civicrm/i/geotag_16.png
 delete mode 100644 civicrm/i/grippie.png
 delete mode 100644 civicrm/i/group.png
 delete mode 100644 civicrm/i/ical_feed.gif
 delete mode 100644 civicrm/i/office-calendar.png
 delete mode 100644 civicrm/i/stop-icon.png
 delete mode 100644 civicrm/i/tel.gif
 create mode 100644 civicrm/js/crm.drupal7.js
 delete mode 100644 civicrm/packages/HTTP/Request.php
 delete mode 100644 civicrm/packages/HTTP/Request/Listener.php
 create mode 100644 civicrm/release-notes/5.27.0.md
 create mode 100644 civicrm/setup/plugins/installDatabase/Preboot.civi-setup.php
 create mode 100644 civicrm/templates/CRM/Contact/Form/Search/Criteria/Fields/sort_name.tpl
 delete mode 100755 civicrm/vendor/pear/log/phpdoc.sh
 create mode 100644 civicrm/vendor/psr/container/.gitignore
 create mode 100644 civicrm/vendor/psr/container/LICENSE
 create mode 100644 civicrm/vendor/psr/container/README.md
 create mode 100644 civicrm/vendor/psr/container/composer.json
 create mode 100644 civicrm/vendor/psr/container/src/ContainerExceptionInterface.php
 create mode 100644 civicrm/vendor/psr/container/src/ContainerInterface.php
 create mode 100644 civicrm/vendor/psr/container/src/NotFoundExceptionInterface.php
 delete mode 100644 civicrm/vendor/symfony/config/Definition/ReferenceDumper.php
 create mode 100644 civicrm/vendor/symfony/config/DependencyInjection/ConfigCachePass.php
 create mode 100644 civicrm/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php
 create mode 100644 civicrm/vendor/symfony/config/Loader/GlobFileLoader.php
 delete mode 100644 civicrm/vendor/symfony/config/Resource/BCResourceInterfaceChecker.php
 create mode 100644 civicrm/vendor/symfony/config/Resource/ClassExistenceResource.php
 create mode 100644 civicrm/vendor/symfony/config/Resource/ComposerResource.php
 create mode 100644 civicrm/vendor/symfony/config/Resource/GlobResource.php
 create mode 100644 civicrm/vendor/symfony/config/Resource/ReflectionClassResource.php
 create mode 100644 civicrm/vendor/symfony/config/Util/Exception/InvalidXmlException.php
 create mode 100644 civicrm/vendor/symfony/config/Util/Exception/XmlParsingException.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Argument/BoundArgument.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Argument/IteratorArgument.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/ChildDefinition.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Config/AutowireServiceResource.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/ContainerAware.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/EnvVarProcessor.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Exception/EnvParameterException.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/Exception/InactiveScopeException.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/Exception/ScopeCrossingInjectionException.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/Exception/ScopeWideningInjectionException.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/IntrospectableContainerInterface.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/Scope.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/ScopeInterface.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/ServiceLocator.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/ServiceSubscriberInterface.php
 delete mode 100644 civicrm/vendor/symfony/dependency-injection/SimpleXMLElement.php
 create mode 100644 civicrm/vendor/symfony/dependency-injection/TypedReference.php
 delete mode 100644 civicrm/vendor/symfony/finder/Adapter/AbstractAdapter.php
 delete mode 100644 civicrm/vendor/symfony/finder/Adapter/AbstractFindAdapter.php
 delete mode 100644 civicrm/vendor/symfony/finder/Adapter/AdapterInterface.php
 delete mode 100644 civicrm/vendor/symfony/finder/Adapter/BsdFindAdapter.php
 delete mode 100644 civicrm/vendor/symfony/finder/Adapter/GnuFindAdapter.php
 delete mode 100644 civicrm/vendor/symfony/finder/Adapter/PhpAdapter.php
 delete mode 100644 civicrm/vendor/symfony/finder/Exception/AdapterFailureException.php
 delete mode 100644 civicrm/vendor/symfony/finder/Exception/OperationNotPermitedException.php
 delete mode 100644 civicrm/vendor/symfony/finder/Exception/ShellCommandFailureException.php
 delete mode 100644 civicrm/vendor/symfony/finder/Expression/Expression.php
 delete mode 100644 civicrm/vendor/symfony/finder/Expression/Glob.php
 delete mode 100644 civicrm/vendor/symfony/finder/Expression/Regex.php
 delete mode 100644 civicrm/vendor/symfony/finder/Expression/ValueInterface.php
 delete mode 100644 civicrm/vendor/symfony/finder/Iterator/FilePathsIterator.php
 delete mode 100644 civicrm/vendor/symfony/finder/Shell/Command.php
 delete mode 100644 civicrm/vendor/symfony/finder/Shell/Shell.php
 create mode 100644 civicrm/vendor/symfony/process/InputStream.php

diff --git a/README.md b/README.md
index a153d40fbc..b83a64fbd4 100644
--- a/README.md
+++ b/README.md
@@ -9,11 +9,14 @@ This is the development repository for the *CiviCRM* plugin for *WordPress*. Wha
 
 If you want to contribute to the development of this plugin, please bear the following in mind:
 
-* Bug fixes should go in the branch 4.5 branch (stable)
* Structural changes should go under master (trunk, i.e. 4.6).
+* Bug Fixes and structural changes should go in the master branch.
+* Regression fixes should go in the current version branch.
 
 ----
-
### About CiviCRM ###
-
CiviCRM is web-based, open source, Constituent Relationship Management (CRM) software geared toward meeting the needs of non-profit and other civic-sector organizations.
+
+### About CiviCRM ###
+
+CiviCRM is web-based, open source, Constituent Relationship Management (CRM) software geared toward meeting the needs of non-profit and other civic-sector organizations.
 
 As a non profit committed to the public good itself, CiviCRM understands that forging and growing strong relationships with constituents is about more than collecting and tracking constituent data - it is about sustaining relationships with supporters over time.
 
@@ -23,4 +26,4 @@ With CiviCRM's robust feature set, organizations can further their mission throu
 
 CiviCRM is localized in over 20 languages including: Chinese (Taiwan, China), Dutch, English (Australia, Canada, U.S., UK), French (France, Canada), German, Italian, Japanese, Russian, and Swedish.
 
-For more information, visit the [CiviCRM website](https://civicrm.org).
\ No newline at end of file
+For more information, visit the [CiviCRM website](https://civicrm.org).
diff --git a/civicrm.php b/civicrm.php
index 9a11fbfab1..fc1b23a1ba 100644
--- a/civicrm.php
+++ b/civicrm.php
@@ -2,7 +2,9 @@
 /*
 Plugin Name: CiviCRM
 Description: CiviCRM - Growing and Sustaining Relationships
-Version: 5.26.2
+Version: 5.27.0
+Requires at least: 4.9
+Requires PHP:      7.1
 Author: CiviCRM LLC
 Author URI: https://civicrm.org/
 Plugin URI: https://docs.civicrm.org/sysadmin/en/latest/install/wordpress/
@@ -54,7 +56,7 @@ if ( ! defined( 'ABSPATH' ) ) exit;
 
 
 // Set version here: when it changes, will force JS to reload
-define( 'CIVICRM_PLUGIN_VERSION', '5.26.2' );
+define( 'CIVICRM_PLUGIN_VERSION', '5.27.0' );
 
 // Store reference to this file
 if (!defined('CIVICRM_PLUGIN_FILE')) {
diff --git a/civicrm/CRM/ACL/API.php b/civicrm/CRM/ACL/API.php
index 95273671bf..ba4991dc2d 100644
--- a/civicrm/CRM/ACL/API.php
+++ b/civicrm/CRM/ACL/API.php
@@ -88,11 +88,13 @@ class CRM_ACL_API {
     // the default value which is valid for the final AND
     $deleteClause = ' ( 1 ) ';
     if (!$skipDeleteClause) {
-      if (CRM_Core_Permission::check('access deleted contacts') and $onlyDeleted) {
-        $deleteClause = '(contact_a.is_deleted)';
+      if (CRM_Core_Permission::check('access deleted contacts')) {
+        if ($onlyDeleted) {
+          $deleteClause = '(contact_a.is_deleted)';
+        }
       }
       else {
-        // CRM-6181
+        // Exclude deleted contacts due to permissions
         $deleteClause = '(contact_a.is_deleted = 0)';
       }
     }
diff --git a/civicrm/CRM/Activity/BAO/Activity.php b/civicrm/CRM/Activity/BAO/Activity.php
index 332e8bac87..1efa820244 100644
--- a/civicrm/CRM/Activity/BAO/Activity.php
+++ b/civicrm/CRM/Activity/BAO/Activity.php
@@ -182,6 +182,8 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
         // CRM-13994 delete activity entity_tag
         $query = "DELETE FROM civicrm_entity_tag WHERE entity_table = 'civicrm_activity' AND entity_id = %1";
         $dao = CRM_Core_DAO::executeQuery($query, [1 => [$activity->id, 'Positive']]);
+
+        CRM_Core_BAO_File::deleteEntityFile('civicrm_activity', $activity->id);
       }
     }
     else {
@@ -989,11 +991,13 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
   }
 
   /**
-   * @param int $userID
+   * @param int $sourceContactID
+   *   The contact ID of the email "from".
    * @param string $subject
    * @param string $html
    * @param string $text
    * @param string $additionalDetails
+   *   The additional information of CC and BCC appended to the activity details.
    * @param int $campaignID
    * @param array $attachments
    * @param int $caseID
@@ -1002,12 +1006,12 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
    *   The created activity ID
    * @throws \CRM_Core_Exception
    */
-  public static function createEmailActivity($userID, $subject, $html, $text, $additionalDetails, $campaignID, $attachments, $caseID) {
+  public static function createEmailActivity($sourceContactID, $subject, $html, $text, $additionalDetails, $campaignID, $attachments, $caseID) {
     $activityTypeID = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Email');
 
     // CRM-6265: save both text and HTML parts in details (if present)
     if ($html and $text) {
-      $details = "-ALTERNATIVE ITEM 0-\n$html$additionalDetails\n-ALTERNATIVE ITEM 1-\n$text$additionalDetails\n-ALTERNATIVE END-\n";
+      $details = "-ALTERNATIVE ITEM 0-\n{$html}{$additionalDetails}\n-ALTERNATIVE ITEM 1-\n{$text}{$additionalDetails}\n-ALTERNATIVE END-\n";
     }
     else {
       $details = $html ? $html : $text;
@@ -1015,12 +1019,11 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
     }
 
     $activityParams = [
-      'source_contact_id' => $userID,
+      'source_contact_id' => $sourceContactID,
       'activity_type_id' => $activityTypeID,
       'activity_date_time' => date('YmdHis'),
       'subject' => $subject,
       'details' => $details,
-      // FIXME: check for name Completed and get ID from that lookup
       'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'status_id', 'Completed'),
       'campaign_id' => $campaignID,
     ];
@@ -1038,6 +1041,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
     }
 
     $activity = civicrm_api3('Activity', 'create', $activityParams);
+
     return $activity['id'];
   }
 
@@ -1077,10 +1081,10 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
    * @throws \CiviCRM_API3_Exception
    */
   public static function sendEmail(
-    &$contactDetails,
-    &$subject,
-    &$text,
-    &$html,
+    $contactDetails,
+    $subject,
+    $text,
+    $html,
     $emailAddress,
     $userID = NULL,
     $from = NULL,
@@ -2587,7 +2591,7 @@ INNER JOIN  civicrm_option_group grp ON (grp.id = option_group_id AND grp.name =
         $activity['DT_RowAttr']['data-entity'] = 'activity';
         $activity['DT_RowAttr']['data-id'] = $activityId;
 
-        $activity['activity_type'] = (!empty($activityIcons[$values['activity_type_id']]) ? '<span class="crm-i ' . $activityIcons[$values['activity_type_id']] . '"></span> ' : '') . $values['activity_type'];
+        $activity['activity_type'] = (!empty($activityIcons[$values['activity_type_id']]) ? '<span class="crm-i ' . $activityIcons[$values['activity_type_id']] . '" aria-hidden="true"></span> ' : '') . $values['activity_type'];
         $activity['subject'] = $values['subject'];
 
         if ($params['contact_id'] == $values['source_contact_id']) {
diff --git a/civicrm/CRM/Activity/Form/ActivityLinks.php b/civicrm/CRM/Activity/Form/ActivityLinks.php
index 024ed70da5..bc7ff22f08 100644
--- a/civicrm/CRM/Activity/Form/ActivityLinks.php
+++ b/civicrm/CRM/Activity/Form/ActivityLinks.php
@@ -30,7 +30,7 @@ class CRM_Activity_Form_ActivityLinks extends CRM_Core_Form {
   public static function commonBuildQuickForm($self) {
     $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', $self);
     if (!$contactId) {
-      $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, FALSE, NULL, $_REQUEST);
+      $contactId = CRM_Utils_Request::retrieve('cid', 'Positive');
     }
     $urlParams = "action=add&reset=1&cid={$contactId}&selectedChild=activity&atype=";
 
diff --git a/civicrm/CRM/Activity/Page/AJAX.php b/civicrm/CRM/Activity/Page/AJAX.php
index e652726a60..1b07ef68a3 100644
--- a/civicrm/CRM/Activity/Page/AJAX.php
+++ b/civicrm/CRM/Activity/Page/AJAX.php
@@ -209,7 +209,7 @@ class CRM_Activity_Page_AJAX {
       }
       // email column links/icon
       if ($row['email']) {
-        $row['email'] = '<a class="crm-hover-button crm-popup" href="' . CRM_Utils_System::url('civicrm/activity/email/add', 'reset=1&action=add&atype=3&cid=' . $row['cid']) . '&caseid=' . $caseID . '" title="' . ts('Send an Email') . '"><i class="crm-i fa-envelope"></i></a>';
+        $row['email'] = '<a class="crm-hover-button crm-popup" href="' . CRM_Utils_System::url('civicrm/activity/email/add', 'reset=1&action=add&atype=3&cid=' . $row['cid']) . '&caseid=' . $caseID . '" title="' . ts('Send an Email') . '"><i class="crm-i fa-envelope" aria-hidden="true"></i></a>';
       }
       // edit links
       $row['actions'] = '';
@@ -219,7 +219,7 @@ class CRM_Activity_Page_AJAX {
         switch ($row['source']) {
           case 'caseRel':
             $row['actions'] = '<a href="#editCaseRoleDialog" title="' . ts('Reassign %1', [1 => $typeLabel]) . '" class="crm-hover-button case-miniform" data-contact_type="' . $contactType . '" data-rel_type="' . $row['relation_type'] . '_' . $row['relationship_direction'] . '" data-cid="' . $row['cid'] . '" data-rel_id="' . $row['rel_id'] . '"data-key="' . CRM_Core_Key::get('civicrm/ajax/relation') . '">' .
-              '<i class="crm-i fa-pencil"></i>' .
+              '<i class="crm-i fa-pencil" aria-hidden="true"></i>' .
               '</a>' .
               '<a href="#deleteCaseRoleDialog" title="' . ts('Remove %1', [1 => $typeLabel]) . '" class="crm-hover-button case-miniform" data-contact_type="' . $contactType . '" data-rel_type="' . $row['relation_type'] . '_' . $row['relationship_direction'] . '" data-cid="' . $row['cid'] . '" data-key="' . CRM_Core_Key::get('civicrm/ajax/delcaserole') . '">' .
               '<span class="icon delete-icon"></span>' .
@@ -228,7 +228,7 @@ class CRM_Activity_Page_AJAX {
 
           case 'caseRoles':
             $row['actions'] = '<a href="#editCaseRoleDialog" title="' . ts('Assign %1', [1 => $typeLabel]) . '" class="crm-hover-button case-miniform" data-contact_type="' . $contactType . '" data-rel_type="' . $row['relation_type'] . '_a_b" data-key="' . CRM_Core_Key::get('civicrm/ajax/relation') . '">' .
-              '<i class="crm-i fa-pencil"></i>' .
+              '<i class="crm-i fa-pencil" aria-hidden="true"></i>' .
               '</a>';
             break;
         }
@@ -353,7 +353,7 @@ class CRM_Activity_Page_AJAX {
     if (!empty($params['assigneeContactIds'])) {
       $assigneeContacts = array_unique(explode(',', $params['assigneeContactIds']));
     }
-    foreach ($assigneeContacts as $key => $value) {
+    foreach ($assigneeContacts as $value) {
       $assigneeParams = [
         'activity_id' => $mainActivityId,
         'contact_id' => $value,
diff --git a/civicrm/CRM/Admin/Form/MessageTemplates.php b/civicrm/CRM/Admin/Form/MessageTemplates.php
index 11b564a309..5f809f25be 100644
--- a/civicrm/CRM/Admin/Form/MessageTemplates.php
+++ b/civicrm/CRM/Admin/Form/MessageTemplates.php
@@ -167,6 +167,7 @@ class CRM_Admin_Form_MessageTemplates extends CRM_Core_Form {
 
     //get the tokens.
     $tokens = CRM_Core_SelectValues::contactTokens();
+    $tokens = array_merge($tokens, CRM_Core_SelectValues::domainTokens());
 
     $this->assign('tokens', CRM_Utils_Token::formatTokensForDisplay($tokens));
 
diff --git a/civicrm/CRM/Admin/Form/Preferences/Mailing.php b/civicrm/CRM/Admin/Form/Preferences/Mailing.php
index d786297fe9..b2f4a975dc 100644
--- a/civicrm/CRM/Admin/Form/Preferences/Mailing.php
+++ b/civicrm/CRM/Admin/Form/Preferences/Mailing.php
@@ -33,6 +33,8 @@ class CRM_Admin_Form_Preferences_Mailing extends CRM_Admin_Form_Preferences {
     'dedupe_email_default' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
     'hash_mailing_url' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
     'auto_recipient_rebuild' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+    'url_tracking_default' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
+    'open_tracking_default' => CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
   ];
 
   public function postProcess() {
diff --git a/civicrm/CRM/Admin/Form/Setting/Localization.php b/civicrm/CRM/Admin/Form/Setting/Localization.php
index f7a8b6ea7c..55bb965cf4 100644
--- a/civicrm/CRM/Admin/Form/Setting/Localization.php
+++ b/civicrm/CRM/Admin/Form/Setting/Localization.php
@@ -161,30 +161,13 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
 
     //cache contact fields retaining localized titles
     //though we changed localization, so reseting cache.
-    Civi::cache('fields')->flush();
+    Civi::cache('fields')->clear();
 
     //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache.
-    Civi::cache('navigation')->flush();
+    Civi::cache('navigation')->clear();
     // reset ACL and System caches
     CRM_Core_BAO_Cache::resetCaches();
 
-    // we do this only to initialize monetary decimal point and thousand separator
-    $config = CRM_Core_Config::singleton();
-
-    // save enabled currencies and default currency in option group 'currencies_enabled'
-    // CRM-1496
-    if (empty($values['currencyLimit'])) {
-      $values['currencyLimit'] = [$values['defaultCurrency']];
-    }
-    elseif (!in_array($values['defaultCurrency'], $values['currencyLimit'])) {
-      $values['currencyLimit'][] = $values['defaultCurrency'];
-    }
-
-    self::updateEnabledCurrencies($values['currencyLimit'], $values['defaultCurrency']);
-
-    // unset currencyLimit so we dont store there
-    unset($values['currencyLimit']);
-
     // make the site multi-lang if requested
     if (!empty($values['makeMultilingual'])) {
       CRM_Core_I18n_Schema::makeMultilingual($values['lcMessages']);
@@ -214,6 +197,21 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     // if we manipulated the language list, return to the localization admin screen
     $return = (bool) (CRM_Utils_Array::value('makeMultilingual', $values) or CRM_Utils_Array::value('addLanguage', $values));
 
+    // Update enabled currencies
+    // we do this only to initialize monetary decimal point and thousand separator
+    $config = CRM_Core_Config::singleton();
+    // save enabled currencies and default currency in option group 'currencies_enabled'
+    // CRM-1496
+    if (empty($values['currencyLimit'])) {
+      $values['currencyLimit'] = [$values['defaultCurrency']];
+    }
+    elseif (!in_array($values['defaultCurrency'], $values['currencyLimit'])) {
+      $values['currencyLimit'][] = $values['defaultCurrency'];
+    }
+    self::updateEnabledCurrencies($values['currencyLimit'], $values['defaultCurrency']);
+    // unset currencyLimit so we dont store there
+    unset($values['currencyLimit']);
+
     $filteredValues = $values;
     unset($filteredValues['makeMultilingual']);
     unset($filteredValues['makeSinglelingual']);
diff --git a/civicrm/CRM/Admin/Form/Setting/Url.php b/civicrm/CRM/Admin/Form/Setting/Url.php
index 09b1dd1fc4..fa854247ea 100644
--- a/civicrm/CRM/Admin/Form/Setting/Url.php
+++ b/civicrm/CRM/Admin/Form/Setting/Url.php
@@ -21,6 +21,7 @@
 class CRM_Admin_Form_Setting_Url extends CRM_Admin_Form_Setting {
   protected $_settings = [
     'disable_core_css' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
+    'defaultExternUrl' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'userFrameworkResourceURL' => CRM_Core_BAO_Setting::URL_PREFERENCES_NAME,
     'imageUploadURL' => CRM_Core_BAO_Setting::URL_PREFERENCES_NAME,
     'customCSSURL' => CRM_Core_BAO_Setting::URL_PREFERENCES_NAME,
diff --git a/civicrm/CRM/Admin/Page/APIExplorer.php b/civicrm/CRM/Admin/Page/APIExplorer.php
index 13363ee231..c769535be3 100644
--- a/civicrm/CRM/Admin/Page/APIExplorer.php
+++ b/civicrm/CRM/Admin/Page/APIExplorer.php
@@ -177,7 +177,7 @@ class CRM_Admin_Page_APIExplorer extends CRM_Core_Page {
     // Fetch block for a specific action
     else {
       $action = strtolower($action);
-      $fnName = 'civicrm_api3_' . _civicrm_api_get_entity_name_from_camel($entity) . '_' . $action;
+      $fnName = 'civicrm_api3_' . CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($entity) . '_' . $action;
       // Support the alternate "1 file per action" structure
       $actionFile = "api/v3/$entity/" . ucfirst($action) . '.php';
       $actionFileContents = file_get_contents("api/v3/$entity/" . ucfirst($action) . '.php', FILE_USE_INCLUDE_PATH);
@@ -205,7 +205,8 @@ class CRM_Admin_Page_APIExplorer extends CRM_Core_Page {
 
   /**
    * Format a docblock to be a bit more readable
-   * Not a proper doc parser... patches welcome :)
+   *
+   * FIXME: APIv4 uses markdown in code docs. Switch to that.
    *
    * @param string $text
    * @return string
@@ -224,8 +225,8 @@ class CRM_Admin_Page_APIExplorer extends CRM_Core_Page {
 
     // Extract code blocks - save for later to skip html conversion
     $code = [];
-    preg_match_all('#@code(.*?)@endcode#is', $text, $code);
-    $text = preg_replace('#@code.*?@endcode#is', '<pre></pre>', $text);
+    preg_match_all('#(@code|```)(.*?)(@endcode|```)#is', $text, $code);
+    $text = preg_replace('#(@code|```)(.*?)(@endcode|```)#is', '<pre></pre>', $text);
 
     // Convert @annotations to titles
     $text = preg_replace_callback(
@@ -242,8 +243,8 @@ class CRM_Admin_Page_APIExplorer extends CRM_Core_Page {
     $text = nl2br($text);
 
     // Add unformatted code blocks back in
-    if ($code && !empty($code[1])) {
-      foreach ($code[1] as $block) {
+    if ($code && !empty($code[2])) {
+      foreach ($code[2] as $block) {
         $text = preg_replace('#<pre></pre>#', "<pre>$block</pre>", $text, 1);
       }
     }
diff --git a/civicrm/CRM/Admin/Page/Admin.php b/civicrm/CRM/Admin/Page/Admin.php
index fc4d291c32..8fb257635c 100644
--- a/civicrm/CRM/Admin/Page/Admin.php
+++ b/civicrm/CRM/Admin/Page/Admin.php
@@ -39,60 +39,28 @@ class CRM_Admin_Page_Admin extends CRM_Core_Page {
     ];
 
     $config = CRM_Core_Config::singleton();
-    if (in_array('CiviContribute', $config->enableComponents)) {
-      $groups['CiviContribute'] = ts('CiviContribute');
-    }
-
-    if (in_array('CiviMember', $config->enableComponents)) {
-      $groups['CiviMember'] = ts('CiviMember');
-    }
-
-    if (in_array('CiviEvent', $config->enableComponents)) {
-      $groups['CiviEvent'] = ts('CiviEvent');
-    }
-
-    if (in_array('CiviMail', $config->enableComponents)) {
-      $groups['CiviMail'] = ts('CiviMail');
-    }
-
-    if (in_array('CiviCase', $config->enableComponents)) {
-      $groups['CiviCase'] = ts('CiviCase');
-    }
-
-    if (in_array('CiviReport', $config->enableComponents)) {
-      $groups['CiviReport'] = ts('CiviReport');
-    }
 
-    if (in_array('CiviCampaign', $config->enableComponents)) {
-      $groups['CiviCampaign'] = ts('CiviCampaign');
+    foreach ($config->enableComponents as $component) {
+      $comp = CRM_Core_Component::get($component);
+      $groups[$comp->info['name']] = $comp->info['translatedName'];
     }
 
     $values = CRM_Core_Menu::getAdminLinks();
 
-    $this->_showHide = new CRM_Core_ShowHideBlocks();
     foreach ($groups as $group => $title) {
       $groupId = str_replace(' ', '_', $group);
-
-      $this->_showHide->addShow("id_{$groupId}_show");
-      $this->_showHide->addHide("id_{$groupId}");
-      $v = CRM_Core_ShowHideBlocks::links($this, $groupId, '', '', FALSE);
-      if (isset($values[$group])) {
-        $adminPanel[$groupId] = $values[$group];
-        $adminPanel[$groupId]['show'] = $v['show'];
-        $adminPanel[$groupId]['hide'] = $v['hide'];
-        $adminPanel[$groupId]['title'] = $title;
-      }
-      else {
-        $adminPanel[$groupId] = [];
-        $adminPanel[$groupId]['show'] = '';
-        $adminPanel[$groupId]['hide'] = '';
-        $adminPanel[$groupId]['title'] = $title;
-      }
+      $adminPanel[$groupId] = array_merge($values[$group] ?? [], ['title' => $title]);
     }
 
     CRM_Utils_Hook::alterAdminPanel($adminPanel);
+    foreach ($adminPanel as $groupId => $group) {
+      if (count($group) == 1) {
+        // Presumably the only thing is the title; remove the section.
+        // This is done here to give the hook a chance to edit the section.
+        unset($adminPanel[$groupId]);
+      }
+    }
     $this->assign('adminPanel', $adminPanel);
-    $this->_showHide->addToTemplate();
     return parent::run();
   }
 
diff --git a/civicrm/CRM/Admin/Page/ConfigTaskList.php b/civicrm/CRM/Admin/Page/ConfigTaskList.php
index f4a6556603..ab7e91de61 100644
--- a/civicrm/CRM/Admin/Page/ConfigTaskList.php
+++ b/civicrm/CRM/Admin/Page/ConfigTaskList.php
@@ -46,7 +46,7 @@ class CRM_Admin_Page_ConfigTaskList extends CRM_Core_Page {
       'sequential' => 1,
       'return' => ["enable_components"],
     ]);
-    $enabled = array();
+    $enabled = [];
     foreach ($result['values'][0]['enable_components'] as $component) {
       $enabled[$component] = 1;
     }
diff --git a/civicrm/CRM/Admin/Page/Job.php b/civicrm/CRM/Admin/Page/Job.php
index f2eed5d69c..e8ba06d9d5 100644
--- a/civicrm/CRM/Admin/Page/Job.php
+++ b/civicrm/CRM/Admin/Page/Job.php
@@ -144,7 +144,7 @@ class CRM_Admin_Page_Job extends CRM_Core_Page_Basic {
     }
 
     $sj = new CRM_Core_JobManager();
-    $rows = $temp = array();
+    $rows = $temp = [];
     foreach ($sj->jobs as $job) {
       $action = array_sum(array_keys($this->links()));
 
diff --git a/civicrm/CRM/Admin/Page/JobLog.php b/civicrm/CRM/Admin/Page/JobLog.php
index 6f23cf0857..c7b1226535 100644
--- a/civicrm/CRM/Admin/Page/JobLog.php
+++ b/civicrm/CRM/Admin/Page/JobLog.php
@@ -95,7 +95,7 @@ class CRM_Admin_Page_JobLog extends CRM_Core_Page_Basic {
     }
     $dao->find();
 
-    $rows = array();
+    $rows = [];
     while ($dao->fetch()) {
       unset($row);
       CRM_Core_DAO::storeValues($dao, $row);
diff --git a/civicrm/CRM/Admin/Page/PaymentProcessor.php b/civicrm/CRM/Admin/Page/PaymentProcessor.php
index 814b0064c7..1fb115f8e8 100644
--- a/civicrm/CRM/Admin/Page/PaymentProcessor.php
+++ b/civicrm/CRM/Admin/Page/PaymentProcessor.php
@@ -108,7 +108,7 @@ class CRM_Admin_Page_PaymentProcessor extends CRM_Core_Page_Basic {
    */
   public function browse($action = NULL) {
     // get all custom groups sorted by weight
-    $paymentProcessor = array();
+    $paymentProcessor = [];
     $dao = new CRM_Financial_DAO_PaymentProcessor();
     $dao->is_test = 0;
     $dao->domain_id = CRM_Core_Config::domainID();
@@ -116,7 +116,7 @@ class CRM_Admin_Page_PaymentProcessor extends CRM_Core_Page_Basic {
     $dao->find();
 
     while ($dao->fetch()) {
-      $paymentProcessor[$dao->id] = array();
+      $paymentProcessor[$dao->id] = [];
       CRM_Core_DAO::storeValues($dao, $paymentProcessor[$dao->id]);
       $paymentProcessor[$dao->id]['payment_processor_type'] = CRM_Core_PseudoConstant::getLabel(
         'CRM_Financial_DAO_PaymentProcessor', 'payment_processor_type_id', $dao->payment_processor_type_id
diff --git a/civicrm/CRM/Batch/BAO/Batch.php b/civicrm/CRM/Batch/BAO/Batch.php
index c777fa4acb..f44c0e4999 100644
--- a/civicrm/CRM/Batch/BAO/Batch.php
+++ b/civicrm/CRM/Batch/BAO/Batch.php
@@ -42,20 +42,10 @@ class CRM_Batch_BAO_Batch extends CRM_Batch_DAO_Batch {
    *   $batch batch object
    */
   public static function create(&$params) {
-    $op = 'edit';
-    $batchId = $params['id'] ?? NULL;
-    if (!$batchId) {
-      $op = 'create';
+    if (empty($params['id']) && empty($params['name'])) {
       $params['name'] = CRM_Utils_String::titleToVar($params['title']);
     }
-    CRM_Utils_Hook::pre($op, 'Batch', $batchId, $params);
-    $batch = new CRM_Batch_DAO_Batch();
-    $batch->copyValues($params);
-    $batch->save();
-
-    CRM_Utils_Hook::post($op, 'Batch', $batch->id, $batch);
-
-    return $batch;
+    return self::writeRecord($params);
   }
 
   /**
diff --git a/civicrm/CRM/Campaign/BAO/Campaign.php b/civicrm/CRM/Campaign/BAO/Campaign.php
index 4ceeec2ea8..7800cf925d 100644
--- a/civicrm/CRM/Campaign/BAO/Campaign.php
+++ b/civicrm/CRM/Campaign/BAO/Campaign.php
@@ -34,10 +34,8 @@ class CRM_Campaign_BAO_Campaign extends CRM_Campaign_DAO_Campaign {
     }
 
     if (empty($params['id'])) {
-
       if (empty($params['created_id'])) {
-        $session = CRM_Core_Session::singleton();
-        $params['created_id'] = $session->get('userID');
+        $params['created_id'] = CRM_Core_Session::getLoggedInContactID();
       }
 
       if (empty($params['created_date'])) {
@@ -47,26 +45,11 @@ class CRM_Campaign_BAO_Campaign extends CRM_Campaign_DAO_Campaign {
       if (empty($params['name'])) {
         $params['name'] = CRM_Utils_String::titleToVar($params['title'], 64);
       }
-
-      CRM_Utils_Hook::pre('create', 'Campaign', NULL, $params);
-    }
-    else {
-      CRM_Utils_Hook::pre('edit', 'Campaign', $params['id'], $params);
     }
 
-    $campaign = new CRM_Campaign_DAO_Campaign();
-    $campaign->copyValues($params);
-    $campaign->save();
-
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::post('edit', 'Campaign', $campaign->id, $campaign);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'Campaign', $campaign->id, $campaign);
-    }
+    $campaign = self::writeRecord($params);
 
     /* Create the campaign group record */
-
     $groupTableName = CRM_Contact_BAO_Group::getTableName();
 
     if (isset($params['groups']) && !empty($params['groups']['include']) && is_array($params['groups']['include'])) {
@@ -81,9 +64,7 @@ class CRM_Campaign_BAO_Campaign extends CRM_Campaign_DAO_Campaign {
     }
 
     //store custom data
-    if (!empty($params['custom']) &&
-      is_array($params['custom'])
-    ) {
+    if (!empty($params['custom']) && is_array($params['custom'])) {
       CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_campaign', $campaign->id);
     }
 
diff --git a/civicrm/CRM/Campaign/BAO/Survey.php b/civicrm/CRM/Campaign/BAO/Survey.php
index 9277e4f040..93b487982b 100644
--- a/civicrm/CRM/Campaign/BAO/Survey.php
+++ b/civicrm/CRM/Campaign/BAO/Survey.php
@@ -62,36 +62,19 @@ class CRM_Campaign_BAO_Survey extends CRM_Campaign_DAO_Survey {
       CRM_Core_DAO::executeQuery($query);
     }
 
-    if (!(CRM_Utils_Array::value('id', $params))) {
-
-      if (!(CRM_Utils_Array::value('created_id', $params))) {
-        $session = CRM_Core_Session::singleton();
-        $params['created_id'] = $session->get('userID');
+    if (empty($params['id'])) {
+      if (empty($params['created_id'])) {
+        $params['created_id'] = CRM_Core_Session::getLoggedInContactID();
       }
-      if (!(CRM_Utils_Array::value('created_date', $params))) {
+
+      if (empty($params['created_date'])) {
         $params['created_date'] = date('YmdHis');
       }
-
-      CRM_Utils_Hook::pre('create', 'Survey', NULL, $params);
     }
-    else {
-      CRM_Utils_Hook::pre('edit', 'Survey', $params['id'], $params);
-    }
-
-    $dao = new CRM_Campaign_DAO_Survey();
-    $dao->copyValues($params);
-    $dao->save();
 
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::post('edit', 'Survey', $dao->id, $dao);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'Survey', $dao->id, $dao);
-    }
+    $dao = self::writeRecord($params);
 
-    if (!empty($params['custom']) &&
-      is_array($params['custom'])
-    ) {
+    if (!empty($params['custom']) && is_array($params['custom'])) {
       CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_survey', $dao->id);
     }
     return $dao;
diff --git a/civicrm/CRM/Campaign/Form/Search.php b/civicrm/CRM/Campaign/Form/Search.php
index 66d744995c..e110db8d6e 100644
--- a/civicrm/CRM/Campaign/Form/Search.php
+++ b/civicrm/CRM/Campaign/Form/Search.php
@@ -55,7 +55,7 @@ class CRM_Campaign_Form_Search extends CRM_Core_Form_Search {
    */
   public function preProcess() {
     $this->_done = FALSE;
-    $this->_defaults = array();
+    $this->_defaults = [];
 
     //set the button name.
     $this->_printButtonName = $this->getButtonName('next', 'print');
diff --git a/civicrm/CRM/Campaign/Page/DashBoard.php b/civicrm/CRM/Campaign/Page/DashBoard.php
index 1318dd1c57..dfd6f3126c 100644
--- a/civicrm/CRM/Campaign/Page/DashBoard.php
+++ b/civicrm/CRM/Campaign/Page/DashBoard.php
@@ -312,11 +312,8 @@ class CRM_Campaign_Page_DashBoard extends CRM_Core_Page {
         }
         $surveysData[$sid]['isActive'] = $isActive;
 
-        $isDefault = NULL;
-        if ($surveysData[$sid]['is_default']) {
-          $isDefault = '<img src="' . $config->resourceBase . 'i/check.gif" alt="' . ts('Default') . '" />';
-        }
-        $surveysData[$sid]['is_default'] = $isDefault;
+        // For some reason, 'is_default' is coming as a string.
+        $surveysData[$sid]['is_default'] = boolval($surveysData[$sid]['is_default']);
 
         if ($surveysData[$sid]['result_id']) {
           $resultSet = '<a href= "javascript:displayResultSet( ' . $sid . ',' . "'" . $surveysData[$sid]['title'] . "'" . ', ' . $surveysData[$sid]['result_id'] . ' )" title="' . ts('view result set') . '">' . ts('Result Set') . '</a>';
@@ -415,11 +412,9 @@ class CRM_Campaign_Page_DashBoard extends CRM_Core_Page {
           $isActive = ts('Yes');
         }
         $petitionsData[$pid]['isActive'] = $isActive;
-        $isDefault = NULL;
-        if ($petitionsData[$pid]['is_default']) {
-          $isDefault = '<img src="' . $config->resourceBase . 'i/check.gif" alt="' . ts('Default') . '" />';
-        }
-        $petitionsData[$pid]['is_default'] = $isDefault;
+
+        // For some reason, 'is_default' is coming as a string.
+        $petitionsData[$pid]['is_default'] = boolval($petitionsData[$pid]['is_default']);
 
         $petitionsData[$pid]['action'] = CRM_Core_Action::formLink(self::petitionActionLinks(),
           $action,
diff --git a/civicrm/CRM/Campaign/xml/Menu/Campaign.xml b/civicrm/CRM/Campaign/xml/Menu/Campaign.xml
index 555eb1f284..5d051df249 100644
--- a/civicrm/CRM/Campaign/xml/Menu/Campaign.xml
+++ b/civicrm/CRM/Campaign/xml/Menu/Campaign.xml
@@ -34,7 +34,6 @@
     <title>Survey Types</title>
     <page_callback>CRM_Campaign_Page_SurveyType</page_callback>
     <access_arguments>administer CiviCampaign</access_arguments>
-    <icon>admin/small/05.png</icon>
     <adminGroup>CiviCampaign</adminGroup>
     <component>CiviCampaign</component>
     <weight>1</weight>
@@ -45,7 +44,6 @@
      <desc>categorize your campaigns using campaign types.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>CiviCampaign</adminGroup>
-     <icon>admin/small/05.png</icon>
      <weight>2</weight>
      <component>CiviCampaign</component>
   </item>
@@ -55,7 +53,6 @@
      <desc>Define statuses for campaign here.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>CiviCampaign</adminGroup>
-     <icon>admin/small/05.png</icon>
      <weight>3</weight>
      <component>CiviCampaign</component>
   </item>
@@ -65,7 +62,6 @@
      <desc>Engagement levels.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>CiviCampaign</adminGroup>
-     <icon>admin/small/05.png</icon>
      <weight>4</weight>
      <component>CiviCampaign</component>
   </item>
diff --git a/civicrm/CRM/Case/BAO/Case.php b/civicrm/CRM/Case/BAO/Case.php
index 2f6ec7c95d..5a3f0b8106 100644
--- a/civicrm/CRM/Case/BAO/Case.php
+++ b/civicrm/CRM/Case/BAO/Case.php
@@ -631,7 +631,7 @@ HERESQL;
           }
         }
         if (isset($case['activity_type_id']) && self::checkPermission($actId, 'edit', $case['activity_type_id'], $userID)) {
-          $casesList[$key]['date'] .= sprintf('<a class="action-item crm-hover-button" href="%s" title="%s"><i class="crm-i fa-pencil"></i></a>',
+          $casesList[$key]['date'] .= sprintf('<a class="action-item crm-hover-button" href="%s" title="%s"><i class="crm-i fa-pencil" aria-hidden="true"></i></a>',
             CRM_Utils_System::url('civicrm/case/activity', ['reset' => 1, 'cid' => $case['contact_id'], 'caseid' => $case['case_id'], 'action' => 'update', 'id' => $actId]),
             ts('Edit activity')
           );
diff --git a/civicrm/CRM/Case/BAO/CaseContact.php b/civicrm/CRM/Case/BAO/CaseContact.php
index 6e5ed5779b..3b409bb65c 100644
--- a/civicrm/CRM/Case/BAO/CaseContact.php
+++ b/civicrm/CRM/Case/BAO/CaseContact.php
@@ -29,14 +29,7 @@ class CRM_Case_BAO_CaseContact extends CRM_Case_DAO_CaseContact {
    * @return CRM_Case_BAO_CaseContact
    */
   public static function create($params) {
-    $hook = empty($params['id']) ? 'create' : 'edit';
-    CRM_Utils_Hook::pre($hook, 'CaseContact', CRM_Utils_Array::value('id', $params), $params);
-
-    $caseContact = new self();
-    $caseContact->copyValues($params);
-    $caseContact->save();
-
-    CRM_Utils_Hook::post($hook, 'CaseContact', $caseContact->id, $caseContact);
+    $caseContact = self::writeRecord($params);
 
     // add to recently viewed
     $caseType = CRM_Case_BAO_Case::getCaseType($caseContact->case_id);
diff --git a/civicrm/CRM/Case/Form/Activity.php b/civicrm/CRM/Case/Form/Activity.php
index d84717985c..01714e436b 100644
--- a/civicrm/CRM/Case/Form/Activity.php
+++ b/civicrm/CRM/Case/Form/Activity.php
@@ -639,6 +639,28 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity {
           ];
           CRM_Case_BAO_Case::processCaseActivity($caseParams);
           $followupStatus = ts("A followup activity has been scheduled.") . '<br /><br />';
+
+          //dev/core#1721
+          if (Civi::settings()->get('activity_assignee_notification') &&
+            !in_array($followupActivity->activity_type_id,
+              Civi::settings()->get('do_not_notify_assignees_for'))
+          ) {
+            $followupActivityIDs = [$followupActivity->id];
+            $followupAssigneeContacts = CRM_Activity_BAO_ActivityAssignment::getAssigneeNames($followupActivityIDs, TRUE, FALSE);
+
+            if (!empty($followupAssigneeContacts)) {
+              $mailToFollowupContacts = [];
+              foreach ($followupAssigneeContacts as $facValues) {
+                $mailToFollowupContacts[$facValues['email']] = $facValues;
+              }
+
+              $facParams['case_id'] = $vval['case_id'];
+              $sentFollowup = CRM_Activity_BAO_Activity::sendToAssignee($followupActivity, $mailToFollowupContacts, $facParams);
+              if ($sentFollowup) {
+                $mailStatus .= '<br />' . ts("A copy of the follow-up activity has also been sent to follow-up assignee contacts(s).");
+              }
+            }
+          }
         }
       }
       $title = ts("%1 Saved", [1 => $this->_activityTypeName]);
diff --git a/civicrm/CRM/Case/Form/AddToCaseAsRole.php b/civicrm/CRM/Case/Form/AddToCaseAsRole.php
index f2809047e3..91d55122a9 100644
--- a/civicrm/CRM/Case/Form/AddToCaseAsRole.php
+++ b/civicrm/CRM/Case/Form/AddToCaseAsRole.php
@@ -51,7 +51,10 @@ class CRM_Case_Form_AddToCaseAsRole extends CRM_Contact_Form_Task {
     $roleTypes = [];
 
     foreach ($relType as $k => $v) {
-      $roleTypes[substr($k, 0, strpos($k, '_'))] = $v;
+      //Limit this to relationship types from contact A to B
+      if (substr($k, -4) == "_a_b") {
+        $roleTypes[substr($k, 0, strpos($k, '_'))] = $v;
+      }
     }
 
     return $roleTypes;
diff --git a/civicrm/CRM/Case/Info.php b/civicrm/CRM/Case/Info.php
index 0f996ee0c8..bf9d4adca5 100644
--- a/civicrm/CRM/Case/Info.php
+++ b/civicrm/CRM/Case/Info.php
@@ -228,6 +228,8 @@ class CRM_Case_Info extends CRM_Core_Component_Info {
    *   List of component names.
    * @param array $metadata
    *   Specification of the setting (per *.settings.php).
+   *
+   * @throws \CRM_Core_Exception.
    */
   public static function onToggleComponents($oldValue, $newValue, $metadata) {
     if (
@@ -238,8 +240,7 @@ class CRM_Case_Info extends CRM_Core_Component_Info {
       $pathToCaseSampleTpl = __DIR__ . '/xml/configuration.sample/';
       self::loadCaseSampleData($pathToCaseSampleTpl . 'case_sample.mysql.tpl');
       if (!CRM_Case_BAO_Case::createCaseViews()) {
-        $msg = ts("Could not create the MySQL views for CiviCase. Your mysql user needs to have the 'CREATE VIEW' permission");
-        CRM_Core_Error::fatal($msg);
+        throw new CRM_Core_Exception(ts("Could not create the MySQL views for CiviCase. Your mysql user needs to have the 'CREATE VIEW' permission"));
       }
     }
   }
diff --git a/civicrm/CRM/Case/Page/Tab.php b/civicrm/CRM/Case/Page/Tab.php
index e89132c3de..12f6cd0671 100644
--- a/civicrm/CRM/Case/Page/Tab.php
+++ b/civicrm/CRM/Case/Page/Tab.php
@@ -63,7 +63,7 @@ class CRM_Case_Page_Tab extends CRM_Core_Page {
     }
     else {
       if ($this->_action & CRM_Core_Action::VIEW) {
-        CRM_Core_Error::fatal('Contact Id is required for view action.');
+        CRM_Core_Error::statusBounce('Contact Id is required for view action.');
       }
     }
 
diff --git a/civicrm/CRM/Case/XMLProcessor/Process.php b/civicrm/CRM/Case/XMLProcessor/Process.php
index 4eb4e8826e..9307f2bb90 100644
--- a/civicrm/CRM/Case/XMLProcessor/Process.php
+++ b/civicrm/CRM/Case/XMLProcessor/Process.php
@@ -23,18 +23,16 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor {
    * @param string $caseType
    * @param array $params
    *
-   * @return bool
-   * @throws Exception
+   * @throws CRM_Core_Exception
    */
   public function run($caseType, &$params) {
     $xml = $this->retrieve($caseType);
 
     if ($xml === FALSE) {
       $docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
-      CRM_Core_Error::fatal(ts("Configuration file could not be retrieved for case type = '%1' %2.",
+      throw new CRM_Core_Exception(ts("Configuration file could not be retrieved for case type = '%1' %2.",
         [1 => $caseType, 2 => $docLink]
       ));
-      return FALSE;
     }
 
     $xmlProcessorProcess = new CRM_Case_XMLProcessor_Process();
@@ -56,10 +54,9 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor {
     $xml = $this->retrieve($caseType);
     if ($xml === FALSE) {
       $docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
-      CRM_Core_Error::fatal(ts("Unable to load configuration file for the referenced case type: '%1' %2.",
+      throw new CRM_Core_Exception(ts("Unable to load configuration file for the referenced case type: '%1' %2.",
         [1 => $caseType, 2 => $docLink]
       ));
-      return FALSE;
     }
 
     switch ($fieldSet) {
@@ -93,8 +90,7 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor {
               $params
             )
             ) {
-              CRM_Core_Error::fatal();
-              return FALSE;
+              throw new CRM_Core_Exception('Unable to create case relationships');
             }
           }
         }
@@ -190,7 +186,7 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor {
    * @param array $params
    *
    * @return bool
-   * @throws Exception
+   * @throws CRM_Core_Exception
    */
   public function createRelationships($relationshipTypeXML, &$params) {
 
@@ -198,10 +194,9 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor {
     list($relationshipType, $relationshipTypeName) = $this->locateNameOrLabel($relationshipTypeXML);
     if ($relationshipType === FALSE) {
       $docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
-      CRM_Core_Error::fatal(ts('Relationship type %1, found in case configuration file, is not present in the database %2',
+      throw new CRM_Core_Exception(ts('Relationship type %1, found in case configuration file, is not present in the database %2',
         [1 => $relationshipTypeName, 2 => $docLink]
       ));
-      return FALSE;
     }
 
     $client = $params['clientID'];
@@ -228,8 +223,7 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor {
       }
 
       if (!$this->createRelationship($relationshipParams)) {
-        CRM_Core_Error::fatal();
-        return FALSE;
+        throw new CRM_Core_Exception('Unable to create case relationship');
       }
     }
     return TRUE;
@@ -415,10 +409,9 @@ AND        a.is_deleted = 0
 
     if (!$activityTypeInfo) {
       $docLink = CRM_Utils_System::docURL2("user/case-management/set-up");
-      CRM_Core_Error::fatal(ts('Activity type %1, found in case configuration file, is not present in the database %2',
+      throw new CRM_Core_Exception(ts('Activity type %1, found in case configuration file, is not present in the database %2',
         [1 => $activityTypeName, 2 => $docLink]
       ));
-      return FALSE;
     }
 
     $activityTypeID = $activityTypeInfo['id'];
@@ -549,8 +542,7 @@ AND        a.is_deleted = 0
     $activity = CRM_Activity_BAO_Activity::create($activityParams);
 
     if (!$activity) {
-      CRM_Core_Error::fatal();
-      return FALSE;
+      throw new CRM_Core_Exception('Unable to create Activity');
     }
 
     // create case activity record
@@ -731,17 +723,16 @@ AND        a.is_deleted = 0
 
   /**
    * @param $caseType
-   * @param null $activityTypeName
+   * @param string|null $activityTypeName
    *
    * @return array|bool|mixed
-   * @throws Exception
+   * @throws CRM_Core_Exception
    */
   public function getMaxInstance($caseType, $activityTypeName = NULL) {
     $xml = $this->retrieve($caseType);
 
     if ($xml === FALSE) {
-      CRM_Core_Error::fatal();
-      return FALSE;
+      throw new CRM_Core_Exception('Unable to locate xml definition for case type ' . $caseType);
     }
 
     $activityInstances = $this->activityTypes($xml->ActivityTypes, TRUE);
diff --git a/civicrm/CRM/Case/XMLProcessor/Report.php b/civicrm/CRM/Case/XMLProcessor/Report.php
index c4fcba5670..1fdff00915 100644
--- a/civicrm/CRM/Case/XMLProcessor/Report.php
+++ b/civicrm/CRM/Case/XMLProcessor/Report.php
@@ -63,10 +63,10 @@ class CRM_Case_XMLProcessor_Report extends CRM_Case_XMLProcessor {
     $clientID,
     $caseID
   ) {
-    $case = $this->_redactionRegexRules = array();
+    $case = $this->_redactionRegexRules = [];
 
     if (empty($this->_redactionStringRules)) {
-      $this->_redactionStringRules = array();
+      $this->_redactionStringRules = [];
     }
 
     if ($this->_isRedact == 1) {
@@ -111,7 +111,7 @@ class CRM_Case_XMLProcessor_Report extends CRM_Case_XMLProcessor {
     foreach ($xml->ActivitySets as $activitySetsXML) {
       foreach ($activitySetsXML->ActivitySet as $activitySetXML) {
         if ((string ) $activitySetXML->name == $activitySetName) {
-          $activityTypes = array();
+          $activityTypes = [];
           $allActivityTypes = CRM_Case_PseudoConstant::caseActivityType(TRUE, TRUE);
           foreach ($activitySetXML->ActivityTypes as $activityTypesXML) {
             foreach ($activityTypesXML as $activityTypeXML) {
@@ -192,7 +192,7 @@ AND    ac.case_id = %1
    * @return mixed
    */
   public function &getActivityInfo($clientID, $activityID, $anyActivity = FALSE, $redact = 0) {
-    static $activityInfos = array();
+    static $activityInfos = [];
     if ($redact) {
       $this->_isRedact = 1;
       $this->getRedactionRules();
@@ -205,7 +205,7 @@ AND    ac.case_id = %1
     }
 
     if (!array_key_exists($index, $activityInfos)) {
-      $activityInfos[$index] = array();
+      $activityInfos[$index] = [];
       $selectCaseActivity = "";
       $joinCaseActivity = "";
 
@@ -259,11 +259,11 @@ WHERE      a.id = %1
    */
   public function &getActivity($clientID, $activityDAO, &$activityTypeInfo) {
     if (empty($this->_redactionStringRules)) {
-      $this->_redactionStringRules = array();
+      $this->_redactionStringRules = [];
     }
 
-    $activity = array();
-    $activity['fields'] = array();
+    $activity = [];
+    $activity['fields'] = [];
     if ($clientID) {
       $clientID = CRM_Utils_Type::escape($clientID, 'Integer');
       if (!in_array($activityTypeInfo['name'], array(
@@ -326,7 +326,7 @@ WHERE      a.id = %1
       }
 
       if ($processTarget) {
-        $targetRedacted = array();
+        $targetRedacted = [];
         foreach ($targetNames as $targetID => $target) {
           // add Recipient SortName as well as Display to the strings to be redacted across the case session
           // suffixed with a randomly generated 4-digit number
@@ -513,11 +513,11 @@ WHERE      a.id = %1
 
     $params = array(1 => array($activityDAO->id, 'Integer'));
 
-    $customGroups = array();
+    $customGroups = [];
     foreach ($sql as $tableName => $sqlClause) {
       $dao = CRM_Core_DAO::executeQuery($sqlClause, $params);
       if ($dao->fetch()) {
-        $customGroup = array();
+        $customGroup = [];
         foreach ($typeValues[$tableName] as $columnName => $typeValue) {
 
           if (CRM_Utils_Array::value('type', $typeValue) == 'Date') {
@@ -565,7 +565,7 @@ WHERE      a.id = %1
    * @return mixed
    */
   public function getActivityTypeCustomSQL($activityTypeID, $dateFormat = NULL, $onlyActive = TRUE) {
-    static $cache = array();
+    static $cache = [];
 
     if (is_null($activityTypeID)) {
       $activityTypeID = 0;
@@ -606,11 +606,11 @@ AND " . CRM_Core_Permission::customGroupClause(CRM_Core_Permission::VIEW, 'cg.')
       );
       $dao = CRM_Core_DAO::executeQuery($query, $params);
 
-      $result = $options = $sql = $groupTitle = array();
+      $result = $options = $sql = $groupTitle = [];
       while ($dao->fetch()) {
         if (!array_key_exists($dao->tableName, $result)) {
-          $result[$dao->tableName] = array();
-          $sql[$dao->tableName] = array();
+          $result[$dao->tableName] = [];
+          $sql[$dao->tableName] = [];
         }
         $result[$dao->tableName][$dao->columnName] = array(
           'label' => $dao->label,
@@ -618,7 +618,7 @@ AND " . CRM_Core_Permission::customGroupClause(CRM_Core_Permission::VIEW, 'cg.')
           'fieldID' => $dao->fieldID,
         );
 
-        $options[$dao->fieldID] = array();
+        $options[$dao->fieldID] = [];
         $options[$dao->fieldID]['attributes'] = array(
           'label' => $dao->label,
           'data_type' => $dao->dataType,
@@ -695,7 +695,7 @@ LIMIT  1
    *
    * @return mixed
    */
-  private function redact($string, $printReport = FALSE, $replaceString = array()) {
+  private function redact($string, $printReport = FALSE, $replaceString = []) {
     if ($printReport) {
       return CRM_Utils_String::redaction($string, $replaceString);
     }
@@ -787,7 +787,7 @@ LIMIT  1
     $template->assign_by_ref('activitySet', $activitySet);
 
     //now collect all the information about activities
-    $activities = array();
+    $activities = [];
     $form->getActivities($clientID, $caseID, $activityTypes, $activities);
     $template->assign_by_ref('activities', $activities);
 
@@ -800,7 +800,7 @@ LIMIT  1
     $activitySetName = CRM_Utils_Request::retrieve('asn', 'String');
     $isRedact = CRM_Utils_Request::retrieve('redact', 'Boolean');
     $includeActivities = CRM_Utils_Request::retrieve('all', 'Positive');
-    $params = $otherRelationships = $globalGroupInfo = array();
+    $params = $otherRelationships = $globalGroupInfo = [];
     $report = new CRM_Case_XMLProcessor_Report($isRedact);
     if ($includeActivities) {
       $params['include_activities'] = 1;
@@ -808,7 +808,7 @@ LIMIT  1
 
     if ($isRedact) {
       $params['is_redact'] = 1;
-      $report->_redactionStringRules = array();
+      $report->_redactionStringRules = [];
     }
     $template = CRM_Core_Smarty::singleton();
 
@@ -960,7 +960,7 @@ LIMIT  1
     $customValues = CRM_Core_BAO_CustomValueTable::getEntityValues($caseID, 'Case');
     $extends = array('case');
     $groupTree = CRM_Core_BAO_CustomGroup::getGroupDetail(NULL, NULL, $extends);
-    $caseCustomFields = array();
+    $caseCustomFields = [];
     foreach ($groupTree as $gid => $group_values) {
       foreach ($group_values['fields'] as $id => $field_values) {
         if (array_key_exists($id, $customValues)) {
diff --git a/civicrm/CRM/Case/xml/Menu/Case.xml b/civicrm/CRM/Case/xml/Menu/Case.xml
index 91d5ceb984..0d77eb9f8e 100644
--- a/civicrm/CRM/Case/xml/Menu/Case.xml
+++ b/civicrm/CRM/Case/xml/Menu/Case.xml
@@ -69,7 +69,6 @@
      <title>CiviCase Settings</title>
      <page_callback>CRM_Admin_Form_Setting_Case</page_callback>
      <adminGroup>CiviCase</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>380</weight>
   </item>
   <item>
@@ -80,7 +79,6 @@
      <page_callback>CRM_Core_Page_Redirect</page_callback>
      <page_arguments>url=civicrm/a/#/caseType</page_arguments>
      <adminGroup>CiviCase</adminGroup>
-     <icon>admin/small/case_type.png</icon>
      <weight>390</weight>
   </item>
   <item>
@@ -90,7 +88,6 @@
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <access_arguments>administer CiviCase</access_arguments>
      <adminGroup>CiviCase</adminGroup>
-     <icon>admin/small/redaction_type.png</icon>
      <weight>400</weight>
   </item>
   <item>
@@ -100,7 +97,6 @@
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <access_arguments>administer CiviCase</access_arguments>
      <adminGroup>CiviCase</adminGroup>
-     <icon>admin/small/case_type.png</icon>
      <weight>400</weight>
   </item>
   <item>
@@ -110,7 +106,6 @@
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <access_arguments>administer CiviCase</access_arguments>
      <adminGroup>CiviCase</adminGroup>
-     <icon>admin/small/case_type.png</icon>
      <weight>400</weight>
   </item>
   <item>
diff --git a/civicrm/CRM/Contact/BAO/Contact.php b/civicrm/CRM/Contact/BAO/Contact.php
index 5122ec5079..d795677303 100644
--- a/civicrm/CRM/Contact/BAO/Contact.php
+++ b/civicrm/CRM/Contact/BAO/Contact.php
@@ -101,7 +101,7 @@ class CRM_Contact_BAO_Contact extends CRM_Contact_DAO_Contact {
    * @return CRM_Contact_DAO_Contact|CRM_Core_Error|NULL
    *   Created or updated contact object or error object.
    *   (error objects are being phased out in favour of exceptions)
-   * @throws \Exception
+   * @throws \CRM_Core_Exception
    */
   public static function add(&$params) {
     $contact = new CRM_Contact_DAO_Contact();
@@ -1320,7 +1320,7 @@ WHERE     civicrm_contact.id = " . CRM_Utils_Type::escape($id, 'Integer');
       return $contactTypes;
     }
     else {
-      CRM_Core_Error::fatal();
+      throw new CRM_Core_Exception();
     }
   }
 
@@ -2017,7 +2017,7 @@ ORDER BY civicrm_email.is_primary DESC";
     }
 
     if (empty($contactID)) {
-      CRM_Core_Error::fatal('Cannot proceed without a valid contact id');
+      throw new CRM_Core_Exception('Cannot proceed without a valid contact id');
     }
 
     // Process group and tag
@@ -3718,8 +3718,14 @@ LEFT JOIN civicrm_address ON ( civicrm_address.contact_id = civicrm_contact.id )
       ['key' => 'contact_type', 'value' => ts('Contact Type')],
       ['key' => 'group', 'value' => ts('Group'), 'entity' => 'GroupContact'],
       ['key' => 'tag', 'value' => ts('Tag'), 'entity' => 'EntityTag'],
+      ['key' => 'city', 'value' => ts('City'), 'type' => 'text', 'entity' => 'Address'],
+      ['key' => 'postal_code', 'value' => ts('Postal Code'), 'type' => 'text', 'entity' => 'Address'],
       ['key' => 'state_province', 'value' => ts('State/Province'), 'entity' => 'Address'],
       ['key' => 'country', 'value' => ts('Country'), 'entity' => 'Address'],
+      ['key' => 'first_name', 'value' => ts('First Name'), 'type' => 'text', 'condition' => ['contact_type' => 'Individual']],
+      ['key' => 'last_name', 'value' => ts('Last Name'), 'type' => 'text', 'condition' => ['contact_type' => 'Individual']],
+      ['key' => 'nick_name', 'value' => ts('Nick Name'), 'type' => 'text', 'condition' => ['contact_type' => 'Individual']],
+      ['key' => 'organization_name', 'value' => ts('Employer name'), 'type' => 'text', 'condition' => ['contact_type' => 'Individual']],
       ['key' => 'gender_id', 'value' => ts('Gender'), 'condition' => ['contact_type' => 'Individual']],
       ['key' => 'is_deceased', 'value' => ts('Deceased'), 'condition' => ['contact_type' => 'Individual']],
       ['key' => 'contact_id', 'value' => ts('Contact ID'), 'type' => 'text'],
diff --git a/civicrm/CRM/Contact/BAO/ContactType.php b/civicrm/CRM/Contact/BAO/ContactType.php
index 947f8dc430..42fb2ba54d 100644
--- a/civicrm/CRM/Contact/BAO/ContactType.php
+++ b/civicrm/CRM/Contact/BAO/ContactType.php
@@ -9,6 +9,8 @@
  +--------------------------------------------------------------------+
  */
 
+use Civi\Api4\ContactType;
+
 /**
  *
  * @package CRM
@@ -53,48 +55,24 @@ class CRM_Contact_BAO_ContactType extends CRM_Contact_DAO_ContactType {
   /**
    * Retrieve basic contact type information.
    *
-   * @param bool $all
+   * @param bool $includeInactive
    *
    * @return array
    *   Array of basic contact types information.
+   *
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
    */
-  public static function basicTypeInfo($all = FALSE) {
-    static $_cache = NULL;
-
-    if ($_cache === NULL) {
-      $_cache = [];
-    }
-
-    $argString = $all ? 'CRM_CT_BTI_1' : 'CRM_CT_BTI_0';
-    if (!array_key_exists($argString, $_cache)) {
-      $cache = CRM_Utils_Cache::singleton();
-      $_cache[$argString] = $cache->get($argString);
-      if (!$_cache[$argString]) {
-        $sql = "
-SELECT *
-FROM   civicrm_contact_type
-WHERE  parent_id IS NULL
-";
-        if ($all === FALSE) {
-          $sql .= " AND is_active = 1";
-        }
-
-        $params = [];
-        $dao = CRM_Core_DAO::executeQuery($sql,
-          $params,
-          FALSE,
-          'CRM_Contact_DAO_ContactType'
-        );
-        while ($dao->fetch()) {
-          $value = [];
-          CRM_Core_DAO::storeValues($dao, $value);
-          $_cache[$argString][$dao->name] = $value;
-        }
-
-        $cache->set($argString, $_cache[$argString]);
+  public static function basicTypeInfo($includeInactive = FALSE) {
+    $cacheKey = 'CRM_CT_BTI_' . (int) $includeInactive;
+    if (!Civi::cache('contactTypes')->has($cacheKey)) {
+      $contactType = ContactType::get()->setCheckPermissions(FALSE)->setSelect(['*'])->addWhere('parent_id', 'IS NULL');
+      if ($includeInactive === FALSE) {
+        $contactType->addWhere('is_active', '=', 1);
       }
+      Civi::cache('contactTypes')->set($cacheKey, (array) $contactType->execute()->indexBy('name'));
     }
-    return $_cache[$argString];
+    return Civi::cache('contactTypes')->get($cacheKey);
   }
 
   /**
@@ -104,6 +82,9 @@ WHERE  parent_id IS NULL
    *
    * @return array
    *   Array of basic contact types
+   *
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
    */
   public static function basicTypes($all = FALSE) {
     return array_keys(self::basicTypeInfo($all));
@@ -114,6 +95,8 @@ WHERE  parent_id IS NULL
    * @param string $key
    *
    * @return array
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
    */
   public static function basicTypePairs($all = FALSE, $key = 'name') {
     $subtypes = self::basicTypeInfo($all);
@@ -189,7 +172,7 @@ WHERE  subtype.name IS NOT NULL AND subtype.parent_id IS NOT NULL {$ctWHERE}
    *   a given basic contact type
    */
   public static function subTypes($contactType = NULL, $all = FALSE, $columnName = 'name', $ignoreCache = FALSE) {
-    if ($columnName == 'name') {
+    if ($columnName === 'name') {
       return array_keys(self::subTypeInfo($contactType, $all, $ignoreCache));
     }
     else {
@@ -236,18 +219,13 @@ WHERE  subtype.name IS NOT NULL AND subtype.parent_id IS NOT NULL {$ctWHERE}
    * Retrieve info array about all types i.e basic + subtypes.
    *
    * @param bool $all
-   * @param bool $reset
    *
    * @return array
    *   Array of basic types + all subtypes.
    */
-  public static function contactTypeInfo($all = FALSE, $reset = FALSE) {
+  public static function contactTypeInfo($all = FALSE) {
     static $_cache = NULL;
 
-    if ($reset === TRUE) {
-      $_cache = NULL;
-    }
-
     if ($_cache === NULL) {
       $_cache = [];
     }
@@ -259,14 +237,14 @@ WHERE  subtype.name IS NOT NULL AND subtype.parent_id IS NOT NULL {$ctWHERE}
       if (!$_cache[$argString]) {
         $_cache[$argString] = [];
 
-        $sql = "
+        $sql = '
 SELECT type.*, parent.name as parent, parent.label as parent_label
 FROM      civicrm_contact_type type
 LEFT JOIN civicrm_contact_type parent ON type.parent_id = parent.id
 WHERE  type.name IS NOT NULL
-";
+';
         if ($all === FALSE) {
-          $sql .= " AND type.is_active = 1";
+          $sql .= ' AND type.is_active = 1';
         }
 
         $dao = CRM_Core_DAO::executeQuery($sql,
@@ -360,19 +338,19 @@ WHERE  type.name IS NOT NULL
       if (!$_cache[$argString]) {
         $_cache[$argString] = [];
 
-        $sql = "
+        $sql = '
 SELECT    c.name as child_name , c.label as child_label , c.id as child_id,
           p.name as parent_name, p.label as parent_label, p.id as parent_id
 FROM      civicrm_contact_type c
 LEFT JOIN civicrm_contact_type p ON ( c.parent_id = p.id )
 WHERE     ( c.name IS NOT NULL )
-";
+';
 
         if ($all === FALSE) {
-          $sql .= "
+          $sql .= '
 AND   c.is_active = 1
 AND   ( p.is_active = 1 OR p.id IS NULL )
-";
+';
         }
         $sql .= " ORDER BY c.id";
 
@@ -578,10 +556,10 @@ WHERE contact_sub_type = '$name'";
 
     // remove navigation entry if any
     if ($name) {
-      $sql = "
+      $sql = '
 DELETE
 FROM civicrm_navigation
-WHERE name = %1";
+WHERE name = %1';
       $params = [1 => ["New $name", 'String']];
       CRM_Core_DAO::executeQuery($sql, $params);
       CRM_Core_BAO_Navigation::resetNavigation();
@@ -597,6 +575,7 @@ WHERE name = %1";
    *   An assoc array of name/value pairs.
    *
    * @return object|void
+   * @throws \CRM_Core_Exception
    */
   public static function add(&$params) {
 
@@ -624,7 +603,7 @@ WHERE name = %1";
 
     if (!empty($params['id'])) {
       $newParams = [
-        'label' => "New $contact",
+        'label' => ts("New %1", [1 => $contact]),
         'is_active' => $active,
       ];
       CRM_Core_BAO_Navigation::processUpdate(['name' => "New $contactName"], $newParams);
@@ -637,7 +616,7 @@ WHERE name = %1";
       $value = ['name' => "New $name"];
       CRM_Core_BAO_Navigation::retrieve($value, $navinfo);
       $navigation = [
-        'label' => "New $contact",
+        'label' => ts("New %1", [1 => $contact]),
         'name' => "New $contactName",
         'url' => "civicrm/contact/add?ct=$name&cst=$contactName&reset=1",
         'permission' => 'add contacts',
@@ -700,6 +679,7 @@ WHERE name = %1";
    *   Subtype.
    *
    * @return bool
+   * @throws \CRM_Core_Exception
    */
   public static function isAllowEdit($contactId, $subType = NULL) {
 
@@ -793,11 +773,12 @@ LIMIT 1";
   }
 
   /**
-   * @todo what does this function do?
    * @param $contactType
    * @param array $subtypeSet
    *
    * @return array
+   * @throws \CRM_Core_Exception
+   * @todo what does this function do?
    */
   public static function getSubtypeCustomPair($contactType, $subtypeSet = []) {
     if (empty($subtypeSet)) {
@@ -810,9 +791,9 @@ LIMIT 1";
       $subtype = CRM_Core_DAO::VALUE_SEPARATOR . $subtype . CRM_Core_DAO::VALUE_SEPARATOR;
       $subTypeClause[] = "extends_entity_column_value LIKE '%{$subtype}%' ";
     }
-    $query = "SELECT table_name
+    $query = 'SELECT table_name
 FROM civicrm_custom_group
-WHERE extends = %1 AND " . implode(" OR ", $subTypeClause);
+WHERE extends = %1 AND ' . implode(" OR ", $subTypeClause);
     $dao = CRM_Core_DAO::executeQuery($query, [1 => [$contactType, 'String']]);
     while ($dao->fetch()) {
       $customSet[] = $dao->table_name;
diff --git a/civicrm/CRM/Contact/BAO/GroupContact.php b/civicrm/CRM/Contact/BAO/GroupContact.php
index 3914a1c366..9058101d05 100644
--- a/civicrm/CRM/Contact/BAO/GroupContact.php
+++ b/civicrm/CRM/Contact/BAO/GroupContact.php
@@ -129,14 +129,13 @@ class CRM_Contact_BAO_GroupContact extends CRM_Contact_DAO_GroupContact {
 
     CRM_Utils_Hook::pre('create', 'GroupContact', $groupId, $contactIds);
 
-    list($numContactsAdded, $numContactsNotAdded)
-      = self::bulkAddContactsToGroup($contactIds, $groupId, $method, $status, $tracking);
-
+    $result = self::bulkAddContactsToGroup($contactIds, $groupId, $method, $status, $tracking);
+    CRM_Contact_BAO_GroupContactCache::invalidateGroupContactCache($groupId);
     CRM_Contact_BAO_Contact_Utils::clearContactCaches();
 
     CRM_Utils_Hook::post('create', 'GroupContact', $groupId, $contactIds);
 
-    return [count($contactIds), $numContactsAdded, $numContactsNotAdded];
+    return [count($contactIds), $result['count_added'], $result['count_not_added']];
   }
 
   /**
@@ -763,7 +762,7 @@ AND    contact_id IN ( $contactStr )
       }
     }
 
-    return [$numContactsAdded, $numContactsNotAdded];
+    return ['count_added' => $numContactsAdded, 'count_not_added' => $numContactsNotAdded];
   }
 
   /**
diff --git a/civicrm/CRM/Contact/BAO/Query.php b/civicrm/CRM/Contact/BAO/Query.php
index 3cabd6f2e0..694f6a84d4 100644
--- a/civicrm/CRM/Contact/BAO/Query.php
+++ b/civicrm/CRM/Contact/BAO/Query.php
@@ -685,12 +685,12 @@ class CRM_Contact_BAO_Query {
   public function addSpecialFields($apiEntity) {
     static $special = ['contact_type', 'contact_sub_type', 'sort_name', 'display_name'];
     // if get called via Contact.get API having address_id as return parameter
-    if ($apiEntity == 'Contact') {
+    if ($apiEntity === 'Contact') {
       $special[] = 'address_id';
     }
     foreach ($special as $name) {
       if (!empty($this->_returnProperties[$name])) {
-        if ($name == 'address_id') {
+        if ($name === 'address_id') {
           $this->_tables['civicrm_address'] = 1;
           $this->_select['address_id'] = 'civicrm_address.id as address_id';
           $this->_element['address_id'] = 1;
@@ -953,14 +953,14 @@ class CRM_Contact_BAO_Query {
           $this->_tables['civicrm_group_contact_cache'] = 1;
           $this->_pseudoConstantsSelect["{$name}"] = [
             'pseudoField' => "groups",
-            'idCol' => "groups",
+            'idCol' => 'groups',
           ];
         }
         elseif ($name === 'notes') {
           //@todo move this handling outside the big IF & ditch $makeException
           // if note field is subject then return subject else body of the note
           $noteColumn = 'note';
-          if (isset($noteField) && $noteField == 'note_subject') {
+          if (isset($noteField) && $noteField === 'note_subject') {
             $noteColumn = 'subject';
           }
 
@@ -1623,7 +1623,7 @@ class CRM_Contact_BAO_Query {
           }
         }
       }
-      elseif ($id == 'email_on_hold') {
+      elseif ($id === 'email_on_hold') {
         if ($onHoldValue = CRM_Utils_Array::value('email_on_hold', $formValues)) {
           // onHoldValue should be 0 or 1 or an array. Some legacy groups may hold ''
           // so in 5.11 we have an extra if that should become redundant over time.
@@ -1636,10 +1636,10 @@ class CRM_Contact_BAO_Query {
           }
         }
       }
-      elseif (substr($id, 0, 7) == 'custom_'
+      elseif (substr($id, 0, 7) === 'custom_'
         &&  (
-          substr($id, -5, 5) == '_from'
-          || substr($id, -3, 3) == '_to'
+          substr($id, -5, 5) === '_from'
+          || substr($id, -3, 3) === '_to'
         )
       ) {
         self::convertCustomRelativeFields($formValues, $params, $values, $id);
@@ -2982,7 +2982,7 @@ class CRM_Contact_BAO_Query {
       $value = CRM_Utils_Array::value($op, $value, $value);
     }
 
-    if ($name == 'group_type') {
+    if ($name === 'group_type') {
       $value = array_keys($this->getGroupsFromTypeCriteria($value));
     }
 
@@ -2997,7 +2997,7 @@ class CRM_Contact_BAO_Query {
     }
     $hasNonSmartGroups = count($regularGroupIDs);
 
-    $isNotOp = ($op == 'NOT IN' || $op == '!=');
+    $isNotOp = ($op === 'NOT IN' || $op === '!=');
 
     $statusJoinClause = $this->getGroupStatusClause($grouping);
     // If we are searching for 'Removed' contacts then despite it being a smart group we only care about the group_contact table.
@@ -3026,11 +3026,11 @@ class CRM_Contact_BAO_Query {
         }
       }
 
-      $gcTable = "`civicrm_group_contact-" . uniqid() . "`";
+      $gcTable = '`civicrm_group_contact-' . uniqid() . "`";
       $joinClause = ["contact_a.id = {$gcTable}.contact_id"];
 
       // @todo consider just casting != to NOT IN & handling both together.
-      if ($op == '!=') {
+      if ($op === '!=') {
         $groupIds = '';
         if (!empty($regularGroupIDs)) {
           $groupIds = CRM_Utils_Type::validate(
@@ -6201,7 +6201,7 @@ AND   displayRelType.is_active = 1
         // @todo - this is a bit specific (one operator).
         // However it is covered by a unit test so can be altered later with
         // some confidence.
-        if ($op == 'BETWEEN') {
+        if ($op === 'BETWEEN') {
           $separator = ' AND ';
         }
         $fieldValue = implode($separator, $fieldValue);
@@ -6250,7 +6250,7 @@ AND   displayRelType.is_active = 1
    * @return string
    */
   public static function getWildCardedValue($wildcard, $op, $value) {
-    if ($wildcard && $op == 'LIKE') {
+    if ($wildcard && $op === 'LIKE') {
       if (CRM_Core_Config::singleton()->includeWildCardInName && (substr($value, 0, 1) != '%')) {
         return "%$value%";
       }
@@ -6698,7 +6698,10 @@ AND   displayRelType.is_active = 1
    *   Should be clause with proper joins, effective to reduce where clause load.
    *
    * @param bool $skipOrderAndLimit
+   *
    * @return string
+   *
+   * @throws \CRM_Core_Exception
    */
   public function getSearchSQL(
     $offset = 0, $rowCount = 0, $sort = NULL,
@@ -6773,7 +6776,7 @@ AND   displayRelType.is_active = 1
       $name = $values[0] ?? NULL;
       $op = $values[1] ?? NULL;
       $value = $values[2] ?? NULL;
-      if ($name == 'contact_id' and $op == '=') {
+      if ($name === 'contact_id' and $op === '=') {
         if (CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $value, 'is_deleted')) {
           $onlyDeleted = TRUE;
         }
diff --git a/civicrm/CRM/Contact/BAO/Relationship.php b/civicrm/CRM/Contact/BAO/Relationship.php
index 53a3454fb9..24122a128a 100644
--- a/civicrm/CRM/Contact/BAO/Relationship.php
+++ b/civicrm/CRM/Contact/BAO/Relationship.php
@@ -1467,7 +1467,7 @@ LEFT JOIN  civicrm_country ON (civicrm_address.country_id = civicrm_country.id)
               if ($values[$rid]['rtype'] == 'b_a') {
                 $replace['clientid'] = $values[$rid]['cid'];
               }
-              $values[$rid]['case'] = '<a href="' . CRM_Utils_System::url('civicrm/case/ajax/details', sprintf('caseId=%d&cid=%d&snippet=4', $values[$rid]['case_id'], $values[$rid]['cid'])) . '" class="action-item crm-hover-button crm-summary-link"><i class="crm-i fa-folder-open-o"></i></a>';
+              $values[$rid]['case'] = '<a href="' . CRM_Utils_System::url('civicrm/case/ajax/details', sprintf('caseId=%d&cid=%d&snippet=4', $values[$rid]['case_id'], $values[$rid]['cid'])) . '" class="action-item crm-hover-button crm-summary-link"><i class="crm-i fa-folder-open-o" aria-hidden="true"></i></a>';
             }
           }
 
@@ -1489,13 +1489,14 @@ LEFT JOIN  civicrm_country ON (civicrm_address.country_id = civicrm_country.id)
   }
 
   /**
-   * Get get list of relationship type based on the target contact type.
+   * Get list of relationship type based on the target contact type.
+   * Both directions of relationships are included if their labels are not the same.
    *
    * @param string $targetContactType
-   *   It's valid contact tpye(may be Individual , Organization , Household).
+   *   A valid contact type (may be Individual, Organization, Household).
    *
    * @return array
-   *   array reference of all relationship types with context to current contact type .
+   *   array reference of all relationship types with context to current contact type.
    */
   public static function getRelationType($targetContactType) {
     $relationshipType = [];
@@ -1505,6 +1506,11 @@ LEFT JOIN  civicrm_country ON (civicrm_address.country_id = civicrm_country.id)
       if ($type['contact_type_b'] == $targetContactType || empty($type['contact_type_b'])) {
         $relationshipType[$key . '_a_b'] = $type['label_a_b'];
       }
+      if (($type['contact_type_a'] == $targetContactType || empty($type['contact_type_a']))
+        && $type['label_a_b'] != $type['label_b_a']
+      ) {
+        $relationshipType[$key . '_b_a'] = $type['label_b_a'];
+      }
     }
 
     return $relationshipType;
diff --git a/civicrm/CRM/Contact/BAO/RelationshipType.php b/civicrm/CRM/Contact/BAO/RelationshipType.php
index 6c44ea5900..08b0d81032 100644
--- a/civicrm/CRM/Contact/BAO/RelationshipType.php
+++ b/civicrm/CRM/Contact/BAO/RelationshipType.php
@@ -85,15 +85,7 @@ class CRM_Contact_BAO_RelationshipType extends CRM_Contact_DAO_RelationshipType
     }
 
     // action is taken depending upon the mode
-    $relationshipType = new CRM_Contact_DAO_RelationshipType();
-
-    $hook = empty($params['id']) ? 'create' : 'edit';
-    CRM_Utils_Hook::pre($hook, 'RelationshipType', CRM_Utils_Array::value('id', $params), $params);
-
-    $relationshipType->copyValues($params);
-    $relationshipType->save();
-
-    CRM_Utils_Hook::post($hook, 'RelationshipType', $relationshipType->id, $relationshipType);
+    $relationshipType = self::writeRecord($params);
 
     CRM_Core_PseudoConstant::relationshipType('label', TRUE);
     CRM_Core_PseudoConstant::relationshipType('name', TRUE);
diff --git a/civicrm/CRM/Contact/Form/CustomData.php b/civicrm/CRM/Contact/Form/CustomData.php
index 86dc621b46..87849e1b28 100644
--- a/civicrm/CRM/Contact/Form/CustomData.php
+++ b/civicrm/CRM/Contact/Form/CustomData.php
@@ -52,13 +52,6 @@ class CRM_Contact_Form_CustomData extends CRM_Core_Form {
    */
   //protected $_groupTree;
 
-  /**
-   * Which blocks should we show and hide.
-   *
-   * @var CRM_Core_ShowHideBlocks
-   */
-  protected $_showHide;
-
   /**
    * Array group titles.
    *
diff --git a/civicrm/CRM/Contact/Form/Edit/Individual.php b/civicrm/CRM/Contact/Form/Edit/Individual.php
index 29d8dc0a5f..f4d933933a 100644
--- a/civicrm/CRM/Contact/Form/Edit/Individual.php
+++ b/civicrm/CRM/Contact/Form/Edit/Individual.php
@@ -88,7 +88,6 @@ class CRM_Contact_Form_Edit_Individual {
         'objectExists',
         ['CRM_Contact_DAO_Contact', $form->_contactId, 'external_identifier']
       );
-      CRM_Core_ShowHideBlocks::links($form, 'demographics', '', '');
     }
   }
 
diff --git a/civicrm/CRM/Contact/Form/Inline.php b/civicrm/CRM/Contact/Form/Inline.php
index fcc034a7c9..2f551a1cea 100644
--- a/civicrm/CRM/Contact/Form/Inline.php
+++ b/civicrm/CRM/Contact/Form/Inline.php
@@ -56,7 +56,7 @@ abstract class CRM_Contact_Form_Inline extends CRM_Core_Form {
    * Common preprocess: fetch contact ID and contact type
    */
   public function preProcess() {
-    $this->_contactId = CRM_Utils_Request::retrieve('cid', 'Positive', $this, TRUE, NULL, $_REQUEST);
+    $this->_contactId = CRM_Utils_Request::retrieve('cid', 'Positive', $this, TRUE);
     $this->assign('contactId', $this->_contactId);
 
     // get contact type and subtype
diff --git a/civicrm/CRM/Contact/Form/Inline/Address.php b/civicrm/CRM/Contact/Form/Inline/Address.php
index 4db79aee78..e33118c913 100644
--- a/civicrm/CRM/Contact/Form/Inline/Address.php
+++ b/civicrm/CRM/Contact/Form/Inline/Address.php
@@ -58,7 +58,7 @@ class CRM_Contact_Form_Inline_Address extends CRM_Contact_Form_Inline {
    * hence calling parent constructor
    */
   public function __construct() {
-    $locBlockNo = CRM_Utils_Request::retrieve('locno', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+    $locBlockNo = CRM_Utils_Request::retrieve('locno', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
     $name = "Address_{$locBlockNo}";
 
     parent::__construct(NULL, CRM_Core_Action::NONE, 'post', $name);
@@ -70,14 +70,14 @@ class CRM_Contact_Form_Inline_Address extends CRM_Contact_Form_Inline {
   public function preProcess() {
     parent::preProcess();
 
-    $this->_locBlockNo = CRM_Utils_Request::retrieve('locno', 'Positive', $this, TRUE, NULL, $_REQUEST);
+    $this->_locBlockNo = CRM_Utils_Request::retrieve('locno', 'Positive', $this, TRUE);
     $this->assign('blockId', $this->_locBlockNo);
 
     $addressSequence = CRM_Core_BAO_Address::addressSequence();
     $this->assign('addressSequence', $addressSequence);
 
     $this->_values = [];
-    $this->_addressId = CRM_Utils_Request::retrieve('aid', 'Positive', $this, FALSE, NULL, $_REQUEST);
+    $this->_addressId = CRM_Utils_Request::retrieve('aid', 'Positive', $this);
 
     $this->_action = CRM_Core_Action::ADD;
     if ($this->_addressId) {
diff --git a/civicrm/CRM/Contact/Form/Inline/CustomData.php b/civicrm/CRM/Contact/Form/Inline/CustomData.php
index 1d30895c36..d8e92f86bb 100644
--- a/civicrm/CRM/Contact/Form/Inline/CustomData.php
+++ b/civicrm/CRM/Contact/Form/Inline/CustomData.php
@@ -40,10 +40,10 @@ class CRM_Contact_Form_Inline_CustomData extends CRM_Contact_Form_Inline {
   public function preProcess() {
     parent::preProcess();
 
-    $this->_groupID = CRM_Utils_Request::retrieve('groupID', 'Positive', $this, TRUE, NULL, $_REQUEST);
+    $this->_groupID = CRM_Utils_Request::retrieve('groupID', 'Positive', $this, TRUE, NULL);
     $this->assign('customGroupId', $this->_groupID);
-    $customRecId = CRM_Utils_Request::retrieve('customRecId', 'Positive', $this, FALSE, 1, $_REQUEST);
-    $cgcount = CRM_Utils_Request::retrieve('cgcount', 'Positive', $this, FALSE, 1, $_REQUEST);
+    $customRecId = CRM_Utils_Request::retrieve('customRecId', 'Positive', $this, FALSE, 1);
+    $cgcount = CRM_Utils_Request::retrieve('cgcount', 'Positive', $this, FALSE, 1);
     $subType = CRM_Contact_BAO_Contact::getContactSubType($this->_contactId, ',');
     CRM_Custom_Form_CustomData::preProcess($this, NULL, $subType, $cgcount,
       $this->_contactType, $this->_contactId);
diff --git a/civicrm/CRM/Contact/Form/Search/Advanced.php b/civicrm/CRM/Contact/Form/Search/Advanced.php
index 642fcfdd72..9336eb604f 100644
--- a/civicrm/CRM/Contact/Form/Search/Advanced.php
+++ b/civicrm/CRM/Contact/Form/Search/Advanced.php
@@ -191,6 +191,14 @@ class CRM_Contact_Form_Search_Advanced extends CRM_Contact_Form_Search {
     ], $defaults);
     $this->normalizeDefaultValues($defaults);
 
+    //991/Subtypes not respected when editing smart group criteria
+    if (!empty($defaults['contact_type']) && !empty($this->_formValues['contact_sub_type'])) {
+      foreach ($this->_formValues['contact_sub_type'] as $subtype) {
+        $basicType = CRM_Contact_BAO_ContactType::getBasicType($subtype);
+        $defaults['contact_type'][$subtype] = $basicType . '__' . $subtype;
+      }
+    }
+
     if ($this->_context === 'amtg') {
       $defaults['task'] = CRM_Contact_Task::GROUP_ADD;
     }
diff --git a/civicrm/CRM/Contact/Form/Search/Criteria.php b/civicrm/CRM/Contact/Form/Search/Criteria.php
index d4d711296c..dbfb6ebe6a 100644
--- a/civicrm/CRM/Contact/Form/Search/Criteria.php
+++ b/civicrm/CRM/Contact/Form/Search/Criteria.php
@@ -244,7 +244,13 @@ class CRM_Contact_Form_Search_Criteria {
    */
   public static function getSearchFieldMetadata() {
     $fields = [
-      'sort_name' => ['title' => ts('Complete OR Partial Name'), 'template_grouping' => 'basic'],
+      'sort_name' => [
+        'title' => ts('Complete OR Partial Name'),
+        'template_grouping' => 'basic',
+        'template' => 'CRM/Contact/Form/Search/Criteria/Fields/sort_name.tpl',
+      ],
+      'first_name' => ['template_grouping' => 'basic'],
+      'last_name' => ['template_grouping' => 'basic'],
       'email' => ['title' => ts('Complete OR Partial Email'), 'entity' => 'Email', 'template_grouping' => 'basic'],
       'contact_tags' => ['name' => 'contact_tags', 'type' => CRM_Utils_Type::T_INT, 'is_pseudofield' => TRUE, 'template_grouping' => 'basic'],
       'created_date' => ['name' => 'created_date', 'template_grouping' => 'changeLog'],
@@ -605,7 +611,6 @@ class CRM_Contact_Form_Search_Criteria {
 
     foreach ($groupDetails as $key => $group) {
       $_groupTitle[$key] = $group['name'];
-      CRM_Core_ShowHideBlocks::links($form, $group['name'], '', '');
 
       foreach ($group['fields'] as $field) {
         $fieldId = $field['id'];
diff --git a/civicrm/CRM/Contact/Form/Search/Custom.php b/civicrm/CRM/Contact/Form/Search/Custom.php
index dbfb6165f2..cfc78ef835 100644
--- a/civicrm/CRM/Contact/Form/Search/Custom.php
+++ b/civicrm/CRM/Contact/Form/Search/Custom.php
@@ -34,7 +34,7 @@ class CRM_Contact_Form_Search_Custom extends CRM_Contact_Form_Search {
       ) = CRM_Contact_BAO_SearchCustom::details($csID, $ssID, $gID);
 
     if (!$this->_customSearchID) {
-      CRM_Core_Error::fatal('Could not get details for custom search.');
+      CRM_Core_Error::statusbounce('Could not get details for custom search.');
     }
 
     // stash this as a hidden element so we can potentially go there if the session
diff --git a/civicrm/CRM/Contact/Form/Search/Custom/Base.php b/civicrm/CRM/Contact/Form/Search/Custom/Base.php
index 25bed0be96..43e59d3ff1 100644
--- a/civicrm/CRM/Contact/Form/Search/Custom/Base.php
+++ b/civicrm/CRM/Contact/Form/Search/Custom/Base.php
@@ -193,7 +193,7 @@ class CRM_Contact_Form_Search_Custom_Base {
 
     foreach ($includeStrings as $string) {
       if (stripos($sql, $string) === FALSE) {
-        CRM_Core_Error::fatal(ts('Could not find \'%1\' string in SQL clause.',
+        CRM_Core_Error::statusBounce(ts('Could not find \'%1\' string in SQL clause.',
           [1 => $string]
         ));
       }
@@ -201,7 +201,7 @@ class CRM_Contact_Form_Search_Custom_Base {
 
     foreach ($excludeStrings as $string) {
       if (preg_match('/(\s' . $string . ')|(' . $string . '\s)/i', $sql)) {
-        CRM_Core_Error::fatal(ts('Found illegal \'%1\' string in SQL clause.',
+        CRM_Core_Error::statusBounce(ts('Found illegal \'%1\' string in SQL clause.',
           [1 => $string]
         ));
       }
diff --git a/civicrm/CRM/Contact/Form/Search/Custom/Group.php b/civicrm/CRM/Contact/Form/Search/Custom/Group.php
index b6e4d59d64..502d041820 100644
--- a/civicrm/CRM/Contact/Form/Search/Custom/Group.php
+++ b/civicrm/CRM/Contact/Form/Search/Custom/Group.php
@@ -329,7 +329,7 @@ class CRM_Contact_Form_Search_Custom_Group extends CRM_Contact_Form_Search_Custo
             $ssGroup = new CRM_Contact_DAO_Group();
             $ssGroup->id = $values;
             if (!$ssGroup->find(TRUE)) {
-              CRM_Core_Error::fatal();
+              CRM_Core_Error::statusBounce(ts('Smart group sepecifed in exclude groups is not found in the database'));
             }
             CRM_Contact_BAO_GroupContactCache::load($ssGroup);
 
@@ -389,7 +389,7 @@ WHERE  gcc.group_id = {$ssGroup->id}
           $ssGroup = new CRM_Contact_DAO_Group();
           $ssGroup->id = $values;
           if (!$ssGroup->find(TRUE)) {
-            CRM_Core_Error::fatal();
+            CRM_Core_Error::statusBounce(ts('Smart group sepecifed in include groups is not found in the database'));
           }
           CRM_Contact_BAO_GroupContactCache::load($ssGroup);
 
diff --git a/civicrm/CRM/Contact/Form/Search/Custom/PriceSet.php b/civicrm/CRM/Contact/Form/Search/Custom/PriceSet.php
index 56f5c5e53c..327bc90045 100644
--- a/civicrm/CRM/Contact/Form/Search/Custom/PriceSet.php
+++ b/civicrm/CRM/Contact/Form/Search/Custom/PriceSet.php
@@ -185,7 +185,7 @@ AND    p.entity_id    = e.id
     }
 
     if (empty($event)) {
-      CRM_Core_Error::fatal(ts('There are no events with Price Sets'));
+      CRM_Core_Error::statusBounce(ts('There are no events with Price Sets'));
     }
 
     $form->add('select',
diff --git a/civicrm/CRM/Contact/Form/Task/Batch.php b/civicrm/CRM/Contact/Form/Task/Batch.php
index 65a7a87315..c213001a72 100644
--- a/civicrm/CRM/Contact/Form/Task/Batch.php
+++ b/civicrm/CRM/Contact/Form/Task/Batch.php
@@ -66,7 +66,7 @@ class CRM_Contact_Form_Task_Batch extends CRM_Contact_Form_Task {
     $ufGroupId = $this->get('ufGroupId');
 
     if (!$ufGroupId) {
-      CRM_Core_Error::fatal('ufGroupId is missing');
+      CRM_Core_Error::statusBounce(ts('ufGroupId is missing'));
     }
     $this->_title = ts('Update multiple contacts') . ' - ' . CRM_Core_BAO_UFGroup::getTitle($ufGroupId);
     CRM_Utils_System::setTitle($this->_title);
diff --git a/civicrm/CRM/Contact/Form/Task/Delete.php b/civicrm/CRM/Contact/Form/Task/Delete.php
index 5b2b088003..a4996b227f 100644
--- a/civicrm/CRM/Contact/Form/Task/Delete.php
+++ b/civicrm/CRM/Contact/Form/Task/Delete.php
@@ -68,10 +68,10 @@ class CRM_Contact_Form_Task_Delete extends CRM_Contact_Form_Task {
 
     if ($cid) {
       if (!CRM_Contact_BAO_Contact_Permission::allow($cid, CRM_Core_Permission::EDIT)) {
-        CRM_Core_Error::fatal(ts('You do not have permission to delete this contact. Note: you can delete contacts if you can edit them.'));
+        CRM_Core_Error::statusBounce(ts('You do not have permission to delete this contact. Note: you can delete contacts if you can edit them.'));
       }
       elseif (CRM_Contact_BAO_Contact::checkDomainContact($cid)) {
-        CRM_Core_Error::fatal(ts('This contact is a special one for the contact information associated with the CiviCRM installation for this domain. No one is allowed to delete it because the information is used for special system purposes.'));
+        CRM_Core_Error::statusBounce(ts('This contact is a special one for the contact information associated with the CiviCRM installation for this domain. No one is allowed to delete it because the information is used for special system purposes.'));
       }
 
       $this->_contactIds = [$cid];
diff --git a/civicrm/CRM/Contact/Form/Task/EmailTrait.php b/civicrm/CRM/Contact/Form/Task/EmailTrait.php
index 2abc3f9132..f5fe8739cf 100644
--- a/civicrm/CRM/Contact/Form/Task/EmailTrait.php
+++ b/civicrm/CRM/Contact/Form/Task/EmailTrait.php
@@ -79,6 +79,15 @@ trait CRM_Contact_Form_Task_EmailTrait {
 
   public $contactEmails = [];
 
+  /**
+   * Contacts form whom emails could not be sent.
+   *
+   * An array of contact ids and the relevant message details.
+   *
+   * @var array
+   */
+  protected $suppressedEmails = [];
+
   /**
    * Getter for isSearchContext.
    *
@@ -174,29 +183,19 @@ trait CRM_Contact_Form_Task_EmailTrait {
       $setDefaults = FALSE;
     }
 
-    $elements = ['to'];
     $this->_allContactIds = $this->_toContactIds = $this->_contactIds;
-    foreach ($elements as $element) {
-      if ($$element->getValue()) {
 
-        foreach ($this->getEmails($$element) as $value) {
-          $contactId = $value['contact_id'];
-          $email = $value['email'];
-          if ($contactId) {
-            switch ($element) {
-              case 'to':
-                $this->_contactIds[] = $this->_toContactIds[] = $contactId;
-                $this->_toContactEmails[] = $email;
-                break;
-
-            }
-
-            $this->_allContactIds[] = $contactId;
-          }
+    if ($to->getValue()) {
+      foreach ($this->getEmails($to) as $value) {
+        $contactId = $value['contact_id'];
+        $email = $value['email'];
+        if ($contactId) {
+          $this->_contactIds[] = $this->_toContactIds[] = $contactId;
+          $this->_toContactEmails[] = $email;
+          $this->_allContactIds[] = $contactId;
         }
-
-        $setDefaults = TRUE;
       }
+      $setDefaults = TRUE;
     }
 
     //get the group of contacts as per selected by user in case of Find Activities
@@ -207,42 +206,24 @@ trait CRM_Contact_Form_Task_EmailTrait {
 
     // check if we need to setdefaults and check for valid contact emails / communication preferences
     if (is_array($this->_allContactIds) && $setDefaults) {
-      $returnProperties = [
-        'sort_name' => 1,
-        'email' => 1,
-        'do_not_email' => 1,
-        'is_deceased' => 1,
-        'on_hold' => 1,
-        'display_name' => 1,
-        'preferred_mail_format' => 1,
-      ];
-
       // get the details for all selected contacts ( to, cc and bcc contacts )
-      list($this->_contactDetails) = CRM_Utils_Token::getTokenDetails($this->_allContactIds,
-        $returnProperties,
-        FALSE,
-        FALSE
-      );
-
-      // make a copy of all contact details
-      $this->_allContactDetails = $this->_contactDetails;
+      $allContactDetails = civicrm_api3('Contact', 'get', [
+        'id' => ['IN' => $this->_allContactIds],
+        'return' => ['sort_name', 'email', 'do_not_email', 'is_deceased', 'on_hold', 'display_name', 'preferred_mail_format'],
+        'options' => ['limit' => 0],
+      ])['values'];
 
       // perform all validations on unique contact Ids
-      foreach (array_unique($this->_allContactIds) as $key => $contactId) {
-        $value = $this->_contactDetails[$contactId];
+      foreach ($allContactDetails as $contactId => $value) {
         if ($value['do_not_email'] || empty($value['email']) || !empty($value['is_deceased']) || $value['on_hold']) {
-          $suppressedEmails++;
-
-          // unset contact details for contacts that we won't be sending email. This is prevent extra computation
-          // during token evaluation etc.
-          unset($this->_contactDetails[$contactId]);
+          $this->setSuppressedEmail($contactId, $value);
         }
         else {
           $email = $value['email'];
 
           // build array's which are used to setdefaults
           if (in_array($contactId, $this->_toContactIds)) {
-            $this->_toContactDetails[$contactId] = $this->_contactDetails[$contactId];
+            $this->_toContactDetails[$contactId] = $this->_contactDetails[$contactId] = $value;
             // If a particular address has been specified as the default, use that instead of contact's primary email
             if (!empty($this->_toEmail) && $this->_toEmail['contact_id'] == $contactId) {
               $email = $this->_toEmail['email'];
@@ -262,7 +243,7 @@ trait CRM_Contact_Form_Task_EmailTrait {
 
     $this->assign('toContact', json_encode($toArray));
 
-    $this->assign('suppressedEmails', $suppressedEmails);
+    $this->assign('suppressedEmails', count($this->suppressedEmails));
 
     $this->assign('totalSelectedContacts', count($this->_contactIds));
 
@@ -360,6 +341,7 @@ trait CRM_Contact_Form_Task_EmailTrait {
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
    * @throws \Civi\API\Exception\UnauthorizedException
+   * @throws \API_Exception
    */
   public function postProcess() {
     $this->bounceIfSimpleMailLimitExceeded(count($this->_contactIds));
@@ -404,7 +386,6 @@ trait CRM_Contact_Form_Task_EmailTrait {
     // If we have had a contact email used here the value returned from the line above will be the
     // numerical key where as $from for use in the sendEmail in Activity needs to be of format of "To Name" <toemailaddress>
     $from = CRM_Utils_Mail::formatFromAddress($from);
-    $subject = $formValues['subject'];
 
     $ccArray = $formValues['cc_id'] ? explode(',', $formValues['cc_id']) : [];
     $cc = $this->getEmailString($ccArray);
@@ -414,21 +395,8 @@ trait CRM_Contact_Form_Task_EmailTrait {
     $bcc = $this->getEmailString($bccArray);
     $additionalDetails .= empty($bccArray) ? '' : "\nbcc : " . $this->getEmailUrlString($bccArray);
 
-    // CRM-5916: prepend case id hash to CiviCase-originating emails’ subjects
-    if (isset($this->_caseId) && is_numeric($this->_caseId)) {
-      $hash = substr(sha1(CIVICRM_SITE_KEY . $this->_caseId), 0, 7);
-      $subject = "[case #$hash] $subject";
-    }
-
-    $attachments = [];
-    CRM_Core_BAO_File::formatAttachment($formValues,
-      $attachments,
-      NULL, NULL
-    );
-
     // format contact details array to handle multiple emails from same contact
     $formattedContactDetails = [];
-    $tempEmails = [];
     foreach ($this->_contactIds as $key => $contactId) {
       // if we dont have details on this contactID, we should ignore
       // potentially this is due to the contact not wanting to receive email
@@ -438,69 +406,33 @@ trait CRM_Contact_Form_Task_EmailTrait {
       $email = $this->_toContactEmails[$key];
       // prevent duplicate emails if same email address is selected CRM-4067
       // we should allow same emails for different contacts
-      $emailKey = "{$contactId}::{$email}";
-      if (!in_array($emailKey, $tempEmails)) {
-        $tempEmails[] = $emailKey;
-        $details = $this->_contactDetails[$contactId];
-        $details['email'] = $email;
-        unset($details['email_id']);
-        $formattedContactDetails[] = $details;
-      }
-    }
-
-    $contributionIds = [];
-    if ($this->getVar('_contributionIds')) {
-      $contributionIds = $this->getVar('_contributionIds');
+      $details = $this->_contactDetails[$contactId];
+      $details['email'] = $email;
+      unset($details['email_id']);
+      $formattedContactDetails["{$contactId}::{$email}"] = $details;
     }
 
     // send the mail
     list($sent, $activityId) = CRM_Activity_BAO_Activity::sendEmail(
       $formattedContactDetails,
-      $subject,
+      $this->getSubject($formValues['subject']),
       $formValues['text_message'],
       $formValues['html_message'],
       NULL,
       NULL,
       $from,
-      $attachments,
+      $this->getAttachments($formValues),
       $cc,
       $bcc,
       array_keys($this->_toContactDetails),
       $additionalDetails,
-      $contributionIds,
+      $this->getVar('_contributionIds') ?? [],
       CRM_Utils_Array::value('campaign_id', $formValues),
       $this->getVar('_caseId')
     );
 
-    $followupStatus = '';
     if ($sent) {
-      $followupActivity = NULL;
-      if (!empty($formValues['followup_activity_type_id'])) {
-        $params['followup_activity_type_id'] = $formValues['followup_activity_type_id'];
-        $params['followup_activity_subject'] = $formValues['followup_activity_subject'];
-        $params['followup_date'] = $formValues['followup_date'];
-        $params['target_contact_id'] = $this->_contactIds;
-        $params['followup_assignee_contact_id'] = explode(',', $formValues['followup_assignee_contact_id']);
-        $followupActivity = CRM_Activity_BAO_Activity::createFollowupActivity($activityId, $params);
-        $followupStatus = ts('A followup activity has been scheduled.');
-
-        if (Civi::settings()->get('activity_assignee_notification')) {
-          if ($followupActivity) {
-            $mailToFollowupContacts = [];
-            $assignee = [$followupActivity->id];
-            $assigneeContacts = CRM_Activity_BAO_ActivityAssignment::getAssigneeNames($assignee, TRUE, FALSE);
-            foreach ($assigneeContacts as $values) {
-              $mailToFollowupContacts[$values['email']] = $values;
-            }
-
-            $sentFollowup = CRM_Activity_BAO_Activity::sendToAssignee($followupActivity, $mailToFollowupContacts);
-            if ($sentFollowup) {
-              $followupStatus .= '<br />' . ts('A copy of the follow-up activity has also been sent to follow-up assignee contacts(s).');
-            }
-          }
-        }
-      }
-
+      $followupStatus = $this->createFollowUpActivities($formValues, $activityId);
       $count_success = count($this->_toContactDetails);
       CRM_Core_Session::setStatus(ts('One message was sent successfully. ', [
         'plural' => '%count messages were sent successfully. ',
@@ -508,23 +440,10 @@ trait CRM_Contact_Form_Task_EmailTrait {
       ]) . $followupStatus, ts('Message Sent', ['plural' => 'Messages Sent', 'count' => $count_success]), 'success');
     }
 
-    // Display the name and number of contacts for those email is not sent.
-    // php 5.4 throws out a notice since the values of these below arrays are arrays.
-    // the behavior is not documented in the php manual, but it does the right thing
-    // suppressing the notices to get things in good shape going forward
-    $emailsNotSent = @array_diff_assoc($this->_allContactDetails, $this->_contactDetails);
-
-    if ($emailsNotSent) {
-      $not_sent = [];
-      foreach ($emailsNotSent as $contactId => $values) {
-        $displayName = $values['display_name'];
-        $email = $values['email'];
-        $contactViewUrl = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid=$contactId");
-        $not_sent[] = "<a href='$contactViewUrl' title='$email'>$displayName</a>" . ($values['on_hold'] ? '(' . ts('on hold') . ')' : '');
-      }
-      $status = '(' . ts('because no email address on file or communication preferences specify DO NOT EMAIL or Contact is deceased or Primary email address is On Hold') . ')<ul><li>' . implode('</li><li>', $not_sent) . '</li></ul>';
+    if (!empty($this->suppressedEmails)) {
+      $status = '(' . ts('because no email address on file or communication preferences specify DO NOT EMAIL or Contact is deceased or Primary email address is On Hold') . ')<ul><li>' . implode('</li><li>', $this->suppressedEmails) . '</li></ul>';
       CRM_Core_Session::setStatus($status, ts('One Message Not Sent', [
-        'count' => count($emailsNotSent),
+        'count' => count($this->suppressedEmails),
         'plural' => '%count Messages Not Sent',
       ]), 'info');
     }
@@ -647,4 +566,91 @@ trait CRM_Contact_Form_Task_EmailTrait {
     return $urlString;
   }
 
+  /**
+   * Set the emails that are not to be sent out.
+   *
+   * @param int $contactID
+   * @param array $values
+   */
+  protected function setSuppressedEmail($contactID, $values) {
+    $contactViewUrl = CRM_Utils_System::url('civicrm/contact/view', 'reset=1&cid=' . $contactID);
+    $this->suppressedEmails[$contactID] = "<a href='$contactViewUrl' title='{$values['email']}'>{$values['display_name']}</a>" . ($values['on_hold'] ? '(' . ts('on hold') . ')' : '');
+  }
+
+  /**
+   * Get any attachments.
+   *
+   * @param array $formValues
+   *
+   * @return array
+   */
+  protected function getAttachments(array $formValues): array {
+    $attachments = [];
+    CRM_Core_BAO_File::formatAttachment($formValues,
+      $attachments,
+      NULL, NULL
+    );
+    return $attachments;
+  }
+
+  /**
+   * Get the subject for the message.
+   *
+   * The case handling should possibly be on the case form.....
+   *
+   * @param string $subject
+   *
+   * @return string
+   */
+  protected function getSubject(string $subject):string {
+    // CRM-5916: prepend case id hash to CiviCase-originating emails’ subjects
+    if (isset($this->_caseId) && is_numeric($this->_caseId)) {
+      $hash = substr(sha1(CIVICRM_SITE_KEY . $this->_caseId), 0, 7);
+      $subject = "[case #$hash] $subject";
+    }
+    return $subject;
+  }
+
+  /**
+   * Create any follow up activities.
+   *
+   * @param array $formValues
+   * @param int $activityId
+   *
+   * @return string
+   *
+   * @throws \CRM_Core_Exception
+   */
+  protected function createFollowUpActivities($formValues, $activityId): string {
+    $params = [];
+    $followupStatus = '';
+    $followupActivity = NULL;
+    if (!empty($formValues['followup_activity_type_id'])) {
+      $params['followup_activity_type_id'] = $formValues['followup_activity_type_id'];
+      $params['followup_activity_subject'] = $formValues['followup_activity_subject'];
+      $params['followup_date'] = $formValues['followup_date'];
+      $params['target_contact_id'] = $this->_contactIds;
+      $params['followup_assignee_contact_id'] = explode(',', $formValues['followup_assignee_contact_id']);
+      $followupActivity = CRM_Activity_BAO_Activity::createFollowupActivity($activityId, $params);
+      $followupStatus = ts('A followup activity has been scheduled.');
+
+      if (Civi::settings()->get('activity_assignee_notification')) {
+        if ($followupActivity) {
+          $mailToFollowupContacts = [];
+          $assignee = [$followupActivity->id];
+          $assigneeContacts = CRM_Activity_BAO_ActivityAssignment::getAssigneeNames($assignee, TRUE, FALSE);
+          foreach ($assigneeContacts as $values) {
+            $mailToFollowupContacts[$values['email']] = $values;
+          }
+
+          $sentFollowup = CRM_Activity_BAO_Activity::sendToAssignee($followupActivity, $mailToFollowupContacts);
+          if ($sentFollowup) {
+            $followupStatus .= '<br />' . ts('A copy of the follow-up activity has also been sent to follow-up assignee contacts(s).');
+          }
+        }
+      }
+    }
+    return $followupStatus;
+  }
+
 }
diff --git a/civicrm/CRM/Contact/Form/Task/Map.php b/civicrm/CRM/Contact/Form/Task/Map.php
index d9f1d339c9..82b7960837 100644
--- a/civicrm/CRM/Contact/Form/Task/Map.php
+++ b/civicrm/CRM/Contact/Form/Task/Map.php
@@ -58,7 +58,7 @@ class CRM_Contact_Form_Task_Map extends CRM_Contact_Form_Task {
         // CRM-11766
         $profileIDs = CRM_Profile_Page_Listings::getProfileContact($profileGID);
         if (!in_array($cid, $profileIDs)) {
-          CRM_Core_Error::fatal();
+          CRM_Core_Error::statusBounce(ts('Contact not found when building list of contacts in the profile'));
         }
       }
       elseif ($context) {
diff --git a/civicrm/CRM/Contact/Form/Task/SaveSearch/Update.php b/civicrm/CRM/Contact/Form/Task/SaveSearch/Update.php
index 72a4b81dcd..76505b00ab 100644
--- a/civicrm/CRM/Contact/Form/Task/SaveSearch/Update.php
+++ b/civicrm/CRM/Contact/Form/Task/SaveSearch/Update.php
@@ -51,7 +51,7 @@ class CRM_Contact_Form_Task_SaveSearch_Update extends CRM_Contact_Form_Task_Save
       $types = explode(CRM_Core_DAO::VALUE_SEPARATOR,
         substr($defaults['group_type'], 1, -1)
       );
-      $defaults['group_type'] = array();
+      $defaults['group_type'] = [];
       foreach ($types as $type) {
         $defaults['group_type'][$type] = 1;
       }
diff --git a/civicrm/CRM/Contact/Import/Form/Preview.php b/civicrm/CRM/Contact/Import/Form/Preview.php
index 5c268de118..77ddd7afa2 100644
--- a/civicrm/CRM/Contact/Import/Form/Preview.php
+++ b/civicrm/CRM/Contact/Import/Form/Preview.php
@@ -151,37 +151,9 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
       }
     }
 
-    $path = "_qf_MapField_display=true";
-    $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $form);
-    if (CRM_Utils_Rule::qfKey($qfKey)) {
-      $path .= "&qfKey=$qfKey";
-    }
-
-    $previousURL = CRM_Utils_System::url('civicrm/import/contact', $path, FALSE, NULL, FALSE);
-    $cancelURL = CRM_Utils_System::url('civicrm/import/contact', 'reset=1');
-
-    $buttons = array(
-      array(
-        'type' => 'back',
-        'name' => ts('Previous'),
-        'js' => array('onclick' => "location.href='{$previousURL}'; return false;"),
-      ),
-      array(
-        'type' => 'next',
-        'name' => ts('Import Now'),
-        'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
-        'isDefault' => TRUE,
-      ),
-      array(
-        'type' => 'cancel',
-        'name' => ts('Cancel'),
-        'js' => array('onclick' => "location.href='{$cancelURL}'; return false;"),
-      ),
-    );
-
-    $this->addButtons($buttons);
-
     $this->addFormRule(array('CRM_Contact_Import_Form_Preview', 'formRule'), $this);
+
+    parent::buildQuickForm();
   }
 
   /**
@@ -197,7 +169,7 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
    *   list of errors to be posted back to the form
    */
   public static function formRule($fields, $files, $self) {
-    $errors = array();
+    $errors = [];
     $invalidTagName = $invalidGroupName = FALSE;
 
     if (!empty($fields['newTagName'])) {
@@ -291,7 +263,7 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
     // check if there is any error occurred
     $errorStack = CRM_Core_Error::singleton();
     $errors = $errorStack->getErrors();
-    $errorMessage = array();
+    $errorMessage = [];
 
     if (is_array($errors)) {
       foreach ($errors as $key => $value) {
@@ -345,14 +317,14 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
 
     $mapper = $this->controller->exportValue('MapField', 'mapper');
 
-    $mapperKeys = array();
-    $mapperLocTypes = array();
-    $mapperPhoneTypes = array();
-    $mapperRelated = array();
-    $mapperRelatedContactType = array();
-    $mapperRelatedContactDetails = array();
-    $mapperRelatedContactLocType = array();
-    $mapperRelatedContactPhoneType = array();
+    $mapperKeys = [];
+    $mapperLocTypes = [];
+    $mapperPhoneTypes = [];
+    $mapperRelated = [];
+    $mapperRelatedContactType = [];
+    $mapperRelatedContactDetails = [];
+    $mapperRelatedContactLocType = [];
+    $mapperRelatedContactPhoneType = [];
 
     foreach ($mapper as $key => $value) {
       $mapperKeys[$key] = $mapper[$key][0];
@@ -403,7 +375,7 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
     $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
 
     foreach ($mapper as $key => $value) {
-      $header = array();
+      $header = [];
       list($id, $first, $second) = explode('_', $mapper[$key][0]);
       if (($first == 'a' && $second == 'b') || ($first == 'b' && $second == 'a')) {
         $relationType = new CRM_Contact_DAO_RelationshipType();
@@ -475,7 +447,7 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
     }
 
     if (is_array($groups)) {
-      $groupAdditions = array();
+      $groupAdditions = [];
       foreach ($groups as $groupId) {
         $addCount = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId);
         if (!empty($relatedContactIds)) {
@@ -513,15 +485,14 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
         'description' => $newTagDesc,
         'is_active' => TRUE,
       );
-      $id = array();
-      $addedTag = CRM_Core_BAO_Tag::add($tagParams, $id);
+      $addedTag = CRM_Core_BAO_Tag::add($tagParams);
       $tag[$addedTag->id] = 1;
     }
     //add Tag to Import
 
     if (is_array($tag)) {
 
-      $tagAdditions = array();
+      $tagAdditions = [];
       foreach ($tag as $tagId => $val) {
         $addTagCount = CRM_Core_BAO_EntityTag::addContactsToTag($contactIds, $tagId);
         if (!empty($relatedContactIds)) {
@@ -556,7 +527,7 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
 
     $errorStack = CRM_Core_Error::singleton();
     $errors = $errorStack->getErrors();
-    $errorMessage = array();
+    $errorMessage = [];
 
     if (is_array($errors)) {
       foreach ($errors as $key => $value) {
diff --git a/civicrm/CRM/Contact/Import/ImportJob.php b/civicrm/CRM/Contact/Import/ImportJob.php
index 81e875b502..7940288294 100644
--- a/civicrm/CRM/Contact/Import/ImportJob.php
+++ b/civicrm/CRM/Contact/Import/ImportJob.php
@@ -42,7 +42,7 @@ class CRM_Contact_Import_ImportJob {
   protected $_allTags;
 
   protected $_mapper;
-  protected $_mapperKeys = array();
+  protected $_mapperKeys = [];
   protected $_mapFields;
 
   protected $_parser;
@@ -52,7 +52,7 @@ class CRM_Contact_Import_ImportJob {
    * @param null $createSql
    * @param bool $createTable
    *
-   * @throws Exception
+   * @throws \CRM_Core_Exception
    */
   public function __construct($tableName = NULL, $createSql = NULL, $createTable = FALSE) {
     $dao = new CRM_Core_DAO();
@@ -60,7 +60,7 @@ class CRM_Contact_Import_ImportJob {
 
     if ($createTable) {
       if (!$createSql) {
-        CRM_Core_Error::fatal('Either an existing table name or an SQL query to build one are required');
+        throw new CRM_Core_Exception(ts('Either an existing table name or an SQL query to build one are required'));
       }
 
       // FIXME: we should regen this table's name if it exists rather than drop it
@@ -72,7 +72,7 @@ class CRM_Contact_Import_ImportJob {
     }
 
     if (!$tableName) {
-      CRM_Core_Error::fatal('Import Table is required.');
+      throw new CRM_Core_Exception(ts('Import Table is required.'));
     }
 
     $this->_tableName = $tableName;
@@ -124,7 +124,7 @@ class CRM_Contact_Import_ImportJob {
    */
   public function runImport(&$form, $timeout = 55) {
     $mapper = $this->_mapper;
-    $mapperFields = array();
+    $mapperFields = [];
     $parserParameters = CRM_Contact_Import_Parser_Contact::getParameterForParser(count($mapper));
     $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
     $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
@@ -294,7 +294,7 @@ class CRM_Contact_Import_ImportJob {
 
     if ($newGroupName) {
       /* Create a new group */
-      $newGroupType = $newGroupType ?? array();
+      $newGroupType = $newGroupType ?? [];
       $gParams = array(
         'title' => $newGroupName,
         'description' => $newGroupDesc,
@@ -306,7 +306,7 @@ class CRM_Contact_Import_ImportJob {
     }
 
     if (is_array($this->_groups)) {
-      $groupAdditions = array();
+      $groupAdditions = [];
       foreach ($this->_groups as $groupId) {
         $addCount = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $groupId);
         $totalCount = $addCount[1];
@@ -355,14 +355,13 @@ class CRM_Contact_Import_ImportJob {
         'is_selectable' => TRUE,
         'used_for' => 'civicrm_contact',
       );
-      $id = array();
-      $addedTag = CRM_Core_BAO_Tag::add($tagParams, $id);
+      $addedTag = CRM_Core_BAO_Tag::add($tagParams);
       $this->_tag[$addedTag->id] = 1;
     }
     //add Tag to Import
 
     if (is_array($this->_tag)) {
-      $tagAdditions = array();
+      $tagAdditions = [];
       foreach ($this->_tag as $tagId => $val) {
         $addTagCount = CRM_Core_BAO_EntityTag::addEntitiesToTag($contactIds, $tagId, 'civicrm_contact', FALSE);
         $totalTagCount = $addTagCount[1];
diff --git a/civicrm/CRM/Contact/Import/Parser.php b/civicrm/CRM/Contact/Import/Parser.php
index 80d10ff586..4a4034037a 100644
--- a/civicrm/CRM/Contact/Import/Parser.php
+++ b/civicrm/CRM/Contact/Import/Parser.php
@@ -548,6 +548,11 @@ abstract class CRM_Contact_Import_Parser extends CRM_Import_Parser {
               'website_type_id' => $this->_activeFields[$i]->_relatedContactWebsiteType,
             ];
           }
+          elseif (empty($this->_activeFields[$i]->_value) && isset($this->_activeFields[$i]->_relatedContactLocType)) {
+            if (empty($params[$this->_activeFields[$i]->_related][$this->_activeFields[$i]->_relatedContactDetails])) {
+              $params[$this->_activeFields[$i]->_related][$this->_activeFields[$i]->_relatedContactDetails] = [];
+            }
+          }
           else {
             $params[$this->_activeFields[$i]->_related][$this->_activeFields[$i]->_relatedContactDetails] = $this->_activeFields[$i]->_value;
           }
@@ -832,6 +837,7 @@ abstract class CRM_Contact_Import_Parser extends CRM_Import_Parser {
               $this->formatLocationBlock($value, $formatted);
             }
             else {
+              // @todo - this is still reachable - e.g. import with related contact info like firstname,lastname,spouse-first-name,spouse-last-name,spouse-home-phone
               CRM_Core_Error::deprecatedFunctionWarning('this is not expected to be reachable now');
               $this->formatContactParameters($value, $formatted);
             }
diff --git a/civicrm/CRM/Contact/Import/Parser/Contact.php b/civicrm/CRM/Contact/Import/Parser/Contact.php
index bb4be04495..760d16059b 100644
--- a/civicrm/CRM/Contact/Import/Parser/Contact.php
+++ b/civicrm/CRM/Contact/Import/Parser/Contact.php
@@ -1167,7 +1167,10 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser {
         /* validate the data against the CF type */
 
         if ($value) {
-          if ($customFields[$customFieldID]['data_type'] == 'Date') {
+          $dataType = $customFields[$customFieldID]['data_type'];
+          $htmlType = $customFields[$customFieldID]['html_type'];
+          $isSerialized = CRM_Core_BAO_CustomField::isSerialized($customFields[$customFieldID]);
+          if ($dataType == 'Date') {
             if (array_key_exists($customFieldID, $addressCustomFields) && CRM_Utils_Date::convertToDefaultDate($params[$key][0], $dateType, $key)) {
               $value = $params[$key][0][$key];
             }
@@ -1178,29 +1181,26 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser {
               self::addToErrorMsg($customFields[$customFieldID]['label'], $errorMessage);
             }
           }
-          elseif ($customFields[$customFieldID]['data_type'] == 'Boolean') {
+          elseif ($dataType == 'Boolean') {
             if (CRM_Utils_String::strtoboolstr($value) === FALSE) {
               self::addToErrorMsg($customFields[$customFieldID]['label'] . '::' . $customFields[$customFieldID]['groupTitle'], $errorMessage);
             }
           }
           // need not check for label filed import
-          $htmlType = [
+          $selectHtmlTypes = [
             'CheckBox',
-            'Multi-Select',
             'Select',
             'Radio',
-            'Multi-Select State/Province',
-            'Multi-Select Country',
           ];
-          if (!in_array($customFields[$customFieldID]['html_type'], $htmlType) || $customFields[$customFieldID]['data_type'] == 'Boolean' || $customFields[$customFieldID]['data_type'] == 'ContactReference') {
-            $valid = CRM_Core_BAO_CustomValue::typecheck($customFields[$customFieldID]['data_type'], $value);
+          if ((!$isSerialized && !in_array($htmlType, $selectHtmlTypes)) || $dataType == 'Boolean' || $dataType == 'ContactReference') {
+            $valid = CRM_Core_BAO_CustomValue::typecheck($dataType, $value);
             if (!$valid) {
               self::addToErrorMsg($customFields[$customFieldID]['label'], $errorMessage);
             }
           }
 
           // check for values for custom fields for checkboxes and multiselect
-          if ($customFields[$customFieldID]['html_type'] == 'CheckBox' || $customFields[$customFieldID]['html_type'] == 'Multi-Select') {
+          if ($isSerialized) {
             $value = trim($value);
             $value = str_replace('|', ',', $value);
             $mulValues = explode(',', $value);
@@ -1222,7 +1222,7 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser {
               }
             }
           }
-          elseif ($customFields[$customFieldID]['html_type'] == 'Select' || ($customFields[$customFieldID]['html_type'] == 'Radio' && $customFields[$customFieldID]['data_type'] != 'Boolean')) {
+          elseif ($htmlType == 'Select' || ($htmlType == 'Radio' && $dataType != 'Boolean')) {
             $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE);
             $flag = FALSE;
             foreach ($customOption as $v2) {
@@ -1234,7 +1234,7 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser {
               self::addToErrorMsg($customFields[$customFieldID]['label'], $errorMessage);
             }
           }
-          elseif ($customFields[$customFieldID]['html_type'] == 'Multi-Select State/Province') {
+          elseif ($isSerialized && $dataType === 'StateProvince') {
             $mulValues = explode(',', $value);
             foreach ($mulValues as $stateValue) {
               if ($stateValue) {
@@ -1247,7 +1247,7 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser {
               }
             }
           }
-          elseif ($customFields[$customFieldID]['html_type'] == 'Multi-Select Country') {
+          elseif ($isSerialized && $dataType == 'Country') {
             $mulValues = explode(',', $value);
             foreach ($mulValues as $countryValue) {
               if ($countryValue) {
diff --git a/civicrm/CRM/Contact/Page/Inline/Actions.php b/civicrm/CRM/Contact/Page/Inline/Actions.php
index 136e8e71ed..ef91f017d8 100644
--- a/civicrm/CRM/Contact/Page/Inline/Actions.php
+++ b/civicrm/CRM/Contact/Page/Inline/Actions.php
@@ -26,7 +26,7 @@ class CRM_Contact_Page_Inline_Actions extends CRM_Core_Page {
    * This method is called after the page is created.
    */
   public function run() {
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
 
     $this->assign('contactId', $contactId);
     $this->assign('actionsMenuList', CRM_Contact_BAO_Contact::contextMenu($contactId));
diff --git a/civicrm/CRM/Contact/Page/Inline/Address.php b/civicrm/CRM/Contact/Page/Inline/Address.php
index 99ee03591c..ce179303e0 100644
--- a/civicrm/CRM/Contact/Page/Inline/Address.php
+++ b/civicrm/CRM/Contact/Page/Inline/Address.php
@@ -27,9 +27,9 @@ class CRM_Contact_Page_Inline_Address extends CRM_Core_Page {
    */
   public function run() {
     // get the emails for this contact
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
-    $locBlockNo = CRM_Utils_Request::retrieve('locno', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
-    $addressId = CRM_Utils_Request::retrieve('aid', 'Positive', CRM_Core_DAO::$_nullObject, FALSE, NULL, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
+    $locBlockNo = CRM_Utils_Request::retrieve('locno', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
+    $addressId = CRM_Utils_Request::retrieve('aid', 'Positive');
 
     $address = [];
     if ($addressId > 0) {
diff --git a/civicrm/CRM/Contact/Page/Inline/ContactInfo.php b/civicrm/CRM/Contact/Page/Inline/ContactInfo.php
index 9243a5fde9..9dad262779 100644
--- a/civicrm/CRM/Contact/Page/Inline/ContactInfo.php
+++ b/civicrm/CRM/Contact/Page/Inline/ContactInfo.php
@@ -27,7 +27,7 @@ class CRM_Contact_Page_Inline_ContactInfo extends CRM_Core_Page {
    */
   public function run() {
     // get the emails for this contact
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
 
     $params = ['id' => $contactId];
 
diff --git a/civicrm/CRM/Contact/Page/Inline/ContactName.php b/civicrm/CRM/Contact/Page/Inline/ContactName.php
index 4e7e7a960c..aef76c6834 100644
--- a/civicrm/CRM/Contact/Page/Inline/ContactName.php
+++ b/civicrm/CRM/Contact/Page/Inline/ContactName.php
@@ -27,7 +27,7 @@ class CRM_Contact_Page_Inline_ContactName extends CRM_Core_Page {
    */
   public function run() {
     // get the emails for this contact
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
 
     $isDeleted = (bool) CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactId, 'is_deleted');
 
diff --git a/civicrm/CRM/Contact/Page/Inline/CustomData.php b/civicrm/CRM/Contact/Page/Inline/CustomData.php
index a2ffabdfd7..8dd50fd786 100644
--- a/civicrm/CRM/Contact/Page/Inline/CustomData.php
+++ b/civicrm/CRM/Contact/Page/Inline/CustomData.php
@@ -27,10 +27,10 @@ class CRM_Contact_Page_Inline_CustomData extends CRM_Core_Page {
    */
   public function run() {
     // get the emails for this contact
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
-    $cgId = CRM_Utils_Request::retrieve('groupID', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
-    $customRecId = CRM_Utils_Request::retrieve('customRecId', 'Positive', CRM_Core_DAO::$_nullObject, FALSE, 1, $_REQUEST);
-    $cgcount = CRM_Utils_Request::retrieve('cgcount', 'Positive', CRM_Core_DAO::$_nullObject, FALSE, 1, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
+    $cgId = CRM_Utils_Request::retrieve('groupID', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
+    $customRecId = CRM_Utils_Request::retrieve('customRecId', 'Positive', CRM_Core_DAO::$_nullObject, FALSE, 1);
+    $cgcount = CRM_Utils_Request::retrieve('cgcount', 'Positive', CRM_Core_DAO::$_nullObject, FALSE, 1);
 
     //custom groups Inline
     $entityType = CRM_Contact_BAO_Contact::getContactType($contactId);
diff --git a/civicrm/CRM/Contact/Page/Inline/Demographics.php b/civicrm/CRM/Contact/Page/Inline/Demographics.php
index b211df4dcf..e3a714872f 100644
--- a/civicrm/CRM/Contact/Page/Inline/Demographics.php
+++ b/civicrm/CRM/Contact/Page/Inline/Demographics.php
@@ -27,7 +27,7 @@ class CRM_Contact_Page_Inline_Demographics extends CRM_Core_Page {
    */
   public function run() {
     // get the emails for this contact
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
 
     $params = ['id' => $contactId];
 
diff --git a/civicrm/CRM/Contact/Page/Inline/Email.php b/civicrm/CRM/Contact/Page/Inline/Email.php
index 8b4fed55d7..7ca97943c1 100644
--- a/civicrm/CRM/Contact/Page/Inline/Email.php
+++ b/civicrm/CRM/Contact/Page/Inline/Email.php
@@ -27,7 +27,7 @@ class CRM_Contact_Page_Inline_Email extends CRM_Core_Page {
    */
   public function run() {
     // get the emails for this contact
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
 
     $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', ['labelColumn' => 'display_name']);
 
diff --git a/civicrm/CRM/Contact/Page/Inline/IM.php b/civicrm/CRM/Contact/Page/Inline/IM.php
index 8882d5ba6d..e20782a326 100644
--- a/civicrm/CRM/Contact/Page/Inline/IM.php
+++ b/civicrm/CRM/Contact/Page/Inline/IM.php
@@ -27,7 +27,7 @@ class CRM_Contact_Page_Inline_IM extends CRM_Core_Page {
    */
   public function run() {
     // get the emails for this contact
-    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE, NULL, $_REQUEST);
+    $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
 
     $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', ['labelColumn' => 'display_name']);
     $IMProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
diff --git a/civicrm/CRM/Contact/Page/View/Relationship.php b/civicrm/CRM/Contact/Page/View/Relationship.php
index ed03a112dd..c1d88ae79c 100644
--- a/civicrm/CRM/Contact/Page/View/Relationship.php
+++ b/civicrm/CRM/Contact/Page/View/Relationship.php
@@ -104,7 +104,7 @@ class CRM_Contact_Page_View_Relationship extends CRM_Core_Page {
     );
 
     $session = CRM_Core_Session::singleton();
-    $recentOther = array();
+    $recentOther = [];
 
     if (($session->get('userID') == $this->getContactId()) ||
       CRM_Contact_BAO_Contact_Permission::allow($this->getContactId(), CRM_Core_Permission::EDIT)
diff --git a/civicrm/CRM/Contact/Page/View/Summary.php b/civicrm/CRM/Contact/Page/View/Summary.php
index f411a21c42..7861eb1491 100644
--- a/civicrm/CRM/Contact/Page/View/Summary.php
+++ b/civicrm/CRM/Contact/Page/View/Summary.php
@@ -114,8 +114,8 @@ class CRM_Contact_Page_View_Summary extends CRM_Contact_Page_View {
     $session->pushUserContext($url);
     $this->assignFieldMetadataToTemplate('Contact');
 
-    $params = array();
-    $defaults = array();
+    $params = [];
+    $defaults = [];
 
     $params['id'] = $params['contact_id'] = $this->_contactId;
     $params['noRelationships'] = $params['noNotes'] = $params['noGroups'] = TRUE;
@@ -218,7 +218,7 @@ class CRM_Contact_Page_View_Summary extends CRM_Contact_Page_View {
     }
 
     // get contact name of shared contact names
-    $sharedAddresses = array();
+    $sharedAddresses = [];
     $shareAddressContactNames = CRM_Contact_BAO_Contact_Utils::getAddressShareContactNames($defaults['address']);
     foreach ($defaults['address'] as $key => $addressValue) {
       if (!empty($addressValue['master_id']) &&
@@ -274,7 +274,7 @@ class CRM_Contact_Page_View_Summary extends CRM_Contact_Page_View {
    */
   public function getTemplateFileName() {
     if ($this->_contactId) {
-      $contactSubtypes = $this->get('contactSubtype') ? explode(CRM_Core_DAO::VALUE_SEPARATOR, $this->get('contactSubtype')) : array();
+      $contactSubtypes = $this->get('contactSubtype') ? explode(CRM_Core_DAO::VALUE_SEPARATOR, $this->get('contactSubtype')) : [];
 
       // there could be multiple subtypes. We check templates for each of the subtype, and return the first one found.
       foreach ($contactSubtypes as $csType) {
diff --git a/civicrm/CRM/Contact/Selector.php b/civicrm/CRM/Contact/Selector.php
index 0e1c82f78c..2296ddd2e4 100644
--- a/civicrm/CRM/Contact/Selector.php
+++ b/civicrm/CRM/Contact/Selector.php
@@ -61,6 +61,7 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     'status',
     'do_not_email',
     'do_not_phone',
+    'do_not_sms',
     'do_not_mail',
   ];
 
diff --git a/civicrm/CRM/Contact/Task.php b/civicrm/CRM/Contact/Task.php
index e4cac5e862..9498e45db2 100644
--- a/civicrm/CRM/Contact/Task.php
+++ b/civicrm/CRM/Contact/Task.php
@@ -262,12 +262,12 @@ class CRM_Contact_Task extends CRM_Core_Task {
    * @return array
    *   set of tasks that are valid for the user
    */
-  public static function permissionedTaskTitles($permission, $params = array()) {
+  public static function permissionedTaskTitles($permission, $params = []) {
     if (!isset($params['deletedContacts'])) {
       $params['deletedContacts'] = FALSE;
     }
     self::tasks();
-    $tasks = array();
+    $tasks = [];
     if ($params['deletedContacts']) {
       if (CRM_Core_Permission::check('access deleted contacts')) {
         $tasks[self::RESTORE] = self::$_tasks[self::RESTORE]['title'];
diff --git a/civicrm/CRM/Contribute/BAO/Contribution.php b/civicrm/CRM/Contribute/BAO/Contribution.php
index 48b01b3e6c..655a9c63ac 100644
--- a/civicrm/CRM/Contribute/BAO/Contribution.php
+++ b/civicrm/CRM/Contribute/BAO/Contribution.php
@@ -835,6 +835,8 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
         CRM_Core_BAO_CustomField::getFieldsForImport('Contribution', FALSE, FALSE, FALSE, $checkPermission)
       );
 
+      $fields['financial_type_id']['title'] = ts('Financial Type ID');
+
       self::$_exportableFields = $fields;
     }
 
@@ -1290,7 +1292,8 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
       if (empty($resultDAO->payment_processor_id) && CRM_Core_Permission::check('edit contributions')) {
         $links = [
           CRM_Core_Action::UPDATE => [
-            'name' => "<i class='crm-i fa-pencil'></i>",
+            'name' => ts('Edit Payment'),
+            'icon' => 'fa-pencil',
             'url' => 'civicrm/payment/edit',
             'class' => 'medium-popup',
             'qs' => "reset=1&id=%%id%%&contribution_id=%%contribution_id%%",
@@ -2755,7 +2758,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
    * @return bool
    * @throws Exception
    */
-  public function loadRelatedObjects(&$input, &$ids, $loadAll = FALSE) {
+  public function loadRelatedObjects($input, &$ids, $loadAll = FALSE) {
     // @todo deprecate this function - the steps should be
     // 1) add additional functions like 'getRelatedMemberships'
     // 2) switch all calls that refer to ->_relatedObjects to
@@ -3679,6 +3682,10 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
           $newFinancialAccount = CRM_Financial_BAO_FinancialAccount::getFinancialAccountForFinancialTypeByRelationship($params['financial_type_id'], $accountRelationship);
           if ($oldFinancialAccount != $newFinancialAccount) {
             $params['total_amount'] = 0;
+            // If we have a fee amount set reverse this as well.
+            if (isset($params['fee_amount'])) {
+              $params['trxnParams']['fee_amount'] = 0 - $params['fee_amount'];
+            }
             if (in_array($params['contribution']->contribution_status_id, $pendingStatus)) {
               $params['trxnParams']['to_financial_account_id'] = CRM_Financial_BAO_FinancialAccount::getFinancialAccountForFinancialTypeByRelationship(
                 $params['prevContribution']->financial_type_id, $accountRelationship);
@@ -3700,6 +3707,10 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
             /* $params['trxnParams']['to_financial_account_id'] = $trxnParams['to_financial_account_id']; */
             $params['financial_account_id'] = $newFinancialAccount;
             $params['total_amount'] = $params['trxnParams']['total_amount'] = $params['trxnParams']['net_amount'] = $trxnParams['total_amount'];
+            // Set the transaction fee amount back to the original value for creating the new positive financial trxn.
+            if (isset($params['fee_amount'])) {
+              $params['trxnParams']['fee_amount'] = $params['fee_amount'];
+            }
             self::updateFinancialAccounts($params);
             CRM_Core_BAO_FinancialTrxn::createDeferredTrxn(CRM_Utils_Array::value('line_item', $params), $params['contribution'], TRUE);
             $params['trxnParams']['to_financial_account_id'] = $trxnParams['to_financial_account_id'];
diff --git a/civicrm/CRM/Contribute/BAO/ContributionRecur.php b/civicrm/CRM/Contribute/BAO/ContributionRecur.php
index b83716daa1..5862d4b777 100644
--- a/civicrm/CRM/Contribute/BAO/ContributionRecur.php
+++ b/civicrm/CRM/Contribute/BAO/ContributionRecur.php
@@ -326,9 +326,12 @@ class CRM_Contribute_BAO_ContributionRecur extends CRM_Contribute_DAO_Contributi
    * @return null|Object
    */
   public static function getSubscriptionDetails($entityID, $entity = 'recur') {
+    // Note: processor_id used to be aliased as subscription_id so we include it here
+    // both as processor_id and subscription_id for legacy compatibility.
     $sql = "
 SELECT rec.id                   as recur_id,
        rec.processor_id         as subscription_id,
+       rec.processor_id,
        rec.frequency_interval,
        rec.installments,
        rec.frequency_unit,
@@ -442,7 +445,8 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
     if ($templateContributions->count()) {
       $templateContribution = $templateContributions->first();
       $result = array_merge($templateContribution, $overrides);
-      $result['line_item'] = CRM_Contribute_BAO_ContributionRecur::calculateRecurLineItems($id, $result['total_amount'], $result['financial_type_id']);
+      $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($templateContribution['id']);
+      $result['line_item'] = self::reformatLineItemsForRepeatContribution($result['total_amount'], $result['financial_type_id'], $lineItems, (array) $templateContribution);
       return $result;
     }
     return [];
@@ -613,6 +617,8 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
    * @param \CRM_Contribute_BAO_Contribution $contribution
    *
    * @return array
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   public static function addRecurLineItems($recurId, $contribution) {
     $foundLineItems = FALSE;
@@ -901,6 +907,7 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
    * @param int $financial_type_id
    *
    * @return array
+   * @throws \CiviCRM_API3_Exception
    */
   public static function calculateRecurLineItems($recurId, $total_amount, $financial_type_id) {
     $originalContribution = civicrm_api3('Contribution', 'getsingle', [
@@ -910,41 +917,7 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
       'return' => ['id', 'financial_type_id'],
     ]);
     $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($originalContribution['id']);
-    $lineSets = [];
-    if (count($lineItems) == 1) {
-      foreach ($lineItems as $index => $lineItem) {
-        if ($lineItem['financial_type_id'] != $originalContribution['financial_type_id']) {
-          // CRM-20685, Repeattransaction produces incorrect Financial Type ID (in specific circumstance) - if number of lineItems = 1, So this conditional will set the financial_type_id as the original if line_item and contribution comes with different data.
-          $financial_type_id = $lineItem['financial_type_id'];
-        }
-        if ($financial_type_id) {
-          // CRM-17718 allow for possibility of changed financial type ID having been set prior to calling this.
-          $lineItem['financial_type_id'] = $financial_type_id;
-        }
-        $taxAmountMatches = FALSE;
-        if ((!empty($lineItem['tax_amount']) && ($lineItem['line_total'] + $lineItem['tax_amount']) == $total_amount)) {
-          $taxAmountMatches = TRUE;
-        }
-        if ($lineItem['line_total'] != $total_amount && !$taxAmountMatches) {
-          // We are dealing with a changed amount! Per CRM-16397 we can work out what to do with these
-          // if there is only one line item, and the UI should prevent this situation for those with more than one.
-          $lineItem['line_total'] = $total_amount;
-          $lineItem['unit_price'] = round($total_amount / $lineItem['qty'], 2);
-        }
-        $priceField = new CRM_Price_DAO_PriceField();
-        $priceField->id = $lineItem['price_field_id'];
-        $priceField->find(TRUE);
-        $lineSets[$priceField->price_set_id][$lineItem['price_field_id']] = $lineItem;
-      }
-    }
-    // CRM-19309 if more than one then just pass them through:
-    elseif (count($lineItems) > 1) {
-      foreach ($lineItems as $index => $lineItem) {
-        $lineSets[$index][$lineItem['price_field_id']] = $lineItem;
-      }
-    }
-
-    return $lineSets;
+    return self::reformatLineItemsForRepeatContribution($total_amount, $financial_type_id, $lineItems, $originalContribution);
   }
 
   /**
@@ -989,4 +962,53 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
     return CRM_Core_PseudoConstant::get(__CLASS__, $fieldName, $params, $context);
   }
 
+  /**
+   * Reformat line items for getTemplateContribution / repeat contribution.
+   *
+   * This is an extraction and may be subject to further cleanup.
+   *
+   * @param float $total_amount
+   * @param int $financial_type_id
+   * @param array $lineItems
+   * @param array $originalContribution
+   *
+   * @return array
+   */
+  protected static function reformatLineItemsForRepeatContribution($total_amount, $financial_type_id, array $lineItems, array $originalContribution): array {
+    $lineSets = [];
+    if (count($lineItems) == 1) {
+      foreach ($lineItems as $index => $lineItem) {
+        if ($lineItem['financial_type_id'] != $originalContribution['financial_type_id']) {
+          // CRM-20685, Repeattransaction produces incorrect Financial Type ID (in specific circumstance) - if number of lineItems = 1, So this conditional will set the financial_type_id as the original if line_item and contribution comes with different data.
+          $financial_type_id = $lineItem['financial_type_id'];
+        }
+        if ($financial_type_id) {
+          // CRM-17718 allow for possibility of changed financial type ID having been set prior to calling this.
+          $lineItem['financial_type_id'] = $financial_type_id;
+        }
+        $taxAmountMatches = FALSE;
+        if ((!empty($lineItem['tax_amount']) && ($lineItem['line_total'] + $lineItem['tax_amount']) == $total_amount)) {
+          $taxAmountMatches = TRUE;
+        }
+        if ($lineItem['line_total'] != $total_amount && !$taxAmountMatches) {
+          // We are dealing with a changed amount! Per CRM-16397 we can work out what to do with these
+          // if there is only one line item, and the UI should prevent this situation for those with more than one.
+          $lineItem['line_total'] = $total_amount;
+          $lineItem['unit_price'] = round($total_amount / $lineItem['qty'], 2);
+        }
+        $priceField = new CRM_Price_DAO_PriceField();
+        $priceField->id = $lineItem['price_field_id'];
+        $priceField->find(TRUE);
+        $lineSets[$priceField->price_set_id][$lineItem['price_field_id']] = $lineItem;
+      }
+    }
+    // CRM-19309 if more than one then just pass them through:
+    elseif (count($lineItems) > 1) {
+      foreach ($lineItems as $index => $lineItem) {
+        $lineSets[$index][$lineItem['price_field_id']] = $lineItem;
+      }
+    }
+    return $lineSets;
+  }
+
 }
diff --git a/civicrm/CRM/Contribute/BAO/Query.php b/civicrm/CRM/Contribute/BAO/Query.php
index c0f5e17f9a..2925909aff 100644
--- a/civicrm/CRM/Contribute/BAO/Query.php
+++ b/civicrm/CRM/Contribute/BAO/Query.php
@@ -893,8 +893,10 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query {
       'receive_date',
       'contribution_cancel_date',
       'contribution_page_id',
+      'contribution_id',
     ];
     $metadata = civicrm_api3('Contribution', 'getfields', [])['values'];
+    $metadata['contribution_id'] = $metadata['id'];
     return array_intersect_key($metadata, array_flip($fields));
   }
 
@@ -960,7 +962,6 @@ class CRM_Contribute_BAO_Query extends CRM_Core_BAO_Query {
     $form->addYesNo('contribution_recurring', ts('Contribution is Recurring?'), TRUE);
 
     $form->addYesNo('contribution_test', ts('Contribution is a Test?'), TRUE);
-
     // Add field for transaction ID search
     $form->addElement('text', 'contribution_trxn_id', ts("Transaction ID"));
     $form->addElement('text', 'contribution_check_number', ts('Check Number'));
diff --git a/civicrm/CRM/Contribute/DAO/Contribution.php b/civicrm/CRM/Contribute/DAO/Contribution.php
index d56ce8b8c6..8d736f25f1 100644
--- a/civicrm/CRM/Contribute/DAO/Contribution.php
+++ b/civicrm/CRM/Contribute/DAO/Contribution.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Contribute/Contribution.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:389ae44affe94e52a14c9c6daa79be1d)
+ * (GenCodeChecksum:0954aa2ae3574927fda6614f14168fc8)
  */
 
 /**
@@ -282,6 +282,9 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO {
           'entity' => 'Contribution',
           'bao' => 'CRM_Contribute_BAO_Contribution',
           'localizable' => 0,
+          'html' => [
+            'type' => 'Text',
+          ],
         ],
         'contribution_contact_id' => [
           'name' => 'contact_id',
diff --git a/civicrm/CRM/Contribute/DAO/ContributionRecur.php b/civicrm/CRM/Contribute/DAO/ContributionRecur.php
index 060a304ed0..192721f6e6 100644
--- a/civicrm/CRM/Contribute/DAO/ContributionRecur.php
+++ b/civicrm/CRM/Contribute/DAO/ContributionRecur.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Contribute/ContributionRecur.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:d0c493bb1a98e2b75ebaceb330a40fb4)
+ * (GenCodeChecksum:1c6a0e2a296ffbb530eee381975b9d17)
  */
 
 /**
@@ -43,7 +43,7 @@ class CRM_Contribute_DAO_ContributionRecur extends CRM_Core_DAO {
   public $contact_id;
 
   /**
-   * Amount to be contributed or charged each recurrence.
+   * Amount to be collected (including any sales tax) by payment processor each recurrence.
    *
    * @var float
    */
@@ -294,7 +294,7 @@ class CRM_Contribute_DAO_ContributionRecur extends CRM_Core_DAO {
           'name' => 'amount',
           'type' => CRM_Utils_Type::T_MONEY,
           'title' => ts('Amount'),
-          'description' => ts('Amount to be contributed or charged each recurrence.'),
+          'description' => ts('Amount to be collected (including any sales tax) by payment processor each recurrence.'),
           'required' => TRUE,
           'precision' => [
             20,
diff --git a/civicrm/CRM/Contribute/Form/AbstractEditPayment.php b/civicrm/CRM/Contribute/Form/AbstractEditPayment.php
index 57e1e5a845..fd7447efd8 100644
--- a/civicrm/CRM/Contribute/Form/AbstractEditPayment.php
+++ b/civicrm/CRM/Contribute/Form/AbstractEditPayment.php
@@ -148,13 +148,6 @@ class CRM_Contribute_Form_AbstractEditPayment extends CRM_Contact_Form_Task {
    */
   public $_honorID = NULL;
 
-  /**
-   * Store the financial Type ID
-   *
-   * @var array
-   */
-  public $_contributionType;
-
   /**
    * The contribution values if an existing contribution
    * @var array
@@ -289,7 +282,6 @@ class CRM_Contribute_Form_AbstractEditPayment extends CRM_Contact_Form_Task {
       $this->_noteID = $daoNote->id;
       $values['note'] = $daoNote->note;
     }
-    $this->_contributionType = $values['financial_type_id'];
   }
 
   /**
diff --git a/civicrm/CRM/Contribute/Form/CancelSubscription.php b/civicrm/CRM/Contribute/Form/CancelSubscription.php
index 831b5e9b55..3cd63518c9 100644
--- a/civicrm/CRM/Contribute/Form/CancelSubscription.php
+++ b/civicrm/CRM/Contribute/Form/CancelSubscription.php
@@ -133,8 +133,7 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
   public function buildQuickForm() {
     $this->buildQuickEntityForm();
     // Determine if we can cancel recurring contribution via API with this processor
-    $cancelSupported = $this->_paymentProcessorObj->supports('CancelRecurring');
-    if ($cancelSupported) {
+    if ($this->_paymentProcessorObj->supports('CancelRecurringNotifyOptional')) {
       $searchRange = [];
       $searchRange[] = $this->createElement('radio', NULL, NULL, ts('Yes'), '1');
       $searchRange[] = $this->createElement('radio', NULL, NULL, ts('No'), '0');
@@ -149,7 +148,6 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
     else {
       $this->assign('cancelRecurNotSupportedText', $this->_paymentProcessorObj->getText('cancelRecurNotSupportedText', []));
     }
-    $this->assign('cancelSupported', $cancelSupported);
 
     if (!empty($this->_donorEmail)) {
       $this->add('checkbox', 'is_notify', ts('Notify Contributor?') . " ({$this->_donorEmail})");
@@ -195,6 +193,8 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
 
   /**
    * Process the form submission.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function postProcess() {
     $message = NULL;
@@ -212,16 +212,17 @@ class CRM_Contribute_Form_CancelSubscription extends CRM_Contribute_Form_Contrib
       }
     }
 
-    if (CRM_Utils_Array::value('send_cancel_request', $params) == 1) {
-      try {
-        $propertyBag = new PropertyBag();
-        $propertyBag->setContributionRecurID($this->getSubscriptionDetails()->recur_id);
-        $propertyBag->setRecurProcessorID($this->getSubscriptionDetails()->subscription_id);
-        $message = $this->_paymentProcessorObj->doCancelRecurring($propertyBag)['message'];
-      }
-      catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
-        CRM_Core_Error::statusBounce($e->getMessage());
+    try {
+      $propertyBag = new PropertyBag();
+      if (isset($params['send_cancel_request'])) {
+        $propertyBag->setIsNotifyProcessorOnCancelRecur(!empty($params['send_cancel_request']));
       }
+      $propertyBag->setContributionRecurID($this->getSubscriptionDetails()->recur_id);
+      $propertyBag->setRecurProcessorID($this->getSubscriptionDetails()->processor_id);
+      $message = $this->_paymentProcessorObj->doCancelRecurring($propertyBag)['message'];
+    }
+    catch (\Civi\Payment\Exception\PaymentProcessorException $e) {
+      CRM_Core_Error::statusBounce($e->getMessage());
     }
 
     if ($cancelSubscription) {
diff --git a/civicrm/CRM/Contribute/Form/Contribution.php b/civicrm/CRM/Contribute/Form/Contribution.php
index b3a7e36cfe..b063ed269d 100644
--- a/civicrm/CRM/Contribute/Form/Contribution.php
+++ b/civicrm/CRM/Contribute/Form/Contribution.php
@@ -77,13 +77,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
    */
   public $_params;
 
-  /**
-   * Store the contribution Type ID
-   *
-   * @var array
-   */
-  public $_contributionType;
-
   /**
    * The contribution values if an existing contribution
    * @var array
@@ -277,7 +270,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     // when custom data is included in this page
     if (!empty($_POST['hidden_custom'])) {
-      $this->applyCustomData('Contribution', CRM_Utils_Array::value('financial_type_id', $_POST), $this->_id);
+      $this->applyCustomData('Contribution', $this->getFinancialTypeID(), $this->_id);
     }
 
     $this->_lineItems = [];
@@ -382,10 +375,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
     }
 
-    if ($this->_contributionType) {
-      $defaults['financial_type_id'] = $this->_contributionType;
-    }
-
     if (empty($defaults['payment_instrument_id'])) {
       $defaults['payment_instrument_id'] = $this->getDefaultPaymentInstrumentId();
     }
@@ -612,7 +601,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     //need to assign custom data type and subtype to the template
     $this->assign('customDataType', 'Contribution');
-    $this->assign('customDataSubType', $this->_contributionType);
+    $this->assign('customDataSubType', $this->getFinancialTypeID());
     $this->assign('entityID', $this->_id);
 
     $contactField = $this->addEntityRef('contact_id', ts('Contributor'), ['create' => TRUE, 'api' => ['extra' => ['email']]], TRUE);
@@ -1737,7 +1726,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         $this->assign('totalTaxAmount', $submittedValues['tax_amount']);
         $this->assign('getTaxDetails', $getTaxDetails);
         $this->assign('dataArray', $taxRate);
-        $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings));
+        $this->assign('taxTerm', Civi::settings()->get('tax_term'));
       }
       else {
         $this->assign('totalTaxAmount', CRM_Utils_Array::value('tax_amount', $submittedValues));
@@ -1808,4 +1797,21 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     return 0;
   }
 
+  /**
+   * Get the financial Type ID for the contribution either from the submitted values or from the contribution values if possible.
+   *
+   * This is important for dev/core#1728 - ie ensure that if we are returned to the form for a form
+   * error that any custom fields based on the selected financial type are loaded.
+   *
+   * @return int
+   */
+  protected function getFinancialTypeID() {
+    if (!empty($this->_submitValues['financial_type_id'])) {
+      return $this->_submitValues['financial_type_id'];
+    }
+    if (!empty($this->_values['financial_type_id'])) {
+      return $this->_values['financial_type_id'];
+    }
+  }
+
 }
diff --git a/civicrm/CRM/Contribute/Form/Contribution/Main.php b/civicrm/CRM/Contribute/Form/Contribution/Main.php
index 12cb2813df..b55883cbee 100644
--- a/civicrm/CRM/Contribute/Form/Contribution/Main.php
+++ b/civicrm/CRM/Contribute/Form/Contribution/Main.php
@@ -479,10 +479,14 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     if (!($allAreBillingModeProcessors && !$this->_values['is_pay_later'])) {
       $submitButton = [
         'type' => 'upload',
-        'name' => !empty($this->_values['is_confirm_enabled']) ? ts('Review your contribution') : ts('Contribute'),
+        'name' => ts('Contribute'),
         'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
         'isDefault' => TRUE,
       ];
+      if (!empty($this->_values['is_confirm_enabled'])) {
+        $submitButton['name'] = ts('Review your contribution');
+        $submitButton['icon'] = 'fa-chevron-right';
+      }
       // Add submit-once behavior when confirm page disabled
       if (empty($this->_values['is_confirm_enabled'])) {
         $this->submitOnce = TRUE;
diff --git a/civicrm/CRM/Contribute/Form/ContributionBase.php b/civicrm/CRM/Contribute/Form/ContributionBase.php
index db2870fa14..ca2805d551 100644
--- a/civicrm/CRM/Contribute/Form/ContributionBase.php
+++ b/civicrm/CRM/Contribute/Form/ContributionBase.php
@@ -371,12 +371,12 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
         $postProfileType = CRM_Core_BAO_UFField::getProfileType($this->_values['custom_post_id']);
       }
 
-      if (((isset($postProfileType) && $postProfileType == 'Membership') ||
-          (isset($preProfileType) && $preProfileType == 'Membership')
+      if (((isset($postProfileType) && $postProfileType === 'Membership') ||
+          (isset($preProfileType) && $preProfileType === 'Membership')
         ) &&
         !$this->_membershipBlock['is_active']
       ) {
-        CRM_Core_Error::fatal(ts('This page includes a Profile with Membership fields - but the Membership Block is NOT enabled. Please notify the site administrator.'));
+        CRM_Core_Error::statusBounce(ts('This page includes a Profile with Membership fields - but the Membership Block is NOT enabled. Please notify the site administrator.'));
       }
 
       $pledgeBlock = CRM_Pledge_BAO_PledgeBlock::getPledgeBlock($this->_id);
@@ -437,7 +437,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
       !$this->_membershipBlock['is_active'] &&
       !$this->_priceSetId
     ) {
-      CRM_Core_Error::fatal(ts('The requested online contribution page is missing a required Contribution Amount section or Membership section or Price Set. Please check with the site administrator for assistance.'));
+      CRM_Core_Error::statusBounce(ts('The requested online contribution page is missing a required Contribution Amount section or Membership section or Price Set. Please check with the site administrator for assistance.'));
     }
 
     if ($this->_values['amount_block_is_active']) {
@@ -577,7 +577,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     //Hence, assign the existing location type email by iterating through the params.
     if ($this->_emailExists && empty($this->_params["email-{$this->_bltID}"])) {
       foreach ($this->_params as $key => $val) {
-        if (substr($key, 0, 6) == 'email-') {
+        if (substr($key, 0, 6) === 'email-') {
           $this->assign('email', $this->_params[$key]);
           break;
         }
@@ -749,6 +749,12 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     CRM_Utils_ReCAPTCHA::enableCaptchaOnForm($this);
   }
 
+  /**
+   * Assign payment field information to the template.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   */
   public function assignPaymentFields() {
     //fix for CRM-3767
     $isMonetary = FALSE;
@@ -765,7 +771,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     // The concept of contributeMode is deprecated.
     // The payment processor object can provide info about the fields it shows.
     if ($isMonetary && is_a($this->_paymentProcessor['object'], 'CRM_Core_Payment')) {
-      /** @var  $paymentProcessorObject \CRM_Core_Payment */
+      /** @var  \CRM_Core_Payment $paymentProcessorObject */
       $paymentProcessorObject = $this->_paymentProcessor['object'];
 
       $paymentFields = $paymentProcessorObject->getPaymentFormFields();
@@ -824,6 +830,8 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
    *
    * @param int $id
    * @param CRM_Core_Form $form
+   *
+   * @throws \CRM_Core_Exception
    */
   public function buildComponentForm($id, $form) {
     if (empty($id)) {
@@ -833,13 +841,13 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     $contactID = $this->getContactID();
 
     foreach (['soft_credit', 'on_behalf'] as $module) {
-      if ($module == 'soft_credit') {
+      if ($module === 'soft_credit') {
         if (empty($form->_values['honoree_profile_id'])) {
           continue;
         }
 
         if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $form->_values['honoree_profile_id'], 'is_active')) {
-          CRM_Core_Error::fatal(ts('This contribution page has been configured for contribution on behalf of honoree and the selected honoree profile is either disabled or not found.'));
+          CRM_Core_Error::statusBounce(ts('This contribution page has been configured for contribution on behalf of honoree and the selected honoree profile is either disabled or not found.'));
         }
 
         $profileContactType = CRM_Core_BAO_UFGroup::getContactType($form->_values['honoree_profile_id']);
@@ -850,7 +858,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
         ];
         $validProfile = CRM_Core_BAO_UFGroup::checkValidProfile($form->_values['honoree_profile_id'], $requiredProfileFields[$profileContactType]);
         if (!$validProfile) {
-          CRM_Core_Error::fatal(ts('This contribution page has been configured for contribution on behalf of honoree and the required fields of the selected honoree profile are disabled or doesn\'t exist.'));
+          CRM_Core_Error::statusBounce(ts('This contribution page has been configured for contribution on behalf of honoree and the required fields of the selected honoree profile are disabled or doesn\'t exist.'));
         }
 
         foreach (['honor_block_title', 'honor_block_text'] as $name) {
@@ -892,7 +900,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
         }
 
         if (!CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $form->_values['onbehalf_profile_id'], 'is_active')) {
-          CRM_Core_Error::fatal(ts('This contribution page has been configured for contribution on behalf of an organization and the selected onbehalf profile is either disabled or not found.'));
+          CRM_Core_Error::statusBounce(ts('This contribution page has been configured for contribution on behalf of an organization and the selected onbehalf profile is either disabled or not found.'));
         }
 
         $member = CRM_Member_BAO_Membership::getMembershipBlock($form->_id);
@@ -911,7 +919,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
                 in_array('Contribution', $onBehalfProfile)
               )
             ) {
-              CRM_Core_Error::fatal($msg);
+              CRM_Core_Error::statusBounce($msg);
             }
           }
         }
@@ -1031,7 +1039,7 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
    */
   public function getTemplateFileName() {
     $fileName = $this->checkTemplateFileExists();
-    return $fileName ? $fileName : parent::getTemplateFileName();
+    return $fileName ?: parent::getTemplateFileName();
   }
 
   /**
@@ -1049,6 +1057,8 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
 
   /**
    * Authenticate pledge user during online payment.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function authenticatePledgeUser() {
     //get the userChecksum and contact id
@@ -1087,12 +1097,12 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
     }
 
     if (!$validUser) {
-      CRM_Core_Error::fatal(ts("Oops. It looks like you have an incorrect or incomplete link (URL). Please make sure you've copied the entire link, and try again. Contact the site administrator if this error persists."));
+      CRM_Core_Error::statusBounce(ts("Oops. It looks like you have an incorrect or incomplete link (URL). Please make sure you've copied the entire link, and try again. Contact the site administrator if this error persists."));
     }
 
     //check for valid pledge status.
     if (!in_array($pledgeValues['status_id'], $validStatus)) {
-      CRM_Core_Error::fatal(ts('Oops. You cannot make a payment for this pledge - pledge status is %1.', [1 => CRM_Utils_Array::value($pledgeValues['status_id'], $allStatus)]));
+      CRM_Core_Error::statusBounce(ts('Oops. You cannot make a payment for this pledge - pledge status is %1.', [1 => CRM_Utils_Array::value($pledgeValues['status_id'], $allStatus)]));
     }
   }
 
@@ -1102,6 +1112,8 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
    * In case user cancel recurring contribution,
    * When we get the control back from payment gate way
    * lets delete the recurring and related contribution.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function cancelRecurring() {
     $isCancel = CRM_Utils_Request::retrieve('cancel', 'Boolean');
@@ -1135,6 +1147,9 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
    *
    * @return bool
    *   Is this a separate membership payment
+   *
+   * @throws \CiviCRM_API3_Exception
+   * @throws \CRM_Core_Exception
    */
   protected function buildMembershipBlock(
     $cid,
diff --git a/civicrm/CRM/Contribute/Form/Task/Status.php b/civicrm/CRM/Contribute/Form/Task/Status.php
index 09f1285c99..c8acc1e8ff 100644
--- a/civicrm/CRM/Contribute/Form/Task/Status.php
+++ b/civicrm/CRM/Contribute/Form/Task/Status.php
@@ -215,8 +215,6 @@ AND    co.id IN ( $contribIDs )";
     $statusID = $params['contribution_status_id'] ?? NULL;
     $baseIPN = new CRM_Core_Payment_BaseIPN();
 
-    $transaction = new CRM_Core_Transaction();
-
     // get the missing pieces for each contribution
     $contribIDs = implode(',', $form->_contributionIds);
     $details = self::getDetails($contribIDs);
@@ -246,11 +244,13 @@ AND    co.id IN ( $contribIDs )";
       );
 
       if ($statusID == array_search('Cancelled', $contributionStatuses)) {
+        $transaction = new CRM_Core_Transaction();
         $baseIPN->cancelled($objects, $transaction);
         $transaction->commit();
         continue;
       }
       elseif ($statusID == array_search('Failed', $contributionStatuses)) {
+        $transaction = new CRM_Core_Transaction();
         $baseIPN->failed($objects, $transaction);
         $transaction->commit();
         continue;
@@ -261,7 +261,6 @@ AND    co.id IN ( $contribIDs )";
           $contributionStatuses
         )
       ) {
-        $transaction->commit();
         continue;
       }
 
@@ -282,8 +281,8 @@ AND    co.id IN ( $contribIDs )";
       $input['trxn_date'] = $params["trxn_date_{$row['contribution_id']}"] . ' ' . date('H:i:s');
       $input['is_email_receipt'] = !empty($params['is_email_receipt']);
 
-      // @todo calling baseIPN like this is a pattern in it's last gasps. Call contribute.completetransaction api.
-      $baseIPN->completeTransaction($input, $ids, $objects, $transaction, FALSE);
+      // @todo calling CRM_Contribute_BAO_Contribution::completeOrder like this is a pattern in it's last gasps. Call contribute.completetransaction api.
+      CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects);
 
       // reset template values before processing next transactions
       $template->clearTemplateVars();
diff --git a/civicrm/CRM/Contribute/Form/UpdateBilling.php b/civicrm/CRM/Contribute/Form/UpdateBilling.php
index 1370802e54..b7d9e550f1 100644
--- a/civicrm/CRM/Contribute/Form/UpdateBilling.php
+++ b/civicrm/CRM/Contribute/Form/UpdateBilling.php
@@ -55,12 +55,12 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Contribute_Form_Contribution
     }
 
     if ((!$this->_crid && !$this->_coid && !$this->_mid) || (!$this->_subscriptionDetails)) {
-      CRM_Core_Error::fatal('Required information missing.');
+      throw new CRM_Core_Exception('Required information missing.');
     }
 
     if (!$this->_paymentProcessor['object']->supports('updateSubscriptionBillingInfo')) {
-      CRM_Core_Error::fatal(ts("%1 processor doesn't support updating subscription billing details.",
-        array(1 => $this->_paymentProcessor['object']->_processorName)
+      throw new CRM_Core_Exception(ts("%1 processor doesn't support updating subscription billing details.",
+        [1 => $this->_paymentProcessor['title']]
       ));
     }
     $this->assign('paymentProcessor', $this->_paymentProcessor);
@@ -84,10 +84,10 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Contribute_Form_Contribution
    *   Default values
    */
   public function setDefaultValues() {
-    $this->_defaults = array();
+    $this->_defaults = [];
 
     if ($this->_subscriptionDetails->contact_id) {
-      $fields = array();
+      $fields = [];
       $names = array(
         'first_name',
         'middle_name',
@@ -170,7 +170,7 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Contribute_Form_Contribution
    *   true if no errors, else array of errors
    */
   public static function formRule($fields, $files, $self) {
-    $errors = array();
+    $errors = [];
     CRM_Core_Form::validateMandatoryFields($self->_fields, $fields, $errors);
 
     // validate the payment instrument values (e.g. credit card number)
@@ -192,7 +192,7 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Contribute_Form_Contribution
     }
     $fields["email-{$this->_bltID}"] = 1;
 
-    $processorParams = array();
+    $processorParams = [];
     foreach ($params as $key => $val) {
       $key = str_replace('billing_', '', $key);
       list($key) = explode('-', $key);
@@ -202,7 +202,7 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Contribute_Form_Contribution
     $processorParams['country'] = CRM_Core_PseudoConstant::country($params["billing_country_id-{$this->_bltID}"], FALSE);
     $processorParams['month'] = $processorParams['credit_card_exp_date']['M'];
     $processorParams['year'] = $processorParams['credit_card_exp_date']['Y'];
-    $processorParams['subscriptionId'] = $this->_subscriptionDetails->subscription_id;
+    $processorParams['subscriptionId'] = $this->getSubscriptionDetails()->processor_id;
     $processorParams['amount'] = $this->_subscriptionDetails->amount;
     $updateSubscription = $this->_paymentProcessor['object']->updateSubscriptionBillingInfo($message, $processorParams);
     if (is_a($updateSubscription, 'CRM_Core_Error')) {
diff --git a/civicrm/CRM/Contribute/Form/UpdateSubscription.php b/civicrm/CRM/Contribute/Form/UpdateSubscription.php
index be18481f5e..51e218b99f 100644
--- a/civicrm/CRM/Contribute/Form/UpdateSubscription.php
+++ b/civicrm/CRM/Contribute/Form/UpdateSubscription.php
@@ -206,7 +206,7 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Contribute_Form_Contrib
     $params['id'] = $this->_subscriptionDetails->recur_id;
     $message = '';
 
-    $params['subscriptionId'] = $this->_subscriptionDetails->subscription_id;
+    $params['subscriptionId'] = $this->getSubscriptionDetails()->processor_id;
     $updateSubscription = TRUE;
     if ($this->_paymentProcessorObj->supports('changeSubscriptionAmount')) {
       try {
diff --git a/civicrm/CRM/Contribute/Page/ContributionPage.php b/civicrm/CRM/Contribute/Page/ContributionPage.php
index 56ae53b7e2..835089da89 100644
--- a/civicrm/CRM/Contribute/Page/ContributionPage.php
+++ b/civicrm/CRM/Contribute/Page/ContributionPage.php
@@ -411,14 +411,14 @@ AND         cp.page_type = 'contribute'
 
     $this->search();
 
-    $params = array();
+    $params = [];
 
     $whereClause = $this->whereClause($params, FALSE);
     $config = CRM_Core_Config::singleton();
     if ($config->includeAlphabeticalPager) {
       $this->pagerAToZ($whereClause, $params);
     }
-    $params = array();
+    $params = [];
     $whereClause = $this->whereClause($params, TRUE);
     $this->pager($whereClause, $params);
 
@@ -434,7 +434,7 @@ AND         cp.page_type = 'contribute'
    ORDER BY is_active desc, title asc
    LIMIT  $offset, $rowCount";
     $contribPage = CRM_Core_DAO::executeQuery($query, $params, TRUE, 'CRM_Contribute_DAO_ContributionPage');
-    $contribPageIds = array();
+    $contribPageIds = [];
     while ($contribPage->fetch()) {
       $contribPageIds[$contribPage->id] = $contribPage->id;
     }
@@ -457,7 +457,7 @@ ORDER BY is_active desc, title asc
     $configureActionLinks = self::configureActionLinks();
 
     while ($dao->fetch()) {
-      $contribution[$dao->id] = array();
+      $contribution[$dao->id] = [];
       CRM_Core_DAO::storeValues($dao, $contribution[$dao->id]);
 
       // form all action links
@@ -485,7 +485,7 @@ ORDER BY is_active desc, title asc
       }
 
       //build the configure links.
-      $sectionsInfo = CRM_Utils_Array::value($dao->id, $contriPageSectionInfo, array());
+      $sectionsInfo = CRM_Utils_Array::value($dao->id, $contriPageSectionInfo, []);
       $contribution[$dao->id]['configureActionLinks'] = CRM_Core_Action::formLink(self::formatConfigureLinks($sectionsInfo),
         $action,
         array('id' => $dao->id),
@@ -565,7 +565,7 @@ ORDER BY is_active desc, title asc
    */
   public function whereClause(&$params, $sortBy = TRUE) {
     // @todo Unused local variable can be safely removed.
-    $values = $clauses = array();
+    $values = $clauses = [];
     $title = $this->get('title');
     $createdId = $this->get('cid');
 
@@ -584,7 +584,7 @@ ORDER BY is_active desc, title asc
     }
 
     $value = $this->get('financial_type_id');
-    $val = array();
+    $val = [];
     if ($value) {
       if (is_array($value)) {
         foreach ($value as $k => $v) {
@@ -627,7 +627,7 @@ ORDER BY is_active desc, title asc
   public function getCampaignIds() {
     // The unfiltered value from the session cannot be trusted, it needs to be
     // processed to get a clean array of positive integers.
-    $ids = array();
+    $ids = [];
     foreach ((array) $this->get('campaign_id') as $id) {
       if ((string) (int) $id === (string) $id && $id > 0) {
         $ids[] = $id;
@@ -695,7 +695,7 @@ ORDER BY UPPER(LEFT(title, 1))
       }
 
       if (empty($sectionsInfo[$sectionName])) {
-        $classes = array();
+        $classes = [];
         if (isset($link['class'])) {
           $classes = $link['class'];
         }
diff --git a/civicrm/CRM/Contribute/xml/Menu/Contribute.xml b/civicrm/CRM/Contribute/xml/Menu/Contribute.xml
index 548902dbc0..cfafe7f6c3 100644
--- a/civicrm/CRM/Contribute/xml/Menu/Contribute.xml
+++ b/civicrm/CRM/Contribute/xml/Menu/Contribute.xml
@@ -41,7 +41,6 @@
     <page_callback>CRM_Contribute_Page_ContributionPage</page_callback>
     <desc>CiviContribute allows you to create and maintain any number of Online Contribution Pages. You can create different pages for different programs or campaigns - and customize text, amounts, types of information collected from contributors, etc.</desc>
     <adminGroup>CiviContribute</adminGroup>
-    <icon>admin/small/online_contribution_pages.png</icon>
     <weight>360</weight>
   </item>
   <item>
@@ -110,7 +109,6 @@
     <page_callback>CRM_Contribute_Page_ManagePremiums</page_callback>
     <desc>CiviContribute allows you to configure any number of Premiums which can be offered to contributors as incentives / thank-you gifts. Define the premiums you want to offer here.</desc>
     <adminGroup>CiviContribute</adminGroup>
-    <icon>admin/small/Premiums.png</icon>
     <weight>365</weight>
   </item>
   <item>
@@ -136,7 +134,6 @@
     <page_callback>CRM_Financial_Page_FinancialAccount</page_callback>
     <desc>Financial types are used to categorize contributions for reporting and accounting purposes. These are also referred to as Funds.</desc>
     <adminGroup>CiviContribute</adminGroup>
-    <icon>admin/small/contribution_types.png</icon>
     <weight>370</weight>
   </item>
   <item>
@@ -145,7 +142,6 @@
     <page_callback>CRM_Admin_Page_Options</page_callback>
     <desc>You may choose to record the payment instrument used for each contribution. Common payment methods are installed by default (e.g. Check, Cash, Credit Card...). If your site requires additional payment methods, add them here.</desc>
     <adminGroup>CiviContribute</adminGroup>
-    <icon>admin/small/payment_instruments.png</icon>
     <weight>380</weight>
   </item>
   <item>
@@ -154,7 +150,6 @@
     <page_callback>CRM_Admin_Page_Options</page_callback>
     <desc>Credit card options that will be offered to contributors using your Online Contribution pages.</desc>
     <adminGroup>CiviContribute</adminGroup>
-    <icon>admin/small/accepted_creditcards.png</icon>
     <weight>395</weight>
   </item>
   <item>
@@ -163,7 +158,6 @@
     <page_callback>CRM_Admin_Page_Options</page_callback>
     <desc>Soft Credit Types that will be offered to contributors during soft credit contribution</desc>
     <adminGroup>CiviContribute</adminGroup>
-    <icon>admin/small/soft_credit_type.png</icon>
   </item>
   <item>
     <path>civicrm/contact/view/contribution</path>
diff --git a/civicrm/CRM/Contribute/xml/Menu/PCP.xml b/civicrm/CRM/Contribute/xml/Menu/PCP.xml
index 916b55489d..731d9be935 100644
--- a/civicrm/CRM/Contribute/xml/Menu/PCP.xml
+++ b/civicrm/CRM/Contribute/xml/Menu/PCP.xml
@@ -8,7 +8,6 @@
      <path_arguments>context=contribute</path_arguments>
      <desc>View and manage existing personal campaign pages.</desc>
      <adminGroup>CiviContribute</adminGroup>
-     <icon>admin/small/contribution_types.png</icon>
      <weight>362</weight>
   </item>
   <item>
diff --git a/civicrm/CRM/Core/Action.php b/civicrm/CRM/Core/Action.php
index 0e54b2445b..f147507602 100644
--- a/civicrm/CRM/Core/Action.php
+++ b/civicrm/CRM/Core/Action.php
@@ -247,7 +247,7 @@ class CRM_Core_Action {
           $urlPath,
           $classes,
           !empty($link['title']) ? "title='{$link['title']}' " : '',
-          $link['name']
+          empty($link['icon']) ? $link['name'] : CRM_Core_Page::crmIcon($link['icon'], $link['name'], TRUE, ['title' => ''])
         );
       }
     }
@@ -312,7 +312,7 @@ class CRM_Core_Action {
 
     // make links indexed sequentially instead of by bitmask
     // otherwise it's next to impossible to reliably add new ones
-    $seqLinks = array();
+    $seqLinks = [];
     foreach ($links as $bit => $link) {
       $link['bit'] = $bit;
       $seqLinks[] = $link;
diff --git a/civicrm/CRM/Core/BAO/ActionLog.php b/civicrm/CRM/Core/BAO/ActionLog.php
index c04e3f30cc..877c88b8ae 100644
--- a/civicrm/CRM/Core/BAO/ActionLog.php
+++ b/civicrm/CRM/Core/BAO/ActionLog.php
@@ -30,30 +30,9 @@ class CRM_Core_BAO_ActionLog extends CRM_Core_DAO_ActionLog {
    * @return array
    */
   public static function create($params) {
-    $actionLog = new CRM_Core_DAO_ActionLog();
+    $params['action_date_time'] = $params['action_date_time'] ?? date('YmdHis');
 
-    $params['action_date_time'] = CRM_Utils_Array::value('action_date_time', $params, date('YmdHis'));
-
-    $actionLog->copyValues($params);
-
-    $edit = (bool) $actionLog->id;
-    if ($edit) {
-      CRM_Utils_Hook::pre('edit', 'ActionLog', $actionLog->id, $actionLog);
-    }
-    else {
-      CRM_Utils_Hook::pre('create', 'ActionLog', NULL, $actionLog);
-    }
-
-    $actionLog->save();
-
-    if ($edit) {
-      CRM_Utils_Hook::post('edit', 'ActionLog', $actionLog->id, $actionLog);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'ActionLog', NULL, $actionLog);
-    }
-
-    return $actionLog;
+    return self::writeRecord($params);
   }
 
 }
diff --git a/civicrm/CRM/Core/BAO/ActionSchedule.php b/civicrm/CRM/Core/BAO/ActionSchedule.php
index c1d7ec1a10..a53e0e6232 100644
--- a/civicrm/CRM/Core/BAO/ActionSchedule.php
+++ b/civicrm/CRM/Core/BAO/ActionSchedule.php
@@ -226,6 +226,7 @@ FROM civicrm_action_schedule cas
    * @param int $id
    *   ID of the Reminder to be deleted.
    *
+   * @throws CRM_Core_Exception
    */
   public static function del($id) {
     if ($id) {
@@ -236,7 +237,7 @@ FROM civicrm_action_schedule cas
         return;
       }
     }
-    CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+    throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
   }
 
   /**
diff --git a/civicrm/CRM/Core/BAO/Address.php b/civicrm/CRM/Core/BAO/Address.php
index e22a25cecd..c0f6561c8a 100644
--- a/civicrm/CRM/Core/BAO/Address.php
+++ b/civicrm/CRM/Core/BAO/Address.php
@@ -1181,7 +1181,7 @@ SELECT is_primary,
     $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', 'Household Member of', 'id', 'name_a_b');
 
     if (!$relTypeId) {
-      CRM_Core_Error::fatal(ts("You seem to have deleted the relationship type 'Household Member of'"));
+      throw new CRM_Core_Exception(ts("You seem to have deleted the relationship type 'Household Member of'"));
     }
 
     $relParam = [
diff --git a/civicrm/CRM/Core/BAO/Block.php b/civicrm/CRM/Core/BAO/Block.php
index a36b698e66..876cd323c5 100644
--- a/civicrm/CRM/Core/BAO/Block.php
+++ b/civicrm/CRM/Core/BAO/Block.php
@@ -40,6 +40,7 @@ class CRM_Core_BAO_Block {
    *
    * @return array
    *   Array of $block objects.
+   * @throws CRM_Core_Exception
    */
   public static function &getValues($blockName, $params) {
     if (empty($params)) {
@@ -52,7 +53,7 @@ class CRM_Core_BAO_Block {
     if (!isset($params['entity_table'])) {
       $block->contact_id = $params['contact_id'];
       if (!$block->contact_id) {
-        CRM_Core_Error::fatal();
+        throw new CRM_Core_Exception('Invalid Contact ID parameter passed');
       }
       $blocks = self::retrieveBlock($block, $blockName);
     }
diff --git a/civicrm/CRM/Core/BAO/Cache.php b/civicrm/CRM/Core/BAO/Cache.php
index ee678348dd..a13a6fee85 100644
--- a/civicrm/CRM/Core/BAO/Cache.php
+++ b/civicrm/CRM/Core/BAO/Cache.php
@@ -149,6 +149,7 @@ class CRM_Core_BAO_Cache extends CRM_Core_DAO_Cache {
    * @param int $componentID
    *   The optional component ID (so componenets can share the same name space).
    * @deprecated
+   * @throws CRM_Core_Exception
    */
   public static function setItem(&$data, $group, $path, $componentID = NULL) {
     CRM_Core_Error::deprecatedFunctionWarning(
@@ -167,7 +168,7 @@ class CRM_Core_BAO_Cache extends CRM_Core_DAO_Cache {
     // CRM-11234
     $lock = Civi::lockManager()->acquire("cache.{$group}_{$path}._{$componentID}");
     if (!$lock->isAcquired()) {
-      CRM_Core_Error::fatal();
+      throw new CRM_Core_Exception('Cannot acquire database lock');
     }
 
     $table = self::getTableName();
diff --git a/civicrm/CRM/Core/BAO/CustomField.php b/civicrm/CRM/Core/BAO/CustomField.php
index b8c8f9543c..0fcf801bd6 100644
--- a/civicrm/CRM/Core/BAO/CustomField.php
+++ b/civicrm/CRM/Core/BAO/CustomField.php
@@ -242,6 +242,20 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
     return $options;
   }
 
+  /**
+   * @inheritDoc
+   */
+  public static function buildOptions($fieldName, $context = NULL, $props = []) {
+    $options = parent::buildOptions($fieldName, $context, $props);
+    // This provides legacy support for APIv3, allowing no-longer-existent html types
+    if ($fieldName == 'html_type' && isset($props['version']) && $props['version'] == 3) {
+      $options['Multi-Select'] = 'Multi-Select';
+      $options['Multi-Select Country'] = 'Multi-Select Country';
+      $options['Multi-Select State/Province'] = 'Multi-Select State/Province';
+    }
+    return $options;
+  }
+
   /**
    * Store and return an array of all active custom fields.
    *
@@ -264,6 +278,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
    *
    * @return array
    *   an array of active custom fields.
+   * @throws \CRM_Core_Exception
    */
   public static function &getFields(
     $customDataType = 'Individual',
@@ -378,6 +393,10 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
         if ($onlyParent) {
           $extends .= " AND $cgTable.extends_entity_column_value IS NULL AND $cgTable.extends_entity_column_id IS NULL ";
         }
+        // Temporary hack - in 5.27 a new field is added to civicrm_custom_field. There is a high
+        // risk this function is called before the upgrade page can be reached and if
+        // so it will potentially result in fatal error.
+        $serializeField = CRM_Core_BAO_Domain::isDBVersionAtLeast('5.27.alpha1') ? "$cfTable.serialize," : '';
 
         $query = "SELECT $cfTable.id, $cfTable.label,
                             $cgTable.title,
@@ -396,6 +415,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
                             $cfTable.date_format,
                             $cfTable.time_format,
                             $cgTable.is_multiple,
+                            $serializeField
                             $cgTable.table_name,
                             og.name as option_group_name
                      FROM $cfTable
@@ -478,6 +498,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
           $fields[$dao->id]['is_required'] = $dao->is_required;
           $fields[$dao->id]['table_name'] = $dao->table_name;
           $fields[$dao->id]['column_name'] = $dao->column_name;
+          $fields[$dao->id]['serialize'] = $serializeField ? $dao->serialize : (int) self::isSerialized($dao);
           $fields[$dao->id]['where'] = $dao->table_name . '.' . $dao->column_name;
           // Probably we should use a different fn to get the extends tables but this is a refactor so not changing that now.
           $fields[$dao->id]['extends_table'] = array_key_exists($dao->extends, CRM_Core_BAO_CustomQuery::$extendsMap) ? CRM_Core_BAO_CustomQuery::$extendsMap[$dao->extends] : '';
@@ -592,6 +613,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
    *
    * @return CRM_Core_BAO_CustomField
    *   The field object.
+   * @throws CRM_Core_Exception
    */
   public static function getFieldObject($fieldID) {
     $field = new CRM_Core_BAO_CustomField();
@@ -603,7 +625,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
     if (empty($fieldValues)) {
       $field->id = $fieldID;
       if (!$field->find(TRUE)) {
-        CRM_Core_Error::fatal();
+        throw new CRM_Core_Exception('Cannot find Custom Field');
       }
 
       $fieldValues = [];
@@ -659,11 +681,8 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
     // FIXME: Why are select state/country separate widget types?
     $isSelect = (in_array($widget, [
       'Select',
-      'Multi-Select',
       'Select State/Province',
-      'Multi-Select State/Province',
       'Select Country',
-      'Multi-Select Country',
       'CheckBox',
       'Radio',
     ]));
@@ -680,7 +699,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
       $selectAttributes = ['class' => 'crm-select2'];
 
       // Search field is always multi-select
-      if ($search || strpos($field->html_type, 'Multi') !== FALSE) {
+      if ($search || (self::isSerialized($field) && $widget === 'Select')) {
         $selectAttributes['class'] .= ' huge';
         $selectAttributes['multiple'] = 'multiple';
         $selectAttributes['placeholder'] = $placeholder;
@@ -874,7 +893,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
       case 'Autocomplete-Select':
         static $customUrls = [];
         // Fixme: why is this a string in the first place??
-        $attributes = array();
+        $attributes = [];
         if ($field->attributes) {
           foreach (explode(' ', $field->attributes) as $at) {
             if (strpos($at, '=')) {
@@ -1053,9 +1072,6 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
       case 'Select Country':
       case 'Select State/Province':
       case 'CheckBox':
-      case 'Multi-Select':
-      case 'Multi-Select State/Province':
-      case 'Multi-Select Country':
         if ($field['data_type'] == 'ContactReference' && $value) {
           if (is_numeric($value)) {
             $display = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $value, 'display_name');
@@ -1233,7 +1249,7 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
     if ($customField->data_type == 'Money' && isset($value)) {
       $value = number_format($value, 2);
     }
-    if (self::isSerialized($customField)) {
+    if (self::isSerialized($customField) && $value) {
       $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldId, FALSE);
       $defaults[$elementName] = [];
       $checkedValue = CRM_Utils_Array::explodePadded($value);
@@ -1773,11 +1789,13 @@ WHERE  id IN ( %1, %2 )
    *   FK to civicrm_custom_field.
    * @param int $newGroupID
    *   FK to civicrm_custom_group.
+   *
+   * @throws CRM_Core_Exception
    */
   public static function moveField($fieldID, $newGroupID) {
     $validation = self::_moveFieldValidate($fieldID, $newGroupID);
     if (TRUE !== $validation) {
-      CRM_Core_Error::fatal(implode(' ', $validation));
+      throw new CRM_Core_Exception(implode(' ', $validation));
     }
     $field = new CRM_Core_DAO_CustomField();
     $field->id = $fieldID;
@@ -1887,7 +1905,12 @@ WHERE  id IN ( %1, %2 )
       $params['date_format'] = Civi::settings()->get('dateInputFormat');
     }
 
-    if ($htmlType === 'CheckBox' || $htmlType === 'Multi-Select') {
+    // Checkboxes are always serialized in current schema
+    if ($htmlType == 'CheckBox') {
+      $params['serialize'] = CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND;
+    }
+
+    if (!empty($params['serialize'])) {
       if (isset($params['default_checkbox_option'])) {
         $defaultArray = [];
         foreach (array_keys($params['default_checkbox_option']) as $k => $v) {
@@ -1941,7 +1964,7 @@ WHERE  id IN ( %1, %2 )
       // retrieve it from one of the other custom fields which use this option group
       if (empty($params['default_value'])) {
         //don't insert only value separator as default value, CRM-4579
-        $defaultValue = self::getOptionGroupDefault($params['option_group_id'], $htmlType);
+        $defaultValue = self::getOptionGroupDefault($params['option_group_id'], !empty($params['serialize']));
 
         if (!CRM_Utils_System::isNull(explode(CRM_Core_DAO::VALUE_SEPARATOR, $defaultValue))) {
           $params['default_value'] = $defaultValue;
@@ -2061,7 +2084,7 @@ WHERE  id IN ( %1, %2 )
    *
    * @return array
    *   fatal is fieldID does not exists, else array of tableName, columnName
-   * @throws \Exception
+   * @throws \CRM_Core_Exception
    */
   public static function getTableColumnGroup($fieldID, $force = FALSE) {
     $cacheKey = "CRM_Core_DAO_CustomField_CustomGroup_TableColumn_{$fieldID}";
@@ -2078,7 +2101,7 @@ AND    cf.id = %1";
       $dao = CRM_Core_DAO::executeQuery($query, $params);
 
       if (!$dao->fetch()) {
-        CRM_Core_Error::fatal();
+        throw new CRM_Core_Exception("Cannot find table and column information for Custom Field " . $fieldID);
       }
       $fieldValues = [$dao->table_name, $dao->column_name, $dao->id];
       $cache->set($cacheKey, $fieldValues);
@@ -2200,49 +2223,33 @@ WHERE  option_group_id = {$optionGroupId}";
    * Get option group default.
    *
    * @param int $optionGroupId
-   * @param string $htmlType
+   * @param bool $serialize
    *
    * @return null|string
    */
-  public static function getOptionGroupDefault($optionGroupId, $htmlType) {
+  public static function getOptionGroupDefault($optionGroupId, $serialize) {
     $query = "
-SELECT   default_value, html_type
+SELECT   default_value, serialize
 FROM     civicrm_custom_field
 WHERE    option_group_id = {$optionGroupId}
-AND      default_value IS NOT NULL
-ORDER BY html_type";
+AND      default_value IS NOT NULL";
 
     $dao = CRM_Core_DAO::executeQuery($query);
-    $defaultValue = NULL;
-    $defaultHTMLType = NULL;
     while ($dao->fetch()) {
-      if ($dao->html_type == $htmlType) {
+      if ($dao->serialize == $serialize) {
         return $dao->default_value;
       }
-      if ($defaultValue == NULL) {
-        $defaultValue = $dao->default_value;
-        $defaultHTMLType = $dao->html_type;
-      }
+      $defaultValue = $dao->default_value;
     }
 
-    // some conversions are needed if either the old or new has a html type which has potential
-    // multiple default values.
-    if (($htmlType == 'CheckBox' || $htmlType == 'Multi-Select') &&
-      ($defaultHTMLType != 'CheckBox' && $defaultHTMLType != 'Multi-Select')
-    ) {
-      $defaultValue = CRM_Core_DAO::VALUE_SEPARATOR . $defaultValue . CRM_Core_DAO::VALUE_SEPARATOR;
+    // Convert serialization
+    if (isset($defaultValue) && $serialize) {
+      return CRM_Utils_Array::implodePadded([$defaultValue]);
     }
-    elseif (($defaultHTMLType == 'CheckBox' || $defaultHTMLType == 'Multi-Select') &&
-      ($htmlType != 'CheckBox' && $htmlType != 'Multi-Select')
-    ) {
-      $defaultValue = substr($defaultValue, 1, -1);
-      $values = explode(CRM_Core_DAO::VALUE_SEPARATOR,
-        substr($defaultValue, 1, -1)
-      );
-      $defaultValue = $values[0];
+    elseif (isset($defaultValue)) {
+      return CRM_Utils_Array::explodePadded($defaultValue)[0];
     }
-
-    return $defaultValue;
+    return NULL;
   }
 
   /**
@@ -2529,15 +2536,20 @@ WHERE cf.id = %1 AND cg.is_multiple = 1";
   /**
    * Does this field store a serialized string?
    *
-   * @param array|object $field
+   * @param CRM_Core_DAO_CustomField|array $field
    *
    * @return bool
    */
   public static function isSerialized($field) {
     // Fields retrieved via api are an array, or from the dao are an object. We'll accept either.
     $html_type = is_object($field) ? $field->html_type : $field['html_type'];
-    // FIXME: Currently the only way to know if data is serialized is by looking at the html_type. It would be cleaner to decouple this.
-    return ($html_type === 'CheckBox' || strpos($html_type, 'Multi') !== FALSE);
+    // APIv3 has a "legacy" mode where it returns old-style html_type of "Multi-Select"
+    // If anyone is using this function in conjunction with legacy api output, we'll accomodate:
+    if ($html_type === 'CheckBox' || strpos($html_type, 'Multi') !== FALSE) {
+      return TRUE;
+    }
+    // Otherwise this is the new standard as of 5.27
+    return is_object($field) ? !empty($field->serialize) : !empty($field['serialize']);
   }
 
   /**
diff --git a/civicrm/CRM/Core/BAO/CustomGroup.php b/civicrm/CRM/Core/BAO/CustomGroup.php
index 4dc6d36f3f..0f08b27798 100644
--- a/civicrm/CRM/Core/BAO/CustomGroup.php
+++ b/civicrm/CRM/Core/BAO/CustomGroup.php
@@ -399,6 +399,7 @@ class CRM_Core_BAO_CustomGroup extends CRM_Core_DAO_CustomGroup {
         'time_format',
         'option_group_id',
         'in_selector',
+        'serialize',
       ],
       'custom_group' => [
         'id',
@@ -1533,7 +1534,6 @@ ORDER BY civicrm_custom_group.weight,
     $form->assign_by_ref("{$prefix}groupTree", $groupTree);
 
     foreach ($groupTree as $id => $group) {
-      CRM_Core_ShowHideBlocks::links($form, $group['title'], '', '');
       foreach ($group['fields'] as $field) {
         $required = $field['is_required'] ?? NULL;
         //fix for CRM-1620
diff --git a/civicrm/CRM/Core/BAO/CustomOption.php b/civicrm/CRM/Core/BAO/CustomOption.php
index 31c522bc77..e876436f75 100644
--- a/civicrm/CRM/Core/BAO/CustomOption.php
+++ b/civicrm/CRM/Core/BAO/CustomOption.php
@@ -138,20 +138,10 @@ class CRM_Core_BAO_CustomOption {
       }
 
       if (in_array($field->html_type, ['CheckBox', 'Multi-Select'])) {
-        if (isset($defVal) && in_array($dao->value, $defVal)) {
-          $options[$dao->id]['is_default'] = '<img src="' . $config->resourceBase . 'i/check.gif" />';
-        }
-        else {
-          $options[$dao->id]['is_default'] = '';
-        }
+        $options[$dao->id]['is_default'] = (isset($defVal) && in_array($dao->value, $defVal));
       }
       else {
-        if ($field->default_value == $dao->value) {
-          $options[$dao->id]['is_default'] = '<img src="' . $config->resourceBase . 'i/check.gif" />';
-        }
-        else {
-          $options[$dao->id]['is_default'] = '';
-        }
+        $options[$dao->id]['is_default'] = ($field->default_value == $dao->value);
       }
       $options[$dao->id]['description'] = $dao->description;
       $options[$dao->id]['class'] = $dao->id . ',' . $class;
@@ -287,7 +277,7 @@ SET    {$dao->columnName} = REPLACE( {$dao->columnName}, %1, %2 )";
           break;
 
         default:
-          CRM_Core_Error::fatal();
+          throw new CRM_Core_Exception('Invalid HTML Type');
       }
       $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
     }
diff --git a/civicrm/CRM/Core/BAO/CustomValue.php b/civicrm/CRM/Core/BAO/CustomValue.php
index 8cbe6b3d08..3a64cdb29d 100644
--- a/civicrm/CRM/Core/BAO/CustomValue.php
+++ b/civicrm/CRM/Core/BAO/CustomValue.php
@@ -206,4 +206,16 @@ class CRM_Core_BAO_CustomValue extends CRM_Core_DAO {
     );
   }
 
+  /**
+   * ACL clause for an APIv4 custom pseudo-entity (aka multi-record custom group extending Contact).
+   * @return array
+   */
+  public function addSelectWhereClause() {
+    $clauses = [
+      'entity_id' => CRM_Utils_SQL::mergeSubquery('Contact'),
+    ];
+    CRM_Utils_Hook::selectWhereClause($this, $clauses);
+    return $clauses;
+  }
+
 }
diff --git a/civicrm/CRM/Core/BAO/CustomValueTable.php b/civicrm/CRM/Core/BAO/CustomValueTable.php
index 1fa9a508a8..0a724557b8 100644
--- a/civicrm/CRM/Core/BAO/CustomValueTable.php
+++ b/civicrm/CRM/Core/BAO/CustomValueTable.php
@@ -153,7 +153,7 @@ class CRM_Core_BAO_CustomValueTable {
 
             case 'File':
               if (!$field['file_id']) {
-                CRM_Core_Error::fatal();
+                throw new CRM_Core_Exception('Missing parameter file_id');
               }
 
               // need to add/update civicrm_entity_file
@@ -318,7 +318,7 @@ class CRM_Core_BAO_CustomValueTable {
         return 'datetime';
 
       default:
-        CRM_Core_Error::fatal();
+        throw new CRM_Core_Exception('Invalid Field Type');
     }
   }
 
@@ -415,12 +415,13 @@ class CRM_Core_BAO_CustomValueTable {
    *   Array of custom values for the entity with key=>value
    *                                   pairs specified as civicrm_custom_field.id => custom value.
    *                                   Empty array if no custom values found.
+   * @throws CRM_Core_Exception
    */
   public static function &getEntityValues($entityID, $entityType = NULL, $fieldIDs = NULL, $formatMultiRecordField = FALSE, $DTparams = NULL) {
     if (!$entityID) {
       // adding this here since an empty contact id could have serious repurcussions
       // like looping forever
-      CRM_Core_Error::fatal('Please file an issue with the backtrace');
+      throw new CRM_Core_Exception('Please file an issue with the backtrace');
       return NULL;
     }
 
diff --git a/civicrm/CRM/Core/BAO/Discount.php b/civicrm/CRM/Core/BAO/Discount.php
index ce24c32e4e..812747eb42 100644
--- a/civicrm/CRM/Core/BAO/Discount.php
+++ b/civicrm/CRM/Core/BAO/Discount.php
@@ -98,11 +98,12 @@ class CRM_Core_BAO_Discount extends CRM_Core_DAO_Discount {
    * @return int
    *   $dao->id       discount id of the set which matches
    *                                 the date criteria
+   * @throws CRM_Core_Exception
    */
   public static function findSet($entityID, $entityTable) {
     if (empty($entityID) || empty($entityTable)) {
       // adding this here, to trap errors if values are not sent
-      CRM_Core_Error::fatal();
+      throw new CRM_Core_Exception('Invalid parameters passed to findSet function');
       return NULL;
     }
 
diff --git a/civicrm/CRM/Core/BAO/Domain.php b/civicrm/CRM/Core/BAO/Domain.php
index 5f1f508cba..14e885a6e2 100644
--- a/civicrm/CRM/Core/BAO/Domain.php
+++ b/civicrm/CRM/Core/BAO/Domain.php
@@ -82,6 +82,29 @@ class CRM_Core_BAO_Domain extends CRM_Core_DAO_Domain {
     );
   }
 
+  /**
+   * Is a database update required to apply latest schema changes.
+   *
+   * @return bool
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public static function isDBUpdateRequired() {
+    $dbVersion = CRM_Core_BAO_Domain::version();
+    $codeVersion = CRM_Utils_System::version();
+    return version_compare($dbVersion, $codeVersion) < 0;
+  }
+
+  /**
+   * Checks that the current DB schema is at least $min version
+   *
+   * @param string|number $min
+   * @return bool
+   */
+  public static function isDBVersionAtLeast($min) {
+    return version_compare(self::version(), $min, '>=');
+  }
+
   /**
    * Get the location values of a domain.
    *
diff --git a/civicrm/CRM/Core/BAO/File.php b/civicrm/CRM/Core/BAO/File.php
index 3e78e3ffea..c2de586197 100644
--- a/civicrm/CRM/Core/BAO/File.php
+++ b/civicrm/CRM/Core/BAO/File.php
@@ -677,7 +677,7 @@ AND       CEF.entity_id    = %2";
 
   /**
    * Delete a file attachment from an entity table / entity ID
-   *
+   * @throws CRM_Core_Exception
    */
   public static function deleteAttachment() {
     $params = [];
@@ -689,7 +689,7 @@ AND       CEF.entity_id    = %2";
 
     $signer = new CRM_Utils_Signer(CRM_Core_Key::privateKey(), self::$_signableFields);
     if (!$signer->validate($signature, $params)) {
-      CRM_Core_Error::fatal('Request signature is invalid');
+      throw new CRM_Core_Exception('Request signature is invalid');
     }
 
     self::deleteEntityFile($params['entityTable'], $params['entityID'], NULL, $params['fileID']);
@@ -726,17 +726,19 @@ AND       CEF.entity_id    = %2";
           $fileType == 'image/x-png' ||
           $fileType == 'image/png'
         ) {
-          $file_url[$fileID] = "
-              <a href='$url' class='crm-image-popup' title='$title'>
-                <i class='crm-i fa-file-image-o'></i>
-              </a>";
+          $file_url[$fileID] = <<<HEREDOC
+              <a href="$url" class="crm-image-popup" title="$title">
+                <i class="crm-i fa-file-image-o" aria-hidden="true"></i>
+              </a>
+HEREDOC;
         }
         // for non image files
         else {
-          $file_url[$fileID] = "
-              <a href='$url' title='$title'>
-                <i class='crm-i fa-paperclip'></i>
-              </a>";
+          $file_url[$fileID] = <<<HEREDOC
+              <a href="$url" title="$title">
+                <i class="crm-i fa-paperclip" aria-hidden="true"></i>
+              </a>
+HEREDOC;
         }
       }
     }
diff --git a/civicrm/CRM/Core/BAO/Job.php b/civicrm/CRM/Core/BAO/Job.php
index 5609b3075f..c4214e60b5 100644
--- a/civicrm/CRM/Core/BAO/Job.php
+++ b/civicrm/CRM/Core/BAO/Job.php
@@ -88,10 +88,11 @@ class CRM_Core_BAO_Job extends CRM_Core_DAO_Job {
    *   ID of the job to be deleted.
    *
    * @return bool|null
+   * @throws CRM_Core_Exception
    */
   public static function del($jobID) {
     if (!$jobID) {
-      CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+      throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
     }
 
     $dao = new CRM_Core_DAO_Job();
@@ -117,15 +118,16 @@ class CRM_Core_BAO_Job extends CRM_Core_DAO_Job {
     // Prevent the job log from getting too big
     // For now, keep last minDays days and at least maxEntries records
     $query = 'SELECT COUNT(*) FROM civicrm_job_log';
-    $count = CRM_Core_DAO::singleValueQuery($query);
+    $count = (int) CRM_Core_DAO::singleValueQuery($query);
 
     if ($count <= $maxEntriesToKeep) {
       return;
     }
 
-    $count = $count - $maxEntriesToKeep;
+    $count = $count - (int) $maxEntriesToKeep;
 
-    $query = "DELETE FROM civicrm_job_log WHERE run_time < SUBDATE(NOW(), $minDaysToKeep) LIMIT $count";
+    $minDaysToKeep = (int) $minDaysToKeep;
+    $query = "DELETE FROM civicrm_job_log WHERE run_time < SUBDATE(NOW(), $minDaysToKeep) ORDER BY id LIMIT $count";
     CRM_Core_DAO::executeQuery($query);
   }
 
diff --git a/civicrm/CRM/Core/BAO/LabelFormat.php b/civicrm/CRM/Core/BAO/LabelFormat.php
index 175d599410..8678560c9c 100644
--- a/civicrm/CRM/Core/BAO/LabelFormat.php
+++ b/civicrm/CRM/Core/BAO/LabelFormat.php
@@ -527,7 +527,7 @@ class CRM_Core_BAO_LabelFormat extends CRM_Core_DAO_OptionValue {
     // make sure serialized array will fit in the 'value' column
     $attribute = CRM_Core_DAO::getAttribute('CRM_Core_BAO_LabelFormat', 'value');
     if (strlen($this->value) > $attribute['maxlength']) {
-      CRM_Core_Error::fatal(ts('Label Format does not fit in database.'));
+      throw new CRM_Core_Exception(ts('Label Format does not fit in database.'));
     }
     $this->save();
 
diff --git a/civicrm/CRM/Core/BAO/Location.php b/civicrm/CRM/Core/BAO/Location.php
index ec50cd15f0..e2d393976c 100644
--- a/civicrm/CRM/Core/BAO/Location.php
+++ b/civicrm/CRM/Core/BAO/Location.php
@@ -260,13 +260,14 @@ WHERE e.id = %1";
    *   Contact id.
    * @param int $locationTypeId
    *   Id of the location to delete.
+   * @throws CRM_Core_Exception
    */
   public static function deleteLocationBlocks($contactId, $locationTypeId) {
     // ensure that contactId has a value
     if (empty($contactId) ||
       !CRM_Utils_Rule::positiveInteger($contactId)
     ) {
-      CRM_Core_Error::fatal();
+      throw new CRM_Core_Exception('Incorrect contact id parameter passed to deleteLocationBlocks');
     }
 
     if (empty($locationTypeId) ||
diff --git a/civicrm/CRM/Core/BAO/Mapping.php b/civicrm/CRM/Core/BAO/Mapping.php
index 19c6ec2290..309972bb6a 100644
--- a/civicrm/CRM/Core/BAO/Mapping.php
+++ b/civicrm/CRM/Core/BAO/Mapping.php
@@ -151,6 +151,7 @@ class CRM_Core_BAO_Mapping extends CRM_Core_DAO_Mapping {
         civicrm_api3('OptionValue', 'create', [
           'option_group_id' => 'mapping_type',
           'label' => $mappingType,
+          'name' => $mappingType,
           'value' => max(array_keys($mappingValues['values'])) + 1,
           'is_reserved' => 1,
         ]);
@@ -1002,6 +1003,7 @@ class CRM_Core_BAO_Mapping extends CRM_Core_DAO_Mapping {
    *
    * @return array
    *   formatted associated array of elements
+   * @throws CRM_Core_Exception
    */
   public static function formattedFields(&$params, $row = FALSE) {
     $fields = [];
@@ -1016,7 +1018,7 @@ class CRM_Core_BAO_Mapping extends CRM_Core_DAO_Mapping {
       foreach ($value as $k => $v) {
         if (in_array($v[0], $types)) {
           if ($contactType && $contactType != $v[0]) {
-            CRM_Core_Error::fatal(ts("Cannot have two clauses with different types: %1, %2",
+            throw new CRM_Core_Exception(ts("Cannot have two clauses with different types: %1, %2",
               [1 => $contactType, 2 => $v[0]]
             ));
           }
diff --git a/civicrm/CRM/Core/BAO/Note.php b/civicrm/CRM/Core/BAO/Note.php
index 86a95fd080..e2ed3102e7 100644
--- a/civicrm/CRM/Core/BAO/Note.php
+++ b/civicrm/CRM/Core/BAO/Note.php
@@ -126,7 +126,7 @@ class CRM_Core_BAO_Note extends CRM_Core_DAO_Note {
    *   $note CRM_Core_BAO_Note object
    * @throws \CRM_Core_Exception
    */
-  public static function add(&$params, $ids = array()) {
+  public static function add(&$params, $ids = []) {
     $dataExists = self::dataExists($params);
     if (!$dataExists) {
       return NULL;
@@ -350,7 +350,7 @@ class CRM_Core_BAO_Note extends CRM_Core_DAO_Note {
    *
    */
   public static function &getNote($id, $entityTable = 'civicrm_relationship') {
-    $viewNote = array();
+    $viewNote = [];
 
     $query = "
   SELECT  id,
@@ -453,7 +453,7 @@ ORDER BY  modified_date desc";
    * @return array
    *   Nested associative array beginning with direct children of given note.
    */
-  private static function buildNoteTree($parentId, $maxDepth = 0, $snippet = FALSE, &$tree = array(), $depth = 0) {
+  private static function buildNoteTree($parentId, $maxDepth = 0, $snippet = FALSE, &$tree = [], $depth = 0) {
     if ($maxDepth && $depth > $maxDepth) {
       return FALSE;
     }
@@ -517,7 +517,7 @@ ORDER BY  modified_date desc";
    * @return array
    *   One-dimensional array containing ids of all desendent notes
    */
-  public static function getDescendentIds($parentId, &$ids = array()) {
+  public static function getDescendentIds($parentId, &$ids = []) {
     // get direct children of given parentId note
     $note = new CRM_Core_DAO_Note();
     $note->entity_table = 'civicrm_note';
diff --git a/civicrm/CRM/Core/BAO/PaperSize.php b/civicrm/CRM/Core/BAO/PaperSize.php
index c14709e855..f7456bc50d 100644
--- a/civicrm/CRM/Core/BAO/PaperSize.php
+++ b/civicrm/CRM/Core/BAO/PaperSize.php
@@ -72,12 +72,13 @@ class CRM_Core_BAO_PaperSize extends CRM_Core_DAO_OptionValue {
    *
    * @return int
    *   Group ID (null if Group ID doesn't exist)
+   * @throws CRM_Core_Exception
    */
   private static function _getGid() {
     if (!self::$_gid) {
       self::$_gid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'paper_size', 'id', 'name');
       if (!self::$_gid) {
-        CRM_Core_Error::fatal(ts('Paper Size Option Group not found in database.'));
+        throw new CRM_Core_Exception(ts('Paper Size Option Group not found in database.'));
       }
     }
     return self::$_gid;
@@ -268,6 +269,7 @@ class CRM_Core_BAO_PaperSize extends CRM_Core_DAO_OptionValue {
    * @param array $values associative array of name/value pairs
    * @param int $id
    *   Id of the database record (null = new record).
+   * @throws CRM_Core_Exception
    */
   public function savePaperSize(&$values, $id) {
     // get the Option Group ID for Paper Sizes (create one if it doesn't exist)
@@ -311,7 +313,7 @@ class CRM_Core_BAO_PaperSize extends CRM_Core_DAO_OptionValue {
     // make sure serialized array will fit in the 'value' column
     $attribute = CRM_Core_DAO::getAttribute('CRM_Core_BAO_PaperSize', 'value');
     if (strlen($this->value) > $attribute['maxlength']) {
-      CRM_Core_Error::fatal(ts('Paper Size does not fit in database.'));
+      throw new CRM_Core_Exception(ts('Paper Size does not fit in database.'));
     }
     $this->save();
 
@@ -325,7 +327,7 @@ class CRM_Core_BAO_PaperSize extends CRM_Core_DAO_OptionValue {
    *
    * @param int $id
    *   ID of the Paper Size to be deleted.
-   *
+   * @throws CRM_Core_Exception
    */
   public static function del($id) {
     if ($id) {
@@ -340,7 +342,7 @@ class CRM_Core_BAO_PaperSize extends CRM_Core_DAO_OptionValue {
         }
       }
     }
-    CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+    throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
   }
 
 }
diff --git a/civicrm/CRM/Core/BAO/PdfFormat.php b/civicrm/CRM/Core/BAO/PdfFormat.php
index 0703108a7f..33783d7306 100644
--- a/civicrm/CRM/Core/BAO/PdfFormat.php
+++ b/civicrm/CRM/Core/BAO/PdfFormat.php
@@ -127,12 +127,13 @@ class CRM_Core_BAO_PdfFormat extends CRM_Core_DAO_OptionValue {
    *
    * @return int
    *   Group ID (null if Group ID doesn't exist)
+   * @throws CRM_Core_Exception
    */
   private static function _getGid() {
     if (!self::$_gid) {
       self::$_gid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', 'pdf_format', 'id', 'name');
       if (!self::$_gid) {
-        CRM_Core_Error::fatal(ts('PDF Format Option Group not found in database.'));
+        throw new CRM_Core_Exception(ts('PDF Format Option Group not found in database.'));
       }
     }
     return self::$_gid;
@@ -325,6 +326,7 @@ class CRM_Core_BAO_PdfFormat extends CRM_Core_DAO_OptionValue {
    * @param array $values associative array of name/value pairs
    * @param int $id
    *   Id of the database record (null = new record).
+   * @throws CRM_Core_Exception
    */
   public function savePdfFormat(&$values, $id = NULL) {
     // get the Option Group ID for PDF Page Formats (create one if it doesn't exist)
@@ -364,7 +366,7 @@ class CRM_Core_BAO_PdfFormat extends CRM_Core_DAO_OptionValue {
     // make sure serialized array will fit in the 'value' column
     $attribute = CRM_Core_DAO::getAttribute('CRM_Core_BAO_PdfFormat', 'value');
     if (strlen($this->value) > $attribute['maxlength']) {
-      CRM_Core_Error::fatal(ts('PDF Page Format does not fit in database.'));
+      throw new CRM_Core_Exception(ts('PDF Page Format does not fit in database.'));
     }
     $this->save();
 
@@ -378,7 +380,7 @@ class CRM_Core_BAO_PdfFormat extends CRM_Core_DAO_OptionValue {
    *
    * @param int $id
    *   ID of the PDF Page Format to be deleted.
-   *
+   * @throws CRM_Core_Exception
    */
   public static function del($id) {
     if ($id) {
@@ -393,7 +395,7 @@ class CRM_Core_BAO_PdfFormat extends CRM_Core_DAO_OptionValue {
         }
       }
     }
-    CRM_Core_Error::fatal(ts('Invalid value passed to delete function.'));
+    throw new CRM_Core_Exception(ts('Invalid value passed to delete function.'));
   }
 
 }
diff --git a/civicrm/CRM/Core/BAO/Phone.php b/civicrm/CRM/Core/BAO/Phone.php
index bf4dd2c043..f5851eee26 100644
--- a/civicrm/CRM/Core/BAO/Phone.php
+++ b/civicrm/CRM/Core/BAO/Phone.php
@@ -57,15 +57,7 @@ class CRM_Core_BAO_Phone extends CRM_Core_DAO_Phone {
     // Ensure mysql phone function exists
     CRM_Core_DAO::checkSqlFunctionsExist();
 
-    $hook = empty($params['id']) ? 'create' : 'edit';
-    CRM_Utils_Hook::pre($hook, 'Phone', $params['id'] ?? NULL, $params);
-
-    $phone = new CRM_Core_DAO_Phone();
-    $phone->copyValues($params);
-    $phone->save();
-
-    CRM_Utils_Hook::post($hook, 'Phone', $phone->id, $phone);
-    return $phone;
+    return self::writeRecord($params);
   }
 
   /**
diff --git a/civicrm/CRM/Core/BAO/PreferencesDate.php b/civicrm/CRM/Core/BAO/PreferencesDate.php
index 513bba5dd5..b05bbf4a15 100644
--- a/civicrm/CRM/Core/BAO/PreferencesDate.php
+++ b/civicrm/CRM/Core/BAO/PreferencesDate.php
@@ -57,18 +57,20 @@ class CRM_Core_BAO_PreferencesDate extends CRM_Core_DAO_PreferencesDate {
    *   Id of the database record.
    * @param bool $is_active
    *   Value we want to set the is_active field.
+   * @throws CRM_Core_Exception
    */
   public static function setIsActive($id, $is_active) {
-    CRM_Core_Error::fatal();
+    throw new CRM_Core_Exception('Cannot call setIsActive function');
   }
 
   /**
    * Delete preference dates.
    *
    * @param int $id
+   * @throws CRM_Core_Exception
    */
   public static function del($id) {
-    CRM_Core_Error::fatal();
+    throw new CRM_Core_Exception('Cannot call del function');
   }
 
   /**
diff --git a/civicrm/CRM/Core/BAO/RecurringEntity.php b/civicrm/CRM/Core/BAO/RecurringEntity.php
index f4b1622de9..fceb1237b1 100644
--- a/civicrm/CRM/Core/BAO/RecurringEntity.php
+++ b/civicrm/CRM/Core/BAO/RecurringEntity.php
@@ -224,6 +224,7 @@ class CRM_Core_BAO_RecurringEntity extends CRM_Core_DAO_RecurringEntity {
    * Generate new DAOs and along with entries in civicrm_recurring_entity table.
    *
    * @return array
+   * @throws CRM_Core_Exception
    */
   public function generateEntities() {
     self::setStatus(self::RUNNING);
@@ -241,7 +242,7 @@ class CRM_Core_BAO_RecurringEntity extends CRM_Core_DAO_RecurringEntity {
         }
       }
       if (empty($findCriteria)) {
-        CRM_Core_Error::fatal("Find criteria missing to generate form. Make sure entity_id and table is set.");
+        throw new CRM_Core_Exception("Find criteria missing to generate form. Make sure entity_id and table is set.");
       }
 
       $count = 0;
@@ -547,11 +548,12 @@ class CRM_Core_BAO_RecurringEntity extends CRM_Core_DAO_RecurringEntity {
    *
    *
    * @return object
+   * @throws new CRM_Core_Exception
    */
   public static function copyCreateEntity($entityTable, $fromCriteria, $newParams, $createRecurringEntity = TRUE) {
     $daoName = self::$_tableDAOMapper[$entityTable];
     if (!$daoName) {
-      CRM_Core_Error::fatal("DAO Mapper missing for $entityTable.");
+      throw new CRM_Core_Exception("DAO Mapper missing for $entityTable.");
     }
     $newObject = CRM_Core_DAO::copyGeneric($daoName, $fromCriteria, $newParams);
 
@@ -631,7 +633,7 @@ class CRM_Core_BAO_RecurringEntity extends CRM_Core_DAO_RecurringEntity {
         $updateDAO = CRM_Core_DAO::cascadeUpdate($daoName, $obj->id, $entityID, $skipData);
       }
       else {
-        CRM_Core_Error::fatal("DAO Mapper missing for $entityTable.");
+        throw new CRM_Core_Exception("DAO Mapper missing for $entityTable.");
       }
     }
     // done with processing. lets unset static var.
@@ -811,7 +813,7 @@ class CRM_Core_BAO_RecurringEntity extends CRM_Core_DAO_RecurringEntity {
         foreach (self::$_linkedEntitiesInfo as $linkedTable => $linfo) {
           $daoName = self::$_tableDAOMapper[$linkedTable];
           if (!$daoName) {
-            CRM_Core_Error::fatal("DAO Mapper missing for $linkedTable.");
+            throw new CRM_Core_Exception("DAO Mapper missing for $linkedTable.");
           }
 
           $linkedDao = new $daoName();
diff --git a/civicrm/CRM/Core/BAO/SchemaHandler.php b/civicrm/CRM/Core/BAO/SchemaHandler.php
index c6757015f0..b9f3bad91f 100644
--- a/civicrm/CRM/Core/BAO/SchemaHandler.php
+++ b/civicrm/CRM/Core/BAO/SchemaHandler.php
@@ -502,7 +502,7 @@ ADD UNIQUE INDEX `unique_entity_id` ( `entity_id` )";
    * @param string $columnName
    * @param $length
    *
-   * @throws Exception
+   * @throws CRM_Core_Exception
    */
   public static function alterFieldLength($customFieldID, $tableName, $columnName, $length) {
     // first update the custom field tables
@@ -543,7 +543,7 @@ MODIFY      {$columnName} varchar( $length )
       CRM_Core_DAO::executeQuery($sql);
     }
     else {
-      CRM_Core_Error::fatal(ts('Could Not Find Custom Field Details for %1, %2, %3',
+      throw new CRM_Core_Exception(ts('Could Not Find Custom Field Details for %1, %2, %3',
         [
           1 => $tableName,
           2 => $columnName,
@@ -866,7 +866,7 @@ MODIFY      {$columnName} varchar( $length )
       }
       $query .= " CHARACTER SET = $newCharSet COLLATE = $tableCollation";
       if ($param['Engine'] === 'InnoDB') {
-        $query .= ' ROW_FORMAT = Dynamic';
+        $query .= ' ROW_FORMAT = Dynamic KEY_BLOCK_SIZE = 0';
       }
       // Disable i18n rewrite.
       CRM_Core_DAO::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
diff --git a/civicrm/CRM/Core/BAO/Setting.php b/civicrm/CRM/Core/BAO/Setting.php
index 7518e37dc2..c6b18e74e9 100644
--- a/civicrm/CRM/Core/BAO/Setting.php
+++ b/civicrm/CRM/Core/BAO/Setting.php
@@ -515,7 +515,7 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
   public static function onChangeEnvironmentSetting($oldValue, $newValue, $metadata) {
     if ($newValue != 'Production') {
       $mailing = Civi::settings()->get('mailing_backend');
-      if ($mailing['outBound_option'] != 2) {
+      if ($mailing['outBound_option'] != CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED) {
         Civi::settings()->set('mailing_backend_store', $mailing);
       }
       Civi::settings()->set('mailing_backend', ['outBound_option' => CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED]);
diff --git a/civicrm/CRM/Core/BAO/StatusPreference.php b/civicrm/CRM/Core/BAO/StatusPreference.php
index 2f225ee9fe..d4e182eadc 100644
--- a/civicrm/CRM/Core/BAO/StatusPreference.php
+++ b/civicrm/CRM/Core/BAO/StatusPreference.php
@@ -28,6 +28,7 @@ class CRM_Core_BAO_StatusPreference extends CRM_Core_DAO_StatusPreference {
    * @param array $params
    *
    * @return array
+   * @throws CRM_Core_Exception
    */
   public static function create($params) {
     $statusPreference = new CRM_Core_BAO_StatusPreference();
@@ -42,11 +43,11 @@ class CRM_Core_BAO_StatusPreference extends CRM_Core_DAO_StatusPreference {
       $params['ignore_severity'] = CRM_Utils_Check::severityMap($params['ignore_severity']);
     }
     if ($params['ignore_severity'] > 7) {
-      CRM_Core_Error::fatal(ts('You can not pass a severity level higher than 7.'));
+      throw new CRM_Core_Exception(ts('You can not pass a severity level higher than 7.'));
     }
     // If severity is now blank, you have an invalid severity string.
     if (is_null($params['ignore_severity'])) {
-      CRM_Core_Error::fatal(ts('Invalid string passed as severity level.'));
+      throw new CRM_Core_Exception(ts('Invalid string passed as severity level.'));
     }
 
     // Check if this StatusPreference already exists.
diff --git a/civicrm/CRM/Core/BAO/Tag.php b/civicrm/CRM/Core/BAO/Tag.php
index 2ef3afb411..17c0bc47cc 100644
--- a/civicrm/CRM/Core/BAO/Tag.php
+++ b/civicrm/CRM/Core/BAO/Tag.php
@@ -412,8 +412,6 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
       }
     }
 
-    $tag = new CRM_Core_DAO_Tag();
-
     // if parent id is set then inherit used for and is hidden properties
     if (!empty($params['parent_id'])) {
       // get parent details
@@ -423,34 +421,28 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
       $params['used_for'] = implode(',', $params['used_for']);
     }
 
+    // Hack to make white null, because html5 color widget can't be empty
     if (isset($params['color']) && strtolower($params['color']) === '#ffffff') {
       $params['color'] = '';
     }
 
-    $tag->copyValues($params);
-    $tag->id = $id;
-    $hook = !$id ? 'create' : 'edit';
-    CRM_Utils_Hook::pre($hook, 'Tag', $tag->id, $params);
-
     // save creator id and time
-    if (!$tag->id) {
-      $session = CRM_Core_Session::singleton();
-      $tag->created_id = $session->get('userID');
-      $tag->created_date = date('YmdHis');
+    if (!$id) {
+      $params['created_id'] = $params['created_id'] ?? CRM_Core_Session::getLoggedInContactID();
+      $params['created_date'] = $params['created_date'] ?? date('YmdHis');
     }
 
-    $tag->save();
-    CRM_Utils_Hook::post($hook, 'Tag', $tag->id, $tag);
+    $tag = self::writeRecord($params);
 
     // if we modify parent tag, then we need to update all children
-    $tag->find(TRUE);
-    if (!$tag->parent_id && $tag->used_for) {
-      CRM_Core_DAO::executeQuery("UPDATE civicrm_tag SET used_for=%1 WHERE parent_id = %2",
-        [
+    if ($id) {
+      $tag->find(TRUE);
+      if (!$tag->parent_id && $tag->used_for) {
+        CRM_Core_DAO::executeQuery("UPDATE civicrm_tag SET used_for=%1 WHERE parent_id = %2", [
           1 => [$tag->used_for, 'String'],
           2 => [$tag->id, 'Integer'],
-        ]
-      );
+        ]);
+      }
     }
 
     CRM_Core_PseudoConstant::flush();
@@ -462,11 +454,10 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
    * Check if there is data to create the object.
    *
    * @param array $params
-   *   (reference ) an assoc array of name/value pairs.
    *
    * @return bool
    */
-  public static function dataExists(&$params) {
+  public static function dataExists($params) {
     // Disallow empty values except for the number zero.
     // TODO: create a utility for this since it's needed in many places
     if (!empty($params['name']) || (string) $params['name'] === '0') {
diff --git a/civicrm/CRM/Core/BAO/UFGroup.php b/civicrm/CRM/Core/BAO/UFGroup.php
index d8a3d6c8ed..5841ab0d72 100644
--- a/civicrm/CRM/Core/BAO/UFGroup.php
+++ b/civicrm/CRM/Core/BAO/UFGroup.php
@@ -516,6 +516,7 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup {
       // if field is not present in customFields, that means the user
       // DOES NOT HAVE permission to access that field
       if (array_key_exists($field->field_name, $customFields)) {
+        $formattedField['serialize'] = !empty($customFields[$field->field_name]['serialize']);
         $formattedField['is_search_range'] = $customFields[$field->field_name]['is_search_range'];
         // fix for CRM-1994
         $formattedField['options_per_line'] = $customFields[$field->field_name]['options_per_line'];
@@ -2699,7 +2700,7 @@ AND    ( entity_id IS NULL OR entity_id <= 0 )
 
     if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
       $fixUrl = CRM_Utils_System::url('civicrm/admin/domain', 'action=update&reset=1');
-      CRM_Core_Error::fatal(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM &raquo; Communications &raquo; FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
+      CRM_Core_Error::statusBounce(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM &raquo; Communications &raquo; FROM Email Addresses</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
     }
 
     foreach ($emailList as $emailTo) {
diff --git a/civicrm/CRM/Core/BAO/UFMatch.php b/civicrm/CRM/Core/BAO/UFMatch.php
index 116ebd141c..b7dd9b2c80 100644
--- a/civicrm/CRM/Core/BAO/UFMatch.php
+++ b/civicrm/CRM/Core/BAO/UFMatch.php
@@ -57,12 +57,14 @@ class CRM_Core_BAO_UFMatch extends CRM_Core_DAO_UFMatch {
    *
    * @param $ctype
    * @param bool $isLogin
+   *
+   * @throws CRM_Core_Exception
    */
   public static function synchronize(&$user, $update, $uf, $ctype, $isLogin = FALSE) {
     $userSystem = CRM_Core_Config::singleton()->userSystem;
     $session = CRM_Core_Session::singleton();
     if (!is_object($session)) {
-      CRM_Core_Error::fatal('wow, session is not an object?');
+      throw new CRM_Core_Exception('wow, session is not an object?');
       return;
     }
 
diff --git a/civicrm/CRM/Core/BAO/WordReplacement.php b/civicrm/CRM/Core/BAO/WordReplacement.php
index d8fe9df6b3..ba4f09d7fa 100644
--- a/civicrm/CRM/Core/BAO/WordReplacement.php
+++ b/civicrm/CRM/Core/BAO/WordReplacement.php
@@ -51,6 +51,7 @@ class CRM_Core_BAO_WordReplacement extends CRM_Core_DAO_WordReplacement {
    * @param null $reset
    *
    * @return null|CRM_Core_BAO_WordReplacement
+   * @throws CRM_Core_Exception
    */
   public static function getWordReplacement($reset = NULL) {
     static $wordReplacement = NULL;
@@ -58,7 +59,7 @@ class CRM_Core_BAO_WordReplacement extends CRM_Core_DAO_WordReplacement {
       $wordReplacement = new CRM_Core_BAO_WordReplacement();
       $wordReplacement->id = CRM_Core_Config::wordReplacementID();
       if (!$wordReplacement->find(TRUE)) {
-        CRM_Core_Error::fatal();
+        throw new CRM_Core_Exception('Unable to find word replacement');
       }
     }
     return $wordReplacement;
diff --git a/civicrm/CRM/Core/Block.php b/civicrm/CRM/Core/Block.php
index 2194e46882..bbd3b427f8 100644
--- a/civicrm/CRM/Core/Block.php
+++ b/civicrm/CRM/Core/Block.php
@@ -120,7 +120,7 @@ class CRM_Core_Block {
           'template' => 'LangSwitch.tpl',
           'info' => ts('CiviCRM Language Switcher'),
           'subject' => '',
-          'templateValues' => array(),
+          'templateValues' => [],
           'active' => TRUE,
           'cache' => BLOCK_NO_CACHE,
           'visibility' => 1,
@@ -133,7 +133,7 @@ class CRM_Core_Block {
           'template' => 'Event.tpl',
           'info' => ts('CiviCRM Upcoming Events'),
           'subject' => ts('Upcoming Events'),
-          'templateValues' => array(),
+          'templateValues' => [],
           'active' => TRUE,
           'cache' => BLOCK_NO_CACHE,
           'visibility' => 1,
@@ -215,7 +215,7 @@ class CRM_Core_Block {
    */
   public static function getInfo() {
 
-    $block = array();
+    $block = [];
     foreach (self::properties() as $id => $value) {
       if ($value['active']) {
         if (in_array($id, array(
@@ -328,7 +328,7 @@ class CRM_Core_Block {
   private static function setTemplateShortcutValues() {
     $config = CRM_Core_Config::singleton();
 
-    static $shortCuts = array();
+    static $shortCuts = [];
 
     if (!($shortCuts)) {
       if (CRM_Core_Permission::check('add contacts')) {
@@ -397,7 +397,7 @@ class CRM_Core_Block {
       }
     }
 
-    $values = array();
+    $values = [];
     foreach ($shortCuts as $key => $short) {
       $values[$key] = self::setShortCutValues($short);
     }
@@ -431,7 +431,7 @@ class CRM_Core_Block {
    * @return array
    */
   private static function setShortcutValues($short) {
-    $value = array();
+    $value = [];
     if (isset($short['url'])) {
       $value['url'] = $short['url'];
     }
@@ -452,7 +452,7 @@ class CRM_Core_Block {
    * Create the list of dashboard links.
    */
   private static function setTemplateDashboardValues() {
-    static $dashboardLinks = array();
+    static $dashboardLinks = [];
     if (CRM_Core_Permission::check('access Contact Dashboard')) {
       $dashboardLinks = array(
         array(
@@ -467,9 +467,9 @@ class CRM_Core_Block {
       return NULL;
     }
 
-    $values = array();
+    $values = [];
     foreach ($dashboardLinks as $dash) {
-      $value = array();
+      $value = [];
       if (isset($dash['url'])) {
         $value['url'] = $dash['url'];
       }
@@ -504,9 +504,9 @@ class CRM_Core_Block {
       );
     }
 
-    $values = array();
+    $values = [];
     foreach ($shortCuts as $short) {
-      $value = array();
+      $value = [];
       $value['url'] = CRM_Utils_System::url($short['path'], $short['query']);
       $value['title'] = $short['title'];
       $values[] = $value;
@@ -601,7 +601,7 @@ class CRM_Core_Block {
       return NULL;
     }
 
-    $block = array();
+    $block = [];
     $block['name'] = 'block-civicrm';
     $block['id'] = $block['name'] . '_' . $id;
     $block['subject'] = self::fetch($id, 'Subject.tpl',
diff --git a/civicrm/CRM/Core/CommunityMessages.php b/civicrm/CRM/Core/CommunityMessages.php
index ff76489da4..081457351c 100644
--- a/civicrm/CRM/Core/CommunityMessages.php
+++ b/civicrm/CRM/Core/CommunityMessages.php
@@ -95,15 +95,16 @@ class CRM_Core_CommunityMessages {
       $isChanged = TRUE;
     }
 
-    if ($document['expires'] <= CRM_Utils_Time::getTimeRaw()) {
+    $refTime = CRM_Utils_Time::getTimeRaw();
+    if ($document['expires'] <= $refTime) {
       $newDocument = $this->fetchDocument();
       if ($newDocument && $this->validateDocument($newDocument)) {
         $document = $newDocument;
-        $document['expires'] = CRM_Utils_Time::getTimeRaw() + $document['ttl'];
+        $document['expires'] = $refTime + $document['ttl'];
       }
       else {
         // keep the old messages for now, try again later
-        $document['expires'] = CRM_Utils_Time::getTimeRaw() + $document['retry'];
+        $document['expires'] = $refTime + $document['retry'];
       }
       $isChanged = TRUE;
     }
diff --git a/civicrm/CRM/Core/Component.php b/civicrm/CRM/Core/Component.php
index b96694a43d..c594c3b6d8 100644
--- a/civicrm/CRM/Core/Component.php
+++ b/civicrm/CRM/Core/Component.php
@@ -70,7 +70,7 @@ class CRM_Core_Component {
    * @param bool $force
    *
    * @return CRM_Core_Component_Info[]
-   * @throws Exception
+   * @throws CRM_Core_Exception
    */
   public static function &getComponents($force = FALSE) {
     if (!isset(Civi::$statics[__CLASS__]['all']) || $force) {
@@ -87,7 +87,7 @@ class CRM_Core_Component {
         require_once $infoClassFile;
         $infoObject = new $infoClass($cr->name, $cr->namespace, $cr->id);
         if ($infoObject->info['name'] !== $cr->name) {
-          CRM_Core_Error::fatal("There is a discrepancy between name in component registry and in info file ({$cr->name}).");
+          throw new CRM_Core_Exception("There is a discrepancy between name in component registry and in info file ({$cr->name}).");
         }
         Civi::$statics[__CLASS__]['all'][$cr->name] = $infoObject;
         unset($infoObject);
diff --git a/civicrm/CRM/Core/Controller.php b/civicrm/CRM/Core/Controller.php
index 26a4eff054..0550fb39f3 100644
--- a/civicrm/CRM/Core/Controller.php
+++ b/civicrm/CRM/Core/Controller.php
@@ -556,8 +556,8 @@ class CRM_Core_Controller extends HTML_QuickForm_Controller {
   public function addWizardStyle(&$wizard) {
     $wizard['style'] = [
       'barClass' => '',
-      'stepPrefixCurrent' => '&raquo;',
-      'stepPrefixPast' => '&#x2714;',
+      'stepPrefixCurrent' => '<i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;',
+      'stepPrefixPast' => '<i class="crm-i fa-check" aria-hidden="true"></i>&nbsp;',
       'stepPrefixFuture' => ' ',
       'subStepPrefixCurrent' => '&nbsp;&nbsp;',
       'subStepPrefixPast' => '&nbsp;&nbsp;',
diff --git a/civicrm/CRM/Core/DAO.php b/civicrm/CRM/Core/DAO.php
index 2b670ae91e..1e245457ec 100644
--- a/civicrm/CRM/Core/DAO.php
+++ b/civicrm/CRM/Core/DAO.php
@@ -1481,12 +1481,6 @@ FROM   civicrm_domain
       return $result;
     }
 
-    if ($freeDAO ||
-      preg_match('/^(insert|update|delete|create|drop|replace)/i', $queryStr)
-    ) {
-      // we typically do this for insert/update/delete statements OR if explicitly asked to
-      // free the dao
-    }
     return $dao;
   }
 
@@ -1736,7 +1730,7 @@ FROM   civicrm_domain
       if (!$blockCopyofCustomValues) {
         $newObject->copyCustomFields($object->id, $newObject->id);
       }
-      CRM_Utils_Hook::post('create', CRM_Core_DAO_AllCoreTables::getBriefName(str_replace('_BAO_', '_DAO_', $daoName)), $newObject->id, $newObject);
+      CRM_Utils_Hook::post('create', CRM_Core_DAO_AllCoreTables::getBriefName($daoName), $newObject->id, $newObject);
     }
 
     return $newObject;
@@ -2459,7 +2453,7 @@ SELECT contact_id
       $coreReferences = CRM_Core_DAO::getReferencesToTable($tableName);
       foreach ($coreReferences as $coreReference) {
         if ($coreReference instanceof \CRM_Core_Reference_Dynamic) {
-          \Civi::$statics[__CLASS__]['contact_references_dynamic'][$tableName][$coreReference->getReferenceTable()][] = $coreReference->getReferenceKey();
+          \Civi::$statics[__CLASS__]['contact_references_dynamic'][$tableName][$coreReference->getReferenceTable()][] = [$coreReference->getReferenceKey(), $coreReference->getTypeColumn()];
         }
       }
     }
@@ -2857,11 +2851,11 @@ SELECT contact_id
    * Generates acl clauses suitable for adding to WHERE or ON when doing an api.get for this entity
    *
    * Return format is in the form of fieldname => clauses starting with an operator. e.g.:
-   * @code
+   * ```
    *   array(
    *     'location_type_id' => array('IS NOT NULL', 'IN (1,2,3)')
    *   )
-   * @endcode
+   * ```
    *
    * Note that all array keys must be actual field names in this entity. Use subqueries to filter on other tables e.g. custom values.
    *
diff --git a/civicrm/CRM/Core/DAO/AllCoreTables.php b/civicrm/CRM/Core/DAO/AllCoreTables.php
index 0fee62521c..9e292fdb5a 100644
--- a/civicrm/CRM/Core/DAO/AllCoreTables.php
+++ b/civicrm/CRM/Core/DAO/AllCoreTables.php
@@ -186,14 +186,86 @@ class CRM_Core_DAO_AllCoreTables {
   }
 
   /**
-   * Get the DAO for the class.
+   * Get the DAO for a BAO class.
    *
-   * @param string $className
+   * @param string $baoName
+   *
+   * @return string|CRM_Core_DAO
+   */
+  public static function getCanonicalClassName($baoName) {
+    return str_replace('_BAO_', '_DAO_', $baoName);
+  }
+
+  /**
+   * Get the BAO for a DAO class.
+   *
+   * @param string $daoName
    *
+   * @return string|CRM_Core_DAO
+   */
+  public static function getBAOClassName($daoName) {
+    $baoName = str_replace('_DAO_', '_BAO_', $daoName);
+    return class_exists($baoName) ? $baoName : $daoName;
+  }
+
+  /**
+   * Convert possibly underscore separated words to camel case with special handling for 'UF'
+   * e.g membership_payment returns MembershipPayment
+   *
+   * @param string $name
+   * @param bool $legacyV3
    * @return string
    */
-  public static function getCanonicalClassName($className) {
-    return str_replace('_BAO_', '_DAO_', $className);
+  public static function convertEntityNameToCamel(string $name, $legacyV3 = FALSE): string {
+    // This map only applies to APIv3
+    $map = [
+      'acl' => 'Acl',
+      'ACL' => 'Acl',
+      'im' => 'Im',
+      'IM' => 'Im',
+    ];
+    if ($legacyV3 && isset($map[$name])) {
+      return $map[$name];
+    }
+
+    $fragments = explode('_', $name);
+    foreach ($fragments as & $fragment) {
+      $fragment = ucfirst($fragment);
+      // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in without underscores)
+      if (strpos($fragment, 'Uf') === 0 && strlen($name) > 2) {
+        $fragment = 'UF' . ucfirst(substr($fragment, 2));
+      }
+    }
+    // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in underscore-separated)
+    if ($fragments[0] === 'Uf') {
+      $fragments[0] = 'UF';
+    }
+    return implode('', $fragments);
+  }
+
+  /**
+   * Convert CamelCase to snake_case, with special handling for some entity names.
+   *
+   * Eg. Activity returns activity
+   *     UFGroup returns uf_group
+   *     OptionValue returns option_value
+   *
+   * @param string $name
+   *
+   * @return string
+   */
+  public static function convertEntityNameToLower(string $name): string {
+    if ($name === strtolower($name)) {
+      return $name;
+    }
+    if ($name === 'PCP' || $name === 'IM' || $name === 'ACL') {
+      return strtolower($name);
+    }
+    return strtolower(ltrim(str_replace('U_F',
+      'uf',
+      // That's CamelCase, beside an odd UFCamel that is expected as uf_camel
+      preg_replace('/(?=[A-Z])/', '_$0', $name)
+    ), '_'));
   }
 
   /**
@@ -242,7 +314,8 @@ class CRM_Core_DAO_AllCoreTables {
    *   Ex: 'Contact'.
    */
   public static function getBriefName($className) {
-    return CRM_Utils_Array::value($className, array_flip(self::daoToClass()));
+    $className = self::getCanonicalClassName($className);
+    return array_search($className, self::daoToClass(), TRUE) ?: NULL;
   }
 
   /**
diff --git a/civicrm/CRM/Core/DAO/CustomField.php b/civicrm/CRM/Core/DAO/CustomField.php
index 7b8ded42ab..5c5e9a1036 100644
--- a/civicrm/CRM/Core/DAO/CustomField.php
+++ b/civicrm/CRM/Core/DAO/CustomField.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/CustomField.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:492b1be45dc41c15b35371410a074393)
+ * (GenCodeChecksum:0b21a2a1f1cba7a76fd8830db1626513)
  */
 
 /**
@@ -224,6 +224,13 @@ class CRM_Core_DAO_CustomField extends CRM_Core_DAO {
    */
   public $option_group_id;
 
+  /**
+   * Serialization method - a non-null value indicates a multi-valued field.
+   *
+   * @var int
+   */
+  public $serialize;
+
   /**
    * Stores Contact Get API params contact reference custom fields. May be used for other filters in the future.
    *
@@ -640,6 +647,20 @@ class CRM_Core_DAO_CustomField extends CRM_Core_DAO {
             'labelColumn' => 'title',
           ],
         ],
+        'serialize' => [
+          'name' => 'serialize',
+          'type' => CRM_Utils_Type::T_INT,
+          'title' => ts('Serialize'),
+          'description' => ts('Serialization method - a non-null value indicates a multi-valued field.'),
+          'where' => 'civicrm_custom_field.serialize',
+          'table_name' => 'civicrm_custom_field',
+          'entity' => 'CustomField',
+          'bao' => 'CRM_Core_BAO_CustomField',
+          'localizable' => 0,
+          'pseudoconstant' => [
+            'callback' => 'CRM_Core_SelectValues::fieldSerialization',
+          ],
+        ],
         'filter' => [
           'name' => 'filter',
           'type' => CRM_Utils_Type::T_STRING,
diff --git a/civicrm/CRM/Core/DAO/Factory.php b/civicrm/CRM/Core/DAO/Factory.php
index 66dd5a9d74..1401d2ba1d 100644
--- a/civicrm/CRM/Core/DAO/Factory.php
+++ b/civicrm/CRM/Core/DAO/Factory.php
@@ -24,12 +24,12 @@ class CRM_Core_DAO_Factory {
    * @param string $className
    *
    * @return mixed
-   * @throws Exception
+   * @throws CRM_Core_Exception
    */
   public static function create($className) {
     $type = self::$_classes[$className] ?? NULL;
     if (!$type) {
-      CRM_Core_Error::fatal("class $className not found");
+      throw new CRM_Core_Exception("class $className not found");
     }
 
     $class = self::$_prefix[$type] . $className;
diff --git a/civicrm/CRM/Core/DAO/OptionValue.php b/civicrm/CRM/Core/DAO/OptionValue.php
index 279f18540e..c2418be597 100644
--- a/civicrm/CRM/Core/DAO/OptionValue.php
+++ b/civicrm/CRM/Core/DAO/OptionValue.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/OptionValue.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:7aa11987c26800632c3798b4cfce95c1)
+ * (GenCodeChecksum:5997192c77d86867e8d13c353dd02351)
  */
 
 /**
@@ -281,7 +281,7 @@ class CRM_Core_DAO_OptionValue extends CRM_Core_DAO {
           'title' => ts('Filter'),
           'description' => ts('Bitwise logic can be used to create subsets of options within an option_group for different uses.'),
           'where' => 'civicrm_option_value.filter',
-          'default' => 'NULL',
+          'default' => '0',
           'table_name' => 'civicrm_option_value',
           'entity' => 'OptionValue',
           'bao' => 'CRM_Core_BAO_OptionValue',
diff --git a/civicrm/CRM/Core/Error.php b/civicrm/CRM/Core/Error.php
index 206570e51b..573cd4739c 100644
--- a/civicrm/CRM/Core/Error.php
+++ b/civicrm/CRM/Core/Error.php
@@ -184,6 +184,19 @@ class CRM_Core_Error extends PEAR_ErrorStack {
       }
     }
 
+    // Use the custom fatalErrorHandler if defined
+    if ($config->fatalErrorHandler && function_exists($config->fatalErrorHandler)) {
+      $name = $config->fatalErrorHandler;
+      $vars = [
+        'pearError' => $pearError,
+      ];
+      $ret = $name($vars);
+      if ($ret) {
+        // the call has been successfully handled so we just exit
+        self::abend(CRM_Core_Error::FATAL_ERROR);
+      }
+    }
+
     $template->assign_by_ref('error', $error);
     $errorDetails = CRM_Core_Error::debug('', $error, FALSE);
     $template->assign_by_ref('errorDetails', $errorDetails);
@@ -204,7 +217,7 @@ class CRM_Core_Error extends PEAR_ErrorStack {
       exit;
     }
     $runOnce = TRUE;
-    self::abend(1);
+    self::abend(CRM_Core_Error::FATAL_ERROR);
   }
 
   /**
@@ -559,6 +572,18 @@ class CRM_Core_Error extends PEAR_ErrorStack {
     }
     $file_log->close();
 
+    // Use the custom fatalErrorHandler if defined
+    if (in_array($priority, [PEAR_LOG_EMERG, PEAR_LOG_ALERT, PEAR_LOG_CRIT, PEAR_LOG_ERR])) {
+      if ($config->fatalErrorHandler && function_exists($config->fatalErrorHandler)) {
+        $name = $config->fatalErrorHandler;
+        $vars = [
+          'debugLogMessage' => $message,
+          'priority' => $priority,
+        ];
+        $name($vars);
+      }
+    }
+
     if (!isset(\Civi::$statics[__CLASS__]['userFrameworkLogging'])) {
       // Set it to FALSE first & then try to set it. This is to prevent a loop as calling
       // $config->userFrameworkLogging can trigger DB queries & under log mode this
@@ -651,22 +676,30 @@ class CRM_Core_Error extends PEAR_ErrorStack {
 
       $prefixString = $prefix ? ($prefix . '.') : '';
 
-      $hash = self::generateLogFileHash($config);
-      $fileName = $config->configAndLogDir . 'CiviCRM.' . $prefixString . $hash . '.log';
+      if (CRM_Utils_Constant::value('CIVICRM_LOG_HASH', TRUE)) {
+        $hash = self::generateLogFileHash($config) . '.';
+      }
+      else {
+        $hash = '';
+      }
+      $fileName = $config->configAndLogDir . 'CiviCRM.' . $prefixString . $hash . 'log';
 
-      // Roll log file monthly or if greater than 256M.
+      // Roll log file monthly or if greater than our threshold.
       // Size-based rotation introduced in response to filesize limits on
       // certain OS/PHP combos.
-      if (file_exists($fileName)) {
-        $fileTime = date("Ym", filemtime($fileName));
-        $fileSize = filesize($fileName);
-        if (($fileTime < date('Ym')) ||
-          ($fileSize > 256 * 1024 * 1024) ||
-          ($fileSize < 0)
-        ) {
-          rename($fileName,
-            $fileName . '.' . date('YmdHi')
-          );
+      $maxBytes = CRM_Utils_Constant::value('CIVICRM_LOG_ROTATESIZE', 256 * 1024 * 1024);
+      if ($maxBytes) {
+        if (file_exists($fileName)) {
+          $fileTime = date("Ym", filemtime($fileName));
+          $fileSize = filesize($fileName);
+          if (($fileTime < date('Ym')) ||
+            ($fileSize > $maxBytes) ||
+            ($fileSize < 0)
+          ) {
+            rename($fileName,
+              $fileName . '.' . date('YmdHi')
+            );
+          }
         }
       }
       \Civi::$statics[__CLASS__]['logger_file' . $prefix] = $fileName;
diff --git a/civicrm/CRM/Core/Form.php b/civicrm/CRM/Core/Form.php
index 416085c733..a3c4023c0e 100644
--- a/civicrm/CRM/Core/Form.php
+++ b/civicrm/CRM/Core/Form.php
@@ -421,7 +421,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
 
     $element = $this->addElement($type, $name, CRM_Utils_String::purifyHTML($label), $attributes, $extra);
     if (HTML_QuickForm::isError($element)) {
-      CRM_Core_Error::fatal(HTML_QuickForm::errorMessage($element));
+      CRM_Core_Error::statusBounce(HTML_QuickForm::errorMessage($element));
     }
 
     if ($inputType == 'color') {
@@ -436,7 +436,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
         $error = $this->addRule($name, ts('%1 is a required field.', [1 => $label]), 'required');
       }
       if (HTML_QuickForm::isError($error)) {
-        CRM_Core_Error::fatal(HTML_QuickForm::errorMessage($element));
+        CRM_Core_Error::statusBounce(HTML_QuickForm::errorMessage($element));
       }
     }
 
@@ -2015,7 +2015,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
   public function addEntityRef($name, $label = '', $props = [], $required = FALSE) {
     // Default properties
     $props['api'] = CRM_Utils_Array::value('api', $props, []);
-    $props['entity'] = CRM_Utils_String::convertStringToCamel(CRM_Utils_Array::value('entity', $props, 'Contact'));
+    $props['entity'] = CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel(CRM_Utils_Array::value('entity', $props, 'Contact'));
     $props['class'] = ltrim(CRM_Utils_Array::value('class', $props, '') . ' crm-form-entityref');
 
     if (array_key_exists('create', $props) && empty($props['create'])) {
diff --git a/civicrm/CRM/Core/Form/Renderer.php b/civicrm/CRM/Core/Form/Renderer.php
index 8450a9baa2..8b224a98c2 100644
--- a/civicrm/CRM/Core/Form/Renderer.php
+++ b/civicrm/CRM/Core/Form/Renderer.php
@@ -370,7 +370,10 @@ class CRM_Core_Form_Renderer extends HTML_QuickForm_Renderer_ArraySmarty {
       $path = $field->getAttribute('data-option-edit-path');
       // NOTE: If we ever needed to support arguments in this link other than reset=1 we could split $path here if it contains a ?
       $url = CRM_Utils_System::url($path, 'reset=1');
-      $el['html'] .= ' <a href="' . $url . '" class="crm-option-edit-link medium-popup crm-hover-button" target="_blank" title="' . ts('Edit Options') . '" data-option-edit-path="' . $path . '"><i class="crm-i fa-wrench"></i></a>';
+      $icon = CRM_Core_Page::crmIcon('fa-wrench', ts('Edit %1 Options', [1 => $field->getLabel() ?: ts('Field')]));
+      $el['html'] .= <<<HEREDOC
+ <a href="$url" class="crm-option-edit-link medium-popup crm-hover-button" target="_blank" data-option-edit-path="$path">$icon</a>
+HEREDOC;
     }
   }
 
@@ -382,7 +385,7 @@ class CRM_Core_Form_Renderer extends HTML_QuickForm_Renderer_ArraySmarty {
     // Initially hide if not needed
     // Note: visibility:hidden prevents layout jumping around unlike display:none
     $display = $field->getValue() !== NULL ? '' : ' style="visibility:hidden;"';
-    $el['html'] .= ' <a href="#" class="crm-hover-button crm-clear-link"' . $display . ' title="' . ts('Clear') . '"><i class="crm-i fa-times"></i></a>';
+    $el['html'] .= ' <a href="#" class="crm-hover-button crm-clear-link"' . $display . ' title="' . ts('Clear') . '"><i class="crm-i fa-times" aria-hidden="true"></i></a>';
   }
 
 }
diff --git a/civicrm/CRM/Core/I18n.php b/civicrm/CRM/Core/I18n.php
index 2f0e3207f3..357dc2f936 100644
--- a/civicrm/CRM/Core/I18n.php
+++ b/civicrm/CRM/Core/I18n.php
@@ -38,18 +38,26 @@ class CRM_Core_I18n {
   public static $SQL_ESCAPER = NULL;
 
   /**
-   * Encode a string for use in SQL.
+   * Escape a string if a mode is specified, otherwise return string unmodified.
    *
    * @param string $text
+   * @param string $mode
    * @return string
    */
-  protected static function escapeSql($text) {
-    if (self::$SQL_ESCAPER == NULL) {
-      return CRM_Core_DAO::escapeString($text);
-    }
-    else {
-      return call_user_func(self::$SQL_ESCAPER, $text);
+  protected static function escape($text, $mode) {
+    switch ($mode) {
+      case 'sql':
+        if (self::$SQL_ESCAPER == NULL) {
+          return CRM_Core_DAO::escapeString($text);
+        }
+        else {
+          return call_user_func(self::$SQL_ESCAPER, $text);
+        }
+
+      case 'js':
+        return substr(json_encode($text, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT), 1, -1);
     }
+    return $text;
   }
 
   /**
@@ -312,23 +320,15 @@ class CRM_Core_I18n {
    *   the translated string
    */
   public function crm_translate($text, $params = []) {
-    if (isset($params['escape'])) {
-      $escape = $params['escape'];
-      unset($params['escape']);
-    }
+    $escape = $params['escape'] ?? NULL;
+    unset($params['escape']);
 
     // sometimes we need to {ts}-tag a string, but don’t want to
     // translate it in the template (like civicrm_navigation.tpl),
     // because we handle the translation in a different way (CRM-6998)
     // in such cases we return early, only doing SQL/JS escaping
     if (isset($params['skip']) and $params['skip']) {
-      if (isset($escape) and ($escape == 'sql')) {
-        $text = self::escapeSql($text);
-      }
-      if (isset($escape) and ($escape == 'js')) {
-        $text = addcslashes($text, "'");
-      }
-      return $text;
+      return self::escape($text, $escape);
     }
 
     $plural = $count = NULL;
@@ -385,17 +385,7 @@ class CRM_Core_I18n {
       $text = $this->strarg($text, $params);
     }
 
-    // escape SQL if we were asked for it
-    if (isset($escape) and ($escape == 'sql')) {
-      $text = self::escapeSql($text);
-    }
-
-    // escape for JavaScript (if requested)
-    if (isset($escape) and ($escape == 'js')) {
-      $text = addcslashes($text, "'");
-    }
-
-    return $text;
+    return self::escape($text, $escape);
   }
 
   /**
diff --git a/civicrm/CRM/Core/I18n/Form.php b/civicrm/CRM/Core/I18n/Form.php
index 2c36e24639..6beb1d669d 100644
--- a/civicrm/CRM/Core/I18n/Form.php
+++ b/civicrm/CRM/Core/I18n/Form.php
@@ -27,7 +27,7 @@ class CRM_Core_I18n_Form extends CRM_Core_Form {
     $id = CRM_Utils_Request::retrieve('id', 'Int', $this);
     $this->_structure = CRM_Core_I18n_SchemaStructure::columns();
     if (!isset($this->_structure[$table][$field])) {
-      CRM_Core_Error::fatal("$table.$field is not internationalized.");
+      CRM_Core_Error::statusBounce("$table.$field is not internationalized.");
     }
 
     $this->addElement('hidden', 'table', $table);
@@ -106,7 +106,7 @@ class CRM_Core_I18n_Form extends CRM_Core_Form {
 
     // validate table and field
     if (!isset($this->_structure[$table][$field])) {
-      CRM_Core_Error::fatal("$table.$field is not internationalized.");
+      CRM_Core_Error::statusBounce("$table.$field is not internationalized.");
     }
 
     $cols = [];
diff --git a/civicrm/CRM/Core/I18n/SchemaStructure.php b/civicrm/CRM/Core/I18n/SchemaStructure.php
index c76ece1754..ecadf83929 100644
--- a/civicrm/CRM/Core/I18n/SchemaStructure.php
+++ b/civicrm/CRM/Core/I18n/SchemaStructure.php
@@ -118,7 +118,7 @@ class CRM_Core_I18n_SchemaStructure {
           'title' => "varchar(127) COMMENT 'Payment Processor Descriptive Name.'",
         ],
         'civicrm_membership_type' => [
-          'name' => "varchar(128) COMMENT 'Name of Membership Type'",
+          'name' => "varchar(128) NOT NULL COMMENT 'Name of Membership Type'",
           'description' => "varchar(255) COMMENT 'Description of Membership Type'",
         ],
         'civicrm_membership_block' => [
@@ -154,7 +154,7 @@ class CRM_Core_I18n_SchemaStructure {
           'help_post' => "text COMMENT 'Description and/or help text to display after this field.'",
         ],
         'civicrm_price_field_value' => [
-          'label' => "varchar(255) COMMENT 'Price field option label'",
+          'label' => "varchar(255) NOT NULL COMMENT 'Price field option label'",
           'description' => "text DEFAULT NULL COMMENT 'Price field option description.'",
           'help_pre' => "text DEFAULT NULL COMMENT 'Price field option pre help text.'",
           'help_post' => "text DEFAULT NULL COMMENT 'Price field option post field help.'",
@@ -486,6 +486,7 @@ class CRM_Core_I18n_SchemaStructure {
           'name' => [
             'type' => "Text",
             'label' => "Name",
+            'required' => "true",
           ],
           'description' => [
             'type' => "TextArea",
@@ -585,6 +586,7 @@ class CRM_Core_I18n_SchemaStructure {
         'civicrm_price_field_value' => [
           'label' => [
             'type' => "Text",
+            'required' => "true",
           ],
           'description' => [
             'type' => "TextArea",
diff --git a/civicrm/CRM/Core/Invoke.php b/civicrm/CRM/Core/Invoke.php
index b0262dfda7..780ae182fa 100644
--- a/civicrm/CRM/Core/Invoke.php
+++ b/civicrm/CRM/Core/Invoke.php
@@ -102,7 +102,7 @@ class CRM_Core_Invoke {
         return CRM_Utils_System::redirect();
       }
       else {
-        CRM_Core_Error::fatal('You do not have permission to execute this url');
+        CRM_Core_Error::statusBounce('You do not have permission to execute this url');
       }
     }
   }
@@ -224,7 +224,7 @@ class CRM_Core_Invoke {
 
       if (!array_key_exists('page_callback', $item)) {
         CRM_Core_Error::debug('Bad item', $item);
-        CRM_Core_Error::fatal(ts('Bad menu record in database'));
+        CRM_Core_Error::statusBounce(ts('Bad menu record in database'));
       }
 
       // check that we are permissioned to access this page
@@ -307,7 +307,7 @@ class CRM_Core_Invoke {
           $object = new $item['page_callback']($title, TRUE, $mode, NULL, $addSequence);
         }
         else {
-          CRM_Core_Error::fatal();
+          throw new CRM_Core_Exception('Execute supplied menu action');
         }
         $result = $object->run($newArgs, $pageArgs);
       }
diff --git a/civicrm/CRM/Core/Menu.php b/civicrm/CRM/Core/Menu.php
index 5ec868771e..390d6a2a7c 100644
--- a/civicrm/CRM/Core/Menu.php
+++ b/civicrm/CRM/Core/Menu.php
@@ -74,7 +74,7 @@ class CRM_Core_Menu {
       // lets call a hook and get any additional files if needed
       CRM_Utils_Hook::xmlMenu($files);
 
-      self::$_items = array();
+      self::$_items = [];
       foreach ($files as $file) {
         self::read($file, self::$_items);
       }
@@ -105,22 +105,24 @@ class CRM_Core_Menu {
    *   An XML document defining a list of menu items.
    * @param array $menu
    *   An alterable list of menu items.
+   *
+   * @throws CRM_Core_Exception
    */
   public static function readXML($xml, &$menu) {
     $config = CRM_Core_Config::singleton();
     foreach ($xml->item as $item) {
       if (!(string ) $item->path) {
         CRM_Core_Error::debug('i', $item);
-        CRM_Core_Error::fatal();
+        throw new CRM_Core_Exception('Unable to read XML file');
       }
       $path = (string ) $item->path;
-      $menu[$path] = array();
+      $menu[$path] = [];
       unset($item->path);
 
       if ($item->ids_arguments) {
-        $ids = array();
+        $ids = [];
         foreach (array('json' => 'json', 'html' => 'html', 'exception' => 'exceptions') as $tag => $attr) {
-          $ids[$attr] = array();
+          $ids[$attr] = [];
           foreach ($item->ids_arguments->{$tag} as $value) {
             $ids[$attr][] = (string) $value;
           }
@@ -152,7 +154,7 @@ class CRM_Core_Menu {
               $elements = explode(';', $value);
               $op = 'or';
             }
-            $items = array();
+            $items = [];
             foreach ($elements as $element) {
               $items[] = $element;
             }
@@ -204,7 +206,7 @@ class CRM_Core_Menu {
    * @param array $menu
    * @param string $path
    *
-   * @throws Exception
+   * @throws CRM_Core_Exception
    */
   public static function fillMenuValues(&$menu, $path) {
     $fieldsToPropagate = array(
@@ -214,7 +216,7 @@ class CRM_Core_Menu {
       'page_arguments',
       'is_ssl',
     );
-    $fieldsPresent = array();
+    $fieldsPresent = [];
     foreach ($fieldsToPropagate as $field) {
       $fieldsPresent[$field] = isset($menu[$path][$field]);
     }
@@ -240,15 +242,15 @@ class CRM_Core_Menu {
       return;
     }
 
-    $messages = array();
+    $messages = [];
     foreach ($fieldsToPropagate as $field) {
       if (!$fieldsPresent[$field]) {
         $messages[] = ts("Could not find %1 in path tree",
-          array(1 => $field)
+          [1 => $field]
         );
       }
     }
-    CRM_Core_Error::fatal("'$path': " . implode(', ', $messages));
+    throw new CRM_Core_Exception("'$path': " . implode(', ', $messages));
   }
 
   /**
@@ -305,7 +307,7 @@ class CRM_Core_Menu {
         CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_menu', 'module_data', FALSE)
       ) {
         // Move unrecognized fields to $module_data.
-        $module_data = array();
+        $module_data = [];
         foreach (array_keys($item) as $key) {
           if (!isset($daoFields[$key])) {
             $module_data[$key] = $item[$key];
@@ -339,7 +341,7 @@ class CRM_Core_Menu {
    * @param array $menu
    */
   public static function buildAdminLinks(&$menu) {
-    $values = array();
+    $values = [];
 
     foreach ($menu as $path => $item) {
       if (empty($item['adminGroup'])) {
@@ -370,15 +372,14 @@ class CRM_Core_Menu {
         'extra' => $item['extra'] ?? NULL,
       );
       if (!array_key_exists($item['adminGroup'], $values)) {
-        $values[$item['adminGroup']] = array();
-        $values[$item['adminGroup']]['fields'] = array();
+        $values[$item['adminGroup']] = [];
+        $values[$item['adminGroup']]['fields'] = [];
       }
       $values[$item['adminGroup']]['fields']["{weight}.{$item['title']}"] = $value;
       $values[$item['adminGroup']]['component_id'] = $item['component_id'];
     }
 
     foreach ($values as $group => $dontCare) {
-      $values[$group]['perColumn'] = round(count($values[$group]['fields']) / 2);
       ksort($values[$group]);
     }
 
@@ -415,7 +416,7 @@ class CRM_Core_Menu {
    *   The breadcrumb for this path
    */
   public static function buildBreadcrumb(&$menu, $path) {
-    $crumbs = array();
+    $crumbs = [];
 
     $pathElements = explode('/', $path);
     array_pop($pathElements);
@@ -505,7 +506,7 @@ class CRM_Core_Menu {
    * @throws \CRM_Core_Exception
    */
   public static function fillComponentIds(&$menu, $path) {
-    static $cache = array();
+    static $cache = [];
 
     if (array_key_exists('component_id', $menu[$path])) {
       return;
@@ -550,7 +551,7 @@ class CRM_Core_Menu {
 
     $args = explode('/', $path);
 
-    $elements = array();
+    $elements = [];
     while (!empty($args)) {
       $string = implode('/', $args);
       $string = CRM_Core_DAO::escapeString($string);
@@ -586,10 +587,10 @@ UNION (
     $menu = new CRM_Core_DAO_Menu();
     $menu->query($query);
 
-    self::$_menuCache = array();
+    self::$_menuCache = [];
     $menuPath = NULL;
     while ($menu->fetch()) {
-      self::$_menuCache[$menu->path] = array();
+      self::$_menuCache[$menu->path] = [];
       CRM_Core_DAO::storeValues($menu, self::$_menuCache[$menu->path]);
 
       // Move module_data into main item.
@@ -646,7 +647,7 @@ UNION (
     if (!is_string($pathArgs)) {
       return;
     }
-    $args = array();
+    $args = [];
 
     $elements = explode(',', $pathArgs);
     foreach ($elements as $keyVal) {
@@ -655,7 +656,7 @@ UNION (
     }
 
     if (array_key_exists('urlToSession', $arr)) {
-      $urlToSession = array();
+      $urlToSession = [];
 
       $params = explode(';', $arr['urlToSession']);
       $count = 0;
diff --git a/civicrm/CRM/Core/OptionGroup.php b/civicrm/CRM/Core/OptionGroup.php
index 2540c15471..89018c1a21 100644
--- a/civicrm/CRM/Core/OptionGroup.php
+++ b/civicrm/CRM/Core/OptionGroup.php
@@ -439,8 +439,6 @@ WHERE  v.option_group_id = g.id
 
   /**
    * Creates a new option group with the passed in values.
-   * @TODO: Should update the group if it already exists intelligently, so multi-lingual is
-   * not messed up. Currently deletes the old group
    *
    * @param string $groupName
    *   The name of the option group - make sure there is no conflict.
@@ -464,10 +462,10 @@ WHERE  v.option_group_id = g.id
    *   the option group ID
    */
   public static function createAssoc($groupName, &$values, &$defaultID, $groupTitle = NULL) {
-    self::deleteAssoc($groupName);
     if (!empty($values)) {
       $group = new CRM_Core_DAO_OptionGroup();
       $group->name = $groupName;
+      $group->find(TRUE);
       $group->title = empty($groupTitle) ? $groupName : $groupTitle;
       $group->is_reserved = 1;
       $group->is_active = 1;
@@ -476,8 +474,9 @@ WHERE  v.option_group_id = g.id
       foreach ($values as $v) {
         $value = new CRM_Core_DAO_OptionValue();
         $value->option_group_id = $group->id;
-        $value->label = $v['label'];
         $value->value = $v['value'];
+        $value->find(TRUE);
+        $value->label = $v['label'];
         $value->name = $v['name'] ?? NULL;
         $value->description = $v['description'] ?? NULL;
         $value->weight = $v['weight'] ?? NULL;
@@ -502,8 +501,11 @@ WHERE  v.option_group_id = g.id
    * @param $values
    * @param bool $flip
    * @param string $field
+   *
+   * @deprecated
    */
   public static function getAssoc($groupName, &$values, $flip = FALSE, $field = 'name') {
+    CRM_Core_Error::deprecatedFunctionWarning('unused function');
     $query = "
 SELECT v.id as amount_id, v.value, v.label, v.name, v.description, v.weight
   FROM civicrm_option_group g,
@@ -546,8 +548,11 @@ ORDER BY v.weight
   /**
    * @param string $groupName
    * @param string $operator
+   *
+   * @deprecated
    */
   public static function deleteAssoc($groupName, $operator = "=") {
+    CRM_Core_Error::deprecatedFunctionWarning('unused function');
     $query = "
 DELETE g, v
   FROM civicrm_option_group g,
diff --git a/civicrm/CRM/Core/Page.php b/civicrm/CRM/Core/Page.php
index 251c642d75..f83b170f93 100644
--- a/civicrm/CRM/Core/Page.php
+++ b/civicrm/CRM/Core/Page.php
@@ -418,4 +418,58 @@ class CRM_Core_Page {
     $this->assign('fields', $dateFields);
   }
 
+  /**
+   * Handy helper to produce the standard markup for an icon with alternative
+   * text for a title and screen readers.
+   *
+   * See also the smarty block function `icon`
+   *
+   * @param string $icon
+   *   The class name of the icon to display.
+   * @param string $text
+   *   The translated text to display.
+   * @param bool $condition
+   *   Whether to display anything at all. This helps simplify code when a
+   *   checkmark should appear if something is true.
+   * @param array $attribs
+   *   Attributes to set or override on the icon element.  Any standard
+   *   attribute can be unset by setting the value to an empty string.
+   *
+   * @return string
+   *   The whole bit to drop in.
+   */
+  public static function crmIcon($icon, $text = NULL, $condition = TRUE, $attribs = []) {
+    if (!$condition) {
+      return '';
+    }
+
+    // Add icon classes to any that might exist in $attribs
+    $classes = array_key_exists('class', $attribs) ? explode(' ', $attribs['class']) : [];
+    $classes[] = 'crm-i';
+    $classes[] = $icon;
+    $attribs['class'] = implode(' ', array_unique($classes));
+
+    $standardAttribs = ['aria-hidden' => 'true'];
+    if ($text === NULL || $text === '') {
+      $title = $sr = '';
+    }
+    else {
+      $standardAttribs['title'] = $text;
+      $sr = "<span class=\"sr-only\">$text</span>";
+    }
+
+    // Assemble attribs
+    $attribString = '';
+    // Strip out title if $attribs specifies a blank title
+    $attribs = array_merge($standardAttribs, $attribs);
+    foreach ($attribs as $attrib => $val) {
+      if (strlen($val)) {
+        $val = htmlspecialchars($val);
+        $attribString .= " $attrib=\"$val\"";
+      }
+    }
+
+    return "<i$attribString></i>$sr";
+  }
+
 }
diff --git a/civicrm/CRM/Core/Page/Redirect.php b/civicrm/CRM/Core/Page/Redirect.php
index 90be62a20b..15141ae4f0 100644
--- a/civicrm/CRM/Core/Page/Redirect.php
+++ b/civicrm/CRM/Core/Page/Redirect.php
@@ -3,13 +3,13 @@
 /**
  * Placeholder page which generates a redirect
  *
- * @code
+ * ```
  * <item>
  *   <path>civicrm/admin/options/case_type</path>
  *   <page_callback>CRM_Core_Page_Redirect</page_callback>
  *   <page_arguments>url=civicrm/foo/bar?whiz=bang&amp;passthru=%%passthru%%</page_arguments>
  * </item>
- * @endcoe
+ * ```
  */
 class CRM_Core_Page_Redirect extends CRM_Core_Page {
 
diff --git a/civicrm/CRM/Core/Payment.php b/civicrm/CRM/Core/Payment.php
index 288359d4e5..c4e4deb2c5 100644
--- a/civicrm/CRM/Core/Payment.php
+++ b/civicrm/CRM/Core/Payment.php
@@ -94,7 +94,7 @@ abstract class CRM_Core_Payment {
   /**
    * Processor type label.
    *
-   * (Deprecated parameter but used in some messages).
+   * (Deprecated unused parameter).
    *
    * @var string
    * @deprecated
@@ -399,6 +399,19 @@ abstract class CRM_Core_Payment {
     return method_exists(CRM_Utils_System::getClassName($this), 'cancelSubscription');
   }
 
+  /**
+   * Does the processor support the user having a choice as to whether to cancel the recurring with the processor?
+   *
+   * If this returns TRUE then there will be an option to send a cancellation request in the cancellation form.
+   *
+   * This would normally be false for processors where CiviCRM maintains the schedule.
+   *
+   * @return bool
+   */
+  protected function supportsCancelRecurringNotifyOptional() {
+    return $this->supportsCancelRecurring();
+  }
+
   /**
    * Does this processor support pre-approval.
    *
@@ -615,7 +628,10 @@ abstract class CRM_Core_Payment {
         }
 
       case 'cancelRecurNotSupportedText':
-        return ts('Automatic cancellation is not supported for this payment processor. You or the contributor will need to manually cancel this recurring contribution using the payment processor website.');
+        if (!$this->supportsCancelRecurring()) {
+          return ts('Automatic cancellation is not supported for this payment processor. You or the contributor will need to manually cancel this recurring contribution using the payment processor website.');
+        }
+        return '';
 
     }
     CRM_Core_Error::deprecatedFunctionWarning('Calls to getText must use a supported method');
@@ -1375,6 +1391,11 @@ abstract class CRM_Core_Payment {
    * proceed. Note the form layer will only call this after calling
    * $processor->supports('cancelRecurring');
    *
+   * A payment processor can control whether to notify the actual payment provider or just
+   * cancel in CiviCRM by setting the `isNotifyProcessorOnCancelRecur` property on PropertyBag.
+   * If supportsCancelRecurringNotifyOptional() is TRUE this will be automatically set based on
+   * the user selection on the form. If FALSE you need to set it yourself.
+   *
    * @param \Civi\Payment\PropertyBag $propertyBag
    *
    * @return array
@@ -1382,7 +1403,8 @@ abstract class CRM_Core_Payment {
    * @throws \Civi\Payment\Exception\PaymentProcessorException
    */
   public function doCancelRecurring(PropertyBag $propertyBag) {
-    if (method_exists($this, 'cancelSubscription')) {
+    if (method_exists($this, 'cancelSubscription')
+    && ($propertyBag->has('isNotifyProcessorOnCancelRecur') && $propertyBag->getIsNotifyProcessorOnCancelRecur())) {
       $message = NULL;
       if ($this->cancelSubscription($message, $propertyBag)) {
         return ['message' => $message];
diff --git a/civicrm/CRM/Core/Payment/AuthorizeNet.php b/civicrm/CRM/Core/Payment/AuthorizeNet.php
index 52657cf221..abf5e4aaa7 100644
--- a/civicrm/CRM/Core/Payment/AuthorizeNet.php
+++ b/civicrm/CRM/Core/Payment/AuthorizeNet.php
@@ -33,12 +33,23 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
   protected $_params = [];
 
   /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
+   * @var GuzzleHttp\Client
    */
-  static private $_singleton = NULL;
+  protected $guzzleClient;
+
+  /**
+   * @return \GuzzleHttp\Client
+   */
+  public function getGuzzleClient(): \GuzzleHttp\Client {
+    return $this->guzzleClient ?? new \GuzzleHttp\Client();
+  }
+
+  /**
+   * @param \GuzzleHttp\Client $guzzleClient
+   */
+  public function setGuzzleClient(\GuzzleHttp\Client $guzzleClient) {
+    $this->guzzleClient = $guzzleClient;
+  }
 
   /**
    * Constructor.
@@ -53,7 +64,6 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
   public function __construct($mode, &$paymentProcessor) {
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('Authorize.net');
 
     $this->_setParam('apiLogin', $paymentProcessor['user_name']);
     $this->_setParam('paymentKey', $paymentProcessor['password']);
@@ -98,6 +108,8 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
    *
    * @return array
    *   the result in a nice formatted array (or an error object)
+   *
+   * @throws \Civi\Payment\Exception\PaymentProcessorException
    */
   public function doDirectPayment(&$params) {
     if (!defined('CURLOPT_SSLCERT')) {
@@ -233,7 +245,7 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
       $intervalLength *= 12;
       $intervalUnit = 'months';
     }
-    elseif ($intervalUnit == 'day') {
+    elseif ($intervalUnit === 'day') {
       $intervalUnit = 'days';
     }
     elseif ($intervalUnit == 'month') {
@@ -316,30 +328,22 @@ class CRM_Core_Payment_AuthorizeNet extends CRM_Core_Payment {
     $template->assign('billingCountry', $this->_getParam('country'));
 
     $arbXML = $template->fetch('CRM/Contribute/Form/Contribution/AuthorizeNetARB.tpl');
-    // submit to authorize.net
 
-    $submit = curl_init($this->_paymentProcessor['url_recur']);
-    if (!$submit) {
-      return self::error(9002, 'Could not initiate connection to payment gateway');
-    }
-    curl_setopt($submit, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($submit, CURLOPT_HTTPHEADER, ["Content-Type: text/xml"]);
-    curl_setopt($submit, CURLOPT_HEADER, 1);
-    curl_setopt($submit, CURLOPT_POSTFIELDS, $arbXML);
-    curl_setopt($submit, CURLOPT_POST, 1);
-    curl_setopt($submit, CURLOPT_SSL_VERIFYPEER, Civi::settings()->get('verifySSL'));
-
-    $response = curl_exec($submit);
-
-    if (!$response) {
-      return self::error(curl_errno($submit), curl_error($submit));
-    }
-
-    curl_close($submit);
-    $responseFields = $this->_ParseArbReturn($response);
-
-    if ($responseFields['resultCode'] == 'Error') {
-      return self::error($responseFields['code'], $responseFields['text']);
+    // Submit to authorize.net
+    $response = $this->getGuzzleClient()->post($this->_paymentProcessor['url_recur'], [
+      'headers' => [
+        'Content-Type' => 'text/xml; charset=UTF8',
+      ],
+      'body' => $arbXML,
+      'curl' => [
+        CURLOPT_RETURNTRANSFER => TRUE,
+        CURLOPT_SSL_VERIFYPEER => Civi::settings()->get('verifySSL'),
+      ],
+    ]);
+    $responseFields = $this->_ParseArbReturn((string) $response->getBody());
+
+    if ($responseFields['resultCode'] === 'Error') {
+      throw new PaymentProcessorException($responseFields['code'], $responseFields['text']);
     }
 
     // update recur processor_id with subscriptionId
diff --git a/civicrm/CRM/Core/Payment/BaseIPN.php b/civicrm/CRM/Core/Payment/BaseIPN.php
index 2da96d6cc4..8f5dd3786f 100644
--- a/civicrm/CRM/Core/Payment/BaseIPN.php
+++ b/civicrm/CRM/Core/Payment/BaseIPN.php
@@ -85,7 +85,7 @@ class CRM_Core_Payment_BaseIPN {
    *
    * @return bool
    */
-  public function validateData(&$input, &$ids, &$objects, $required = TRUE, $paymentProcessorID = NULL) {
+  public function validateData($input, &$ids, &$objects, $required = TRUE, $paymentProcessorID = NULL) {
 
     // Check if the contribution exists
     // make sure contribution exists and is valid
@@ -158,7 +158,7 @@ class CRM_Core_Payment_BaseIPN {
    *
    * @return bool|array
    */
-  public function loadObjects(&$input, &$ids, &$objects, $required, $paymentProcessorID, $error_handling = NULL) {
+  public function loadObjects($input, &$ids, &$objects, $required, $paymentProcessorID, $error_handling = NULL) {
     if (empty($error_handling)) {
       // default options are that we log an error & echo it out
       // note that we should refactor this error handling into error code @ some point
@@ -274,15 +274,18 @@ class CRM_Core_Payment_BaseIPN {
   /**
    * Handled pending contribution status.
    *
+   * @deprecated
+   *
    * @param array $objects
    * @param object $transaction
    *
    * @return bool
    */
   public function pending(&$objects, &$transaction) {
+    CRM_Core_Error::deprecatedFunctionWarning('This function will be removed at some point');
     $transaction->commit();
-    Civi::log()->debug("Returning since contribution status is Pending");
-    echo "Success: Returning since contribution status is pending<p>";
+    Civi::log()->debug('Returning since contribution status is Pending');
+    echo 'Success: Returning since contribution status is pending<p>';
     return TRUE;
   }
 
diff --git a/civicrm/CRM/Core/Payment/Dummy.php b/civicrm/CRM/Core/Payment/Dummy.php
index e0a079a8f1..1f3d9336cd 100644
--- a/civicrm/CRM/Core/Payment/Dummy.php
+++ b/civicrm/CRM/Core/Payment/Dummy.php
@@ -11,18 +11,16 @@
  *
  * @package CRM
  * @author Marshal Newrock <marshal@idealso.com>
- * $Id: Dummy.php 45429 2013-02-06 22:11:18Z lobo $
  */
 
 use Civi\Payment\Exception\PaymentProcessorException;
+use Civi\Payment\PropertyBag;
 
 /**
  * Dummy payment processor
  */
 class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
-  const CHARSET = 'iso-8859-1';
-
-  protected $_mode = NULL;
+  protected $_mode;
 
   protected $_params = [];
   protected $_doDirectPaymentResult = [];
@@ -43,28 +41,17 @@ class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
     }
   }
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * Constructor.
    *
    * @param string $mode
    *   The mode of operation: live or test.
    *
-   * @param $paymentProcessor
-   *
-   * @return \CRM_Core_Payment_Dummy
+   * @param array $paymentProcessor
    */
   public function __construct($mode, &$paymentProcessor) {
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('Dummy Processor');
   }
 
   /**
@@ -78,19 +65,19 @@ class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
    * @throws \Civi\Payment\Exception\PaymentProcessorException
    */
   public function doDirectPayment(&$params) {
+    $propertyBag = PropertyBag::cast($params);
     // Invoke hook_civicrm_paymentProcessor
     // In Dummy's case, there is no translation of parameters into
     // the back-end's canonical set of parameters.  But if a processor
     // does this, it needs to invoke this hook after it has done translation,
     // but before it actually starts talking to its proprietary back-end.
-    if (!empty($params['is_recur'])) {
-      $throwAnENoticeIfNotSetAsTheseAreRequired = $params['frequency_interval'] . $params['frequency_unit'];
+    if ($propertyBag->getIsRecur()) {
+      $throwAnENoticeIfNotSetAsTheseAreRequired = $propertyBag->getRecurFrequencyInterval() . $propertyBag->getRecurFrequencyUnit();
     }
     // no translation in Dummy processor
-    $cookedParams = $params;
     CRM_Utils_Hook::alterPaymentProcessorParams($this,
       $params,
-      $cookedParams
+      $propertyBag
     );
     // This means we can test failing transactions by setting a past year in expiry. A full expiry check would
     // be more complete.
@@ -107,26 +94,25 @@ class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
       $result['trxn_id'] = array_shift($this->_doDirectPaymentResult['trxn_id']);
       return $result;
     }
-    if ($this->_mode == 'test') {
+    if ($this->_mode === 'test') {
       $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'test\\_%'";
       $p = [];
-      $trxn_id = strval(CRM_Core_DAO::singleValueQuery($query, $p));
+      $trxn_id = (string) CRM_Core_DAO::singleValueQuery($query, $p);
       $trxn_id = str_replace('test_', '', $trxn_id);
-      $trxn_id = intval($trxn_id) + 1;
+      $trxn_id = (int) $trxn_id + 1;
       $params['trxn_id'] = 'test_' . $trxn_id . '_' . uniqid();
     }
     else {
       $query = "SELECT MAX(trxn_id) FROM civicrm_contribution WHERE trxn_id LIKE 'live_%'";
       $p = [];
-      $trxn_id = strval(CRM_Core_DAO::singleValueQuery($query, $p));
+      $trxn_id = (string) CRM_Core_DAO::singleValueQuery($query, $p);
       $trxn_id = str_replace('live_', '', $trxn_id);
-      $trxn_id = intval($trxn_id) + 1;
+      $trxn_id = (int) $trxn_id + 1;
       $params['trxn_id'] = 'live_' . $trxn_id . '_' . uniqid();
     }
-    $params['gross_amount'] = $params['amount'];
+    $params['gross_amount'] = $propertyBag->getAmount();
     // Add a fee_amount so we can make sure fees are handled properly in underlying classes.
     $params['fee_amount'] = 1.50;
-    $params['net_amount'] = $params['gross_amount'] - $params['fee_amount'];
     $params['description'] = $this->getPaymentDescription($params);
 
     return $params;
@@ -142,7 +128,8 @@ class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
   }
 
   /**
-   * Supports altering future start dates
+   * Supports altering future start dates.
+   *
    * @return bool
    */
   public function supportsFutureRecurStartDate() {
@@ -159,28 +146,6 @@ class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
    */
   public function doRefund(&$params) {}
 
-  /**
-   * Generate error object.
-   *
-   * Throwing exceptions is preferred over this.
-   *
-   * @param string $errorCode
-   * @param string $errorMessage
-   *
-   * @return CRM_Core_Error
-   *   Error object.
-   */
-  public function &error($errorCode = NULL, $errorMessage = NULL) {
-    $e = CRM_Core_Error::singleton();
-    if ($errorCode) {
-      $e->push($errorCode, 0, NULL, $errorMessage);
-    }
-    else {
-      $e->push(9001, 0, NULL, 'Unknown System Error.');
-    }
-    return $e;
-  }
-
   /**
    * This function checks to see if we have the right config values.
    *
@@ -221,13 +186,37 @@ class CRM_Core_Payment_Dummy extends CRM_Core_Payment {
   }
 
   /**
-   * @param string $message
-   * @param array $params
+   * Does this processor support cancelling recurring contributions through code.
    *
-   * @return bool|object
+   * If the processor returns true it must be possible to take action from within CiviCRM
+   * that will result in no further payments being processed. In the case of token processors (e.g
+   * IATS, eWay) updating the contribution_recur table is probably sufficient.
+   *
+   * @return bool
    */
-  public function cancelSubscription(&$message = '', $params = []) {
+  protected function supportsCancelRecurring() {
     return TRUE;
   }
 
+  /**
+   * Cancel a recurring subscription.
+   *
+   * Payment processor classes should override this rather than implementing cancelSubscription.
+   *
+   * A PaymentProcessorException should be thrown if the update of the contribution_recur
+   * record should not proceed (in many cases this function does nothing
+   * as the payment processor does not need to take any action & this should silently
+   * proceed. Note the form layer will only call this after calling
+   * $processor->supports('cancelRecurring');
+   *
+   * @param \Civi\Payment\PropertyBag $propertyBag
+   *
+   * @return array
+   *
+   * @throws \Civi\Payment\Exception\PaymentProcessorException
+   */
+  public function doCancelRecurring(PropertyBag $propertyBag) {
+    return ['message' => ts('Recurring contribution cancelled')];
+  }
+
 }
diff --git a/civicrm/CRM/Core/Payment/Elavon.php b/civicrm/CRM/Core/Payment/Elavon.php
index 71ca4d5af1..35a93702e1 100644
--- a/civicrm/CRM/Core/Payment/Elavon.php
+++ b/civicrm/CRM/Core/Payment/Elavon.php
@@ -28,14 +28,6 @@ class CRM_Core_Payment_Elavon extends CRM_Core_Payment {
   const
     CHARSET = 'UFT-8';
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var CRM_Core_Payment_Elavon
-   */
-  static private $_singleton = NULL;
-
   /**
    * Constructor.
    *
@@ -50,7 +42,6 @@ class CRM_Core_Payment_Elavon extends CRM_Core_Payment {
     // live or test
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('Elavon');
   }
 
   /**
@@ -120,11 +111,11 @@ class CRM_Core_Payment_Elavon extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if (isset($params['is_recur']) && $params['is_recur'] == TRUE) {
-      CRM_Core_Error::fatal(ts('Elavon - recurring payments not implemented'));
+      throw new CRM_Core_Exception(ts('Elavon - recurring payments not implemented'));
     }
 
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('Elavon / Nova Virtual Merchant Gateway requires curl with SSL support'));
+      throw new CRM_Core_Exception(ts('Elavon / Nova Virtual Merchant Gateway requires curl with SSL support'));
     }
 
     //Create the array of variables to be sent to the processor from the $params array
diff --git a/civicrm/CRM/Core/Payment/FirstData.php b/civicrm/CRM/Core/Payment/FirstData.php
index a8f5b4f7ff..5e520cf7e4 100644
--- a/civicrm/CRM/Core/Payment/FirstData.php
+++ b/civicrm/CRM/Core/Payment/FirstData.php
@@ -55,14 +55,6 @@ class CRM_Core_Payment_FirstData extends CRM_Core_Payment {
   // (not used, implicit in the API, might need to convert?)
   const CHARSET = 'UFT-8';
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * Constructor.
    *
@@ -156,11 +148,11 @@ class CRM_Core_Payment_FirstData extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if ($params['is_recur'] == TRUE) {
-      CRM_Core_Error::fatal(ts('First Data - recurring payments not implemented'));
+      throw new CRM_Core_Exception(ts('First Data - recurring payments not implemented'));
     }
 
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('%1 - Gateway requires curl with SSL support', [1 => $paymentProcessor]));
+      throw new CRM_Core_Exception(ts('%1 - Gateway requires curl with SSL support', [1 => $paymentProcessor]));
     }
 
     /**********************************************************
diff --git a/civicrm/CRM/Core/Payment/Manual.php b/civicrm/CRM/Core/Payment/Manual.php
index 3027564199..0a311b48da 100644
--- a/civicrm/CRM/Core/Payment/Manual.php
+++ b/civicrm/CRM/Core/Payment/Manual.php
@@ -196,6 +196,19 @@ class CRM_Core_Payment_Manual extends CRM_Core_Payment {
     return TRUE;
   }
 
+  /**
+   * Does the processor support the user having a choice as to whether to cancel the recurring with the processor?
+   *
+   * If this returns TRUE then there will be an option to send a cancellation request in the cancellation form.
+   *
+   * This would normally be false for processors where CiviCRM maintains the schedule.
+   *
+   * @return bool
+   */
+  protected function supportsCancelRecurringNotifyOptional() {
+    return FALSE;
+  }
+
   /**
    * Are back office payments supported.
    *
diff --git a/civicrm/CRM/Core/Payment/PayJunction.php b/civicrm/CRM/Core/Payment/PayJunction.php
index 646421ee03..f544ee10c0 100644
--- a/civicrm/CRM/Core/Payment/PayJunction.php
+++ b/civicrm/CRM/Core/Payment/PayJunction.php
@@ -22,14 +22,6 @@ class CRM_Core_Payment_PayJunction extends CRM_Core_Payment {
   // (not used, implicit in the API, might need to convert?)
   const CHARSET = 'UFT-8';
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * Constructor.
    *
@@ -43,7 +35,6 @@ class CRM_Core_Payment_PayJunction extends CRM_Core_Payment {
   public function __construct($mode, &$paymentProcessor) {
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('PayJunction');
   }
 
   /**
diff --git a/civicrm/CRM/Core/Payment/PayPalIPN.php b/civicrm/CRM/Core/Payment/PayPalIPN.php
index a506ab3f29..0d3eae5386 100644
--- a/civicrm/CRM/Core/Payment/PayPalIPN.php
+++ b/civicrm/CRM/Core/Payment/PayPalIPN.php
@@ -263,8 +263,9 @@ class CRM_Core_Payment_PayPalIPN extends CRM_Core_Payment_BaseIPN {
     if ($status == 'Denied' || $status == 'Failed' || $status == 'Voided') {
       return $this->failed($objects, $transaction);
     }
-    elseif ($status == 'Pending') {
-      return $this->pending($objects, $transaction);
+    if ($status === 'Pending') {
+      Civi::log()->debug('Returning since contribution status is Pending');
+      return;
     }
     elseif ($status == 'Refunded' || $status == 'Reversed') {
       return $this->cancelled($objects, $transaction);
diff --git a/civicrm/CRM/Core/Payment/PayPalImpl.php b/civicrm/CRM/Core/Payment/PayPalImpl.php
index 42fdfa2f80..022067bd98 100644
--- a/civicrm/CRM/Core/Payment/PayPalImpl.php
+++ b/civicrm/CRM/Core/Payment/PayPalImpl.php
@@ -43,19 +43,6 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment {
   public function __construct($mode, &$paymentProcessor) {
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-
-    if ($this->isPayPalType($this::PAYPAL_STANDARD)) {
-      $this->_processorName = ts('PayPal Standard');
-    }
-    elseif ($this->isPayPalType($this::PAYPAL_EXPRESS)) {
-      $this->_processorName = ts('PayPal Express');
-    }
-    elseif ($this->isPayPalType($this::PAYPAL_PRO)) {
-      $this->_processorName = ts('PayPal Pro');
-    }
-    else {
-      throw new PaymentProcessorException('CRM_Core_Payment_PayPalImpl: Payment processor type is not defined!');
-    }
   }
 
   /**
@@ -929,7 +916,7 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment {
     // if recurring donations, add a few more items
     if (!empty($params['is_recur'])) {
       if (!$params['contributionRecurID']) {
-        CRM_Core_Error::fatal(ts('Recurring contribution, but no database id'));
+        throw new CRM_Core_Exception(ts('Recurring contribution, but no database id'));
       }
 
       $paypalParams += [
diff --git a/civicrm/CRM/Core/Payment/PayPalProIPN.php b/civicrm/CRM/Core/Payment/PayPalProIPN.php
index 885fac970f..a215552724 100644
--- a/civicrm/CRM/Core/Payment/PayPalProIPN.php
+++ b/civicrm/CRM/Core/Payment/PayPalProIPN.php
@@ -351,8 +351,8 @@ class CRM_Core_Payment_PayPalProIPN extends CRM_Core_Payment_BaseIPN {
       $this->failed($objects, $transaction);
       return;
     }
-    elseif ($status == 'Pending') {
-      $this->pending($objects, $transaction);
+    if ($status === 'Pending') {
+      Civi::log()->debug('Returning since contribution status is Pending');
       return;
     }
     elseif ($status == 'Refunded' || $status == 'Reversed') {
@@ -588,7 +588,7 @@ INNER JOIN civicrm_membership_payment mp ON m.id = mp.membership_id AND mp.contr
     // & suspec main function may be a victom of copy & paste
     // membership would be an easy add - but not relevant to my customer...
     $this->_component = $input['component'] = 'contribute';
-    $input['trxn_date'] = date('Y-m-d-H-i-s', strtotime(self::retrieve('time_created', 'String')));
+    $input['trxn_date'] = date('Y-m-d H:i:s', strtotime(self::retrieve('time_created', 'String')));
     $paymentProcessorID = $contributionRecur['payment_processor_id'];
 
     if (!$this->validateData($input, $ids, $objects, TRUE, $paymentProcessorID)) {
diff --git a/civicrm/CRM/Core/Payment/PayflowPro.php b/civicrm/CRM/Core/Payment/PayflowPro.php
index 1d4b92c5e9..1f5b769336 100644
--- a/civicrm/CRM/Core/Payment/PayflowPro.php
+++ b/civicrm/CRM/Core/Payment/PayflowPro.php
@@ -17,14 +17,6 @@ class CRM_Core_Payment_PayflowPro extends CRM_Core_Payment {
   const
     CHARSET = 'UFT-8';
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * Constructor
    *
@@ -36,7 +28,6 @@ class CRM_Core_Payment_PayflowPro extends CRM_Core_Payment {
     // live or test
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('Payflow Pro');
   }
 
   /*
@@ -58,7 +49,7 @@ class CRM_Core_Payment_PayflowPro extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('Payflow Pro requires curl with SSL support'));
+      throw new CRM_Core_Exception(ts('Payflow Pro requires curl with SSL support'));
     }
 
     /*
@@ -373,7 +364,7 @@ class CRM_Core_Payment_PayflowPro extends CRM_Core_Payment {
    * @throws Exception
    */
   public function doTransferCheckout(&$params, $component) {
-    CRM_Core_Error::fatal(ts('This function is not implemented'));
+    throw new CRM_Core_Exception(ts('This function is not implemented'));
   }
 
   /**
diff --git a/civicrm/CRM/Core/Payment/PaymentExpress.php b/civicrm/CRM/Core/Payment/PaymentExpress.php
index 2f40ea054f..54ddfa21c6 100644
--- a/civicrm/CRM/Core/Payment/PaymentExpress.php
+++ b/civicrm/CRM/Core/Payment/PaymentExpress.php
@@ -41,14 +41,6 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
 
   protected $_mode = NULL;
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * Constructor.
    *
@@ -63,7 +55,6 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
 
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('DPS Payment Express');
   }
 
   /**
@@ -103,7 +94,7 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
    *   Assoc array of input parameters for this transaction.
    */
   public function doDirectPayment(&$params) {
-    CRM_Core_Error::fatal(ts('This function is not implemented'));
+    throw new CRM_Core_Exception(ts('This function is not implemented'));
   }
 
   /**
@@ -118,7 +109,7 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
     $component = strtolower($component);
     $config = CRM_Core_Config::singleton();
     if ($component != 'contribute' && $component != 'event') {
-      CRM_Core_Error::fatal(ts('Component is invalid'));
+      throw new CRM_Core_Exception(ts('Component is invalid'));
     }
 
     $url = CRM_Utils_System::externUrl('extern/pxIPN');
@@ -211,7 +202,7 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
       }
       else {
         // calling DPS failed
-        CRM_Core_Error::fatal(ts('Unable to establish connection to the payment gateway.'));
+        throw new CRM_Core_Exception(ts('Unable to establish connection to the payment gateway.'));
       }
     }
     else {
diff --git a/civicrm/CRM/Core/Payment/PaymentExpressIPN.php b/civicrm/CRM/Core/Payment/PaymentExpressIPN.php
index ab34ea13f1..878b948f96 100644
--- a/civicrm/CRM/Core/Payment/PaymentExpressIPN.php
+++ b/civicrm/CRM/Core/Payment/PaymentExpressIPN.php
@@ -38,14 +38,6 @@
  */
 class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * Mode of operation: live or test
    *
@@ -109,6 +101,8 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
    * @param $transactionReference
    *
    * @return bool
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   public function newOrderNotify($success, $privateData, $component, $amount, $transactionReference) {
     $ids = $input = $params = [];
@@ -160,8 +154,6 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
       return FALSE;
     }
 
-    $transaction = new CRM_Core_Transaction();
-
     // check if contribution is already completed, if so we ignore this ipn
 
     if ($contribution->contribution_status_id == 1) {
@@ -181,7 +173,7 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
         $contribution->trxn_id = $ids['membership'];
       }
     }
-    $this->completeTransaction($input, $ids, $objects, $transaction);
+    CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects);
     return TRUE;
   }
 
@@ -308,7 +300,7 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
         $info = curl_getinfo($curl);
         if ($info['http_code'] < 200 || $info['http_code'] > 299) {
           $log_message = "DPS error: HTTP {$info['http_code']} retrieving {$info['url']}.";
-          CRM_Core_Error::fatal($log_message);
+          throw new CRM_Core_Exception($log_message);
         }
         else {
           fwrite($message_log, sprintf("\n\r%s:- %s\n", date("D M j G:i:s T Y"), $response));
@@ -318,7 +310,7 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
           $valid = CRM_Core_Payment_PaymentExpressUtils::_xmlAttribute($response, 'valid');
           // CRM_Core_Payment_PaymentExpressUtils::_xmlAttribute() returns NULL if preg fails.
           if (is_null($valid)) {
-            CRM_Core_Error::fatal(ts("DPS error: Unable to parse XML response from DPS.", [1 => $valid]));
+            throw new CRM_Core_Exception(ts("DPS error: Unable to parse XML response from DPS.", [1 => $valid]));
           }
           $success = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'Success');
           $txnId = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'TxnId');
@@ -334,7 +326,7 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
       }
       else {
         // calling DPS failed
-        CRM_Core_Error::fatal(ts('Unable to establish connection to the payment gateway to verify transaction response.'));
+        throw new CRM_Core_Exception(ts('Unable to establish connection to the payment gateway to verify transaction response.'));
         exit;
       }
     }
diff --git a/civicrm/CRM/Core/Payment/ProcessorForm.php b/civicrm/CRM/Core/Payment/ProcessorForm.php
index 322f07cfd2..3f927557b0 100644
--- a/civicrm/CRM/Core/Payment/ProcessorForm.php
+++ b/civicrm/CRM/Core/Payment/ProcessorForm.php
@@ -106,7 +106,7 @@ class CRM_Core_Payment_ProcessorForm {
     if (!empty($form->_values['is_monetary']) &&
       !$form->_paymentProcessor['class_name'] && empty($form->_values['is_pay_later'])
     ) {
-      CRM_Core_Error::fatal(ts('Payment processor is not set for this page'));
+      CRM_Core_Error::statusBounce(ts('Payment processor is not set for this page'));
     }
 
     if (!empty($form->_membershipBlock) && !empty($form->_membershipBlock['is_separate_payment']) &&
@@ -115,7 +115,7 @@ class CRM_Core_Payment_ProcessorForm {
       )
     ) {
 
-      CRM_Core_Error::fatal(ts('This contribution page is configured to support separate contribution and membership payments. This %1 plugin does not currently support multiple simultaneous payments, or the option to "Execute real-time monetary transactions" is disabled. Please contact the site administrator and notify them of this error',
+      CRM_Core_Error::statusBounce(ts('This contribution page is configured to support separate contribution and membership payments. This %1 plugin does not currently support multiple simultaneous payments, or the option to "Execute real-time monetary transactions" is disabled. Please contact the site administrator and notify them of this error',
           [1 => $form->_paymentProcessor['payment_processor_type']]
         )
       );
diff --git a/civicrm/CRM/Core/Payment/Realex.php b/civicrm/CRM/Core/Payment/Realex.php
index 8100aa9531..610b101cbd 100644
--- a/civicrm/CRM/Core/Payment/Realex.php
+++ b/civicrm/CRM/Core/Payment/Realex.php
@@ -44,14 +44,6 @@ class CRM_Core_Payment_Realex extends CRM_Core_Payment {
 
   protected $_params = [];
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * Constructor.
    *
@@ -65,7 +57,6 @@ class CRM_Core_Payment_Realex extends CRM_Core_Payment {
   public function __construct($mode, &$paymentProcessor) {
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('Realex');
 
     $this->_setParam('merchant_ref', $paymentProcessor['user_name']);
     $this->_setParam('secret', $paymentProcessor['password']);
diff --git a/civicrm/CRM/Core/Payment/eWAY.php b/civicrm/CRM/Core/Payment/eWAY.php
index 8f198b46c8..bc6710ae8d 100644
--- a/civicrm/CRM/Core/Payment/eWAY.php
+++ b/civicrm/CRM/Core/Payment/eWAY.php
@@ -102,14 +102,6 @@ class CRM_Core_Payment_eWAY extends CRM_Core_Payment {
   // (not used, implicit in the API, might need to convert?)
   const CHARSET = 'UTF-8';
 
-  /**
-   * We only need one instance of this object. So we use the singleton
-   * pattern and cache the instance in this variable
-   *
-   * @var object
-   */
-  static private $_singleton = NULL;
-
   /**
    * *******************************************************
    * Constructor
@@ -126,7 +118,6 @@ class CRM_Core_Payment_eWAY extends CRM_Core_Payment {
     // live or test
     $this->_mode = $mode;
     $this->_paymentProcessor = $paymentProcessor;
-    $this->_processorName = ts('eWay');
   }
 
   /**
@@ -139,11 +130,11 @@ class CRM_Core_Payment_eWAY extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if (CRM_Utils_Array::value('is_recur', $params) == TRUE) {
-      CRM_Core_Error::fatal(ts('eWAY - recurring payments not implemented'));
+      throw new CRM_Core_Exception(ts('eWAY - recurring payments not implemented'));
     }
 
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('eWAY - Gateway requires curl with SSL support'));
+      throw new CRM_Core_Exception(ts('eWAY - Gateway requires curl with SSL support'));
     }
 
     // eWAY Client ID
diff --git a/civicrm/CRM/Core/Permission/Base.php b/civicrm/CRM/Core/Permission/Base.php
index a91c126b8c..b3f5a066f1 100644
--- a/civicrm/CRM/Core/Permission/Base.php
+++ b/civicrm/CRM/Core/Permission/Base.php
@@ -170,9 +170,10 @@ class CRM_Core_Permission_Base {
    * @param string $permissionName
    *   Name of the permission we are interested in.
    *
+   * @throws CRM_Core_Exception.
    */
   public function permissionEmails($permissionName) {
-    CRM_Core_Error::fatal("this function only works in Drupal 6 at the moment");
+    throw new CRM_Core_Exception("this function only works in Drupal 6 at the moment");
   }
 
   /**
@@ -181,9 +182,10 @@ class CRM_Core_Permission_Base {
    * @param string $roleName
    *   Name of the role we are interested in.
    *
+   * @throws CRM_Core_Exception.
    */
   public function roleEmails($roleName) {
-    CRM_Core_Error::fatal("this function only works in Drupal 6 at the moment");
+    throw new CRM_Core_Exception("this function only works in Drupal 6 at the moment");
   }
 
   /**
diff --git a/civicrm/CRM/Core/PseudoConstant.php b/civicrm/CRM/Core/PseudoConstant.php
index afbb0b5fbb..e158ee21f0 100644
--- a/civicrm/CRM/Core/PseudoConstant.php
+++ b/civicrm/CRM/Core/PseudoConstant.php
@@ -194,7 +194,7 @@ class CRM_Core_PseudoConstant {
       'fresh' => FALSE,
       'context' => $context,
     ];
-    $entity = CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getCanonicalClassName($daoName));
+    $entity = CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
 
     // Custom fields are not in the schema
     if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
@@ -1527,7 +1527,7 @@ WHERE  id = %1
     }
     // Filter domain specific options
     if (in_array('domain_id', $availableFields)) {
-      $wheres[] = 'domain_id = ' . CRM_Core_Config::domainID();
+      $wheres[] = 'domain_id = ' . CRM_Core_Config::domainID() . ' OR  domain_id is NULL';
     }
     $queryParams = [
       1 => [$params['keyColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES],
diff --git a/civicrm/CRM/Core/Region.php b/civicrm/CRM/Core/Region.php
index b1809af636..5d101d1d70 100644
--- a/civicrm/CRM/Core/Region.php
+++ b/civicrm/CRM/Core/Region.php
@@ -68,7 +68,7 @@ class CRM_Core_Region {
   /**
    * Add a snippet of content to a region.
    *
-   * @code
+   * ```
    * CRM_Core_Region::instance('page-header')->add(array(
    *   'markup' => '<div style="color:red">Hello!</div>',
    * ));
@@ -81,7 +81,7 @@ class CRM_Core_Region {
    * CRM_Core_Region::instance('page-header')->add(array(
    *   'callback' => 'myextension_callback_function',
    * ));
-   * @endcode
+   * ```
    *
    * Note: This function does not perform any extra encoding of markup, script code, or etc. If
    * you're passing in user-data, you must clean it yourself.
diff --git a/civicrm/CRM/Core/SelectValues.php b/civicrm/CRM/Core/SelectValues.php
index 6b451af1eb..b2c515867e 100644
--- a/civicrm/CRM/Core/SelectValues.php
+++ b/civicrm/CRM/Core/SelectValues.php
@@ -68,11 +68,7 @@ class CRM_Core_SelectValues {
    * @return array
    */
   public static function contactType() {
-    static $contactType = NULL;
-    if (!$contactType) {
-      $contactType = CRM_Contact_BAO_ContactType::basicTypePairs();
-    }
-    return $contactType;
+    return CRM_Contact_BAO_ContactType::basicTypePairs();
   }
 
   /**
@@ -181,12 +177,9 @@ class CRM_Core_SelectValues {
       'Select Date' => ts('Select Date'),
       'File' => ts('File'),
       'Select State/Province' => ts('Select State/Province'),
-      'Multi-Select State/Province' => ts('Multi-Select State/Province'),
       'Select Country' => ts('Select Country'),
-      'Multi-Select Country' => ts('Multi-Select Country'),
       'RichTextEditor' => ts('Rich Text Editor'),
       'Autocomplete-Select' => ts('Autocomplete-Select'),
-      'Multi-Select' => ts('Multi-Select'),
       'Link' => ts('Link'),
       'ContactReference' => ts('Autocomplete-Select'),
     ];
@@ -1179,4 +1172,14 @@ class CRM_Core_SelectValues {
     return $ret;
   }
 
+  public static function fieldSerialization() {
+    return [
+      CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND => 'separator_bookend',
+      CRM_Core_DAO::SERIALIZE_SEPARATOR_TRIMMED => 'separator_trimmed',
+      CRM_Core_DAO::SERIALIZE_JSON => 'json',
+      CRM_Core_DAO::SERIALIZE_PHP => 'php',
+      CRM_Core_DAO::SERIALIZE_COMMA => 'comma',
+    ];
+  }
+
 }
diff --git a/civicrm/CRM/Core/ShowHideBlocks.php b/civicrm/CRM/Core/ShowHideBlocks.php
index 934eb317a3..1b4786987c 100644
--- a/civicrm/CRM/Core/ShowHideBlocks.php
+++ b/civicrm/CRM/Core/ShowHideBlocks.php
@@ -16,14 +16,6 @@
  */
 class CRM_Core_ShowHideBlocks {
 
-  /**
-   * The icons prefixed to block show and hide links.
-   *
-   * @var string
-   */
-  public static $_showIcon;
-  public static $_hideIcon;
-
   /**
    * The array of ids of blocks that will be shown.
    *
@@ -64,17 +56,6 @@ class CRM_Core_ShowHideBlocks {
     }
   }
 
-  /**
-   * Load icon vars used in hide and show links.
-   */
-  public static function setIcons() {
-    if (!isset(self::$_showIcon)) {
-      $config = CRM_Core_Config::singleton();
-      self::$_showIcon = '<img src="' . $config->resourceBase . 'i/TreePlus.gif" class="action-icon" alt="' . ts('show field or section') . '"/>';
-      self::$_hideIcon = '<img src="' . $config->resourceBase . 'i/TreeMinus.gif" class="action-icon" alt="' . ts('hide field or section') . '"/>';
-    }
-  }
-
   /**
    * Add the values from this class to the template.
    */
@@ -130,115 +111,4 @@ class CRM_Core_ShowHideBlocks {
     }
   }
 
-  /**
-   * Create a well formatted html link from the smaller pieces.
-   *
-   * @param string $name
-   *   Name of the link.
-   * @param string $href
-   * @param string $text
-   * @param string $js
-   *
-   * @return string
-   *   the formatted html link
-   */
-  public static function linkHtml($name, $href, $text, $js) {
-    return '<a name="' . $name . '" id="' . $name . '" href="' . $href . '" ' . $js . ">$text</a>";
-  }
-
-  /**
-   * Create links that we can use in the form.
-   *
-   * @param CRM_Core_Form $form
-   *   The form object.
-   * @param string $prefix
-   *   The attribute that we are referencing.
-   * @param string $showLinkText
-   *   The text to be shown for the show link.
-   * @param string $hideLinkText
-   *   The text to be shown for the hide link.
-   *
-   * @param bool $assign
-   *
-   * @return array
-   */
-  public static function links(&$form, $prefix, $showLinkText, $hideLinkText, $assign = TRUE) {
-    $showCode = "if(event.preventDefault) event.preventDefault(); else event.returnValue = false; cj('#id_{$prefix}').show(); cj('#id_{$prefix}_show').hide();";
-    $hideCode = "if(event.preventDefault) event.preventDefault(); else event.returnValue = false; cj('#id_{$prefix}').hide(); cj('#id_{$prefix}_show').show();";
-
-    self::setIcons();
-    $values = [];
-    $values['show'] = self::linkHtml("${prefix}_show", "#${prefix}_hide", self::$_showIcon . $showLinkText, "onclick=\"$showCode\"");
-    $values['hide'] = self::linkHtml("${prefix}_hide", "#${prefix}", self::$_hideIcon . $hideLinkText, "onclick=\"$hideCode\"");
-
-    if ($assign) {
-      $form->assign($prefix, $values);
-    }
-    else {
-      return $values;
-    }
-  }
-
-  /**
-   * Create html link elements that we can use in the form.
-   *
-   * @param CRM_Core_Form $form
-   *   The form object.
-   * @param int $index
-   *   The current index of the element being processed.
-   * @param int $maxIndex
-   *   The max number of elements that will be processed.
-   * @param string $prefix
-   *   The attribute that we are referencing.
-   * @param string $showLinkText
-   *   The text to be shown for the show link.
-   * @param string $hideLinkText
-   *   The text to be shown for the hide link.
-   * @param string $elementType
-   *   The set the class.
-   * @param string $hideLink
-   *   The hide block string.
-   */
-  public function linksForArray(&$form, $index, $maxIndex, $prefix, $showLinkText, $hideLinkText, $elementType = NULL, $hideLink = NULL) {
-    $showHidePrefix = str_replace(["]", "["], ["", "_"], $prefix);
-    $showHidePrefix = "id_" . $showHidePrefix;
-    if ($index == $maxIndex) {
-      $showCode = $hideCode = "return false;";
-    }
-    else {
-      $next = $index + 1;
-      if ($elementType) {
-        $showCode = "cj('#${prefix}_${next}_show').show(); return false;";
-        if ($hideLink) {
-          $hideCode = $hideLink;
-        }
-        else {
-          $hideCode = "cj('#${prefix}_${next}_show, #${prefix}_${next}').hide(); return false;";
-        }
-      }
-      else {
-        $showCode = "cj('#{$showHidePrefix}_{$next}_show').show(); return false;";
-        $hideCode = "cj('#{$showHidePrefix}_{$next}_show, #{$showHidePrefix}_{$next}').hide(); return false;";
-      }
-    }
-
-    self::setIcons();
-    if ($elementType) {
-      $form->addElement('link', "${prefix}[${index}][show]", NULL, "#${prefix}_${index}", self::$_showIcon . $showLinkText,
-        ['onclick' => "cj('#${prefix}_${index}_show').hide(); cj('#${prefix}_${index}').show();" . $showCode]
-      );
-      $form->addElement('link', "${prefix}[${index}][hide]", NULL, "#${prefix}_${index}", self::$_hideIcon . $hideLinkText,
-        ['onclick' => "cj('#${prefix}_${index}').hide(); cj('#${prefix}_${index}_show').show();" . $hideCode]
-      );
-    }
-    else {
-      $form->addElement('link', "${prefix}[${index}][show]", NULL, "#${prefix}_${index}", self::$_showIcon . $showLinkText,
-        ['onclick' => "cj('#{$showHidePrefix}_{$index}_show').hide(); cj('#{$showHidePrefix}_{$index}').show();" . $showCode]
-      );
-      $form->addElement('link', "${prefix}[${index}][hide]", NULL, "#${prefix}_${index}", self::$_hideIcon . $hideLinkText,
-        ['onclick' => "cj('#{$showHidePrefix}_{$index}').hide(); cj('#{$showHidePrefix}_{$index}_show').show();" . $hideCode]
-      );
-    }
-  }
-
 }
diff --git a/civicrm/CRM/Core/Smarty.php b/civicrm/CRM/Core/Smarty.php
index e45873d4db..86fcab419a 100644
--- a/civicrm/CRM/Core/Smarty.php
+++ b/civicrm/CRM/Core/Smarty.php
@@ -258,14 +258,14 @@ class CRM_Core_Smarty extends Smarty {
   /**
    * Temporarily assign a list of variables.
    *
-   * @code
+   * ```
    * $smarty->pushScope(array(
    *   'first_name' => 'Alice',
    *   'last_name' => 'roberts',
    * ));
    * $html = $smarty->fetch('view-contact.tpl');
    * $smarty->popScope();
-   * @endcode
+   * ```
    *
    * @param array $vars
    *   (string $name => mixed $value).
diff --git a/civicrm/CRM/Core/Smarty/plugins/block.crmButton.php b/civicrm/CRM/Core/Smarty/plugins/block.crmButton.php
index b9869e20d3..8c5f573a86 100644
--- a/civicrm/CRM/Core/Smarty/plugins/block.crmButton.php
+++ b/civicrm/CRM/Core/Smarty/plugins/block.crmButton.php
@@ -38,9 +38,21 @@ function smarty_block_crmButton($params, $text, &$smarty) {
   // Always add class 'button' - fixme probably should be crm-button
   $params['class'] = empty($params['class']) ? 'button' : 'button ' . $params['class'];
   // Any FA icon works
-  $icon = CRM_Utils_Array::value('icon', $params, 'pencil');
+  if (array_key_exists('icon', $params) && !$params['icon']) {
+    // icon=0 should produce a button with no icon
+    $iconMarkup = '';
+  }
+  else {
+    $icon = $params['icon'] ?? 'fa-pencil';
+    // Assume for now that all icons are Font Awesome v4.x but handle if it's
+    // specified
+    if (strpos($icon, 'fa-') !== 0) {
+      $icon = "fa-$icon";
+    }
+    $iconMarkup = "<i class='crm-i $icon' aria-hidden=\"true\"></i>&nbsp; ";
+  }
   // All other params are treated as html attributes
   CRM_Utils_Array::remove($params, 'icon', 'p', 'q', 'a', 'f', 'h', 'fb', 'fe');
   $attributes = CRM_Utils_String::htmlAttributes($params);
-  return "<a $attributes><span><i class='crm-i fa-$icon'></i>&nbsp; $text</span></a>";
+  return "<a $attributes><span>$iconMarkup$text</span></a>";
 }
diff --git a/civicrm/CRM/Core/Smarty/plugins/block.crmScope.php b/civicrm/CRM/Core/Smarty/plugins/block.crmScope.php
index 66bb8bcb4f..3e0e028003 100644
--- a/civicrm/CRM/Core/Smarty/plugins/block.crmScope.php
+++ b/civicrm/CRM/Core/Smarty/plugins/block.crmScope.php
@@ -5,7 +5,7 @@
  *
  * Example:
  *
- * @code
+ * ```
  * {tsScope x=1}
  *   Expect {$x}==1
  *   {tsScope x=2}
@@ -13,7 +13,7 @@
  *   {/tsScope}
  *   Expect {$x}==1
  * {/tsScope}
- * @endcode
+ * ```
  *
  * @param array $params
  *   Must define 'name'.
diff --git a/civicrm/CRM/Core/Smarty/plugins/block.icon.php b/civicrm/CRM/Core/Smarty/plugins/block.icon.php
new file mode 100644
index 0000000000..ac68cfe027
--- /dev/null
+++ b/civicrm/CRM/Core/Smarty/plugins/block.icon.php
@@ -0,0 +1,43 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @author Andrew Hunt, AGH Strategies
+ */
+
+/**
+ * Display an icon with some alternative text.
+ *
+ * This is a wrapper around CRM_Core_Page::icon().
+ *
+ * @param $params
+ *   - condition: if present and falsey, return empty
+ *   - icon: the icon class to display instead of fa-check
+ *   - anything else is passed along as attributes for the icon
+ *
+ * @param $text
+ *   The translated text to include in the icon's title and screen-reader text.
+ *
+ * @param $smarty
+ *
+ * @return string
+ */
+function smarty_block_icon($params, $text, &$smarty) {
+  $condition = array_key_exists('condition', $params) ? $params['condition'] : 1;
+  $icon = $params['icon'] ?? 'fa-check';
+  $dontPass = [
+    'condition' => 1,
+    'icon' => 1,
+  ];
+  return CRM_Core_Page::crmIcon($icon, $text, $condition, array_diff_key($params, $dontPass));
+}
diff --git a/civicrm/CRM/Core/Smarty/plugins/function.copyIcon.php b/civicrm/CRM/Core/Smarty/plugins/function.copyIcon.php
new file mode 100644
index 0000000000..19f4a36991
--- /dev/null
+++ b/civicrm/CRM/Core/Smarty/plugins/function.copyIcon.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @author Andrew Hunt, AGH Strategies
+ */
+
+/**
+ * Display a copy icon that copies the first row's values down.
+ *
+ * @param $params
+ *   - name: the field name
+ *   - title: the field title
+ *
+ * @param $smarty
+ *
+ * @return string
+ */
+function smarty_function_copyIcon($params, &$smarty) {
+  $text = ts('Click to copy %1 from row one to all rows.', [1 => $params['title']]);
+  return <<<HEREDOC
+<i class="crm-i fa-clone action-icon" fname="{$params['name']}" title="$text"><span class="sr-only">$text</span></i>
+HEREDOC;
+}
diff --git a/civicrm/CRM/Core/Smarty/plugins/function.crmVersion.php b/civicrm/CRM/Core/Smarty/plugins/function.crmVersion.php
index e25693c93a..6f9ab7c617 100644
--- a/civicrm/CRM/Core/Smarty/plugins/function.crmVersion.php
+++ b/civicrm/CRM/Core/Smarty/plugins/function.crmVersion.php
@@ -20,11 +20,11 @@
 /**
  * Display the CiviCRM version
  *
- * @code
+ * ```
  * The version is {crmVersion}.
  *
  * {crmVersion redact=auto assign=ver}The version is {$ver}.
- * @endcode
+ * ```
  *
  * @param $params
  * @param $smarty
diff --git a/civicrm/CRM/Core/Smarty/plugins/function.privacyFlag.php b/civicrm/CRM/Core/Smarty/plugins/function.privacyFlag.php
new file mode 100644
index 0000000000..050f7a19d6
--- /dev/null
+++ b/civicrm/CRM/Core/Smarty/plugins/function.privacyFlag.php
@@ -0,0 +1,56 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @author Andrew Hunt, AGH Strategies
+ *
+ */
+
+/**
+ * Display a banned icon to flag privacy preferences
+ *
+ * @param $params
+ *   - field: the applicable privacy field
+ *     (one of CRM_Core_SelectValues::privacy() or `on_hold`)
+ *   - condition: if present and falsey, return empty
+ *
+ * @param $smarty
+ *
+ * @return string
+ */
+function smarty_function_privacyFlag($params, &$smarty) {
+  if (array_key_exists('condition', $params) && !$params['condition']) {
+    return '';
+  }
+  $icons = [
+    'do_not_phone' => 'fa-phone',
+    'do_not_email' => 'fa-paper-plane',
+    'do_not_mail' => 'fa-envelope',
+    'do_not_sms' => 'fa-mobile',
+    'do_not_trade' => 'fa-exchange',
+    'is_opt_out' => 'fa-paper-plane-o',
+  ];
+  $titles = CRM_Core_SelectValues::privacy();
+  $field = $params['field'] ?? 'do_not_mail';
+  if ($field == 'on_hold') {
+    $text = ts('Email on hold - generally due to bouncing.');
+    return <<<HEREDOC
+<span class="privacy-flag email-hold" title="$text"><i class="crm-i fa-exclamation-triangle fa-lg font-red" aria-hidden="true"></i></span><span class="sr-only">$text</span>
+HEREDOC;
+  }
+  $class = str_replace('_', '-', $field);
+  $text = ts('Privacy flag: %1', [1 => $titles[$field]]);
+  return <<<HEREDOC
+<span class="fa-stack privacy-flag $class" title="$text" aria-hidden="true"><i class="crm-i {$icons[$field]} fa-stack-1x"></i><i class="crm-i fa-ban fa-stack-2x font-red"></i></span><span class="sr-only">$text</span>
+HEREDOC;
+}
diff --git a/civicrm/CRM/Core/TemporaryErrorScope.php b/civicrm/CRM/Core/TemporaryErrorScope.php
index d8853b8ef8..ab0cf4b3f8 100644
--- a/civicrm/CRM/Core/TemporaryErrorScope.php
+++ b/civicrm/CRM/Core/TemporaryErrorScope.php
@@ -14,9 +14,9 @@
  *
  * To ensure that they throw exceptions, use:
  *
- * @code
+ * ```
  * $errorScope = CRM_Core_TemporaryErrorScope::useException();
- * @endcode
+ * ```
  *
  * Note that relying on this is a code-smell: it can be
  * safe to temporarily switch to exception
diff --git a/civicrm/CRM/Core/Transaction.php b/civicrm/CRM/Core/Transaction.php
index 04be629fb3..a2297bee1f 100644
--- a/civicrm/CRM/Core/Transaction.php
+++ b/civicrm/CRM/Core/Transaction.php
@@ -28,7 +28,7 @@
  *
  * Examples:
  *
- * @code
+ * ```
  * // Some business logic using the helper functions
  * function my_business_logic() {
  *   CRM_Core_Transaction::create()->run(function($tx) {
@@ -60,7 +60,7 @@
  *   }
  * }
  *
- * @endcode
+ * ```
  *
  * Note: As of 4.6, the transaction manager supports both reference-counting and nested
  * transactions (SAVEPOINTs). In the past, it only supported reference-counting. The two cases
diff --git a/civicrm/CRM/Core/xml/Menu/Admin.xml b/civicrm/CRM/Core/xml/Menu/Admin.xml
index c681503606..acf56251f1 100644
--- a/civicrm/CRM/Core/xml/Menu/Admin.xml
+++ b/civicrm/CRM/Core/xml/Menu/Admin.xml
@@ -7,7 +7,6 @@
      <desc>Configure custom fields to collect and store custom data which is not included in the standard CiviCRM forms.</desc>
      <page_callback>CRM_Custom_Page_Group</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/custm_data.png</icon>
      <weight>10</weight>
   </item>
   <item>
@@ -48,7 +47,6 @@
      <desc>Profiles allow you to aggregate groups of fields and include them in your site as input forms, contact display pages, and search and listings features.</desc>
      <page_callback>CRM_UF_Page_Group</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/Profile.png</icon>
      <weight>20</weight>
   </item>
   <item>
@@ -94,7 +92,6 @@
      <desc>CiviCRM has several built-in activity types (meetings, phone calls, emails sent). Track other types of interactions by creating custom activity types here.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/05.png</icon>
      <weight>30</weight>
   </item>
   <item>
@@ -103,7 +100,6 @@
      <desc>Contacts can be linked to each other through Relationships (e.g. Spouse, Employer, etc.). Define the types of relationships you want to record here.</desc>
      <page_callback>CRM_Admin_Page_RelationshipType</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/rela_type.png</icon>
      <weight>35</weight>
   </item>
   <item>
@@ -111,7 +107,6 @@
      <title>Contact Types</title>
      <page_callback>CRM_Admin_Page_ContactType</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/09.png</icon>
      <weight>40</weight>
   </item>
   <item>
@@ -120,7 +115,6 @@
      <desc>Options for assigning gender to individual contacts (e.g. Male, Female, Other).</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>45</weight>
   </item>
   <item>
@@ -129,7 +123,6 @@
      <desc>Options for individual contact prefixes (e.g. Ms., Mr., Dr. etc.).</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/title.png</icon>
      <weight>50</weight>
   </item>
   <item>
@@ -138,7 +131,6 @@
      <desc>Options for individual contact suffixes (e.g. Jr., Sr. etc.).</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/10.png</icon>
      <weight>55</weight>
   </item>
   <item>
@@ -147,7 +139,6 @@
      <desc>Options for categorizing contact addresses and phone numbers (e.g. Home, Work, Billing, etc.).</desc>
      <page_callback>CRM_Admin_Page_LocationType</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/13.png</icon>
      <weight>60</weight>
   </item>
   <item>
@@ -164,7 +155,6 @@
      <desc>List of IM services which can be used when recording screen-names for contacts.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/07.png</icon>
      <weight>70</weight>
   </item>
   <item>
@@ -173,7 +163,6 @@
      <desc>List of mobile phone providers which can be assigned when recording contact phone numbers.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/08.png</icon>
      <weight>75</weight>
   </item>
   <item>
@@ -183,7 +172,6 @@
     Mobile, Fax, Pager)</desc>
     <page_callback>CRM_Admin_Page_Options</page_callback>
     <adminGroup>Customize Data and Screens</adminGroup>
-    <icon>tel.gif</icon>
     <weight>80</weight>
   </item>
   <item>
@@ -191,7 +179,6 @@
      <title>Display Preferences</title>
      <page_callback>CRM_Admin_Form_Preferences_Display</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>90</weight>
   </item>
   <item>
@@ -199,7 +186,6 @@
      <title>Search Preferences</title>
      <page_callback>CRM_Admin_Form_Setting_Search</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>95</weight>
   </item>
   <item>
@@ -207,7 +193,6 @@
      <title>Date Preferences</title>
      <page_callback>CRM_Admin_Form_PreferencesDate</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>97</weight>
   </item>
   <item>
@@ -216,7 +201,6 @@
      <desc>Add or remove menu items, and modify the order of items on the navigation menu.</desc>
      <page_callback>CRM_Admin_Page_Navigation</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/template.png</icon>
      <weight>100</weight>
   </item>
   <item>
@@ -233,7 +217,6 @@
      <desc>Developers and accidental techies with a bit of PHP and SQL knowledge can create new search forms to handle specific search and reporting needs which aren't covered by the built-in Advanced Search and Search Builder features.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Customize Data and Screens</adminGroup>
-     <icon>admin/small/template.png</icon>
      <weight>110</weight>
   </item>
   <item>
@@ -243,7 +226,6 @@
      <path_arguments>action=update</path_arguments>
      <page_callback>CRM_Contact_Form_Domain</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/domain.png</icon>
      <weight>10</weight>
   </item>
   <item>
@@ -252,7 +234,6 @@
      <desc>List of Email Addresses which can be used when sending emails to contacts.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/title.png</icon>
      <weight>20</weight>
   </item>
   <item>
@@ -261,7 +242,6 @@
      <desc>Message templates allow you to save and re-use messages with layouts which you can use when sending email to one or more contacts.</desc>
      <page_callback>CRM_Admin_Page_MessageTemplates</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/template.png</icon>
      <access_arguments>edit message templates;edit user-driven message templates;edit system workflow message templates</access_arguments>
      <weight>30</weight>
   </item>
@@ -281,7 +261,6 @@
      <access_callback>1</access_callback>
      <access_arguments>administer CiviCRM;edit all events</access_arguments>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/template.png</icon>
      <weight>40</weight>
   </item>
   <item>
@@ -294,7 +273,6 @@
      <desc>One or more preferred methods of communication can be assigned to each contact. Customize the available options here.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/communication.png</icon>
      <weight>50</weight>
   </item>
   <item>
@@ -303,7 +281,6 @@
      <desc>Configure Label Formats that are used when creating mailing labels.</desc>
      <page_callback>CRM_Admin_Page_LabelFormats</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/template.png</icon>
      <weight>60</weight>
   </item>
   <item>
@@ -312,7 +289,6 @@
      <desc>Configure PDF Page Formats that can be assigned to Message Templates when creating PDF letters.</desc>
      <page_callback>CRM_Admin_Page_PdfFormats</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/template.png</icon>
      <weight>70</weight>
   </item>
   <item>
@@ -321,7 +297,6 @@
      <desc>Options for Communication Style selection.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>75</weight>
   </item>
   <item>
@@ -330,7 +305,6 @@
      <desc>Options for assigning email greetings to individual and household contacts.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>80</weight>
   </item>
   <item>
@@ -339,7 +313,6 @@
      <desc>Options for assigning postal greetings to individual and household contacts.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>90</weight>
   </item>
   <item>
@@ -348,7 +321,6 @@
      <desc>Options for assigning addressee to individual, household and organization contacts.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Communications</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>100</weight>
   </item>
   <item>
@@ -356,7 +328,6 @@
      <title>Languages, Currency, Locations</title>
      <page_callback>CRM_Admin_Form_Setting_Localization</page_callback>
      <adminGroup>Localization</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>10</weight>
   </item>
   <item>
@@ -364,7 +335,6 @@
      <title>Address Settings</title>
      <page_callback>CRM_Admin_Form_Preferences_Address</page_callback>
      <adminGroup>Localization</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>20</weight>
   </item>
   <item>
@@ -372,7 +342,6 @@
      <title>Date Formats</title>
      <page_callback>CRM_Admin_Form_Setting_Date</page_callback>
      <adminGroup>Localization</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>30</weight>
   </item>
   <item>
@@ -381,7 +350,6 @@
      <desc>Options for contact languages.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Localization</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>40</weight>
   </item>
   <item>
@@ -390,7 +358,6 @@
      <desc>Grant or deny access to actions (view, edit...), features and components.</desc>
      <page_callback>CRM_Admin_Page_Access</page_callback>
      <adminGroup>Users and Permissions</adminGroup>
-     <icon>admin/small/03.png</icon>
      <weight>10</weight>
   </item>
     <item>
@@ -406,7 +373,6 @@
      <desc>Automatically create a CiviCRM contact record for each CMS user record.</desc>
      <page_callback>CRM_Admin_Form_CMSUser</page_callback>
      <adminGroup>Users and Permissions</adminGroup>
-     <icon>admin/small/Synch_user.png</icon>
      <weight>20</weight>
   </item>
   <item>
@@ -416,7 +382,6 @@
      <page_callback>CRM_Admin_Page_ConfigTaskList</page_callback>
      <return_url>civicrm/admin/configtask</return_url>
      <adminGroup>System Settings</adminGroup>
-     <icon>check.gif</icon>
      <weight>1</weight>
   </item>
   <item>
@@ -425,7 +390,6 @@
    <desc>Enable or disable components (e.g. CiviEvent, CiviMember, etc.) for your site based on the features you need. We recommend disabling any components not being used in order to simplify the user interface. You can easily re-enable components at any time from this screen.</desc>
      <page_callback>CRM_Admin_Form_Setting_Component</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>10</weight>
   </item>
   <item>
@@ -435,7 +399,6 @@
      <desc></desc>
      <access_arguments>administer CiviCRM</access_arguments>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/price_sets.png</icon>
      <weight>120</weight>
   </item>
   <item>
@@ -449,7 +412,6 @@
      <title>Outbound Email Settings</title>
      <page_callback>CRM_Admin_Form_Setting_Smtp</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/07.png</icon>
      <weight>20</weight>
   </item>
   <item>
@@ -458,7 +420,6 @@
      <desc>Payment Processor setup for CiviCRM transactions</desc>
      <page_callback>CRM_Admin_Page_PaymentProcessor</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/online_contribution_pages.png</icon>
      <weight>30</weight>
      <access_arguments>administer payment processors</access_arguments>
   </item>
@@ -467,7 +428,6 @@
      <title>Mapping and Geocoding</title>
      <page_callback>CRM_Admin_Form_Setting_Mapping</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>40</weight>
   </item>
   <item>
@@ -476,7 +436,6 @@
      <desc>Enable undelete/move to trash feature, detailed change logging, ReCAPTCHA to protect forms.</desc>
      <page_callback>CRM_Admin_Form_Setting_Miscellaneous</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>50</weight>
   </item>
   <item>
@@ -484,7 +443,6 @@
      <title>Directories</title>
      <page_callback>CRM_Admin_Form_Setting_Path</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>60</weight>
   </item>
   <item>
@@ -492,7 +450,6 @@
      <title>Resource URLs</title>
      <page_callback>CRM_Admin_Form_Setting_Url</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>70</weight>
   </item>
   <item>
@@ -501,7 +458,6 @@
      <desc>Reset the Base Directory Path and Base URL settings - generally when a CiviCRM site is moved to another location in the file system and/or to another domain.</desc>
      <page_callback>CRM_Admin_Form_Setting_UpdateConfigBackend</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/updatepath.png</icon>
      <weight>80</weight>
   </item>
   <item>
@@ -509,7 +465,6 @@
      <title>CMS Database Integration</title>
      <page_callback>CRM_Admin_Form_Setting_UF</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>90</weight>
   </item>
   <item>
@@ -518,7 +473,6 @@
      <desc>File Extensions that can be considered safe.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>100</weight>
   </item>
   <item>
@@ -527,7 +481,6 @@
      <desc>Access all meta-data option groups.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>105</weight>
   </item>
   <item>
@@ -536,7 +489,6 @@
      <desc>Import and Export mappings allow you to easily run the same job multiple times. This option allows you to rename or delete existing mappings.</desc>
      <page_callback>CRM_Admin_Page_Mapping</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/import_export_map.png</icon>
      <weight>110</weight>
   </item>
   <item>
@@ -544,7 +496,6 @@
      <title>Debugging</title>
      <page_callback>CRM_Admin_Form_Setting_Debugging</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>120</weight>
   </item>
   <item>
@@ -552,7 +503,6 @@
      <title>Multi Site Settings</title>
      <page_callback>CRM_Admin_Form_Generic</page_callback>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>130</weight>
   </item>
   <item>
@@ -594,7 +544,6 @@
      <page_callback>CRM_Admin_Page_Job</page_callback>
      <access_arguments>access CiviCRM,administer CiviCRM</access_arguments>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/13.png</icon>
      <weight>1370</weight>
   </item>
   <item>
@@ -604,7 +553,6 @@
      <page_callback>CRM_Admin_Page_JobLog</page_callback>
      <access_arguments>access CiviCRM,administer CiviCRM</access_arguments>
      <adminGroup>Manage</adminGroup>
-     <icon>admin/small/13.png</icon>
      <weight>1380</weight>
   </item>
   <item>
@@ -613,7 +561,6 @@
      <desc>List of types which can be assigned to Grants. (Enable CiviGrant from Administer > Systme Settings > Enable Components if you want to track grants.)</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>Option Lists</adminGroup>
-     <icon>admin/small/grant_type.png</icon>
      <weight>385</weight>
   </item>
   <item>
@@ -655,7 +602,6 @@
      <desc>Price sets allow you to offer multiple options with associated fees (e.g. pre-conference workshops, additional meals, etc.). Configure Price Sets for events which need more than a single set of fee levels.</desc>
      <access_arguments>access CiviCRM,access CiviEvent</access_arguments>
      <adminGroup>Customize</adminGroup>
-     <icon>admin/small/price_sets.png</icon>
      <weight>380</weight>
   </item>
   <item>
@@ -694,7 +640,6 @@
      <page_callback>CRM_SMS_Page_Provider</page_callback>
      <access_arguments>administer CiviCRM</access_arguments>
      <adminGroup>System Settings</adminGroup>
-     <icon>admin/small/36.png</icon>
      <weight>500</weight>
   </item>
     <item>
diff --git a/civicrm/CRM/Core/xml/Menu/Contact.xml b/civicrm/CRM/Core/xml/Menu/Contact.xml
index 26bf51d30c..e49b57236d 100644
--- a/civicrm/CRM/Core/xml/Menu/Contact.xml
+++ b/civicrm/CRM/Core/xml/Menu/Contact.xml
@@ -343,7 +343,6 @@
    <page_callback>CRM_Contact_Page_DedupeRules</page_callback>
    <access_arguments>administer dedupe rules;merge duplicate contacts</access_arguments>
    <adminGroup>Manage</adminGroup>
-   <icon>admin/small/duplicate_matching.png</icon>
    <weight>105</weight>
 </item>
 <item>
diff --git a/civicrm/CRM/Core/xml/Menu/Tag.xml b/civicrm/CRM/Core/xml/Menu/Tag.xml
index e05e6eed8b..aa975c3aba 100644
--- a/civicrm/CRM/Core/xml/Menu/Tag.xml
+++ b/civicrm/CRM/Core/xml/Menu/Tag.xml
@@ -8,7 +8,6 @@
     <page_callback>CRM_Tag_Page_Tag</page_callback>
     <access_arguments>administer CiviCRM;manage tags</access_arguments>
     <adminGroup>Customize Data and Screens</adminGroup>
-    <icon>admin/small/11.png</icon>
     <weight>25</weight>
   </item>
   <item>
diff --git a/civicrm/CRM/Custom/Form/Field.php b/civicrm/CRM/Custom/Form/Field.php
index 4f5625d81a..e61d23ed80 100644
--- a/civicrm/CRM/Custom/Form/Field.php
+++ b/civicrm/CRM/Custom/Form/Field.php
@@ -76,7 +76,6 @@ class CRM_Custom_Form_Field extends CRM_Core_Form {
       'Select' => 'Select',
       'Radio' => 'Radio',
       'CheckBox' => 'CheckBox',
-      'Multi-Select' => 'Multi-Select',
       'Autocomplete-Select' => 'Autocomplete-Select',
     ],
     ['Text' => 'Text', 'Select' => 'Select', 'Radio' => 'Radio'],
@@ -85,8 +84,8 @@ class CRM_Custom_Form_Field extends CRM_Core_Form {
     ['TextArea' => 'TextArea', 'RichTextEditor' => 'RichTextEditor'],
     ['Date' => 'Select Date'],
     ['Radio' => 'Radio'],
-    ['StateProvince' => 'Select State/Province', 'Multi-Select' => 'Multi-Select State/Province'],
-    ['Country' => 'Select Country', 'Multi-Select' => 'Multi-Select Country'],
+    ['StateProvince' => 'Select State/Province'],
+    ['Country' => 'Select Country'],
     ['File' => 'File'],
     ['Link' => 'Link'],
     ['ContactReference' => 'Autocomplete-Select'],
@@ -141,7 +140,6 @@ class CRM_Custom_Form_Field extends CRM_Core_Form {
           'Select' => ts('Select'),
           'Radio' => ts('Radio'),
           'CheckBox' => ts('CheckBox'),
-          'Multi-Select' => ts('Multi-Select'),
           'Autocomplete-Select' => ts('Autocomplete-Select'),
         ],
         [
@@ -162,8 +160,8 @@ class CRM_Custom_Form_Field extends CRM_Core_Form {
         ['TextArea' => ts('TextArea'), 'RichTextEditor' => ts('Rich Text Editor')],
         ['Date' => ts('Select Date')],
         ['Radio' => ts('Radio')],
-        ['StateProvince' => ts('Select State/Province'), 'Multi-Select' => ts('Multi-Select State/Province')],
-        ['Country' => ts('Select Country'), 'Multi-Select' => ts('Multi-Select Country')],
+        ['StateProvince' => ts('Select State/Province')],
+        ['Country' => ts('Select Country')],
         ['File' => ts('Select File')],
         ['Link' => ts('Link')],
         ['ContactReference' => ts('Autocomplete-Select')],
@@ -329,6 +327,8 @@ class CRM_Custom_Form_Field extends CRM_Core_Form {
       'return' => ['title'],
     ];
 
+    $this->add('checkbox', 'serialize', ts('Multi-Select'));
+
     if ($this->_action == CRM_Core_Action::UPDATE) {
       $this->freeze('data_type');
       if (!empty($this->_values['option_group_id'])) {
@@ -727,7 +727,7 @@ SELECT count(*)
     if (isset($fields['data_type'][1])) {
       $dataField = $fields['data_type'][1];
     }
-    $optionFields = ['Select', 'Multi-Select', 'CheckBox', 'Radio'];
+    $optionFields = ['Select', 'CheckBox', 'Radio'];
 
     if (isset($fields['option_type']) && $fields['option_type'] == 1) {
       //capture duplicate Custom option values
@@ -950,6 +950,17 @@ AND    option_group_id = %2";
       $params['is_search_range'] = 0;
     }
 
+    // Serialization cannot be changed on update
+    if ($this->_id) {
+      unset($params['serialize']);
+    }
+    elseif (strpos($params['html_type'], 'Select') === 0) {
+      $params['serialize'] = $params['serialize'] ? CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND : 'null';
+    }
+    else {
+      $params['serialize'] = $params['html_type'] == 'CheckBox' ? CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND : 'null';
+    }
+
     $filter = 'null';
     if ($dataTypeKey == 11 && !empty($params['filter_selected'])) {
       if ($params['filter_selected'] == 'Advance' && trim(CRM_Utils_Array::value('filter', $params))) {
diff --git a/civicrm/CRM/Dedupe/MergeHandler.php b/civicrm/CRM/Dedupe/MergeHandler.php
index db454c0e70..e48352cfd7 100644
--- a/civicrm/CRM/Dedupe/MergeHandler.php
+++ b/civicrm/CRM/Dedupe/MergeHandler.php
@@ -123,7 +123,7 @@ class CRM_Dedupe_MergeHandler {
   public function getTablesDynamicallyRelatedToContactTable() {
     if (!isset(\Civi::$statics[__CLASS__]['dynamic'])) {
       \Civi::$statics[__CLASS__]['dynamic'] = [];
-      foreach (CRM_Core_DAO::getDynamicReferencesToTable('civicrm_contact') as $tableName => $field) {
+      foreach (CRM_Core_DAO::getDynamicReferencesToTable('civicrm_contact') as $tableName => $fields) {
         if ($tableName === 'civicrm_financial_item') {
           // It turns out that civicrm_financial_item does not have an index on entity_table (only as the latter
           // part of a entity_id/entity_table index which probably is not adding any value over & above entity_id
@@ -131,7 +131,9 @@ class CRM_Dedupe_MergeHandler {
           // values for entity_table in the schema.
           continue;
         }
-        $sql[] = "(SELECT '$tableName' as civicrm_table, '{$field[0]}' as field_name FROM $tableName WHERE entity_table = 'civicrm_contact' LIMIT 1)";
+        foreach ($fields as $field) {
+          $sql[] = "(SELECT '$tableName' as civicrm_table, '{$field[0]}' as field_name FROM $tableName WHERE {$field[1]} = 'civicrm_contact' LIMIT 1)";
+        }
       }
       $sqlString = implode(' UNION ', $sql);
       if ($sqlString) {
diff --git a/civicrm/CRM/Dedupe/Merger.php b/civicrm/CRM/Dedupe/Merger.php
index c19ed52f2a..9f161af164 100644
--- a/civicrm/CRM/Dedupe/Merger.php
+++ b/civicrm/CRM/Dedupe/Merger.php
@@ -492,6 +492,7 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
     $otherId = $mergeHandler->getToRemoveID();
     $cidRefs = self::cidRefs();
     $eidRefs = $mergeHandler->getTablesDynamicallyRelatedToContactTable();
+    $dynamicRefs = CRM_Core_DAO::getDynamicReferencesToTable('civicrm_contact');
     $cpTables = self::cpTables();
     $paymentTables = self::paymentTables();
     self::filterRowBasedCustomDataFromCustomTables($cidRefs);
@@ -543,14 +544,15 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
 
           $preOperationSqls = self::operationSql($mainId, $otherId, $table, $tableOperations);
           $sqls = array_merge($sqls, $preOperationSqls);
-          $sqls[] = "UPDATE IGNORE $table SET $field = $mainId WHERE $field = $otherId";
-          $sqls[] = "DELETE FROM $table WHERE $field = $otherId";
+          $sqls[] = "UPDATE $table SET $field = $mainId WHERE $field = $otherId";
         }
       }
 
       if (isset($eidRefs[$table])) {
-        $sqls[] = "UPDATE IGNORE $table SET {$eidRefs[$table]}= $mainId WHERE {$eidRefs[$table]} = $otherId AND entity_table = 'civicrm_contact'";
-        $sqls[] = "DELETE FROM $table WHERE {$eidRefs[$table]} = $otherId AND entity_table = 'civicrm_contact'";
+        foreach ($dynamicRefs[$table] as $dynamicRef) {
+          $sqls[] = "UPDATE IGNORE $table SET {$dynamicRef[0]}= $mainId WHERE {$dynamicRef[0]} = $otherId AND {$dynamicRef[1]} = 'civicrm_contact'";
+          $sqls[] = "DELETE FROM $table WHERE {$dynamicRef[0]} = $otherId AND {$dynamicRef[1]} = 'civicrm_contact'";
+        }
       }
     }
 
@@ -1918,90 +1920,72 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
         return [$cFields, $submitted];
       }
       $htmlType = $cFields[$fid]['attributes']['html_type'];
-      switch ($htmlType) {
-        case 'File':
-          // Handled in CustomField->move(). Tested in testMergeCustomFields.
-          unset($submitted["custom_$fid"]);
-          break;
-
-        case 'Select Country':
-          // @todo Test in testMergeCustomFields disabled as this does not work, Handle in CustomField->move().
-        case 'Select State/Province':
-          $submitted[$key] = CRM_Core_BAO_CustomField::displayValue($value, $fid);
-          break;
-
-        case 'Select Date':
-          if ($cFields[$fid]['attributes']['is_view']) {
-            $submitted[$key] = date('YmdHis', strtotime($submitted[$key]));
-          }
-          break;
+      $isSerialized = CRM_Core_BAO_CustomField::isSerialized($cFields[$fid]['attributes']);
 
-        case 'CheckBox':
-        case 'Multi-Select':
-        case 'Multi-Select Country':
-        case 'Multi-Select State/Province':
-          // Merge values from both contacts for multivalue fields, CRM-4385
-          // get the existing custom values from db.
-          $customParams = ['entityID' => $mainId, $key => TRUE];
-          $customfieldValues = CRM_Core_BAO_CustomValueTable::getValues($customParams);
-          if (!empty($customfieldValues[$key])) {
-            $existingValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, $customfieldValues[$key]);
-            if (is_array($existingValue) && !empty($existingValue)) {
-              $mergeValue = $submittedCustomFields = [];
-              if ($value == 'null') {
-                // CRM-19074 if someone has deliberately chosen to overwrite with 'null', respect it.
-                $submitted[$key] = $value;
+      if ($htmlType === 'File') {
+        // Handled in CustomField->move(). Tested in testMergeCustomFields.
+        unset($submitted["custom_$fid"]);
+      }
+      elseif (!$isSerialized && ($htmlType === 'Select Country' || $htmlType === 'Select State/Province')) {
+        // @todo Test in testMergeCustomFields disabled as this does not work, Handle in CustomField->move().
+        $submitted[$key] = CRM_Core_BAO_CustomField::displayValue($value, $fid);
+      }
+      elseif ($htmlType === 'Select Date') {
+        if ($cFields[$fid]['attributes']['is_view']) {
+          $submitted[$key] = date('YmdHis', strtotime($submitted[$key]));
+        }
+      }
+      elseif ($isSerialized) {
+        // Merge values from both contacts for multivalue fields, CRM-4385
+        // get the existing custom values from db.
+        $customParams = ['entityID' => $mainId, $key => TRUE];
+        $customfieldValues = CRM_Core_BAO_CustomValueTable::getValues($customParams);
+        if (!empty($customfieldValues[$key])) {
+          $existingValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, $customfieldValues[$key]);
+          if (is_array($existingValue) && !empty($existingValue)) {
+            $mergeValue = $submittedCustomFields = [];
+            if ($value == 'null') {
+              // CRM-19074 if someone has deliberately chosen to overwrite with 'null', respect it.
+              $submitted[$key] = $value;
+            }
+            else {
+              if ($value) {
+                $submittedCustomFields = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
               }
-              else {
-                if ($value) {
-                  $submittedCustomFields = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
-                }
 
-                // CRM-19653: overwrite or add the existing custom field value with dupicate contact's
-                // custom field value stored at $submittedCustomValue.
-                foreach ($submittedCustomFields as $k => $v) {
-                  if ($v != '' && !in_array($v, $mergeValue)) {
-                    $mergeValue[] = $v;
-                  }
+              // CRM-19653: overwrite or add the existing custom field value with dupicate contact's
+              // custom field value stored at $submittedCustomValue.
+              foreach ($submittedCustomFields as $k => $v) {
+                if ($v != '' && !in_array($v, $mergeValue)) {
+                  $mergeValue[] = $v;
                 }
+              }
 
-                //keep state and country as array format.
-                //for checkbox and m-select format w/ VALUE_SEPARATOR
-                if (in_array($htmlType, [
-                  'CheckBox',
-                  'Multi-Select',
-                ])) {
-                  $submitted[$key] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR,
-                      $mergeValue
-                    ) . CRM_Core_DAO::VALUE_SEPARATOR;
-                }
-                else {
-                  $submitted[$key] = $mergeValue;
-                }
+              //keep state and country as array format.
+              //for checkbox and m-select format w/ VALUE_SEPARATOR
+              if (in_array($htmlType, ['CheckBox', 'Select'])) {
+                $submitted[$key] = CRM_Utils_Array::implodePadded($mergeValue);
+              }
+              else {
+                $submitted[$key] = $mergeValue;
               }
             }
           }
-          elseif (in_array($htmlType, [
-            'Multi-Select Country',
-            'Multi-Select State/Province',
-          ])) {
-            //we require submitted values should be in array format
-            if ($value) {
-              $mergeValueArray = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
-              //hack to remove null values from array.
-              $mergeValue = [];
-              foreach ($mergeValueArray as $k => $v) {
-                if ($v != '') {
-                  $mergeValue[] = $v;
-                }
+        }
+        elseif (in_array($htmlType, ['Select Country', 'Select State/Province'])) {
+          //we require submitted values should be in array format
+          if ($value) {
+            $mergeValueArray = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
+            //hack to remove null values from array.
+            $mergeValue = [];
+            foreach ($mergeValueArray as $k => $v) {
+              if ($v != '') {
+                $mergeValue[] = $v;
               }
-              $submitted[$key] = $mergeValue;
             }
+            $submitted[$key] = $mergeValue;
           }
-          break;
-
-        default:
-          break;
+        }
       }
     }
     return [$cFields, $submitted];
diff --git a/civicrm/CRM/Event/BAO/Event.php b/civicrm/CRM/Event/BAO/Event.php
index 1e178acae2..794e5d14e5 100644
--- a/civicrm/CRM/Event/BAO/Event.php
+++ b/civicrm/CRM/Event/BAO/Event.php
@@ -846,10 +846,6 @@ WHERE civicrm_event.is_active = 1
     // be clearer & safer here
     $permissions = CRM_Core_Permission::event(CRM_Core_Permission::VIEW);
 
-    // check if we're in shopping cart mode for events
-    $enable_cart = Civi::settings()->get('enable_cart');
-    if ($enable_cart) {
-    }
     while ($dao->fetch()) {
       if (!empty($permissions) && in_array($dao->event_id, $permissions)) {
         $info = [];
@@ -891,7 +887,9 @@ WHERE civicrm_event.is_active = 1
         $info['location'] = $address;
         $info['url'] = CRM_Utils_System::url('civicrm/event/info', 'reset=1&id=' . $dao->event_id, TRUE, NULL, FALSE);
 
-        if ($enable_cart) {
+        // @todo Move to eventcart extension
+        // check if we're in shopping cart mode for events
+        if ((bool) Civi::settings()->get('enable_cart')) {
           $reg = CRM_Event_Cart_BAO_EventInCart::get_registration_link($dao->event_id);
           $info['registration_link'] = CRM_Utils_System::url($reg['path'], $reg['query'], TRUE);
           $info['registration_link_text'] = $reg['label'];
@@ -2387,4 +2385,45 @@ LEFT  JOIN  civicrm_price_field_value value ON ( value.id = lineItem.price_field
     ];
   }
 
+  /**
+   * Get the appropriate links to iCal pages/feeds.
+   *
+   * @param int $eventId
+   *
+   * @return array
+   *   All of the icons to show.
+   */
+  public static function getICalLinks($eventId = NULL) {
+    $return = $eventId ? [] : [
+      [
+        'url' => CRM_Utils_System::url('civicrm/event/ical', 'reset=1&list=1&html=1', TRUE, NULL, TRUE),
+        'text' => ts('HTML listing of current and future public events.'),
+        'icon' => 'fa-th-list',
+      ],
+      [
+        'url' => CRM_Utils_System::url('civicrm/event/ical', 'reset=1&list=1&rss=1', TRUE, NULL, TRUE),
+        'text' => ts('Get RSS 2.0 feed for current and future public events.'),
+        'icon' => 'fa-rss',
+      ],
+    ];
+    $query = [
+      'reset' => 1,
+    ];
+    if ($eventId) {
+      $query['id'] = $eventId;
+    }
+    $return[] = [
+      'url' => CRM_Utils_System::url('civicrm/event/ical', $query, TRUE, NULL, TRUE),
+      'text' => $eventId ? ts('Download iCalendar entry for this event.') : ts('Download iCalendar entry for current and future public events.'),
+      'icon' => 'fa-download',
+    ];
+    $query['list'] = 1;
+    $return[] = [
+      'url' => CRM_Utils_System::url('civicrm/event/ical', $query, TRUE, NULL, TRUE),
+      'text' => $eventId ? ts('iCalendar feed for this event.') : ts('iCalendar feed for current and future public events.'),
+      'icon' => 'fa-link',
+    ];
+    return $return;
+  }
+
 }
diff --git a/civicrm/CRM/Event/Cart/BAO/MerParticipant.php b/civicrm/CRM/Event/Cart/BAO/MerParticipant.php
index 553ab9578b..4cdf4e341b 100644
--- a/civicrm/CRM/Event/Cart/BAO/MerParticipant.php
+++ b/civicrm/CRM/Event/Cart/BAO/MerParticipant.php
@@ -38,7 +38,7 @@ class CRM_Event_Cart_BAO_MerParticipant extends CRM_Event_BAO_Participant {
     $a = (array) $participant;
     $this->copyValues($a);
 
-    $this->email = $participant['email'] ?? NULL;
+    $this->email = $a['email'] ?? NULL;
   }
 
   /**
diff --git a/civicrm/CRM/Event/Controller/Registration.php b/civicrm/CRM/Event/Controller/Registration.php
index 5233eb3e80..561d2ed8b8 100644
--- a/civicrm/CRM/Event/Controller/Registration.php
+++ b/civicrm/CRM/Event/Controller/Registration.php
@@ -10,11 +10,7 @@
  */
 
 /**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * Class CRM_Event_Controller_Registration
  */
 class CRM_Event_Controller_Registration extends CRM_Core_Controller {
 
diff --git a/civicrm/CRM/Event/Controller/Search.php b/civicrm/CRM/Event/Controller/Search.php
index 8bf9a9996e..927c9422fe 100644
--- a/civicrm/CRM/Event/Controller/Search.php
+++ b/civicrm/CRM/Event/Controller/Search.php
@@ -9,14 +9,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 /**
  * This class is used by the Search functionality.
  *
@@ -36,6 +28,8 @@ class CRM_Event_Controller_Search extends CRM_Core_Controller {
    * @param string $title
    * @param bool|int $action
    * @param bool $modal
+   *
+   * @throws \CRM_Core_Exception
    */
   public function __construct($title = NULL, $action = CRM_Core_Action::NONE, $modal = TRUE) {
 
diff --git a/civicrm/CRM/Event/Form/ManageEvent/TabHeader.php b/civicrm/CRM/Event/Form/ManageEvent/TabHeader.php
index 890782c624..6b4c83d199 100644
--- a/civicrm/CRM/Event/Form/ManageEvent/TabHeader.php
+++ b/civicrm/CRM/Event/Form/ManageEvent/TabHeader.php
@@ -86,8 +86,7 @@ class CRM_Event_Form_ManageEvent_TabHeader {
     }
 
     // check if we're in shopping cart mode for events
-    $enableCart = Civi::settings()->get('enable_cart');
-    if (!$enableCart) {
+    if (!(bool) Civi::settings()->get('enable_cart')) {
       unset($tabs['conference']);
     }
 
@@ -107,7 +106,7 @@ LEFT JOIN  civicrm_recurring_entity re ON ( e.id = re.entity_id AND re.entity_ta
 WHERE      e.id = %1
 ";
       //Check if repeat is configured
-      $eventHasParent = CRM_Core_BAO_RecurringEntity::getParentFor($eventID, 'civicrm_event');
+      CRM_Core_BAO_RecurringEntity::getParentFor($eventID, 'civicrm_event');
       $params = [
         1 => [$eventID, 'Integer'],
         2 => [$eventNameMapping->getId(), 'Integer'],
diff --git a/civicrm/CRM/Event/Form/Registration.php b/civicrm/CRM/Event/Form/Registration.php
index efa71d4605..8e69eb560e 100644
--- a/civicrm/CRM/Event/Form/Registration.php
+++ b/civicrm/CRM/Event/Form/Registration.php
@@ -199,10 +199,10 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
     $this->_isEventFull = $this->get('isEventFull');
     $this->_lineItemParticipantsCount = $this->get('lineItemParticipants');
     if (!is_array($this->_lineItem)) {
-      $this->_lineItem = array();
+      $this->_lineItem = [];
     }
     if (!is_array($this->_lineItemParticipantsCount)) {
-      $this->_lineItemParticipantsCount = array();
+      $this->_lineItemParticipantsCount = [];
     }
     $this->_availableRegistrations = $this->get('availableRegistrations');
     $this->_participantIDS = $this->get('participantIDs');
@@ -232,7 +232,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
       }
 
       // get all the values from the dao object
-      $this->_values = $this->_fields = array();
+      $this->_values = $this->_fields = [];
 
       //retrieve event information
       $params = array('id' => $this->_eventId);
@@ -519,7 +519,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
       if ($contactID) {
         //FIX CRM-9653
         if (is_array($id)) {
-          $fields = array();
+          $fields = [];
           foreach ($id as $profileID) {
             $field = CRM_Core_BAO_UFGroup::getFields($profileID, FALSE, CRM_Core_Action::ADD,
               NULL, NULL, FALSE, NULL,
@@ -643,7 +643,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
     }
     $eventFee = $form->_values['fee'] ?? NULL;
     if (!is_array($eventFee) || empty($eventFee)) {
-      $form->_values['fee'] = array();
+      $form->_values['fee'] = [];
     }
 
     //fix for non-upgraded price sets.CRM-4256.
@@ -876,7 +876,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
 
     $priceSetId = $form->get('priceSetId');
     $addParticipantNum = substr($form->_name, 12);
-    $priceSetFields = $priceSetDetails = array();
+    $priceSetFields = $priceSetDetails = [];
     $hasPriceFieldsCount = FALSE;
     if ($priceSetId) {
       $priceSetDetails = $form->get('priceSet');
@@ -975,7 +975,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
     $priceSetDetails = $form->get('priceSet');
 
     foreach ($params as $key => & $value) {
-      $vals = array();
+      $vals = [];
       if (strpos($key, 'price_') !== FALSE) {
         $fieldId = substr($key, 6);
         if (!array_key_exists($fieldId, $priceSetDetails['fields']) ||
@@ -1014,7 +1014,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
     $priceSet = $form->get('priceSet');
     $priceSetId = $form->get('priceSetId');
 
-    $optionsCount = array();
+    $optionsCount = [];
     if (!$priceSetId ||
       !is_array($priceSet) ||
       empty($priceSet) ||
@@ -1024,7 +1024,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
       return $optionsCount;
     }
 
-    $priceSetFields = $priceMaxFieldDetails = array();
+    $priceSetFields = $priceMaxFieldDetails = [];
     if (!empty($priceSet['optionsCountTotal'])) {
       $priceSetFields = $priceSet['optionsCountDetails']['fields'];
     }
@@ -1123,7 +1123,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
    * @param array $optionFullIds
    * @param CRM_Core_Form $form
    */
-  public static function resetElementValue($optionFullIds = array(), &$form) {
+  public static function resetElementValue($optionFullIds = [], &$form) {
     if (!is_array($optionFullIds) ||
       empty($optionFullIds) ||
       !$form->isSubmitted()
@@ -1196,7 +1196,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
    * @param array $optionIds
    * @param CRM_Core_Form $form
    */
-  public static function resetSubmittedValue($elementName, $optionIds = array(), &$form) {
+  public static function resetSubmittedValue($elementName, $optionIds = [], &$form) {
     if (empty($elementName) ||
       !$form->elementExists($elementName) ||
       !$form->getSubmitValue($elementName)
@@ -1247,7 +1247,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
    * @return array
    */
   public static function validatePriceSet(&$form, $params) {
-    $errors = array();
+    $errors = [];
     $hasOptMaxValue = FALSE;
     if (!is_array($params) || empty($params)) {
       return $errors;
@@ -1268,7 +1268,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
       return $errors;
     }
 
-    $optionsCountDetails = $optionsMaxValueDetails = array();
+    $optionsCountDetails = $optionsMaxValueDetails = [];
     if (
       isset($priceSetDetails['optionsMaxValueTotal'])
       && $priceSetDetails['optionsMaxValueTotal']
@@ -1289,7 +1289,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
       $feeBlock = $priceSetDetails['fields'];
     }
 
-    $optionMaxValues = $fieldSelected = array();
+    $optionMaxValues = $fieldSelected = [];
     foreach ($params as $pNum => $values) {
       if (!is_array($values) || $values == 'skip') {
         continue;
@@ -1348,7 +1348,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
 
     //validate for option max value.
     foreach ($optionMaxValues as $fieldId => $values) {
-      $options = CRM_Utils_Array::value('options', $feeBlock[$fieldId], array());
+      $options = CRM_Utils_Array::value('options', $feeBlock[$fieldId], []);
       foreach ($values as $optId => $total) {
         $optMax = $optionsMaxValueDetails[$fieldId]['options'][$optId];
         $opDbCount = CRM_Utils_Array::value('db_total_count', $options[$optId], 0);
@@ -1383,7 +1383,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
     $this->_participantId = $participantID;
     $this->set('participantId', $this->_participantId);
 
-    $ids = $participantValues = array();
+    $ids = $participantValues = [];
     $participantParams = array('id' => $this->_participantId);
     CRM_Event_BAO_Participant::getValues($participantParams, $participantValues, $ids);
     $this->_values['participant'] = $participantValues[$this->_participantId];
@@ -1486,14 +1486,14 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
    */
   public function processRegistration($params, $contactID = NULL) {
     $session = CRM_Core_Session::singleton();
-    $this->_participantInfo = array();
+    $this->_participantInfo = [];
 
     // CRM-4320, lets build array of cancelled additional participant ids
     // those are drop or skip by primary at the time of confirmation.
     // get all in and then unset those are confirmed.
     $cancelledIds = $this->_additionalParticipantIds;
 
-    $participantCount = array();
+    $participantCount = [];
     foreach ($params as $participantNum => $record) {
       if ($record == 'skip') {
         $participantCount[$participantNum] = 'skip';
diff --git a/civicrm/CRM/Event/Form/Registration/Confirm.php b/civicrm/CRM/Event/Form/Registration/Confirm.php
index 4547e4c173..14afb06fe5 100644
--- a/civicrm/CRM/Event/Form/Registration/Confirm.php
+++ b/civicrm/CRM/Event/Form/Registration/Confirm.php
@@ -439,33 +439,13 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
     $fields = [];
     foreach ($params as $key => $value) {
       CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
-      //unset the billing parameters if it is pay later mode
-      //to avoid creation of billing location
-      // @todo - the reasoning for this is unclear - elsewhere we check what fields are provided by
-      // the form & if billing fields exist we create the address, relying on the form to collect
-      // only information we intend to store.
       if ($this->_allowWaitlist
         || $this->_requireApproval
         || (!empty($value['is_pay_later']) && !$this->_isBillingAddressRequiredForPayLater)
         || empty($value['is_primary'])
       ) {
-        $billingFields = [
-          "email-{$this->_bltID}",
-          'billing_first_name',
-          'billing_middle_name',
-          'billing_last_name',
-          "billing_street_address-{$this->_bltID}",
-          "billing_city-{$this->_bltID}",
-          "billing_state_province-{$this->_bltID}",
-          "billing_state_province_id-{$this->_bltID}",
-          "billing_postal_code-{$this->_bltID}",
-          "billing_country-{$this->_bltID}",
-          "billing_country_id-{$this->_bltID}",
-          "address_name-{$this->_bltID}",
-        ];
-        foreach ($billingFields as $field) {
-          unset($value[$field]);
-        }
+        // This is confusing because unnecessary code around it has been removed. It is not
+        // clear why we do this / whether we should.
         if (!empty($value['is_pay_later'])) {
           $this->_values['params']['is_pay_later'] = TRUE;
         }
diff --git a/civicrm/CRM/Event/Form/Registration/Register.php b/civicrm/CRM/Event/Form/Registration/Register.php
index e39d386e6b..a2bc57ef5f 100644
--- a/civicrm/CRM/Event/Form/Registration/Register.php
+++ b/civicrm/CRM/Event/Form/Registration/Register.php
@@ -467,25 +467,24 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
 
       // CRM-11182 - Optional confirmation screen
       // Change button label depending on whether the next action is confirm or register
+      $buttonParams = [
+        'type' => 'upload',
+        'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
+        'isDefault' => TRUE,
+      ];
       if (
         !$this->_values['event']['is_multiple_registrations']
         && !$this->_values['event']['is_monetary']
         && !$this->_values['event']['is_confirm_enabled']
       ) {
-        $buttonLabel = ts('Register');
+        $buttonParams['name'] = ts('Register');
       }
       else {
-        $buttonLabel = ts('Review your registration');
+        $buttonParams['name'] = ts('Review your registration');
+        $buttonParams['icon'] = 'fa-chevron-right';
       }
 
-      $this->addButtons([
-        [
-          'type' => 'upload',
-          'name' => $buttonLabel,
-          'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
-          'isDefault' => TRUE,
-        ],
-      ]);
+      $this->addButtons([$buttonParams]);
     }
 
     $this->addFormRule(['CRM_Event_Form_Registration_Register', 'formRule'], $this);
diff --git a/civicrm/CRM/Event/Form/Registration/ThankYou.php b/civicrm/CRM/Event/Form/Registration/ThankYou.php
index d186528e18..4f9898b540 100644
--- a/civicrm/CRM/Event/Form/Registration/ThankYou.php
+++ b/civicrm/CRM/Event/Form/Registration/ThankYou.php
@@ -175,6 +175,8 @@ class CRM_Event_Form_Registration_ThankYou extends CRM_Event_Form_Registration {
       $this->assign('friendURL', $url);
     }
 
+    $this->assign('iCal', CRM_Event_BAO_Event::getICalLinks($this->_eventId));
+
     $this->freeze();
 
     //lets give meaningful status message, CRM-4320.
diff --git a/civicrm/CRM/Event/Form/Task/Batch.php b/civicrm/CRM/Event/Form/Task/Batch.php
index 3979b29edd..9a52015e42 100644
--- a/civicrm/CRM/Event/Form/Task/Batch.php
+++ b/civicrm/CRM/Event/Form/Task/Batch.php
@@ -75,19 +75,18 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
   /**
    * Build the form object.
    *
-   *
-   * @return void
+   * @throws \CRM_Core_Exception
    */
   public function buildQuickForm() {
     $ufGroupId = $this->get('ufGroupId');
     if (!$ufGroupId) {
-      CRM_Core_Error::fatal('ufGroupId is missing');
+      CRM_Core_Error::statusBounce('ufGroupId is missing');
     }
 
     $this->_title = ts('Update multiple participants') . ' - ' . CRM_Core_BAO_UFGroup::getTitle($ufGroupId);
     CRM_Utils_System::setTitle($this->_title);
     $this->addDefaultButtons(ts('Save'));
-    $this->_fields = [];
+
     $this->_fields = CRM_Core_BAO_UFGroup::getFields($ufGroupId, FALSE, CRM_Core_Action::VIEW);
     if (array_key_exists('participant_status', $this->_fields)) {
       $this->assign('statusProfile', 1);
@@ -194,7 +193,7 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
           }
         }
         else {
-          if ($field['name'] == 'participant_role') {
+          if ($field['name'] === 'participant_role') {
             $field['is_multiple'] = TRUE;
           }
           // handle non custom fields
@@ -208,7 +207,7 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
     // don't set the status message when form is submitted.
     $buttonName = $this->controller->getButtonName('submit');
 
-    if ($suppressFields && $buttonName != '_qf_Batch_next') {
+    if ($suppressFields && $buttonName !== '_qf_Batch_next') {
       CRM_Core_Session::setStatus(ts("File type field(s) in the selected profile are not supported for Update multiple participants."), ts('Unsupported Field Type'), 'info');
     }
 
@@ -218,12 +217,11 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
   /**
    * Set default values for the form.
    *
-   *
-   * @return void
+   * @return array
    */
   public function setDefaultValues() {
     if (empty($this->_fields)) {
-      return;
+      return [];
     }
 
     $defaults = [];
@@ -265,6 +263,8 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
    * @param int $statusId
    *
    * @return mixed
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   public static function updatePendingOnlineContribution($participantId, $statusId) {
     if (!$participantId || !$statusId) {
@@ -315,13 +315,17 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
   /**
    * Update contribution status.
    *
+   * @param array $params
+   *
+   * @return NULL|int
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   * @throws \Exception
+   *
    * @deprecated
    * This is only called from one place in the code &
    * it is unclear whether it is a function on the way in or on the way out
    *
-   * @param array $params
-   *
-   * @return NULL|int
    */
   public static function updateContributionStatus($params) {
     // get minimum required values.
@@ -346,7 +350,7 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
       );
     }
 
-    if ($componentName == 'Event') {
+    if ($componentName === 'Event') {
       $name = 'event';
       $ids['participant'] = $componentId;
 
@@ -358,7 +362,7 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
       }
     }
 
-    if ($componentName == 'Membership') {
+    if ($componentName === 'Membership') {
       $name = 'contribute';
       $ids['membership'] = $componentId;
     }
@@ -367,14 +371,13 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
     $input['component'] = $name;
 
     $baseIPN = new CRM_Core_Payment_BaseIPN();
-    $transaction = new CRM_Core_Transaction();
 
     // reset template values.
     $template = CRM_Core_Smarty::singleton();
     $template->clearTemplateVars();
 
     if (!$baseIPN->validateData($input, $ids, $objects, FALSE)) {
-      CRM_Core_Error::fatal();
+      throw new CRM_Core_Exception('validation error');
     }
 
     $contribution = &$objects['contribution'];
@@ -385,11 +388,13 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
     ]);
     $input['IAmAHorribleNastyBeyondExcusableHackInTheCRMEventFORMTaskClassThatNeedsToBERemoved'] = $params['IAmAHorribleNastyBeyondExcusableHackInTheCRMEventFORMTaskClassThatNeedsToBERemoved'] ?? NULL;
     if ($statusId == $contributionStatuses['Cancelled']) {
+      $transaction = new CRM_Core_Transaction();
       $baseIPN->cancelled($objects, $transaction, $input);
       $transaction->commit();
       return $statusId;
     }
     elseif ($statusId == $contributionStatuses['Failed']) {
+      $transaction = new CRM_Core_Transaction();
       $baseIPN->failed($objects, $transaction, $input);
       $transaction->commit();
       return $statusId;
@@ -397,7 +402,6 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
 
     // status is not pending
     if ($contribution->contribution_status_id != $contributionStatuses['Pending']) {
-      $transaction->commit();
       return;
     }
 
@@ -426,7 +430,7 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
     //complete the contribution.
     // @todo use the api - ie civicrm_api3('Contribution', 'completetransaction', $input);
     // as this method is not preferred / supported.
-    $baseIPN->completeTransaction($input, $ids, $objects, $transaction, FALSE);
+    CRM_Contribute_BAO_Contribution::completeOrder($input, $ids, $objects);
 
     // reset template values before processing next transactions
     $template->clearTemplateVars();
@@ -448,7 +452,10 @@ class CRM_Event_Form_Task_Batch extends CRM_Event_Form_Task {
   }
 
   /**
-   * @param $params
+   * @param array $params
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   public function submit($params) {
     $statusClasses = CRM_Event_PseudoConstant::participantStatusClass();
diff --git a/civicrm/CRM/Event/Import/Form/MapField.php b/civicrm/CRM/Event/Import/Form/MapField.php
index b418566f2b..f208534d4a 100644
--- a/civicrm/CRM/Event/Import/Form/MapField.php
+++ b/civicrm/CRM/Event/Import/Form/MapField.php
@@ -38,7 +38,7 @@ class CRM_Event_Import_Form_MapField extends CRM_Import_Form_MapField {
 
     $skipColumnHeader = $this->controller->exportValue('DataSource', 'skipColumnHeader');
     $this->_onDuplicate = $this->get('onDuplicate');
-    $highlightedFields = array();
+    $highlightedFields = [];
     if ($skipColumnHeader) {
       $this->assign('skipColumnHeader', $skipColumnHeader);
       $this->assign('rowDisplayCount', 3);
@@ -107,7 +107,7 @@ class CRM_Event_Import_Form_MapField extends CRM_Import_Form_MapField {
       //mapping is to be loaded from database
 
       $params = array('id' => $savedMapping);
-      $temp = array();
+      $temp = [];
       $mappingDetails = CRM_Core_BAO_Mapping::retrieve($params, $temp);
 
       $this->assign('loadedMapping', $mappingDetails->name);
@@ -135,7 +135,7 @@ class CRM_Event_Import_Form_MapField extends CRM_Import_Form_MapField {
 
     $this->addFormRule(array('CRM_Event_Import_Form_MapField', 'formRule'), $this);
 
-    $defaults = array();
+    $defaults = [];
     $mapperKeys = array_keys($this->_mapperFields);
     $hasHeaders = !empty($this->_columnHeaders);
     $headerPatterns = $this->get('headerPatterns');
@@ -181,7 +181,7 @@ class CRM_Event_Import_Form_MapField extends CRM_Import_Form_MapField {
             $jsSet = TRUE;
           }
           else {
-            $defaults["mapper[$i]"] = array();
+            $defaults["mapper[$i]"] = [];
           }
           if (!$jsSet) {
             for ($k = 1; $k < 4; $k++) {
@@ -276,12 +276,12 @@ class CRM_Event_Import_Form_MapField extends CRM_Import_Form_MapField {
    *   list of errors to be posted back to the form
    */
   public static function formRule($fields, $files, $self) {
-    $errors = array();
+    $errors = [];
     // define so we avoid notices below
     $errors['_qf_default'] = '';
     $fieldMessage = NULL;
     if (!array_key_exists('savedMapping', $fields)) {
-      $importKeys = array();
+      $importKeys = [];
       foreach ($fields['mapper'] as $mapperPart) {
         $importKeys[] = $mapperPart[0];
       }
@@ -392,10 +392,10 @@ class CRM_Event_Import_Form_MapField extends CRM_Import_Form_MapField {
     $seperator = $this->controller->exportValue('DataSource', 'fieldSeparator');
     $skipColumnHeader = $this->controller->exportValue('DataSource', 'skipColumnHeader');
 
-    $mapperKeys = array();
-    $mapper = array();
+    $mapperKeys = [];
+    $mapper = [];
     $mapperKeys = $this->controller->exportValue($this->_name, 'mapper');
-    $mapperKeysMain = array();
+    $mapperKeysMain = [];
 
     for ($i = 0; $i < $this->_columnCount; $i++) {
       $mapper[$i] = $this->_mapperFields[$mapperKeys[$i][0]];
@@ -414,7 +414,7 @@ class CRM_Event_Import_Form_MapField extends CRM_Import_Form_MapField {
       $mappingFields->mapping_id = $params['mappingId'];
       $mappingFields->find();
 
-      $mappingFieldsId = array();
+      $mappingFieldsId = [];
       while ($mappingFields->fetch()) {
         if ($mappingFields->id) {
           $mappingFieldsId[$mappingFields->column_number] = $mappingFields->id;
diff --git a/civicrm/CRM/Event/Page/DashBoard.php b/civicrm/CRM/Event/Page/DashBoard.php
index f92fc7a090..9f86809e13 100644
--- a/civicrm/CRM/Event/Page/DashBoard.php
+++ b/civicrm/CRM/Event/Page/DashBoard.php
@@ -9,14 +9,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 /**
  * This is page is for Event Dashboard
  */
@@ -32,8 +24,7 @@ class CRM_Event_Page_DashBoard extends CRM_Core_Page {
     CRM_Utils_System::setTitle(ts('CiviEvent'));
 
     $eventSummary = CRM_Event_BAO_Event::getEventSummary();
-    $enableCart = Civi::settings()->get('enable_cart');
-    $eventSummary['tab'] = CRM_Event_Page_ManageEvent::tabs($enableCart);
+    $eventSummary['tab'] = CRM_Event_Page_ManageEvent::tabs();
 
     $actionColumn = FALSE;
     if (!empty($eventSummary) &&
@@ -50,6 +41,7 @@ class CRM_Event_Page_DashBoard extends CRM_Core_Page {
 
     $this->assign('actionColumn', $actionColumn);
     $this->assign('eventSummary', $eventSummary);
+    $this->assign('iCal', CRM_Event_BAO_Event::getICalLinks());
   }
 
   /**
diff --git a/civicrm/CRM/Event/Page/EventInfo.php b/civicrm/CRM/Event/Page/EventInfo.php
index c07681da8b..265b3f5dfe 100644
--- a/civicrm/CRM/Event/Page/EventInfo.php
+++ b/civicrm/CRM/Event/Page/EventInfo.php
@@ -46,6 +46,8 @@ class CRM_Event_Page_EventInfo extends CRM_Core_Page {
     $context = CRM_Utils_Request::retrieve('context', 'Alphanumeric', $this, FALSE, 'register');
     $this->assign('context', $context);
 
+    $this->assign('iCal', CRM_Event_BAO_Event::getICalLinks($this->_id));
+
     // Sometimes we want to suppress the Event Full msg
     $noFullMsg = CRM_Utils_Request::retrieve('noFullMsg', 'String', $this, FALSE, 'false');
 
@@ -126,7 +128,7 @@ class CRM_Event_Page_EventInfo extends CRM_Core_Page {
             }
             // show tax rate with amount
             $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-            $taxTerm = $invoiceSettings['tax_term'] ?? NULL;
+            $taxTerm = Civi::settings()->get('tax_term');
             $displayOpt = $invoiceSettings['tax_display_settings'] ?? NULL;
             $invoicing = $invoiceSettings['invoicing'] ?? NULL;
             foreach ($fieldValues['options'] as $optionId => $optionVal) {
@@ -339,8 +341,7 @@ class CRM_Event_Page_EventInfo extends CRM_Core_Page {
     $this->assign('location', $values['location']);
 
     if (CRM_Core_Permission::check(['access CiviEvent', 'edit all events'])) {
-      $enableCart = Civi::settings()->get('enable_cart');
-      $this->assign('manageEventLinks', CRM_Event_Page_ManageEvent::tabs($enableCart));
+      $this->assign('manageEventLinks', CRM_Event_Page_ManageEvent::tabs());
     }
 
     return parent::run();
diff --git a/civicrm/CRM/Event/Page/ManageEvent.php b/civicrm/CRM/Event/Page/ManageEvent.php
index 20b4ed5e86..bc7badd236 100644
--- a/civicrm/CRM/Event/Page/ManageEvent.php
+++ b/civicrm/CRM/Event/Page/ManageEvent.php
@@ -130,7 +130,8 @@ class CRM_Event_Page_ManageEvent extends CRM_Core_Page {
    * @return array
    *   (reference) of tab links
    */
-  public static function &tabs($enableCart) {
+  public static function &tabs() {
+    $enableCart = Civi::settings()->get('enable_cart');
     $cacheKey = $enableCart ? 1 : 0;
     if (!(self::$_tabLinks)) {
       self::$_tabLinks = [];
@@ -224,6 +225,7 @@ class CRM_Event_Page_ManageEvent extends CRM_Core_Page {
 
     // assign vars to templates
     $this->assign('action', $action);
+    $this->assign('iCal', CRM_Event_BAO_Event::getICalLinks());
     $id = CRM_Utils_Request::retrieve('id', 'Positive',
       $this, FALSE, 0, 'REQUEST'
     );
diff --git a/civicrm/CRM/Event/StateMachine/Registration.php b/civicrm/CRM/Event/StateMachine/Registration.php
index b86e7baf20..e70a4bc8ef 100644
--- a/civicrm/CRM/Event/StateMachine/Registration.php
+++ b/civicrm/CRM/Event/StateMachine/Registration.php
@@ -9,17 +9,8 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 /**
  * State machine for managing different states of the EventWizard process.
- *
  */
 class CRM_Event_StateMachine_Registration extends CRM_Core_StateMachine {
 
@@ -27,9 +18,9 @@ class CRM_Event_StateMachine_Registration extends CRM_Core_StateMachine {
    * Class constructor.
    *
    * @param object $controller
-   * @param \const|int $action
+   * @param int $action
    *
-   * @return \CRM_Event_StateMachine_Registration CRM_Event_StateMachine
+   * @throws \CRM_Core_Exception
    */
   public function __construct($controller, $action = CRM_Core_Action::NONE) {
     parent::__construct($controller, $action);
diff --git a/civicrm/CRM/Event/StateMachine/Search.php b/civicrm/CRM/Event/StateMachine/Search.php
index f98de49db6..f235ac4026 100644
--- a/civicrm/CRM/Event/StateMachine/Search.php
+++ b/civicrm/CRM/Event/StateMachine/Search.php
@@ -10,11 +10,7 @@
  */
 
 /**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * Class CRM_Event_StateMachine_Search
  */
 class CRM_Event_StateMachine_Search extends CRM_Core_StateMachine {
 
@@ -28,7 +24,7 @@ class CRM_Event_StateMachine_Search extends CRM_Core_StateMachine {
   /**
    * Class constructor.
    *
-   * @param object $controller
+   * @param CRM_Core_Controller $controller
    * @param int $action
    */
   public function __construct($controller, $action = CRM_Core_Action::NONE) {
diff --git a/civicrm/CRM/Event/xml/Menu/Event.xml b/civicrm/CRM/Event/xml/Menu/Event.xml
index 9bf47c9d1a..fda18a1b92 100644
--- a/civicrm/CRM/Event/xml/Menu/Event.xml
+++ b/civicrm/CRM/Event/xml/Menu/Event.xml
@@ -72,7 +72,6 @@
      <desc>Create and edit event configuration including times, locations, online registration forms, and fees. Links for iCal and RSS syndication.</desc>
      <access_arguments>access CiviCRM,access CiviEvent</access_arguments>
      <adminGroup>CiviEvent</adminGroup>
-     <icon>admin/small/event_manage.png</icon>
      <weight>370</weight>
   </item>
   <item>
@@ -82,7 +81,6 @@
      <desc>Administrators can create Event Templates - which are basically master event records pre-filled with default values</desc>
      <access_arguments>access CiviEvent</access_arguments>
      <adminGroup>CiviEvent</adminGroup>
-     <icon>admin/small/template.png</icon>
      <weight>375</weight>
   </item>
   <item>
@@ -92,7 +90,6 @@
      <desc>Use Event Types to categorize your events. Event feeds can be filtered by Event Type and participant searches can use Event Type as a criteria.</desc>
      <access_arguments>administer CiviCRM,access CiviEvent</access_arguments>
      <adminGroup>CiviEvent</adminGroup>
-     <icon>admin/small/event_type.png</icon>
      <weight>385</weight>
   </item>
   <item>
@@ -102,7 +99,6 @@
      <desc>Define statuses for event participants here (e.g. Registered, Attended, Cancelled...). You can then assign statuses and search for participants by status.</desc>
      <access_arguments>administer CiviCRM,access CiviEvent</access_arguments>
      <adminGroup>CiviEvent</adminGroup>
-     <icon>admin/small/parti_status.png</icon>
      <weight>390</weight>
   </item>
   <item>
@@ -112,7 +108,6 @@
      <desc>Define participant roles for events here (e.g. Attendee, Host, Speaker...). You can then assign roles and search for participants by role.</desc>
      <access_arguments>administer CiviCRM,access CiviEvent</access_arguments>
      <adminGroup>CiviEvent</adminGroup>
-     <icon>admin/small/parti_role.png</icon>
      <weight>395</weight>
   </item>
   <item>
@@ -121,7 +116,6 @@
      <desc>Template to control participant listing display.</desc>
      <page_callback>CRM_Admin_Page_Options</page_callback>
      <adminGroup>CiviEvent</adminGroup>
-     <icon>admin/small/01.png</icon>
      <weight>398</weight>
   </item>
   <item>
diff --git a/civicrm/CRM/Event/xml/Menu/PCP.xml b/civicrm/CRM/Event/xml/Menu/PCP.xml
index d64ccb5d0a..3b4012f7c6 100644
--- a/civicrm/CRM/Event/xml/Menu/PCP.xml
+++ b/civicrm/CRM/Event/xml/Menu/PCP.xml
@@ -7,7 +7,6 @@
      <path_arguments>context=event</path_arguments>
      <desc>View and manage existing personal campaign pages.</desc>
      <adminGroup>CiviEvent</adminGroup>
-     <icon>admin/small/contribution_types.png</icon>
      <weight>362</weight>
   </item>
   <item>
diff --git a/civicrm/CRM/Extension/Browser.php b/civicrm/CRM/Extension/Browser.php
index 89994cb00e..ff173a54a3 100644
--- a/civicrm/CRM/Extension/Browser.php
+++ b/civicrm/CRM/Extension/Browser.php
@@ -94,10 +94,10 @@ class CRM_Extension_Browser {
    */
   public function checkRequirements() {
     if (!$this->isEnabled()) {
-      return array();
+      return [];
     }
 
-    $errors = array();
+    $errors = [];
 
     if (!$this->cacheDir || !is_dir($this->cacheDir) || !is_writable($this->cacheDir)) {
       $civicrmDestination = urlencode(CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1'));
@@ -124,10 +124,10 @@ class CRM_Extension_Browser {
    */
   public function getExtensions() {
     if (!$this->isEnabled() || count($this->checkRequirements())) {
-      return array();
+      return [];
     }
 
-    $exts = array();
+    $exts = [];
 
     $remote = $this->_discoverRemote();
     if (is_array($remote)) {
@@ -180,7 +180,7 @@ class CRM_Extension_Browser {
       $remotes = json_decode($this->grabCachedJson(), TRUE);
     }
 
-    $this->_remotesDiscovered = array();
+    $this->_remotesDiscovered = [];
     foreach ((array) $remotes as $id => $xml) {
       $ext = CRM_Extension_Info::loadFromString($xml);
       $this->_remotesDiscovered[] = $ext;
@@ -230,7 +230,7 @@ class CRM_Extension_Browser {
     if (FALSE === $this->getRepositoryUrl()) {
       // don't check if the user has configured civi not to check an external
       // url for extensions. See CRM-10575.
-      return array();
+      return [];
     }
 
     $filename = $this->cacheDir . DIRECTORY_SEPARATOR . self::CACHE_JSON_FILE . '.' . md5($this->getRepositoryUrl());
diff --git a/civicrm/CRM/Extension/ClassLoader.php b/civicrm/CRM/Extension/ClassLoader.php
index 9ce09a4492..2e181a8877 100644
--- a/civicrm/CRM/Extension/ClassLoader.php
+++ b/civicrm/CRM/Extension/ClassLoader.php
@@ -10,12 +10,7 @@
  */
 
 /**
- *
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * Class CRM_Extension_ClassLoader
  */
 class CRM_Extension_ClassLoader {
 
diff --git a/civicrm/CRM/Extension/Container/Default.php b/civicrm/CRM/Extension/Container/Default.php
index 04796ad933..f5a6c4ce3c 100644
--- a/civicrm/CRM/Extension/Container/Default.php
+++ b/civicrm/CRM/Extension/Container/Default.php
@@ -26,7 +26,7 @@ class CRM_Extension_Container_Default extends CRM_Extension_Container_Basic {
    * @return array
    */
   public function checkRequirements() {
-    $errors = array();
+    $errors = [];
 
     // In current configuration, we don't construct the default container
     // unless baseDir is set, so this error condition is more theoretical.
diff --git a/civicrm/CRM/Extension/Downloader.php b/civicrm/CRM/Extension/Downloader.php
index cc43c8be6e..a76ca105e1 100644
--- a/civicrm/CRM/Extension/Downloader.php
+++ b/civicrm/CRM/Extension/Downloader.php
@@ -49,7 +49,7 @@ class CRM_Extension_Downloader {
    *   list of error messages; empty if OK
    */
   public function checkRequirements($extensionInfo = NULL) {
-    $errors = array();
+    $errors = [];
 
     if (!$this->containerDir || !is_dir($this->containerDir) || !is_writable($this->containerDir)) {
       $civicrmDestination = urlencode(CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1'));
diff --git a/civicrm/CRM/Financial/BAO/FinancialItem.php b/civicrm/CRM/Financial/BAO/FinancialItem.php
index 60c6332f6c..317fb8dadb 100644
--- a/civicrm/CRM/Financial/BAO/FinancialItem.php
+++ b/civicrm/CRM/Financial/BAO/FinancialItem.php
@@ -85,10 +85,8 @@ class CRM_Financial_BAO_FinancialItem extends CRM_Financial_DAO_FinancialItem {
     ];
 
     if ($taxTrxnID) {
-      $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-      $taxTerm = $invoiceSettings['tax_term'] ?? NULL;
       $params['amount'] = $lineItem->tax_amount;
-      $params['description'] = $taxTerm;
+      $params['description'] = Civi::settings()->get('tax_term');
       $accountRelName = 'Sales Tax Account is';
     }
     else {
diff --git a/civicrm/CRM/Financial/BAO/Payment.php b/civicrm/CRM/Financial/BAO/Payment.php
index 8a06f7f26c..05de84f0b7 100644
--- a/civicrm/CRM/Financial/BAO/Payment.php
+++ b/civicrm/CRM/Financial/BAO/Payment.php
@@ -42,7 +42,7 @@ class CRM_Financial_BAO_Payment {
     $isPaymentCompletesContribution = self::isPaymentCompletesContribution($params['contribution_id'], $params['total_amount'], $contributionStatus);
     $lineItems = self::getPayableLineItems($params);
 
-    $whiteList = ['check_number', 'payment_processor_id', 'fee_amount', 'total_amount', 'contribution_id', 'net_amount', 'card_type_id', 'pan_truncation', 'trxn_result_code', 'payment_instrument_id', 'trxn_id', 'trxn_date'];
+    $whiteList = ['check_number', 'payment_processor_id', 'fee_amount', 'total_amount', 'contribution_id', 'net_amount', 'card_type_id', 'pan_truncation', 'trxn_result_code', 'payment_instrument_id', 'trxn_id', 'trxn_date', 'order_reference'];
     $paymentTrxnParams = array_intersect_key($params, array_fill_keys($whiteList, 1));
     $paymentTrxnParams['is_payment'] = 1;
     // Really we should have a DB default.
@@ -163,10 +163,41 @@ class CRM_Financial_BAO_Payment {
       //  change status to refunded.
       self::updateContributionStatus($contribution['id'], 'Refunded');
     }
+    self::updateRelatedContribution($params, $params['contribution_id']);
     CRM_Contribute_BAO_Contribution::recordPaymentActivity($params['contribution_id'], CRM_Utils_Array::value('participant_id', $params), $params['total_amount'], $trxn->currency, $trxn->trxn_date);
     return $trxn;
   }
 
+  /**
+   * Function to update contribution's check_number and trxn_id by
+   *  concatenating values from financial trxn's check_number and trxn_id respectively
+   *
+   * @param array $params
+   * @param int $contributionID
+   */
+  public static function updateRelatedContribution($params, $contributionID) {
+    $contributionDAO = new CRM_Contribute_DAO_Contribution();
+    $contributionDAO->id = $contributionID;
+    $contributionDAO->find(TRUE);
+
+    foreach (['trxn_id', 'check_number'] as $fieldName) {
+      if (!empty($params[$fieldName])) {
+        $values = [];
+        if (!empty($contributionDAO->$fieldName)) {
+          $values = explode(',', $contributionDAO->$fieldName);
+        }
+        // if submitted check_number or trxn_id value is
+        //   already present then ignore else add to $values array
+        if (!in_array($params[$fieldName], $values)) {
+          $values[] = $params[$fieldName];
+        }
+        $contributionDAO->$fieldName = implode(',', $values);
+      }
+    }
+
+    $contributionDAO->save();
+  }
+
   /**
    * Send an email confirming a payment that has been received.
    *
diff --git a/civicrm/CRM/Financial/Form/PaymentEdit.php b/civicrm/CRM/Financial/Form/PaymentEdit.php
index f131ef7677..b40f1325a3 100644
--- a/civicrm/CRM/Financial/Form/PaymentEdit.php
+++ b/civicrm/CRM/Financial/Form/PaymentEdit.php
@@ -214,7 +214,7 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form {
       civicrm_api3('FinancialTrxn', 'create', $submittedValues);
     }
 
-    self::updateRelatedContribution($submittedValues, $this->_contributionID);
+    CRM_Financial_BAO_Payment::updateRelatedContribution($submittedValues, $this->_contributionID);
   }
 
   /**
@@ -230,35 +230,6 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form {
     $this->submit($params);
   }
 
-  /**
-   * Function to update contribution's check_number and trxn_id by
-   *  concatenating values from financial trxn's check_number and trxn_id respectively
-   *
-   * @param array $params
-   * @param int $contributionID
-   */
-  public static function updateRelatedContribution($params, $contributionID) {
-    $contributionDAO = new CRM_Contribute_DAO_Contribution();
-    $contributionDAO->id = $contributionID;
-    $contributionDAO->find(TRUE);
-
-    foreach (['trxn_id', 'check_number'] as $fieldName) {
-      if (!empty($params[$fieldName])) {
-        if (!empty($contributionDAO->$fieldName)) {
-          $values = explode(',', $contributionDAO->$fieldName);
-          // if submitted check_number or trxn_id value is
-          //   already present then ignore else add to $values array
-          if (!in_array($params[$fieldName], $values)) {
-            $values[] = $params[$fieldName];
-          }
-          $contributionDAO->$fieldName = implode(',', $values);
-        }
-      }
-    }
-
-    $contributionDAO->save();
-  }
-
   /**
    * Get payment fields
    */
diff --git a/civicrm/CRM/Financial/Form/SalesTaxTrait.php b/civicrm/CRM/Financial/Form/SalesTaxTrait.php
index 45710bd064..3ea4d0183c 100644
--- a/civicrm/CRM/Financial/Form/SalesTaxTrait.php
+++ b/civicrm/CRM/Financial/Form/SalesTaxTrait.php
@@ -36,12 +36,10 @@ trait CRM_Financial_Form_SalesTaxTrait {
    * @return string
    */
   public function getSalesTaxTerm() {
-    $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-    $invoicing = $invoiceSettings['invoicing'] ?? NULL;
-    if (!$invoicing) {
+    if (!Civi::settings()->get('invoicing')) {
       return '';
     }
-    return $invoiceSettings['tax_term'] ?? NULL;
+    return Civi::settings()->get('tax_term');
   }
 
   /**
diff --git a/civicrm/CRM/Grant/BAO/Grant.php b/civicrm/CRM/Grant/BAO/Grant.php
index 3d5fa8e1ac..c314802a2b 100644
--- a/civicrm/CRM/Grant/BAO/Grant.php
+++ b/civicrm/CRM/Grant/BAO/Grant.php
@@ -10,11 +10,7 @@
  */
 
 /**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * Class CRM_Grant_BAO_Grant
  */
 class CRM_Grant_BAO_Grant extends CRM_Grant_DAO_Grant {
 
@@ -113,21 +109,14 @@ class CRM_Grant_BAO_Grant extends CRM_Grant_DAO_Grant {
    * Add grant.
    *
    * @param array $params
-   *   Reference array contains the values submitted by the form.
    * @param array $ids
-   *   Reference array contains the id.
-   *
    *
    * @return object
    */
-  public static function add(&$params, &$ids) {
-
-    if (!empty($ids['grant_id'])) {
-      CRM_Utils_Hook::pre('edit', 'Grant', $ids['grant_id'], $params);
-    }
-    else {
-      CRM_Utils_Hook::pre('create', 'Grant', NULL, $params);
-    }
+  public static function add($params, $ids = []) {
+    $id = $ids['grant_id'] ?? $params['id'] ?? NULL;
+    $hook = $id ? 'edit' : 'create';
+    CRM_Utils_Hook::pre($hook, 'Grant', $id, $params);
 
     // first clean up all the money fields
     $moneyFields = [
@@ -154,7 +143,7 @@ class CRM_Grant_BAO_Grant extends CRM_Grant_DAO_Grant {
       }
     }
     $grant = new CRM_Grant_DAO_Grant();
-    $grant->id = $ids['grant_id'] ?? NULL;
+    $grant->id = $id;
 
     $grant->copyValues($params);
 
@@ -200,27 +189,20 @@ class CRM_Grant_BAO_Grant extends CRM_Grant_DAO_Grant {
       );
     }
 
-    if (!empty($ids['grant'])) {
-      CRM_Utils_Hook::post('edit', 'Grant', $grant->id, $grant);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'Grant', $grant->id, $grant);
-    }
+    CRM_Utils_Hook::post($hook, 'Grant', $grant->id, $grant);
 
     return $result;
   }
 
   /**
-   * Create the event.
+   * Adds a grant.
    *
    * @param array $params
-   *   Reference array contains the values submitted by the form.
    * @param array $ids
-   *   Reference array contains the id.
    *
    * @return object
    */
-  public static function create(&$params, &$ids) {
+  public static function create($params, $ids = []) {
     $transaction = new CRM_Core_Transaction();
 
     $grant = self::add($params, $ids);
diff --git a/civicrm/CRM/Grant/BAO/Query.php b/civicrm/CRM/Grant/BAO/Query.php
index 5efbb3b1ff..d91699ca81 100644
--- a/civicrm/CRM/Grant/BAO/Query.php
+++ b/civicrm/CRM/Grant/BAO/Query.php
@@ -10,11 +10,7 @@
  */
 
 /**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * Class CRM_Grant_BAO_Query
  */
 class CRM_Grant_BAO_Query extends CRM_Core_BAO_Query {
 
diff --git a/civicrm/CRM/Grant/Form/Grant.php b/civicrm/CRM/Grant/Form/Grant.php
index 7f81aceb68..80d4f97b8d 100644
--- a/civicrm/CRM/Grant/Form/Grant.php
+++ b/civicrm/CRM/Grant/Form/Grant.php
@@ -9,14 +9,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 /**
  * This class generates form components for processing a case
  *
diff --git a/civicrm/CRM/Grant/Form/Task.php b/civicrm/CRM/Grant/Form/Task.php
index 561bd0bfc9..b983cec3d7 100644
--- a/civicrm/CRM/Grant/Form/Task.php
+++ b/civicrm/CRM/Grant/Form/Task.php
@@ -9,14 +9,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 /**
  * Class for grant form task actions.
  * FIXME: This needs refactoring to properly inherit from CRM_Core_Form_Task and share more functions.
diff --git a/civicrm/CRM/Group/Form/Edit.php b/civicrm/CRM/Group/Form/Edit.php
index fa3135f426..d0e6ac595d 100644
--- a/civicrm/CRM/Group/Form/Edit.php
+++ b/civicrm/CRM/Group/Form/Edit.php
@@ -102,7 +102,7 @@ class CRM_Group_Form_Edit extends CRM_Core_Form {
       );
       CRM_Utils_System::appendBreadCrumb($breadCrumb);
 
-      $this->_groupValues = array();
+      $this->_groupValues = [];
       $params = array('id' => $this->_id);
       $this->_group = CRM_Contact_BAO_Group::retrieve($params, $this->_groupValues);
       $this->_title = $this->_groupValues['title'];
@@ -172,14 +172,14 @@ class CRM_Group_Form_Edit extends CRM_Core_Form {
    * @return array
    */
   public function setDefaultValues() {
-    $defaults = array();
+    $defaults = [];
     if (isset($this->_id)) {
       $defaults = $this->_groupValues;
       if (!empty($defaults['group_type'])) {
         $types = explode(CRM_Core_DAO::VALUE_SEPARATOR,
           substr($defaults['group_type'], 1, -1)
         );
-        $defaults['group_type'] = array();
+        $defaults['group_type'] = [];
         foreach ($types as $type) {
           $defaults['group_type'][$type] = 1;
         }
@@ -286,7 +286,7 @@ class CRM_Group_Form_Edit extends CRM_Core_Form {
    *   list of errors to be posted back to the form
    */
   public static function formRule($fields, $fileParams, $options) {
-    $errors = array();
+    $errors = [];
 
     $doParentCheck = $options['doParentCheck'];
     $self = &$options['selfObj'];
@@ -360,7 +360,7 @@ WHERE  title = %1
 
       // CRM-21431 If all group_type are unchecked, the change will not be saved otherwise.
       if (!isset($params['group_type'])) {
-        $params['group_type'] = array();
+        $params['group_type'] = [];
       }
 
       $params['is_reserved'] = CRM_Utils_Array::value('is_reserved', $params, FALSE);
@@ -411,7 +411,7 @@ WHERE  title = %1
    */
   public static function buildParentGroups(&$form) {
     $groupNames = CRM_Core_PseudoConstant::group();
-    $parentGroups = $parentGroupElements = array();
+    $parentGroups = $parentGroupElements = [];
     if (isset($form->_id) && !empty($form->_groupValues['parents'])) {
       $parentGroupIds = explode(',', $form->_groupValues['parents']);
       foreach ($parentGroupIds as $parentGroupId) {
@@ -433,7 +433,7 @@ WHERE  title = %1
       $potentialParentGroupIds = array_keys($groupNames);
     }
 
-    $parentGroupSelectValues = array();
+    $parentGroupSelectValues = [];
     foreach ($potentialParentGroupIds as $potentialParentGroupId) {
       if (array_key_exists($potentialParentGroupId, $groupNames)) {
         $parentGroupSelectValues[$potentialParentGroupId] = $groupNames[$potentialParentGroupId];
diff --git a/civicrm/CRM/Import/Form/Preview.php b/civicrm/CRM/Import/Form/Preview.php
index 3d01c5a300..5067a22c48 100644
--- a/civicrm/CRM/Import/Form/Preview.php
+++ b/civicrm/CRM/Import/Form/Preview.php
@@ -36,21 +36,37 @@ abstract class CRM_Import_Form_Preview extends CRM_Core_Form {
    * Build the form object.
    */
   public function buildQuickForm() {
+
+    // FIXME: This is a hack...
+    // The tpl contains javascript that starts the import on form submit
+    // Since our back/cancel buttons are of html type "submit" we have to prevent a form submit event when they are clicked
+    // Hacking in some onclick js to make them act more like links instead of buttons
+    $path = CRM_Utils_System::currentPath();
+    $query = ['_qf_MapField_display' => 'true'];
+    $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String');
+    if (CRM_Utils_Rule::qfKey($qfKey)) {
+      $query['qfKey'] = $qfKey;
+    }
+    $previousURL = CRM_Utils_System::url($path, $query, FALSE, NULL, FALSE);
+    $cancelURL = CRM_Utils_System::url($path, 'reset=1', FALSE, NULL, FALSE);
+
     $this->addButtons([
-        [
-          'type' => 'back',
-          'name' => ts('Previous'),
-        ],
-        [
-          'type' => 'next',
-          'name' => ts('Import Now'),
-          'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
-          'isDefault' => TRUE,
-        ],
-        [
-          'type' => 'cancel',
-          'name' => ts('Cancel'),
-        ],
+      [
+        'type' => 'back',
+        'name' => ts('Previous'),
+        'js' => ['onclick' => "location.href='{$previousURL}'; return false;"],
+      ],
+      [
+        'type' => 'next',
+        'name' => ts('Import Now'),
+        'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
+        'isDefault' => TRUE,
+      ],
+      [
+        'type' => 'cancel',
+        'name' => ts('Cancel'),
+        'js' => ['onclick' => "location.href='{$cancelURL}'; return false;"],
+      ],
     ]);
   }
 
diff --git a/civicrm/CRM/Invoicing/Utils.php b/civicrm/CRM/Invoicing/Utils.php
index dbcc4befac..24fe4078e7 100644
--- a/civicrm/CRM/Invoicing/Utils.php
+++ b/civicrm/CRM/Invoicing/Utils.php
@@ -69,8 +69,7 @@ class CRM_Invoicing_Utils {
    * is unsupported. Here we have a wrapper function to make later cleanup easier.
    */
   public static function getTaxTerm() {
-    $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-    return $invoiceSettings['tax_term'] ?? NULL;
+    return Civi::settings()->get('tax_term');
   }
 
 }
diff --git a/civicrm/CRM/Logging/Schema.php b/civicrm/CRM/Logging/Schema.php
index 5d4ae83f83..183af4100a 100644
--- a/civicrm/CRM/Logging/Schema.php
+++ b/civicrm/CRM/Logging/Schema.php
@@ -142,6 +142,9 @@ AND    TABLE_NAME LIKE 'civicrm_%'
     // do not log civicrm_mailing_event* tables, CRM-12300
     $this->tables = preg_grep('/^civicrm_mailing_event_/', $this->tables, PREG_GREP_INVERT);
 
+    // dev/core#1762 Don't log subscription_history
+    $this->tables = preg_grep('/^civicrm_subscription_history/', $this->tables, PREG_GREP_INVERT);
+
     // do not log civicrm_mailing_recipients table, CRM-16193
     $this->tables = array_diff($this->tables, ['civicrm_mailing_recipients']);
     $this->logTableSpec = array_fill_keys($this->tables, []);
diff --git a/civicrm/CRM/Mailing/BAO/Mailing.php b/civicrm/CRM/Mailing/BAO/Mailing.php
index 46ee694de3..8169513e89 100644
--- a/civicrm/CRM/Mailing/BAO/Mailing.php
+++ b/civicrm/CRM/Mailing/BAO/Mailing.php
@@ -690,6 +690,7 @@ class CRM_Mailing_BAO_Mailing extends CRM_Mailing_DAO_Mailing {
       }
 
       $this->templates['mailingID'] = $this->id;
+      $this->templates['campaign_id'] = $this->campaign_id;
       $this->templates['template_type'] = $this->template_type;
       CRM_Utils_Hook::alterMailContent($this->templates);
     }
@@ -1558,8 +1559,8 @@ ORDER BY   civicrm_email.is_bulkmail DESC
         // correct template IDs here
         'override_verp' => TRUE,
         'forward_replies' => FALSE,
-        'open_tracking' => TRUE,
-        'url_tracking' => TRUE,
+        'open_tracking' => Civi::settings()->get('open_tracking_default'),
+        'url_tracking' => Civi::settings()->get('url_tracking_default'),
         'visibility' => 'Public Pages',
         'replyto_email' => $domain_email,
         'header_id' => CRM_Mailing_PseudoConstant::defaultComponent('header_id', ''),
diff --git a/civicrm/CRM/Mailing/BAO/MailingAB.php b/civicrm/CRM/Mailing/BAO/MailingAB.php
index 02b305e499..7d26a2c100 100644
--- a/civicrm/CRM/Mailing/BAO/MailingAB.php
+++ b/civicrm/CRM/Mailing/BAO/MailingAB.php
@@ -34,15 +34,13 @@ class CRM_Mailing_BAO_MailingAB extends CRM_Mailing_DAO_MailingAB {
    *   Form values.
    *
    * @param array $params
-   * @param array $ids
    *
-   * @return object
-   *   $mailingab      The new mailingab object
+   * @return CRM_Mailing_DAO_MailingAB
    */
-  public static function create(&$params, $ids = []) {
+  public static function create(&$params) {
     $transaction = new CRM_Core_Transaction();
 
-    $mailingab = self::add($params, $ids);
+    $mailingab = self::writeRecord($params);
 
     if (is_a($mailingab, 'CRM_Core_Error')) {
       $transaction->rollback();
@@ -52,47 +50,6 @@ class CRM_Mailing_BAO_MailingAB extends CRM_Mailing_DAO_MailingAB {
     return $mailingab;
   }
 
-  /**
-   * function to add the mailings.
-   *
-   * @param array $params
-   *   Reference array contains the values submitted by the form.
-   * @param array $ids
-   *   Reference array contains the id.
-   *
-   *
-   * @return object
-   */
-  public static function add(&$params, $ids = []) {
-    $id = CRM_Utils_Array::value('mailingab_id', $ids, CRM_Utils_Array::value('id', $params));
-
-    if ($id) {
-      CRM_Utils_Hook::pre('edit', 'MailingAB', $id, $params);
-    }
-    else {
-      CRM_Utils_Hook::pre('create', 'MailingAB', NULL, $params);
-    }
-
-    $mailingab = new CRM_Mailing_DAO_MailingAB();
-    $mailingab->id = $id;
-    if (!$id) {
-      $mailingab->domain_id = CRM_Utils_Array::value('domain_id', $params, CRM_Core_Config::domainID());
-    }
-
-    $mailingab->copyValues($params);
-
-    $result = $mailingab->save();
-
-    if ($id) {
-      CRM_Utils_Hook::post('edit', 'MailingAB', $mailingab->id, $mailingab);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'MailingAB', $mailingab->id, $mailingab);
-    }
-
-    return $result;
-  }
-
   /**
    * Delete MailingAB and all its associated records.
    *
diff --git a/civicrm/CRM/Mailing/BAO/Query.php b/civicrm/CRM/Mailing/BAO/Query.php
index f734f1cd12..b9d58a99fc 100644
--- a/civicrm/CRM/Mailing/BAO/Query.php
+++ b/civicrm/CRM/Mailing/BAO/Query.php
@@ -122,7 +122,7 @@ class CRM_Mailing_BAO_Query {
    * rather than a static function.
    */
   public static function getSearchFieldMetadata() {
-    $fields = ['mailing_job_start_date'];
+    $fields = ['mailing_job_start_date', 'is_archived'];
     $metadata = civicrm_api3('Mailing', 'getfields', [])['values'];
     $metadata = array_merge($metadata, civicrm_api3('MailingJob', 'getfields', [])['values']);
     return array_intersect_key($metadata, array_flip($fields));
diff --git a/civicrm/CRM/Mailing/BAO/TrackableURL.php b/civicrm/CRM/Mailing/BAO/TrackableURL.php
index 86650e3afe..0113e53bb9 100644
--- a/civicrm/CRM/Mailing/BAO/TrackableURL.php
+++ b/civicrm/CRM/Mailing/BAO/TrackableURL.php
@@ -76,7 +76,9 @@ class CRM_Mailing_BAO_TrackableURL extends CRM_Mailing_DAO_TrackableURL {
       $urlCache[$mailing_id . $url] = $redirect;
     }
 
-    $returnUrl = CRM_Utils_System::externUrl('extern/url', "u=$id&qid=$queue_id");
+    // This looks silly - calling the hook twice. This smells like an accident. Restoring old cache-based lookup.
+    // $returnUrl = CRM_Utils_System::externUrl('extern/url', "u=$id&qid=$queue_id");
+    $returnUrl = "{$urlCache[$mailing_id . $url]}&qid={$queue_id}";
 
     if ($hrefExists) {
       $returnUrl = "href='{$returnUrl}' rel='nofollow'";
diff --git a/civicrm/CRM/Mailing/DAO/MailingAB.php b/civicrm/CRM/Mailing/DAO/MailingAB.php
index 64aec05fb1..37fa94d1b9 100644
--- a/civicrm/CRM/Mailing/DAO/MailingAB.php
+++ b/civicrm/CRM/Mailing/DAO/MailingAB.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Mailing/MailingAB.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:74ff2df50144a54a2c5a740187f6a8ca)
+ * (GenCodeChecksum:808ef560b5f6c959cb4f3ceea87f5e38)
  */
 
 /**
@@ -227,6 +227,7 @@ class CRM_Mailing_DAO_MailingAB extends CRM_Core_DAO {
           'type' => CRM_Utils_Type::T_INT,
           'title' => ts('Domain ID'),
           'description' => ts('Which site is this mailing for'),
+          'required' => TRUE,
           'where' => 'civicrm_mailing_abtest.domain_id',
           'table_name' => 'civicrm_mailing_abtest',
           'entity' => 'MailingAB',
diff --git a/civicrm/CRM/Mailing/Event/BAO/Bounce.php b/civicrm/CRM/Mailing/Event/BAO/Bounce.php
index f9056e6f79..57c8c3a99b 100644
--- a/civicrm/CRM/Mailing/Event/BAO/Bounce.php
+++ b/civicrm/CRM/Mailing/Event/BAO/Bounce.php
@@ -224,7 +224,7 @@ class CRM_Mailing_Event_BAO_Bounce extends CRM_Mailing_Event_DAO_Bounce {
 
     $dao->query($query);
 
-    $results = array();
+    $results = [];
 
     while ($dao->fetch()) {
       $url = CRM_Utils_System::url('civicrm/contact/view',
diff --git a/civicrm/CRM/Mailing/Form/Search.php b/civicrm/CRM/Mailing/Form/Search.php
index f2a9671723..04f321d995 100644
--- a/civicrm/CRM/Mailing/Form/Search.php
+++ b/civicrm/CRM/Mailing/Form/Search.php
@@ -29,6 +29,9 @@ class CRM_Mailing_Form_Search extends CRM_Core_Form_Search {
     parent::preProcess();
   }
 
+  /**
+   * @throws \CiviCRM_API3_Exception
+   */
   public function buildQuickForm() {
     $parent = $this->controller->getParent();
     $nameTextLabel = ($parent->_sms) ? ts('SMS Name') : ts('Mailing Name');
@@ -44,6 +47,8 @@ class CRM_Mailing_Form_Search extends CRM_Core_Form_Search {
       CRM_Core_DAO::getAttribute('CRM_Contact_DAO_Contact', 'sort_name')
     );
 
+    CRM_Mailing_BAO_Query::buildSearchForm($this);
+
     CRM_Campaign_BAO_Campaign::addCampaignInComponentSearch($this);
 
     // CRM-15434 - Fix mailing search by status in non-English languages
@@ -52,7 +57,6 @@ class CRM_Mailing_Form_Search extends CRM_Core_Form_Search {
       $this->addElement('checkbox', "mailing_status[$statusId]", NULL, $statusName);
     }
     $this->addElement('checkbox', 'status_unscheduled', NULL, ts('Draft / Unscheduled'));
-    $this->addYesNo('is_archived', ts('Mailing is Archived'), TRUE);
 
     // Search by language, if multi-lingual
     $enabledLanguages = CRM_Core_I18n::languages(TRUE);
@@ -77,9 +81,11 @@ class CRM_Mailing_Form_Search extends CRM_Core_Form_Search {
 
   /**
    * @return array
+   * @throws \CRM_Core_Exception
    */
   public function setDefaultValues() {
     $defaults = $statusVals = [];
+    $entityDefaults = parent::setDefaultValues();
     $parent = $this->controller->getParent();
 
     if ($parent->get('unscheduled')) {
@@ -99,11 +105,15 @@ class CRM_Mailing_Form_Search extends CRM_Core_Form_Search {
     if ($parent->_sms) {
       $defaults['sms'] = 1;
     }
-    return $defaults;
+    return array_merge($defaults, $entityDefaults);
   }
 
+  /**
+   * @throws \CRM_Core_Exception
+   */
   public function postProcess() {
-    $params = $this->controller->exportValues($this->_name);
+    $this->setFormValues();
+    $params = $this->_formValues;
 
     if (!empty($params['mailing_relative'])) {
       list($params['mailing_low'], $params['mailing_high']) = CRM_Utils_Date::getFromTo($params['mailing_relative'], $params['mailing_low'], $params['mailing_high']);
@@ -141,4 +151,26 @@ class CRM_Mailing_Form_Search extends CRM_Core_Form_Search {
     }
   }
 
+  /**
+   * Handle force=1 in the url.
+   *
+   * Search field metadata is normally added in buildForm but we are bypassing that in this flow
+   * (I've always found the flow kinda confusing & perhaps that is the problem but this mitigates)
+   *
+   * @throws \CiviCRM_API3_Exception
+   */
+  protected function handleForcedSearch() {
+    $this->setSearchMetadata();
+    $this->addContactSearchFields();
+  }
+
+  /**
+   * Set the metadata for the form.
+   *
+   * @throws \CiviCRM_API3_Exception
+   */
+  protected function setSearchMetadata() {
+    $this->addSearchFieldMetadata(['Mailing' => CRM_Mailing_BAO_Query::getSearchFieldMetadata()]);
+  }
+
 }
diff --git a/civicrm/CRM/Mailing/Form/Unsubscribe.php b/civicrm/CRM/Mailing/Form/Unsubscribe.php
index 4f2c4f7874..95a6759659 100644
--- a/civicrm/CRM/Mailing/Form/Unsubscribe.php
+++ b/civicrm/CRM/Mailing/Form/Unsubscribe.php
@@ -16,6 +16,14 @@
  */
 class CRM_Mailing_Form_Unsubscribe extends CRM_Core_Form {
 
+  /**
+   * Prevent people double-submitting the form (e.g. by double-clicking).
+   * https://lab.civicrm.org/dev/core/-/issues/1773
+   *
+   * @var bool
+   */
+  public $submitOnce = TRUE;
+
   public function preProcess() {
 
     $this->_type = 'unsubscribe';
diff --git a/civicrm/CRM/Mailing/Page/Browse.php b/civicrm/CRM/Mailing/Page/Browse.php
index 769919e7b3..9982bd1a79 100644
--- a/civicrm/CRM/Mailing/Page/Browse.php
+++ b/civicrm/CRM/Mailing/Page/Browse.php
@@ -64,7 +64,7 @@ class CRM_Mailing_Page_Browse extends CRM_Core_Page {
   public function preProcess() {
     Civi::resources()->addStyleFile('civicrm', 'css/searchForm.css', 1, 'html-header');
 
-    $this->_unscheduled = $this->_archived = $archiveLinks = FALSE;
+    $this->_unscheduled = $archiveLinks = FALSE;
     $this->_mailingId = CRM_Utils_Request::retrieve('mid', 'Positive', $this);
     $this->_sms = CRM_Utils_Request::retrieve('sms', 'Positive', $this);
 
@@ -119,6 +119,7 @@ class CRM_Mailing_Page_Browse extends CRM_Core_Page {
     $newArgs = func_get_args();
     // since we want only first function argument
     $newArgs = $newArgs[0];
+    $this->_isArchived = $this->isArchived($newArgs);
     if (isset($_GET['runJobs']) || CRM_Utils_Array::value('2', $newArgs) == 'queue') {
       $mailerJobSize = Civi::settings()->get('mailerJobSize');
       CRM_Mailing_BAO_MailingJob::runJobs_pre($mailerJobSize);
@@ -140,10 +141,7 @@ class CRM_Mailing_Page_Browse extends CRM_Core_Page {
     }
     $this->set('unscheduled', $this->_unscheduled);
 
-    if (CRM_Utils_Array::value(3, $newArgs) == 'archived') {
-      $this->_archived = TRUE;
-    }
-    $this->set('archived', $this->_archived);
+    $this->set('archived', $this->isArchived($newArgs));
 
     if (CRM_Utils_Array::value(3, $newArgs) == 'scheduled') {
       $this->_scheduled = TRUE;
@@ -260,7 +258,8 @@ class CRM_Mailing_Page_Browse extends CRM_Core_Page {
       $urlParams .= '&scheduled=false';
       $this->assign('unscheduled', TRUE);
     }
-    elseif (CRM_Utils_Array::value(3, $newArgs) == 'archived') {
+
+    if ($this->isArchived($newArgs)) {
       $urlString .= '/archived';
       $this->assign('archived', TRUE);
     }
@@ -353,4 +352,17 @@ class CRM_Mailing_Page_Browse extends CRM_Core_Page {
     return implode(' AND ', $clauses);
   }
 
+  /**
+   * Is the search limited to archived mailings.
+   *
+   * @param array $urlArguments
+   *
+   * @return bool
+   *
+   * @throws \CRM_Core_Exception
+   */
+  protected function isArchived($urlArguments): bool {
+    return in_array('archived', $urlArguments, TRUE) || CRM_Utils_Request::retrieveValue('is_archived', 'Boolean');
+  }
+
 }
diff --git a/civicrm/CRM/Mailing/Page/Common.php b/civicrm/CRM/Mailing/Page/Common.php
index 5a39c63f3c..4bae016690 100644
--- a/civicrm/CRM/Mailing/Page/Common.php
+++ b/civicrm/CRM/Mailing/Page/Common.php
@@ -43,17 +43,13 @@ class CRM_Mailing_Page_Common extends CRM_Core_Page {
       throw new CRM_Core_Exception(ts("There was an error in your request"));
     }
 
-    $cancel = CRM_Utils_Request::retrieve("_qf_{$this->_type}_cancel", 'String', CRM_Core_DAO::$_nullObject,
-      FALSE, NULL, $_REQUEST
-    );
+    $cancel = CRM_Utils_Request::retrieve("_qf_{$this->_type}_cancel", 'String');
     if ($cancel) {
       $config = CRM_Core_Config::singleton();
       CRM_Utils_System::redirect($config->userFrameworkBaseURL);
     }
 
-    $confirm = CRM_Utils_Request::retrieve('confirm', 'Boolean', CRM_Core_DAO::$_nullObject,
-      FALSE, NULL, $_REQUEST
-    );
+    $confirm = CRM_Utils_Request::retrieve('confirm', 'Boolean');
 
     list($displayName, $email) = CRM_Mailing_Event_BAO_Queue::getContactInfo($queue_id);
     $this->assign('display_name', $displayName);
diff --git a/civicrm/CRM/Mailing/Page/Open.php b/civicrm/CRM/Mailing/Page/Open.php
new file mode 100644
index 0000000000..ac26fbfff8
--- /dev/null
+++ b/civicrm/CRM/Mailing/Page/Open.php
@@ -0,0 +1,58 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+
+/**
+ * Indicate that a CiviMail message has been opened
+ *
+ * General Usage: civicrm/mailing/open?qid={event_queue_id}
+ *
+ * NOTE: The parameter name has changed slightly from 'extern/open.php?q={event_queue_id}`.
+ */
+class CRM_Mailing_Page_Open extends CRM_Core_Page {
+
+  /**
+   * Mark the mailing as opened
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function run() {
+    $queue_id = CRM_Utils_Request::retrieveValue('qid', 'Positive', NULL, FALSE, 'GET');
+    if (!$queue_id) {
+      // Deprecated: "?q=" is problematic in Drupal integrations, but we'll accept if igiven
+      $queue_id = CRM_Utils_Request::retrieveValue('q', 'Positive', NULL, FALSE, 'GET');;
+    }
+    if (!$queue_id) {
+      echo "Missing input parameters\n";
+      exit();
+    }
+
+    CRM_Mailing_Event_BAO_Opened::open($queue_id);
+
+    $filename = Civi::paths()->getPath('[civicrm.root]/i/tracker.gif');
+
+    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+    header('Content-Description: File Transfer');
+    header('Content-type: image/gif');
+    header('Content-Length: ' . filesize($filename));
+    header('Content-Disposition: inline; filename=tracker.gif');
+
+    readfile($filename);
+
+    CRM_Utils_System::civiExit();
+  }
+
+}
diff --git a/civicrm/CRM/Mailing/Page/Url.php b/civicrm/CRM/Mailing/Page/Url.php
new file mode 100644
index 0000000000..29be68c661
--- /dev/null
+++ b/civicrm/CRM/Mailing/Page/Url.php
@@ -0,0 +1,104 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+
+/**
+ * Redirects a user to the full url from a mailing url.
+ *
+ * General Usage: civicrm/mailing/url?qid={event_queue_id}&u={url_id}
+ *
+ * Additional arguments may be handled by extractPassthroughParameters().
+ */
+class CRM_Mailing_Page_Url extends CRM_Core_Page {
+
+  /**
+   * Redirect the user to the specified url.
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function run() {
+    $queue_id = CRM_Utils_Request::retrieveValue('qid', 'Integer');
+    $url_id = CRM_Utils_Request::retrieveValue('u', 'Integer', NULL, TRUE);
+    $url = CRM_Mailing_Event_BAO_TrackableURLOpen::track($queue_id, $url_id);
+    $query_string = $this->extractPassthroughParameters();
+
+    if (strlen($query_string) > 0) {
+      // Parse the url to preserve the fragment.
+      $pieces = parse_url($url);
+
+      if (isset($pieces['fragment'])) {
+        $url = str_replace('#' . $pieces['fragment'], '', $url);
+      }
+
+      // Handle additional query string params.
+      if ($query_string) {
+        if (stristr($url, '?')) {
+          $url .= '&' . $query_string;
+        }
+        else {
+          $url .= '?' . $query_string;
+        }
+      }
+
+      // slap the fragment onto the end per URL spec
+      if (isset($pieces['fragment'])) {
+        $url .= '#' . $pieces['fragment'];
+      }
+    }
+    CRM_Utils_System::redirect($url, [
+      'for' => 'civicrm/mailing/url',
+      'queue_id' => $queue_id,
+      'url_id' => $url_id,
+    ]);
+  }
+
+  /**
+   * Determine if this request has any valid pass-through parameters.
+   *
+   * Under CRM-7103 (v3.3), all unrecognized query-parameters (besides qid/u) are passed
+   * through as part of the redirect. This mechanism is relevant to certain
+   * customizations (eg using `hook_alterMailParams` to append extra URL args)
+   * but does not matter for normal URLs.
+   *
+   * The functionality seems vaguely problematic (IMHO) - especially now that
+   * 'extern/url.php' is moving into the CMS/Civi router ('civicrm/mailing/url').
+   * But it's the current protocol.
+   *
+   * A better design might be to support `hook_alterRedirect` in the CiviMail
+   * click-through tracking. Then you don't have to take any untrusted inputs
+   * and you can fix URL mistakes in realtime.
+   *
+   * @return string
+   * @link https://issues.civicrm.org/jira/browse/CRM-7103
+   */
+  protected function extractPassthroughParameters():string {
+    $config = CRM_Core_Config::singleton();
+
+    $query_param = $_GET;
+    unset($query_param['qid']);
+    unset($query_param['u']);
+    unset($query_param[$config->userFrameworkURLVar]);
+    if ($config->userFramework === 'WordPress') {
+      // Ugh
+      unset($query_param['page']);
+      unset($query_param['noheader']);
+    }
+
+    $query_string = http_build_query($query_param);
+    return $query_string;
+  }
+
+}
diff --git a/civicrm/CRM/Mailing/xml/Menu/Mailing.xml b/civicrm/CRM/Mailing/xml/Menu/Mailing.xml
index 639406b8af..d4cc7d274a 100644
--- a/civicrm/CRM/Mailing/xml/Menu/Mailing.xml
+++ b/civicrm/CRM/Mailing/xml/Menu/Mailing.xml
@@ -17,7 +17,6 @@
     <desc>Configure spool period, throttling and other mailer settings.</desc>
     <access_arguments>access CiviCRM,access CiviMail</access_arguments>
     <adminGroup>CiviMail</adminGroup>
-    <icon>admin/small/07.png</icon>
     <weight>400</weight>
   </item>
   <item>
@@ -27,7 +26,6 @@
     <desc>Configure the header and footer used for mailings. Customize the content of automated Subscribe, Unsubscribe, Resubscribe and Opt-out messages.</desc>
     <access_arguments>access CiviCRM,access CiviMail</access_arguments>
     <adminGroup>CiviMail</adminGroup>
-    <icon>admin/small/Profile.png</icon>
     <weight>410</weight>
   </item>
   <item>
@@ -36,7 +34,6 @@
     <desc>List of Email Addresses which can be used when sending emails to contacts.</desc>
     <page_callback>CRM_Admin_Page_Options</page_callback>
     <adminGroup>CiviMail</adminGroup>
-    <icon>admin/small/title.png</icon>
     <weight>415</weight>
   </item>
   <item>
@@ -46,7 +43,6 @@
     <desc>Configure email account setting.</desc>
     <access_arguments>access CiviCRM,access CiviMail</access_arguments>
     <adminGroup>CiviMail</adminGroup>
-    <icon>admin/small/07.png</icon>
     <weight>420</weight>
   </item>
   <item>
@@ -206,4 +202,14 @@
     <page_callback>CRM_Mailing_Page_AJAX::getContactMailings</page_callback>
     <access_arguments>access CiviCRM</access_arguments>
   </item>
+  <item>
+    <path>civicrm/mailing/url</path>
+    <page_callback>CRM_Mailing_Page_Url</page_callback>
+    <access_arguments>*always allow*</access_arguments>
+  </item>
+  <item>
+    <path>civicrm/mailing/open</path>
+    <page_callback>CRM_Mailing_Page_Open</page_callback>
+    <access_arguments>*always allow*</access_arguments>
+  </item>
 </menu>
diff --git a/civicrm/CRM/Member/BAO/MembershipType.php b/civicrm/CRM/Member/BAO/MembershipType.php
index 8a56e9bde5..09b3eef0c4 100644
--- a/civicrm/CRM/Member/BAO/MembershipType.php
+++ b/civicrm/CRM/Member/BAO/MembershipType.php
@@ -740,7 +740,6 @@ class CRM_Member_BAO_MembershipType extends CRM_Member_DAO_MembershipType {
       if (!empty($results)) {
         $results['label'] = $results['name'] = $params['name'];
         $results['amount'] = empty($params['minimum_fee']) ? 0 : $params['minimum_fee'];
-        $optionsIds['id'] = $results['id'];
       }
       else {
         $results = [
@@ -756,12 +755,12 @@ class CRM_Member_BAO_MembershipType extends CRM_Member_DAO_MembershipType {
       if ($previousID) {
         CRM_Member_Form_MembershipType::checkPreviousPriceField($previousID, $priceSetId, $membershipTypeId, $optionsIds);
         if (!empty($optionsIds['option_id'])) {
-          $optionsIds['id'] = current(CRM_Utils_Array::value('option_id', $optionsIds));
+          $results['id'] = current($optionsIds['option_id']);
         }
       }
       $results['financial_type_id'] = $params['financial_type_id'] ?? NULL;
       $results['description'] = $params['description'] ?? NULL;
-      CRM_Price_BAO_PriceFieldValue::add($results, $optionsIds);
+      CRM_Price_BAO_PriceFieldValue::add($results);
     }
   }
 
diff --git a/civicrm/CRM/Member/DAO/MembershipType.php b/civicrm/CRM/Member/DAO/MembershipType.php
index 58c07d9bd7..9e51fd1fcc 100644
--- a/civicrm/CRM/Member/DAO/MembershipType.php
+++ b/civicrm/CRM/Member/DAO/MembershipType.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Member/MembershipType.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:c188b3772bd7ba843454e591a1fb0fd6)
+ * (GenCodeChecksum:c75161ef1844cf9a3977d458f0cb515b)
  */
 
 /**
@@ -237,6 +237,7 @@ class CRM_Member_DAO_MembershipType extends CRM_Core_DAO {
           'type' => CRM_Utils_Type::T_STRING,
           'title' => ts('Membership Type'),
           'description' => ts('Name of Membership Type'),
+          'required' => TRUE,
           'maxlength' => 128,
           'size' => CRM_Utils_Type::HUGE,
           'import' => TRUE,
diff --git a/civicrm/CRM/Member/Form.php b/civicrm/CRM/Member/Form.php
index a2e2ec3aa0..73f7cb46a9 100644
--- a/civicrm/CRM/Member/Form.php
+++ b/civicrm/CRM/Member/Form.php
@@ -356,27 +356,14 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment {
   /**
    * Create a recurring contribution record.
    *
-   * Recurring contribution parameters are set explicitly rather than merging paymentParams because it's hard
-   * to know the downstream impacts if we keep passing around the same array.
+   * @param array $contributionRecurParams
    *
-   * @param $paymentParams
+   * @param int $membershipID
    *
    * @return array
    * @throws \CiviCRM_API3_Exception
    */
-  protected function processRecurringContribution($paymentParams) {
-    $membershipID = $paymentParams['membership_type_id'][1];
-    $contributionRecurParams = [
-      'contact_id' => $paymentParams['contactID'],
-      'amount' => $paymentParams['total_amount'],
-      'contribution_status_id' => 'Pending',
-      'payment_processor_id' => $paymentParams['payment_processor_id'],
-      'campaign_id' => $paymentParams['campaign_id'],
-      'financial_type_id' => $paymentParams['financial_type_id'],
-      'is_email_receipt' => $paymentParams['is_email_receipt'],
-      'payment_instrument_id' => $paymentParams['payment_instrument_id'],
-      'invoice_id' => $paymentParams['invoice_id'],
-    ];
+  protected function processRecurringContribution($contributionRecurParams, $membershipID) {
 
     $mapping = [
       'frequency_interval' => 'duration_interval',
diff --git a/civicrm/CRM/Member/Form/Membership.php b/civicrm/CRM/Member/Form/Membership.php
index 412b6d27ee..dd4d948daa 100644
--- a/civicrm/CRM/Member/Form/Membership.php
+++ b/civicrm/CRM/Member/Form/Membership.php
@@ -357,20 +357,12 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
     }
     $this->assign('alreadyAutoRenew', $alreadyAutoRenew);
 
-    $this->assign('member_is_test', CRM_Utils_Array::value('member_is_test', $defaults));
+    $this->assign('member_is_test', $defaults['member_is_test'] ?? NULL);
+    $this->assign('membership_status_id', $defaults['status_id'] ?? NULL);
+    $this->assign('is_pay_later', !empty($defaults['is_pay_later']));
 
-    $this->assign('membership_status_id', CRM_Utils_Array::value('status_id', $defaults));
-
-    if (!empty($defaults['is_pay_later'])) {
-      $this->assign('is_pay_later', TRUE);
-    }
     if ($this->_mode) {
       $defaults = $this->getBillingDefaults($defaults);
-      // hack to simplify credit card entry for testing
-      // $defaults['credit_card_type']     = 'Visa';
-      // $defaults['credit_card_number']   = '4807731747657838';
-      // $defaults['cvv2']                 = '000';
-      // $defaults['credit_card_exp_date'] = array( 'Y' => '2012', 'M' => '05' );
     }
 
     //setting default join date if there is no join date
@@ -925,7 +917,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
    * or FALSE otherwise.
    */
   private function convertIsOverrideValue() {
-    $this->_params['is_override'] = CRM_Member_StatusOverrideTypes::isOverridden($this->_params['is_override']);
+    $this->_params['is_override'] = CRM_Member_StatusOverrideTypes::isOverridden($this->_params['is_override'] ?? CRM_Member_StatusOverrideTypes::NO);
   }
 
   /**
@@ -1098,8 +1090,6 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       $formValues['financial_type_id'] = $this->_priceSet['financial_type_id'];
     }
 
-    $config = CRM_Core_Config::singleton();
-
     $membershipTypeValues = [];
     foreach ($this->_memTypeSelected as $memType) {
       $membershipTypeValues[$memType]['membership_type_id'] = $memType;
@@ -1335,7 +1325,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       // add all the additional payment params we need
       $formValues['amount'] = $params['total_amount'];
       // @todo this is a candidate for beginPostProcessFunction.
-      $formValues['currencyID'] = $config->defaultCurrency;
+      $formValues['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency;
       $formValues['description'] = ts("Contribution submitted by a staff person using member's credit card for signup");
       $formValues['invoiceID'] = md5(uniqid(rand(), TRUE));
       $formValues['financial_type_id'] = $params['financial_type_id'];
@@ -1456,7 +1446,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       $params['contribution_source'] = ts('%1 Membership Signup: Credit card or direct debit (by %2)',
         [1 => $membershipType, 2 => $userName]
       );
-      $params['source'] = $formValues['source'] ? $formValues['source'] : $params['contribution_source'];
+      $params['source'] = $formValues['source'] ?: $params['contribution_source'];
       $params['trxn_id'] = $result['trxn_id'] ?? NULL;
       $params['is_test'] = ($this->_mode === 'live') ? 0 : 1;
       if (!empty($formValues['send_receipt'])) {
@@ -1856,7 +1846,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       ]);
 
       $membership = $createdMemberships[$memType];
-      $memEndDate = ($membership->end_date) ? $membership->end_date : $endDate;
+      $memEndDate = $membership->end_date ?: $endDate;
 
       //get the end date from calculated dates.
       if (!$memEndDate && !$isRecur) {
diff --git a/civicrm/CRM/Member/Form/MembershipRenewal.php b/civicrm/CRM/Member/Form/MembershipRenewal.php
index 04287f6bfe..8f688e9b55 100644
--- a/civicrm/CRM/Member/Form/MembershipRenewal.php
+++ b/civicrm/CRM/Member/Form/MembershipRenewal.php
@@ -537,20 +537,30 @@ class CRM_Member_Form_MembershipRenewal extends CRM_Member_Form {
       if (!empty($this->_params['send_receipt'])) {
         $paymentParams['email'] = $this->_contributorEmail;
       }
-      $paymentParams['is_email_receipt'] = !empty($this->_params['send_receipt']);
 
       $paymentParams['contactID'] = $this->_contributorContactID;
 
       CRM_Core_Payment_Form::mapParams($this->_bltID, $this->_params, $paymentParams, TRUE);
 
-      $payment = $this->_paymentProcessor['object'];
-
       if (!empty($this->_params['auto_renew'])) {
-        $contributionRecurParams = $this->processRecurringContribution($paymentParams);
+
+        $contributionRecurParams = $this->processRecurringContribution([
+          'contact_id' => $this->_contributorContactID,
+          'amount' => $this->_params['total_amount'],
+          'contribution_status_id' => 'Pending',
+          'payment_processor_id' => $this->_params['payment_processor_id'],
+          'campaign_id' => $this->_params['campaign_id'],
+          'financial_type_id' => $this->_params['financial_type_id'],
+          'is_email_receipt' => !empty($this->_params['send_receipt']),
+          'payment_instrument_id' => $this->_params['payment_instrument_id'],
+          'invoice_id' => $this->_params['invoice_id'],
+        ], $membershipID = $paymentParams['membership_type_id'][1]);
+
         $contributionRecurID = $contributionRecurParams['contributionRecurID'];
         $paymentParams = array_merge($paymentParams, $contributionRecurParams);
       }
 
+      $payment = $this->_paymentProcessor['object'];
       $result = $payment->doPayment($paymentParams);
       $this->_params = array_merge($this->_params, $result);
 
@@ -585,11 +595,10 @@ class CRM_Member_Form_MembershipRenewal extends CRM_Member_Form {
       $membershipSource = $this->_params['membership_source'];
     }
 
-    // @todo Move this into CRM_Member_BAO_Membership::processMembership
     $pending = ($this->_params['contribution_status_id'] == CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Pending'));
-    list($membership) = CRM_Member_BAO_Membership::processMembership(
+    $membership = $this->processMembership(
       $this->_contactID, $this->_params['membership_type_id'][1], $isTestMembership,
-      $renewalDate, NULL, $customFieldsFormatted, $numRenewTerms, $this->_membershipId,
+      $renewalDate, $customFieldsFormatted, $numRenewTerms, $this->_membershipId,
       $pending,
       $contributionRecurID, $membershipSource, $this->_params['is_pay_later'], CRM_Utils_Array::value('campaign_id',
       $this->_params)
@@ -725,4 +734,184 @@ class CRM_Member_Form_MembershipRenewal extends CRM_Member_Form {
     );
   }
 
+  /**
+   * Process membership.
+   *
+   * This is duplicated from the BAO class - on the basis that it's actually easier to divide & conquer when
+   * it comes to clearing up really bad code.
+   *
+   * @param int $contactID
+   * @param int $membershipTypeID
+   * @param bool $is_test
+   * @param string $changeToday
+   * @param $customFieldsFormatted
+   * @param $numRenewTerms
+   * @param int $membershipID
+   * @param $pending
+   * @param int $contributionRecurID
+   * @param $membershipSource
+   * @param $isPayLater
+   * @param int $campaignId
+   *
+   * @return CRM_Member_BAO_Membership
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   */
+  public function processMembership($contactID, $membershipTypeID, $is_test, $changeToday, $customFieldsFormatted, $numRenewTerms, $membershipID, $pending, $contributionRecurID, $membershipSource, $isPayLater, $campaignId) {
+    $updateStatusId = FALSE;
+    $allStatus = CRM_Member_PseudoConstant::membershipStatus();
+    $format = '%Y%m%d';
+    $membershipTypeDetails = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($membershipTypeID);
+    $ids = [];
+
+    // CRM-7297 - allow membership type to be be changed during renewal so long as the parent org of new membershipType
+    // is the same as the parent org of an existing membership of the contact
+    $currentMembership = CRM_Member_BAO_Membership::getContactMembership($contactID, $membershipTypeID,
+      $is_test, $membershipID, TRUE
+    );
+
+    // Do NOT do anything.
+    //1. membership with status : PENDING/CANCELLED (CRM-2395)
+    //2. Paylater/IPN renew. CRM-4556.
+    if ($pending || in_array($currentMembership['status_id'], [
+      array_search('Pending', $allStatus),
+      // CRM-15475
+      array_search('Cancelled', CRM_Member_PseudoConstant::membershipStatus(NULL, " name = 'Cancelled' ", 'name', FALSE, TRUE)),
+    ])) {
+
+      $memParams = [
+        'id' => $currentMembership['id'],
+        'status_id' => $currentMembership['status_id'],
+        'start_date' => $currentMembership['start_date'],
+        'end_date' => $currentMembership['end_date'],
+        'join_date' => $currentMembership['join_date'],
+        'membership_type_id' => $membershipTypeID,
+        'max_related' => !empty($membershipTypeDetails['max_related']) ? $membershipTypeDetails['max_related'] : NULL,
+        'membership_activity_status' => ($pending || $isPayLater) ? 'Scheduled' : 'Completed',
+      ];
+      if ($contributionRecurID) {
+        $memParams['contribution_recur_id'] = $contributionRecurID;
+      }
+      // @todo stop passing $ids - it is empty
+      return CRM_Member_BAO_Membership::create($memParams, $ids);
+    }
+
+    // Check and fix the membership if it is STALE
+    CRM_Member_BAO_Membership::fixMembershipStatusBeforeRenew($currentMembership, $changeToday);
+
+    // Now Renew the membership
+    if (!$currentMembership['is_current_member']) {
+      // membership is not CURRENT
+
+      // CRM-7297 Membership Upsell - calculate dates based on new membership type
+      $dates = CRM_Member_BAO_MembershipType::getRenewalDatesForMembershipType($currentMembership['id'],
+        $changeToday,
+        $membershipTypeID,
+        $numRenewTerms
+      );
+
+      $currentMembership['join_date'] = CRM_Utils_Date::customFormat($currentMembership['join_date'], $format);
+      foreach (['start_date', 'end_date'] as $dateType) {
+        $currentMembership[$dateType] = $dates[$dateType] ?? NULL;
+      }
+      $currentMembership['is_test'] = $is_test;
+
+      if (!empty($membershipSource)) {
+        $currentMembership['source'] = $membershipSource;
+      }
+      else {
+        $currentMembership['source'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership',
+          $currentMembership['id'],
+          'source'
+        );
+      }
+
+      if (!empty($currentMembership['id'])) {
+        $ids['membership'] = $currentMembership['id'];
+      }
+      $memParams = $currentMembership;
+      $memParams['membership_type_id'] = $membershipTypeID;
+
+      //set the log start date.
+      $memParams['log_start_date'] = CRM_Utils_Date::customFormat($dates['log_start_date'], $format);
+    }
+    else {
+
+      // CURRENT Membership
+      $membership = new CRM_Member_DAO_Membership();
+      $membership->id = $currentMembership['id'];
+      $membership->find(TRUE);
+      // CRM-7297 Membership Upsell - calculate dates based on new membership type
+      $dates = CRM_Member_BAO_MembershipType::getRenewalDatesForMembershipType($membership->id,
+        $changeToday,
+        $membershipTypeID,
+        $numRenewTerms
+      );
+
+      // Insert renewed dates for CURRENT membership
+      $memParams = [];
+      $memParams['join_date'] = $membership->join_date;
+      $memParams['start_date'] = $membership->start_date;
+      $memParams['end_date'] = $dates['end_date'] ?? NULL;
+      $memParams['membership_type_id'] = $membershipTypeID;
+
+      //set the log start date.
+      $memParams['log_start_date'] = CRM_Utils_Date::customFormat($dates['log_start_date'], $format);
+
+      //CRM-18067
+      if (!empty($membershipSource)) {
+        $memParams['source'] = $membershipSource;
+      }
+      elseif (empty($membership->source)) {
+        $memParams['source'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership',
+          $currentMembership['id'],
+          'source'
+        );
+      }
+
+      if (!empty($currentMembership['id'])) {
+        $ids['membership'] = $currentMembership['id'];
+      }
+      $memParams['membership_activity_status'] = ($pending || $isPayLater) ? 'Scheduled' : 'Completed';
+    }
+    //CRM-4555
+    if ($pending) {
+      $updateStatusId = array_search('Pending', $allStatus);
+    }
+
+    // Putting this in an IF is precautionary as it seems likely that it would be ignored if empty, but
+    // perhaps shouldn't be?
+    if ($contributionRecurID) {
+      $memParams['contribution_recur_id'] = $contributionRecurID;
+    }
+    //CRM-4555
+    //if we decided status here and want to skip status
+    //calculation in create( ); then need to pass 'skipStatusCal'.
+    if ($updateStatusId) {
+      $memParams['status_id'] = $updateStatusId;
+      $memParams['skipStatusCal'] = TRUE;
+    }
+
+    //since we are renewing,
+    //make status override false.
+    $memParams['is_override'] = FALSE;
+
+    $params['modified_id'] = $contactID;
+
+    //inherit campaign from contrib page.
+    if (isset($campaignId)) {
+      $memParams['campaign_id'] = $campaignId;
+    }
+
+    $memParams['custom'] = $customFieldsFormatted;
+    // @todo stop passing $ids (membership and userId may be set by this point)
+    $membership = CRM_Member_BAO_Membership::create($memParams, $ids);
+
+    // not sure why this statement is here, seems quite odd :( - Lobo: 12/26/2010
+    // related to: http://forum.civicrm.org/index.php/topic,11416.msg49072.html#msg49072
+    $membership->find(TRUE);
+
+    return $membership;
+  }
+
 }
diff --git a/civicrm/CRM/Member/Import/Form/MapField.php b/civicrm/CRM/Member/Import/Form/MapField.php
index 1d537f7bcb..e7c110692f 100644
--- a/civicrm/CRM/Member/Import/Form/MapField.php
+++ b/civicrm/CRM/Member/Import/Form/MapField.php
@@ -47,7 +47,7 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
     $skipColumnHeader = $this->controller->exportValue('DataSource', 'skipColumnHeader');
     $this->_onDuplicate = $this->get('onDuplicate', $onDuplicate ?? "");
 
-    $highlightedFields = array();
+    $highlightedFields = [];
     if ($skipColumnHeader) {
       $this->assign('skipColumnHeader', $skipColumnHeader);
       $this->assign('rowDisplayCount', 3);
@@ -120,7 +120,7 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
       //mapping is to be loaded from database
 
       $params = array('id' => $savedMapping);
-      $temp = array();
+      $temp = [];
       $mappingDetails = CRM_Core_BAO_Mapping::retrieve($params, $temp);
 
       $this->assign('loadedMapping', $mappingDetails->name);
@@ -150,7 +150,7 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
 
     //-------- end of saved mapping stuff ---------
 
-    $defaults = array();
+    $defaults = [];
     $mapperKeys = array_keys($this->_mapperFields);
     $hasHeaders = !empty($this->_columnHeaders);
     $headerPatterns = $this->get('headerPatterns');
@@ -198,7 +198,7 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
             $jsSet = TRUE;
           }
           else {
-            $defaults["mapper[$i]"] = array();
+            $defaults["mapper[$i]"] = [];
           }
           if (!$jsSet) {
             for ($k = 1; $k < 4; $k++) {
@@ -293,10 +293,10 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
    *   list of errors to be posted back to the form
    */
   public static function formRule($fields, $files, $self) {
-    $errors = array();
+    $errors = [];
 
     if (!array_key_exists('savedMapping', $fields)) {
-      $importKeys = array();
+      $importKeys = [];
       foreach ($fields['mapper'] as $mapperPart) {
         $importKeys[] = $mapperPart[0];
       }
@@ -403,12 +403,12 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
     $seperator = $this->controller->exportValue('DataSource', 'fieldSeparator');
     $skipColumnHeader = $this->controller->exportValue('DataSource', 'skipColumnHeader');
 
-    $mapperKeys = array();
-    $mapper = array();
+    $mapperKeys = [];
+    $mapper = [];
     $mapperKeys = $this->controller->exportValue($this->_name, 'mapper');
-    $mapperKeysMain = array();
-    $mapperLocType = array();
-    $mapperPhoneType = array();
+    $mapperKeysMain = [];
+    $mapperLocType = [];
+    $mapperPhoneType = [];
 
     for ($i = 0; $i < $this->_columnCount; $i++) {
       $mapper[$i] = $this->_mapperFields[$mapperKeys[$i][0]];
@@ -441,7 +441,7 @@ class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
       $mappingFields->mapping_id = $params['mappingId'];
       $mappingFields->find();
 
-      $mappingFieldsId = array();
+      $mappingFieldsId = [];
       while ($mappingFields->fetch()) {
         if ($mappingFields->id) {
           $mappingFieldsId[$mappingFields->column_number] = $mappingFields->id;
diff --git a/civicrm/CRM/Member/Page/DashBoard.php b/civicrm/CRM/Member/Page/DashBoard.php
index 57fb30cda5..8ba2539c13 100644
--- a/civicrm/CRM/Member/Page/DashBoard.php
+++ b/civicrm/CRM/Member/Page/DashBoard.php
@@ -40,7 +40,7 @@ class CRM_Member_Page_DashBoard extends CRM_Core_Page {
     }
     $this->assign('membershipSummary', TRUE);
     CRM_Utils_System::setTitle(ts('CiviMember'));
-    $membershipSummary = array();
+    $membershipSummary = [];
     $preMonth = date("Y-m-d", mktime(0, 0, 0, date("m") - 1, 01, date("Y")));
     $preMonthEnd = date("Y-m-t", mktime(0, 0, 0, date("m") - 1, 01, date("Y")));
 
diff --git a/civicrm/CRM/Member/xml/Menu/Member.xml b/civicrm/CRM/Member/xml/Menu/Member.xml
index ffe0eb051e..c8b0dae7f8 100644
--- a/civicrm/CRM/Member/xml/Menu/Member.xml
+++ b/civicrm/CRM/Member/xml/Menu/Member.xml
@@ -24,7 +24,6 @@
      <page_callback>CRM_Member_Page_MembershipType</page_callback>
      <desc>Define the types of memberships you want to offer. For each type, you can specify a 'name' (Gold Member, Honor Society Member...), a description, duration, and a minimum fee.</desc>
      <adminGroup>CiviMember</adminGroup>
-     <icon>admin/small/membership_type.png</icon>
      <weight>370</weight>
   </item>
   <item>
@@ -33,7 +32,6 @@
      <page_callback>CRM_Member_Page_MembershipStatus</page_callback>
      <desc>Status 'rules' define the current status for a membership based on that membership's start and end dates. You can adjust the default status options and rules as needed to meet your needs.</desc>
      <adminGroup>CiviMember</adminGroup>
-     <icon>admin/small/membership_status.png</icon>
      <weight>380</weight>
   </item>
   <item>
diff --git a/civicrm/CRM/Pledge/BAO/Pledge.php b/civicrm/CRM/Pledge/BAO/Pledge.php
index 4fdc3ec5f6..1390af09f9 100644
--- a/civicrm/CRM/Pledge/BAO/Pledge.php
+++ b/civicrm/CRM/Pledge/BAO/Pledge.php
@@ -137,7 +137,7 @@ class CRM_Pledge_BAO_Pledge extends CRM_Pledge_DAO_Pledge {
     $isRecalculatePledgePayment = self::isPaymentsRequireRecalculation($params);
     $transaction = new CRM_Core_Transaction();
 
-    $paymentParams = array();
+    $paymentParams = [];
     if (!empty($params['installment_amount'])) {
       $params['amount'] = $params['installment_amount'] * $params['installments'];
     }
@@ -206,7 +206,7 @@ class CRM_Pledge_BAO_Pledge extends CRM_Pledge_DAO_Pledge {
       "action=view&reset=1&id={$pledge->id}&cid={$pledge->contact_id}&context=home"
     );
 
-    $recentOther = array();
+    $recentOther = [];
     if (CRM_Core_Permission::checkActionPermission('CiviPledge', CRM_Core_Action::UPDATE)) {
       $recentOther['editUrl'] = CRM_Utils_System::url('civicrm/contact/view/pledge',
         "action=update&reset=1&id={$pledge->id}&cid={$pledge->contact_id}&context=home"
@@ -330,7 +330,7 @@ class CRM_Pledge_BAO_Pledge extends CRM_Pledge_DAO_Pledge {
    * @return array|null
    */
   public static function getTotalAmountAndCount($status = NULL, $startDate = NULL, $endDate = NULL) {
-    $where = array();
+    $where = [];
     $select = $from = $queryDate = NULL;
     $statusId = CRM_Core_PseudoConstant::getKey('CRM_Pledge_BAO_Pledge', 'status_id', $status);
 
@@ -365,7 +365,7 @@ GROUP BY  currency
     $start = substr($startDate, 0, 8);
     $end = substr($endDate, 0, 8);
     $pCount = 0;
-    $pamount = array();
+    $pamount = [];
     $dao = CRM_Core_DAO::executeQuery($query);
     while ($dao->fetch()) {
       $pCount += $dao->pledge_count;
@@ -380,7 +380,7 @@ GROUP BY  currency
       ),
     );
 
-    $where = array();
+    $where = [];
     switch ($status) {
       case 'Completed':
         $select = 'sum( total_amount ) as received_pledge , count( cd.id ) as received_count';
@@ -428,7 +428,7 @@ GROUP BY  currency
 ";
     if ($select) {
       $dao = CRM_Core_DAO::executeQuery($query);
-      $amount = array();
+      $amount = [];
       $count = 0;
 
       while ($dao->fetch()) {
@@ -462,7 +462,7 @@ GROUP BY  currency
    *   return the list of pledge fields
    */
   public static function getHonorContacts($honorId) {
-    $params = array();
+    $params = [];
     $honorDAO = new CRM_Contribute_DAO_ContributionSoft();
     $honorDAO->contact_id = $honorId;
     $honorDAO->find();
@@ -506,7 +506,7 @@ GROUP BY  currency
    */
   public static function sendAcknowledgment(&$form, $params) {
     //handle Acknowledgment.
-    $allPayments = $payments = array();
+    $allPayments = $payments = [];
 
     // get All Payments status types.
     $paymentStatusTypes = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
@@ -516,7 +516,7 @@ GROUP BY  currency
 
     if (!empty($allPayments)) {
       foreach ($allPayments as $payID => $values) {
-        $contributionValue = $contributionStatus = array();
+        $contributionValue = $contributionStatus = [];
         if (isset($values['contribution_id'])) {
           $contributionParams = array('id' => $values['contribution_id']);
           $returnProperties = array('contribution_status_id', 'receive_date');
@@ -573,7 +573,7 @@ GROUP BY  currency
       'domain' => array('name', 'phone', 'address', 'email'),
       'contact' => CRM_Core_SelectValues::contactTokens(),
     );
-    $domainValues = array();
+    $domainValues = [];
     foreach ($tokens['domain'] as $token) {
       $domainValues[$token] = CRM_Utils_Token::getDomainTokenReplacement($token, $domain);
     }
@@ -599,10 +599,10 @@ GROUP BY  currency
     if (!empty($params['hidden_custom'])) {
       $groupTree = CRM_Core_BAO_CustomGroup::getTree('Pledge', NULL, $params['id']);
       $pledgeParams = array(array('pledge_id', '=', $params['id'], 0, 0));
-      $customGroup = array();
+      $customGroup = [];
       // retrieve custom data
       foreach ($groupTree as $groupID => $group) {
-        $customFields = $customValues = array();
+        $customFields = $customValues = [];
         if ($groupID == 'info') {
           continue;
         }
@@ -708,7 +708,7 @@ GROUP BY  currency
   public static function exportableFields($checkPermission = TRUE) {
     if (!self::$_exportableFields) {
       if (!self::$_exportableFields) {
-        self::$_exportableFields = array();
+        self::$_exportableFields = [];
       }
 
       $fields = CRM_Pledge_DAO_Pledge::export();
@@ -773,12 +773,12 @@ GROUP BY  currency
    *   associated array of pledge id(s)
    */
   public static function getContactPledges($contactID) {
-    $pledgeDetails = array();
+    $pledgeDetails = [];
     $pledgeStatuses = CRM_Core_OptionGroup::values('pledge_status',
       FALSE, FALSE, FALSE, NULL, 'name'
     );
 
-    $status = array();
+    $status = [];
 
     // get pending and in progress status
     foreach (array(
@@ -833,7 +833,7 @@ GROUP BY  currency
    */
   public static function updatePledgeStatus($params) {
 
-    $returnMessages = array();
+    $returnMessages = [];
 
     $sendReminders = CRM_Utils_Array::value('send_reminders', $params, FALSE);
 
@@ -881,7 +881,7 @@ SELECT  pledge.contact_id              as contact_id,
     $dao = CRM_Core_DAO::executeQuery($query);
 
     $now = date('Ymd');
-    $pledgeDetails = $contactIds = $pledgePayments = $pledgeStatus = array();
+    $pledgeDetails = $contactIds = $pledgePayments = $pledgeStatus = [];
     while ($dao->fetch()) {
       $checksumValue = CRM_Contact_BAO_Contact_Utils::generateChecksum($dao->contact_id);
 
@@ -941,7 +941,7 @@ SELECT  pledge.contact_id              as contact_id,
         'contact' => CRM_Core_SelectValues::contactTokens(),
       );
 
-      $domainValues = array();
+      $domainValues = [];
       foreach ($tokens['domain'] as $token) {
         $domainValues[$token] = CRM_Utils_Token::getDomainTokenReplacement($token, $domain);
       }
@@ -1100,7 +1100,7 @@ SELECT  pledge.contact_id              as contact_id,
     ));
     $paymentDAO->find();
 
-    $paymentIDs = array();
+    $paymentIDs = [];
     while ($paymentDAO->fetch()) {
       $paymentIDs[] = $paymentDAO->id;
     }
@@ -1261,7 +1261,7 @@ SELECT  pledge.contact_id              as contact_id,
    *
    * @return array|bool
    */
-  public static function buildOptions($fieldName, $context = NULL, $props = array()) {
+  public static function buildOptions($fieldName, $context = NULL, $props = []) {
     $result = parent::buildOptions($fieldName, $context, $props);
     if ($fieldName == 'status_id') {
       $result = array_diff($result, array('Failed'));
diff --git a/civicrm/CRM/Pledge/BAO/PledgeBlock.php b/civicrm/CRM/Pledge/BAO/PledgeBlock.php
index 8d363e06f9..2672e631cf 100644
--- a/civicrm/CRM/Pledge/BAO/PledgeBlock.php
+++ b/civicrm/CRM/Pledge/BAO/PledgeBlock.php
@@ -70,58 +70,18 @@ class CRM_Pledge_BAO_PledgeBlock extends CRM_Pledge_DAO_PledgeBlock {
   }
 
   /**
-   * Add pledgeBlock.
+   * Add or update pledgeBlock.
    *
    * @param array $params
-   *   Reference array contains the values submitted by the form.
-   *
    *
    * @return object
    */
-  public static function add(&$params) {
-
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::pre('edit', 'PledgeBlock', $params['id'], $params);
-    }
-    else {
-      CRM_Utils_Hook::pre('create', 'PledgeBlock', NULL, $params);
-    }
-
-    $pledgeBlock = new CRM_Pledge_DAO_PledgeBlock();
-
-    // fix for pledge_frequency_unit
-    $freqUnits = $params['pledge_frequency_unit'] ?? NULL;
-
-    if ($freqUnits && is_array($freqUnits)) {
-      unset($params['pledge_frequency_unit']);
-      $newFreqUnits = array();
-      foreach ($freqUnits as $k => $v) {
-        if ($v) {
-          $newFreqUnits[$k] = $v;
-        }
-      }
-
-      $freqUnits = $newFreqUnits;
-      if (is_array($freqUnits) && !empty($freqUnits)) {
-        $freqUnits = implode(CRM_Core_DAO::VALUE_SEPARATOR, array_keys($freqUnits));
-        $pledgeBlock->pledge_frequency_unit = $freqUnits;
-      }
-      else {
-        $pledgeBlock->pledge_frequency_unit = '';
-      }
+  public static function add($params) {
+    // FIXME: This is assuming checkbox input like ['foo' => 1, 'bar' => 0, 'baz' => 1]. Not API friendly.
+    if (!empty($params['pledge_frequency_unit']) && is_array($params['pledge_frequency_unit'])) {
+      $params['pledge_frequency_unit'] = array_keys(array_filter($params['pledge_frequency_unit']));
     }
-
-    $pledgeBlock->copyValues($params);
-    $result = $pledgeBlock->save();
-
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::post('edit', 'PledgeBlock', $pledgeBlock->id, $pledgeBlock);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'Pledge', $pledgeBlock->id, $pledgeBlock);
-    }
-
-    return $result;
+    return self::writeRecord($params);
   }
 
   /**
@@ -159,7 +119,7 @@ class CRM_Pledge_BAO_PledgeBlock extends CRM_Pledge_DAO_PledgeBlock {
    * @return array
    */
   public static function getPledgeBlock($pageID) {
-    $pledgeBlock = array();
+    $pledgeBlock = [];
 
     $dao = new CRM_Pledge_DAO_PledgeBlock();
     $dao->entity_table = 'civicrm_contribution_page';
@@ -180,7 +140,7 @@ class CRM_Pledge_BAO_PledgeBlock extends CRM_Pledge_DAO_PledgeBlock {
     //build pledge payment fields.
     if (!empty($form->_values['pledge_id'])) {
       //get all payments required details.
-      $allPayments = array();
+      $allPayments = [];
       $returnProperties = array(
         'status_id',
         'scheduled_date',
@@ -193,9 +153,9 @@ class CRM_Pledge_BAO_PledgeBlock extends CRM_Pledge_DAO_PledgeBlock {
       // get all status
       $allStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
 
-      $nextPayment = array();
+      $nextPayment = [];
       $isNextPayment = FALSE;
-      $overduePayments = array();
+      $overduePayments = [];
       foreach ($allPayments as $payID => $value) {
         if ($allStatus[$value['status_id']] == 'Overdue') {
           $overduePayments[$payID] = array(
@@ -224,7 +184,7 @@ class CRM_Pledge_BAO_PledgeBlock extends CRM_Pledge_DAO_PledgeBlock {
       }
 
       // build check box array for payments.
-      $payments = array();
+      $payments = [];
       if (!empty($overduePayments)) {
         foreach ($overduePayments as $id => $payment) {
           $label = ts("%1 - due on %2 (overdue)", array(
@@ -276,7 +236,7 @@ class CRM_Pledge_BAO_PledgeBlock extends CRM_Pledge_DAO_PledgeBlock {
       }
       // Frequency unit drop-down label suffixes switch from *ly to *(s)
       $freqUnitVals = explode(CRM_Core_DAO::VALUE_SEPARATOR, $pledgeBlock['pledge_frequency_unit']);
-      $freqUnits = array();
+      $freqUnits = [];
       $frequencyUnits = CRM_Core_OptionGroup::values('recur_frequency_units');
       foreach ($freqUnitVals as $key => $val) {
         if (array_key_exists($val, $frequencyUnits)) {
@@ -287,7 +247,7 @@ class CRM_Pledge_BAO_PledgeBlock extends CRM_Pledge_DAO_PledgeBlock {
       // CRM-18854
       if (!empty($pledgeBlock['is_pledge_start_date_visible'])) {
         if (!empty($pledgeBlock['pledge_start_date'])) {
-          $defaults = array();
+          $defaults = [];
           $date = (array) json_decode($pledgeBlock['pledge_start_date']);
           foreach ($date as $field => $value) {
             switch ($field) {
diff --git a/civicrm/CRM/Pledge/BAO/PledgePayment.php b/civicrm/CRM/Pledge/BAO/PledgePayment.php
index 38f947cc69..d049f9e55a 100644
--- a/civicrm/CRM/Pledge/BAO/PledgePayment.php
+++ b/civicrm/CRM/Pledge/BAO/PledgePayment.php
@@ -154,31 +154,11 @@ WHERE     pledge_id = %1
    *   pledge payment id
    */
   public static function add($params) {
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::pre('edit', 'PledgePayment', $params['id'], $params);
-    }
-    else {
-      CRM_Utils_Hook::pre('create', 'PledgePayment', NULL, $params);
-    }
-
-    $payment = new CRM_Pledge_DAO_PledgePayment();
-    $payment->copyValues($params);
-
     // set currency for CRM-1496
-    if (!isset($payment->currency)) {
-      $payment->currency = CRM_Core_Config::singleton()->defaultCurrency;
+    if (empty($params['id']) && !isset($params['currency'])) {
+      $params['currency'] = CRM_Core_Config::singleton()->defaultCurrency;
     }
-
-    $result = $payment->save();
-
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::post('edit', 'PledgePayment', $payment->id, $payment);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'PledgePayment', $payment->id, $payment);
-    }
-
-    return $result;
+    return self::writeRecord($params);
   }
 
   /**
diff --git a/civicrm/CRM/Price/BAO/LineItem.php b/civicrm/CRM/Price/BAO/LineItem.php
index 516b2c84ec..c974eeb48f 100644
--- a/civicrm/CRM/Price/BAO/LineItem.php
+++ b/civicrm/CRM/Price/BAO/LineItem.php
@@ -286,7 +286,7 @@ WHERE li.contribution_id = %1";
     }
     if ($invoicing) {
       // @todo - this is an inappropriate place to be doing form level assignments.
-      $taxTerm = $invoiceSettings['tax_term'] ?? NULL;
+      $taxTerm = Civi::settings()->get('tax_term');
       $smarty = CRM_Core_Smarty::singleton();
       $smarty->assign('taxTerm', $taxTerm);
       $smarty->assign('getTaxDetails', $getTaxDetails);
diff --git a/civicrm/CRM/Price/BAO/PriceField.php b/civicrm/CRM/Price/BAO/PriceField.php
index cf3bf99f5f..091d9810e4 100644
--- a/civicrm/CRM/Price/BAO/PriceField.php
+++ b/civicrm/CRM/Price/BAO/PriceField.php
@@ -9,14 +9,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 /**
  * Business objects for managing price fields.
  *
@@ -306,7 +298,7 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField {
     $valueFieldName = 'amount';
     $seperator = '|';
     $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-    $taxTerm = $invoiceSettings['tax_term'] ?? NULL;
+    $taxTerm = Civi::settings()->get('tax_term');
     $displayOpt = $invoiceSettings['tax_display_settings'] ?? NULL;
     $invoicing = $invoiceSettings['invoicing'] ?? NULL;
     switch ($field->html_type) {
@@ -386,10 +378,10 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField {
             $opt['label'] = !empty($opt['label']) ? $opt['label'] . '<span class="crm-price-amount-label-separator">&nbsp;-&nbsp;</span>' : '';
             $preHelpText = $postHelpText = '';
             if (!empty($opt['help_pre'])) {
-              $preHelpText = '<span class="crm-price-amount-help-pre description">' . $opt['help_pre'] . '</span>: ';
+              $preHelpText = '<span class="crm-price-amount-help-pre description">' . $opt['help_pre'] . '</span><span class="crm-price-amount-help-pre-separator">:&nbsp;</span>';
             }
             if (!empty($opt['help_post'])) {
-              $postHelpText = ': <span class="crm-price-amount-help-post description">' . $opt['help_post'] . '</span>';
+              $postHelpText = '<span class="crm-price-amount-help-post-separator">:&nbsp;</span><span class="crm-price-amount-help-post description">' . $opt['help_post'] . '</span>';
             }
             if (isset($taxAmount) && $invoicing) {
               if ($displayOpt == 'Do_not_show') {
diff --git a/civicrm/CRM/Price/BAO/PriceFieldValue.php b/civicrm/CRM/Price/BAO/PriceFieldValue.php
index 34d431210a..7ad8514b75 100644
--- a/civicrm/CRM/Price/BAO/PriceFieldValue.php
+++ b/civicrm/CRM/Price/BAO/PriceFieldValue.php
@@ -26,35 +26,18 @@ class CRM_Price_BAO_PriceFieldValue extends CRM_Price_DAO_PriceFieldValue {
    *
    * @param array $params
    *
-   * @param array $ids
-   *  Deprecated variable.
-   *
    * @return CRM_Price_DAO_PriceFieldValue
    */
-  public static function add(&$params, $ids = []) {
-    $hook = empty($params['id']) ? 'create' : 'edit';
-    CRM_Utils_Hook::pre($hook, 'PriceFieldValue', CRM_Utils_Array::value('id', $params), $params);
-
-    $fieldValueBAO = new CRM_Price_BAO_PriceFieldValue();
-    $fieldValueBAO->copyValues($params);
-
-    // CRM-16189
-    $priceFieldID = $params['price_field_id'] ?? NULL;
-
-    $id = CRM_Utils_Array::value('id', $ids, CRM_Utils_Array::value('id', $params));
+  public static function add($params) {
+    $fieldValueBAO = self::writeRecord($params);
 
-    if (!$priceFieldID) {
-      $priceFieldID = CRM_Core_DAO::getFieldValue('CRM_Price_BAO_PriceFieldValue', $id, 'price_field_id');
-    }
     if (!empty($params['is_default'])) {
+      $priceFieldID = $params['price_field_id'] ?? CRM_Core_DAO::getFieldValue('CRM_Price_BAO_PriceFieldValue', $fieldValueBAO->id, 'price_field_id');
       $query = 'UPDATE civicrm_price_field_value SET is_default = 0 WHERE  price_field_id = %1';
-      $p = [1 => [$params['price_field_id'], 'Integer']];
+      $p = [1 => [$priceFieldID, 'Integer']];
       CRM_Core_DAO::executeQuery($query, $p);
     }
 
-    $fieldValueBAO->save();
-    CRM_Utils_Hook::post($hook, 'PriceFieldValue', $fieldValueBAO->id, $fieldValueBAO);
-
     // Reset the cached values in this function.
     CRM_Price_BAO_PriceField::getOptions(CRM_Utils_Array::value('price_field_id', $params), FALSE, TRUE);
     return $fieldValueBAO;
@@ -78,7 +61,7 @@ class CRM_Price_BAO_PriceFieldValue extends CRM_Price_DAO_PriceFieldValue {
       return NULL;
     }
     if (!$id && empty($params['name'])) {
-      $params['name'] = strtolower(CRM_Utils_String::munge($params['label'], '_', 242));
+      $params['name'] = strtolower(CRM_Utils_String::munge(($params['label'] ?? '_'), '_', 242));
     }
 
     if ($id && !empty($params['weight'])) {
@@ -93,13 +76,8 @@ class CRM_Price_BAO_PriceFieldValue extends CRM_Price_DAO_PriceFieldValue {
       $fieldValues = ['price_field_id' => CRM_Utils_Array::value('price_field_id', $params, 0)];
       $params['weight'] = CRM_Utils_Weight::updateOtherWeights('CRM_Price_DAO_PriceFieldValue', $oldWeight, $params['weight'], $fieldValues);
     }
-    else {
-      if (!$id) {
-        CRM_Core_DAO::setCreateDefaults($params, self::getDefaults());
-        if (empty($params['name'])) {
-          $params['name'] = CRM_Utils_String::munge(CRM_Utils_Array::value('label', $params), '_', 64);
-        }
-      }
+    elseif (!$id) {
+      CRM_Core_DAO::setCreateDefaults($params, self::getDefaults());
     }
 
     $financialType = $params['financial_type_id'] ?? NULL;
@@ -110,7 +88,8 @@ class CRM_Price_BAO_PriceFieldValue extends CRM_Price_DAO_PriceFieldValue {
     if (!empty($financialType) && !array_key_exists($financialType, $financialTypes) && $params['is_active']) {
       throw new CRM_Core_Exception("Financial Type for Price Field Option is either disabled or does not exist");
     }
-    return self::add($params, $ids);
+    $params['id'] = $id;
+    return self::add($params);
   }
 
   /**
diff --git a/civicrm/CRM/Price/BAO/PriceSet.php b/civicrm/CRM/Price/BAO/PriceSet.php
index 7983cc531b..dcb362b67b 100644
--- a/civicrm/CRM/Price/BAO/PriceSet.php
+++ b/civicrm/CRM/Price/BAO/PriceSet.php
@@ -71,6 +71,7 @@ class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet {
     $priceSetBAO->save();
 
     CRM_Utils_Hook::post($hook, 'PriceSet', $priceSetBAO->id, $priceSetBAO);
+    unset(\Civi::$statics['CRM_Core_PseudoConstant']);
     return $priceSetBAO;
   }
 
@@ -113,26 +114,22 @@ class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet {
    *
    */
   public static function getDefaultPriceSet($entity = 'contribution') {
-    if (!empty(self::$_defaultPriceSet[$entity])) {
-      return self::$_defaultPriceSet[$entity];
-    }
-    $entityName = 'default_contribution_amount';
-    if ($entity == 'membership') {
-      $entityName = 'default_membership_type_amount';
+    if (isset(\Civi::$statics[__CLASS__][$entity])) {
+      return \Civi::$statics[__CLASS__][$entity];
     }
+    $priceSetName = ($entity === 'membership') ? 'default_membership_type_amount' : 'default_contribution_amount';
 
     $sql = "
 SELECT      ps.id AS setID, pfv.price_field_id AS priceFieldID, pfv.id AS priceFieldValueID, pfv.name, pfv.label, pfv.membership_type_id, pfv.amount, pfv.financial_type_id
 FROM        civicrm_price_set ps
 LEFT JOIN   civicrm_price_field pf ON pf.`price_set_id` = ps.id
 LEFT JOIN   civicrm_price_field_value pfv ON pfv.price_field_id = pf.id
-WHERE       ps.name = '{$entityName}'
+WHERE       ps.name = '{$priceSetName}'
 ";
 
     $dao = CRM_Core_DAO::executeQuery($sql);
-    self::$_defaultPriceSet[$entity] = [];
     while ($dao->fetch()) {
-      self::$_defaultPriceSet[$entity][$dao->priceFieldValueID] = [
+      \Civi::$statics[__CLASS__][$entity][$dao->priceFieldValueID] = [
         'setID' => $dao->setID,
         'priceFieldID' => $dao->priceFieldID,
         'name' => $dao->name,
@@ -144,7 +141,7 @@ WHERE       ps.name = '{$entityName}'
       ];
     }
 
-    return self::$_defaultPriceSet[$entity];
+    return \Civi::$statics[__CLASS__][$entity];
   }
 
   /**
@@ -1171,6 +1168,7 @@ WHERE  id = %1";
     $copy->save();
 
     CRM_Utils_Hook::copy('Set', $copy);
+    unset(\Civi::$statics['CRM_Core_PseudoConstant']);
     return $copy;
   }
 
diff --git a/civicrm/CRM/Price/DAO/PriceField.php b/civicrm/CRM/Price/DAO/PriceField.php
index 56dc69ac28..987ae6614f 100644
--- a/civicrm/CRM/Price/DAO/PriceField.php
+++ b/civicrm/CRM/Price/DAO/PriceField.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Price/PriceField.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:88307b88d5be27887068a778e663b0a2)
+ * (GenCodeChecksum:691cc70f15386dd0c2cd4ab63f9798af)
  */
 
 /**
@@ -204,6 +204,7 @@ class CRM_Price_DAO_PriceField extends CRM_Core_DAO {
             'table' => 'civicrm_price_set',
             'keyColumn' => 'id',
             'labelColumn' => 'title',
+            'nameColumn' => 'name',
           ],
         ],
         'name' => [
diff --git a/civicrm/CRM/Price/DAO/PriceFieldValue.php b/civicrm/CRM/Price/DAO/PriceFieldValue.php
index 15ab9471e6..058ddf7a6f 100644
--- a/civicrm/CRM/Price/DAO/PriceFieldValue.php
+++ b/civicrm/CRM/Price/DAO/PriceFieldValue.php
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Price/PriceFieldValue.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:a5371a5b399a3e0730bc216886ce5efe)
+ * (GenCodeChecksum:47c904125e3421dde14b5fcd9b8a6f16)
  */
 
 /**
@@ -217,6 +217,7 @@ class CRM_Price_DAO_PriceFieldValue extends CRM_Core_DAO {
           'type' => CRM_Utils_Type::T_STRING,
           'title' => ts('Name'),
           'description' => ts('Price field option name'),
+          'required' => TRUE,
           'maxlength' => 255,
           'size' => CRM_Utils_Type::HUGE,
           'where' => 'civicrm_price_field_value.name',
@@ -233,6 +234,7 @@ class CRM_Price_DAO_PriceFieldValue extends CRM_Core_DAO {
           'type' => CRM_Utils_Type::T_STRING,
           'title' => ts('Label'),
           'description' => ts('Price field option label'),
+          'required' => TRUE,
           'maxlength' => 255,
           'size' => CRM_Utils_Type::HUGE,
           'where' => 'civicrm_price_field_value.label',
diff --git a/civicrm/CRM/Price/Page/Field.php b/civicrm/CRM/Price/Page/Field.php
index 3563bd3dcc..20c55449a6 100644
--- a/civicrm/CRM/Price/Page/Field.php
+++ b/civicrm/CRM/Price/Page/Field.php
@@ -111,7 +111,7 @@ class CRM_Price_Page_Field extends CRM_Core_Page {
 
     // display taxTerm for priceFields
     $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-    $taxTerm = $invoiceSettings['tax_term'] ?? NULL;
+    $taxTerm = Civi::settings()->get('tax_term');
     $invoicing = $invoiceSettings['invoicing'] ?? NULL;
     $getTaxDetails = FALSE;
     $taxRate = CRM_Core_PseudoConstant::getTaxRates();
diff --git a/civicrm/CRM/Price/Page/Option.php b/civicrm/CRM/Price/Page/Option.php
index d477b90b83..a8ea081f50 100644
--- a/civicrm/CRM/Price/Page/Option.php
+++ b/civicrm/CRM/Price/Page/Option.php
@@ -130,7 +130,7 @@ class CRM_Price_Page_Option extends CRM_Core_Page {
     $taxRate = CRM_Core_PseudoConstant::getTaxRates();
     // display taxTerm for priceFields
     $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-    $taxTerm = $invoiceSettings['tax_term'] ?? NULL;
+    $taxTerm = Civi::settings()->get('tax_term');
     $invoicing = $invoiceSettings['invoicing'] ?? NULL;
     $getTaxDetails = FALSE;
     foreach ($customOption as $id => $values) {
@@ -160,12 +160,6 @@ class CRM_Price_Page_Option extends CRM_Core_Page {
           $action -= CRM_Core_Action::DISABLE;
         }
       }
-      if (!empty($customOption[$id]['is_default'])) {
-        $customOption[$id]['is_default'] = '<img src="' . $config->resourceBase . 'i/check.gif" />';
-      }
-      else {
-        $customOption[$id]['is_default'] = '';
-      }
       $customOption[$id]['order'] = $customOption[$id]['weight'];
       $customOption[$id]['action'] = CRM_Core_Action::formLink(self::actionLinks(), $action,
         [
diff --git a/civicrm/CRM/Queue/ErrorPolicy.php b/civicrm/CRM/Queue/ErrorPolicy.php
index 110e07bc91..f7bc774add 100644
--- a/civicrm/CRM/Queue/ErrorPolicy.php
+++ b/civicrm/CRM/Queue/ErrorPolicy.php
@@ -13,12 +13,12 @@
  * To ensure that PHP errors or unhandled exceptions are reported in JSON
  * format, wrap this around your code. For example:
  *
- * @code
+ * ```
  * $errorContainer = new CRM_Queue_ErrorPolicy();
  * $errorContainer->call(function() {
  *    ...include some files, do some work, etc...
  * });
- * @endcode
+ * ```
  *
  * Note: Most of the code in this class is pretty generic vis-a-vis error
  * handling -- except for 'reportError', whose message format is only
diff --git a/civicrm/CRM/Queue/Service.php b/civicrm/CRM/Queue/Service.php
index c86f790ad4..60d2521cba 100644
--- a/civicrm/CRM/Queue/Service.php
+++ b/civicrm/CRM/Queue/Service.php
@@ -15,7 +15,7 @@
  * different queue-providers may store the queue content in different
  * ways (in memory, in SQL, or in an external service).
  *
- * @code
+ * ```
  * $queue = CRM_Queue_Service::singleton()->create(array(
  *   'type' => 'interactive',
  *   'name' => 'upgrade-tasks',
@@ -31,7 +31,7 @@
  *     $queue->releaseItem($item);
  *   }
  * }
- * @endcode
+ * ```
  */
 class CRM_Queue_Service {
 
diff --git a/civicrm/CRM/Report/Form.php b/civicrm/CRM/Report/Form.php
index abbd87fd93..f09de2def6 100644
--- a/civicrm/CRM/Report/Form.php
+++ b/civicrm/CRM/Report/Form.php
@@ -139,11 +139,6 @@ class CRM_Report_Form extends CRM_Core_Form {
    */
   protected $_groupFilter = FALSE;
 
-  /**
-   * Required for civiexportexcel.
-   */
-  public $supportsExportExcel = TRUE;
-
   /**
    * Has the report been optimised for group filtering.
    *
@@ -1440,7 +1435,7 @@ class CRM_Report_Form extends CRM_Core_Form {
     if (!CRM_Core_Permission::check('view report sql')) {
       return;
     }
-    $ignored_output_modes = ['pdf', 'csv', 'print', 'excel2007'];
+    $ignored_output_modes = ['pdf', 'csv', 'print'];
     if (in_array($this->_outputMode, $ignored_output_modes)) {
       return;
     }
@@ -2862,11 +2857,6 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
       $this->_absoluteUrl = TRUE;
       $this->addPaging = FALSE;
     }
-    elseif ($this->_outputMode == 'excel2007') {
-      $printOnly = TRUE;
-      $this->_absoluteUrl = TRUE;
-      $this->addPaging = FALSE;
-    }
     elseif ($this->_outputMode == 'copy' && $this->_criteriaForm) {
       $this->_createNew = TRUE;
     }
@@ -3501,9 +3491,6 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
     elseif ($this->_outputMode == 'csv') {
       CRM_Report_Utils_Report::export2csv($this, $rows);
     }
-    elseif ($this->_outputMode == 'excel2007') {
-      CRM_CiviExportExcel_Utils_Report::export2excel2007($this, $rows);
-    }
     elseif ($this->_outputMode == 'group') {
       $group = $this->_params['groups'];
       $this->add2group($group);
diff --git a/civicrm/CRM/Report/Form/Campaign/SurveyDetails.php b/civicrm/CRM/Report/Form/Campaign/SurveyDetails.php
index a5496a5469..c3f9967b4e 100644
--- a/civicrm/CRM/Report/Form/Campaign/SurveyDetails.php
+++ b/civicrm/CRM/Report/Form/Campaign/SurveyDetails.php
@@ -42,7 +42,7 @@ class CRM_Report_Form_Campaign_SurveyDetails extends CRM_Report_Form {
    * say Q1, Q2 instead of the full title - to save space.
    * @var array
    */
-  private $_columnTitleOverrides = array();
+  private $_columnTitleOverrides = [];
 
   /**
    */
@@ -52,7 +52,7 @@ class CRM_Report_Form_Campaign_SurveyDetails extends CRM_Report_Form {
   public function __construct() {
     //filter options for survey activity status.
     $responseStatus = array('' => '- Any -');
-    self::$_surveyRespondentStatus = array();
+    self::$_surveyRespondentStatus = [];
     $activityStatus = CRM_Core_PseudoConstant::activityStatus('name');
     if ($statusId = array_search('Scheduled', $activityStatus)) {
       $responseStatus[$statusId] = ts('Reserved');
@@ -64,10 +64,10 @@ class CRM_Report_Form_Campaign_SurveyDetails extends CRM_Report_Form {
     }
 
     $optionGroups = CRM_Campaign_BAO_Survey::getResultSets('name');
-    $resultOptions = array();
+    $resultOptions = [];
     foreach ($optionGroups as $gid => $name) {
       if ($name) {
-        $value = array();
+        $value = [];
         $value = CRM_Core_OptionGroup::values($name);
         if (!empty($value)) {
           $value = array_combine($value, $value);
@@ -221,12 +221,12 @@ class CRM_Report_Form_Campaign_SurveyDetails extends CRM_Report_Form {
   }
 
   public function select() {
-    $select = array();
+    $select = [];
 
     //add the survey response fields.
     $this->_addSurveyResponseColumns();
 
-    $this->_columnHeaders = array();
+    $this->_columnHeaders = [];
     foreach ($this->_columns as $tableName => $table) {
       if (!isset($table['fields'])) {
         continue;
@@ -302,7 +302,7 @@ class CRM_Report_Form_Campaign_SurveyDetails extends CRM_Report_Form {
   }
 
   public function where() {
-    $clauses = array();
+    $clauses = [];
     foreach ($this->_columns as $tableName => $table) {
       if (array_key_exists('filters', $table)) {
         foreach ($table['filters'] as $fieldName => $field) {
@@ -376,9 +376,9 @@ class CRM_Report_Form_Campaign_SurveyDetails extends CRM_Report_Form {
       return $coverSheet;
     }
 
-    $fieldIds = array();
+    $fieldIds = [];
 
-    $surveyResponseFields = array();
+    $surveyResponseFields = [];
     foreach ($this->_columns as $tableName => $values) {
       if (!is_array($values['fields'])) {
         continue;
@@ -408,7 +408,7 @@ INNER JOIN  civicrm_option_value val ON ( val.option_group_id = field.option_gro
      WHERE  field.id IN (' . implode(' , ', $fieldIds) . ' )
   Order By  val.weight';
       $field = CRM_Core_DAO::executeQuery($query);
-      $options = array();
+      $options = [];
       while ($field->fetch()) {
         $name = "custom_{$field->id}";
         $surveyResponseFields[$name]['options'][$field->value] = $field->label;
@@ -426,7 +426,7 @@ INNER JOIN  civicrm_option_value val ON ( val.option_group_id = survey.result_id
      WHERE  survey.id IN ( ' . implode(' , ', array_values($surveyIds)) . ' )
   Order By  val.weight';
     $resultSet = CRM_Core_DAO::executeQuery($query);
-    $surveyResultFields = array();
+    $surveyResultFields = [];
     while ($resultSet->fetch()) {
       $surveyResultFields[$resultSet->id]['title'] = $resultSet->title;
       $surveyResultFields[$resultSet->id]['options'][$resultSet->value] = $resultSet->label;
@@ -518,7 +518,7 @@ INNER JOIN  civicrm_survey survey ON ( survey.result_id = grp.id )
   Order By  val.weight';
 
     $result = CRM_Core_DAO::executeQuery($query);
-    $resultSet = array();
+    $resultSet = [];
     while ($result->fetch()) {
       $resultSet[$result->id][$result->value] = $result->label;
     }
@@ -531,7 +531,7 @@ INNER JOIN  civicrm_survey survey ON ( survey.result_id = grp.id )
       if (!empty($row['civicrm_activity_survey_id'])) {
         $surveyId = $row['civicrm_activity_survey_id'];
       }
-      $result = CRM_Utils_Array::value($surveyId, $resultSet, array());
+      $result = CRM_Utils_Array::value($surveyId, $resultSet, []);
       $resultLabel = $row['civicrm_activity_result'] ?? NULL;
       if ($respondentStatus == 'Reserved') {
         $row['civicrm_activity_result'] = implode(' | ', array_keys($result));
@@ -556,8 +556,8 @@ INNER JOIN  civicrm_survey survey ON ( survey.result_id = grp.id )
       return;
     }
 
-    $surveyResponseFields = array();
-    $surveyResponseFieldIds = array();
+    $surveyResponseFields = [];
+    $surveyResponseFieldIds = [];
     foreach ($this->_columns as $tableName => $values) {
       if (!is_array($values['fields'])) {
         continue;
@@ -610,8 +610,8 @@ INNER JOIN  civicrm_custom_group cg ON ( cg.id = cf.custom_group_id )
      WHERE  cf.id IN ( ' . implode(' , ', $surveyResponseFieldIds) . ' )
   Order By  ov.weight';
 
-    $responseFields = array();
-    $fieldValueMap = array();
+    $responseFields = [];
+    $fieldValueMap = [];
     $properties = array(
       'id',
       'data_type',
@@ -656,7 +656,7 @@ INNER JOIN  civicrm_custom_group cg ON ( cg.id = cf.custom_group_id )
           in_array($this->_outputMode, array('print', 'pdf'))
         ) {
           $optGrpId = $responseFields[$name]['option_group_id'] ?? NULL;
-          $options = CRM_Utils_Array::value($optGrpId, $fieldValueMap, array());
+          $options = CRM_Utils_Array::value($optGrpId, $fieldValueMap, []);
           $value = implode(' | ', array_keys($options));
         }
         else {
@@ -678,7 +678,7 @@ INNER JOIN  civicrm_custom_group cg ON ( cg.id = cf.custom_group_id )
       return;
     }
 
-    $responseFields = array();
+    $responseFields = [];
     foreach ($surveyIds as $surveyId) {
       $responseFields += CRM_Campaign_BAO_Survey::getSurveyResponseFields($surveyId);
       $this->_surveyResponseFields = $responseFields;
@@ -702,7 +702,7 @@ INNER JOIN  civicrm_custom_group cg ON ( cg.id = cf.custom_group_id )
         $this->_locationBasedPhoneField = TRUE;
       }
     }
-    $responseFieldIds = array();
+    $responseFieldIds = [];
     foreach (array_keys($responseFields) as $key) {
       $cfId = CRM_Core_BAO_CustomField::getKeyID($key);
       if ($cfId) {
diff --git a/civicrm/CRM/Report/Form/Contact/Summary.php b/civicrm/CRM/Report/Form/Contact/Summary.php
index 485f4d814f..c920b08f7d 100644
--- a/civicrm/CRM/Report/Form/Contact/Summary.php
+++ b/civicrm/CRM/Report/Form/Contact/Summary.php
@@ -134,7 +134,7 @@ class CRM_Report_Form_Contact_Summary extends CRM_Report_Form {
    * @return array
    */
   public static function formRule($fields, $files, $self) {
-    $errors = $grouping = array();
+    $errors = $grouping = [];
     return $errors;
   }
 
@@ -156,7 +156,7 @@ class CRM_Report_Form_Contact_Summary extends CRM_Report_Form {
 
     $sql = $this->buildQuery(TRUE);
 
-    $rows = $graphRows = array();
+    $rows = $graphRows = [];
     $this->buildRows($sql, $rows);
 
     $this->formatDisplay($rows);
diff --git a/civicrm/CRM/Report/Form/Contribute/Detail.php b/civicrm/CRM/Report/Form/Contribute/Detail.php
index 9d4c12d22a..73c1369b3a 100644
--- a/civicrm/CRM/Report/Form/Contribute/Detail.php
+++ b/civicrm/CRM/Report/Form/Contribute/Detail.php
@@ -640,7 +640,8 @@ UNION ALL
     $contributionTypes = CRM_Contribute_PseudoConstant::financialType();
     $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'label');
     $paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
-    $contributionPages = CRM_Contribute_PseudoConstant::contributionPage();
+    // We pass in TRUE as 2nd param so that even disabled contribution page titles are returned and replaced in the report
+    $contributionPages = CRM_Contribute_PseudoConstant::contributionPage(NULL, TRUE);
     $batches = CRM_Batch_BAO_Batch::getBatches();
     foreach ($rows as $rowNum => $row) {
       if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
diff --git a/civicrm/CRM/Report/Form/Contribute/Repeat.php b/civicrm/CRM/Report/Form/Contribute/Repeat.php
index 7b66f28d6d..aa4846c532 100644
--- a/civicrm/CRM/Report/Form/Contribute/Repeat.php
+++ b/civicrm/CRM/Report/Form/Contribute/Repeat.php
@@ -244,7 +244,7 @@ class CRM_Report_Form_Contribute_Repeat extends CRM_Report_Form {
    * Override parent select for reasons someone will someday make sense of & document.
    */
   public function select() {
-    $select = array();
+    $select = [];
     $append = NULL;
     // since contact fields not related to financial type
     if (array_key_exists('financial_type', $this->_params['group_bys']) ||
@@ -409,7 +409,7 @@ LEFT JOIN $this->tempTableRepeat2 {$this->_aliases['civicrm_contribution']}2
     }
 
     if (!$this->_amountClauseWithAND) {
-      $amountClauseWithAND = array();
+      $amountClauseWithAND = [];
       if (!empty($clauses['total_amount1'])) {
         $amountClauseWithAND[] = str_replace("{$this->_aliases['civicrm_contribution']}.total_amount",
           "{$this->_aliases['civicrm_contribution']}1.total_amount_sum", $clauses['total_amount1']);
@@ -478,7 +478,7 @@ LEFT JOIN $this->tempTableRepeat2 {$this->_aliases['civicrm_contribution']}2
    */
   public static function formRule($fields, $files, $self) {
 
-    $errors = $checkDate = $errorCount = array();
+    $errors = $checkDate = $errorCount = [];
 
     $rules = array(
       'id' => array(
@@ -558,7 +558,7 @@ LEFT JOIN $this->tempTableRepeat2 {$this->_aliases['civicrm_contribution']}2
       foreach ($fields['fields'] as $fld_id => $value) {
         if (!($fld_id == 'total_amount1') && !($fld_id == 'total_amount2') && !(substr($fld_id, 0, 7) === "custom_")) {
           $found = FALSE;
-          $invlidGroups = array();
+          $invlidGroups = [];
           foreach ($fields['group_bys'] as $grp_id => $val) {
             $validFields = $rules[$grp_id];
             if (in_array($fld_id, $validFields)) {
@@ -671,7 +671,7 @@ LEFT JOIN $this->tempTableRepeat2 {$this->_aliases['civicrm_contribution']}2
     $sql = "{$this->_select} {$this->_from} {$this->_where}";
     $dao = $this->executeReportQuery($sql);
     //store contributions in array 'contact_sums' for comparison
-    $contact_sums = array();
+    $contact_sums = [];
     while ($dao->fetch()) {
       $contact_sums[$dao->contact_civireport_id] = array(
         'contribution1_total_amount_sum' => $dao->contribution1_total_amount_sum,
@@ -753,7 +753,7 @@ GROUP BY    currency
 ";
     $dao = $this->executeReportQuery($sql);
 
-    $amount = $average = $amount2 = $average2 = array();
+    $amount = $average = $amount2 = $average2 = [];
     $count = $count2 = 0;
     while ($dao->fetch()) {
       if ($dao->amount) {
@@ -824,7 +824,7 @@ GROUP BY    currency
     $count = 0;
     $sql = "{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy} {$this->_orderBy} {$this->_limit}";
     $dao = $this->executeReportQuery($sql);
-    $rows = array();
+    $rows = [];
     while ($dao->fetch()) {
       foreach ($this->_columnHeaders as $key => $value) {
         $rows[$count][$key] = $dao->$key;
diff --git a/civicrm/CRM/Report/Form/Event/ParticipantListing.php b/civicrm/CRM/Report/Form/Event/ParticipantListing.php
index 50175c9aaf..c465fb6f85 100644
--- a/civicrm/CRM/Report/Form/Event/ParticipantListing.php
+++ b/civicrm/CRM/Report/Form/Event/ParticipantListing.php
@@ -404,7 +404,7 @@ WHERE ce.entity_table = 'civicrm_event'
 ORDER BY  cv.label
 ";
     $dao = CRM_Core_DAO::executeQuery($query);
-    $elements = array();
+    $elements = [];
     while ($dao->fetch()) {
       $elements[$dao->id] = "$dao->label\n";
     }
@@ -417,8 +417,8 @@ ORDER BY  cv.label
   }
 
   public function select() {
-    $select = array();
-    $this->_columnHeaders = array();
+    $select = [];
+    $this->_columnHeaders = [];
 
     //add blank column at the Start
     if (array_key_exists('options', $this->_params) &&
@@ -475,7 +475,7 @@ ORDER BY  cv.label
    * @return array
    */
   public static function formRule($fields, $files, $self) {
-    $errors = $grouping = array();
+    $errors = $grouping = [];
     return $errors;
   }
 
@@ -530,7 +530,7 @@ ORDER BY  cv.label
   }
 
   public function where() {
-    $clauses = array();
+    $clauses = [];
     foreach ($this->_columns as $tableName => $table) {
       if (array_key_exists('filters', $table)) {
         foreach ($table['filters'] as $fieldName => $field) {
@@ -673,7 +673,7 @@ ORDER BY  cv.label
         $roleId = $row['civicrm_participant_role_id'];
         if ($roleId) {
           $roles = explode(CRM_Core_DAO::VALUE_SEPARATOR, $roleId);
-          $roleId = array();
+          $roleId = [];
           foreach ($roles as $role) {
             $roleId[$role] = CRM_Event_PseudoConstant::participantRole($role, FALSE);
           }
diff --git a/civicrm/CRM/Report/Utils/Report.php b/civicrm/CRM/Report/Utils/Report.php
index 627c2a97c7..e2ca8de213 100644
--- a/civicrm/CRM/Report/Utils/Report.php
+++ b/civicrm/CRM/Report/Utils/Report.php
@@ -251,7 +251,7 @@ WHERE  inst.report_id = %1";
         $value = $row[$v] ?? NULL;
         if (isset($value)) {
           // Remove HTML, unencode entities, and escape quotation marks.
-          $value = str_replace('"', '""', html_entity_decode(strip_tags($value)));
+          $value = str_replace('"', '""', html_entity_decode(strip_tags($value), ENT_QUOTES | ENT_HTML401));
 
           if (CRM_Utils_Array::value('type', $form->_columnHeaders[$v]) & 4) {
             if (CRM_Utils_Array::value('group_by', $form->_columnHeaders[$v]) == 'MONTH' ||
diff --git a/civicrm/CRM/Report/xml/Menu/Report.xml b/civicrm/CRM/Report/xml/Menu/Report.xml
index 2e262817d5..725bbf8d63 100644
--- a/civicrm/CRM/Report/xml/Menu/Report.xml
+++ b/civicrm/CRM/Report/xml/Menu/Report.xml
@@ -51,7 +51,6 @@
      <desc>Component wise listing of all available templates</desc>
      <access_arguments>access CiviCRM,access CiviReport</access_arguments>
      <adminGroup>CiviReport</adminGroup>
-     <icon>admin/small/report_template.gif</icon>
   </item>
   <item>
      <path>civicrm/admin/report/options/report_template</path>
@@ -60,7 +59,6 @@
      <desc>Browse, Edit and Delete the Report templates.</desc>
      <access_arguments>access CiviCRM,access CiviReport</access_arguments>
      <adminGroup>CiviReport</adminGroup>
-     <icon>admin/small/template.png</icon>
   </item>
   <item>
      <path>civicrm/admin/report/list</path>
@@ -68,6 +66,5 @@
      <page_callback>CRM_Report_Page_InstanceList</page_callback>
      <desc>Browse existing report, change report criteria and settings.</desc>
      <adminGroup>CiviReport</adminGroup>
-     <icon>admin/small/report_list.gif</icon>
   </item>
 </menu>
diff --git a/civicrm/CRM/SMS/Page/Provider.php b/civicrm/CRM/SMS/Page/Provider.php
index f8f4ad4e37..9122dca44e 100644
--- a/civicrm/CRM/SMS/Page/Provider.php
+++ b/civicrm/CRM/SMS/Page/Provider.php
@@ -112,7 +112,7 @@ class CRM_SMS_Page_Provider extends CRM_Core_Page_Basic {
    */
   public function browse($action = NULL) {
     $providers = CRM_SMS_BAO_Provider::getProviders();
-    $rows = array();
+    $rows = [];
     foreach ($providers as $provider) {
       $action = array_sum(array_keys($this->links()));
       // update enable/disable links.
diff --git a/civicrm/CRM/SMS/Provider.php b/civicrm/CRM/SMS/Provider.php
index 387092876d..896302ea13 100644
--- a/civicrm/CRM/SMS/Provider.php
+++ b/civicrm/CRM/SMS/Provider.php
@@ -22,7 +22,7 @@ abstract class CRM_SMS_Provider {
    *
    * @var object
    */
-  static private $_singleton = array();
+  static private $_singleton = [];
   const MAX_SMS_CHAR = 460;
 
   /**
@@ -34,7 +34,7 @@ abstract class CRM_SMS_Provider {
    * @return object
    * @throws CRM_Core_Exception
    */
-  public static function &singleton($providerParams = array(), $force = FALSE) {
+  public static function &singleton($providerParams = [], $force = FALSE) {
     $mailingID = $providerParams['mailing_id'] ?? NULL;
     $providerID = $providerParams['provider_id'] ?? NULL;
     $providerName = $providerParams['provider'] ?? NULL;
@@ -125,7 +125,7 @@ abstract class CRM_SMS_Provider {
    * @return self|null|object
    * @throws CRM_Core_Exception
    */
-  public function createActivity($apiMsgID, $message, $headers = array(), $jobID = NULL, $userID = NULL) {
+  public function createActivity($apiMsgID, $message, $headers = [], $jobID = NULL, $userID = NULL) {
     if ($jobID) {
       $sql = "
 SELECT scheduled_id FROM civicrm_mailing m
diff --git a/civicrm/CRM/Upgrade/Form.php b/civicrm/CRM/Upgrade/Form.php
index 10c2b54253..e1f7bcd2de 100644
--- a/civicrm/CRM/Upgrade/Form.php
+++ b/civicrm/CRM/Upgrade/Form.php
@@ -10,11 +10,7 @@
  */
 
 /**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * Class CRM_Upgrade_Form
  */
 class CRM_Upgrade_Form extends CRM_Core_Form {
   const QUEUE_NAME = 'CRM_Upgrade';
diff --git a/civicrm/CRM/Upgrade/Incremental/php/FiveTwentySeven.php b/civicrm/CRM/Upgrade/Incremental/php/FiveTwentySeven.php
new file mode 100644
index 0000000000..c37d150605
--- /dev/null
+++ b/civicrm/CRM/Upgrade/Incremental/php/FiveTwentySeven.php
@@ -0,0 +1,109 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Upgrade logic for FiveTwentySeven */
+class CRM_Upgrade_Incremental_php_FiveTwentySeven extends CRM_Upgrade_Incremental_Base {
+
+  /**
+   * Compute any messages which should be displayed beforeupgrade.
+   *
+   * Note: This function is called iteratively for each upcoming
+   * revision to the database.
+   *
+   * @param string $preUpgradeMessage
+   * @param string $rev
+   *   a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
+   * @param null $currentVer
+   */
+  public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
+    // Example: Generate a pre-upgrade message.
+    // if ($rev == '5.12.34') {
+    //   $preUpgradeMessage .= '<p>' . ts('A new permission, "%1", has been added. This permission is now used to control access to the Manage Tags screen.', array(1 => ts('manage tags'))) . '</p>';
+    // }
+    $preUpgradeMessage .= '<p>' . ts('Starting with version 5.28.0, CiviCRM will
+      require the PHP Internationalization extension (PHP-Intl).  In preparation
+      for this, the system check will show a warning beginning in 5.27.0 if your
+      site lacks this extension.') . '</p>';
+  }
+
+  /**
+   * Compute any messages which should be displayed after upgrade.
+   *
+   * @param string $postUpgradeMessage
+   *   alterable.
+   * @param string $rev
+   *   an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
+   */
+  public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
+    // Example: Generate a post-upgrade message.
+    // if ($rev == '5.12.34') {
+    //   $postUpgradeMessage .= '<br /><br />' . ts("By default, CiviCRM now disables the ability to import directly from SQL. To use this feature, you must explicitly grant permission 'import SQL datasource'.");
+    // }
+  }
+
+  /*
+   * Important! All upgrade functions MUST add a 'runSql' task.
+   * Uncomment and use the following template for a new upgrade version
+   * (change the x in the function name):
+   */
+
+  /**
+   * Upgrade function.
+   *
+   * @param string $rev
+   */
+  public function upgrade_5_27_alpha1($rev) {
+    // Add column before running sql which populates the column's values
+    $this->addTask('Add serialize column to civicrm_custom_field', 'addColumn',
+      'civicrm_custom_field', 'serialize', "int unsigned DEFAULT NULL COMMENT 'Serialization method - a non-null value indicates a multi-valued field.'"
+    );
+    $this->addTask('Make the label field required on price field value', 'priceFieldValueLabelRequired');
+    $this->addTask('Make the name field required on civicrm_membership_type', 'nameMembershipTypeRequired');
+    $this->addTask('Rebuild Multilingal Schema', 'rebuildMultilingalSchema', '5.27.alpha1');
+    $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
+  }
+
+  public function priceFieldValueLabelRequired($ctx) {
+    $domain = new CRM_Core_DAO_Domain();
+    $domain->find(TRUE);
+    if ($domain->locales) {
+      $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
+      foreach ($locales as $locale) {
+        CRM_Core_DAO::executeQuery("UPDATE civicrm_price_field_value SET label_{$locale} = '' WHERE label_{$locale} IS NULL", [], TRUE, NULL, FALSE, FALSE);
+        CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_price_field_value CHANGE `label_{$locale}` `label_{$locale}` varchar(255) NOT NULL   COMMENT 'Price field option label'", [], TRUE, NULL, FALSE, FALSE);
+      }
+    }
+    else {
+      CRM_Core_DAO::executeQuery("UPDATE civicrm_price_field_value SET label = '' WHERE label IS NULL");
+      CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_price_field_value CHANGE `label` `label` varchar(255) NOT NULL   COMMENT 'Price field option label'", [], TRUE, NULL, FALSE, FALSE);
+    }
+    return TRUE;
+  }
+
+  public function nameMembershipTypeRequired($ctx) {
+    $domain = new CRM_Core_DAO_Domain();
+    $domain->find(TRUE);
+    if ($domain->locales) {
+      $locales = explode(CRM_Core_DAO::VALUE_SEPARATOR, $domain->locales);
+      foreach ($locales as $locale) {
+        CRM_Core_DAO::executeQuery("UPDATE civicrm_membership_type SET name_{$locale} = '' WHERE name_{$locale} IS NULL", [], TRUE, NULL, FALSE, FALSE);
+        CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_membership_type CHANGE `name_{$locale}` `name_{$locale}` varchar(128) NOT NULL   COMMENT 'Name of Membership Type'", [], TRUE, NULL, FALSE, FALSE);
+      }
+    }
+    else {
+      CRM_Core_DAO::executeQuery("UPDATE civicrm_membership_type SET name = '' WHERE name IS NULL");
+      CRM_Core_DAO::executeQuery("ALTER TABLE civicrm_membership_type CHANGE `name` `name` varchar(128) NOT NULL   COMMENT 'Name of Membership Type'", [], TRUE, NULL, FALSE, FALSE);
+    }
+    return TRUE;
+  }
+
+}
diff --git a/civicrm/CRM/Upgrade/Incremental/sql/5.26.0.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/5.26.0.mysql.tpl
deleted file mode 100644
index 481ff00a5a..0000000000
--- a/civicrm/CRM/Upgrade/Incremental/sql/5.26.0.mysql.tpl
+++ /dev/null
@@ -1 +0,0 @@
-{* file to handle db changes in 5.26.0 during upgrade *}
diff --git a/civicrm/CRM/Upgrade/Incremental/sql/5.26.2.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/5.26.2.mysql.tpl
deleted file mode 100644
index 614c9d2d2b..0000000000
--- a/civicrm/CRM/Upgrade/Incremental/sql/5.26.2.mysql.tpl
+++ /dev/null
@@ -1 +0,0 @@
-{* file to handle db changes in 5.26.2 during upgrade *}
diff --git a/civicrm/CRM/Upgrade/Incremental/sql/5.27.0.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/5.27.0.mysql.tpl
new file mode 100644
index 0000000000..a39da32233
--- /dev/null
+++ b/civicrm/CRM/Upgrade/Incremental/sql/5.27.0.mysql.tpl
@@ -0,0 +1 @@
+{* file to handle db changes in 5.27.0 during upgrade *}
diff --git a/civicrm/CRM/Upgrade/Incremental/sql/5.26.1.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/5.27.alpha1.mysql.tpl
similarity index 60%
rename from civicrm/CRM/Upgrade/Incremental/sql/5.26.1.mysql.tpl
rename to civicrm/CRM/Upgrade/Incremental/sql/5.27.alpha1.mysql.tpl
index e75b095255..b2364e975c 100644
--- a/civicrm/CRM/Upgrade/Incremental/sql/5.26.1.mysql.tpl
+++ b/civicrm/CRM/Upgrade/Incremental/sql/5.27.alpha1.mysql.tpl
@@ -1,5 +1,10 @@
 {* file to handle db changes in 5.27.alpha1 during upgrade *}
 
+UPDATE civicrm_custom_field SET serialize = 1, html_type = REPLACE(html_type, 'Multi-', '')
+WHERE html_type LIKE 'Multi-%' OR html_type = 'CheckBox';
+
+ALTER TABLE `civicrm_contribution_recur` CHANGE `amount` `amount` DECIMAL( 20,2 ) COMMENT 'Amount to be collected (including any sales tax) by payment processor each recurrence.';
+
 -- dev/core/-/issues/1794
 ALTER TABLE `civicrm_custom_group` CHANGE `collapse_adv_display` `collapse_adv_display` TINYINT(4) UNSIGNED NULL DEFAULT '0' COMMENT 'Will this group be in collapsed or expanded mode on advanced search display ?';
 ALTER TABLE `civicrm_custom_group` CHANGE `collapse_display` `collapse_display` TINYINT(4) UNSIGNED NULL DEFAULT '0' COMMENT 'Will this group be in collapsed or expanded mode on initial display ?';
diff --git a/civicrm/CRM/Upgrade/Incremental/sql/5.27.beta1.mysql.tpl b/civicrm/CRM/Upgrade/Incremental/sql/5.27.beta1.mysql.tpl
new file mode 100644
index 0000000000..699d61878c
--- /dev/null
+++ b/civicrm/CRM/Upgrade/Incremental/sql/5.27.beta1.mysql.tpl
@@ -0,0 +1,8 @@
+{* file to handle db changes in 5.27.beta1 during upgrade *}
+ALTER TABLE civicrm_option_value MODIFY COLUMN `filter` int unsigned DEFAULT 0 COMMENT 'Bitwise logic can be used to create subsets of options within an option_group for different uses.';
+
+-- To think about: This will update ones where someone has explicitly set it to NULL for their own purposes and they don't care about the dropdowns. How likely is that? How can we tell if it's one they created since 5.26 and didn't intend to set it to NULL?
+UPDATE civicrm_option_value ov
+INNER JOIN civicrm_option_group og ON (ov.option_group_id = og.id AND og.name='activity_type')
+SET ov.filter = 0
+WHERE ov.filter IS NULL;
diff --git a/civicrm/CRM/Utils/API/MatchOption.php b/civicrm/CRM/Utils/API/MatchOption.php
index f92723c337..fa87a1cf8b 100644
--- a/civicrm/CRM/Utils/API/MatchOption.php
+++ b/civicrm/CRM/Utils/API/MatchOption.php
@@ -21,7 +21,7 @@
  *   - "match-mandatory" will generate an error
  *   - "match" will allow action to proceed -- thus inserting a new record
  *
- * @code
+ * ```
  * $result = civicrm_api('contact', 'create', array(
  *   'options' => array(
  *     'match' => array('last_name', 'first_name')
@@ -30,7 +30,7 @@
  *   'last_name' => 'Lebowski',
  *   'nick_name' => 'The Dude',
  * ));
- * @endcode
+ * ```
  *
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
diff --git a/civicrm/CRM/Utils/API/ReloadOption.php b/civicrm/CRM/Utils/API/ReloadOption.php
index 764d81bf80..3e320d5c14 100644
--- a/civicrm/CRM/Utils/API/ReloadOption.php
+++ b/civicrm/CRM/Utils/API/ReloadOption.php
@@ -13,13 +13,13 @@
  * Implement the "reload" option. This option can be used with "create" to force
  * the API to reload a clean copy of the entity before returning the result.
  *
- * @code
+ * ```
  * $clean = civicrm_api('myentity', 'create', array(
  *   'options' => array(
  *     'reload' => 1
  *   ),
  * ));
- * @endcode
+ * ```
  *
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
diff --git a/civicrm/CRM/Utils/Address/USPS.php b/civicrm/CRM/Utils/Address/USPS.php
index bba6d337a9..721b2e70e0 100644
--- a/civicrm/CRM/Utils/Address/USPS.php
+++ b/civicrm/CRM/Utils/Address/USPS.php
@@ -68,19 +68,17 @@ class CRM_Utils_Address_USPS {
 
     $XMLQuery = '<AddressValidateRequest USERID="' . $userID . '"><Address ID="0"><Address1>' . CRM_Utils_Array::value('supplemental_address_1', $values, '') . '</Address1><Address2>' . $address2 . '</Address2><City>' . $values['city'] . '</City><State>' . $values['state_province'] . '</State><Zip5>' . $values['postal_code'] . '</Zip5><Zip4>' . CRM_Utils_Array::value('postal_code_suffix', $values, '') . '</Zip4></Address></AddressValidateRequest>';
 
-    require_once 'HTTP/Request.php';
-    $request = new HTTP_Request();
-
-    $request->setURL($url);
-
-    $request->addQueryString('API', 'Verify');
-    $request->addQueryString('XML', $XMLQuery);
-
-    $response = $request->sendRequest();
+    $client = new GuzzleHttp\Client();
+    $request = $client->request('GET', $url, [
+      'query' => [
+        'API' => 'Verify',
+        'XML' => $XMLQuery,
+      ],
+    ]);
 
     $session = CRM_Core_Session::singleton();
 
-    $code = $request->getResponseCode();
+    $code = $request->getStatusCode();
     if ($code != 200) {
       $session->setStatus(ts('USPS Address Lookup Failed with HTTP status code: %1',
         [1 => $code]
@@ -88,7 +86,7 @@ class CRM_Utils_Address_USPS {
       return FALSE;
     }
 
-    $responseBody = $request->getResponseBody();
+    $responseBody = $request->getBody();
 
     $xml = simplexml_load_string($responseBody);
 
diff --git a/civicrm/CRM/Utils/AutoClean.php b/civicrm/CRM/Utils/AutoClean.php
index 48e0cf9e2d..1be38b0ece 100644
--- a/civicrm/CRM/Utils/AutoClean.php
+++ b/civicrm/CRM/Utils/AutoClean.php
@@ -29,14 +29,14 @@ class CRM_Utils_AutoClean {
   /**
    * Call a cleanup function when the current context shuts down.
    *
-   * @code
+   * ```
    * function doStuff() {
    *   $ac = CRM_Utils_AutoClean::with(function(){
    *     MyCleanup::doIt();
    *   });
    *   ...
    * }
-   * @endcode
+   * ```
    *
    * @param mixed $callback
    * @return CRM_Utils_AutoClean
@@ -52,12 +52,12 @@ class CRM_Utils_AutoClean {
    * Temporarily swap values using callback functions, and cleanup
    * when the current context shuts down.
    *
-   * @code
+   * ```
    * function doStuff() {
    *   $ac = CRM_Utils_AutoClean::swap('My::get', 'My::set', 'tmpValue');
    *   ...
    * }
-   * @endcode
+   * ```
    *
    * @param mixed $getter
    *   Function to lookup current value.
diff --git a/civicrm/CRM/Utils/Cache/SqlGroup.php b/civicrm/CRM/Utils/Cache/SqlGroup.php
index 3f499aa930..8d0205a8e6 100644
--- a/civicrm/CRM/Utils/Cache/SqlGroup.php
+++ b/civicrm/CRM/Utils/Cache/SqlGroup.php
@@ -99,7 +99,12 @@ class CRM_Utils_Cache_SqlGroup implements CRM_Utils_Cache_Interface {
    * @param string $key
    * @param mixed $value
    * @param null|int|\DateInterval $ttl
+   *
    * @return bool
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CRM_Utils_Cache_CacheException
+   * @throws \CRM_Utils_Cache_InvalidArgumentException
    */
   public function set($key, $value, $ttl = NULL) {
     CRM_Utils_Cache::assertValidKey($key);
@@ -127,18 +132,18 @@ class CRM_Utils_Cache_SqlGroup implements CRM_Utils_Cache_Interface {
         2 => [time(), 'Positive'],
         3 => [$expires, 'Positive'],
       ];
-      $dao = CRM_Core_DAO::executeQuery($sql, $args, FALSE, NULL, FALSE, FALSE);
+      CRM_Core_DAO::executeQuery($sql, $args, TRUE, NULL, FALSE, FALSE);
     }
     else {
       $sql = "INSERT INTO {$this->table} (group_name,path,data,created_date,expired_date) VALUES (%1,%2,%3,FROM_UNIXTIME(%4),FROM_UNIXTIME(%5))";
       $args = [
-        1 => [$this->group, 'String'],
+        1 => [(string) $this->group, 'String'],
         2 => [$key, 'String'],
         3 => [$dataSerialized, 'String'],
         4 => [time(), 'Positive'],
         5 => [$expires, 'Positive'],
       ];
-      $dao = CRM_Core_DAO::executeQuery($sql, $args, FALSE, NULL, FALSE, FALSE);
+      CRM_Core_DAO::executeQuery($sql, $args, TRUE, NULL, FALSE, FALSE);
     }
 
     $lock->release();
@@ -153,6 +158,8 @@ class CRM_Utils_Cache_SqlGroup implements CRM_Utils_Cache_Interface {
    * @param mixed $default
    *
    * @return mixed
+   *
+   * @throws \CRM_Utils_Cache_InvalidArgumentException
    */
   public function get($key, $default = NULL) {
     CRM_Utils_Cache::assertValidKey($key);
@@ -167,12 +174,17 @@ class CRM_Utils_Cache_SqlGroup implements CRM_Utils_Cache_Interface {
     return (isset($this->expiresCache[$key]) && time() < $this->expiresCache[$key]) ? $this->reobjectify($this->valueCache[$key]) : $default;
   }
 
+  /**
+   * @param mixed $value
+   *
+   * @return object
+   */
   private function reobjectify($value) {
     return is_object($value) ? unserialize(serialize($value)) : $value;
   }
 
   /**
-   * @param $key
+   * @param string $key
    * @param null $default
    *
    * @return mixed
@@ -193,7 +205,9 @@ class CRM_Utils_Cache_SqlGroup implements CRM_Utils_Cache_Interface {
 
   /**
    * @param string $key
+   *
    * @return bool
+   * @throws \CRM_Utils_Cache_InvalidArgumentException
    */
   public function delete($key) {
     CRM_Utils_Cache::assertValidKey($key);
diff --git a/civicrm/CRM/Utils/Check/Component/Env.php b/civicrm/CRM/Utils/Check/Component/Env.php
index 1cbf084c60..1f63ec83e7 100644
--- a/civicrm/CRM/Utils/Check/Component/Env.php
+++ b/civicrm/CRM/Utils/Check/Component/Env.php
@@ -739,10 +739,8 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
       );
     }
     else {
-      $codeVersion = CRM_Utils_System::version();
-
       // if db.ver < code.ver, time to upgrade
-      if (version_compare($dbVersion, $codeVersion) < 0) {
+      if (CRM_Core_BAO_Domain::isDBUpdateRequired()) {
         $messages[] = new CRM_Utils_Check_Message(
           __FUNCTION__,
           ts('New codebase version detected. You must visit <a href=\'%1\'>upgrade screen</a> to upgrade the database.', [1 => $upgradeUrl]),
@@ -753,7 +751,7 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
       }
 
       // if db.ver > code.ver, sth really wrong
-      if (version_compare($dbVersion, $codeVersion) > 0) {
+      if (version_compare($dbVersion, CRM_Utils_System::version()) > 0) {
         $messages[] = new CRM_Utils_Check_Message(
           __FUNCTION__,
           ts('Your database is marked with an unexpected version number: %1. The v%2 codebase may not be compatible with your database state.
@@ -986,4 +984,18 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
     return $messages;
   }
 
+  public function checkPHPIntlExists() {
+    $messages = [];
+    if (!extension_loaded('intl')) {
+      $messages[] = new CRM_Utils_Check_Message(
+        __FUNCTION__,
+        ts('This system currently does not have the PHP-Intl extension enabled.  Please contact your system administrator about getting the extension enabled.'),
+        ts('Missing PHP Extension: INTL'),
+        \Psr\Log\LogLevel::WARNING,
+        'fa-server'
+      );
+    }
+    return $messages;
+  }
+
 }
diff --git a/civicrm/CRM/Utils/Check/Component/Schema.php b/civicrm/CRM/Utils/Check/Component/Schema.php
index 12d17d2203..c1333dfa05 100644
--- a/civicrm/CRM/Utils/Check/Component/Schema.php
+++ b/civicrm/CRM/Utils/Check/Component/Schema.php
@@ -94,6 +94,10 @@ class CRM_Utils_Check_Component_Schema extends CRM_Utils_Check_Component {
    * @return array
    */
   public function checkSmartGroupCustomFieldCriteria() {
+    if (CRM_Core_BAO_Domain::isDBUpdateRequired()) {
+      // Do not run this check when the db has not been updated as it might fail on non-updated schema issues.
+      return [];
+    }
     $messages = $problematicSG = [];
     $customFieldIds = array_keys(CRM_Core_BAO_CustomField::getFields('ANY', FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE));
     try {
@@ -153,8 +157,8 @@ class CRM_Utils_Check_Component_Schema extends CRM_Utils_Check_Component {
             $fieldName = ' <span style="color:red"> - Deleted - </span> ';
           }
         }
-        $groupEdit = '<a href="' . CRM_Utils_System::url('civicrm/contact/search/advanced', "?reset=1&ssID={$field['ssid']}", TRUE) . '" title="' . ts('Edit search criteria') . '"> <i class="crm-i fa-pencil"></i> </a>';
-        $groupConfig = '<a href="' . CRM_Utils_System::url('civicrm/group', "?reset=1&action=update&id={$id}", TRUE) . '" title="' . ts('Group settings') . '"> <i class="crm-i fa-gear"></i> </a>';
+        $groupEdit = '<a href="' . CRM_Utils_System::url('civicrm/contact/search/advanced', "?reset=1&ssID={$field['ssid']}", TRUE) . '" title="' . ts('Edit search criteria') . '"> <i class="crm-i fa-pencil" aria-hidden="true"></i> </a>';
+        $groupConfig = '<a href="' . CRM_Utils_System::url('civicrm/group', "?reset=1&action=update&id={$id}", TRUE) . '" title="' . ts('Group settings') . '"> <i class="crm-i fa-gear" aria-hidden="true"></i> </a>';
         $html .= "<tr><td>{$id} - {$field['title']} </td><td>{$groupEdit} {$groupConfig}</td><td class='disabled'>{$fieldName}</td>";
       }
 
@@ -183,8 +187,11 @@ class CRM_Utils_Check_Component_Schema extends CRM_Utils_Check_Component {
     if (CRM_Core_Config::singleton()->moneyvalueformat !== '%!i') {
       $msg = new CRM_Utils_Check_Message(
         __FUNCTION__,
-        ts('<p>The Money Value format stored is deprecated please report your configuration on <a href="https://lab.civicrm.org/dev/core/-/issues/1494">Gitlab Issue</a>'),
-        ts('Deprectad money value format configuration'),
+        ts(
+          '<p>The Monetary Value Display format is a deprecated setting, and this site has a non-standard format. Please report your configuration on <a href="%1">this Gitlab issue</a>.',
+          [1 => 'https://lab.civicrm.org/dev/core/-/issues/1494']
+        ),
+        ts('Deprecated monetary value display format configuration'),
         \Psr\Log\LogLevel::WARNING,
         'fa-server'
       );
diff --git a/civicrm/CRM/Utils/ConsoleTee.php b/civicrm/CRM/Utils/ConsoleTee.php
index 75cb7eaec8..f7adb10695 100644
--- a/civicrm/CRM/Utils/ConsoleTee.php
+++ b/civicrm/CRM/Utils/ConsoleTee.php
@@ -12,12 +12,12 @@
 /**
  * Capture the output from the console, copy it to a file, and pass it on.
  *
- * @code
+ * ```
  * $tee = CRM_Utils_ConsoleTee::create()->start();
  * echo "hello world";
  * $tee->stop();
  * assertEquals("hello world", file_get_contents($tee->getFileName()));
- * @endCode
+ * ```
  *
  * Loosely speaking, it serves a similar purpose to Unix `tee`.
  *
diff --git a/civicrm/CRM/Utils/FakeObject.php b/civicrm/CRM/Utils/FakeObject.php
index fef296edbc..a20246fe6b 100644
--- a/civicrm/CRM/Utils/FakeObject.php
+++ b/civicrm/CRM/Utils/FakeObject.php
@@ -19,12 +19,12 @@
  * This is a quick-and-dirty way to define a vaguely-class-ish structure. It's non-performant, abnormal,
  * and not a complete OOP system. Only use for testing/mocking.
  *
- * @code
+ * ```
  * $object = new CRM_Utils_FakeObject(array(
  *   'doIt' => function() {  print "It!\n"; }
  * ));
  * $object->doIt();
- * @endcode
+ * ```
  */
 class CRM_Utils_FakeObject {
 
diff --git a/civicrm/CRM/Utils/Geocode/Google.php b/civicrm/CRM/Utils/Geocode/Google.php
index 1cb0c847ca..6ab1397fea 100644
--- a/civicrm/CRM/Utils/Geocode/Google.php
+++ b/civicrm/CRM/Utils/Geocode/Google.php
@@ -105,10 +105,9 @@ class CRM_Utils_Geocode_Google {
 
     $query = 'https://' . self::$_server . self::$_uri . $add;
 
-    require_once 'HTTP/Request.php';
-    $request = new HTTP_Request($query);
-    $request->sendRequest();
-    $string = $request->getResponseBody();
+    $client = new GuzzleHttp\Client();
+    $request = $client->request('GET', $query);
+    $string = $request->getBody();
 
     libxml_use_internal_errors(TRUE);
     $xml = @simplexml_load_string($string);
diff --git a/civicrm/CRM/Utils/GlobalStack.php b/civicrm/CRM/Utils/GlobalStack.php
index 047de04c3c..50403d9546 100644
--- a/civicrm/CRM/Utils/GlobalStack.php
+++ b/civicrm/CRM/Utils/GlobalStack.php
@@ -17,7 +17,7 @@
 /**
  * Temporarily change a global variable.
  *
- * @code
+ * ```
  * $globals = CRM_Utils_GlobalStack::singleton();
  * $globals->push(array(
  *   '_GET' => array(
@@ -26,7 +26,7 @@
  * ));
  * ...do stuff...
  * $globals->pop();
- * @endcode
+ * ```
  *
  * Note: for purposes of this class, we'll refer to the array passed into
  * push() as a frame.
diff --git a/civicrm/CRM/Utils/Hook.php b/civicrm/CRM/Utils/Hook.php
index 6e8a7b5910..32f01c2f3f 100644
--- a/civicrm/CRM/Utils/Hook.php
+++ b/civicrm/CRM/Utils/Hook.php
@@ -1162,7 +1162,7 @@ abstract class CRM_Utils_Hook {
    *   See discussion in CRM-16224 as to whether $paymentObj should be passed by reference.
    * @param array &$rawParams
    *    array of params as passed to to the processor
-   * @param array &$cookedParams
+   * @param array|\Civi\Payment\PropertyBag &$cookedParams
    *     params after the processor code has translated them into its own key/value pairs
    *
    * @return mixed
@@ -2234,10 +2234,8 @@ abstract class CRM_Utils_Hook {
    *      If omitted, default to "array('civicrm/a')" for backward compat.
    *      For a utility that should only be loaded on-demand, use "array()".
    *      For a utility that should be loaded in all pages use, "array('*')".
-   * @return null
-   *   the return value is ignored
    *
-   * @code
+   * ```
    * function mymod_civicrm_angularModules(&$angularModules) {
    *   $angularModules['myAngularModule'] = array(
    *     'ext' => 'org.example.mymod',
@@ -2252,7 +2250,10 @@ abstract class CRM_Utils_Hook {
    *     'basePages' => array('civicrm/a'),
    *   );
    * }
-   * @endcode
+   * ```
+   *
+   * @return null
+   *   the return value is ignored
    */
   public static function angularModules(&$angularModules) {
     return self::singleton()->invoke(['angularModules'], $angularModules,
@@ -2266,7 +2267,7 @@ abstract class CRM_Utils_Hook {
    *
    * @param \Civi\Angular\Manager $angular
    *
-   * @code
+   * ```
    * function example_civicrm_alterAngular($angular) {
    *   $changeSet = \Civi\Angular\ChangeSet::create('mychanges')
    *     ->alterHtml('~/crmMailing/EditMailingCtrl/2step.html', function(phpQueryObject $doc) {
@@ -2275,7 +2276,7 @@ abstract class CRM_Utils_Hook {
    *   );
    *   $angular->add($changeSet);
    * }
-   * @endCode
+   * ```
    */
   public static function alterAngular($angular) {
     $event = \Civi\Core\Event\GenericHookEvent::create([
@@ -2365,7 +2366,7 @@ abstract class CRM_Utils_Hook {
   /**
    * Modify the CiviCRM container - add new services, parameters, extensions, etc.
    *
-   * @code
+   * ```
    * use Symfony\Component\Config\Resource\FileResource;
    * use Symfony\Component\DependencyInjection\Definition;
    *
@@ -2373,7 +2374,7 @@ abstract class CRM_Utils_Hook {
    *   $container->addResource(new FileResource(__FILE__));
    *   $container->setDefinition('mysvc', new Definition('My\Class', array()));
    * }
-   * @endcode
+   * ```
    *
    * Tip: The container configuration will be compiled/cached. The default cache
    * behavior is aggressive. When you first implement the hook, be sure to
diff --git a/civicrm/CRM/Utils/Migrate/Export.php b/civicrm/CRM/Utils/Migrate/Export.php
index 76a440e26a..7dc6b17d7f 100644
--- a/civicrm/CRM/Utils/Migrate/Export.php
+++ b/civicrm/CRM/Utils/Migrate/Export.php
@@ -22,7 +22,7 @@ class CRM_Utils_Migrate_Export {
    * @var array
    * Description of export field mapping
    *
-   * @code
+   * ```
    * 'exampleEntityMappingName' => array(
    *   'data' => array(),                     // placeholder; this will get filled-in during execution
    *   'name' => 'CustomGroup',               // per-item XML tag name
@@ -31,7 +31,7 @@ class CRM_Utils_Migrate_Export {
    *   'idNameFields' => array('id', 'name'), // name of the (local/autogenerated) "id" and (portable) "name" columns
    *   'idNameMap' => array(),                // placeholder; this will get filled-in during execution
    * ),
-   * @endcode
+   * ```
    */
   protected $_xml;
 
diff --git a/civicrm/CRM/Utils/PagerAToZ.php b/civicrm/CRM/Utils/PagerAToZ.php
index c9e15a636a..eeed2e961a 100644
--- a/civicrm/CRM/Utils/PagerAToZ.php
+++ b/civicrm/CRM/Utils/PagerAToZ.php
@@ -135,9 +135,7 @@ class CRM_Utils_PagerAToZ {
       $qfKey = $query->_formValues['qfKey'] ?? NULL;
     }
     if (empty($qfKey)) {
-      // CRM-20943 Can only pass variables by reference and also cannot use $this so using $empty setting to NULL which is default.
-      $emptyVariable = NULL;
-      $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $emptyVariable, FALSE, NULL, $_REQUEST);
+      $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String');
     }
 
     $aToZBar = [];
diff --git a/civicrm/CRM/Utils/SQL/BaseParamQuery.php b/civicrm/CRM/Utils/SQL/BaseParamQuery.php
index 159f56a5fa..20125db2bd 100644
--- a/civicrm/CRM/Utils/SQL/BaseParamQuery.php
+++ b/civicrm/CRM/Utils/SQL/BaseParamQuery.php
@@ -191,11 +191,11 @@ class CRM_Utils_SQL_BaseParamQuery implements ArrayAccess {
   /**
    * Get the value of a SQL parameter.
    *
-   * @code
+   * ```
    *   $select['cid'] = 123;
    *   $select->where('contact.id = #cid');
    *   echo $select['cid'];
-   * @endCode
+   * ```
    *
    * @param string $offset
    * @return mixed
@@ -209,11 +209,11 @@ class CRM_Utils_SQL_BaseParamQuery implements ArrayAccess {
   /**
    * Set the value of a SQL parameter.
    *
-   * @code
+   * ```
    *   $select['cid'] = 123;
    *   $select->where('contact.id = #cid');
    *   echo $select['cid'];
-   * @endCode
+   * ```
    *
    * @param string $offset
    * @param mixed $value
diff --git a/civicrm/CRM/Utils/SQL/Delete.php b/civicrm/CRM/Utils/SQL/Delete.php
index 6bbc076691..fcb5443030 100644
--- a/civicrm/CRM/Utils/SQL/Delete.php
+++ b/civicrm/CRM/Utils/SQL/Delete.php
@@ -13,7 +13,7 @@
  * Dear God Why Do I Have To Write This (Dumb SQL Builder)
  *
  * Usage:
- * @code
+ * ```
  * $del = CRM_Utils_SQL_Delete::from('civicrm_activity act')
  *     ->where('activity_type_id = #type', array('type' => 234))
  *     ->where('status_id IN (#statuses)', array('statuses' => array(1,2,3))
@@ -24,7 +24,7 @@
  *        'value' => $form['foo']
  *      ))
  * echo $del->toSQL();
- * @endcode
+ * ```
  *
  * Design principles:
  *  - Portable
@@ -48,7 +48,7 @@
  * xor output. The notations for input and output interpolation are a bit different,
  * and they may not be mixed.
  *
- * @code
+ * ```
  * // Interpolate on input. Set params when using them.
  * $select->where('activity_type_id = #type', array(
  *   'type' => 234,
@@ -58,7 +58,7 @@
  * $select
  *     ->where('activity_type_id = #type')
  *     ->param('type', 234),
- * @endcode
+ * ```
  *
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
diff --git a/civicrm/CRM/Utils/SQL/Select.php b/civicrm/CRM/Utils/SQL/Select.php
index 47707a316f..4aa6b7e516 100644
--- a/civicrm/CRM/Utils/SQL/Select.php
+++ b/civicrm/CRM/Utils/SQL/Select.php
@@ -13,7 +13,7 @@
  * Dear God Why Do I Have To Write This (Dumb SQL Builder)
  *
  * Usage:
- * @code
+ * ```
  * $select = CRM_Utils_SQL_Select::from('civicrm_activity act')
  *     ->join('absence', 'inner join civicrm_activity absence on absence.id = act.source_record_id')
  *     ->where('activity_type_id = #type', array('type' => 234))
@@ -25,7 +25,7 @@
  *        'value' => $form['foo']
  *      ))
  * echo $select->toSQL();
- * @endcode
+ * ```
  *
  * Design principles:
  *  - Portable
@@ -49,7 +49,7 @@
  * xor output. The notations for input and output interpolation are a bit different,
  * and they may not be mixed.
  *
- * @code
+ * ```
  * // Interpolate on input. Set params when using them.
  * $select->where('activity_type_id = #type', array(
  *   'type' => 234,
@@ -59,7 +59,7 @@
  * $select
  *     ->where('activity_type_id = #type')
  *     ->param('type', 234),
- * @endcode
+ * ```
  *
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
diff --git a/civicrm/CRM/Utils/Signer.php b/civicrm/CRM/Utils/Signer.php
index eb902bc189..2b6491f9d0 100644
--- a/civicrm/CRM/Utils/Signer.php
+++ b/civicrm/CRM/Utils/Signer.php
@@ -20,7 +20,7 @@
  *
  * FIXME: Add TTL support?
  *
- * @code
+ * ```
  * $signer = new CRM_Utils_Signer('myprivatekey', array('param1','param2'));
  * $params = array(
  *   'param1' => 'hello',
@@ -29,7 +29,7 @@
  * $token = $signer->sign($params);
  * ...
  * assertTrue($signer->validate($token, $params));
- * @endcode
+ * ```
  */
 class CRM_Utils_Signer {
   /**
diff --git a/civicrm/CRM/Utils/String.php b/civicrm/CRM/Utils/String.php
index 18d4904b1f..e0cac9a763 100644
--- a/civicrm/CRM/Utils/String.php
+++ b/civicrm/CRM/Utils/String.php
@@ -86,37 +86,17 @@ class CRM_Utils_String {
   }
 
   /**
-   * Convert possibly underscore separated words to camel case with special handling for 'UF'
-   * e.g membership_payment returns MembershipPayment
-   *
-   * @param string $string
+   * Convert possibly underscore separated words to camel case.
    *
+   * @param string $str
+   * @param bool $ucFirst
+   *   Should the first letter be capitalized like `CamelCase` or lower like `camelCase`
    * @return string
    */
-  public static function convertStringToCamel($string) {
-    $map = [
-      'acl' => 'Acl',
-      'ACL' => 'Acl',
-      'im' => 'Im',
-      'IM' => 'Im',
-    ];
-    if (isset($map[$string])) {
-      return $map[$string];
-    }
-
-    $fragments = explode('_', $string);
-    foreach ($fragments as & $fragment) {
-      $fragment = ucfirst($fragment);
-      // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in without underscores)
-      if (strpos($fragment, 'Uf') === 0 && strlen($string) > 2) {
-        $fragment = 'UF' . ucfirst(substr($fragment, 2));
-      }
-    }
-    // Special case: UFGroup, UFJoin, UFMatch, UFField (if passed in underscore-separated)
-    if ($fragments[0] === 'Uf') {
-      $fragments[0] = 'UF';
-    }
-    return implode('', $fragments);
+  public static function convertStringToCamel($str, $ucFirst = TRUE) {
+    $fragments = explode('_', $str);
+    $camel = implode('', array_map('ucfirst', $fragments));
+    return $ucFirst ? $camel : lcfirst($camel);
   }
 
   /**
diff --git a/civicrm/CRM/Utils/System.php b/civicrm/CRM/Utils/System.php
index 8713cf27fa..11e9eb1710 100644
--- a/civicrm/CRM/Utils/System.php
+++ b/civicrm/CRM/Utils/System.php
@@ -318,6 +318,41 @@ class CRM_Utils_System {
     return urldecode(CRM_Utils_Url::unparseUrl($event->url));
   }
 
+  /**
+   * Perform any current conversions/migrations on the extern URL.
+   *
+   * @param \Civi\Core\Event\GenericHookEvent $e
+   * @see CRM_Utils_Hook::alterExternUrl
+   */
+  public static function migrateExternUrl(\Civi\Core\Event\GenericHookEvent $e) {
+
+    /**
+     * $mkRouteUri is a small adapter to return generated URL as a "UriInterface".
+     * @param string $path
+     * @param string $query
+     * @return \Psr\Http\Message\UriInterface
+     */
+    $mkRouteUri = function ($path, $query) use ($e) {
+      $urlTxt = CRM_Utils_System::url($path, $query, $e->absolute, $e->fragment, FALSE);
+      if ($e->isSSL || ($e->isSSL === NULL && \CRM_Utils_System::isSSL())) {
+        $urlTxt = str_replace('http://', 'https://', $urlTxt);
+      }
+      return CRM_Utils_Url::parseUrl($urlTxt);
+    };
+
+    switch (Civi::settings()->get('defaultExternUrl') . ':' . $e->path) {
+      case 'router:extern/open':
+        $e->url = $mkRouteUri('civicrm/mailing/open', preg_replace('/(^|&)q=/', '\1qid=', $e->query));
+        break;
+
+      case 'router:extern/url':
+        $e->url = $mkRouteUri('civicrm/mailing/url', $e->query);
+        break;
+
+      // Otherwise, keep the default.
+    }
+  }
+
   /**
    * @deprecated
    * @see \CRM_Utils_System::currentPath
diff --git a/civicrm/CRM/Utils/System/Drupal.php b/civicrm/CRM/Utils/System/Drupal.php
index f0c8cdbc7d..bf4f8693cf 100644
--- a/civicrm/CRM/Utils/System/Drupal.php
+++ b/civicrm/CRM/Utils/System/Drupal.php
@@ -72,6 +72,19 @@ class CRM_Utils_System_Drupal extends CRM_Utils_System_DrupalBase {
     return $form_state['user']->uid;
   }
 
+  /**
+   * Appends a Drupal 7 Javascript file when the CRM Menubar Javascript file has
+   * been included. The file is added before the menu bar so we can properly listen
+   * for the menu bar ready event.
+   */
+  public function appendCoreResources(\Civi\Core\Event\GenericHookEvent $event) {
+    $menuBarFileIndex = array_search('js/crm.menubar.js', $event->list);
+
+    if ($menuBarFileIndex !== FALSE) {
+      array_splice($event->list, $menuBarFileIndex, 0, ['js/crm.drupal7.js']);
+    }
+  }
+
   /**
    * @inheritDoc
    */
diff --git a/civicrm/CRM/Utils/System/Drupal8.php b/civicrm/CRM/Utils/System/Drupal8.php
index 82fe4d85e4..6e42f703b8 100644
--- a/civicrm/CRM/Utils/System/Drupal8.php
+++ b/civicrm/CRM/Utils/System/Drupal8.php
@@ -654,13 +654,13 @@ class CRM_Utils_System_Drupal8 extends CRM_Utils_System_DrupalBase {
    *
    * For example, 'civicrm/contact/view?reset=1&cid=66' will be returned as:
    *
-   * @code
+   * ```
    * array(
    *   'path' => 'civicrm/contact/view',
    *   'route' => 'civicrm.civicrm_contact_view',
    *   'query' => array('reset' => '1', 'cid' => '66'),
    * );
-   * @endcode
+   * ```
    *
    * @param string $url
    *   The url to parse.
diff --git a/civicrm/CRM/Utils/System/WordPress.php b/civicrm/CRM/Utils/System/WordPress.php
index 873020ce53..d844e98b45 100644
--- a/civicrm/CRM/Utils/System/WordPress.php
+++ b/civicrm/CRM/Utils/System/WordPress.php
@@ -35,6 +35,87 @@ class CRM_Utils_System_WordPress extends CRM_Utils_System_Base {
     $this->is_wordpress = TRUE;
   }
 
+  public function initialize() {
+    parent::initialize();
+    $this->registerPathVars();
+  }
+
+  /**
+   * Specify the default computation for various paths/URLs.
+   */
+  protected function registerPathVars():void {
+    $isNormalBoot = function_exists('get_option');
+    if ($isNormalBoot) {
+      // Normal mode - CMS boots first, then calls Civi. "Normal" web pages and newer extern routes.
+      // To simplify the code-paths, some items are re-registered with WP-specific functions.
+      $cmsRoot = function() {
+        return [
+          'path' => untrailingslashit(ABSPATH),
+          'url' => home_url(),
+        ];
+      };
+      Civi::paths()->register('cms', $cmsRoot);
+      Civi::paths()->register('cms.root', $cmsRoot);
+      Civi::paths()->register('civicrm.files', function () {
+        $upload_dir = wp_get_upload_dir();
+        return [
+          'path' => $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR,
+          'url' => $upload_dir['baseurl'] . '/civicrm/',
+        ];
+      });
+      Civi::paths()->register('civicrm.root', function () {
+        return [
+          'path' => CIVICRM_PLUGIN_DIR . 'civicrm' . DIRECTORY_SEPARATOR,
+          'url' => CIVICRM_PLUGIN_URL . 'civicrm/',
+        ];
+      });
+      Civi::paths()->register('wp.frontend.base', function () {
+        return [
+          'url' => home_url('/'),
+        ];
+      });
+      Civi::paths()->register('wp.frontend', function () {
+        $config = CRM_Core_Config::singleton();
+        $basepage = get_page_by_path($config->wpBasePage);
+        return [
+          'url' => get_permalink($basepage->ID),
+        ];
+      });
+      Civi::paths()->register('wp.backend.base', function () {
+        return [
+          'url' => admin_url(),
+        ];
+      });
+      Civi::paths()->register('wp.backend', function() {
+        return [
+          'url' => admin_url('admin.php'),
+        ];
+      });
+    }
+    else {
+      // Legacy support - only relevant for older extern routes.
+      Civi::paths()
+        ->register('wp.frontend.base', function () {
+          return ['url' => rtrim(CIVICRM_UF_BASEURL, '/') . '/'];
+        })
+        ->register('wp.frontend', function () {
+          $config = \CRM_Core_Config::singleton();
+          $suffix = defined('CIVICRM_UF_WP_BASEPAGE') ? CIVICRM_UF_WP_BASEPAGE : $config->wpBasePage;
+          return [
+            'url' => Civi::paths()->getVariable('wp.frontend.base', 'url') . $suffix,
+          ];
+        })
+        ->register('wp.backend.base', function () {
+          return ['url' => rtrim(CIVICRM_UF_BASEURL, '/') . '/wp-admin/'];
+        })
+        ->register('wp.backend', function () {
+          return [
+            'url' => Civi::paths()->getVariable('wp.backend.base', 'url') . 'admin.php',
+          ];
+        });
+    }
+  }
+
   /**
    * @inheritDoc
    */
diff --git a/civicrm/CRM/Utils/Time.php b/civicrm/CRM/Utils/Time.php
index dd4b4e2cca..b700e57207 100644
--- a/civicrm/CRM/Utils/Time.php
+++ b/civicrm/CRM/Utils/Time.php
@@ -21,10 +21,14 @@
 class CRM_Utils_Time {
 
   /**
-   * @var int
-   *   the seconds offset from the real world time
+   * A function which determines the current time.
+   * Only used during testing (with mocked time).
+   *
+   * The normal value, NULL, indicates the use of real time.
+   *
+   * @var callable|null
    */
-  static private $_delta = 0;
+  static private $callback = NULL;
 
   /**
    * Get the time.
@@ -45,7 +49,7 @@ class CRM_Utils_Time {
    *   seconds since epoch
    */
   public static function getTimeRaw() {
-    return time() + self::$_delta;
+    return self::$callback === NULL ? time() : call_user_func(self::$callback);
   }
 
   /**
@@ -56,10 +60,61 @@ class CRM_Utils_Time {
    * @param string $returnFormat
    *   Format in which date is to be retrieved.
    *
+   * Note: The progression of time will be influenced by TIME_FUNC, which may be:
+   *   - 'frozen' (time does not move)
+   *   - 'natural' (time moves naturally)
+   *   - 'linear:XXX' (time moves in increments of XXX milliseconds - with every lookup)
+   *   - 'prng:XXX' (time moves by random increments, between 0 and XXX milliseconds)
    * @return string
    */
   public static function setTime($newDateTime, $returnFormat = 'YmdHis') {
-    self::$_delta = strtotime($newDateTime) - time();
+    $mode = getenv('TIME_FUNC') ? getenv('TIME_FUNC') : 'natural';
+
+    list ($modeName, $modeNum) = explode(":", "$mode:");
+
+    switch ($modeName) {
+      case 'frozen':
+        // Every getTime() will produce the same value (ie $newDateTime).
+        $now = strtotime($newDateTime);
+        self::$callback = function () use ($now) {
+          return $now;
+        };
+        break;
+
+      case 'natural':
+        // Time changes to $newDateTime and then proceeds naturally.
+        $delta = strtotime($newDateTime) - time();
+        self::$callback = function () use ($delta) {
+          return time() + $delta;
+        };
+        break;
+
+      case 'linear':
+        // Time changes to $newDateTime and then proceeds in fixed increments ($modeNum milliseconds).
+        $incr = ($modeNum / 1000.0);
+        $now = (float) strtotime($newDateTime) - $incr;
+        self::$callback = function () use (&$now, $incr) {
+          $now += $incr;
+          return floor($now);
+        };
+        break;
+
+      case 'prng':
+        // Time changes to $newDateTime and then proceeds using deterministic pseudorandom increments (of up to $modeNum milliseconds).
+        $seed = md5($newDateTime . chr(0) . $mode, TRUE);
+        $now = (float) strtotime($newDateTime);
+        self::$callback = function () use (&$seed, &$now, $modeNum) {
+          $mod = gmp_strval(gmp_mod(gmp_import($seed), "$modeNum"));
+          $seed = md5($seed . $now, TRUE);
+          $now = $now + ($mod / 1000.0);
+          return floor($now);
+        };
+        break;
+
+      default:
+        throw new \RuntimeException("Unrecognized TIME_FUNC ($mode)");
+    }
+
     return self::getTime($returnFormat);
   }
 
@@ -67,7 +122,7 @@ class CRM_Utils_Time {
    * Remove any time overrides.
    */
   public static function resetTime() {
-    self::$_delta = 0;
+    self::$callback = NULL;
   }
 
   /**
diff --git a/civicrm/CRM/Utils/Url.php b/civicrm/CRM/Utils/Url.php
index 1b73c1dc7e..51340c3f72 100644
--- a/civicrm/CRM/Utils/Url.php
+++ b/civicrm/CRM/Utils/Url.php
@@ -19,7 +19,7 @@ class CRM_Utils_Url {
    *
    * @param string $url
    *
-   * @return \GuzzleHttp\Psr7\UriInterface
+   * @return \Psr\Http\Message\UriInterface
    */
   public static function parseUrl($url) {
     return new Uri($url);
@@ -28,7 +28,7 @@ class CRM_Utils_Url {
   /**
    * Unparse url back to a string.
    *
-   * @param \GuzzleHttp\Psr7\UriInterface $parsed
+   * @param \Psr\Http\Message\UriInterface $parsed
    *
    * @return string
    */
diff --git a/civicrm/Civi.php b/civicrm/Civi.php
index ebd09e8afe..95009e35c3 100644
--- a/civicrm/Civi.php
+++ b/civicrm/Civi.php
@@ -19,11 +19,11 @@ class Civi {
   /**
    * A central location for static variable storage.
    * @var array
-   * @code
+   * ```
    * `Civi::$statics[__CLASS__]['foo'] = 'bar';
-   * @endcode
+   * ```
    */
-  public static $statics = array();
+  public static $statics = [];
 
   /**
    * Retrieve a named cache instance.
@@ -106,7 +106,7 @@ class Civi {
    * singletons, containers.
    */
   public static function reset() {
-    self::$statics = array();
+    self::$statics = [];
     Civi\Core\Container::singleton();
   }
 
diff --git a/civicrm/Civi/API/Request.php b/civicrm/Civi/API/Request.php
index 22fa382a71..5d0457ef7d 100644
--- a/civicrm/Civi/API/Request.php
+++ b/civicrm/Civi/API/Request.php
@@ -74,7 +74,7 @@ class Request {
    * @return string
    */
   public static function normalizeEntityName($entity) {
-    return \CRM_Utils_String::convertStringToCamel(\CRM_Utils_String::munge($entity));
+    return \CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel(\CRM_Utils_String::munge($entity), TRUE);
   }
 
   /**
diff --git a/civicrm/Civi/API/SelectQuery.php b/civicrm/Civi/API/SelectQuery.php
index 92e09ad8d1..97fac0a133 100644
--- a/civicrm/Civi/API/SelectQuery.php
+++ b/civicrm/Civi/API/SelectQuery.php
@@ -63,7 +63,7 @@ abstract class SelectQuery {
   /**
    * @var array
    */
-  protected $entityFieldNames;
+  protected $entityFieldNames = [];
   /**
    * @var array
    */
@@ -361,11 +361,11 @@ abstract class SelectQuery {
    * Get acl clause for an entity
    *
    * @param string $tableAlias
-   * @param string $baoName
+   * @param \CRM_Core_DAO|string $baoName
    * @param array $stack
    * @return array
    */
-  protected function getAclClause($tableAlias, $baoName, $stack = []) {
+  public function getAclClause($tableAlias, $baoName, $stack = []) {
     if (!$this->checkPermissions) {
       return [];
     }
diff --git a/civicrm/Civi/API/Subscriber/ChainSubscriber.php b/civicrm/Civi/API/Subscriber/ChainSubscriber.php
index ff4f79256e..e76220ca0d 100644
--- a/civicrm/Civi/API/Subscriber/ChainSubscriber.php
+++ b/civicrm/Civi/API/Subscriber/ChainSubscriber.php
@@ -18,7 +18,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  * The ChainSubscriber looks for API parameters which specify a nested or
  * chained API call. For example:
  *
- * @code
+ * ```
  * $result = civicrm_api('Contact', 'create', array(
  *   'version' => 3,
  *   'first_name' => 'Amy',
@@ -27,7 +27,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  *     'location_type_id' => 123,
  *   ),
  * ));
- * @endcode
+ * ```
  *
  * The ChainSubscriber looks for any parameters of the form "api.Email.create";
  * if found, it issues the nested API call (and passes some extra context --
diff --git a/civicrm/Civi/API/Subscriber/DynamicFKAuthorization.php b/civicrm/Civi/API/Subscriber/DynamicFKAuthorization.php
index 6a19cded03..3aaa1a89c6 100644
--- a/civicrm/Civi/API/Subscriber/DynamicFKAuthorization.php
+++ b/civicrm/Civi/API/Subscriber/DynamicFKAuthorization.php
@@ -12,6 +12,7 @@
 namespace Civi\API\Subscriber;
 
 use Civi\API\Events;
+use CRM_Core_DAO_AllCoreTables as AllCoreTables;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -123,7 +124,7 @@ class DynamicFKAuthorization implements EventSubscriberInterface {
    */
   public function __construct($kernel, $entityName, $actions, $lookupDelegateSql, $lookupCustomFieldSql, $allowedDelegates = NULL) {
     $this->kernel = $kernel;
-    $this->entityName = \CRM_Utils_String::convertStringToCamel($entityName);
+    $this->entityName = AllCoreTables::convertEntityNameToCamel($entityName, TRUE);
     $this->actions = $actions;
     $this->lookupDelegateSql = $lookupDelegateSql;
     $this->lookupCustomFieldSql = $lookupCustomFieldSql;
@@ -138,7 +139,7 @@ class DynamicFKAuthorization implements EventSubscriberInterface {
    */
   public function onApiAuthorize(\Civi\API\Event\AuthorizeEvent $event) {
     $apiRequest = $event->getApiRequest();
-    if ($apiRequest['version'] == 3 && \CRM_Utils_String::convertStringToCamel($apiRequest['entity']) == $this->entityName && in_array(strtolower($apiRequest['action']), $this->actions)) {
+    if ($apiRequest['version'] == 3 && AllCoreTables::convertEntityNameToCamel($apiRequest['entity'], TRUE) == $this->entityName && in_array(strtolower($apiRequest['action']), $this->actions)) {
       if (isset($apiRequest['params']['field_name'])) {
         $fldIdx = \CRM_Utils_Array::index(['field_name'], $this->getCustomFields());
         if (empty($fldIdx[$apiRequest['params']['field_name']])) {
diff --git a/civicrm/Civi/API/WhitelistRule.php b/civicrm/Civi/API/WhitelistRule.php
index c17b41cb2e..5150b362f8 100644
--- a/civicrm/Civi/API/WhitelistRule.php
+++ b/civicrm/Civi/API/WhitelistRule.php
@@ -14,14 +14,14 @@ namespace Civi\API;
  * A WhitelistRule is used to determine if an API call is authorized.
  * For example:
  *
- * @code
+ * ```
  * new WhitelistRule(array(
  *   'entity' => 'Contact',
  *   'actions' => array('get','getsingle'),
  *   'required' => array('contact_type' => 'Organization'),
  *   'fields' => array('id', 'display_name', 'sort_name', 'created_date'),
  * ));
- * @endcode
+ * ```
  *
  * This rule would allow API requests that attempt to get contacts of type "Organization",
  * but only a handful of fields ('id', 'display_name', 'sort_name', 'created_date')
diff --git a/civicrm/Civi/ActionSchedule/Event/MailingQueryEvent.php b/civicrm/Civi/ActionSchedule/Event/MailingQueryEvent.php
index 0158b41e7d..8739514169 100644
--- a/civicrm/Civi/ActionSchedule/Event/MailingQueryEvent.php
+++ b/civicrm/Civi/ActionSchedule/Event/MailingQueryEvent.php
@@ -13,20 +13,20 @@ use Symfony\Component\EventDispatcher\Event;
  *
  * The basic mailing query looks a bit like this (depending on configuration):
  *
- * @code
+ * ```
  * SELECT reminder.id AS reminderID, reminder.contact_id as contactID, ...
  * FROM `civicrm_action_log` reminder
  * ... JOIN `target_entity` e ON e.id = reminder.entity_id ...
  * WHERE reminder.action_schedule_id = #casActionScheduleId
- * @endcode
+ * ```
  *
  * Listeners may modify the query. For example, suppose we want to load
  * additional fields from the related 'foo' entity:
  *
- * @code
+ * ```
  * $event->query->join('foo', '!casMailingJoinType civicrm_foo foo ON foo.myentity_id = e.id')
  *   ->select('foo.bar_value AS bar');
- * @endcode
+ * ```
  *
  * There are several parameters pre-set for use in queries:
  *  - 'casActionScheduleId'
diff --git a/civicrm/Civi/ActionSchedule/RecipientBuilder.php b/civicrm/Civi/ActionSchedule/RecipientBuilder.php
index a54bca3b83..c8a32dd97e 100644
--- a/civicrm/Civi/ActionSchedule/RecipientBuilder.php
+++ b/civicrm/Civi/ActionSchedule/RecipientBuilder.php
@@ -37,7 +37,7 @@ namespace Civi\ActionSchedule;
  * to fire the reminders X days after the registration date. The
  * MappingInterface::createQuery() could return a query like:
  *
- * @code
+ * ```
  * CRM_Utils_SQL_Select::from('civicrm_participant e')
  *   ->join('event', 'INNER JOIN civicrm_event event ON e.event_id = event.id')
  *   ->where('e.is_pay_later = 1')
@@ -46,7 +46,7 @@ namespace Civi\ActionSchedule;
  *   ->param('casDateField', 'e.register_date')
  *   ->param($defaultParams)
  *   ...etc...
- * @endcode
+ * ```
  *
  * In the RELATION_FIRST phase, RecipientBuilder adds a LEFT-JOIN+WHERE to find
  * participants who have *not* yet received any reminder, and filters those
diff --git a/civicrm/Civi/Angular/AngularLoader.php b/civicrm/Civi/Angular/AngularLoader.php
index 58e6998700..1dca6bcd9e 100644
--- a/civicrm/Civi/Angular/AngularLoader.php
+++ b/civicrm/Civi/Angular/AngularLoader.php
@@ -8,12 +8,12 @@ namespace Civi\Angular;
  * The AngularLoader stops short of bootstrapping AngularJS. You may
  * need to `<div ng-app="..."></div>` or `angular.bootstrap(...)`.
  *
- * @code
+ * ```
  * $loader = new AngularLoader();
  * $loader->setPageName('civicrm/case/a');
  * $loader->setModules(array('crmApp'));
  * $loader->load();
- * @endCode
+ * ```
  *
  * @link https://docs.angularjs.org/guide/bootstrap
  */
diff --git a/civicrm/Civi/Api4/Action/CustomValue/GetFields.php b/civicrm/Civi/Api4/Action/CustomValue/GetFields.php
index c2ca32a1a8..9ba2981dd8 100644
--- a/civicrm/Civi/Api4/Action/CustomValue/GetFields.php
+++ b/civicrm/Civi/Api4/Action/CustomValue/GetFields.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\CustomValue;
 
 use Civi\Api4\Service\Spec\SpecFormatter;
diff --git a/civicrm/Civi/Api4/Action/Entity/GetLinks.php b/civicrm/Civi/Api4/Action/Entity/GetLinks.php
index a5c6c53fbd..5a4bc69785 100644
--- a/civicrm/Civi/Api4/Action/Entity/GetLinks.php
+++ b/civicrm/Civi/Api4/Action/Entity/GetLinks.php
@@ -33,16 +33,14 @@ class GetLinks extends \Civi\Api4\Generic\BasicGetAction {
     foreach ($schema->getTables() as $table) {
       $entity = CoreUtil::getApiNameFromTableName($table->getName());
       // Since this is an api function, exclude tables that don't have an api
-      if (class_exists('\Civi\Api4\\' . $entity)) {
+      if (strpos($entity, 'Custom_') === 0 || class_exists('\Civi\Api4\\' . $entity)) {
         $item = [
           'entity' => $entity,
           'table' => $table->getName(),
           'links' => [],
         ];
         foreach ($table->getTableLinks() as $link) {
-          $link = $link->toArray();
-          $link['entity'] = CoreUtil::getApiNameFromTableName($link['targetTable']);
-          $item['links'][] = $link;
+          $item['links'][] = $link->toArray();
         }
         $result[] = $item;
       }
diff --git a/civicrm/Civi/Api4/Action/GetActions.php b/civicrm/Civi/Api4/Action/GetActions.php
index bb82f93555..fbab1f057d 100644
--- a/civicrm/Civi/Api4/Action/GetActions.php
+++ b/civicrm/Civi/Api4/Action/GetActions.php
@@ -10,15 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
 namespace Civi\Api4\Action;
 
 use Civi\API\Exception\NotImplementedException;
diff --git a/civicrm/Civi/Api4/Action/GroupContact/Save.php b/civicrm/Civi/Api4/Action/GroupContact/Save.php
index b695ae63f7..bb19580b68 100644
--- a/civicrm/Civi/Api4/Action/GroupContact/Save.php
+++ b/civicrm/Civi/Api4/Action/GroupContact/Save.php
@@ -10,15 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
 namespace Civi\Api4\Action\GroupContact;
 
 /**
diff --git a/civicrm/Civi/Api4/Action/Relationship/Get.php b/civicrm/Civi/Api4/Action/Relationship/Get.php
index 71d51b4d83..e9460283c4 100644
--- a/civicrm/Civi/Api4/Action/Relationship/Get.php
+++ b/civicrm/Civi/Api4/Action/Relationship/Get.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\Relationship;
 
 /**
diff --git a/civicrm/Civi/Api4/Action/Setting/AbstractSettingAction.php b/civicrm/Civi/Api4/Action/Setting/AbstractSettingAction.php
index d4a7a7dbe5..31e2289682 100644
--- a/civicrm/Civi/Api4/Action/Setting/AbstractSettingAction.php
+++ b/civicrm/Civi/Api4/Action/Setting/AbstractSettingAction.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\Setting;
 
 use Civi\Api4\Domain;
diff --git a/civicrm/Civi/Api4/Action/Setting/Get.php b/civicrm/Civi/Api4/Action/Setting/Get.php
index fd4a0ce3f0..9a6539de66 100644
--- a/civicrm/Civi/Api4/Action/Setting/Get.php
+++ b/civicrm/Civi/Api4/Action/Setting/Get.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\Setting;
 
 use Civi\Api4\Generic\Result;
diff --git a/civicrm/Civi/Api4/Action/Setting/GetFields.php b/civicrm/Civi/Api4/Action/Setting/GetFields.php
index bc6c9d68a1..44711ef4c8 100644
--- a/civicrm/Civi/Api4/Action/Setting/GetFields.php
+++ b/civicrm/Civi/Api4/Action/Setting/GetFields.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\Setting;
 
 /**
diff --git a/civicrm/Civi/Api4/Action/Setting/Revert.php b/civicrm/Civi/Api4/Action/Setting/Revert.php
index 11abc64db4..f6a2f38003 100644
--- a/civicrm/Civi/Api4/Action/Setting/Revert.php
+++ b/civicrm/Civi/Api4/Action/Setting/Revert.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\Setting;
 
 use Civi\Api4\Generic\Result;
diff --git a/civicrm/Civi/Api4/Action/Setting/Set.php b/civicrm/Civi/Api4/Action/Setting/Set.php
index 9353436c82..cd8413331f 100644
--- a/civicrm/Civi/Api4/Action/Setting/Set.php
+++ b/civicrm/Civi/Api4/Action/Setting/Set.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\Setting;
 
 use Civi\Api4\Generic\Result;
diff --git a/civicrm/Civi/Api4/Action/System/Check.php b/civicrm/Civi/Api4/Action/System/Check.php
index 9b44021cad..9080f60a8d 100644
--- a/civicrm/Civi/Api4/Action/System/Check.php
+++ b/civicrm/Civi/Api4/Action/System/Check.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\System;
 
 /**
diff --git a/civicrm/Civi/Api4/Action/System/Flush.php b/civicrm/Civi/Api4/Action/System/Flush.php
index 8d5ab9119e..5eefb63cae 100644
--- a/civicrm/Civi/Api4/Action/System/Flush.php
+++ b/civicrm/Civi/Api4/Action/System/Flush.php
@@ -10,14 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Action\System;
 
 /**
diff --git a/civicrm/Civi/Api4/Contribution.php b/civicrm/Civi/Api4/Contribution.php
index fe0fe24647..99743ba015 100644
--- a/civicrm/Civi/Api4/Contribution.php
+++ b/civicrm/Civi/Api4/Contribution.php
@@ -10,13 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- */
-
-
 namespace Civi\Api4;
 
 /**
diff --git a/civicrm/Civi/Api4/ContributionPage.php b/civicrm/Civi/Api4/ContributionPage.php
index 17f1c6a0ef..cfafb5b018 100644
--- a/civicrm/Civi/Api4/ContributionPage.php
+++ b/civicrm/Civi/Api4/ContributionPage.php
@@ -10,13 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- */
-
-
 namespace Civi\Api4;
 
 /**
diff --git a/civicrm/Civi/Api4/ContributionRecur.php b/civicrm/Civi/Api4/ContributionRecur.php
new file mode 100644
index 0000000000..4d3884d15f
--- /dev/null
+++ b/civicrm/Civi/Api4/ContributionRecur.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Api4;
+
+/**
+ * ContributionRecur entity.
+ *
+ * @package Civi\Api4
+ */
+class ContributionRecur extends Generic\DAOEntity {
+
+}
diff --git a/civicrm/Civi/Api4/Event/Events.php b/civicrm/Civi/Api4/Event/Events.php
index bb866e287b..c5247695c5 100644
--- a/civicrm/Civi/Api4/Event/Events.php
+++ b/civicrm/Civi/Api4/Event/Events.php
@@ -23,21 +23,14 @@ namespace Civi\Api4\Event;
 
 class Events {
 
-  /**
-   * Prepare the specification for a request. Fired from within a request to
-   * get fields.
-   *
-   * @see \Civi\Api4\Event\GetSpecEvent
-   */
-  const GET_SPEC = 'civi.api.get_spec';
-
   /**
    * Build the database schema, allow adding of custom joins and tables.
    */
   const SCHEMA_MAP_BUILD = 'api.schema_map.build';
 
   /**
-   * Alter query results of APIv4 select query
+   * Add back POST_SELECT_QUERY const due to Joomla upgrade failure
+   * https://lab.civicrm.org/dev/joomla/-/issues/28#note_39487
    */
   const POST_SELECT_QUERY = 'api.select_query.post';
 
diff --git a/civicrm/Civi/Api4/Event/Subscriber/ContactSchemaMapSubscriber.php b/civicrm/Civi/Api4/Event/Subscriber/ContactSchemaMapSubscriber.php
deleted file mode 100644
index d41ab9f140..0000000000
--- a/civicrm/Civi/Api4/Event/Subscriber/ContactSchemaMapSubscriber.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-/*
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC. All rights reserved.                        |
- |                                                                    |
- | This work is published under the GNU AGPLv3 license with some      |
- | permitted exceptions and without any warranty. For full license    |
- | and copyright information, see https://civicrm.org/licensing       |
- +--------------------------------------------------------------------+
- */
-
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
-namespace Civi\Api4\Event\Subscriber;
-
-use Civi\Api4\Event\Events;
-use Civi\Api4\Event\SchemaMapBuildEvent;
-use Civi\Api4\Service\Schema\Joinable\Joinable;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-class ContactSchemaMapSubscriber implements EventSubscriberInterface {
-
-  /**
-   * @return array
-   */
-  public static function getSubscribedEvents() {
-    return [
-      Events::SCHEMA_MAP_BUILD => 'onSchemaBuild',
-    ];
-  }
-
-  /**
-   * @param \Civi\Api4\Event\SchemaMapBuildEvent $event
-   */
-  public function onSchemaBuild(SchemaMapBuildEvent $event) {
-    $schema = $event->getSchemaMap();
-    $table = $schema->getTableByName('civicrm_contact');
-    $this->addCreatedActivitiesLink($table);
-    $this->fixPreferredLanguageAlias($table);
-  }
-
-  /**
-   * @param \Civi\Api4\Service\Schema\Table $table
-   */
-  private function addCreatedActivitiesLink($table) {
-    $alias = 'created_activities';
-    $joinable = new Joinable('civicrm_activity_contact', 'contact_id', $alias);
-    $joinable->addCondition($alias . '.record_type_id = 1');
-    $joinable->setJoinType($joinable::JOIN_TYPE_ONE_TO_MANY);
-    $table->addTableLink('id', $joinable);
-  }
-
-  /**
-   * @param \Civi\Api4\Service\Schema\Table $table
-   */
-  private function fixPreferredLanguageAlias($table) {
-    foreach ($table->getExternalLinks() as $link) {
-      if ($link->getAlias() === 'languages') {
-        $link->setAlias('preferred_language');
-        return;
-      }
-    }
-  }
-
-}
diff --git a/civicrm/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php b/civicrm/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php
deleted file mode 100644
index e21c2dd381..0000000000
--- a/civicrm/Civi/Api4/Event/Subscriber/PostSelectQuerySubscriber.php
+++ /dev/null
@@ -1,335 +0,0 @@
-<?php
-
-/*
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC. All rights reserved.                        |
- |                                                                    |
- | This work is published under the GNU AGPLv3 license with some      |
- | permitted exceptions and without any warranty. For full license    |
- | and copyright information, see https://civicrm.org/licensing       |
- +--------------------------------------------------------------------+
- */
-
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
-namespace Civi\Api4\Event\Subscriber;
-
-use Civi\Api4\Event\Events;
-use Civi\Api4\Event\PostSelectQueryEvent;
-use Civi\Api4\Query\Api4SelectQuery;
-use Civi\Api4\Utils\ArrayInsertionUtil;
-use Civi\Api4\Utils\FormattingUtil;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-/**
- * Changes the results of a select query, doing 1-n joins and unserializing data
- */
-class PostSelectQuerySubscriber implements EventSubscriberInterface {
-
-  /**
-   * @inheritDoc
-   */
-  public static function getSubscribedEvents() {
-    return [
-      Events::POST_SELECT_QUERY => 'onPostQuery',
-    ];
-  }
-
-  /**
-   * @param \Civi\Api4\Event\PostSelectQueryEvent $event
-   */
-  public function onPostQuery(PostSelectQueryEvent $event) {
-    $results = $event->getResults();
-    $event->setResults($this->postRun($results, $event->getQuery()));
-  }
-
-  /**
-   * @param array $results
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   *
-   * @return array
-   */
-  protected function postRun(array $results, Api4SelectQuery $query) {
-    if (empty($results)) {
-      return $results;
-    }
-
-    FormattingUtil::formatOutputValues($results, $query->getApiFieldSpec(), $query->getEntity());
-
-    // Group the selects to avoid queries for each field
-    $groupedSelects = $this->getNtoManyJoinSelects($query);
-    foreach ($groupedSelects as $finalAlias => $selects) {
-      $joinPath = $query->getPathJoinTypes($selects[0]);
-      $selects = $this->formatSelects($finalAlias, $selects, $query);
-      $joinResults = $this->getJoinResults($query, $finalAlias, $selects);
-      $this->formatJoinResults($joinResults, $query, $finalAlias);
-
-      // Insert join results into original result
-      foreach ($results as &$primaryResult) {
-        $baseId = $primaryResult['id'];
-        $filtered = array_filter($joinResults, function ($res) use ($baseId) {
-          return ($res['_base_id'] == $baseId);
-        });
-        $filtered = array_values($filtered);
-        ArrayInsertionUtil::insert($primaryResult, $joinPath, $filtered);
-      }
-    }
-
-    return array_values($results);
-  }
-
-  /**
-   * @param array $joinResults
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   * @param string $alias
-   */
-  private function formatJoinResults(&$joinResults, $query, $alias) {
-    $join = $query->getJoinedTable($alias);
-    $fields = [];
-    foreach ($join->getEntityFields() as $field) {
-      $name = explode('.', $field->getName());
-      $fields[array_pop($name)] = $field->toArray();
-    }
-    if ($fields) {
-      FormattingUtil::formatOutputValues($joinResults, $fields, $join->getEntity());
-    }
-  }
-
-  /**
-   * Find only those joins that need to be handled by a separate query and weren't done in the main query.
-   *
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   *
-   * @return array
-   */
-  private function getNtoManyJoinSelects(Api4SelectQuery $query) {
-    $joinedDotSelects = array_filter(
-      $query->getSelect(),
-      function ($select) use ($query) {
-        return strpos($select, '.') && array_filter($query->getPathJoinTypes($select));
-      }
-    );
-
-    $selects = [];
-    // group related selects by alias so they can be executed in one query
-    foreach ($joinedDotSelects as $select) {
-      $parts = explode('.', $select);
-      $finalAlias = $parts[count($parts) - 2];
-      $selects[$finalAlias][] = $select;
-    }
-
-    // sort by depth, e.g. email selects should be done before email.location
-    uasort($selects, function ($a, $b) {
-      $aFirst = $a[0];
-      $bFirst = $b[0];
-      return substr_count($aFirst, '.') > substr_count($bFirst, '.');
-    });
-
-    return $selects;
-  }
-
-  /**
-   * @param array $selects
-   * @param $serializationType
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   *
-   * @return array
-   */
-  private function getResultsForSerializedField(
-    array $selects,
-    $serializationType,
-    Api4SelectQuery $query
-  ) {
-    // Get the alias (Selects are grouped and all target the same table)
-    $sampleField = current($selects);
-    $alias = strstr($sampleField, '.', TRUE);
-
-    // Fetch the results with the serialized field
-    $selects['serialized'] = $query::MAIN_TABLE_ALIAS . '.' . $alias;
-    $serializedResults = $this->runWithNewSelects($selects, $query);
-    $newResults = [];
-
-    // Create a new results array, with a separate entry for each option value
-    foreach ($serializedResults as $result) {
-      $optionValues = \CRM_Core_DAO::unSerializeField(
-        $result['serialized'],
-        $serializationType
-      );
-      unset($result['serialized']);
-      foreach ($optionValues as $value) {
-        $newResults[] = array_merge($result, ['value' => $value]);
-      }
-    }
-
-    $optionValueValues = array_unique(array_column($newResults, 'value'));
-    $optionValues = $this->getOptionValuesFromValues(
-      $selects,
-      $query,
-      $optionValueValues
-    );
-    $valueField = $alias . '.value';
-
-    // Index by value
-    foreach ($optionValues as $key => $subResult) {
-      $optionValues[$subResult['value']] = $subResult;
-      unset($subResult[$key]);
-
-      // Exclude 'value' if not in original selects
-      if (!in_array($valueField, $selects)) {
-        unset($optionValues[$subResult['value']]['value']);
-      }
-    }
-
-    // Replace serialized with the sub-select results
-    foreach ($newResults as &$result) {
-      $result = array_merge($result, $optionValues[$result['value']]);
-      unset($result['value']);
-    }
-
-    return $newResults;
-  }
-
-  /**
-   * Prepares selects for the subquery to fetch join results
-   *
-   * @param string $alias
-   * @param array $selects
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   *
-   * @return array
-   */
-  private function formatSelects($alias, $selects, Api4SelectQuery $query) {
-    $mainAlias = $query::MAIN_TABLE_ALIAS;
-    $selectFields = [];
-
-    foreach ($selects as $select) {
-      $selectAlias = str_replace('`', '', $query->getField($select)['sql_name']);
-      $fieldAlias = substr($select, strrpos($select, '.') + 1);
-      $selectFields[$fieldAlias] = $selectAlias;
-    }
-
-    $firstSelect = $selects[0];
-    $pathParts = explode('.', $firstSelect);
-    $numParts = count($pathParts);
-    $parentAlias = $numParts > 2 ? $pathParts[$numParts - 3] : $mainAlias;
-
-    $selectFields['id'] = sprintf('%s.id', $alias);
-    $selectFields['_parent_id'] = $parentAlias . '.id';
-    $selectFields['_base_id'] = $mainAlias . '.id';
-
-    return $selectFields;
-  }
-
-  /**
-   * @param array $selects
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   *
-   * @return array
-   */
-  private function runWithNewSelects(array $selects, Api4SelectQuery $query) {
-    $aliasedSelects = array_map(function ($field, $alias) {
-      return sprintf('%s as "%s"', $field, $alias);
-    }, $selects, array_keys($selects));
-
-    $newSelect = sprintf('SELECT DISTINCT %s', implode(", ", $aliasedSelects));
-    $sql = $query->getQuery()->toSQL();
-    // Replace the "SELECT" clause
-    $sql = $newSelect . substr($sql, strpos($sql, "\nFROM"));
-
-    if (is_array($query->debugOutput)) {
-      $query->debugOutput['sql'][] = $sql;
-    }
-
-    $relatedResults = [];
-    $resultDAO = \CRM_Core_DAO::executeQuery($sql);
-    while ($resultDAO->fetch()) {
-      $relatedResult = [];
-      foreach ($selects as $alias => $column) {
-        $returnName = $alias;
-        $alias = str_replace('.', '_', $alias);
-        if (property_exists($resultDAO, $alias)) {
-          $relatedResult[$returnName] = $resultDAO->$alias;
-        }
-      };
-      $relatedResults[] = $relatedResult;
-    }
-
-    return $relatedResults;
-  }
-
-  /**
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   * @param $alias
-   * @param $selects
-   * @return array
-   */
-  protected function getJoinResults(Api4SelectQuery $query, $alias, $selects) {
-    $apiFieldSpec = $query->getApiFieldSpec();
-    if (!empty($apiFieldSpec[$alias]['serialize'])) {
-      $type = $apiFieldSpec[$alias]['serialize'];
-      $joinResults = $this->getResultsForSerializedField($selects, $type, $query);
-    }
-    else {
-      $joinResults = $this->runWithNewSelects($selects, $query);
-    }
-
-    // Remove results with no matching entries
-    $joinResults = array_filter($joinResults, function ($result) {
-      return !empty($result['id']);
-    });
-
-    return $joinResults;
-  }
-
-  /**
-   * Get all the option_value values required in the query
-   *
-   * @param array $selects
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
-   * @param array $values
-   *
-   * @return array
-   */
-  private function getOptionValuesFromValues(
-    array $selects,
-    Api4SelectQuery $query,
-    array $values
-  ) {
-    $sampleField = current($selects);
-    $alias = strstr($sampleField, '.', TRUE);
-
-    // Get the option value table that was joined
-    $relatedTable = NULL;
-    foreach ($query->getJoinedTables() as $joinedTable) {
-      if ($joinedTable->getAlias() === $alias) {
-        $relatedTable = $joinedTable;
-      }
-    }
-
-    // We only want subselects related to the joined table
-    $subSelects = array_filter($selects, function ($select) use ($alias) {
-      return strpos($select, $alias) === 0;
-    });
-
-    // Fetch all related option_value entries
-    $valueField = $alias . '.value';
-    $subSelects[] = $valueField;
-    $tableName = $relatedTable->getTargetTable();
-    $conditions = $relatedTable->getExtraJoinConditions();
-    $conditions[] = $valueField . ' IN ("' . implode('", "', $values) . '")';
-    $subQuery = new \CRM_Utils_SQL_Select($tableName . ' ' . $alias);
-    $subQuery->where($conditions);
-    $subQuery->select($subSelects);
-    $subResults = $subQuery->execute()->fetchAll();
-
-    return $subResults;
-  }
-
-}
diff --git a/civicrm/Civi/Api4/Generic/AbstractEntity.php b/civicrm/Civi/Api4/Generic/AbstractEntity.php
index 74d28bfb33..8a1ed4e862 100644
--- a/civicrm/Civi/Api4/Generic/AbstractEntity.php
+++ b/civicrm/Civi/Api4/Generic/AbstractEntity.php
@@ -66,10 +66,9 @@ abstract class AbstractEntity {
     $permissions = \CRM_Core_Permission::getEntityActionPermissions();
 
     // For legacy reasons the permissions are keyed by lowercase entity name
-    // Note: Convert to camel & back in order to circumvent all the api3 naming oddities
-    $lcentity = _civicrm_api_get_entity_name_from_camel(\CRM_Utils_String::convertStringToCamel(self::getEntityName()));
+    $lcentity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower(self::getEntityName());
     // Merge permissions for this entity with the defaults
-    return \CRM_Utils_Array::value($lcentity, $permissions, []) + $permissions['default'];
+    return ($permissions[$lcentity] ?? []) + $permissions['default'];
   }
 
   /**
diff --git a/civicrm/Civi/Api4/Generic/BasicGetAction.php b/civicrm/Civi/Api4/Generic/BasicGetAction.php
index 20cfe1821a..f1d34d237f 100644
--- a/civicrm/Civi/Api4/Generic/BasicGetAction.php
+++ b/civicrm/Civi/Api4/Generic/BasicGetAction.php
@@ -115,7 +115,7 @@ class BasicGetAction extends AbstractGetAction {
     foreach ($records as &$values) {
       foreach ($this->entityFields() as $field) {
         if (!empty($field['options'])) {
-          foreach (array_keys(FormattingUtil::$pseudoConstantContexts) as $suffix) {
+          foreach (FormattingUtil::$pseudoConstantSuffixes as $suffix) {
             $pseudofield = $field['name'] . ':' . $suffix;
             if (!isset($values[$pseudofield]) && isset($values[$field['name']]) && $this->_isFieldSelected($pseudofield)) {
               $values[$pseudofield] = $values[$field['name']];
diff --git a/civicrm/Civi/Api4/Generic/DAOEntity.php b/civicrm/Civi/Api4/Generic/DAOEntity.php
index 38888227c6..f63c87ba62 100644
--- a/civicrm/Civi/Api4/Generic/DAOEntity.php
+++ b/civicrm/Civi/Api4/Generic/DAOEntity.php
@@ -10,15 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
 namespace Civi\Api4\Generic;
 
 /**
@@ -28,6 +19,8 @@ abstract class DAOEntity extends AbstractEntity {
 
   /**
    * @return DAOGetAction
+   *
+   * @throws \API_Exception
    */
   public static function get() {
     return new DAOGetAction(static::class, __FUNCTION__);
@@ -49,6 +42,8 @@ abstract class DAOEntity extends AbstractEntity {
 
   /**
    * @return DAOCreateAction
+   *
+   * @throws \API_Exception
    */
   public static function create() {
     return new DAOCreateAction(static::class, __FUNCTION__);
diff --git a/civicrm/Civi/Api4/Generic/DAOGetAction.php b/civicrm/Civi/Api4/Generic/DAOGetAction.php
index 73098f5a5c..d922781ada 100644
--- a/civicrm/Civi/Api4/Generic/DAOGetAction.php
+++ b/civicrm/Civi/Api4/Generic/DAOGetAction.php
@@ -45,6 +45,13 @@ class DAOGetAction extends AbstractGetAction {
    */
   protected $select = [];
 
+  /**
+   * Joins to other entities.
+   *
+   * @var array
+   */
+  protected $join = [];
+
   /**
    * Field(s) by which to group the results.
    *
@@ -120,4 +127,32 @@ class DAOGetAction extends AbstractGetAction {
     return $this;
   }
 
+  /**
+   * @param string $entity
+   * @param bool $required
+   * @param array ...$conditions
+   * @return DAOGetAction
+   */
+  public function addJoin(string $entity, bool $required = FALSE, ...$conditions): DAOGetAction {
+    array_unshift($conditions, $entity, $required);
+    $this->join[] = $conditions;
+    return $this;
+  }
+
+  /**
+   * @param array $join
+   * @return DAOGetAction
+   */
+  public function setJoin(array $join): DAOGetAction {
+    $this->join = $join;
+    return $this;
+  }
+
+  /**
+   * @return array
+   */
+  public function getJoin(): array {
+    return $this->join;
+  }
+
 }
diff --git a/civicrm/Civi/Api4/Generic/Traits/CustomValueActionTrait.php b/civicrm/Civi/Api4/Generic/Traits/CustomValueActionTrait.php
index 236cb3fc4d..acf90cdcf5 100644
--- a/civicrm/Civi/Api4/Generic/Traits/CustomValueActionTrait.php
+++ b/civicrm/Civi/Api4/Generic/Traits/CustomValueActionTrait.php
@@ -76,7 +76,7 @@ trait CustomValueActionTrait {
    * @inheritDoc
    */
   protected function deleteObjects($items) {
-    $customTable = CoreUtil::getCustomTableByName($this->getCustomGroup());
+    $customTable = CoreUtil::getTableName($this->getEntityName());
     $ids = [];
     foreach ($items as $item) {
       \CRM_Utils_Hook::pre('delete', $this->getEntityName(), $item['id'], \CRM_Core_DAO::$_nullArray);
diff --git a/civicrm/Civi/Api4/Generic/Traits/DAOActionTrait.php b/civicrm/Civi/Api4/Generic/Traits/DAOActionTrait.php
index 45b572a252..85ac173f5e 100644
--- a/civicrm/Civi/Api4/Generic/Traits/DAOActionTrait.php
+++ b/civicrm/Civi/Api4/Generic/Traits/DAOActionTrait.php
@@ -10,21 +10,13 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
 namespace Civi\Api4\Generic\Traits;
 
 use Civi\Api4\Utils\FormattingUtil;
 
 /**
  * @method string getLanguage()
- * @method setLanguage(string $language)
+ * @method $this setLanguage(string $language)
  */
 trait DAOActionTrait {
 
@@ -103,9 +95,11 @@ trait DAOActionTrait {
    *
    * @param array $items
    *   The records to write to the DB.
+   *
    * @return array
    *   The records after being written to the DB (e.g. including newly assigned "id").
    * @throws \API_Exception
+   * @throws \CRM_Core_Exception
    */
   protected function writeObjects($items) {
     $baoName = $this->getBaoName();
@@ -130,7 +124,7 @@ trait DAOActionTrait {
       $item['check_permissions'] = $this->getCheckPermissions();
 
       // For some reason the contact bao requires this
-      if ($entityId && $this->getEntityName() == 'Contact') {
+      if ($entityId && $this->getEntityName() === 'Contact') {
         $item['contact_id'] = $entityId;
       }
 
@@ -138,7 +132,7 @@ trait DAOActionTrait {
         $this->checkContactPermissions($baoName, $item);
       }
 
-      if ($this->getEntityName() == 'Address') {
+      if ($this->getEntityName() === 'Address') {
         $createResult = $baoName::add($item, $this->fixAddress);
       }
       elseif (method_exists($baoName, $method)) {
@@ -162,7 +156,11 @@ trait DAOActionTrait {
   /**
    * @param array $params
    * @param int $entityId
+   *
    * @return mixed
+   *
+   * @throws \API_Exception
+   * @throws \CRM_Core_Exception
    */
   protected function formatCustomParams(&$params, $entityId) {
     $customParams = [];
@@ -204,7 +202,7 @@ trait DAOActionTrait {
           $value = FormattingUtil::replacePseudoconstant($options, $value, TRUE);
         }
 
-        if ($customFieldType == 'CheckBox') {
+        if ($customFieldType === 'CheckBox') {
           // this function should be part of a class
           formatCheckBoxField($value, 'custom_' . $customFieldId, $this->getEntityName());
         }
@@ -232,13 +230,14 @@ trait DAOActionTrait {
   /**
    * Check edit/delete permissions for contacts and related entities.
    *
-   * @param $baoName
-   * @param $item
+   * @param string $baoName
+   * @param array $item
+   *
    * @throws \Civi\API\Exception\UnauthorizedException
    */
   protected function checkContactPermissions($baoName, $item) {
-    if ($baoName == 'CRM_Contact_BAO_Contact' && !empty($item['id'])) {
-      $permission = $this->getActionName() == 'delete' ? \CRM_Core_Permission::DELETE : \CRM_Core_Permission::EDIT;
+    if ($baoName === 'CRM_Contact_BAO_Contact' && !empty($item['id'])) {
+      $permission = $this->getActionName() === 'delete' ? \CRM_Core_Permission::DELETE : \CRM_Core_Permission::EDIT;
       if (!\CRM_Contact_BAO_Contact_Permission::allow($item['id'], $permission)) {
         throw new \Civi\API\Exception\UnauthorizedException('Permission denied to modify contact record');
       }
diff --git a/civicrm/Civi/Api4/LocationType.php b/civicrm/Civi/Api4/LocationType.php
index 836e59463f..cef5221620 100644
--- a/civicrm/Civi/Api4/LocationType.php
+++ b/civicrm/Civi/Api4/LocationType.php
@@ -10,15 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
 namespace Civi\Api4;
 
 /**
diff --git a/civicrm/Civi/Api4/MembershipType.php b/civicrm/Civi/Api4/MembershipType.php
new file mode 100644
index 0000000000..293c9602c1
--- /dev/null
+++ b/civicrm/Civi/Api4/MembershipType.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Api4;
+
+/**
+ * MembershipType entity.
+ *
+ * @package Civi\Api4
+ */
+class MembershipType extends Generic\DAOEntity {
+
+}
diff --git a/civicrm/Civi/Api4/PriceField.php b/civicrm/Civi/Api4/PriceField.php
new file mode 100644
index 0000000000..66aaa4428a
--- /dev/null
+++ b/civicrm/Civi/Api4/PriceField.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Api4;
+
+/**
+ * PriceField entity.
+ *
+ * @package Civi\Api4
+ */
+class PriceField extends Generic\DAOEntity {
+
+}
diff --git a/civicrm/Civi/Api4/PriceFieldValue.php b/civicrm/Civi/Api4/PriceFieldValue.php
new file mode 100644
index 0000000000..851abbcf6e
--- /dev/null
+++ b/civicrm/Civi/Api4/PriceFieldValue.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Api4;
+
+/**
+ * PriceFieldValue entity.
+ *
+ * @package Civi\Api4
+ */
+class PriceFieldValue extends Generic\DAOEntity {
+
+}
diff --git a/civicrm/Civi/Api4/PriceSet.php b/civicrm/Civi/Api4/PriceSet.php
new file mode 100644
index 0000000000..91a7e27d91
--- /dev/null
+++ b/civicrm/Civi/Api4/PriceSet.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Api4;
+
+/**
+ * PriceSet entity.
+ *
+ * @package Civi\Api4
+ */
+class PriceSet extends Generic\DAOEntity {
+
+}
diff --git a/civicrm/Civi/Api4/Query/Api4SelectQuery.php b/civicrm/Civi/Api4/Query/Api4SelectQuery.php
index d7e6da44c8..794df9580a 100644
--- a/civicrm/Civi/Api4/Query/Api4SelectQuery.php
+++ b/civicrm/Civi/Api4/Query/Api4SelectQuery.php
@@ -12,15 +12,10 @@
 namespace Civi\Api4\Query;
 
 use Civi\API\SelectQuery;
-use Civi\Api4\Event\Events;
-use Civi\Api4\Event\PostSelectQueryEvent;
 use Civi\Api4\Service\Schema\Joinable\CustomGroupJoinable;
-use Civi\Api4\Service\Schema\Joinable\Joinable;
-use Civi\Api4\Service\Schema\Joinable\OptionValueJoinable;
 use Civi\Api4\Utils\FormattingUtil;
 use Civi\Api4\Utils\CoreUtil;
 use Civi\Api4\Utils\SelectUtil;
-use CRM_Core_DAO_AllCoreTables as AllCoreTables;
 
 /**
  * A query `node` may be in one of three formats:
@@ -42,12 +37,6 @@ class Api4SelectQuery extends SelectQuery {
    */
   protected $apiVersion = 4;
 
-  /**
-   * @var \Civi\Api4\Service\Schema\Joinable\Joinable[]
-   *   The joinable tables that have been joined so far
-   */
-  protected $joinedTables = [];
-
   /**
    * @var array
    * [alias => expr][]
@@ -91,17 +80,20 @@ class Api4SelectQuery extends SelectQuery {
     if ($apiGet->getDebug()) {
       $this->debugOutput =& $apiGet->_debugOutput;
     }
-    $baoName = CoreUtil::getBAOFromApiName($this->entity);
-    $this->entityFieldNames = array_column($baoName::fields(), 'name');
-    foreach ($apiGet->entityFields() as $path => $field) {
+    foreach ($apiGet->entityFields() as $field) {
+      $this->entityFieldNames[] = $field['name'];
       $field['sql_name'] = '`' . self::MAIN_TABLE_ALIAS . '`.`' . $field['column_name'] . '`';
-      $this->addSpecField($path, $field);
+      $this->addSpecField($field['name'], $field);
     }
 
-    $this->constructQueryObject($baoName);
+    $baoName = CoreUtil::getBAOFromApiName($this->entity);
+    $this->constructQueryObject();
 
     // Add ACLs first to avoid redundant subclauses
     $this->query->where($this->getAclClause(self::MAIN_TABLE_ALIAS, $baoName));
+
+    // Add explicit joins. Other joins implied by dot notation may be added later
+    $this->addExplicitJoins($apiGet->getJoin());
   }
 
   /**
@@ -134,24 +126,21 @@ class Api4SelectQuery extends SelectQuery {
       $this->debugOutput['sql'][] = $sql;
     }
     $query = \CRM_Core_DAO::executeQuery($sql);
-    $i = 0;
     while ($query->fetch()) {
-      $id = $query->id ?? $i++;
       if (in_array('row_count', $this->select)) {
         $results[]['row_count'] = (int) $query->c;
         break;
       }
-      $results[$id] = [];
+      $result = [];
       foreach ($this->selectAliases as $alias => $expr) {
         $returnName = $alias;
         $alias = str_replace('.', '_', $alias);
-        $results[$id][$returnName] = property_exists($query, $alias) ? $query->$alias : NULL;
+        $result[$returnName] = property_exists($query, $alias) ? $query->$alias : NULL;
       }
+      $results[] = $result;
     }
-    $event = new PostSelectQueryEvent($results, $this);
-    \Civi::dispatcher()->dispatch(Events::POST_SELECT_QUERY, $event);
-
-    return $event->getResults();
+    FormattingUtil::formatOutputValues($results, $this->getApiFieldSpec(), $this->getEntity());
+    return $results;
   }
 
   protected function buildSelectClause() {
@@ -174,7 +163,7 @@ class Api4SelectQuery extends SelectQuery {
       });
       foreach ($wildFields as $item) {
         $pos = array_search($item, array_values($this->select));
-        $this->joinFK($item);
+        $this->autoJoinFK($item);
         $matches = SelectUtil::getMatchingFields($item, array_keys($this->apiFieldSpec));
         array_splice($this->select, $pos, 1, $matches);
       }
@@ -193,9 +182,6 @@ class Api4SelectQuery extends SelectQuery {
           }
           $valid = FALSE;
         }
-        elseif ($field['is_many']) {
-          $valid = FALSE;
-        }
       }
       if ($valid) {
         $alias = $expr->getAlias();
@@ -236,11 +222,20 @@ class Api4SelectQuery extends SelectQuery {
       if ($dir !== 'ASC' && $dir !== 'DESC') {
         throw new \API_Exception("Invalid sort direction. Cannot order by $item $dir");
       }
-      $expr = SqlExpression::convert($item);
-      foreach ($expr->getFields() as $fieldName) {
-        $this->getField($fieldName, TRUE);
+      $expr = $this->getExpression($item);
+      $column = $expr->render($this->apiFieldSpec);
+
+      // Use FIELD() function to sort on pseudoconstant values
+      $suffix = strstr($item, ':');
+      if ($suffix && $expr->getType() === 'SqlField') {
+        $field = $this->getField($item);
+        $options = FormattingUtil::getPseudoconstantList($field['entity'], $field['name'], substr($suffix, 1));
+        if ($options) {
+          asort($options);
+          $column = "FIELD($column,'" . implode("','", array_keys($options)) . "')";
+        }
       }
-      $this->query->orderBy($expr->render($this->apiFieldSpec) . " $dir");
+      $this->query->orderBy("$column $dir");
     }
   }
 
@@ -259,11 +254,7 @@ class Api4SelectQuery extends SelectQuery {
    */
   protected function buildGroupBy() {
     foreach ($this->groupBy as $item) {
-      $expr = SqlExpression::convert($item);
-      foreach ($expr->getFields() as $fieldName) {
-        $this->getField($fieldName, TRUE);
-      }
-      $this->query->groupBy($expr->render($this->apiFieldSpec));
+      $this->query->groupBy($this->getExpression($item)->render($this->apiFieldSpec));
     }
   }
 
@@ -272,7 +263,7 @@ class Api4SelectQuery extends SelectQuery {
    *
    * @param array $clause
    * @param string $type
-   *   WHERE|HAVING
+   *   WHERE|HAVING|ON
    * @return string SQL where clause
    *
    * @throws \API_Exception
@@ -311,7 +302,7 @@ class Api4SelectQuery extends SelectQuery {
    * Validate and transform a leaf clause array to SQL.
    * @param array $clause [$fieldName, $operator, $criteria]
    * @param string $type
-   *   WHERE|HAVING
+   *   WHERE|HAVING|ON
    * @return string SQL
    * @throws \API_Exception
    * @throws \Exception
@@ -319,6 +310,9 @@ class Api4SelectQuery extends SelectQuery {
   protected function composeClause(array $clause, string $type) {
     // Pad array for unary operators
     list($expr, $operator, $value) = array_pad($clause, 3, NULL);
+    if (!in_array($operator, \CRM_Core_DAO::acceptedSQLOperators(), TRUE)) {
+      throw new \API_Exception('Illegal operator');
+    }
 
     // For WHERE clause, expr must be the name of a field.
     if ($type === 'WHERE') {
@@ -327,7 +321,7 @@ class Api4SelectQuery extends SelectQuery {
       $fieldAlias = $field['sql_name'];
     }
     // For HAVING, expr must be an item in the SELECT clause
-    else {
+    elseif ($type === 'HAVING') {
       // Expr references a fieldName or alias
       if (isset($this->selectAliases[$expr])) {
         $fieldAlias = $expr;
@@ -357,6 +351,21 @@ class Api4SelectQuery extends SelectQuery {
       }
       $fieldAlias = '`' . $fieldAlias . '`';
     }
+    elseif ($type === 'ON') {
+      $expr = $this->getExpression($expr);
+      $fieldName = count($expr->getFields()) === 1 ? $expr->getFields()[0] : NULL;
+      $fieldAlias = $expr->render($this->apiFieldSpec);
+      if (is_string($value)) {
+        $valExpr = $this->getExpression($value);
+        if ($fieldName && $valExpr->getType() === 'SqlString') {
+          FormattingUtil::formatInputValue($valExpr->expr, $fieldName, $this->apiFieldSpec[$fieldName]);
+        }
+        return sprintf('%s %s %s', $fieldAlias, $operator, $valExpr->render($this->apiFieldSpec));
+      }
+      elseif ($fieldName) {
+        FormattingUtil::formatInputValue($value, $fieldName, $this->apiFieldSpec[$fieldName]);
+      }
+    }
 
     $sql_clause = \CRM_Core_DAO::createSQLFilter($fieldAlias, [$operator => $value]);
     if ($sql_clause === NULL) {
@@ -365,6 +374,19 @@ class Api4SelectQuery extends SelectQuery {
     return $sql_clause;
   }
 
+  /**
+   * @param string $expr
+   * @return SqlExpression
+   * @throws \API_Exception
+   */
+  protected function getExpression(string $expr) {
+    $sqlExpr = SqlExpression::convert($expr);
+    foreach ($sqlExpr->getFields() as $fieldName) {
+      $this->getField($fieldName, TRUE);
+    }
+    return $sqlExpr;
+  }
+
   /**
    * @inheritDoc
    */
@@ -389,7 +411,7 @@ class Api4SelectQuery extends SelectQuery {
     $fieldName = $col ? substr($expr, 0, $col) : $expr;
     // Perform join if field not yet available - this will add it to apiFieldSpec
     if (!isset($this->apiFieldSpec[$fieldName]) && strpos($fieldName, '.')) {
-      $this->joinFK($fieldName);
+      $this->autoJoinFK($fieldName);
     }
     $field = $this->apiFieldSpec[$fieldName] ?? NULL;
     if ($strict && !$field) {
@@ -400,13 +422,78 @@ class Api4SelectQuery extends SelectQuery {
   }
 
   /**
-   * Joins a path and adds all fields in the joined eneity to apiFieldSpec
+   * Join onto other entities as specified by the api call.
+   *
+   * @param $joins
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\NotImplementedException
+   */
+  private function addExplicitJoins($joins) {
+    foreach ($joins as $join) {
+      // First item in the array is the entity name
+      $entity = array_shift($join);
+      // Which might contain an alias. Split on the keyword "AS"
+      list($entity, $alias) = array_pad(explode(' AS ', $entity), 2, NULL);
+      // Ensure alias is a safe string, and supply default if not given
+      $alias = $alias ? \CRM_Utils_String::munge($alias) : strtolower($entity);
+      // First item in the array is a boolean indicating if the join is required (aka INNER or LEFT).
+      // The rest are join conditions.
+      $side = array_shift($join) ? 'INNER' : 'LEFT';
+      $joinEntityGet = \Civi\API\Request::create($entity, 'get', ['version' => 4, 'checkPermissions' => $this->checkPermissions]);
+      foreach ($joinEntityGet->entityFields() as $field) {
+        $field['sql_name'] = '`' . $alias . '`.`' . $field['column_name'] . '`';
+        $field['is_join'] = TRUE;
+        $this->addSpecField($alias . '.' . $field['name'], $field);
+      }
+      $conditions = $this->getJoinConditions($entity, $alias);
+      foreach (array_filter($join) as $clause) {
+        $conditions[] = $this->treeWalkClauses($clause, 'ON');
+      }
+      $tableName = CoreUtil::getTableName($entity);
+      $this->join($side, $tableName, $alias, $conditions);
+    }
+  }
+
+  /**
+   * Supply conditions for an explicit join.
+   *
+   * @param $entity
+   * @param $alias
+   * @return array
+   */
+  private function getJoinConditions($entity, $alias) {
+    $conditions = [];
+    // getAclClause() expects a stack of 1-to-1 join fields to help it dedupe, but this is more flexible,
+    // so unless this is a direct 1-to-1 join with the main entity, we'll just hack it
+    // with a padded empty stack to bypass its deduping.
+    $stack = [NULL, NULL];
+    foreach ($this->apiFieldSpec as $name => $field) {
+      if ($field['entity'] !== $entity && $field['fk_entity'] === $entity) {
+        $conditions[] = $this->treeWalkClauses([$name, '=', "$alias.id"], 'ON');
+      }
+      elseif (strpos($name, "$alias.") === 0 && substr_count($name, '.') === 1 &&  $field['fk_entity'] === $this->entity) {
+        $conditions[] = $this->treeWalkClauses([$name, '=', 'id'], 'ON');
+        $stack = ['id'];
+      }
+    }
+    // Hmm, if we came up with > 1 condition, then it's ambiguous how it should be joined so we won't return anything but the generic ACLs
+    if (count($conditions) > 1) {
+      $stack = [NULL, NULL];
+      $conditions = [];
+    }
+    $baoName = CoreUtil::getBAOFromApiName($entity);
+    $acls = array_values($this->getAclClause($alias, $baoName, $stack));
+    return array_merge($acls, $conditions);
+  }
+
+  /**
+   * Joins a path and adds all fields in the joined entity to apiFieldSpec
    *
    * @param $key
    * @throws \API_Exception
    * @throws \Exception
    */
-  protected function joinFK($key) {
+  protected function autoJoinFK($key) {
     if (isset($this->apiFieldSpec[$key])) {
       return;
     }
@@ -419,23 +506,12 @@ class Api4SelectQuery extends SelectQuery {
     array_pop($pathArray);
     $pathString = implode('.', $pathArray);
 
-    if (!$joiner->canJoin($this, $pathString)) {
+    if (!$joiner->canAutoJoin($this->getFrom(), $pathString)) {
       return;
     }
 
     $joinPath = $joiner->join($this, $pathString);
 
-    $isMany = FALSE;
-    foreach ($joinPath as $joinable) {
-      if ($joinable->getJoinType() === Joinable::JOIN_TYPE_ONE_TO_MANY) {
-        $isMany = TRUE;
-      }
-      if ($joinable instanceof OptionValueJoinable) {
-        \Civi::log()->warning('Use API pseudoconstant suffix like :name or :label instead of join.', ['civi.tag' => 'deprecated']);
-      }
-    }
-
-    /** @var \Civi\Api4\Service\Schema\Joinable\Joinable $lastLink */
     $lastLink = array_pop($joinPath);
 
     // Custom field names are already prefixed
@@ -445,33 +521,20 @@ class Api4SelectQuery extends SelectQuery {
     }
     $prefix = $pathArray ? implode('.', $pathArray) . '.' : '';
     // Cache field info for retrieval by $this->getField()
-    $joinEntity = $lastLink->getEntity();
     foreach ($lastLink->getEntityFields() as $fieldObject) {
-      $fieldArray = ['entity' => $joinEntity] + $fieldObject->toArray();
+      $fieldArray = $fieldObject->toArray();
       $fieldArray['sql_name'] = '`' . $lastLink->getAlias() . '`.`' . $fieldArray['column_name'] . '`';
       $fieldArray['is_custom'] = $isCustom;
       $fieldArray['is_join'] = TRUE;
-      $fieldArray['is_many'] = $isMany;
       $this->addSpecField($prefix . $fieldArray['name'], $fieldArray);
     }
   }
 
-  /**
-   * @param \Civi\Api4\Service\Schema\Joinable\Joinable $joinable
-   *
-   * @return $this
-   */
-  public function addJoinedTable(Joinable $joinable) {
-    $this->joinedTables[] = $joinable;
-
-    return $this;
-  }
-
   /**
    * @return FALSE|string
    */
   public function getFrom() {
-    return AllCoreTables::getTableForClass(AllCoreTables::getFullName($this->entity));
+    return CoreUtil::getTableName($this->entity);
   }
 
   /**
@@ -523,13 +586,6 @@ class Api4SelectQuery extends SelectQuery {
     return $this->selectFields;
   }
 
-  /**
-   * @return bool
-   */
-  public function isFillUniqueFields() {
-    return $this->isFillUniqueFields;
-  }
-
   /**
    * @return \CRM_Utils_SQL_Select
    */
@@ -579,85 +635,14 @@ class Api4SelectQuery extends SelectQuery {
     return $this->apiVersion;
   }
 
-  /**
-   * @return \Civi\Api4\Service\Schema\Joinable\Joinable[]
-   */
-  public function getJoinedTables() {
-    return $this->joinedTables;
-  }
-
-  /**
-   * @return \Civi\Api4\Service\Schema\Joinable\Joinable
-   */
-  public function getJoinedTable($alias) {
-    foreach ($this->joinedTables as $join) {
-      if ($join->getAlias() == $alias) {
-        return $join;
-      }
-    }
-  }
-
   /**
    * Get table name on basis of entity
    *
-   * @param string $baoName
-   *
    * @return void
    */
-  public function constructQueryObject($baoName) {
-    if (strstr($this->entity, 'Custom_')) {
-      $this->query = \CRM_Utils_SQL_Select::from(CoreUtil::getCustomTableByName(str_replace('Custom_', '', $this->entity)) . ' ' . self::MAIN_TABLE_ALIAS);
-      $this->entityFieldNames = array_keys($this->apiFieldSpec);
-    }
-    else {
-      $bao = new $baoName();
-      $this->query = \CRM_Utils_SQL_Select::from($bao->tableName() . ' ' . self::MAIN_TABLE_ALIAS);
-    }
-  }
-
-  /**
-   * Checks if a field either belongs to the main entity or is joinable 1-to-1.
-   *
-   * Used to determine if a field can be added to the SELECT of the main query,
-   * or if it must be fetched post-query.
-   *
-   * @param string $fieldPath
-   * @return bool
-   */
-  public function isOneToOneField(string $fieldPath) {
-    return strpos($fieldPath, '.') === FALSE || !array_filter($this->getPathJoinTypes($fieldPath));
-  }
-
-  /**
-   * Separates a string like 'emails.location_type.label' into an array, where
-   * each value in the array tells whether it is 1-1 or 1-n join type
-   *
-   * @param string $pathString
-   *   Dot separated path to the field
-   *
-   * @return array
-   *   Index is table alias and value is boolean whether is 1-to-many join
-   */
-  public function getPathJoinTypes($pathString) {
-    $pathParts = explode('.', $pathString);
-    // remove field
-    array_pop($pathParts);
-    $path = [];
-    $query = $this;
-    $isMultipleChecker = function($alias) use ($query) {
-      foreach ($query->getJoinedTables() as $table) {
-        if ($table->getAlias() === $alias) {
-          return $table->getJoinType() === Joinable::JOIN_TYPE_ONE_TO_MANY;
-        }
-      }
-      return FALSE;
-    };
-
-    foreach ($pathParts as $part) {
-      $path[$part] = $isMultipleChecker($part);
-    }
-
-    return $path;
+  public function constructQueryObject() {
+    $tableName = CoreUtil::getTableName($this->entity);
+    $this->query = \CRM_Utils_SQL_Select::from($tableName . ' ' . self::MAIN_TABLE_ALIAS);
   }
 
   /**
@@ -671,7 +656,7 @@ class Api4SelectQuery extends SelectQuery {
       return;
     }
     $defaults = [];
-    $defaults['is_custom'] = $defaults['is_join'] = $defaults['is_many'] = FALSE;
+    $defaults['is_custom'] = $defaults['is_join'] = FALSE;
     $field += $defaults;
     $this->apiFieldSpec[$path] = $field;
   }
diff --git a/civicrm/Civi/Api4/Query/SqlExpression.php b/civicrm/Civi/Api4/Query/SqlExpression.php
index e21f3880f4..2759d3baff 100644
--- a/civicrm/Civi/Api4/Query/SqlExpression.php
+++ b/civicrm/Civi/Api4/Query/SqlExpression.php
@@ -35,7 +35,7 @@ abstract class SqlExpression {
    * The raw expression, minus the alias.
    * @var string
    */
-  protected $expr = '';
+  public $expr = '';
 
   /**
    * SqlFunction constructor.
@@ -148,4 +148,14 @@ abstract class SqlExpression {
     return $this->alias ?? $this->fields[0] ?? \CRM_Utils_String::munge($this->expr);
   }
 
+  /**
+   * Returns the name of this sql expression class.
+   *
+   * @return string
+   */
+  public function getType(): string {
+    $className = get_class($this);
+    return substr($className, strrpos($className, '\\') + 1);
+  }
+
 }
diff --git a/civicrm/Civi/Api4/Result/ReplaceResult.php b/civicrm/Civi/Api4/Result/ReplaceResult.php
index c1d6522f86..890a2a87e0 100644
--- a/civicrm/Civi/Api4/Result/ReplaceResult.php
+++ b/civicrm/Civi/Api4/Result/ReplaceResult.php
@@ -10,16 +10,13 @@
  +--------------------------------------------------------------------+
  */
 
+namespace Civi\Api4\Result;
+
 /**
+ * Class ReplaceResult
  *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * @package Civi\Api4\Result
  */
-
-namespace Civi\Api4\Result;
-
 class ReplaceResult extends \Civi\Api4\Generic\Result {
   /**
    * @var array
diff --git a/civicrm/Civi/Api4/Service/Schema/Joinable/CustomGroupJoinable.php b/civicrm/Civi/Api4/Service/Schema/Joinable/CustomGroupJoinable.php
index fd5ab30f9d..61b38dccd1 100644
--- a/civicrm/Civi/Api4/Service/Schema/Joinable/CustomGroupJoinable.php
+++ b/civicrm/Civi/Api4/Service/Schema/Joinable/CustomGroupJoinable.php
@@ -41,15 +41,17 @@ class CustomGroupJoinable extends Joinable {
    * @param $targetTable
    * @param $alias
    * @param bool $isMultiRecord
-   * @param string $entity
    * @param string $columns
    */
-  public function __construct($targetTable, $alias, $isMultiRecord, $entity, $columns) {
-    $this->entity = $entity;
+  public function __construct($targetTable, $alias, $isMultiRecord, $columns) {
     $this->columns = $columns;
     parent::__construct($targetTable, 'entity_id', $alias);
     $this->joinType = $isMultiRecord ?
       self::JOIN_TYPE_ONE_TO_MANY : self::JOIN_TYPE_ONE_TO_ONE;
+    // Only multi-record groups are considered an api "entity"
+    if (!$isMultiRecord) {
+      $this->entity = NULL;
+    }
   }
 
   /**
@@ -59,11 +61,11 @@ class CustomGroupJoinable extends Joinable {
     if (!$this->entityFields) {
       $fields = CustomField::get()
         ->setCheckPermissions(FALSE)
-        ->setSelect(['custom_group.name', '*'])
+        ->setSelect(['custom_group.name', 'custom_group.extends', 'custom_group.table_name', '*'])
         ->addWhere('custom_group.table_name', '=', $this->getTargetTable())
         ->execute();
       foreach ($fields as $field) {
-        $this->entityFields[] = \Civi\Api4\Service\Spec\SpecFormatter::arrayToField($field, $this->getEntity());
+        $this->entityFields[] = \Civi\Api4\Service\Spec\SpecFormatter::arrayToField($field, $this->getEntityFromExtends($field['custom_group.extends']));
       }
     }
     return $this->entityFields;
@@ -92,4 +94,25 @@ class CustomGroupJoinable extends Joinable {
     return $this->columns[$fieldName];
   }
 
+  /**
+   * Translate custom_group.extends to entity name.
+   *
+   * Custom_group.extends pretty much maps 1-1 with entity names, except for a couple oddballs.
+   * @see \CRM_Core_SelectValues::customGroupExtends
+   *
+   * @param $extends
+   * @return string
+   * @throws \API_Exception
+   * @throws \Civi\API\Exception\UnauthorizedException
+   */
+  private function getEntityFromExtends($extends) {
+    if (strpos($extends, 'Participant') === 0) {
+      return 'Participant';
+    }
+    if ($extends === 'Contact' || in_array($extends, \CRM_Contact_BAO_ContactType::basicTypes(TRUE))) {
+      return 'Contact';
+    }
+    return $extends;
+  }
+
 }
diff --git a/civicrm/Civi/Api4/Service/Schema/Joinable/OptionValueJoinable.php b/civicrm/Civi/Api4/Service/Schema/Joinable/OptionValueJoinable.php
deleted file mode 100644
index 6b9b539faa..0000000000
--- a/civicrm/Civi/Api4/Service/Schema/Joinable/OptionValueJoinable.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-/*
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC. All rights reserved.                        |
- |                                                                    |
- | This work is published under the GNU AGPLv3 license with some      |
- | permitted exceptions and without any warranty. For full license    |
- | and copyright information, see https://civicrm.org/licensing       |
- +--------------------------------------------------------------------+
- */
-
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
-namespace Civi\Api4\Service\Schema\Joinable;
-
-class OptionValueJoinable extends Joinable {
-  /**
-   * @var string
-   */
-  protected $optionGroupName;
-
-  /**
-   * @param string $optionGroup
-   *   Can be either the option group name or ID
-   * @param string|null $alias
-   *   The join alias
-   * @param string $keyColumn
-   *   Which column to use to join, defaults to "value"
-   */
-  public function __construct($optionGroup, $alias = NULL, $keyColumn = 'value') {
-    $this->optionGroupName = $optionGroup;
-    $optionValueTable = 'civicrm_option_value';
-
-    // default join alias to option group name, e.g. activity_type
-    if (!$alias && !is_numeric($optionGroup)) {
-      $alias = $optionGroup;
-    }
-
-    parent::__construct($optionValueTable, $keyColumn, $alias);
-
-    if (!is_numeric($optionGroup)) {
-      $subSelect = 'SELECT id FROM civicrm_option_group WHERE name = "%s"';
-      $subQuery = sprintf($subSelect, $optionGroup);
-      $condition = sprintf('%s.option_group_id = (%s)', $alias, $subQuery);
-    }
-    else {
-      $condition = sprintf('%s.option_group_id = %d', $alias, $optionGroup);
-    }
-
-    $this->addCondition($condition);
-  }
-
-  /**
-   * The existing condition must also be re-aliased
-   *
-   * @param string $alias
-   *
-   * @return $this
-   */
-  public function setAlias($alias) {
-    foreach ($this->conditions as $index => $condition) {
-      $search = $this->alias . '.';
-      $replace = $alias . '.';
-      $this->conditions[$index] = str_replace($search, $replace, $condition);
-    }
-
-    parent::setAlias($alias);
-
-    return $this;
-  }
-
-}
diff --git a/civicrm/Civi/Api4/Service/Schema/Joiner.php b/civicrm/Civi/Api4/Service/Schema/Joiner.php
index 6333e14a77..4bd59de171 100644
--- a/civicrm/Civi/Api4/Service/Schema/Joiner.php
+++ b/civicrm/Civi/Api4/Service/Schema/Joiner.php
@@ -60,10 +60,14 @@ class Joiner {
     foreach ($fullPath as $link) {
       $target = $link->getTargetTable();
       $alias = $link->getAlias();
+      $bao = \CRM_Core_DAO_AllCoreTables::getBAOClassName(\CRM_Core_DAO_AllCoreTables::getClassForTable($target));
       $conditions = $link->getConditionsForJoin($baseTable);
+      // Custom fields do not have a bao, and currently do not have field-specific ACLs
+      if ($bao) {
+        $conditions = array_merge($conditions, $query->getAclClause($alias, $bao, explode('.', $joinPath)));
+      }
 
       $query->join($side, $target, $alias, $conditions);
-      $query->addJoinedTable($link);
 
       $baseTable = $link->getAlias();
     }
@@ -72,20 +76,33 @@ class Joiner {
   }
 
   /**
-   * @param \Civi\Api4\Query\Api4SelectQuery $query
+   * Determines if path string points to a simple n-1 join that can be automatically added
+   *
+   * @param string $baseTable
    * @param $joinPath
    *
    * @return bool
    */
-  public function canJoin(Api4SelectQuery $query, $joinPath) {
-    return !empty($this->getPath($query->getFrom(), $joinPath));
+  public function canAutoJoin($baseTable, $joinPath) {
+    try {
+      $path = $this->getPath($baseTable, $joinPath);
+      foreach ($path as $joinable) {
+        if ($joinable->getJoinType() === $joinable::JOIN_TYPE_ONE_TO_MANY) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    catch (\Exception $e) {
+      return FALSE;
+    }
   }
 
   /**
    * @param string $baseTable
    * @param string $joinPath
    *
-   * @return array
+   * @return \Civi\Api4\Service\Schema\Joinable\Joinable[]
    * @throws \Exception
    */
   protected function getPath($baseTable, $joinPath) {
diff --git a/civicrm/Civi/Api4/Service/Schema/SchemaMapBuilder.php b/civicrm/Civi/Api4/Service/Schema/SchemaMapBuilder.php
index 74dc0f3453..afecc01056 100644
--- a/civicrm/Civi/Api4/Service/Schema/SchemaMapBuilder.php
+++ b/civicrm/Civi/Api4/Service/Schema/SchemaMapBuilder.php
@@ -27,7 +27,6 @@ use Civi\Api4\Event\SchemaMapBuildEvent;
 use Civi\Api4\Service\Schema\Joinable\CustomGroupJoinable;
 use Civi\Api4\Service\Schema\Joinable\Joinable;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Civi\Api4\Service\Schema\Joinable\OptionValueJoinable;
 use CRM_Core_DAO_AllCoreTables as AllCoreTables;
 
 class SchemaMapBuilder {
@@ -99,41 +98,6 @@ class SchemaMapBuilder {
       $joinable->setJoinType($joinable::JOIN_TYPE_MANY_TO_ONE);
       $table->addTableLink($field, $joinable);
     }
-    elseif (!empty($data['pseudoconstant'])) {
-      $this->addPseudoConstantJoin($table, $field, $data);
-    }
-  }
-
-  /**
-   * @param Table $table
-   * @param string $field
-   * @param array $data
-   */
-  private function addPseudoConstantJoin(Table $table, $field, array $data) {
-    $pseudoConstant = $data['pseudoconstant'] ?? NULL;
-    $tableName = $pseudoConstant['table'] ?? NULL;
-    $optionGroupName = $pseudoConstant['optionGroupName'] ?? NULL;
-    $keyColumn = $pseudoConstant['keyColumn'] ?? 'id';
-
-    if ($tableName) {
-      $alias = str_replace('civicrm_', '', $tableName);
-      $joinable = new Joinable($tableName, $keyColumn, $alias);
-      $condition = $pseudoConstant['condition'] ?? NULL;
-      if ($condition) {
-        $joinable->addCondition($condition);
-      }
-      $table->addTableLink($field, $joinable);
-    }
-    elseif ($optionGroupName) {
-      $keyColumn = $pseudoConstant['keyColumn'] ?? 'value';
-      $joinable = new OptionValueJoinable($optionGroupName, NULL, $keyColumn);
-
-      if (!empty($data['serialize'])) {
-        $joinable->setJoinType($joinable::JOIN_TYPE_ONE_TO_MANY);
-      }
-
-      $table->addTableLink($field, $joinable);
-    }
   }
 
   /**
@@ -144,17 +108,15 @@ class SchemaMapBuilder {
   private function addBackReferences(SchemaMap $map) {
     foreach ($map->getTables() as $table) {
       foreach ($table->getTableLinks() as $link) {
-        // there are too many possible joins from option value so skip
-        if ($link instanceof OptionValueJoinable) {
-          continue;
-        }
-
         $target = $map->getTableByName($link->getTargetTable());
         $tableName = $link->getBaseTable();
-        $plural = str_replace('civicrm_', '', $this->getPlural($tableName));
-        $joinable = new Joinable($tableName, $link->getBaseColumn(), $plural);
-        $joinable->setJoinType($joinable::JOIN_TYPE_ONE_TO_MANY);
-        $target->addTableLink($link->getTargetColumn(), $joinable);
+        // Exclude custom field tables
+        if (strpos($link->getTargetTable(), 'civicrm_value_') !== 0 && strpos($link->getBaseTable(), 'civicrm_value_') !== 0) {
+          $plural = str_replace('civicrm_', '', $this->getPlural($tableName));
+          $joinable = new Joinable($tableName, $link->getBaseColumn(), $plural);
+          $joinable->setJoinType($joinable::JOIN_TYPE_ONE_TO_MANY);
+          $target->addTableLink($link->getTargetColumn(), $joinable);
+        }
       }
     }
   }
@@ -213,21 +175,22 @@ class SchemaMapBuilder {
         $customTable = new Table($tableName);
       }
 
-      if (!empty($fieldData->option_group_id)) {
-        $optionValueJoinable = new OptionValueJoinable($fieldData->option_group_id, $fieldData->label);
-        $customTable->addTableLink($fieldData->column_name, $optionValueJoinable);
-      }
-
       $map->addTable($customTable);
 
       $alias = $fieldData->custom_group_name;
       $links[$alias]['tableName'] = $tableName;
       $links[$alias]['isMultiple'] = !empty($fieldData->is_multiple);
       $links[$alias]['columns'][$fieldData->name] = $fieldData->column_name;
+
+      // Add backreference
+      if (!empty($fieldData->is_multiple)) {
+        $joinable = new Joinable($baseTable->getName(), 'id', AllCoreTables::convertEntityNameToLower($entity));
+        $customTable->addTableLink('entity_id', $joinable);
+      }
     }
 
     foreach ($links as $alias => $link) {
-      $joinable = new CustomGroupJoinable($link['tableName'], $alias, $link['isMultiple'], $entity, $link['columns']);
+      $joinable = new CustomGroupJoinable($link['tableName'], $alias, $link['isMultiple'], $link['columns']);
       $baseTable->addTableLink('id', $joinable);
     }
   }
diff --git a/civicrm/Civi/Api4/Service/Spec/Provider/ContactTypeCreationSpecProvider.php b/civicrm/Civi/Api4/Service/Spec/Provider/ContactTypeCreationSpecProvider.php
index 1e45728d8c..891fe67920 100644
--- a/civicrm/Civi/Api4/Service/Spec/Provider/ContactTypeCreationSpecProvider.php
+++ b/civicrm/Civi/Api4/Service/Spec/Provider/ContactTypeCreationSpecProvider.php
@@ -10,19 +10,15 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
 namespace Civi\Api4\Service\Spec\Provider;
 
 use Civi\Api4\Service\Spec\RequestSpec;
 
+/**
+ * Class ContactTypeCreationSpecProvider
+ *
+ * @package Civi\Api4\Service\Spec\Provider
+ */
 class ContactTypeCreationSpecProvider implements Generic\SpecProviderInterface {
 
   /**
diff --git a/civicrm/Civi/Api4/Service/Spec/Provider/ContributionCreationSpecProvider.php b/civicrm/Civi/Api4/Service/Spec/Provider/ContributionCreationSpecProvider.php
index 1a370b3449..a7095a0ba3 100644
--- a/civicrm/Civi/Api4/Service/Spec/Provider/ContributionCreationSpecProvider.php
+++ b/civicrm/Civi/Api4/Service/Spec/Provider/ContributionCreationSpecProvider.php
@@ -10,19 +10,15 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
 namespace Civi\Api4\Service\Spec\Provider;
 
 use Civi\Api4\Service\Spec\RequestSpec;
 
+/**
+ * Class ContributionCreationSpecProvider
+ *
+ * @package Civi\Api4\Service\Spec\Provider
+ */
 class ContributionCreationSpecProvider implements Generic\SpecProviderInterface {
 
   /**
diff --git a/civicrm/Civi/Api4/Service/Spec/Provider/ContributionRecurCreationSpecProvider.php b/civicrm/Civi/Api4/Service/Spec/Provider/ContributionRecurCreationSpecProvider.php
new file mode 100644
index 0000000000..6d38d6a9c0
--- /dev/null
+++ b/civicrm/Civi/Api4/Service/Spec/Provider/ContributionRecurCreationSpecProvider.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+
+namespace Civi\Api4\Service\Spec\Provider;
+
+use Civi\Api4\Service\Spec\RequestSpec;
+
+/**
+ * Class ContributionRecurCreationSpecProvider
+ *
+ * @package Civi\Api4\Service\Spec\Provider
+ */
+class ContributionRecurCreationSpecProvider implements Generic\SpecProviderInterface {
+
+  /**
+   * @inheritDoc
+   */
+  public function modifySpec(RequestSpec $spec) {
+    $spec->getFieldByName('create_date')->setDefaultValue('now');
+  }
+
+  /**
+   * @inheritDoc
+   */
+  public function applies($entity, $action) {
+    return $entity === 'ContributionRecur' && $action === 'create';
+  }
+
+}
diff --git a/civicrm/Civi/Api4/Service/Spec/Provider/DomainCreationSpecProvider.php b/civicrm/Civi/Api4/Service/Spec/Provider/DomainCreationSpecProvider.php
index 061595f6cf..b417dbad72 100644
--- a/civicrm/Civi/Api4/Service/Spec/Provider/DomainCreationSpecProvider.php
+++ b/civicrm/Civi/Api4/Service/Spec/Provider/DomainCreationSpecProvider.php
@@ -10,15 +10,6 @@
  +--------------------------------------------------------------------+
  */
 
-/**
- *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
- */
-
-
 namespace Civi\Api4\Service\Spec\Provider;
 
 use Civi\Api4\Service\Spec\RequestSpec;
diff --git a/civicrm/Civi/Api4/Event/GetSpecEvent.php b/civicrm/Civi/Api4/Service/Spec/Provider/PriceFieldValueCreationSpecProvider.php
similarity index 50%
rename from civicrm/Civi/Api4/Event/GetSpecEvent.php
rename to civicrm/Civi/Api4/Service/Spec/Provider/PriceFieldValueCreationSpecProvider.php
index 16e1e84ba2..00c6b19d1e 100644
--- a/civicrm/Civi/Api4/Event/GetSpecEvent.php
+++ b/civicrm/Civi/Api4/Service/Spec/Provider/PriceFieldValueCreationSpecProvider.php
@@ -14,41 +14,28 @@
  *
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
  */
 
 
-namespace Civi\Api4\Event;
-
-use Civi\Api4\Generic\AbstractAction;
-use Symfony\Component\EventDispatcher\Event as BaseEvent;
+namespace Civi\Api4\Service\Spec\Provider;
 
-class GetSpecEvent extends BaseEvent {
-  /**
-   * @var \Civi\Api4\Generic\AbstractAction
-   */
-  protected $request;
+use Civi\Api4\Service\Spec\RequestSpec;
 
-  /**
-   * @param \Civi\Api4\Generic\AbstractAction $request
-   */
-  public function __construct(AbstractAction $request) {
-    $this->request = $request;
-  }
+class PriceFieldValueCreationSpecProvider implements Generic\SpecProviderInterface {
 
   /**
-   * @return \Civi\Api4\Generic\AbstractAction
+   * @inheritDoc
    */
-  public function getRequest() {
-    return $this->request;
+  public function modifySpec(RequestSpec $spec) {
+    // Name will be auto-generated from label if not supplied
+    $spec->getFieldByName('name')->setRequired(FALSE);
   }
 
   /**
-   * @param $request
+   * @inheritDoc
    */
-  public function setRequest(AbstractAction $request) {
-    $this->request = $request;
+  public function applies($entity, $action) {
+    return $entity === 'PriceFieldValue' && $action === 'create';
   }
 
 }
diff --git a/civicrm/Civi/Api4/Service/Spec/SpecFormatter.php b/civicrm/Civi/Api4/Service/Spec/SpecFormatter.php
index c6d884f1be..1da26d1520 100644
--- a/civicrm/Civi/Api4/Service/Spec/SpecFormatter.php
+++ b/civicrm/Civi/Api4/Service/Spec/SpecFormatter.php
@@ -67,9 +67,6 @@ class SpecFormatter {
       $field->setHelpPre($data['help_pre'] ?? NULL);
       $field->setHelpPost($data['help_post'] ?? NULL);
       $field->setOptions(self::customFieldHasOptions($data));
-      if (\CRM_Core_BAO_CustomField::isSerialized($data)) {
-        $field->setSerialize(\CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND);
-      }
     }
     else {
       $name = $data['name'] ?? NULL;
@@ -77,9 +74,8 @@ class SpecFormatter {
       $field->setRequired(!empty($data['required']));
       $field->setTitle($data['title'] ?? NULL);
       $field->setOptions(!empty($data['pseudoconstant']));
-      $field->setSerialize($data['serialize'] ?? NULL);
     }
-
+    $field->setSerialize($data['serialize'] ?? NULL);
     $field->setDefaultValue($data['default'] ?? NULL);
     $field->setDescription($data['description'] ?? NULL);
     self::setInputTypeAndAttrs($field, $data, $dataTypeName);
@@ -145,10 +141,6 @@ class SpecFormatter {
     $inputAttrs = $data['html'] ?? [];
     unset($inputAttrs['type']);
 
-    if (strstr($inputType, 'Multi-Select') || ($inputType == 'Select' && !empty($data['serialize']))) {
-      $inputAttrs['multiple'] = TRUE;
-      $inputType = 'Select';
-    }
     $map = [
       'Select State/Province' => 'Select',
       'Select Country' => 'Select',
@@ -156,6 +148,9 @@ class SpecFormatter {
       'Link' => 'Url',
     ];
     $inputType = $map[$inputType] ?? $inputType;
+    if ($inputType == 'Select' && !empty($data['serialize'])) {
+      $inputAttrs['multiple'] = TRUE;
+    }
     if ($inputType == 'Date' && !empty($inputAttrs['formatType'])) {
       self::setLegacyDateFormat($inputAttrs);
     }
diff --git a/civicrm/Civi/Api4/Service/Spec/SpecGatherer.php b/civicrm/Civi/Api4/Service/Spec/SpecGatherer.php
index d9909c477d..00fa09b503 100644
--- a/civicrm/Civi/Api4/Service/Spec/SpecGatherer.php
+++ b/civicrm/Civi/Api4/Service/Spec/SpecGatherer.php
@@ -14,7 +14,6 @@
  *
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
  *
  */
 
@@ -32,13 +31,6 @@ class SpecGatherer {
    */
   protected $specProviders = [];
 
-  /**
-   * A cache of DAOs based on entity
-   *
-   * @var \CRM_Core_DAO[]
-   */
-  protected $DAONames;
-
   /**
    * Returns a RequestSpec with all the fields available. Uses spec providers
    * to add or modify field specifications.
@@ -117,15 +109,24 @@ class SpecGatherer {
   }
 
   /**
+   * Get custom fields that extend this entity
+   *
+   * @see \CRM_Core_SelectValues::customGroupExtends
+   *
    * @param string $entity
    * @param \Civi\Api4\Service\Spec\RequestSpec $specification
    * @param array $values
    * @throws \API_Exception
    */
   private function addCustomFields($entity, RequestSpec $specification, $values = []) {
+    // Custom_group.extends pretty much maps 1-1 with entity names, except for a couple oddballs (Contact, Participant).
     $extends = [$entity];
     if ($entity === 'Contact') {
-      $extends = !empty($values['contact_type']) ? [$values['contact_type'], 'Contact'] : ['Contact', 'Individual', 'Organization', 'Household'];
+      $contactType = !empty($values['contact_type']) ? [$values['contact_type']] : \CRM_Contact_BAO_ContactType::basicTypes();
+      $extends = array_merge(['Contact'], $contactType);
+    }
+    if ($entity === 'Participant') {
+      $extends = ['Participant', 'ParticipantRole', 'ParticipantEventName', 'ParticipantEventType'];
     }
     $customFields = CustomField::get()
       ->setCheckPermissions(FALSE)
@@ -146,6 +147,7 @@ class SpecGatherer {
    */
   private function getCustomGroupFields($customGroup, RequestSpec $specification) {
     $customFields = CustomField::get()
+      ->setCheckPermissions(FALSE)
       ->addWhere('custom_group.name', '=', $customGroup)
       ->setSelect(['custom_group.name', 'custom_group.table_name', '*'])
       ->execute();
diff --git a/civicrm/Civi/Api4/Utils/ArrayInsertionUtil.php b/civicrm/Civi/Api4/Utils/ArrayInsertionUtil.php
index 4c2d2f6b2d..951f769790 100644
--- a/civicrm/Civi/Api4/Utils/ArrayInsertionUtil.php
+++ b/civicrm/Civi/Api4/Utils/ArrayInsertionUtil.php
@@ -10,17 +10,13 @@
  +--------------------------------------------------------------------+
  */
 
+namespace Civi\Api4\Utils;
+
 /**
+ * Class ArrayInsertionUtil
  *
- * @package CRM
- * @copyright CiviCRM LLC https://civicrm.org/licensing
- * $Id$
- *
+ * @package Civi\Api4\Utils
  */
-
-
-namespace Civi\Api4\Utils;
-
 class ArrayInsertionUtil {
 
   /**
diff --git a/civicrm/Civi/Api4/Utils/CoreUtil.php b/civicrm/Civi/Api4/Utils/CoreUtil.php
index 9055a63149..1f4c7766a4 100644
--- a/civicrm/Civi/Api4/Utils/CoreUtil.php
+++ b/civicrm/Civi/Api4/Utils/CoreUtil.php
@@ -21,7 +21,6 @@
 
 namespace Civi\Api4\Utils;
 
-use Civi\Api4\CustomGroup;
 use CRM_Core_DAO_AllCoreTables as AllCoreTables;
 
 require_once 'api/v3/utils.php';
@@ -39,34 +38,39 @@ class CoreUtil {
    */
   public static function getBAOFromApiName($entityName) {
     if ($entityName === 'CustomValue' || strpos($entityName, 'Custom_') === 0) {
-      return 'CRM_Contact_BAO_Contact';
+      return 'CRM_Core_BAO_CustomValue';
     }
     return \_civicrm_api3_get_BAO($entityName);
   }
 
   /**
-   * Get table name of given Custom group
+   * Get table name of given entity
    *
-   * @param string $customGroupName
+   * @param string $entityName
    *
    * @return string
    */
-  public static function getCustomTableByName($customGroupName) {
-    return CustomGroup::get()
-      ->addSelect('table_name')
-      ->addWhere('name', '=', $customGroupName)
-      ->execute()
-      ->first()['table_name'];
+  public static function getTableName($entityName) {
+    if (strpos($entityName, 'Custom_') === 0) {
+      $customGroup = substr($entityName, 7);
+      return \CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $customGroup, 'table_name', 'name');
+    }
+    return AllCoreTables::getTableForEntityName($entityName);
   }
 
   /**
    * Given a sql table name, return the name of the api entity.
    *
    * @param $tableName
-   * @return string
+   * @return string|NULL
    */
   public static function getApiNameFromTableName($tableName) {
-    return AllCoreTables::getBriefName(AllCoreTables::getClassForTable($tableName));
+    $entityName = AllCoreTables::getBriefName(AllCoreTables::getClassForTable($tableName));
+    if (!$entityName) {
+      $customGroup = \CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $tableName, 'name', 'table_name');
+      $entityName = $customGroup ? "Custom_$customGroup" : NULL;
+    }
+    return $entityName;
   }
 
 }
diff --git a/civicrm/Civi/Api4/Utils/FormattingUtil.php b/civicrm/Civi/Api4/Utils/FormattingUtil.php
index be91ce41e1..77e50db8f5 100644
--- a/civicrm/Civi/Api4/Utils/FormattingUtil.php
+++ b/civicrm/Civi/Api4/Utils/FormattingUtil.php
@@ -31,6 +31,8 @@ class FormattingUtil {
     'label' => 'get',
   ];
 
+  public static $pseudoConstantSuffixes = ['name', 'abbr', 'label', 'color', 'description', 'icon'];
+
   /**
    * Massage values into the format the BAO expects for a write operation
    *
@@ -46,7 +48,7 @@ class FormattingUtil {
         if ($value === 'null') {
           $value = 'Null';
         }
-        self::formatInputValue($value, $name, $field);
+        self::formatInputValue($value, $name, $field, 'create');
         // Ensure we have an array for serialized fields
         if (!empty($field['serialize'] && !is_array($value))) {
           $value = (array) $value;
@@ -80,18 +82,21 @@ class FormattingUtil {
    * @param $value
    * @param string $fieldName
    * @param array $fieldSpec
+   * @param string $action
    * @throws \API_Exception
+   * @throws \CRM_Core_Exception
    */
-  public static function formatInputValue(&$value, $fieldName, $fieldSpec) {
+  public static function formatInputValue(&$value, $fieldName, $fieldSpec, $action = 'get') {
     // Evaluate pseudoconstant suffix
     $suffix = strpos($fieldName, ':');
     if ($suffix) {
-      $options = self::getPseudoconstantList($fieldSpec['entity'], $fieldSpec['name'], substr($fieldName, $suffix + 1));
+      $options = self::getPseudoconstantList($fieldSpec['entity'], $fieldSpec['name'], substr($fieldName, $suffix + 1), $action);
       $value = self::replacePseudoconstant($options, $value, TRUE);
+      return;
     }
     elseif (is_array($value)) {
       foreach ($value as &$val) {
-        self::formatInputValue($val, $fieldName, $fieldSpec);
+        self::formatInputValue($val, $fieldName, $fieldSpec, $action);
       }
       return;
     }
@@ -188,17 +193,20 @@ class FormattingUtil {
    */
   public static function getPseudoconstantList($entity, $fieldName, $valueType, $params = [], $action = 'get') {
     $context = self::$pseudoConstantContexts[$valueType] ?? NULL;
-    if (!$context) {
+    // For create actions, only unique identifiers can be used.
+    // For get actions any valid suffix is ok.
+    if (($action === 'create' && !$context) || !in_array($valueType, self::$pseudoConstantSuffixes, TRUE)) {
       throw new \API_Exception('Illegal expression');
     }
-    $baoName = CoreUtil::getBAOFromApiName($entity);
+    $baoName = $context ? CoreUtil::getBAOFromApiName($entity) : NULL;
     // Use BAO::buildOptions if possible
     if ($baoName) {
       $options = $baoName::buildOptions($fieldName, $context, $params);
     }
-    // Fallback for option lists that exist in the api but not the BAO - note: $valueType gets ignored here
+    // Fallback for option lists that exist in the api but not the BAO
     if (!isset($options) || $options === FALSE) {
-      $options = civicrm_api4($entity, 'getFields', ['action' => $action, 'loadOptions' => TRUE, 'where' => [['name', '=', $fieldName]]])[0]['options'] ?? NULL;
+      $options = civicrm_api4($entity, 'getFields', ['action' => $action, 'loadOptions' => ['id', $valueType], 'where' => [['name', '=', $fieldName]]])[0]['options'] ?? NULL;
+      $options = $options ? array_column($options, $valueType, 'id') : $options;
     }
     if (is_array($options)) {
       return $options;
@@ -277,7 +285,7 @@ class FormattingUtil {
           \Civi::$statics[__CLASS__][__FUNCTION__][$contactType][] = $field['name'];
           // Include suffixed variants like prefix_id:label
           if (!empty($field['pseudoconstant'])) {
-            foreach (array_keys(self::$pseudoConstantContexts) as $suffix) {
+            foreach (self::$pseudoConstantSuffixes as $suffix) {
               \Civi::$statics[__CLASS__][__FUNCTION__][$contactType][] = $field['name'] . ':' . $suffix;
             }
           }
diff --git a/civicrm/Civi/Api4/services.xml b/civicrm/Civi/Api4/services.xml
index 3d8a2fcab1..630a646326 100644
--- a/civicrm/Civi/Api4/services.xml
+++ b/civicrm/Civi/Api4/services.xml
@@ -4,21 +4,21 @@
 
     <services>
 
-        <service id="spec_gatherer" class="Civi\Api4\Service\Spec\SpecGatherer"/>
+        <service id="spec_gatherer" class="Civi\Api4\Service\Spec\SpecGatherer" public="true"/>
 
         <service id="schema_map_builder" class="Civi\Api4\Service\Schema\SchemaMapBuilder" public="false">
             <argument type="service" id="dispatcher" />
         </service>
 
-        <service id="schema_map" class="Civi\Api4\Service\Schema\SchemaMap">
+        <service id="schema_map" class="Civi\Api4\Service\Schema\SchemaMap" public="true">
           <factory service="schema_map_builder" method="build"/>
         </service>
 
-        <service id="joiner" class="Civi\Api4\Service\Schema\Joiner">
+        <service id="joiner" class="Civi\Api4\Service\Schema\Joiner" public="true">
             <argument type="service" id="schema_map"/>
         </service>
 
-        <service id="action_object_provider" class="Civi\Api4\Provider\ActionObjectProvider">
+        <service id="action_object_provider" class="Civi\Api4\Provider\ActionObjectProvider" public="true">
             <tag name="event_subscriber"/>
         </service>
 
diff --git a/civicrm/Civi/Core/AssetBuilder.php b/civicrm/Civi/Core/AssetBuilder.php
index 82e2141461..155c32c779 100644
--- a/civicrm/Civi/Core/AssetBuilder.php
+++ b/civicrm/Civi/Core/AssetBuilder.php
@@ -20,7 +20,7 @@ use Civi\Core\Exception\UnknownAssetException;
  * named "api-fields.json" which lists all the fields of
  * all the API entities.
  *
- * @code
+ * ```
  * // Build a URL to `api-fields.json`.
  * $url = \Civi::service('asset_builder')->getUrl('api-fields.json');
  *
@@ -37,7 +37,7 @@ use Civi\Core\Exception\UnknownAssetException;
  *   $mimeType = 'application/json';
  *   $content = json_encode($fields);
  * }
- * @endCode
+ * ```
  *
  * Assets can be parameterized. Each combination of ($asset,$params)
  * will be cached separately. For example, we might want a copy of
@@ -45,7 +45,7 @@ use Civi\Core\Exception\UnknownAssetException;
  * Simply pass the chosen entities into `getUrl()`, then update
  * the definition to use `$params['entities']`, as in:
  *
- * @code
+ * ```
  * // Build a URL to `api-fields.json`.
  * $url = \Civi::service('asset_builder')->getUrl('api-fields.json', array(
  *   'entities' => array('Contact', 'Phone', 'Email', 'Address'),
@@ -63,7 +63,7 @@ use Civi\Core\Exception\UnknownAssetException;
  *   $mimeType = 'application/json';
  *   $content = json_encode($fields);
  * }
- * @endCode
+ * ```
  *
  * Note: These assets are designed to hold non-sensitive data, such as
  * aggregated JS or common metadata. There probably are ways to
diff --git a/civicrm/Civi/Core/CiviEventDispatcher.php b/civicrm/Civi/Core/CiviEventDispatcher.php
index 18d8aa3043..9f3da3215e 100644
--- a/civicrm/Civi/Core/CiviEventDispatcher.php
+++ b/civicrm/Civi/Core/CiviEventDispatcher.php
@@ -2,7 +2,7 @@
 
 namespace Civi\Core;
 
-use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
+use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\EventDispatcher\Event;
 
 /**
@@ -15,7 +15,7 @@ use Symfony\Component\EventDispatcher\Event;
  *
  * @see \CRM_Utils_Hook
  */
-class CiviEventDispatcher extends ContainerAwareEventDispatcher {
+class CiviEventDispatcher extends EventDispatcher {
 
   const DEFAULT_HOOK_PRIORITY = -100;
 
@@ -61,6 +61,34 @@ class CiviEventDispatcher extends ContainerAwareEventDispatcher {
     return (substr($eventName, 0, 5) === 'hook_') && (strpos($eventName, '::') === FALSE);
   }
 
+  /**
+   * Adds a service as event listener.
+   *
+   * This provides partial backwards compatibility with ContainerAwareEventDispatcher.
+   *
+   * @param string $eventName Event for which the listener is added
+   * @param array $callback The service ID of the listener service & the method
+   *                        name that has to be called
+   * @param int $priority The higher this value, the earlier an event listener
+   *                      will be triggered in the chain.
+   *                      Defaults to 0.
+   *
+   * @throws \InvalidArgumentException
+   */
+  public function addListenerService($eventName, $callback, $priority = 0) {
+    if (!\is_array($callback) || 2 !== \count($callback)) {
+      throw new \InvalidArgumentException('Expected an array("service", "method") argument');
+    }
+
+    $this->addListener($eventName, function($event) use ($callback) {
+      static $svc;
+      if ($svc === NULL) {
+        $svc = \Civi::container()->get($callback[0]);
+      }
+      return call_user_func([$svc, $callback[1]], $event);
+    }, $priority);
+  }
+
   /**
    * @inheritDoc
    */
diff --git a/civicrm/Civi/Core/CiviEventInspector.php b/civicrm/Civi/Core/CiviEventInspector.php
index 77d91684e2..34514f9bf7 100644
--- a/civicrm/Civi/Core/CiviEventInspector.php
+++ b/civicrm/Civi/Core/CiviEventInspector.php
@@ -7,10 +7,10 @@ namespace Civi\Core;
  * The event inspector is a development tool which provides metadata about events.
  * It can be used for code-generators and documentation-generators.
  *
- * @code
+ * ```
  * $i = new CiviEventInspector();
  * print_r(CRM_Utils_Array::collect('name', $i->getAll()));
- * @endCode
+ * ```
  *
  * An event definition includes these fields:
  *  - type: string, required. Ex: 'hook' or 'object'
diff --git a/civicrm/Civi/Core/Container.php b/civicrm/Civi/Core/Container.php
index 57ee309164..15c7860a9d 100644
--- a/civicrm/Civi/Core/Container.php
+++ b/civicrm/Civi/Core/Container.php
@@ -121,32 +121,32 @@ class Container {
       'Civi\Angular\Manager',
       []
     ))
-      ->setFactory([new Reference(self::SELF), 'createAngularManager']);
+      ->setFactory([new Reference(self::SELF), 'createAngularManager'])->setPublic(TRUE);
 
     $container->setDefinition('dispatcher', new Definition(
       'Civi\Core\CiviEventDispatcher',
       [new Reference('service_container')]
     ))
-      ->setFactory([new Reference(self::SELF), 'createEventDispatcher']);
+      ->setFactory([new Reference(self::SELF), 'createEventDispatcher'])->setPublic(TRUE);
 
     $container->setDefinition('magic_function_provider', new Definition(
       'Civi\API\Provider\MagicFunctionProvider',
       []
-    ));
+    ))->setPublic(TRUE);
 
     $container->setDefinition('civi_api_kernel', new Definition(
       'Civi\API\Kernel',
       [new Reference('dispatcher'), new Reference('magic_function_provider')]
     ))
-      ->setFactory([new Reference(self::SELF), 'createApiKernel']);
+      ->setFactory([new Reference(self::SELF), 'createApiKernel'])->setPublic(TRUE);
 
     $container->setDefinition('cxn_reg_client', new Definition(
       'Civi\Cxn\Rpc\RegistrationClient',
       []
     ))
-      ->setFactory('CRM_Cxn_BAO_Cxn::createRegistrationClient');
+      ->setFactory('CRM_Cxn_BAO_Cxn::createRegistrationClient')->setPublic(TRUE);
 
-    $container->setDefinition('psr_log', new Definition('CRM_Core_Error_Log', []));
+    $container->setDefinition('psr_log', new Definition('CRM_Core_Error_Log', []))->setPublic(TRUE);
 
     $basicCaches = [
       'js_strings' => 'js_strings',
@@ -176,7 +176,7 @@ class Container {
       $container->setDefinition("cache.{$cacheSvc}", new Definition(
         'CRM_Utils_Cache_Interface',
         [$definitionParams]
-      ))->setFactory('CRM_Utils_Cache::create');
+      ))->setFactory('CRM_Utils_Cache::create')->setPublic(TRUE);
     }
 
     // PrevNextCache cannot use memory or array cache at the moment because the
@@ -189,22 +189,22 @@ class Container {
           'type' => ['SqlGroup'],
         ],
       ]
-    ))->setFactory('CRM_Utils_Cache::create');
+    ))->setFactory('CRM_Utils_Cache::create')->setPublic(TRUE);
 
     $container->setDefinition('sql_triggers', new Definition(
       'Civi\Core\SqlTriggers',
       []
-    ));
+    ))->setPublic(TRUE);
 
     $container->setDefinition('asset_builder', new Definition(
       'Civi\Core\AssetBuilder',
       []
-    ));
+    ))->setPublic(TRUE);
 
     $container->setDefinition('themes', new Definition(
       'Civi\Core\Themes',
       []
-    ));
+    ))->setPublic(TRUE);
 
     $container->setDefinition('pear_mail', new Definition('Mail'))
       ->setFactory('CRM_Utils_Mail::createMailer');
@@ -228,47 +228,47 @@ class Container {
       $container->setDefinition($name, new Definition(
         $class
       ))
-        ->setFactory([$class, 'singleton']);
+        ->setFactory([$class, 'singleton'])->setPublic(TRUE);
     }
     $container->setAlias('cache.short', 'cache.default');
 
     $container->setDefinition('resources', new Definition(
       'CRM_Core_Resources',
       [new Reference('service_container')]
-    ))->setFactory([new Reference(self::SELF), 'createResources']);
+    ))->setFactory([new Reference(self::SELF), 'createResources'])->setPublic(TRUE);
 
     $container->setDefinition('prevnext', new Definition(
       'CRM_Core_PrevNextCache_Interface',
       [new Reference('service_container')]
-    ))->setFactory([new Reference(self::SELF), 'createPrevNextCache']);
+    ))->setFactory([new Reference(self::SELF), 'createPrevNextCache'])->setPublic(TRUE);
 
     $container->setDefinition('prevnext.driver.sql', new Definition(
       'CRM_Core_PrevNextCache_Sql',
       []
-    ));
+    ))->setPublic(TRUE);
 
     $container->setDefinition('prevnext.driver.redis', new Definition(
       'CRM_Core_PrevNextCache_Redis',
       [new Reference('cache_config')]
-    ));
+    ))->setPublic(TRUE);
 
     $container->setDefinition('cache_config', new Definition('ArrayObject'))
-      ->setFactory([new Reference(self::SELF), 'createCacheConfig']);
+      ->setFactory([new Reference(self::SELF), 'createCacheConfig'])->setPublic(TRUE);
 
     $container->setDefinition('civi.mailing.triggers', new Definition(
       'Civi\Core\SqlTrigger\TimestampTriggers',
       ['civicrm_mailing', 'Mailing']
-    ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']);
+    ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo'])->setPublic(TRUE);
 
     $container->setDefinition('civi.activity.triggers', new Definition(
       'Civi\Core\SqlTrigger\TimestampTriggers',
       ['civicrm_activity', 'Activity']
-    ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']);
+    ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo'])->setPublic(TRUE);
 
     $container->setDefinition('civi.case.triggers', new Definition(
       'Civi\Core\SqlTrigger\TimestampTriggers',
       ['civicrm_case', 'Case']
-    ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']);
+    ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo'])->setPublic(TRUE);
 
     $container->setDefinition('civi.case.staticTriggers', new Definition(
       'Civi\Core\SqlTrigger\StaticTriggers',
@@ -291,22 +291,22 @@ class Container {
         ],
       ]
     ))
-      ->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']);
+      ->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo'])->setPublic(TRUE);
 
     $container->setDefinition('civi_token_compat', new Definition(
       'Civi\Token\TokenCompatSubscriber',
       []
-    ))->addTag('kernel.event_subscriber');
+    ))->addTag('kernel.event_subscriber')->setPublic(TRUE);
     $container->setDefinition("crm_mailing_action_tokens", new Definition(
       "CRM_Mailing_ActionTokens",
       []
-    ))->addTag('kernel.event_subscriber');
+    ))->addTag('kernel.event_subscriber')->setPublic(TRUE);
 
     foreach (['Activity', 'Contribute', 'Event', 'Mailing', 'Member'] as $comp) {
       $container->setDefinition("crm_" . strtolower($comp) . "_tokens", new Definition(
         "CRM_{$comp}_Tokens",
         []
-      ))->addTag('kernel.event_subscriber');
+      ))->addTag('kernel.event_subscriber')->setPublic(TRUE);
     }
 
     \CRM_Api4_Services::hook_container($container);
@@ -325,10 +325,10 @@ class Container {
 
   /**
    * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
-   * @return \Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher
+   * @return \Symfony\Component\EventDispatcher\EventDispatcher
    */
   public function createEventDispatcher($container) {
-    $dispatcher = new CiviEventDispatcher($container);
+    $dispatcher = new CiviEventDispatcher();
     if (\CRM_Core_Config::isUpgradeMode()) {
       $dispatcher->setDispatchPolicy(\CRM_Upgrade_DispatchPolicy::get('upgrade.main'));
     }
@@ -354,6 +354,7 @@ class Container {
     $dispatcher->addListener('hook_civicrm_buildAsset', ['\CRM_Core_Resources', 'renderMenubarStylesheet']);
     $dispatcher->addListener('hook_civicrm_coreResourceList', ['\CRM_Utils_System', 'appendCoreResources']);
     $dispatcher->addListener('hook_civicrm_getAssetUrl', ['\CRM_Utils_System', 'alterAssetUrl']);
+    $dispatcher->addListener('hook_civicrm_alterExternUrl', ['\CRM_Utils_System', 'migrateExternUrl'], 1000);
     $dispatcher->addListener('civi.dao.postInsert', ['\CRM_Core_BAO_RecurringEntity', 'triggerInsert']);
     $dispatcher->addListener('civi.dao.postUpdate', ['\CRM_Core_BAO_RecurringEntity', 'triggerUpdate']);
     $dispatcher->addListener('civi.dao.postDelete', ['\CRM_Core_BAO_RecurringEntity', 'triggerDelete']);
diff --git a/civicrm/Civi/Core/Event/GenericHookEvent.php b/civicrm/Civi/Core/Event/GenericHookEvent.php
index 6c62ea498a..1b29ff76e9 100644
--- a/civicrm/Civi/Core/Event/GenericHookEvent.php
+++ b/civicrm/Civi/Core/Event/GenericHookEvent.php
@@ -26,7 +26,7 @@ namespace Civi\Core\Event;
  * and methods. This requires some kind of mapping. `GenericHookEvent`
  * maps each parameter to a field (using magic methods):
  *
- * @code
+ * ```
  * // Creating an event object.
  * $event = GenericHookEvent::create(array(
  *   'bar' => 'abc',
@@ -41,7 +41,7 @@ namespace Civi\Core\Event;
  *
  * // Dispatching an event.
  * Civi::dispatcher()->dispatch('hook_civicrm_foo', $event);
- * @endCode
+ * ```
  *
  * Design Discussion:
  *
@@ -56,10 +56,10 @@ namespace Civi\Core\Event;
  * as an array, and all the returned values are merged into one big array.
  * You can add and retrieve return-values using these methods:
  *
- * @code
+ * ```
  * $event->addReturnValues(array(...));
  * foreach ($event->getReturnValues() as $retVal) { ... }
- * @endCode
+ * ```
  */
 class GenericHookEvent extends \Symfony\Component\EventDispatcher\Event {
 
diff --git a/civicrm/Civi/Core/Paths.php b/civicrm/Civi/Core/Paths.php
index d0d15814b3..89b433679a 100644
--- a/civicrm/Civi/Core/Paths.php
+++ b/civicrm/Civi/Core/Paths.php
@@ -30,7 +30,10 @@ class Paths {
    * Class constructor.
    */
   public function __construct() {
-    $paths = $this;
+    // Below is a *default* set of functions to calculate paths/URLs.
+    // Some variables may be overridden as follow:
+    // - The global `$civicrm_paths` may be preset before Civi boots. (Ex: via `civicrm.settings.php`, `settings.php`, or `vendor/autoload.php`)
+    // - Variables may be re-registered. (Ex: via `CRM_Utils_System_WordPress`)
     $this
       ->register('civicrm.root', function () {
         return \CRM_Core_Config::singleton()->userSystem->getCiviSourceStorage();
@@ -84,24 +87,6 @@ class Paths {
           'path' => is_dir($dir) ? $dir : \Civi::paths()->getPath('[civicrm.root]/l10n'),
         ];
       })
-      ->register('wp.frontend.base', function () {
-        return ['url' => rtrim(CIVICRM_UF_BASEURL, '/') . '/'];
-      })
-      ->register('wp.frontend', function () use ($paths) {
-        $config = \CRM_Core_Config::singleton();
-        $suffix = defined('CIVICRM_UF_WP_BASEPAGE') ? CIVICRM_UF_WP_BASEPAGE : $config->wpBasePage;
-        return [
-          'url' => $paths->getVariable('wp.frontend.base', 'url') . $suffix,
-        ];
-      })
-      ->register('wp.backend.base', function () {
-        return ['url' => rtrim(CIVICRM_UF_BASEURL, '/') . '/wp-admin/'];
-      })
-      ->register('wp.backend', function () use ($paths) {
-        return [
-          'url' => $paths->getVariable('wp.backend.base', 'url') . 'admin.php',
-        ];
-      })
       ->register('cms', function () {
         return [
           'path' => \CRM_Core_Config::singleton()->userSystem->cmsRootPath(),
diff --git a/civicrm/Civi/Core/Resolver.php b/civicrm/Civi/Core/Resolver.php
index 379f94d64c..a1ebfe2b0f 100644
--- a/civicrm/Civi/Core/Resolver.php
+++ b/civicrm/Civi/Core/Resolver.php
@@ -222,11 +222,11 @@ class ResolverApi {
   /**
    * Recursively interpolate values.
    *
-   * @code
+   * ```
    * $params = array('foo' => '@1');
    * $this->interpolate($params, array('@1'=> $object))
    * assert $data['foo'] == $object;
-   * @endcode
+   * ```
    *
    * @param array $array
    *   Array which may or many not contain a mix of tokens.
diff --git a/civicrm/Civi/Core/Themes.php b/civicrm/Civi/Core/Themes.php
index 8e7dc5988d..9156eb5558 100644
--- a/civicrm/Civi/Core/Themes.php
+++ b/civicrm/Civi/Core/Themes.php
@@ -133,7 +133,7 @@ class Themes {
    * @see CRM_Utils_Hook::themes
    */
   public function getAvailable() {
-    $result = array();
+    $result = [];
     foreach ($this->getAll() as $key => $theme) {
       if ($key{0} !== '_') {
         $result[$key] = $theme['title'];
@@ -164,14 +164,14 @@ class Themes {
   public function resolveUrls($active, $cssExt, $cssFile) {
     $all = $this->getAll();
     if (!isset($all[$active])) {
-      return array();
+      return [];
     }
 
     $cssId = $this->cssId($cssExt, $cssFile);
 
     foreach ($all[$active]['search_order'] as $themeKey) {
       if (isset($all[$themeKey]['excludes']) && in_array($cssId, $all[$themeKey]['excludes'])) {
-        $result = array();
+        $result = [];
       }
       else {
         $result = Civi\Core\Resolver::singleton()
diff --git a/civicrm/Civi/Payment/PropertyBag.php b/civicrm/Civi/Payment/PropertyBag.php
index d17c04b845..8878734691 100644
--- a/civicrm/Civi/Payment/PropertyBag.php
+++ b/civicrm/Civi/Payment/PropertyBag.php
@@ -72,6 +72,7 @@ class PropertyBag implements \ArrayAccess {
     'transactionID'               => TRUE,
     'transaction_id'              => 'transactionID',
     'trxnResultCode'              => TRUE,
+    'isNotifyProcessorOnCancelRecur' => TRUE,
   ];
 
   /**
@@ -210,6 +211,13 @@ class PropertyBag implements \ArrayAccess {
       // Good, modern name.
       return $prop;
     }
+    // Handling for legacy addition of billing details.
+    if ($newName === NULL && substr($prop, -2) === '-' . \CRM_Core_BAO_LocationType::getBilling()
+      && isset(static::$propMap[substr($prop, 0, -2)])
+    ) {
+      $newName = substr($prop, 0, -2);
+    }
+
     if ($newName === NULL) {
       if ($silent) {
         // Only for use by offsetExists
@@ -380,7 +388,7 @@ class PropertyBag implements \ArrayAccess {
       throw new \InvalidArgumentException("setAmount requires a numeric amount value");
     }
 
-    return $this->set('amount', CRM_Utils_Money::format($value, NULL, NULL, TRUE), $label);
+    return $this->set('amount', $label, \CRM_Utils_Money::format($value, NULL, NULL, TRUE));
   }
 
   /**
@@ -473,6 +481,8 @@ class PropertyBag implements \ArrayAccess {
    *
    * @param string $input
    * @param string $label e.g. 'default'
+   *
+   * @return \Civi\Payment\PropertyBag
    */
   public function setBillingCity($input, $label = 'default') {
     return $this->set('billingCity', $label, (string) $input);
@@ -770,9 +780,12 @@ class PropertyBag implements \ArrayAccess {
    *
    * @param string $label
    *
-   * @return bool|null
+   * @return bool
    */
   public function getIsRecur($label = 'default'):bool {
+    if (!$this->has('isRecur')) {
+      return FALSE;
+    }
     return $this->get('isRecur', $label);
   }
 
@@ -787,6 +800,35 @@ class PropertyBag implements \ArrayAccess {
     return $this->set('isRecur', $label, (bool) $isRecur);
   }
 
+  /**
+   * Set whether the user has selected to notify the processor of a cancellation request.
+   *
+   * When cancelling the user may be presented with an option to notify the processor. The payment
+   * processor can take their response, if present, into account.
+   *
+   * @param bool $value
+   * @param string $label e.g. 'default'
+   *
+   * @return \Civi\Payment\PropertyBag
+   */
+  public function setIsNotifyProcessorOnCancelRecur($value, $label = 'default') {
+    return $this->set('isNotifyProcessorOnCancelRecur', $label, (bool) $value);
+  }
+
+  /**
+   * Get whether the user has selected to notify the processor of a cancellation request.
+   *
+   * When cancelling the user may be presented with an option to notify the processor. The payment
+   * processor can take their response, if present, into account.
+   *
+   * @param string $label e.g. 'default'
+   *
+   * @return \Civi\Payment\PropertyBag
+   */
+  public function getIsNotifyProcessorOnCancelRecur($label = 'default') {
+    return $this->get('isNotifyProcessorOnCancelRecur', $label);
+  }
+
   /**
    * Last name
    *
diff --git a/civicrm/Civi/Test.php b/civicrm/Civi/Test.php
index 50d6ebf31c..1d9db12079 100644
--- a/civicrm/Civi/Test.php
+++ b/civicrm/Civi/Test.php
@@ -100,12 +100,12 @@ class Test {
   /**
    * Create a builder for the headless environment.
    *
-   * @return \Civi\Test\CiviEnvBuilder
-   *
-   * @code
+   * ```
    * \Civi\Test::headless()->apply();
    * \Civi\Test::headless()->sqlFile('ex.sql')->apply();
-   * @endCode
+   * ```
+   *
+   * @return \Civi\Test\CiviEnvBuilder
    */
   public static function headless() {
     $civiRoot = dirname(__DIR__);
@@ -130,12 +130,12 @@ class Test {
   /**
    * Create a builder for end-to-end testing on the live environment.
    *
-   * @return \Civi\Test\CiviEnvBuilder
-   *
-   * @code
+   * ```
    * \Civi\Test::e2e()->apply();
    * \Civi\Test::e2e()->install('foo.bar')->apply();
-   * @endCode
+   * ```
+   *
+   * @return \Civi\Test\CiviEnvBuilder
    */
   public static function e2e() {
     $builder = new \Civi\Test\CiviEnvBuilder('CiviEnvBuilder');
diff --git a/civicrm/Civi/Test/Api3TestTrait.php b/civicrm/Civi/Test/Api3TestTrait.php
index 6d5421053d..fbe73cd0fe 100644
--- a/civicrm/Civi/Test/Api3TestTrait.php
+++ b/civicrm/Civi/Test/Api3TestTrait.php
@@ -302,7 +302,7 @@ trait Api3TestTrait {
    * @throws \Exception
    */
   public function runApi4Legacy($v3Entity, $v3Action, $v3Params = []) {
-    $v4Entity = self::convertEntityNameToApi4($v3Entity);
+    $v4Entity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel($v3Entity);
     $v4Action = $v3Action = strtolower($v3Action);
     $v4Params = ['checkPermissions' => isset($v3Params['check_permissions']) ? (bool) $v3Params['check_permissions'] : FALSE];
     $sequential = !empty($v3Params['sequential']);
@@ -641,9 +641,9 @@ trait Api3TestTrait {
 
     // Handle single api call
     list(, $chainEntity, $chainAction) = explode('.', $key);
-    $lcChainEntity = \_civicrm_api_get_entity_name_from_camel($chainEntity);
-    $chainEntity = self::convertEntityNameToApi4($chainEntity);
-    $lcMainEntity = \_civicrm_api_get_entity_name_from_camel($mainEntity);
+    $lcChainEntity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($chainEntity);
+    $chainEntity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToCamel($chainEntity);
+    $lcMainEntity = \CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($mainEntity);
     $params = is_array($params) ? $params : [];
 
     // Api3 expects this to be inherited
@@ -677,19 +677,4 @@ trait Api3TestTrait {
     return $this->runApi4Legacy($chainEntity, $chainAction, $params);
   }
 
-  /**
-   * Fix the naming differences between api3 & api4 entities.
-   *
-   * @param string $legacyName
-   * @return string
-   */
-  public static function convertEntityNameToApi4($legacyName) {
-    $api4Name = \CRM_Utils_String::convertStringToCamel($legacyName);
-    $map = [
-      'Im' => 'IM',
-      'Acl' => 'ACL',
-    ];
-    return $map[$api4Name] ?? $api4Name;
-  }
-
 }
diff --git a/civicrm/Civi/Test/DbTestTrait.php b/civicrm/Civi/Test/DbTestTrait.php
index 74388ada0f..866984566f 100644
--- a/civicrm/Civi/Test/DbTestTrait.php
+++ b/civicrm/Civi/Test/DbTestTrait.php
@@ -154,7 +154,7 @@ trait DbTestTrait {
    */
   public function assertDBCompareValues($daoName, $searchParams, $expectedValues) {
     //get the values from db
-    $dbValues = array();
+    $dbValues = [];
     \CRM_Core_DAO::commonRetrieve($daoName, $searchParams, $dbValues);
 
     // compare db values with expected values
diff --git a/civicrm/Civi/Test/GenericAssertionsTrait.php b/civicrm/Civi/Test/GenericAssertionsTrait.php
index 0d53d034ba..8d04b6359b 100644
--- a/civicrm/Civi/Test/GenericAssertionsTrait.php
+++ b/civicrm/Civi/Test/GenericAssertionsTrait.php
@@ -35,8 +35,8 @@ trait GenericAssertionsTrait {
    * @param array $actual
    */
   public function assertTreeEquals($expected, $actual) {
-    $e = array();
-    $a = array();
+    $e = [];
+    $a = [];
     \CRM_Utils_Array::flatten($expected, $e, '', ':::');
     \CRM_Utils_Array::flatten($actual, $a, '', ':::');
     ksort($e);
diff --git a/civicrm/Civi/Test/GuzzleTestTrait.php b/civicrm/Civi/Test/GuzzleTestTrait.php
new file mode 100644
index 0000000000..c372d3eee9
--- /dev/null
+++ b/civicrm/Civi/Test/GuzzleTestTrait.php
@@ -0,0 +1,191 @@
+<?php
+
+namespace Civi\Test;
+
+use GuzzleHttp\Handler\MockHandler;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Middleware;
+use GuzzleHttp\Client;
+
+/**
+ * Class GuzzleTestTrait
+ *
+ * This trait defines a number of helper functions for testing guzzle.
+ */
+trait GuzzleTestTrait {
+  /**
+   * @var \GuzzleHttp\Client
+   */
+  protected $guzzleClient;
+
+  /**
+   * Array containing guzzle history of requests and responses.
+   *
+   * @var array
+   */
+  protected $container;
+
+  /**
+   * Mockhandler to simulate guzzle requests.
+   *
+   * @var \GuzzleHttp\Handler\MockHandler
+   */
+  protected $mockHandler;
+
+  /**
+   * The url to mock-interact with.
+   *
+   * @var string
+   */
+  protected $baseUri;
+
+  /**
+   * @return \GuzzleHttp\Client
+   */
+  public function getGuzzleClient() {
+    return $this->guzzleClient;
+  }
+
+  /**
+   * @param \GuzzleHttp\Client $guzzleClient
+   */
+  public function setGuzzleClient($guzzleClient) {
+    $this->guzzleClient = $guzzleClient;
+  }
+
+  /**
+   * @return array
+   */
+  public function getContainer() {
+    return $this->container;
+  }
+
+  /**
+   * @param array $container
+   */
+  public function setContainer($container) {
+    $this->container = $container;
+  }
+
+  /**
+   * @return mixed
+   */
+  public function getBaseUri() {
+    return $this->baseUri;
+  }
+
+  /**
+   * @param mixed $baseUri
+   */
+  public function setBaseUri($baseUri) {
+    $this->baseUri = $baseUri;
+  }
+
+  /**
+   * @return \GuzzleHttp\Handler\MockHandler
+   */
+  public function getMockHandler() {
+    return $this->mockHandler;
+  }
+
+  /**
+   * @param \GuzzleHttp\Handler\MockHandler $mockHandler
+   */
+  public function setMockHandler($mockHandler) {
+    $this->mockHandler = $mockHandler;
+  }
+
+  /**
+   * @param $responses
+   */
+  protected function createMockHandler($responses) {
+    $mocks = [];
+    foreach ($responses as $response) {
+      $mocks[] = new Response(200, [], $response);
+    }
+    $this->setMockHandler(new MockHandler($mocks));
+  }
+
+  /**
+   * @param $files
+   */
+  protected function createMockHandlerForFiles($files) {
+    $body = [];
+    foreach ($files as $file) {
+      $body[] = trim(file_get_contents(__DIR__ . $file));
+    }
+    $this->createMockHandler($body);
+  }
+
+  /**
+   * Set up a guzzle client with a history container.
+   *
+   * After you have run the requests you can inspect $this->container
+   * for the outgoing requests and incoming responses.
+   *
+   * If $this->mock is defined then no outgoing http calls will be made
+   * and the responses configured on the handler will be returned instead
+   * of replies from a remote provider.
+   */
+  protected function setUpClientWithHistoryContainer() {
+    $this->container = [];
+    $history = Middleware::history($this->container);
+    $handler = HandlerStack::create($this->getMockHandler());
+    $handler->push($history);
+    $this->guzzleClient = new Client(['base_uri' => $this->baseUri, 'handler' => $handler]);
+  }
+
+  /**
+   * Get the bodies of the requests sent via Guzzle.
+   *
+   * @return array
+   */
+  protected function getRequestBodies() {
+    $requests = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $requests[] = (string) $guzzle['request']->getBody();
+    }
+    return $requests;
+  }
+
+  /**
+   * Get the bodies of the requests sent via Guzzle.
+   *
+   * @return array
+   */
+  protected function getRequestHeaders() {
+    $requests = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $requests[] = $guzzle['request']->getHeaders();
+    }
+    return $requests;
+  }
+
+  /**
+   * Get the bodies of the requests sent via Guzzle.
+   *
+   * @return array
+   */
+  protected function getRequestUrls() {
+    $requests = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $requests[] = (string) $guzzle['request']->getUri();
+    }
+    return $requests;
+  }
+
+  /**
+   * Get the bodies of the responses returned via Guzzle.
+   *
+   * @return array
+   */
+  protected function getResponseBodies() {
+    $responses = [];
+    foreach ($this->getContainer() as $guzzle) {
+      $responses[] = (string) $guzzle['response']->getBody();
+    }
+    return $responses;
+  }
+
+}
diff --git a/civicrm/Civi/Test/HookInterface.php b/civicrm/Civi/Test/HookInterface.php
index 53d5c8cd11..4885cd0677 100644
--- a/civicrm/Civi/Test/HookInterface.php
+++ b/civicrm/Civi/Test/HookInterface.php
@@ -9,13 +9,13 @@ namespace Civi\Test;
  * This interface allows you to subscribe to hooks as part of the test.
  * Simply create an eponymous hook function (e.g. `hook_civicrm_post()`).
  *
- * @code
+ * ```
  * class MyTest extends \PHPUnit_Framework_TestCase implements \Civi\Test\HookInterface {
  *   public function hook_civicrm_post($op, $objectName, $objectId, &$objectRef) {
  *     echo "Running hook_civicrm_post\n";
  *   }
  * }
- * @endCode
+ * ```
  *
  * At time of writing, there are a few limitations in how HookInterface is handled
  * by CiviTestListener:
diff --git a/civicrm/Civi/Test/MailingTestTrait.php b/civicrm/Civi/Test/MailingTestTrait.php
index 6609750fbe..b6ee14d872 100644
--- a/civicrm/Civi/Test/MailingTestTrait.php
+++ b/civicrm/Civi/Test/MailingTestTrait.php
@@ -18,7 +18,7 @@ trait MailingTestTrait {
    *
    * @return int
    */
-  public function createMailing($params = array()) {
+  public function createMailing($params = []) {
     $params = array_merge(array(
       'subject' => 'maild' . rand(),
       'body_text' => 'bdkfhdskfhduew{domain.address}{action.optOutUrl}',
diff --git a/civicrm/Civi/Token/Event/TokenRegisterEvent.php b/civicrm/Civi/Token/Event/TokenRegisterEvent.php
index ee867b949e..730ddb616c 100644
--- a/civicrm/Civi/Token/Event/TokenRegisterEvent.php
+++ b/civicrm/Civi/Token/Event/TokenRegisterEvent.php
@@ -8,7 +8,7 @@ namespace Civi\Token\Event;
  * The TokenRegisterEvent is fired when constructing a list of available
  * tokens. Listeners may register by specifying the entity/field/label for the token.
  *
- * @code
+ * ```
  * $ev->entity('profile')
  *    ->register('viewUrl', ts('Default Profile URL (View Mode)')
  *    ->register('editUrl', ts('Default Profile URL (Edit Mode)');
@@ -17,7 +17,7 @@ namespace Civi\Token\Event;
  *   'field' => 'viewUrl',
  *   'label' => ts('Default Profile URL (View Mode)'),
  * ));
- * @endcode
+ * ```
  *
  * Event name: 'civi.token.list'
  */
diff --git a/civicrm/Civi/Token/Event/TokenValueEvent.php b/civicrm/Civi/Token/Event/TokenValueEvent.php
index c9a251ccc7..ed7a3e2504 100644
--- a/civicrm/Civi/Token/Event/TokenValueEvent.php
+++ b/civicrm/Civi/Token/Event/TokenValueEvent.php
@@ -8,7 +8,7 @@ namespace Civi\Token\Event;
  * A TokenValueEvent is fired to convert raw query data into mergeable
  * tokens. For example:
  *
- * @code
+ * ```
  * $event = new TokenValueEvent($myContext, 'text/html', array(
  *   array('contact_id' => 123),
  *   array('contact_id' => 456),
diff --git a/civicrm/Civi/Token/TokenRow.php b/civicrm/Civi/Token/TokenRow.php
index cb38ead05b..536b6ab237 100644
--- a/civicrm/Civi/Token/TokenRow.php
+++ b/civicrm/Civi/Token/TokenRow.php
@@ -11,25 +11,25 @@ namespace Civi\Token;
  * (1) When setting up a job, you may specify general/baseline info.
  * This is called the "context" data. Here, we create two rows:
  *
- * @code
+ * ```
  * $proc->addRow()->context('contact_id', 123);
  * $proc->addRow()->context('contact_id', 456);
- * @endCode
+ * ```
  *
  * (2) When defining a token (eg `{profile.viewUrl}`), you might read the
  * context-data (`contact_id`) and set the token-data (`profile => viewUrl`):
  *
- * @code
+ * ```
  * foreach ($proc->getRows() as $row) {
  *   $row->tokens('profile', [
  *     'viewUrl' => 'http://example.com/profile?cid=' . urlencode($row->context['contact_id'];
  *   ]);
  * }
- * @endCode
+ * ```
  *
  * The context and tokens can be accessed using either methods or attributes.
  *
- * @code
+ * ```
  * # Setting context data
  * $row->context('contact_id', 123);
  * $row->context(['contact_id' => 123]);
@@ -43,7 +43,7 @@ namespace Civi\Token;
  *
  * # Reading token data
  * echo $row->tokens['profile']['viewUrl'];
- * @endCode
+ * ```
  *
  * Note: The methods encourage a "fluent" style. They were written for PHP 5.3
  * (eg before short-array syntax was supported) and are fairly flexible about
diff --git a/civicrm/ang/api4Explorer/Clause.html b/civicrm/ang/api4Explorer/Clause.html
index 6ccdff2bcd..9f9412e9f7 100644
--- a/civicrm/ang/api4Explorer/Clause.html
+++ b/civicrm/ang/api4Explorer/Clause.html
@@ -1,7 +1,7 @@
 <legend>{{ data.label || data.op + ' group' }}<span class="crm-marker" ng-if="data.required"> *</span></legend>
 <div class="btn-group btn-group-xs" ng-if="data.groupParent">
   <button class="btn btn-danger-outline" ng-click="removeGroup()" title="{{:: ts('Remove group') }}">
-    <i class="crm-i fa-trash"></i>
+    <i class="crm-i fa-trash" aria-hidden="true"></i>
   </button>
 </div>
 <div class="api4-clause-group-sortable" ng-model="data.clauses" ui-sortable="{axis: 'y', connectWith: '.api4-clause-group-sortable', containment: '.api4-clause-fieldset', over: onSortOver}" ui-sortable-start="onSort" ui-sortable-stop="onSort">
@@ -10,7 +10,7 @@
       <span class="badge badge-info">
         <span ng-if="!index && !data.groupParent">{{ data.type }}</span>
         <span ng-if="index || data.groupParent">{{ data.op }}</span>
-        <i class="crm-i fa-arrows"></i>
+        <i class="crm-i fa-arrows" aria-hidden="true"></i>
       </span>
     </div>
     <div ng-if="clause[0] !== 'AND' && clause[0] !== 'OR' && clause[0] !== 'NOT'" class="api4-input-group">
diff --git a/civicrm/ang/api4Explorer/Explorer.html b/civicrm/ang/api4Explorer/Explorer.html
index abff9b0162..d1379c8929 100644
--- a/civicrm/ang/api4Explorer/Explorer.html
+++ b/civicrm/ang/api4Explorer/Explorer.html
@@ -8,7 +8,7 @@
   <!--This warning will show if bootstrap is unavailable. Normally it will be hidden by the bootstrap .collapse class.-->
   <div class="messages warning no-popup collapse">
     <p>
-      <i class="crm-i fa-exclamation-triangle"></i>
+      <i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i>
       <strong>{{:: ts('Bootstrap theme not found.') }}</strong>
     </p>
     <p>{{:: ts('This screen may not work correctly without a bootstrap-based theme such as Shoreditch installed.') }}</p>
@@ -48,21 +48,36 @@
             <label class="radio-inline">
               <input type="radio" ng-model="params[name]" ng-value="false" />false
             </label>
-            <a href class="crm-hover-button" title="Clear" ng-click="clearParam(name)" ng-show="params[name] !== null"><i class="crm-i fa-times"></i></a>
+            <a href class="crm-hover-button" title="Clear" ng-click="clearParam(name)" ng-show="params[name] !== null"><i class="crm-i fa-times" aria-hidden="true"></i></a>
           </div>
           <fieldset class="api4-input form-inline" ng-mouseenter="help('select', availableParams.select)" ng-mouseleave="help()" ng-if="availableParams.select && !isSelectRowCount()">
             <legend>select<span class="crm-marker" ng-if="::availableParams.select.required"> *</span></legend>
             <div ng-model="params.select" ui-sortable="{axis: 'y'}">
               <div class="api4-input form-inline" ng-repeat="item in params.select track by $index">
-                <i class="crm-i fa-arrows"></i>
+                <i class="crm-i fa-arrows" aria-hidden="true"></i>
                 <input class="form-control huge" type="text" ng-model="params.select[$index]" />
-                <a href class="crm-hover-button" title="Clear" ng-click="clearParam('select', $index)"><i class="crm-i fa-times"></i></a>
+                <a href class="crm-hover-button" title="Clear" ng-click="clearParam('select', $index)"><i class="crm-i fa-times" aria-hidden="true"></i></a>
               </div>
             </div>
             <div class="api4-input form-inline">
               <input class="collapsible-optgroups form-control huge" ng-model="controls.select" crm-ui-select="{data: fieldsAndJoinsAndFunctionsAndWildcards}" placeholder="Add select" />
             </div>
           </fieldset>
+          <fieldset class="api4-input form-inline" ng-mouseenter="help('join', availableParams.join)" ng-mouseleave="help()" ng-if="::availableParams.join">
+            <legend>join<span class="crm-marker" ng-if="::availableParams.join.required"> *</span></legend>
+            <div ng-model="params.join" ui-sortable="{axis: 'y'}">
+              <div class="api4-input form-inline" ng-repeat="item in params.join track by $index">
+                <i class="crm-i fa-arrows"></i>
+                <input class="form-control twenty" type="text" ng-model="params.join[$index][0]" />
+                <select class="form-control" ng-model="params.join[$index][1]" ng-options="o.k as o.v for o in ::joinTypes" ></select>
+                <input class="form-control twenty" type="text" ng-model="params.join[$index][2]" />
+                <a href class="crm-hover-button" title="Clear" ng-click="clearParam('join', $index)"><i class="crm-i fa-times"></i></a>
+              </div>
+            </div>
+            <div class="api4-input form-inline">
+              <input class="collapsible-optgroups form-control huge" ng-model="controls.join" crm-ui-select="{data: entities}" placeholder="Add join" />
+            </div>
+          </fieldset>
           <div class="api4-input form-inline" ng-mouseenter="help('fields', availableParams.fields)" ng-mouseleave="help()" ng-if="::availableParams.fields">
             <label for="api4-param-fields">fields<span class="crm-marker" ng-if="::availableParams.fields.required"> *</span></label>
             <input class="form-control" ng-list crm-ui-select="::{data: fields, multiple: true}" id="api4-param-fields" ng-model="params.fields" style="width: 85%;"/>
@@ -75,7 +90,7 @@
             <label for="api4-param-{{:: name }}">{{:: name }}<span class="crm-marker" ng-if="::param.required"> *</span></label>
             <input class="form-control" ng-if="::!param.options" type="{{:: param.type[0] === 'int' && param.type.length === 1 ? 'number' : 'text' }}" id="api4-param-{{:: name }}" ng-model="params[name]"/>
             <select class="form-control" ng-if="::param.options" ng-options="o for o in ::param.options" id="api4-param-{{:: name }}" ng-model="params[name]"></select>
-            <a href class="crm-hover-button" title="Clear" ng-click="clearParam(name)" ng-show="!!params[name]"><i class="crm-i fa-times"></i></a>
+            <a href class="crm-hover-button" title="Clear" ng-click="clearParam(name)" ng-show="!!params[name]"><i class="crm-i fa-times" aria-hidden="true"></i></a>
           </div>
           <div class="api4-input" ng-mouseenter="help(name, param)" ng-mouseleave="help()" ng-repeat="(name, param) in ::getGenericParams(['array', 'mixed'])">
             <label for="api4-param-{{:: name }}">{{:: name }}<span class="crm-marker" ng-if="::param.required"> *</span></label>
@@ -98,9 +113,9 @@
             <legend>groupBy<span class="crm-marker" ng-if="::availableParams.groupBy.required"> *</span></legend>
             <div ng-model="params.groupBy" ui-sortable="{axis: 'y'}">
               <div class="api4-input form-inline" ng-repeat="item in params.groupBy track by $index">
-                <i class="crm-i fa-arrows"></i>
+                <i class="crm-i fa-arrows" aria-hidden="true"></i>
                 <input class="form-control huge" type="text" ng-model="params.groupBy[$index]" />
-                <a href class="crm-hover-button" title="Clear" ng-click="clearParam('groupBy', $index)"><i class="crm-i fa-times"></i></a>
+                <a href class="crm-hover-button" title="Clear" ng-click="clearParam('groupBy', $index)"><i class="crm-i fa-times" aria-hidden="true"></i></a>
               </div>
             </div>
             <div class="api4-input form-inline">
@@ -113,17 +128,17 @@
             <legend>orderBy<span class="crm-marker" ng-if="::availableParams.orderBy.required"> *</span></legend>
             <div ng-model="params.orderBy" ui-sortable="{axis: 'y'}">
               <div class="api4-input form-inline" ng-repeat="clause in params.orderBy">
-                <i class="crm-i fa-arrows"></i>
+                <i class="crm-i fa-arrows" aria-hidden="true"></i>
                 <input class="form-control huge" type="text" ng-model="clause[0]" />
                 <select class="form-control" ng-model="clause[1]">
                   <option value="ASC">ASC</option>
                   <option value="DESC">DESC</option>
                 </select>
-                <a href class="crm-hover-button" title="Clear" ng-click="clearParam('orderBy', $index)"><i class="crm-i fa-times"></i></a>
+                <a href class="crm-hover-button" title="Clear" ng-click="clearParam('orderBy', $index)"><i class="crm-i fa-times" aria-hidden="true"></i></a>
               </div>
             </div>
             <div class="api4-input form-inline">
-              <input class="collapsible-optgroups form-control huge" ng-model="controls.orderBy" crm-ui-select="{data: fieldsAndJoinsAndFunctions}" placeholder="Add orderBy" />
+              <input class="collapsible-optgroups form-control huge" ng-model="controls.orderBy" crm-ui-select="{data: fieldsAndJoinsAndFunctionsWithSuffixes}" placeholder="Add orderBy" />
             </div>
           </fieldset>
           <fieldset ng-if="::availableParams.limit && availableParams.offset">
@@ -136,7 +151,7 @@
                 <label for="api4-param-offset">offset<span class="crm-marker" ng-if="::availableParams.offset.required"> *</span></label>
                 <input class="form-control" type="number" min="0" id="api4-param-offset" ng-model="params.offset"/>
               </span>
-              <a href class="crm-hover-button" title="Clear" ng-click="clearParam('limit');clearParam('offset');" ng-show="!!params.limit || !!params.offset"><i class="crm-i fa-times"></i></a>
+              <a href class="crm-hover-button" title="Clear" ng-click="clearParam('limit');clearParam('offset');" ng-show="!!params.limit || !!params.offset"><i class="crm-i fa-times" aria-hidden="true"></i></a>
             </div>
           </fieldset>
           <fieldset ng-if="::availableParams.chain" ng-mouseenter="help('chain', availableParams.chain)" ng-mouseleave="help()">
diff --git a/civicrm/ang/api4Explorer/Explorer.js b/civicrm/ang/api4Explorer/Explorer.js
index 97c6152e23..17de0a2958 100644
--- a/civicrm/ang/api4Explorer/Explorer.js
+++ b/civicrm/ang/api4Explorer/Explorer.js
@@ -28,6 +28,7 @@
     $scope.havingOptions = [];
     $scope.fieldsAndJoins = [];
     $scope.fieldsAndJoinsAndFunctions = [];
+    $scope.fieldsAndJoinsAndFunctionsWithSuffixes = [];
     $scope.fieldsAndJoinsAndFunctionsAndWildcards = [];
     $scope.availableParams = {};
     $scope.params = {};
@@ -52,6 +53,7 @@
     $scope.loading = false;
     $scope.controls = {};
     $scope.langs = ['php', 'js', 'ang', 'cli'];
+    $scope.joinTypes = [{k: false, v: ts('Optional')}, {k: true, v: ts('Required')}];
     $scope.code = {
       php: [
         {name: 'oop', label: ts('OOP Style'), code: ''},
@@ -136,7 +138,7 @@
           }
           fields.push({
             text: link.alias,
-            description: 'Join to ' + link.entity,
+            description: 'Implicit join to ' + link.entity,
             children: wildCard.concat(formatForSelect2(linkFields, [], 'name', ['description'], link.alias + '.'))
           });
         }
@@ -253,7 +255,7 @@
       if (_.isEmpty($scope.availableParams)) {
         return;
       }
-      var specialParams = ['select', 'fields', 'action', 'where', 'values', 'defaults', 'orderBy', 'chain', 'groupBy', 'having'];
+      var specialParams = ['select', 'fields', 'action', 'where', 'values', 'defaults', 'orderBy', 'chain', 'groupBy', 'having', 'join'];
       if ($scope.availableParams.limit && $scope.availableParams.offset) {
         specialParams.push('limit', 'offset');
       }
@@ -356,6 +358,7 @@
       $scope.action = $routeParams.api4action;
       $scope.fieldsAndJoins.length = 0;
       $scope.fieldsAndJoinsAndFunctions.length = 0;
+      $scope.fieldsAndJoinsAndFunctionsWithSuffixes.length = 0;
       $scope.fieldsAndJoinsAndFunctionsAndWildcards.length = 0;
       if (!actions.length) {
         formatForSelect2(getEntity().actions, actions, 'name', ['description', 'params']);
@@ -381,10 +384,12 @@
             });
           }
           $scope.fieldsAndJoinsAndFunctions = addJoins($scope.fields.concat(functions), true);
+          $scope.fieldsAndJoinsAndFunctionsWithSuffixes = addJoins(getFieldList($scope.action, ['name', 'label']).concat(functions), false, ['name', 'label']);
           $scope.fieldsAndJoinsAndFunctionsAndWildcards = addJoins(getFieldList($scope.action, ['name', 'label']).concat(functions), true, ['name', 'label']);
         } else {
           $scope.fieldsAndJoins = getFieldList($scope.action, ['name']);
           $scope.fieldsAndJoinsAndFunctions = $scope.fields;
+          $scope.fieldsAndJoinsAndFunctionsWithSuffixes = getFieldList($scope.action, ['name', 'label']);
           $scope.fieldsAndJoinsAndFunctionsAndWildcards = getFieldList($scope.action, ['name', 'label']);
         }
         $scope.fieldsAndJoinsAndFunctionsAndWildcards.unshift({id: '*', text: '*', 'description': 'All core ' + $scope.entity + ' fields'});
@@ -454,12 +459,15 @@
               });
             });
           }
-          if (typeof objectParams[name] !== 'undefined' || name === 'groupBy' || name === 'select') {
+          if (typeof objectParams[name] !== 'undefined' || name === 'groupBy' || name === 'select' || name === 'join') {
             $scope.$watch('controls.' + name, function(value) {
               var field = value;
               $timeout(function() {
                 if (field) {
-                  if (typeof objectParams[name] === 'undefined') {
+                  if (name === 'join') {
+                    $scope.params[name].push([field + ' AS ' + _.snakeCase(field), false, '[]']);
+                  }
+                  else if (typeof objectParams[name] === 'undefined') {
                     $scope.params[name].push(field);
                   } else {
                     var defaultOp = _.cloneDeep(objectParams[name]);
diff --git a/civicrm/ang/crmCaseType.js b/civicrm/ang/crmCaseType.js
index 0b97432237..c8b836b385 100644
--- a/civicrm/ang/crmCaseType.js
+++ b/civicrm/ang/crmCaseType.js
@@ -138,9 +138,9 @@
       link: function(scope, element, attrs) {
         element.addClass('crm-editable crm-editable-enabled');
         var titleLabel = $(element).find('span');
-        var penIcon = $('<i class="crm-i fa-pencil crm-editable-placeholder"></i>').prependTo(element);
-        var saveButton = $('<button type="button"><i class="crm-i fa-check"></i></button>').appendTo(element);
-        var cancelButton = $('<button type="cancel"><i class="crm-i fa-times"></i></button>').appendTo(element);
+        var penIcon = $('<i class="crm-i fa-pencil crm-editable-placeholder" aria-hidden="true"></i>').prependTo(element);
+        var saveButton = $('<button type="button"><i class="crm-i fa-check" aria-hidden="true"></i></button>').appendTo(element);
+        var cancelButton = $('<button type="cancel"><i class="crm-i fa-times" aria-hidden="true"></i></button>').appendTo(element);
         $('button', element).wrapAll('<div class="crm-editable-form" style="display:none" />');
         var buttons = $('.crm-editable-form', element);
         titleLabel.on('click', startEditMode);
diff --git a/civicrm/ang/crmCaseType/activityTypesTable.html b/civicrm/ang/crmCaseType/activityTypesTable.html
index 3563f0318f..46645da174 100644
--- a/civicrm/ang/crmCaseType/activityTypesTable.html
+++ b/civicrm/ang/crmCaseType/activityTypesTable.html
@@ -15,10 +15,10 @@ Required vars: caseType
   <tbody ui-sortable ng-model="caseType.definition.activityTypes">
   <tr ng-repeat="activityType in caseType.definition.activityTypes">
     <td>
-      <i class="crm-i fa-arrows grip-n-drag"></i>
+      <i class="crm-i fa-arrows grip-n-drag" aria-hidden="true"></i>
     </td>
     <td>
-      <i class="crm-i {{ activityTypes[activityType.name].icon }}"></i>
+      <i class="crm-i {{ activityTypes[activityType.name].icon }}" aria-hidden="true"></i>
       {{ activityTypes[activityType.name].label }}
     </td>
     <td>
diff --git a/civicrm/ang/crmCaseType/list.html b/civicrm/ang/crmCaseType/list.html
index ed3f7bd359..c9ebc7e60d 100644
--- a/civicrm/ang/crmCaseType/list.html
+++ b/civicrm/ang/crmCaseType/list.html
@@ -74,6 +74,6 @@ Required vars: caseTypes
   </table>
 
   <div class="crm-submit-buttons">
-    <a ng-href="#/caseType/new" class="button"><span><i class="crm-i fa-plus-circle"></i> {{:: ts('New Case Type') }}</span></a>
+    <a ng-href="#/caseType/new" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {{:: ts('New Case Type') }}</span></a>
   </div>
 </div>
diff --git a/civicrm/ang/crmCaseType/sequenceTable.html b/civicrm/ang/crmCaseType/sequenceTable.html
index ef62fb06b5..4ee780edd2 100644
--- a/civicrm/ang/crmCaseType/sequenceTable.html
+++ b/civicrm/ang/crmCaseType/sequenceTable.html
@@ -14,10 +14,10 @@ Required vars: activitySet
   <tbody ui-sortable ng-model="activitySet.activityTypes">
   <tr ng-repeat="activity in activitySet.activityTypes">
     <td>
-      <i class="crm-i fa-arrows grip-n-drag"></i>
+      <i class="crm-i fa-arrows grip-n-drag" aria-hidden="true"></i>
     </td>
     <td>
-      <i class="crm-i {{ activityTypes[activity.name].icon }}"></i>
+      <i class="crm-i {{ activityTypes[activity.name].icon }}" aria-hidden="true"></i>
       {{ activity.name }}
     </td>
     <td>
diff --git a/civicrm/ang/crmCaseType/statusTable.html b/civicrm/ang/crmCaseType/statusTable.html
index e7dfd9eb21..085241e22f 100644
--- a/civicrm/ang/crmCaseType/statusTable.html
+++ b/civicrm/ang/crmCaseType/statusTable.html
@@ -28,7 +28,7 @@ Required vars: selectedStatuses
   <tfoot>
   <tr>
     <td></td>
-    <td><a class="crm-hover-button action-item" ng-click="newStatus()" href><i class="crm-i fa-plus"></i> {{:: ts('New Status') }}</a></td>
+    <td><a class="crm-hover-button action-item" ng-click="newStatus()" href><i class="crm-i fa-plus" aria-hidden="true"></i> {{:: ts('New Status') }}</a></td>
     <td></td>
   </tr>
   </tfoot>
diff --git a/civicrm/ang/crmCaseType/timelineTable.html b/civicrm/ang/crmCaseType/timelineTable.html
index 76113a1208..e25351d782 100644
--- a/civicrm/ang/crmCaseType/timelineTable.html
+++ b/civicrm/ang/crmCaseType/timelineTable.html
@@ -19,10 +19,10 @@ Required vars: activitySet
   <tbody ui-sortable ng-model="activitySet.activityTypes">
   <tr ng-repeat="activity in activitySet.activityTypes">
     <td>
-      <i class="crm-i fa-arrows grip-n-drag"></i>
+      <i class="crm-i fa-arrows grip-n-drag" aria-hidden="true"></i>
     </td>
     <td>
-      <i class="crm-i {{activityTypes[activity.name].icon}}"></i>
+      <i class="crm-i {{activityTypes[activity.name].icon}}" aria-hidden="true"></i>
       {{activity.label}}
     </td>
     <td>
diff --git a/civicrm/ang/crmCxn/ManageCtrl.html b/civicrm/ang/crmCxn/ManageCtrl.html
index 78509a0601..2e84994ec6 100644
--- a/civicrm/ang/crmCxn/ManageCtrl.html
+++ b/civicrm/ang/crmCxn/ManageCtrl.html
@@ -115,6 +115,6 @@
 </div>
 
 <div ng-show="appMetas.length === 0" class="messages status no-popup">
-  <i class="crm-i fa-info-circle"></i>
+  <i class="crm-i fa-info-circle" aria-hidden="true"></i>
   {{:: ts('No available applications') }}
 </div>
diff --git a/civicrm/ang/crmMailing.css b/civicrm/ang/crmMailing.css
index b853cb4466..0d854055ff 100644
--- a/civicrm/ang/crmMailing.css
+++ b/civicrm/ang/crmMailing.css
@@ -86,10 +86,6 @@ input[name=preview_test_email]:-ms-input-placeholder {
   font-size: 1.2em;
   float: none;
 }
-.crm-container a.crmMailing-submit-button div {
-  background: url(../i/check.gif) no-repeat left center;
-  padding-left: 20px;
-}
 .crm-container a.crmMailing-submit-button.disabled,
 .crm-container a.crmMailing-submit-button.blocking {
   opacity: .6;
diff --git a/civicrm/ang/crmMailing/BlockPreview.js b/civicrm/ang/crmMailing/BlockPreview.js
index 5e582dc056..334e15d440 100644
--- a/civicrm/ang/crmMailing/BlockPreview.js
+++ b/civicrm/ang/crmMailing/BlockPreview.js
@@ -48,7 +48,7 @@
             markup += '</ol>';
             markup = '<h4>' + ts('A test message will be sent to %1 people:', {1: count}) + '</h4>' + markup;
             if (!count) {
-              markup = '<div class="messages status"><i class="crm-i fa-exclamation-triangle"></i> ' +
+              markup = '<div class="messages status"><i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i> ' +
               (data.contact.count ? ts('None of the contacts in this group have an email address.') : ts('Group is empty.')) +
               '</div>';
             }
diff --git a/civicrm/ang/crmMailing/EditMailingCtrl/2step.html b/civicrm/ang/crmMailing/EditMailingCtrl/2step.html
index 5901a0dd79..6e0ee05ef5 100644
--- a/civicrm/ang/crmMailing/EditMailingCtrl/2step.html
+++ b/civicrm/ang/crmMailing/EditMailingCtrl/2step.html
@@ -42,9 +42,7 @@
           <div crm-mailing-block-schedule crm-mailing="mailing"></div>
         </div>
         <center>
-          <a class="button crmMailing-submit-button crmMailing-btn-primary" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
-            <div>{{:: ts('Submit Mailing') }}</div>
-          </a>
+          <a class="button crmMailing-submit-button crmMailing-btn-primary" crm-icon="fa-paper-plane" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">{{:: ts('Submit Mailing') }}</a>
         </center>
       </div>
 
diff --git a/civicrm/ang/crmMailing/EditMailingCtrl/wizard.html b/civicrm/ang/crmMailing/EditMailingCtrl/wizard.html
index 569880f0c0..8c18184099 100644
--- a/civicrm/ang/crmMailing/EditMailingCtrl/wizard.html
+++ b/civicrm/ang/crmMailing/EditMailingCtrl/wizard.html
@@ -45,9 +45,7 @@
           <div crm-mailing-block-review crm-mailing="mailing" crm-mailing-attachments="attachments"></div>
         </div>
         <center>
-          <a class="button crmMailing-submit-button crmMailing-btn-primary" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
-            <div>{{:: ts('Submit Mailing') }}</div>
-          </a>
+          <a class="button crmMailing-submit-button crmMailing-btn-primary" crm-icon="fa-paper-plane" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">{{:: ts('Submit Mailing') }}</a>
         </center>
       </div>
 
diff --git a/civicrm/ang/crmMailing/EditMailingCtrl/workflow.html b/civicrm/ang/crmMailing/EditMailingCtrl/workflow.html
index e5a3d4eb45..bdd3245dde 100644
--- a/civicrm/ang/crmMailing/EditMailingCtrl/workflow.html
+++ b/civicrm/ang/crmMailing/EditMailingCtrl/workflow.html
@@ -47,14 +47,10 @@
           <div crm-mailing-block-approve crm-mailing="mailing"></div>
         </div>
         <center ng-if="!checkPerm('approve mailings') && !checkPerm('access CiviMail')">
-          <a class="button crmMailing-submit-button crmMailing-btn-primary" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
-            <div>{{:: ts('Submit Mailing') }}</div>
-          </a>
+          <a class="button crmMailing-submit-button crmMailing-btn-primary" crm-icon="fa-check" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">{{:: ts('Submit Mailing') }}</a>
         </center>
         <center ng-if="checkPerm('approve mailings') || checkPerm('access CiviMail')">
-          <a class="button crmMailing-submit-button crmMailing-btn-primary" ng-click="approve('Approved')" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">
-            <div>{{:: ts('Submit and Approve Mailing') }}</div>
-          </a>
+          <a class="button crmMailing-submit-button crmMailing-btn-primary" crm-icon="fa-paper-plane" ng-click="approve('Approved')" ng-class="{blocking: block.check(), disabled: crmMailingSubform.$invalid}">{{:: ts('Submit and Approve Mailing') }}</a>
         </center>
       </div>
 
diff --git a/civicrm/ang/crmMailing/EmailBodyCtrl/tokenAlert.html b/civicrm/ang/crmMailing/EmailBodyCtrl/tokenAlert.html
index 81e52e1737..46e03827ee 100644
--- a/civicrm/ang/crmMailing/EmailBodyCtrl/tokenAlert.html
+++ b/civicrm/ang/crmMailing/EmailBodyCtrl/tokenAlert.html
@@ -4,7 +4,7 @@
 </p>
 
 <div ng-show="missing['domain.address'] && insertable">
-  <a ng-click="insertToken('domain.address')" class="button"><span><i class="crm-i fa-plus-circle"></i> {{:: ts('Address') }}</span></a>
+  <a ng-click="insertToken('domain.address')" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {{:: ts('Address') }}</span></a>
 
   <div class="clear"></div>
 </div>
@@ -24,18 +24,18 @@
     <tbody>
     <tr>
       <td>
-        <a ng-click="insertToken('action.unsubscribeUrl')" class="button"><span><i class="crm-i fa-plus-circle"></i> {{:: ts('Unsubscribe') }}</span></a>
+        <a ng-click="insertToken('action.unsubscribeUrl')" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {{:: ts('Unsubscribe') }}</span></a>
       </td>
       <td>
-        <a ng-click="insertToken('action.unsubscribe')" class="button"><span><i class="crm-i fa-plus-circle"></i> {{:: ts('Unsubscribe') }}</span></a>
+        <a ng-click="insertToken('action.unsubscribe')" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {{:: ts('Unsubscribe') }}</span></a>
       </td>
     </tr>
     <tr>
       <td>
-        <a ng-click="insertToken('action.optOutUrl')" class="button"><span><i class="crm-i fa-plus-circle"></i> {{:: ts('Opt-out') }}</span></a>
+        <a ng-click="insertToken('action.optOutUrl')" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {{:: ts('Opt-out') }}</span></a>
       </td>
       <td>
-        <a ng-click="insertToken('action.optOut')" class="button"><span><i class="crm-i fa-plus-circle"></i> {{:: ts('Opt-out') }}</span></a>
+        <a ng-click="insertToken('action.optOut')" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {{:: ts('Opt-out') }}</span></a>
       </td>
     </tr>
     </tbody>
diff --git a/civicrm/ang/crmMailing/Recipients.js b/civicrm/ang/crmMailing/Recipients.js
index 4203d4a3c8..0d39cde49e 100644
--- a/civicrm/ang/crmMailing/Recipients.js
+++ b/civicrm/ang/crmMailing/Recipients.js
@@ -99,7 +99,7 @@
           if (option.entity_type != 'civicrm_mailing' && isMandatory(option.entity_id)) {
             spanClass = 'crmMailing-mandatory';
           }
-          return '<i class="crm-i '+icon+'"></i> <span class="' + spanClass + '">' + item.text + '</span>';
+          return '<i class="crm-i '+icon+'" aria-hidden="true"></i> <span class="' + spanClass + '">' + item.text + '</span>';
         }
 
         function validate() {
diff --git a/civicrm/ang/crmMailingAB/EditCtrl/edit.html b/civicrm/ang/crmMailingAB/EditCtrl/edit.html
index de95f0351b..94e6b2574b 100644
--- a/civicrm/ang/crmMailingAB/EditCtrl/edit.html
+++ b/civicrm/ang/crmMailingAB/EditCtrl/edit.html
@@ -158,9 +158,7 @@
           }"
           crm-abtest="abtest"></div>
         <center>
-          <a class="button crmMailing-submit-button" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingAB.$invalid}">
-            <div>{{:: ts('Submit Mailing') }}</div>
-          </a>
+          <a class="button crmMailing-submit-button" crm-icon="fa-paper-plane" ng-click="submit()" ng-class="{blocking: block.check(), disabled: crmMailingAB.$invalid}">{{:: ts('Submit Mailing') }}</a>
         </center>
       </div>
       <span crm-ui-wizard-buttons style="float:right;">
diff --git a/civicrm/ang/crmMailingAB/ListCtrl.html b/civicrm/ang/crmMailingAB/ListCtrl.html
index 29fe00ed63..0d5c1499e8 100644
--- a/civicrm/ang/crmMailingAB/ListCtrl.html
+++ b/civicrm/ang/crmMailingAB/ListCtrl.html
@@ -52,12 +52,12 @@ Required vars: mailingABList
 </div>
 
 <div ng-show="mailingABList.length === 0" class="messages status no-popup">
-  <i class="crm-i fa-info-circle"></i>
+  <i class="crm-i fa-info-circle" aria-hidden="true"></i>
   {{:: ts('You have no A/B mailings') }}
 </div>
 
 
 <div class="crm-submit-buttons">
   <br>
-  <a ng-href="#/abtest/new" class="button"><span><i class="crm-i fa-bar-chart"></i> {{:: ts('New A/B Test') }}</span></a>
+  <a ng-href="#/abtest/new" class="button"><span><i class="crm-i fa-flask" aria-hidden="true"></i> {{:: ts('New A/B Test') }}</span></a>
 </div>
diff --git a/civicrm/ang/crmStatusPage/StatusPage.html b/civicrm/ang/crmStatusPage/StatusPage.html
index bf252cbeb1..dfdfbdf24b 100644
--- a/civicrm/ang/crmStatusPage/StatusPage.html
+++ b/civicrm/ang/crmStatusPage/StatusPage.html
@@ -14,7 +14,7 @@
     >
     <div class="crm-status-item" ng-repeat="status in statuses | filter:{is_visible: tab.is_visible}" >
       <h3 class="crm-severity-{{status.severity}}">
-        <i ng-if="status.icon" class="crm-i {{status.icon}}"></i>
+        <i ng-if="status.icon" class="crm-i {{status.icon}}" aria-hidden="true"></i>
         {{status.title}}
         <div statuspage-popup-menu class="hush-menu css_right"></div>
         <div ng-if="!status.is_visible" class="hidden-until css_right">
diff --git a/civicrm/ang/crmUi.js b/civicrm/ang/crmUi.js
index 0b09c60de7..7482999091 100644
--- a/civicrm/ang/crmUi.js
+++ b/civicrm/ang/crmUi.js
@@ -824,9 +824,9 @@
             return steps[selectedIndex] && steps[selectedIndex].isStepValid();
           };
           this.iconFor = function(index) {
-            if (index < this.$index()) return '√';
-            if (index === this.$index()) return '»';
-            return ' ';
+            if (index < this.$index()) return 'crm-i fa-check';
+            if (index === this.$index()) return 'crm-i fa-angle-double-right';
+            return '';
           };
           this.isSelectable = function(step) {
             if (step.selected) return false;
@@ -919,7 +919,7 @@
             return;
           }
           if (attrs.crmIcon.substring(0,3) == 'fa-') {
-            $(element).prepend('<i class="crm-i ' + attrs.crmIcon + '"></i> ');
+            $(element).prepend('<i class="crm-i ' + attrs.crmIcon + '" aria-hidden="true"></i> ');
           }
           else {
             $(element).prepend('<span class="icon ui-icon-' + attrs.crmIcon + '"></span> ');
@@ -1051,7 +1051,7 @@
     // set a custom title (i.e., it has an initial title of "CiviCRM"). See the
     // global variables pageTitle and documentTitle.
     // Example (same title for both): <h1 crm-page-title>{{ts('Hello')}}</h1>
-    // Example (separate document title): <h1 crm-document-title="ts('Hello')" crm-page-title><i class="crm-i fa-flag"></i>{{ts('Hello')}}</h1>
+    // Example (separate document title): <h1 crm-document-title="ts('Hello')" crm-page-title><i class="crm-i fa-flag" aria-hidden="true"></i>{{ts('Hello')}}</h1>
     .directive('crmPageTitle', function($timeout) {
       return {
         scope: {
diff --git a/civicrm/ang/crmUi/tabset.html b/civicrm/ang/crmUi/tabset.html
index 6bb45711f0..9a17d97e1b 100644
--- a/civicrm/ang/crmUi/tabset.html
+++ b/civicrm/ang/crmUi/tabset.html
@@ -2,7 +2,7 @@
   <ul>
     <li ng-repeat="tab in tabs" class="ui-corner-all crm-tab-button crm-count-{{tab.count}}">
       <a href="#{{tab.id}}">
-        <i ng-if="tab.crmIcon" class="crm-i {{tab.crmIcon}}"></i>
+        <i ng-if="tab.crmIcon" class="crm-i {{tab.crmIcon}}" aria-hidden="true"></i>
         {{tab.$parent.$eval(tab.crmTitle)}}
         <em ng-if="tab.count">{{tab.count}}</em>
       </a>
diff --git a/civicrm/ang/crmUi/wizard.html b/civicrm/ang/crmUi/wizard.html
index bb55c89b1d..2539f38336 100644
--- a/civicrm/ang/crmUi/wizard.html
+++ b/civicrm/ang/crmUi/wizard.html
@@ -1,7 +1,7 @@
 <div class="crm-wizard">
   <ul class="crm-wizard-nav wizard-bar">
     <li ng-repeat="step in steps" ng-class="{'current-step':step.selected}" class="{{crmUiWizardNavClass}}">
-      <span>{{crmUiWizardCtrl.iconFor($index)}}</span>
+      <i class="{{crmUiWizardCtrl.iconFor($index)}}"></i>
       <a href="" ng-click="crmUiWizardCtrl.select(step)" ng-show="crmUiWizardCtrl.isSelectable(step)">{{1 + $index}}. {{step.$parent.$eval(step.crmTitle)}}</a>
       <span ng-show="!crmUiWizardCtrl.isSelectable(step)">{{1 + $index}}. {{step.$parent.$eval(step.crmTitle)}}</span>
       <!-- Don't know a good way to localize text like "1. Title" -->
diff --git a/civicrm/ang/exportui/exportField.html b/civicrm/ang/exportui/exportField.html
index 7ae919749c..25d1bfb84e 100644
--- a/civicrm/ang/exportui/exportField.html
+++ b/civicrm/ang/exportui/exportField.html
@@ -1,5 +1,5 @@
 <div>
-  <span class="crm-export-row-handle crm-i fa-arrows"></span>
+  <span class="crm-export-row-handle crm-i fa-arrows" aria-hidden="true"></span>
   <input class="big" crm-ui-select="{data: getFields, allowClear: true, placeholder: 'clear'}" ng-model="field.select" />
 </div>
 <div ng-if="fields[field.select].relationship_type_id">
diff --git a/civicrm/api/api.php b/civicrm/api/api.php
index 8208af08db..be1946db37 100644
--- a/civicrm/api/api.php
+++ b/civicrm/api/api.php
@@ -281,33 +281,25 @@ function _civicrm_api_replace_variable($value, $parentResult, $separator) {
  *
  * @return string
  *   Entity name in underscore separated format.
+ *
+ * @deprecated
  */
 function _civicrm_api_get_entity_name_from_camel($entity) {
-  if (!$entity || $entity === strtolower($entity)) {
-    return $entity;
-  }
-  elseif ($entity == 'PCP') {
-    return 'pcp';
-  }
-  else {
-    $entity = ltrim(strtolower(str_replace('U_F',
-          'uf',
-          // That's CamelCase, beside an odd UFCamel that is expected as uf_camel
-          preg_replace('/(?=[A-Z])/', '_$0', $entity)
-        )), '_');
+  if (!$entity) {
+    // @todo - this should not be called when empty.
+    return '';
   }
-  return $entity;
+  return CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($entity);
 }
 
 /**
  * Having a DAO object find the entity name.
  *
- * @param object $bao
+ * @param CRM_Core_DAO $bao
  *   DAO being passed in.
  *
  * @return string
  */
 function _civicrm_api_get_entity_name_from_dao($bao) {
-  $daoName = str_replace("BAO", "DAO", get_class($bao));
-  return CRM_Core_DAO_AllCoreTables::getBriefName($daoName);
+  return CRM_Core_DAO_AllCoreTables::getBriefName(get_class($bao));
 }
diff --git a/civicrm/api/class.api.php b/civicrm/api/class.api.php
index 3e93b97a58..4ba61dd30b 100644
--- a/civicrm/api/class.api.php
+++ b/civicrm/api/class.api.php
@@ -4,36 +4,36 @@
  *
  * This class allows to consume the API, either from within a module that knows civicrm already:
  *
- * @code
+ * ```
  *   require_once('api/class.api.php');
  *   $api = new civicrm_api3();
- * @endcode
+ * ```
  *
  * or from any code on the same server as civicrm
  *
- * @code
+ * ```
  *   require_once('/your/civi/folder/api/class.api.php');
  *   // the path to civicrm.settings.php
  *   $api = new civicrm_api3 (array('conf_path'=> '/your/path/to/your/civicrm/or/joomla/site));
- * @endcode
+ * ```
  *
  * or to query a remote server via the rest api
  *
- * @code
+ * ```
  *   $api = new civicrm_api3 (array ('server' => 'http://example.org',
  *                                   'api_key'=>'theusersecretkey',
  *                                   'key'=>'thesitesecretkey'));
- * @endcode
+ * ```
  *
  * No matter how initialised and if civicrm is local or remote, you use the class the same way.
  *
- * @code
+ * ```
  *   $api->{entity}->{action}($params);
- * @endcode
+ * ```
  *
  * So, to get the individual contacts:
  *
- * @code
+ * ```
  *   if ($api->Contact->Get(array('contact_type'=>'Individual','return'=>'sort_name,current_employer')) {
  *     // each key of the result array is an attribute of the api
  *     echo "\n contacts found " . $api->count;
@@ -44,37 +44,37 @@
  *   } else {
  *     echo $api->errorMsg();
  *   }
- * @endcode
+ * ```
  *
  * Or, to create an event:
  *
- * @code
+ * ```
  *   if ($api->Event->Create(array('title'=>'Test','event_type_id' => 1,'is_public' => 1,'start_date' => 19430429))) {
  *     echo "created event id:". $api->id;
  *   } else {
  *     echo $api->errorMsg();
  *   }
- * @endcode
+ * ```
  *
  * To make it easier, the Actions can either take for input an
  * associative array $params, or simply an id. The following two lines
  * are equivalent.
  *
- * @code
+ * ```
  *   $api->Activity->Get (42);
  *   $api->Activity->Get (array('id'=>42));
- * @endcode
+ * ```
  *
  *
  * You can also get the result like civicrm_api does, but as an object
  * instead of an array (eg $entity->attribute instead of
  * $entity['attribute']).
  *
- * @code
+ * ```
  *   $result = $api->result;
  *   // is the json encoded result
  *   echo $api;
- * @endcode
+ * ```
  */
 class civicrm_api3 {
 
diff --git a/civicrm/api/v3/Activity.php b/civicrm/api/v3/Activity.php
index d02aaa2d02..8898fb2215 100644
--- a/civicrm/api/v3/Activity.php
+++ b/civicrm/api/v3/Activity.php
@@ -202,6 +202,8 @@ function _civicrm_api3_activity_create_spec(&$params) {
     'FKApiName' => 'Case',
   ];
 
+  $params['activity_date_time']['api.default'] = 'now';
+
 }
 
 /**
@@ -739,13 +741,6 @@ function _civicrm_api3_activity_check_params(&$params) {
     throw new API_Exception('Invalid Activity Duration (in minutes)');
   }
 
-  //if adding a new activity & date_time not set make it now
-  // this should be managed by the wrapper layer & setting ['api.default'] in speces
-  // needs testing
-  if (empty($params['id']) && empty($params['activity_date_time'])) {
-    $params['activity_date_time'] = CRM_Utils_Date::processDate(date('Y-m-d H:i:s'));
-  }
-
   return NULL;
 }
 
diff --git a/civicrm/api/v3/Attachment.php b/civicrm/api/v3/Attachment.php
index 1e78d6796b..8583f0b8c5 100644
--- a/civicrm/api/v3/Attachment.php
+++ b/civicrm/api/v3/Attachment.php
@@ -15,7 +15,7 @@
  * file content.
  * For core fields use "entity_table", for custom fields use "field_name"
  *
- * @code
+ * ```
  * // Create an attachment for a core field
  * $result = civicrm_api3('Attachment', 'create', array(
  *   'entity_table' => 'civicrm_activity',
@@ -26,9 +26,9 @@
  * ));
  * $attachment = $result['values'][$result['id']];
  * echo sprintf("<a href='%s'>View %s</a>", $attachment['url'], $attachment['name']);
- * @endcode
+ * ```
  *
- * @code
+ * ```
  * // Create an attachment for a custom file field
  * $result = civicrm_api3('Attachment', 'create', array(
  *   'field_name' => 'custom_6',
@@ -39,9 +39,9 @@
  * ));
  * $attachment = $result['values'][$result['id']];
  * echo sprintf("<a href='%s'>View %s</a>", $attachment['url'], $attachment['name']);
- * @endcode
+ * ```
  *
- * @code
+ * ```
  * // Move an existing file and save as an attachment
  * $result = civicrm_api3('Attachment', 'create', array(
  *   'entity_table' => 'civicrm_activity',
@@ -54,7 +54,7 @@
  * ));
  * $attachment = $result['values'][$result['id']];
  * echo sprintf("<a href='%s'>View %s</a>", $attachment['url'], $attachment['name']);
- * @endcode
+ * ```
  *
  * Notes:
  *  - File content is not returned by default. One must specify 'return => content'.
diff --git a/civicrm/api/v3/Case.php b/civicrm/api/v3/Case.php
index 1f5b9b6ae4..5249010c45 100644
--- a/civicrm/api/v3/Case.php
+++ b/civicrm/api/v3/Case.php
@@ -21,7 +21,7 @@
  *
  * @param array $params
  *
- * @code
+ * ```
  * // REQUIRED for create:
  * 'case_type_id' => int OR
  * 'case_type' => str (provide one or the other)
@@ -38,7 +38,7 @@
  * 'start_date' => str datestamp // defaults to: date('YmdHis')
  * 'duration' => int // in minutes
  * 'details' => str // html format
- * @endcode
+ * ```
  *
  * @throws API_Exception
  * @return array
@@ -556,13 +556,13 @@ function civicrm_api3_case_update($params) {
  *
  * @param array $params
  *
- * @code
+ * ```
  *   //REQUIRED:
  *   'id' => int
  *
  *   //OPTIONAL
  *   'move_to_trash' => bool (defaults to false)
- * @endcode
+ * ```
  *
  * @throws API_Exception
  * @return mixed
diff --git a/civicrm/api/v3/Contribution.php b/civicrm/api/v3/Contribution.php
index 66f6cc0c93..bbe0169181 100644
--- a/civicrm/api/v3/Contribution.php
+++ b/civicrm/api/v3/Contribution.php
@@ -594,6 +594,14 @@ function civicrm_api3_contribution_repeattransaction($params) {
     throw new API_Exception(
       'A valid original contribution ID is required', 'invalid_data');
   }
+  // We don't support repeattransaction without a related recurring contribution.
+  if (empty($contribution->contribution_recur_id)) {
+    throw new API_Exception(
+      'Repeattransaction API can only be used in the context of contributions that have a contribution_recur_id.',
+      'invalid_data'
+    );
+  }
+
   $original_contribution = clone $contribution;
   $input['payment_processor_id'] = civicrm_api3('contributionRecur', 'getvalue', [
     'return' => 'payment_processor_id',
@@ -709,6 +717,7 @@ function _civicrm_api3_contribution_repeattransaction_spec(&$params) {
       'optionGroupName' => 'contribution_status',
     ],
     'api.required' => TRUE,
+    'api.default' => 'Pending',
   ];
   $params['receive_date'] = [
     'title' => 'Contribution Receive Date',
diff --git a/civicrm/api/v3/CustomField.php b/civicrm/api/v3/CustomField.php
index 020ebe2bbf..1667721744 100644
--- a/civicrm/api/v3/CustomField.php
+++ b/civicrm/api/v3/CustomField.php
@@ -30,6 +30,12 @@
  */
 function civicrm_api3_custom_field_create($params) {
 
+  // Legacy handling for old way of naming serialized fields
+  if (!empty($params['html_type']) && ($params['html_type'] == 'CheckBox' || strpos($params['html_type'], 'Multi-') === 0)) {
+    $params['serialize'] = 1;
+    $params['html_type'] = str_replace('Multi-', '', $params['html_type']);
+  }
+
   // Array created for passing options in params.
   if (isset($params['option_values']) && is_array($params['option_values'])) {
     $weight = 0;
@@ -116,7 +122,26 @@ function civicrm_api3_custom_field_delete($params) {
  * @return array
  */
 function civicrm_api3_custom_field_get($params) {
-  return _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+  if (CRM_Core_BAO_Domain::isDBVersionAtLeast('5.27.alpha1') && ($params['legacy_html_type'] ?? TRUE) && !empty($params['return'])) {
+    if (is_array($params['return'])) {
+      $params['return'][] = 'serialize';
+    }
+    elseif (is_string($params['return'])) {
+      $params['return'] .= ',serialize';
+    }
+  }
+
+  $results = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+
+  if (($params['legacy_html_type'] ?? TRUE) && !empty($results['values']) && is_array($results['values'])) {
+    foreach ($results['values'] as $id => $result) {
+      if (!empty($result['serialize']) && !empty($result['html_type'])) {
+        $results['values'][$id]['html_type'] = str_replace('Select', 'Multi-Select', $result['html_type']);
+      }
+    }
+  }
+
+  return $results;
 }
 
 /**
diff --git a/civicrm/api/v3/CustomValue.php b/civicrm/api/v3/CustomValue.php
index 0711224f00..34f96a9f2d 100644
--- a/civicrm/api/v3/CustomValue.php
+++ b/civicrm/api/v3/CustomValue.php
@@ -22,7 +22,7 @@
  *   Expected keys are in format custom_fieldID:recordID or custom_groupName:fieldName:recordID.
  *
  * @example:
- * @code
+ * ```
  *   // entity ID. You do not need to specify entity type, we figure it out based on the fields you're using
  *   'entity_id' => 123,
  *   // (omitting :id) inserts or updates a field in a single-valued group
@@ -39,7 +39,7 @@
  *   'custom_some_group:my_field' => 'myinfo',
  *   // updates record ID 8 in my_other_field in multi-valued some_big_group
  *   'custom_some_big_group:my_other_field:8' => 'myinfo',
- * @endcode
+ * ```
  *
  * @throws Exception
  * @return array
diff --git a/civicrm/api/v3/Generic.php b/civicrm/api/v3/Generic.php
index d8f2e92db4..0eef89a7a2 100644
--- a/civicrm/api/v3/Generic.php
+++ b/civicrm/api/v3/Generic.php
@@ -406,6 +406,7 @@ function civicrm_api3_generic_replace($apiRequest) {
  *
  * @return array
  *   Array of results
+ * @throws \CiviCRM_API3_Exception
  */
 function civicrm_api3_generic_getoptions($apiRequest) {
   // Resolve aliases.
diff --git a/civicrm/api/v3/Generic/Getlist.php b/civicrm/api/v3/Generic/Getlist.php
index 2fecc84c4f..f63948e27c 100644
--- a/civicrm/api/v3/Generic/Getlist.php
+++ b/civicrm/api/v3/Generic/Getlist.php
@@ -22,7 +22,7 @@
  * @throws \CiviCRM_API3_Exception
  */
 function civicrm_api3_generic_getList($apiRequest) {
-  $entity = _civicrm_api_get_entity_name_from_camel($apiRequest['entity']);
+  $entity = CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($apiRequest['entity']);
   $request = $apiRequest['params'];
   $meta = civicrm_api3_generic_getfields(['action' => 'get'] + $apiRequest, FALSE);
 
diff --git a/civicrm/api/v3/GroupContact.php b/civicrm/api/v3/GroupContact.php
index 250438378f..ef1121ccb9 100644
--- a/civicrm/api/v3/GroupContact.php
+++ b/civicrm/api/v3/GroupContact.php
@@ -72,7 +72,7 @@ function _civicrm_api3_group_contact_create_spec(&$params) {
  *
  * This api has a legacy/nonstandard signature.
  * On success, the return array will be structured as follows:
- * @code
+ * ```
  * array(
  *   "is_error" => 0,
  *   "version"  => 3,
@@ -83,16 +83,16 @@ function _civicrm_api3_group_contact_create_spec(&$params) {
  *     "total_count" => integer
  *   )
  * )
- * @endcode
+ * ```
  *
  * On failure, the return array will be structured as follows:
- * @code
+ * ```
  * array(
  *   'is_error' => 1,
  *   'error_message' = string,
  *   'error_data' = mixed or undefined
  * )
- * @endcode
+ * ```
  *
  * @param array $params
  *   Input parameters:
diff --git a/civicrm/api/v3/Mailing.php b/civicrm/api/v3/Mailing.php
index 185b3cd374..011a19f149 100644
--- a/civicrm/api/v3/Mailing.php
+++ b/civicrm/api/v3/Mailing.php
@@ -134,8 +134,8 @@ function _civicrm_api3_mailing_create_spec(&$params) {
 
   $params['forward_replies']['api.default'] = FALSE;
   $params['auto_responder']['api.default'] = FALSE;
-  $params['open_tracking']['api.default'] = TRUE;
-  $params['url_tracking']['api.default'] = TRUE;
+  $params['open_tracking']['api.default'] = Civi::settings()->get('open_tracking_default');
+  $params['url_tracking']['api.default'] = Civi::settings()->get('url_tracking_default');
 
   $params['header_id']['api.default'] = CRM_Mailing_PseudoConstant::defaultComponent('Header', '');
   $params['footer_id']['api.default'] = CRM_Mailing_PseudoConstant::defaultComponent('Footer', '');
diff --git a/civicrm/api/v3/MailingAB.php b/civicrm/api/v3/MailingAB.php
index a8c96ab80a..8ae6d7f89b 100644
--- a/civicrm/api/v3/MailingAB.php
+++ b/civicrm/api/v3/MailingAB.php
@@ -23,6 +23,7 @@ function _civicrm_api3_mailing_a_b_create_spec(&$spec) {
   $spec['created_date']['api.default'] = 'now';
   $spec['created_id']['api.required'] = 1;
   $spec['created_id']['api.default'] = 'user_contact_id';
+  $spec['domain_id']['api.default'] = CRM_Core_Config::domainID();
 }
 
 /**
diff --git a/civicrm/api/v3/Payment.php b/civicrm/api/v3/Payment.php
index b601cd684f..bf10d26f15 100644
--- a/civicrm/api/v3/Payment.php
+++ b/civicrm/api/v3/Payment.php
@@ -273,6 +273,22 @@ function _civicrm_api3_payment_create_spec(&$params) {
         'type' => 'Text',
       ],
     ],
+    'order_reference' => [
+      'name' => 'order_reference',
+      'type' => CRM_Utils_Type::T_STRING,
+      'title' => 'Order Reference',
+      'description' => 'Payment Processor external order reference',
+      'maxlength' => 255,
+      'size' => 25,
+      'where' => 'civicrm_financial_trxn.order_reference',
+      'table_name' => 'civicrm_financial_trxn',
+      'entity' => 'FinancialTrxn',
+      'bao' => 'CRM_Financial_DAO_FinancialTrxn',
+      'localizable' => 0,
+      'html' => [
+        'type' => 'Text',
+      ],
+    ],
     'check_number' => [
       'name' => 'check_number',
       'type' => CRM_Utils_Type::T_STRING,
diff --git a/civicrm/api/v3/Setting.php b/civicrm/api/v3/Setting.php
index 2f6e7ee6d8..7e9ea8ffa3 100644
--- a/civicrm/api/v3/Setting.php
+++ b/civicrm/api/v3/Setting.php
@@ -248,6 +248,9 @@ function _civicrm_api3_setting_fill_spec(&$params) {
  *
  * @return array
  *   api result array
+ *
+ * @throws \API_Exception
+ * @throws \CiviCRM_API3_Exception
  */
 function civicrm_api3_setting_create($params) {
   $domains = _civicrm_api3_setting_getDomainArray($params);
@@ -379,24 +382,24 @@ function _civicrm_api3_setting_getvalue_spec(&$params) {
  * @param array $params
  *
  * @return array
- * @throws \Exception
+ * @throws API_Exception
  */
 function _civicrm_api3_setting_getDomainArray(&$params) {
   if (empty($params['domain_id']) && isset($params['id'])) {
     $params['domain_id'] = $params['id'];
   }
 
-  if ($params['domain_id'] == 'current_domain') {
+  if ($params['domain_id'] === 'current_domain') {
     $params['domain_id'] = CRM_Core_Config::domainID();
   }
 
-  if ($params['domain_id'] == 'all') {
+  if ($params['domain_id'] === 'all') {
     $domainAPIResult = civicrm_api('domain', 'get', ['version' => 3, 'return' => 'id']);
     if (isset($domainAPIResult['values'])) {
       $params['domain_id'] = array_keys($domainAPIResult['values']);
     }
     else {
-      throw new Exception('All domains not retrieved - problem with Domain Get api call ' . $domainAPIResult['error_message']);
+      throw new API_Exception('All domains not retrieved - problem with Domain Get api call ' . $domainAPIResult['error_message']);
     }
   }
   if (is_array($params['domain_id'])) {
diff --git a/civicrm/api/v3/examples/Setting/GetFields.ex.php b/civicrm/api/v3/examples/Setting/GetFields.ex.php
index 2f479ace75..936e6f6f77 100644
--- a/civicrm/api/v3/examples/Setting/GetFields.ex.php
+++ b/civicrm/api/v3/examples/Setting/GetFields.ex.php
@@ -2775,7 +2775,7 @@ function setting_getfields_expectedresult() {
         'html_type' => 'text',
         'default' => 'simple',
         'add' => '4.5',
-        'title' => 'How to handle full-tet queries',
+        'title' => 'How to handle full-text queries',
         'is_domain' => 1,
         'is_contact' => 0,
         'description' => '',
diff --git a/civicrm/api/v3/utils.php b/civicrm/api/v3/utils.php
index a8e8e65d02..ae9eaa0a18 100644
--- a/civicrm/api/v3/utils.php
+++ b/civicrm/api/v3/utils.php
@@ -1237,7 +1237,7 @@ function formatCheckBoxField(&$checkboxFieldValue, $customFieldLabel, $entity) {
  * @return array
  */
 function _civicrm_api3_basic_get($bao_name, $params, $returnAsSuccess = TRUE, $entity = "", $sql = NULL, $uniqueFields = FALSE) {
-  $entity = $entity ?: CRM_Core_DAO_AllCoreTables::getBriefName(str_replace('_BAO_', '_DAO_', $bao_name));
+  $entity = $entity ?: CRM_Core_DAO_AllCoreTables::getBriefName($bao_name);
   $options = _civicrm_api3_get_options_from_params($params);
 
   $query = new \Civi\API\Api3SelectQuery($entity, CRM_Utils_Array::value('check_permissions', $params, FALSE));
@@ -2377,7 +2377,7 @@ function _civicrm_api3_api_resolve_alias($entity, $fieldName, $action = 'create'
   if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
     return $fieldName;
   }
-  if ($fieldName == _civicrm_api_get_entity_name_from_camel($entity) . '_id') {
+  if ($fieldName === (CRM_Core_DAO_AllCoreTables::convertEntityNameToLower($entity) . '_id')) {
     return 'id';
   }
   $result = civicrm_api($entity, 'getfields', [
diff --git a/civicrm/civicrm-version.php b/civicrm/civicrm-version.php
index 58fe534bcf..4e293db9c9 100644
--- a/civicrm/civicrm-version.php
+++ b/civicrm/civicrm-version.php
@@ -1,7 +1,7 @@
 <?php
 /** @deprecated */
 function civicrmVersion( ) {
-  return array( 'version'  => '5.26.2',
+  return array( 'version'  => '5.27.0',
                 'cms'      => 'Wordpress',
                 'revision' => '' );
 }
diff --git a/civicrm/composer.json b/civicrm/composer.json
index 6e414e4c66..f7226e719a 100644
--- a/civicrm/composer.json
+++ b/civicrm/composer.json
@@ -46,14 +46,14 @@
     "cache/integration-tests": "~0.16.0",
     "dompdf/dompdf" : "0.8.*",
     "electrolinux/phpquery": "^0.9.6",
-    "symfony/config": "^2.8.50 || ~3.0",
+    "symfony/config": "~3.0 || ~4.4",
     "symfony/polyfill-iconv": "~1.0",
-    "symfony/dependency-injection": "^2.8.50 || ~3.0",
-    "symfony/event-dispatcher": "^2.8.50 || ~3.0",
-    "symfony/filesystem": "^2.8.50 || ~3.0",
-    "symfony/process": "^2.8.50 || ~3.0",
+    "symfony/dependency-injection": "~3.0 || ~4.4",
+    "symfony/event-dispatcher": "~3.0 || ~4.4",
+    "symfony/filesystem": "~3.0 || ~4.4",
+    "symfony/process": "~3.0 || ~4.4",
     "psr/log": "~1.0",
-    "symfony/finder": "^2.8.50 || ~3.0",
+    "symfony/finder": "~3.0 || ~4.4",
     "tecnickcom/tcpdf" : "6.2.*",
     "totten/ca-config": "~17.05",
     "zetacomponents/base": "1.9.*",
@@ -69,7 +69,7 @@
     "guzzlehttp/guzzle": "^6.3",
     "psr/simple-cache": "~1.0.1",
     "cweagans/composer-patches": "~1.0",
-    "pear/log": "1.13.1",
+    "pear/log": "1.13.2",
     "adrienrn/php-mimetyper": "0.2.2",
     "civicrm/composer-downloads-plugin": "^2.0",
     "league/csv": "^9.2",
diff --git a/civicrm/composer.lock b/civicrm/composer.lock
index 42f872a30d..d2b5f94261 100644
--- a/civicrm/composer.lock
+++ b/civicrm/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "00d8b8be8e838f8ff098162f88af562c",
+    "content-hash": "f547e4d1ac65fa8044d302f46a7e7267",
     "packages": [
         {
             "name": "adrienrn/php-mimetyper",
@@ -890,20 +890,20 @@
         },
         {
             "name": "pear/log",
-            "version": "1.13.1",
+            "version": "1.13.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/pear/Log.git",
-                "reference": "c4be9ded2353c7c231d4c35cc3da75b209453803"
+                "reference": "d8cde3dba893a36ec561bf6188fdc39f4221c4d3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/pear/Log/zipball/c4be9ded2353c7c231d4c35cc3da75b209453803",
-                "reference": "c4be9ded2353c7c231d4c35cc3da75b209453803",
+                "url": "https://api.github.com/repos/pear/Log/zipball/d8cde3dba893a36ec561bf6188fdc39f4221c4d3",
+                "reference": "d8cde3dba893a36ec561bf6188fdc39f4221c4d3",
                 "shasum": ""
             },
             "require": {
-                "pear/pear_exception": "1.0.0",
+                "pear/pear_exception": "1.0.1",
                 "php": ">5.2"
             },
             "require-dev": {
@@ -939,7 +939,7 @@
                 "log",
                 "logging"
             ],
-            "time": "2016-04-16T00:49:33+00:00"
+            "time": "2020-06-02T00:04:03+00:00"
         },
         {
             "name": "pear/mail",
@@ -1168,16 +1168,16 @@
         },
         {
             "name": "pear/pear_exception",
-            "version": "v1.0.0",
+            "version": "v1.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/pear/PEAR_Exception.git",
-                "reference": "8c18719fdae000b690e3912be401c76e406dd13b"
+                "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/8c18719fdae000b690e3912be401c76e406dd13b",
-                "reference": "8c18719fdae000b690e3912be401c76e406dd13b",
+                "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
+                "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
                 "shasum": ""
             },
             "require": {
@@ -1193,9 +1193,9 @@
                 }
             },
             "autoload": {
-                "psr-0": {
-                    "PEAR": ""
-                }
+                "classmap": [
+                    "PEAR/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "include-path": [
@@ -1219,7 +1219,7 @@
             "keywords": [
                 "exception"
             ],
-            "time": "2015-02-10T20:07:52+00:00"
+            "time": "2019-12-10T10:24:42+00:00"
         },
         {
             "name": "pear/validate_finance_creditcard",
@@ -1659,6 +1659,55 @@
             ],
             "time": "2016-08-06T20:24:11+00:00"
         },
+        {
+            "name": "psr/container",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/container.git",
+                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Container\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common Container Interface (PHP FIG PSR-11)",
+            "homepage": "https://github.com/php-fig/container",
+            "keywords": [
+                "PSR-11",
+                "container",
+                "container-interface",
+                "container-interop",
+                "psr"
+            ],
+            "time": "2017-02-14T16:28:37+00:00"
+        },
         {
             "name": "psr/http-message",
             "version": "1.0.1",
@@ -1851,25 +1900,32 @@
         },
         {
             "name": "symfony/config",
-            "version": "v2.8.50",
+            "version": "v3.4.40",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/config.git",
-                "reference": "7dd5f5040dc04c118d057fb5886563963eb70011"
+                "reference": "3634991bea549e73c45a964c38f30ceeae6ed877"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/config/zipball/7dd5f5040dc04c118d057fb5886563963eb70011",
-                "reference": "7dd5f5040dc04c118d057fb5886563963eb70011",
+                "url": "https://api.github.com/repos/symfony/config/zipball/3634991bea549e73c45a964c38f30ceeae6ed877",
+                "reference": "3634991bea549e73c45a964c38f30ceeae6ed877",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.9",
-                "symfony/filesystem": "~2.3|~3.0.0",
+                "php": "^5.5.9|>=7.0.8",
+                "symfony/filesystem": "~2.8|~3.0|~4.0",
                 "symfony/polyfill-ctype": "~1.8"
             },
+            "conflict": {
+                "symfony/dependency-injection": "<3.3",
+                "symfony/finder": "<3.3"
+            },
             "require-dev": {
-                "symfony/yaml": "~2.7|~3.0.0"
+                "symfony/dependency-injection": "~3.3|~4.0",
+                "symfony/event-dispatcher": "~3.3|~4.0",
+                "symfony/finder": "~3.3|~4.0",
+                "symfony/yaml": "~3.0|~4.0"
             },
             "suggest": {
                 "symfony/yaml": "To use the yaml reference dumper"
@@ -1877,7 +1933,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.8-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -1904,43 +1960,51 @@
             ],
             "description": "Symfony Config Component",
             "homepage": "https://symfony.com",
-            "time": "2018-11-26T09:38:12+00:00"
+            "time": "2020-04-12T14:33:46+00:00"
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v2.8.50",
+            "version": "v3.4.40",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8"
+                "reference": "d10ff5503b0b27711087eef4ac7835a752fe42fd"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c306198fee8f872a8f5f031e6e4f6f83086992d8",
-                "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d10ff5503b0b27711087eef4ac7835a752fe42fd",
+                "reference": "d10ff5503b0b27711087eef4ac7835a752fe42fd",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.9"
+                "php": "^5.5.9|>=7.0.8",
+                "psr/container": "^1.0"
             },
             "conflict": {
-                "symfony/expression-language": "<2.6"
+                "symfony/config": "<3.3.7",
+                "symfony/finder": "<3.3",
+                "symfony/proxy-manager-bridge": "<3.4",
+                "symfony/yaml": "<3.4"
+            },
+            "provide": {
+                "psr/container-implementation": "1.0"
             },
             "require-dev": {
-                "symfony/config": "~2.2|~3.0.0",
-                "symfony/expression-language": "~2.6|~3.0.0",
-                "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7"
+                "symfony/config": "~3.3|~4.0",
+                "symfony/expression-language": "~2.8|~3.0|~4.0",
+                "symfony/yaml": "~3.4|~4.0"
             },
             "suggest": {
                 "symfony/config": "",
                 "symfony/expression-language": "For using expressions in service container configuration",
+                "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required",
                 "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
                 "symfony/yaml": ""
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.8-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -1967,31 +2031,34 @@
             ],
             "description": "Symfony DependencyInjection Component",
             "homepage": "https://symfony.com",
-            "time": "2019-04-16T11:33:46+00:00"
+            "time": "2020-04-13T09:33:40+00:00"
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.8.50",
+            "version": "v3.4.40",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0"
+                "reference": "9d4e22943b73acc1ba50595b7de1a01fe9dbad48"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0",
-                "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9d4e22943b73acc1ba50595b7de1a01fe9dbad48",
+                "reference": "9d4e22943b73acc1ba50595b7de1a01fe9dbad48",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.9"
+                "php": "^5.5.9|>=7.0.8"
+            },
+            "conflict": {
+                "symfony/dependency-injection": "<3.3"
             },
             "require-dev": {
                 "psr/log": "~1.0",
-                "symfony/config": "^2.0.5|~3.0.0",
-                "symfony/dependency-injection": "~2.6|~3.0.0",
-                "symfony/expression-language": "~2.6|~3.0.0",
-                "symfony/stopwatch": "~2.3|~3.0.0"
+                "symfony/config": "~2.8|~3.0|~4.0",
+                "symfony/dependency-injection": "~3.3|~4.0",
+                "symfony/expression-language": "~2.8|~3.0|~4.0",
+                "symfony/stopwatch": "~2.8|~3.0|~4.0"
             },
             "suggest": {
                 "symfony/dependency-injection": "",
@@ -2000,7 +2067,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.8-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -2027,30 +2094,30 @@
             ],
             "description": "Symfony EventDispatcher Component",
             "homepage": "https://symfony.com",
-            "time": "2018-11-21T14:20:20+00:00"
+            "time": "2020-03-15T09:38:08+00:00"
         },
         {
             "name": "symfony/filesystem",
-            "version": "v2.8.50",
+            "version": "v3.4.40",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
-                "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080"
+                "reference": "78a93e5606a19d0fb490afc3c4a9b7ecd86e1515"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/7ae46872dad09dffb7fe1e93a0937097339d0080",
-                "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/78a93e5606a19d0fb490afc3c4a9b7ecd86e1515",
+                "reference": "78a93e5606a19d0fb490afc3c4a9b7ecd86e1515",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.9",
+                "php": "^5.5.9|>=7.0.8",
                 "symfony/polyfill-ctype": "~1.8"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.8-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -2077,29 +2144,29 @@
             ],
             "description": "Symfony Filesystem Component",
             "homepage": "https://symfony.com",
-            "time": "2018-11-11T11:18:13+00:00"
+            "time": "2020-04-12T16:54:01+00:00"
         },
         {
             "name": "symfony/finder",
-            "version": "v2.8.50",
+            "version": "v3.4.40",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "1444eac52273e345d9b95129bf914639305a9ba4"
+                "reference": "5ec813ccafa8164ef21757e8c725d3a57da59200"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/1444eac52273e345d9b95129bf914639305a9ba4",
-                "reference": "1444eac52273e345d9b95129bf914639305a9ba4",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/5ec813ccafa8164ef21757e8c725d3a57da59200",
+                "reference": "5ec813ccafa8164ef21757e8c725d3a57da59200",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.9"
+                "php": "^5.5.9|>=7.0.8"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.8-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -2126,20 +2193,20 @@
             ],
             "description": "Symfony Finder Component",
             "homepage": "https://symfony.com",
-            "time": "2018-11-11T11:18:13+00:00"
+            "time": "2020-02-14T07:34:21+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
-            "version": "v1.12.0",
+            "version": "v1.17.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-ctype.git",
-                "reference": "550ebaac289296ce228a706d0867afc34687e3f4"
+                "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
-                "reference": "550ebaac289296ce228a706d0867afc34687e3f4",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
+                "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
                 "shasum": ""
             },
             "require": {
@@ -2151,7 +2218,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.12-dev"
+                    "dev-master": "1.17-dev"
                 }
             },
             "autoload": {
@@ -2184,20 +2251,20 @@
                 "polyfill",
                 "portable"
             ],
-            "time": "2019-08-06T08:03:45+00:00"
+            "time": "2020-05-12T16:14:59+00:00"
         },
         {
             "name": "symfony/polyfill-iconv",
-            "version": "v1.12.0",
+            "version": "v1.17.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-iconv.git",
-                "reference": "685968b11e61a347c18bf25db32effa478be610f"
+                "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/685968b11e61a347c18bf25db32effa478be610f",
-                "reference": "685968b11e61a347c18bf25db32effa478be610f",
+                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/c4de7601eefbf25f9d47190abe07f79fe0a27424",
+                "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424",
                 "shasum": ""
             },
             "require": {
@@ -2209,7 +2276,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.12-dev"
+                    "dev-master": "1.17-dev"
                 }
             },
             "autoload": {
@@ -2243,29 +2310,29 @@
                 "portable",
                 "shim"
             ],
-            "time": "2019-08-06T08:03:45+00:00"
+            "time": "2020-05-12T16:47:27+00:00"
         },
         {
             "name": "symfony/process",
-            "version": "v2.8.50",
+            "version": "v3.4.40",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git",
-                "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8"
+                "reference": "f5104c9dcbc2cfad45d01d5150c1da9836967271"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/c3591a09c78639822b0b290d44edb69bf9f05dc8",
-                "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8",
+                "url": "https://api.github.com/repos/symfony/process/zipball/f5104c9dcbc2cfad45d01d5150c1da9836967271",
+                "reference": "f5104c9dcbc2cfad45d01d5150c1da9836967271",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.9"
+                "php": "^5.5.9|>=7.0.8"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.8-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -2292,7 +2359,7 @@
             ],
             "description": "Symfony Process Component",
             "homepage": "https://symfony.com",
-            "time": "2018-11-11T11:18:13+00:00"
+            "time": "2020-04-12T14:33:46+00:00"
         },
         {
             "name": "tecnickcom/tcpdf",
@@ -2431,9 +2498,7 @@
             "version": "3.0.0+php53",
             "dist": {
                 "type": "zip",
-                "url": "https://github.com/tplaner/When/archive/c1ec099f421bff354cc5c929f83b94031423fc80.zip",
-                "reference": null,
-                "shasum": null
+                "url": "https://github.com/tplaner/When/archive/c1ec099f421bff354cc5c929f83b94031423fc80.zip"
             },
             "require": {
                 "php": ">=5.3.0"
@@ -2771,5 +2836,6 @@
     "platform-dev": [],
     "platform-overrides": {
         "php": "7.1"
-    }
+    },
+    "plugin-api-version": "1.1.0"
 }
diff --git a/civicrm/css/admin.css b/civicrm/css/admin.css
index faa614cd4f..41d332fd41 100644
--- a/civicrm/css/admin.css
+++ b/civicrm/css/admin.css
@@ -43,3 +43,19 @@
   border: 1px solid #000;
   text-align: center;
 }
+
+@media screen and (min-width: 480px) {
+  #crm-container .admin-section-items {
+    column-count: 2;
+    column-gap: 1em;
+  }
+  #crm-container .admin-section-items dl {
+    -webkit-column-break-inside: avoid;
+    page-break-inside: avoid;
+    break-inside: avoid;
+    margin: 0 1em;
+  }
+  #crm-container .admin-section-items dt {
+    font-weight: bold;
+  }
+}
diff --git a/civicrm/css/civicrm.css b/civicrm/css/civicrm.css
index 06aa01c01d..d260ee66ab 100644
--- a/civicrm/css/civicrm.css
+++ b/civicrm/css/civicrm.css
@@ -5,6 +5,20 @@
  * Other civi blocks outside the main container also have the class crm-container (but not the id)
  * All styles should start with .crm-container unless they are specific to the main div only
  */
+
+/* Use this class to hide text that should only be there for screen readers */
+.sr-only {
+   border: 0;
+   clip: rect(1px, 1px, 1px, 1px);
+   clip-path: inset(50%);
+   height: 1px;
+   width: 1px;
+   margin: -1px;
+   overflow: hidden;
+   padding: 0;
+   position: absolute;
+}
+
 .crm-container input {
   box-sizing: content-box;
 }
@@ -1535,18 +1549,12 @@ input.crm-form-entityref {
   cursor: pointer;
   position: relative;
   white-space: nowrap;
-  padding-right: 15px !important;
   display: inline;
 }
 .crm-container .btn-slide:after {
-  content: "";
-  display: block;
-  height: 15px;
-  position: absolute;
-  right: 2px;
-  top: 3px;
-  width: 15px;
-  background: url("../i/TreePlus.gif") no-repeat right 1px;
+  font-family: "FontAwesome";
+  content: "\f0da";
+  padding-left: .5ex;
 }
 
 .crm-container .btn-slide-active .panel {
@@ -1687,6 +1695,10 @@ input.crm-form-entityref {
 .crm-container a.crm-event-feed-link {
   margin: 0 1ex;
   color: #52534D;
+  display: inline-block;
+  font-size: 10px;
+  padding: 2px 2px 0;
+  vertical-align: bottom;
 }
 
 .crm-container a.crm-event-feed-link:hover {
@@ -2218,73 +2230,110 @@ div.crm-master-accordion-header a.helpicon {
 
 /* accordion styles */
 
-.crm-container .crm-accordion-header {
-  background-image: url("../i/TreeMinusWhite.gif");
-  background-repeat: no-repeat;
-  background-position: 2px center;
+.crm-container .crm-accordion-header,
+.crm-container .crm-collapsible .collapsible-title,
+.crm-container span.collapsed,
+.crm-container a.collapsed,
+.crm-container .crm-expand-row {
   cursor: pointer;
+}
+
+.crm-container .crm-accordion-wrapper {
+  margin-bottom: 4px;
+}
+
+/* Specific types of headers */
+
+#crm-container .widget-content .crm-accordion-header {
+  background-color: #EFEFE5;
+  color: #080808;
+}
+
+.crm-container a.crm-expand-row:before,
+.crm-container a.crm-expand-row:link::before,
+.crm-container a.crm-expand-row:visited::before {
+  color: #3E3E3E;
+}
+
+.crm-container .crm-accordion-header {
   color: #F5F6F1;
   font-weight: normal;
-  padding: 4px 8px 4px 20px;
+  padding: 4px 8px;
   background-color: #5D677B;
+  border-radius: 4px 4px 0 0;
 }
 
-.crm-container .crm-accordion-header:hover {
-  background-color: #32414f;
+.crm-container .collapsed .crm-accordion-header {
+  border-radius: 4px;
 }
 
-.crm-container .collapsed .crm-accordion-header {
-  background-image: url("../i/TreePlusWhite.gif");
+.crm-container .crm-accordion-header.active {
+  font-weight: bold;
+  background-color: #3E3E3E;
 }
 
-.crm-container .collapsed .crm-accordion-body,
-.crm-container .crm-collapsible.collapsed .collapsible-title + * {
-  display: none;
+.crm-container .crm-accordion-header:hover {
+  background-color: #2F2F2E;
 }
 
-.crm-container .crm-expand-row {
-  min-width: 16px;
-  min-height: 16px;
-  display: inline-block;
+#crm-container .widget-content .crm-accordion-header:hover {
+  background-color: #e8e8de;
 }
 
-.crm-container .crm-accordion-inner .crm-accordion-header,
-.crm-container .crm-accordion-wrapper .crm-master-accordion-header,
-.crm-container .crm-collapsible .collapsible-title {
-  background-image: url("../i/TreeMinus.gif");
+.crm-container .crm-accordion-wrapper .crm-master-accordion-header {
   background-color: transparent;
   color: #3E3E3E;
 }
 
-.crm-container .crm-accordion-inner.collapsed .crm-accordion-header,
-.crm-container .crm-accordion-wrapper.collapsed .crm-master-accordion-header,
-.crm-container .crm-collapsible.collapsed .collapsible-title {
-  background-image: url("../i/TreePlus.gif");
-}
-
 .crm-container .crm-accordion-wrapper .crm-master-accordion-header {
-  background-color: transparent;
   font-size: 16px;
-  color: #3e3e3e;
-  margin-bottom: 0;
 }
 
-.crm-container .crm-accordion-inner .crm-accordion-header {
-  font-size: 13px;
+.crm-container .crm-master-accordion-header.crm-accordion-header:hover,
+.crm-container .crm-collapsible .collapsible-title:hover {
+  color: #121A2D;
 }
 
-.crm-container .crm-accordion-wrapper {
-  margin-bottom: 4px;
+.crm-container .collapsed .crm-accordion-body,
+.crm-container .crm-collapsible.collapsed .collapsible-title + * {
+  display: none;
 }
 
-.crm-container .crm-accordion-header {
-  border-radius: 4px 4px 0 0;
+/* Collapse icon */
+
+/* General icon settings for all collapsible things */
+.crm-container .crm-accordion-header:before,
+.crm-container .crm-collapsible .collapsible-title:before,
+.crm-container span.collapsed:before,
+.crm-container a.collapsed:before,
+.crm-container .crm-expand-row:before {
+  font-family: "FontAwesome";
+  display: inline-block;
+  width: 1em;
+  content: "\f0da";
+  font-size: 13px;
 }
 
-.crm-container .collapsed .crm-accordion-header {
-  border-radius: 4px;
+/* Collapsed icon */
+.crm-container .collapsed .crm-accordion-header:before,
+.crm-container .crm-collapsible.collapsed .collapsible-title:before,
+.crm-container span.collapsed:before,
+.crm-container a.collapsed:before,
+.crm-container .crm-expand-row:before {
+  content: "\f0da";
+}
+
+/* Expanded icon */
+.crm-container .crm-accordion-header:before,
+.crm-container .crm-collapsible .collapsible-title:before,
+.crm-container span.expanded:before,
+.crm-container a.expanded:before,
+.crm-container .crm-expand-row.expanded:before {
+  content: "\f0d7";
 }
 
+/* Accordion bodies */
+
 .crm-container .crm-accordion-body {
   border-radius: 0 0 4px 4px;
   border: 1px solid #70716B;
@@ -2292,12 +2341,8 @@ div.crm-master-accordion-header a.helpicon {
   padding: 4px 0;
 }
 
-.crm-container .crm-collapsible .collapsible-title {
-  padding-left: 19px;
-  text-decoration: none;
-  background-repeat: no-repeat;
-  background-position: 0 center;
-  cursor: pointer;
+#crm-container .widget-content .crm-accordion-body {
+  border-color: #e8e8de;
 }
 
 .crm-container .crm-master-accordion-header+.crm-accordion-body {
@@ -2305,19 +2350,10 @@ div.crm-master-accordion-header a.helpicon {
   padding: 0;
 }
 
-.crm-container .crm-accordion-header.active {
-  font-weight: bold;
-  background-color: #41477E;
-}
-
-.crm-container .crm-accordion-header.active:hover {
-  background-color: #2E3471;
-}
-
-.crm-container .crm-master-accordion-header.crm-accordion-header:hover,
-.crm-container .crm-collapsible .collapsible-title:hover {
-  background-color: transparent;
-  color: #0200A0;
+#crm-container .widget-content .crm-accordion-body,
+.crm-container .crm-accordion-body.padded {
+  padding-left: .5em;
+  padding-right: .5em;
 }
 
 .crm-container .crm-child-row > td {
@@ -2456,9 +2492,8 @@ div.crm-master-accordion-header a.helpicon {
 
 /* privacy icons */
 #crm-container div span.privacy-flag {
-  background-repeat: no-repeat;
-  background-image: url("../i/stop-icon.png");
   float: right;
+  font-size: 80%;
 }
 
 /* specific, targeted fixes */
@@ -3025,6 +3060,7 @@ tbody.scrollContent tr.alternateRow {
 }
 .crm-container .select2-container-multi .select2-choices .select2-search-field input {
   padding: 4px;
+  min-height: unset;  /* Overide style imposed by WordPress 5.3 - see https://lab.civicrm.org/dev/wordpress/issues/46 */
 }
 .crm-container .select2-search-choice-close {
   top: 2px;
@@ -3484,21 +3520,6 @@ span.crm-select-item-color {
   padding-left: 20px;
 }
 
-.crm-container span.collapsed,
-.crm-container a.collapsed,
-.crm-container .crm-expand-row {
-  background: url("../i/TreePlus.gif") no-repeat 0 0;
-  padding-left: 19px;
-  cursor: pointer;
-}
-
-.crm-container span.expanded,
-.crm-container a.expanded {
-  background: url("../i/TreeMinus.gif") no-repeat 0 0;
-  padding-left: 19px;
-  cursor: pointer;
-}
-
 /* Notifications */
 #crm-notification-container {
   width: 350px;
diff --git a/civicrm/css/contactSummary.css b/civicrm/css/contactSummary.css
index 813f0c4916..1fc283ef56 100644
--- a/civicrm/css/contactSummary.css
+++ b/civicrm/css/contactSummary.css
@@ -226,12 +226,6 @@ div#crm-contact-thumbnail {
   text-align: right;
 }
 
-#crm-container .geotag {
-  padding: 2px 0 2px 20px !important;
-  background: url('../i/geotag_16.png') left center no-repeat;
-  font-size: .9em;
-}
-
 /* contact actions */
 
 #crm-contact-actions-wrapper {
diff --git a/civicrm/css/dashboard.css b/civicrm/css/dashboard.css
index cf2f34e815..7f783555fd 100644
--- a/civicrm/css/dashboard.css
+++ b/civicrm/css/dashboard.css
@@ -71,25 +71,6 @@
   min-height: 10em;
 }
 
-#crm-container .widget-content .crm-accordion-header {
-  background-color: #EFEFE5;
-  background-image: url("../i/TreeMinus.gif");
-  color: #080808;
-}
-
-#crm-container .widget-content .crm-accordion-wrapper.collapsed .crm-accordion-header {
-  background-image: url("../i/TreePlus.gif");
-}
-
-#crm-container .widget-content .crm-accordion-header:hover {
-  background-color: #e8e8de;
-}
-
-#crm-container .widget-content .crm-accordion-body {
-  border-color: #e8e8de;
-  padding: 4px .5em;
-}
-
 #crm-container .widget-controls {
   background-color: #5D677B;
   /* Standards-browsers do this anyway because all inner block elements are floated.  IE doesn't because it's crap. */
diff --git a/civicrm/i/TreeMinus.gif b/civicrm/i/TreeMinus.gif
deleted file mode 100644
index 964739a1ec8487402e005be65528fc72fb48e27d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 67
zcmZ?wbhEHb6krfwn8*MEii(P0nnCd=3nv2u6N3(j3zBDG5}DG!^7LE&#U%@GIp}W@
NI?vzsD3F1{8USeH4s-wj

diff --git a/civicrm/i/TreeMinusWhite.gif b/civicrm/i/TreeMinusWhite.gif
deleted file mode 100644
index f5ae57ea85aed0b3251c03e23be9e9b635eb112a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 67
zcmZ?wbhEHb6krfwSjfQe|NsAc_wE5nAW;0t!pHywIv@fh&%h+o(!cWbTmHo*3vW5-
PZxK4r-}Wewfx#L8hQAq@

diff --git a/civicrm/i/TreePlus.gif b/civicrm/i/TreePlus.gif
deleted file mode 100644
index a07d4c540ffdfcaa0551d02654905280ed62c9c0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 70
zcmZ?wbhEHb6krfwn8*MEii(P0nnCd=3nv2u6N3(j3zBDG5}(q)^7PyJOg4_^vgFV4
Q#=mR0>@iI(n1R6>0Fz7)Q2+n{

diff --git a/civicrm/i/TreePlusWhite.gif b/civicrm/i/TreePlusWhite.gif
deleted file mode 100644
index 69c21a32f90183ba564885ac0bafc2adde1861e8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 70
zcmZ?wbhEHb6krfwSjfQe|NsAc_wE5nAW;0t!pHywIv@fh&%h+!(!cWb+xbj3j_0!E
S&+*2;Yq;z&O)Z##!5RS4lp1va

diff --git a/civicrm/i/admin/01.png b/civicrm/i/admin/01.png
deleted file mode 100644
index 159903a0cd7326e403fe94d74ff262cfac38b7ac..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3059
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
B$2<T4

diff --git a/civicrm/i/admin/02.png b/civicrm/i/admin/02.png
deleted file mode 100644
index fe203d73d4d8186cc8a73424cd3ec5d6d71937c5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2761
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
P00000NkvXXu0mjfQr{+L

diff --git a/civicrm/i/admin/03.png b/civicrm/i/admin/03.png
deleted file mode 100644
index eea651b8fd5d4289ba52418928f443210c47286d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1945
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

diff --git a/civicrm/i/admin/04.png b/civicrm/i/admin/04.png
deleted file mode 100644
index 6b9e2c295921f05077d11e9f67dca3257d54b4f1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2442
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
IM6N<$f<HNkAOHXW

diff --git a/civicrm/i/admin/05.png b/civicrm/i/admin/05.png
deleted file mode 100644
index be900bbb9138b35d6294c8b4254484d8e7d930ed..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2261
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

diff --git a/civicrm/i/admin/06.png b/civicrm/i/admin/06.png
deleted file mode 100644
index 8b363579e70f0ff96114733b33f5b3c215319ad6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3067
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
JPDHLkV1fWq)f)f+

diff --git a/civicrm/i/admin/07.png b/civicrm/i/admin/07.png
deleted file mode 100644
index 594e42a4159814dd7db36ff8bffcf7bf68046e96..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1369
zcmV-f1*ZCmP)<h;3K|Lk000e1NJLTq001Na001Ni1^@s6;Q*MJ00004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$>q$gGRCwCV
zm}^WNRTRh13@mhEVHXezE$oiGg($nE8j_N3sYx{$T}@+YG@7<1HZdlU7)kogCdQ<x
ziF`9Ae(?37jWtkX@X;EwRGVr`x+{;RF0}(_DNxs8S>CYMGY@uWW_O0|LTGPta%b+|
zx%W5!d(N4AmjbCU&oq}?$|{QC0T)WDEk_6b`VSt0Lc>E=QsXrShKFEzc6Qq!a;qPM
zw5)7xpx$GL;fbp4ai_)Q6&NY4hsO8MXakwEjIeJ{<+dsGY2QEkOZK3mi@F~mUfRif
zK}Fl-zd=}BT8Z2<CD}mH%XmdZBLwWVCOFm64{yJEKqs;Yq!AKPs0gij_*5$}wgO?G
z>e}5fy)p-dh3IG`jBR1aBs3g9<iPtiu?_3G+I+BN;Sgk1w6Lm1b6*+*`=dtPtV1D-
z9H_nXqZitoueX53yh9r7>6n2byrw;|q=ve%qqAV6Y4F`yg+?k)hM}lP?lFXkfG6~F
zRfU25?rY$<P*m=iLNq5<^dVwDZe|HMUjUe$M%a;V0D?dfqa~B>c@SP9-Xhrc{8eDj
ze+le}<ncrXMzkl^g7p420rnCTu#*dro}Pwk;8e6^)VfhZO-VjvkOK)&R$Q{ai%}@K
zG71QNbv*skP-hn7WprvD3LmkkK$J!kwL)~1p2^3zxqcBmSN_mYM-8d`g$phrMF1?B
zhG=g|3AxFaP+T&Q0T~QYOHBo4cQ!DyesKSAE&j3)4LCIKWsIs)R3s%uFwgB-FlU>T
zJ|u@j5d^0e6oNQFl38*xz?sK^yQ^1Y^4Q|>PD0(TOvO0dLKvgh6uVS1f1;%2id6{J
zQG+>4QxNJhM$Lk*WAjl3({uPDDxmqbSO}Fr@epYk_I&7TDx`p_$^iCvuLz|P_TDSw
zV6V=PdDeT2gA!|zBFsr#9}*QxjQ~YLJ)RHaC!ov#p6i2PDJ=%ZYF4P@c8`M7Ua06F
zO@5LR8*IwtnK~gLAuUwp0Xs1bEM{%SD(+v{@fon?7^7pTB5xwFyzz&Xh)x~dF>bJA
za$~GH0Kp(Su$Zex{|tz25kFM+UsyFHv12qC;>)ek#@KQ(-z>s~Z++luD%I_q+!j_3
zNMiy^ZYsDAR_VgKua3dag4`s5Ht?Th+SxlH{II4a0VJe$YD;#0+zc*dw-36$ABL-a
zQ*h|T1Dii}Bn5#0T?oS0yebtHR;VnuLjS;s{<FalFf|RE2V%$Zv+^q|KzK(8G&Q@R
z{<-JT?tiRW$DZVXc!&$#!|?gp8^A4@1&C+gI03H}?b_0V;s8GpQ({RN;>3HckiUfx
z>RtB!o~~m(&b>@r2+zRXbJ%nm?Y8RK{b=tLIvN^HMa5t$DiKe;{y_*${EhWc2i|@W
z=efk3S_N?uo6e)%QtdVP7jRa(UiqxJp~+_5cTjWSl~Ay4toO&Zo1I_%GBxBm%zs4^
zRtT4?2Z6L8){C*A#{SdZ_758KDrzDJJN`_yep=wK>6mK*!`<J&&mW&T84BDxt+NMK
z{2jAVG1j||_?&OG+l;1c&58Be?)rVu(R%z`XofqoX`r&l9cSPC@RODdQ&vI{l<a6M
zn%KtrZ^FArUw#QMyEc;;%N<WOw9NSjU|#kH$>#N1$CI6dH?GlIOGhQ>_@*t6?inqh
b{{<KTmXA(w*%&^Y00000NkvXXu0mjf3paq|

diff --git a/civicrm/i/admin/08.png b/civicrm/i/admin/08.png
deleted file mode 100644
index e56dbd826e38f2b9819c96ec694e2690841f40e5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2812
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
O0000<MNUMnLSTaFkY}I(

diff --git a/civicrm/i/admin/09.png b/civicrm/i/admin/09.png
deleted file mode 100644
index 32db30b9f00de74ff3bec7217db3ef5d6633c83a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2591
zcmV+)3gGpLP)<h;3K|Lk000e1NJLTq001Na001Ni1^@s6;Q*MJ00004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU*u}MThRCwC7
zR|{}d)fxWo?%nJ&$<2d69%eV>AtVGs6)*@PfEcP3qE)cgj`3BTQWbSN)OK2?wXK7W
z6Rfsc8zz8N$EZaoihx!Unwlz)gdh??*bOE~LP$2*_ujqt^gs750W=5|I5Xdz`#6v9
z{*UiJSHMNIbcZOV+r=`gQCKWTRYW5yhC|9b$7AXz^g8ri))c<Wq>N;fRFZ9LOmm2{
zjC7ynDu!rspucwj9iQxmKM;doWovqX-_dI?E@zvRV=GuXGo7t|^cJ?e<$X3<+uz>C
z9<QlkQ!}kBe~fwRWg|0Ttfk;5m3eGe%O-v2ZQB^5jhV~E7@+sn)r{5GYp*}s*}|4D
zDq^KB`(+^|&M!*zy!YCRj13Oz8*>upLRpzMuE)KP)l_9NSBAxUA)6R3*gC1^yUYf`
z`RTSzfFuF!?Lc)kP+JRZ+oogVMxdrfpTOVGor^3f3$y1hK~|FKPnXm@r6~z)!FUH-
zJXvDBJzXR5;yJjNHNNr!`^R%nvds-I>kqlhPFbq9RvSM%*Uq?=FBKo@>Le4ZpdhU(
zNM!G9_$xco*})#TaSFS6N(#GiVlunV<zO?%SlE44^L0|(Wt>oDrFJ_fJDnu~1?P>6
z3t^K2<b^{D1VR7owNL*6;h;~uS5=0XtRfOt(eIb>@dqF2lUy#{ZB0$ut+Q|v_VqO7
z(B&5w9Yg7<Vin&s6i^WG$>{CwhksZeL70{)tjL8NRy2Y=9uH7f_KkH)COaNDpY~k{
zA?Ytq<v*Eor5VgB;AAj{J|dOkw4r#;SUmX5HF$M<HTn(@z)aRl%e5k#TPJQAR90$T
zl4%cayFGj9gFluQU$o06<jDBdiZslvNCWJ4z-9w@7AGXY>r-*Zg7@HVA4J}yM6CY%
ziql!f+hW>3;K9wae8`%ai_Tr4w2LJ)^k!qv>p2;gr3hHGAZltI0!#_m@u?5%|MsQ!
z?4HM*xc~klNCiIw)~%z0;nn4V%Yf%u^am(-8aul_+7Wr{Qq(e`#A(cLc|P@!G{%Oe
z4uuGr0HcxiOh8$QokuqX+oLq}24E@)Gmj&#QOj%KZOFr{UwRAob%P!vcFDA;;c-hX
z+nUN)b0%Z0PR4fRGq$Txhi9dp?!1(ok?yRenl(Iv+RIhW#KSL`Jgm{i*k*~b57QX?
zXbcgX$Cx~HS`c|n<K@L&&kp}tvx<1x3T$ODq_(GM(>Dx^y(KdCPZMMP&5X6R>0~5H
zzaDI3ZM72P<NvQOzR(ydp0luQn3b;VvnWfuQ{Ti_hXznS&JU@Cf;O!JxGrAMSFM7V
z(!TNOtMJ60Rfy(GgN2iJzaCS9tKDy{<*COmCa8r453QP$;hMN^FjC|+rBBtAx@2$}
z9=hcK+@1&~POgKrX$Nrk-MTuv-Prf>FR<a=PI!tNVKxK40WXHw9)yHo*RlU>sX6-c
zv(4usc1}W5Z@VwE{Pv%==8VsG?%IA7MboDsRZ=uUT?fC!g9Xb_R9r&kqgKx<t~>Sh
zQ0`oamiHE*fi<G2BpYUvf?!m{kuUt{IJOglvjBbj+q;f$dac~MrQxfu?`s^5%!1!M
zcW?P!4>xD!<x6c_KSAl787L(8<l2XkZVe$dBN?6pZhWtZh<L969(hEcNctmVBer(L
zkTYWmoOUn9S$s$|MPW^G;H29JpGk!wBU>^|D0_^hXLW~nHMf0h3|0Jk&Ap|!-c#ow
z;p^SM2jSsC_z!Hwi7p?e&z}gD2{0QZY!6N2RpqoIYehzaG1`rz#wyG(2XKYei<E>Q
z8a5w9hu4n&ejkRr!?4V#gvp)++jT#z3o8mjb$?ttDxqmBpSicFx~A@wGi}MqSX@(u
zB$3Kzun#+1S}}j_Wb{Yva817+oB#DL78*0o`k=j^4Z}MAdNRENlR?3&?;pUi@rz)H
zMj;hOsh2TK*IKX;#CbQ@8I%~*`qgXCa#`+8cV=F>WLdM-YJ-^+*laW)IVBYd29=<|
zVHJ^)n~Rq1yI~$zgx;_n#&8lQ<&u?BQuHE9*s$d|{AuM#a;Vte)Q0fHMTn3UB8nRC
zm2ccf(=rz!F#Hn5f&Y|+gv=X%)M~INBF0n=GC$`~HIP*!qN<3nYJy0ML=_R;Aqhu&
z63~Bw$Xt7ZQvD8ELIqRzq4h`^ETRCr&4C^wokk@krmdwyp^P{aY8;HlqT;3oG`&-y
z5lWr?{d`M)iBqOYvbHHPC#!@N14M%eBRvxYrsZkhU<iGmTi`hi9O<NEwd-L_nIb`v
zqd2(#B>sD#9@#W75-}j??m}W|Iem}<eQmvuoe37t{_(}LFl}DGMkw*xh08e!9$+Q|
zk%$>!G{j((1#&YVl0e@t&;s;4y$Eg1Zk!C{Q9+lm_1}re9n*(cG=>kGO$aJ39HRq3
zu-}978)hODiy<7-*XD?7;2xkpPHLo0pSN5iq&SjS@WCQY7U^7SBp3ue?zmkPCPEfX
zWHk|Eil?C>+K!htq`={jFgAAu9I148qc1JJI)WUs+R<ZPR4h3Tb9ONTatuLQS0kn<
zXMvMb*%|tnn6iQgwP?F_*>8=GBytO9A&h7yAFFC0Qgk6x%10@t9AmQ~`Z}@p=b2bo
zoCvXY15B+4F}`9p?z~09X9FEby=nr2L?%E)g0ehvt=((Sbb@RYrIu1&+coH*^Nrmk
z!p3`%dV-Z;;n1?qhy=<!?ow{SigXixVD)SNUL#t>4`gj^Xt8JF`9s5+Rf1<AK*YGk
zc<(1DjE#Dx_6GKTstwSf>4dHoLmZI^yo5oHa0CN!<XCC3x8FWn82Kr2{dy#u1bCwn
zZN87zIt9N*NY<=08W|itqzhv-9BN^*Jd3-Ar>K?@<QlFO;kYK5sMi8si!T8K5wmWQ
zuQw7?E*nFUs2(dkez+RP-4r?(8Qy~axG*}B+SN?wGTCAu(FjdDG(FN0Jtb&#%{Nl$
z-Tca{sM2<wwi5sKS+fQkPlVCjJ3L|y%}p^`Bc`%%IeobIuMy6wYc(tH!ldbSVn()R
zl>~zxJEnN-hys@b-9p^gzn?M=)mJ3zgt)s%srPw9ShD>HPDbPrHI8Z@@GV3<on55T
zPhj2Z^}?u!wgtD9qWJ2S#@xcCoSa5R1D6CtToUxD*QDDq4MVUhJ{)wo@QS-%(-tnU
zvA7bC+WP6_@#Pn<<MW-X@xdD-2RGroCrVB(Z(@}}N`F8|l$-`<k!GP&lldy@iDLxX
zV8T>hKrku?PN28D3qvPgB-d;q5_?Dc1Nol-0|0A$hTJjnj8Omp002ovPDHLkV1j|}
B%!B{{

diff --git a/civicrm/i/admin/10.png b/civicrm/i/admin/10.png
deleted file mode 100644
index 6b2bde2c514e36904857ff166d35b30f99df8d55..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2449
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
P00000NkvXXu0mjfb8oK2

diff --git a/civicrm/i/admin/11.png b/civicrm/i/admin/11.png
deleted file mode 100644
index cb8a01be7325e00b68ed59d2b715dffbf0c778af..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1944
zcmV;J2WR++P)<h;3K|Lk000e1NJLTq001Na001Ni1^@s6;Q*MJ00004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU(DoI2^RCwCN
zSPM{8*BSoq-Cfuxu)7c*tupB}1h5trEbAkoU}B0<qOsFPlSrZwoR9_|Bx<Z<+GLVx
zq$Zut7$1wa8py<`V;rj)ZL}n0(iRl3CP)fFL{J{?F6=J5?Bm}4m)(V3+yxR0{g*TM
z-2Xr4p6~qs_n!ygc^*RX3L766w?L=Ut=DKY>6l~@aIpRgrBXRJIXU@<Q>RQhrdF#H
zADBP?iOB}#4@i1{Qqt7yoSd(YeE4D8Lkkw1vRJJ#i*j?5{x5*UVzD|UHB~c5r|TBp
z_wL*0ARqqA>2l>378Hml9nida^QK>KZEZVx^yn?0uC}hO+GsF1O(s+1qyvi9YLk*v
zQnK^%@|6BO>+b1kYH4XnBrma(3dm};HgtD&*-oB3Y4LBM)o2>y<KyR0RW=!bhPY8z
zUw`Sbyu80t^$jZVR0I$a^_MTZjV4pH&1TC}sZ{69X7g>*yS^_#jBgEM7zX5t#o)PL
zWlil|nl}?FtpeyY0ae$e__EDykB~aerhXWDEa<vz!Hr%UI^7&vsQXPSO#<yEx()>Z
zQYs@3W!=X<ee$JVurAUICJA6NQ<VeMa(Z_H4hLYcQK8^=k*$?L|Fa3M{hvZl0C!NU
zuDbw8yz+$=ndQcgCTv~=#A*~U#jS=@ItAe(GZZ%}5a*}?<0eFmmwo<)bd_HLo8Cvu
z#cS9|niCTOl>I<@&xI|#*4%Lg8_s6pr_(af(PFNzz0z<q^}ZjaEPPOtIEyPotilf7
zJrr->r#z2vpx+Ms?js(hXRw>&v5mB*?*!=m*BA0D(&}KoJ%Hjv>|l%z{-bX`nL6$V
zYb<)X=#1R)u`YjRJ6J~K+5ZOn3Lo);680jI0F1}kS{^SRa$ae?$-h9F%JBjk$}*{x
zKuDypa4eBqi@7<gpQpK23ARU;6f@D$%8H7^7F}+#6mc3cIJcK$@PYD7j1y)_{98Di
zk|Bxv$(C~axw7+)KalA)DvoilL!Vrs5mX6?j#VJcbqg&m^#$vS-%Nb;@uwM9)Gn|3
z{PZt6dwQYNs^FH$;SQq`E&~@P6wkX*cYEs&w+zuy3h38sBp;Nhf199T&(koo#+~*G
zmG-Zn9>`sl9(Nhn+g;dsn6@<Ol&;7qWp!KI&3i9jy^*?oO$?UJkAThQ9_EhV5s$yU
z?}2)T>fv$*tsPEm)ElhFKeuit_1oh~`}mxn&#608ns5*LTVb{W=e{tY@tO^+n8Cxk
zD9lb)z-D)Q2Ol1InBakce0t$0lQ3Xd9(zui@Jd<dX_JL3_O4x_*C9Z(X5Y>y_0K)r
z3A4oxS-5C$hAgqx>EvJ^;KufhAD@PRd2K9pP>{F&^Isc^|J2rfq1OB|8U8W~ATaR>
zQ$P9Q*ph5**w=741<rFr9}ErP&cOrpzV_a}@^A(&B7SLkJ6=C<{XK`1e~ApYf&mg_
z`kH5!{QKP<vC>{+x0m-Lxe+8ZeszD)41$D`{zMeM2)PKAmyFo(*4Ni+ul5xXmUF=X
zK`fE~{?w6m+vm;brc;1BkR#p!gMkXvbAI54xfI|{da4MN#p=Qn8!uYVR&^?a0uqug
zBV$(e$HyN{aXH$+aiY+q4dIz!ToT&y{GENGRAQXI(2mER`-};7G_}^$Tq-&E!O#Bo
zVo?IRJB<OM3;5t@nHH@5P#X^?dD;<pnH=2~<DJKkk)qMwbD*rO@Yw|mWe|=*E@59~
zF!mrpLc{PrePEw(2?w+7UObYgZ)j}%CUsOm0-Z#xY}0Sn|8mEsZL?((nE^J7lLlo%
zr2eqin34SQwf9dB#s!r!5&6%av7I<^K8vtaj|IplnL1tO-d%fEq$Q;>=<Dkv&N9O!
zA9S@JiTx6Q36Xg`9T_z0X#9CsGq!ErQ$)tyq0&B-L~7Kr@4WfW+GieL^<!9E6henD
zt>G7%-~=D?<{%gj5h@v~D>*F9eYL{juss=SVI0q?w_xqMm8DzWTC56FnbA+E216JC
z1R=nA-oq%B>_#mX&3(0@xw%C+yZ252(4fr9NYBvk)ECT5ogs&b_l0oO(~c)xEP02G
zN8$3lwvUdVeUJ<_A@BCzLN3)@tjSuIwN-ya--t*?OYHY&R8Y@?r`1`_#$aFRXCN>o
z{$PUMI=-W<&R_lOx3}$D8X=3c!s_;h@DBgbsw|SDw#tI#50#V;4A`F<^VTr|NlQzc
zQTE6Eh3V60t0;s-2`<q25)q4mo+vDyv$dhQ>6^L1&e{_R*+{9cudmBqmh;Nq^4(t|
zf{FHq&^uY;jSMl^TzJ4vVDd*j_>cI9)!mT%l}{}<UNuzk9sEJQnSYlz@W=SqN;e3D
zJpZjOig!__PfMM)fBo7YWX34_X`hm#XmjOZhht#XSb)9{5BWs6=axi8MZHJQ&7ND^
e*w>){2`~WEX&)M%VsbnH0000<MNUMnLSTX}OTx1N

diff --git a/civicrm/i/admin/12.png b/civicrm/i/admin/12.png
deleted file mode 100644
index cdb432d166072e56d1dc54364e76aa3f416a56ff..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2597
zcmV+=3flFFP)<h;3K|Lk000e1NJLTq001Na001Ni1^@s6;Q*MJ00004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU*w@E}nRCwC7
zSbJ=h<sE*$>$#uP)6;ut0Z}OkRA@mEQJZ;*6AkLF*^Fj!F<G|6Kb%`8OXfCradV5t
zgoMQGW};?^yTxS}bwkljAb@~ERRThxv^}ToxqtU>&-=C%St?e+H+g$b&-b41d*0{w
z{GQ+MJxUmcP!t7o7<wwIT^%=+HK7+~Ehji!^~3Ex@D?uM(C4x!9#IGS7Ns7U*I@Ps
zZh-QngNcHJ{G?;$!|<7j5D#+M$qNBU`7nma%568T%0AuI8IQPLfZ~LM$$|i6V`9XD
zn$VH$P8`~Puy~W_heyvBkb2IGin3tMg2a>Alo1Iv(rKtrH5H1gK<vQ_fk?{0y55GK
zE0<+{Jy*s*HlWtHc3;L&vz4lc%A|{O(S>dK@SFfX(FA0-T=6h`qK1x`eoZo>Zu}%Q
z6wN5g#!A_P$A26v;NOsd0@NxlEP@m?U3GmE_P$g=OjnQyaC-&#<9Rcr&N4X~?TXtv
zIbown%@js0j11K=e5`^Jv790^^OvRZ$d(=~T^Yq7ulsJ$b3sBD%rdWBnYyQQej-^Q
zL&JPnvF@XBK?+}ZpbxE!8sSn$-~Le#8cY|D|F{`n{Ir3--o)k0m&EV<L_&7sy6CmH
zU*7;H2oc7TXt^{8Bay;Szdwk5dr#r9t;;d6AqKoRhO}G5FTbwfwc`=v=g(T#?mvj%
zU2s5Ko*sL+Tqx##_RWqJ$7>E=eQ^leUM)d$J^cOo6<D$)LNKF1sl-`?MLYP_a}zuN
z@ml!U1@s|B3io{@_T>HXSML5yx^J=+L838=NX`T-il|fv>YU{=w^hfJe-3xuvjyvg
z{x1w5MR<#fFz})31~grVYum`hgT>E(PyOc=tKwY<4dUh6fGTrcfY)Jq*z+caZg?0s
z=F8__MrIEgL3(_kriIOgdedcFw_C%}xYKn>vVwU0%rc)uy|7Qmz0a<ED_`E7<|kd#
zG=D5|IIUS3(oAz+|HeDM5${;@Wi0qy$J*#td}ZCAkU!=kF?tMHrHXMsf)g~I-;Qs_
z5&dTL4Bv?*i+d}U%k&RiPLKN%)0g*@@8xH~?9Aw@GJLXPoyCy&V%yS{cYgliCw^i?
z8#{9IE=F66hIbF$i<0>c)^2LScu|2>9znY@hGV;2tiJR<G{5|Nl!k$C-G4{25)@&3
zbvS+<zHcM+9Y&awuVG-z*V%@qt9a-;uO#&MhiTELZvDZRo_K1rJ3NZ9BS+A`FhFlY
zLC3Oo?0sVZtNd{^X4-(vaTc<jI2m1!wHKR+?i|4m-l9eT)tX?(Cn#UO`o2#P(=1VY
zzE6e(Ys?){6GPfcz$pNorJ?pU*FJF5qfc)(qH&nXG8V2`1iw0hqi?*6mgQGrf25BF
zxee{@DXum!bjrYZd;qav0)uZKo4T25z@~u~#>?=TY_)n7s_HWw0ZWcx%tgIgqdpxN
zhQ?aRy){ITPMc?o+HA<J?tAd@ABKj(8s(t5xdSn?j;44P?udpxgQGa%_F~uDf59#7
z2l<T=?0!3oqgF4r9Xy6Z!2-17WtfV|LR-YPe;<G!GARsE`z%DFDy^!@giy(bN5(t?
z6^R<4dwv>MT-hNLcLq?$rn@$q-Io~EN||4dp~7lz@DdXr$#@RCb`-F8Gy-4A;FfD%
z;hie@+kdXce|-b_cHZ2WqFdZ^{(@HAdfRFOau`0UUh`0^RuPLSEYKELcv4d$gd$YY
zs1A>vgQ_WK03|ove0`--0t+@w%^~&7IGD7^1oO~G{?u{o+u@=X?ZL?4Z{X0mx9#u6
zVarC_Kn-CuF`c&>;;|^qNEQx-oo+Ctz_X3qj3+=C(*oD|-j&}FSuTK`b_)r}ZfK5`
z>NRPI!UBZgJaTCHCQ`il`c1vqckoRddT$AKZl5F-E)I_^Md!jdaq$h8;*IBa&j8X?
zc5;eNwsf*YmNha!QA<nVRK<06dz80Kq^akHXKSd$jL^8-&=ku;xTMqKO{%P0C0j!x
zk;c`xNAb?19(M0b^05wyx3S`8hK!&~G8B+vFHKq)I(dp4A|r~2x>I9yDI*$FVNz2y
zidy04o+m89mw-Atlk)luprUOFBamt8a*^d35=@NcBcf^0`M_9rGrE@_$2-H_>{%@O
z6*H;511Ben)SNrBKgSMG$TN(J3x_5tfH~Z-stWfHAo?o-s9v?0X@TrITiX*jT}~w+
z>-Cogy@5@O?NCMCc94)@G(-u=WDl*AYMmf+{Sgd3lVezXr21kwQFc&a)|6al#{F|m
z8T3XMO6`zqSZ*ET;}a5CEUuunEiUyVwB(beRGQ)SLumnLd}zyeH+Z}L^|j)_rn_oO
z`xnMCS^5hbc#D3agj}RRttkjvqNvAMvQ!t<Tm+NF5^9<W%W-BH8XGBN_ntwn@yNC#
zrzJdy;96Q^$d48Y#Fg15Hnyt2MIIi`F0P6?h8-_H6u$n#FPwRcu5(tb+gQ1*e}guE
z@kM%Lv!+F26uc%olVJ5)ij@w`z<FfUCm<Tm>2izi?pCyQq{$2okfp-)Egl5Q)TPD8
zcv!roNiqZaRLChyO89?SCId)^W?;)0I{XJQ{l7jH^_$u+aWc83XzA=hI(rdXyRtCN
zG{vCdy(1nh8cktjLOFb(ot@BiM24Z`1?<^7$VB7m#25OpP^;CEYS1au0Qr0oh8{|z
z>|NP}rY4gDcR!&0kX2tj4c4M<@5jXGejGk9b-kfkRA6R7frb_3DKY~B5?4Np^~<jl
z40Uxiqpd9?i>vS=!BX9>@_$Q~lfZA03<(YCx-Xe}|2b7ZXL}+%!(gk*9kEEUf20BW
z)4LJx1*oZ|vFVzP;gjQd>)=tDWuQjt)Q<>Rg5u?I6NN&NKtfoe+hpj4mM&YCMKYz%
z{cJz$5CB;`&-7MP#iJpcWWPP1S>s9_i4tNn(^Q5_=qZzp$bQLlcnoJ1a9taQsUr+=
zo`9^{tgPC$i(*ljA3cT-v}p<XLP;`~%;;>x*`$ej#`?u%XK`(iAq?el^rHfr?kvwW
zM8*hE>;MVIlg5`w#K;c4jGpGXp)^XNMMV@4c>q?SoRwvB9d%akTKQaX*kVM`*_oR<
zg=$QHmX2b%1l42~)1h^`gdf_nCrYJ7?ehp~s@8pUKoeshdJxX%OE_@g2;ISueYM9f
z(q;)srVT0bk<kJZ*=JbGSaEqPa?KIhA3+H|0-!LQ<F6<o)4q+fWBPn2Ce0CbDeNg5
z=$tW4&#`6St+8Gz>RbVN-kDVY;Gu~>cYpQX^Zo_xe*z2uubmjs+310e00000NkvXX
Hu0mjfmP_x8

diff --git a/civicrm/i/admin/13.png b/civicrm/i/admin/13.png
deleted file mode 100644
index ae10d7dda631f9429d3ed816dba9eb189521476b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2385
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
D+$wPh

diff --git a/civicrm/i/admin/14.png b/civicrm/i/admin/14.png
deleted file mode 100644
index 4078a96e35c9f178214d88d910d1b0c6ca668f06..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2516
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

diff --git a/civicrm/i/admin/36.png b/civicrm/i/admin/36.png
deleted file mode 100644
index 0af91e7ae2af8ea1062cc52bbf4ece95cce6ebaa..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1880
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
S2H8;n0000<MNUMnLSTZ~hl$?+

diff --git a/civicrm/i/admin/DataStore.gif b/civicrm/i/admin/DataStore.gif
deleted file mode 100644
index f277d48a2c7dbbd6082ea6ca7b8edddac8ca8504..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1172
zcmZvbe`p(J7{|YhhE<0()>hU~q@7+I&UQ4^(Jo6Vti(%{?y}Jz)2Z_m93FP)iJ<}6
z*{xkS%LP(7>Pq9pI_Q<L9kV}fGKj59q_Pg(6`|a=l1Ow+OYCenw~@zd|8waB@B8I>
zdEnv0hxaAFueR>3a+KpXR!Uku(rQRnCrNRu%=oG4EM*N!X=KQh5NLuWl_3>o6nYp6
z4>17F4N4o7)M!Meh(IDstqe88^h5VTsfNgaD+L(_X&T8g2?DV!F-#6H0Ub~P5#V6W
zq)AJXJVHW*Sdo}kLbD0K4zGf05e$b?GP0zlNH$1F5IaGPN>EKib%Yi0A_5%TWDsdY
zGLb;U5;2rR&V;E$SD=UxIdE%XQ50qvIu9iP(G6}bEb_zjLa&CxKr989heg1HWNTp&
z{3g6QsueIIO1ZVL2vHMZ9lU~o2sf99Mabn~n$UG93Pcf{HIvmSC6gggf~AQSTY16^
zN^6vqX+)q1OCm$9$P;Fep^+w&ERetw%Mg=?g)|vS(nd&*kRTG<N=);ESjdu*BF!K<
zLBa&F>Z-8+V}bI7<zZoQaWRw0%+1Zs%*;$qPL7R@sj3=_#iG$@cXxL<9ByxK=Xt)R
zr6mvu)YsR$-ENo5<#aj=3k&I9_T<SSNs=r#AZy)9SZQ5WRs8$#I^Zr|uwJbnQ4SR3
zu=Ge7dv?F4qu|MDVZ8nI^PP^0#LfcA*7fMdN?XImt=GQmaa_MJu=z~tVsG)b>6>?+
z_$?l~l?nDY?CHETP;{W_Z0)Y0pZcGAZocezpR23?&j#C||J&i<P`R~By)yjs*Sq_C
zp9e-=!NDEpe0Hh&>A+_PDwP+v%wBElEvX3%dRi+JV+Vu3TouM`*G|8a4v(tKTN}@p
zyyxqgkAHvoVqNHsntcw9PskN-E^UZc?%&yMd%4ZL^TClHyF3wl<%y3nR|fuG_-4cQ
zn!UfC3hruoOmciR7yop9)#<(NcgHUrTK{<c{n3T=T|9fD>67qZH!g|EjQ6$Y|7hI3
z<-_@^n6o2<>r;`V@83T-b$elmPu4omEibF<E}!APti8ARc30?&Lzj=)+k6jgA0KQv
zYTwq!-7G1<Vf(S-J^Nmn4ZYg*@zOstbyYW>Df0h5{6kSsMPXyAqpafyf83@`$(~KK
So1-3g?AE5<9i7Dv!1EukuS2K+

diff --git a/civicrm/i/admin/PayPal_mark_37x23.gif b/civicrm/i/admin/PayPal_mark_37x23.gif
deleted file mode 100644
index d0a918a26e9b242274eee6d31973be32201823fd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 402
zcmZ?wbhEHbRAmrnIKsftFmv;!gBR;(ZVD)#W)RtY{^q0m&)z8bR=)rAb^ZSH2@Ui6
zm+dL&Svi06F#(5y{bz1Er1c1yq%jz${r~@;fe4`ZlLf3w2SkGGWMKWDpwgF;Id6r<
z+ML(>4AvYg(RDAIcfQJAvj0H}n}UPFF{if$E=Dn2u7w@59eCC-B^HF3h@ZXIz%8l5
zH@UrOmy`Vk;X{wZL#*X^52P%pXV?%WAk4s<!^)h=ZO_8c71dnDT+Hjm6U5o<AD+YA
zCCrgt9Kk7MFT8|9o6R+1Wtwn-7PA*$Y7=J_51$tYAB!-rkH8FuVm^*`ZLN%x8&*c7
z76<zC6m$EpWX+g+%EGsGxvzjvrU0++N@1QyzFs+|9PB|X5q5XYI2`%keS81+o0bZP
zjK_urj@s^O91#|Z4bEn4%3dxS84DZQ_?f-#SWH;t)W*l`@Z`kB#jZU{ru>uUNIXmN
QsQ+KJWQM1(D+hx$04NWIk^lez

diff --git a/civicrm/i/admin/Premiums.png b/civicrm/i/admin/Premiums.png
deleted file mode 100644
index 89b2f501a9d9186c30aa24e038f807cc888929cf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2403
zcmV-p37qzcP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU)^+`lQRCwC7
zS7~fi*A@QWI&T(l!`Pm&jdu(fvyEd+Xi}B{E{Vfd5<#mhKU%3jS~XIWDp5!ywT;qL
zmC{s=lD28uKuTJX#fIR7#l-<{7))$zXE0`FuxIgjJl<zt-s^p~2PTdUuBsmC=q~Tx
zd$#YMa~~y1687%hD}hi=O${Zt6h+nSArzmBe_v=!=mc5*XyO?%#n;u=*501`29b?Y
zVqaD$-o`mTCL}EMoqW?JeoH*}t~8$lgg%k`3FF$talF6Kcy`Z{_}pR?pb2Np)qakJ
z-|)zM;{>JI#dv~EjA>&0?nU?7Lj*_28ae*_-Oh<`RuK*o78lf%rAiJRO8-@UzEYc&
z#ph&Z^1AeNPN~(hoZl~sE>~#0y1Lsy04aM@K{&7&L)h8Yf3JlbHzq%M<Ve}$cV?u7
zcG?cT(U^3Yw7*`gaLmU3Yvfsr`C`WI->=&@(~Zt@Y?j5@R>B)^6hBv3DEyENH1Ulb
zM^#o-B>h&tCG&=WWm!a{Q7{aHp|aR*;kwS-;ekp;-)}NiH0S23W(6*UD+Xg@VVpea
zxpn5u*hPmUY<uE~jDt@-l~wreyH3lCFIt};9*!LUngVOquZI*3gJwCf9FNnXHfbBZ
zo-+6K!RPf(FESc6uN^;L`g4tjfks0UJka2I>MpRN=Y&U`j&@JaBzEua`mx0leDn5d
z<Ax0o7zz<lLQI^ojHc;nubhjvOG|Gksc<+@C<sitAkayIKqYP6n)aikM_24z*b`XL
zLsn}*R^o;3Zr^Wi-&IkR@9>>vq9}r*8B_@yse<AFyk4(GVg(CBthr@&qO6R2Rz7S7
z3yUL3qNejiL4gLRPa9v|x9?g~Tie8|)EZ+scuGQ$VjxChh=#*p875h+<n)w6k&~B~
zQ4krMD9#H{7O7S)D^?oxii-7}C0n)zSV6%i+~m6m7U@|9<UR$C>~q>f*!A$0msy=I
zb*q5rn!M;#NhG&G|6tX(awZ%DIr*KJbm}ApuRQn=atjT(aqLs5drc6@A;Xh9P+#vr
zQBfC`FAozHxOuF-BT&W!%Mq|gM8skg*cc7BJ1V+{!adASpLyDP`0x+DlkMuQ*dn@D
zW^LJ+UH#bZqzM(nq+aWQs-+1wRT@?vs>TSbM5N&hWL&ujUn~p#!TaEF0K8%ZDJe5C
zmIX*6Gh?+#PtW;$5{?}koGdO%R%kRlD2Bz`Z}nfP`)ueJOsYENxiaHQzG&A&=)c$u
z<;jn5Lr|l#`eE2J(h+L!Kz>6Vy6lrE+E)dx+(_K#LCN`#k!tCKhg}7;y9lPfG3fO%
z5U>&@NH~dbkyy$rI9zF)3hmq9zPX`c)V;ba^?{sh4fV5UyWSjh1^>-#FEKo63-CI<
zJ{dVxJK%0<!P2@9(Lt=J*u4wh(iO0E-Nc3qXL0>Y6IA!DL)O+!XrXloU+n<h*$O+o
z6w**O)CC^sGg(9;Gr~o3hOEFJ{$OowX&rmT?g*Yg_JO_e=1t#<^9{qlk47aIQ>fQH
zQj(KVT;F8Ert*BG?5x6IQ!7^1eTu6SeypzE464G2mfk^VJKAxsr59dG3ns)tFn3~!
zMupPK?dTuv#kyTl2por4bjJM@alhXy;rSPOUiXZITjd}{B9gVEbNoG7xC|HCtI?T+
z;Q^#;wfN)9Z$qgTkoL+iVam>j^62|`>+n0U^?Py4Pzr)66dMev%*=tlrx~SzAw(ZM
zfKl5mWcWLwPEiq{&4fT^jwo~G%4D#&cdB;I<%q-!A044t6R%W46ZMe<B;f78oWXUc
zA0|UF{Ms}uD=!BV<FT{-BosOwN_Ia6%k^&L^<02;)m8|pI`GXk(31PjFmhU#-9MuM
zO>sE+sjG#g80$i{hIS7P_YEZ(km@o+os)~n?jCr0`>}0|q~g8bM{Z>~{QvqpQpQ{u
zt$rGjSPUr_kHe$Qf~I^sLX9=#Mo4fk&j&~HQY<P9C+L?Lc!py*Rp<OTQD9<?nejj{
zXmyQD_yq+ICCO~D(Gg^QaRRpr*Ft~rAS@?NVfFP!bXPu#+_mfAK3jv7z!(A#96(^8
z7ux;~IE+;&EKngFnz3GHp5@VYc`RtQOr5%GIhGi9FlILoP8o`j-rt4Law7)FLBjW*
zg2!?T%PxEZYvwX!J^Ec(E?+{4wH3C~9pE*oP+zXa__9sNTwVx;GC}}$C;k+1|EbR$
z7m?up`4yn3@Zh-59E^$JBoV1$AHus2L7A=v_3;Pf861Uw*CB-c0q9y!!llhe^125R
zym}f@g&NG7ZTM>FI+BuklE!DOhs46;A;qlT`Qg1EB&6_2DLS(-Y{OW=YUK1>geKbn
z`-wV~jat#OdK<DyE*L#i3r)n25DA6X-iKt58KDh(;2*e&w2&DpjT%ZpAVB5_`epZf
z{1)rv=kq;y5`jpwr1bWWc;6cu8VN@fDx|15IR9}JYpw10DlHE=yB>kHsTs?hU9hd#
z0#2=g;zlFJ^Y4QyEghO0=W+a;=db(spMCvrNBS&wdk}&`K;7rIW^(?(T;VbZWsWOB
z<WmUx{g>+d#n%p~dtP#vK7h(=b(l&jL~Q#W_{PVf|MDCh+B~SsHXzvcIXFQBUFrP@
zm>SW~Xkbw-dAGZvz4=0e<E7LT#paEbhR46`aGzdGnWl^t71N!7NC|rtqs{4$Jib2M
z(TJ6sHz04vP7J>DC*%(G!M*7KFy@BtW(&f3o8Sz^(9+g;snw_a=aj_!*<l;-JMH#+
z3XEGGzmD-&F?brmCO`j^s@|@KiHaTU(jDdKCzY>k+=_u!--e20Nbl8as2SH-%_G)N
zx}EOh-l*adPm7X*rR4v~MLkUB<^lH3V@bj|t8O}Lvj6U(^2+BY2HjY0YJyp1fK#z#
z;`~ST_5Cj2k)beEPf1f=o}r;)DEzN<I|OkGM`KETPUhu3d8$=#Ia)q)Gw+Z3LbcJD
z=-^le^U0K7)K2m+aM*1BwF2zi37%yF9*6sxV=kmliu7qpicGP@y#mMJ|3Uu|U;r#)
Ve33<pyYK)2002ovPDHLkV1l+4nK1wW

diff --git a/civicrm/i/admin/Profile.png b/civicrm/i/admin/Profile.png
deleted file mode 100644
index c2b746b8ba25f092e47b27f6e19f999fec849635..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2860
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
KMNUMnLSTZS---4B

diff --git a/civicrm/i/admin/Synch_user.png b/civicrm/i/admin/Synch_user.png
deleted file mode 100644
index f92a154a6f181bd0d4cd0a936a25a1b35eb95cfc..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2320
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

diff --git a/civicrm/i/admin/accepted_creditcards.png b/civicrm/i/admin/accepted_creditcards.png
deleted file mode 100644
index ec34af9729fcdd83086e1e516d3802840e1318da..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2128
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
GLSTZrv<!{_

diff --git a/civicrm/i/admin/communication.png b/civicrm/i/admin/communication.png
deleted file mode 100644
index 10ea5d60553e3bb46a8e77eaacd3fa79175cab2f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1545
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

diff --git a/civicrm/i/admin/contribution_types.png b/civicrm/i/admin/contribution_types.png
deleted file mode 100644
index dd372944b41458e199d114ae87410fc0edae3c1e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2860
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
KMNUMnLSTZe^=?A|

diff --git a/civicrm/i/admin/custm_data.png b/civicrm/i/admin/custm_data.png
deleted file mode 100644
index 2ff99b29225972048bdb10762d302fada006adf9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2182
zcmV;12zmF3P)<h;3K|Lk000e1NJLTq001Na001Ni1^@s6;Q*MJ00004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU)7)eAyRCwC7
zm}_htR~5(q^Vs*pW5?@wZLhsGj#IakZgCQ~5`--Tk%XiUK_-+y;))MI5UMCDAcPe2
z0aXG7K?s5RC5=#lDn*GDL{WugCjkiw1-lA?L{QstoVp~=dhLD9>&|fQow40Caj+VD
ztm_%i-kJIB|NPH6cPzQC3rUi&nysTTG?;A)9}cQg-ZUJP%l6pYMf1e<iv1FOT*Mk|
z(kg+p$2;Svx--#yII6&PfNI%BY2L#8oQau&F*Z|U&y;|%`vsC$GpV;VI-J=M$_GOV
zqA?X5DiD;Rs1g)KLR^+|8-QUBzV1NnF?FahqU5-U63tdrSwQe(eokjD9ROj1X$4NL
zH;|T8q-Pz+g+mW!mJ6fC!2QE)eh#Qv4k+qkivjs4jdcU62L?lqtJwr%nGSTFp;ER`
zt=KSh2NuCJzArA|7H^gW4zC*!ecOIZz%T+}&<TW_nGd~Y!=!VaJxKy`mab8N?0NxZ
zyB~_?Y*InMR2eBl3YBazYIH1XL45Xe88GH9UG#8YT@LpFwIa~h4kQP^{d|`;_~jHV
z6(|XHECIv!rILm3{^${Mb!|BT9+2>*12OH;p6K9v1yWb~;QWQkNLTZlM+bH{;rZt}
zFgEF;XwdWkzeIu-myqiY;)ma#fJJAX-XF#{KE?2pKi<GAzqcpX9BAx6toXB^SCNVr
zkxeVewZ$p70|X?CG>2^ig)&;|4E*W0DP&_6OkUOTtCxWUh0IuMAfEC;vc`)qm+^F-
zAar^}IK&H)SAZA+872;HCqtLZl>a)8odjqGO7~&v6@mD-<h5u1ri*X>cmY57N)-sw
z<5b0)z^DkB6fDyaYMuWl@Y-3=l<YqG+KRo5fJ8f>_Mmk>T#ti04fH=)72XjWuZDg_
z{N3M!_}*)2?EGX7%&}=$V(+?ac{tu4a8`tQ^*5JKuc*+@-I?6rXS$0|Y;D*6@cLh|
zslAFbS4xObcp3wyn4>!~t}-f&p%6a&u?)WTo&7NE8ccsM$E0d*5{x1Cj>C_wdkM7f
zZa~>rj%_<W@KjeGfh0!XxPiKOh1v!~hRkhN!>Ag(<GWCTDmFz_T$*HF4UrTme8_yL
za9o?zm*LVmNens`8R4$ZLjyaSaxXmBGu+wLs6pWdj-XVN5syjWp>-Wc4BN8l8#|B`
zS%A5I6l4M^mrRU~j>95VY*Hm2SHzf}n#KHlg^tN(?sC|Aw>94#XyD0)+zUrKhCAD$
zn%Bw|F}8p7G5q3}m+@Fvksc^RCQ}DO0RgB46vzZs(H&nQRj5=dc`${!c?uKvl1(5g
zW~NKRNAZM;(t?3RGKgNR0CaGNcDyqk)C9d4%o`N*BVYX@PQQ8%7ONrZ{0$MlNTZ({
z3nZjbkBun_(>Ec)RbQXL?mfNaAzk>0U*j;#^O5f<zJI4mceIXy55))jw?%WJw(x>y
zlkpg(Gu;e!1+KM#{{2s2;J_y^TTUYs4<j54qoL_R3=Dh_o!Ppjka<2*eII#$OTOZZ
zJ`#W5%R_s&g!*9<wMCU!B@jj7clXnqt3;oXr?@#An$rYR#g%abyLL3tHB<&IL$nhS
zGFkP&91n&M$A@s?gJETJ3!rp@<#~aV=ti#WF9msx;VZBJsijg;lmp^s32Gl)A&2H^
zA)P8T!I-p1M1Yj$beuZ%7sSXX6B9FHZ#z6>HWG9^Uo7MLwK?=|ZNim*&626p*xb`_
zJCN#_8Z89{h~VZhJbcXZ6jKRC_Ebx$a~QwwAReMcYh{7dA@%sR1f=+iZ2!pn5v9y(
zZPO5;LTXa@8I1*k>F(KpEqyJ*N8LU3cZei_Y~3irkTvlsrL`oyL`95;LJfNTODHG9
zEYeh3h9&si$~*xPv`z}5K~#JWG(B~TfK*IhD+sX3tN%qzq(7aTDpQszqChsM!)R%Z
z-3c^PU?X(XeN<X~Q=7sU5{KdHkf&Tx257QTMKqE`uv&&x_LD#WiB7bn(xSonKGWVv
zWq@aywPb2n?4`SV=+JRIGd}CQvF8J|XL}!@@Ns1Vi!iDPm*jh^Az<U|xe4StDP(2U
z3$3m%H%FSA&88706&Qs)Ldx*4O-#HcdR$8@Y0J}JC=|M*l`Phw;?Nlk4V`h14fNXk
z_CCt`A89l8<+93c;o?9YQSX9WihNUcd?2<AL_dE%e~HW-z&Js0Qx^&gXl{)QAkWmd
zgqhPVQBsQCR+HY{%Zev2;H8rnTzWNT<SCXL+H2-JQ_`d1fTX1o{wq$^#n`{Gl(u8n
z=vV9VP4fAi@K9@}UU(=HlL_uRWt)l352fh&t)f_#X&KCw;;m&h3pBo_86o9Hya&7Y
z>eBfmUl(t#Vmo*CBI3yq#>b~gp&+%8A}N#*K*hNd8M`1d?ee9!MEY;qT(@+86>Gd{
zS{#FeJH^8n+sB*Z*RZiAhS@@aimK!-L#Typ=}VJRhVYc@t`pGY<l8uL;&rrlq%b@@
zindIH@J?ZF0qM3R{&8`NjGYusmIL)}-6%3{(MM|zl+8Bd=+Q$W1fT!HlVZVk^VTg`
zq!w4lr2c5rv1qiuQoP5xVC$<;N5@7CkBm|c+CYUcAlk<q`G>1DMQfw2k7w}Ir+fT*
zwA^slQ6YNCKm2i0L|<CcdPDbA;@(+QNAk<cYX3j<p5GwoA&VXVww1urlEfQS-+hIo
zRsRR=|0Y*oU(Zi>?b>$e-5)q)-gmx<-0Q96<gYKD{+|E?0M_FGhpcY=_5c6?07*qo
IM6N<$g4CQ2oB#j-

diff --git a/civicrm/i/admin/domain.png b/civicrm/i/admin/domain.png
deleted file mode 100644
index b4a8edf63c76841ea40a1b7dc53cf5c3964b8098..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1268
zcmV<Q1Pl9#P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$hDk(0RCwCd
zS8Zq<MHqf(cK7yjz2>7zS`(8-(?p}D6iS7vU_o02e`ramRuB=DD*8iERIrNv5ZZ=-
z*7`%Rp(zOVM?im6DWWK}kyeEUt&wYNT0^2alHBFK_V#PWcd~cQ-rZg@ISS&0=Voqp
z?wM!auh|fll9MW>8myw(jOAU%U&G<F_^xW&;|=T9ZRY??l7g5<t~;}kdPIGD=N)@r
zdhmAOh9mdOIu+jiaukl98ULgxp#8S)7v35CbcgG@z&T%$gDMIP9Xzx+R;Q8%j9yKE
zYr0Yb6kUOM+7!cUKX5EF7oWTeo&b;#K*2Hdo`A9B0-U-s3CxkR9#tv)nM#+;#iwWC
z*ue3^=_M2p0`bd#cmnqBYKNEiZw5$Pa^71Tf&&N7!!HxbYg6^>TjBow?*U_I6u$C7
z2vuR^vjI;)Ucva&>VRvCTnuO-u#mvtIQ}_c0^>r!$`&BFju+xp1zpD@)Z@^Uvp_wr
z4}~hGnIb5;oB)cF36u%oc}W4`3IT$QDTN%A2>}W|0hkgH5^j*o0?=?Rr4`eHut>VH
zf+d}*q7d<kzEvazD7ZffI2A?T%DRAxMDPTpG5Y8JNdr&GxquipWOMdnNmx2Qk1)pp
z=DN}`;F?~{ku{Of=}1Hi6)ISxsI-Xea`wyStgK<!FXETUMI|BqnP~Hd2hayBC<va|
z)Av;Q+=-!~kz8W--V$3D%P1iPYH8(V*w5pCR-6}e6$0MqBK+_;R46$1eqR@MTM;dp
zoVC`poakIKH+Ok*etcs~V^c?K)Aq2gMv;63*L?r%Tf-NExDQ?8q?!N)C)^+l;O3kE
z`aAh%@7=B29@^d0jxN(|3(F2;#I{|?WHPR8+OF$>9s7M|_WTc1zt*Yx7q9n!HR#_g
z$O39fLBl3gdWo{shR=*WdE|q~_T92+J!XJ+YwBT<J|Ye^XlMu{4@VHav-_s#j-6{d
zKJNeNPJB4%=P6pC<ZdZ9b@>9(?%B5WuFmd<!FHSR#>29WdoiYAPZ0#i3>?SCXC^py
z3c`_FVRzrY4jFE>v^)e`VCLt~O&CjocEc`U(N1vHMy&e;H_zhTBhuFq1s*7IK_M29
z`Ae{H?t}%sufj?e@C#r?m50k>fFLo<e+$&S0JM1{z>Rn~T^vxL4G}?HLBs&^zX2ri
zs<oy;#sYp9C_W2R)=s4kS4TXZTwKNR0uqR1q0f4hVjWQ{Sc15zFHM}HN)erYlnNyU
ztwm5DNMLO!X27x*z|>IvD$DvvEp@31S5+6dewAgtQG)<dg{!InQKBFSUYOV30{E)e
zf$BGS?VB(Ak_-QF`+o?~R8Ut-jQ@L(>n0#$V1{U`2m_r!%8+?Il@xIDEIV@gJ1Y(K
zxIBVTNR>Fn!W7nEX3B;G$BhrKtFO?cz0dDy8vgOr79*c|6pPy{h>s9oBfdc#<r5Rn
z@qzx{(e{?m(?M@YK~=Jr^xD+b6}_*gr+G_T+lHGJrHLjIxkM~B5xaPC`fMg+oh!Uo
eO1;AUE5HEF4;Iv%VRzU70000<MNUMnLSTa9K~%T^

diff --git a/civicrm/i/admin/duplicate_matching.png b/civicrm/i/admin/duplicate_matching.png
deleted file mode 100644
index 6ae758ade5e6e45c11bac1c49746c78d844986f6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3202
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

diff --git a/civicrm/i/admin/event_manage.png b/civicrm/i/admin/event_manage.png
deleted file mode 100644
index e1a7637b16ddd15e2a232e3b91c45905e61e3cee..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2805
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
Hu0mjfPRvy*

diff --git a/civicrm/i/admin/event_type.png b/civicrm/i/admin/event_type.png
deleted file mode 100644
index 2c2fa8837576f839f50f27c36f9213fb93b808ab..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2706
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
M07*qoM6N<$f?5>$iU0rr

diff --git a/civicrm/i/admin/import_export_map.png b/civicrm/i/admin/import_export_map.png
deleted file mode 100644
index e469807bcc198826d44b919ccfac3365526b4c58..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3182
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
UtBDKJ_5c6?07*qoM6N<$g8t?D*Z=?k

diff --git a/civicrm/i/admin/membership_status.png b/civicrm/i/admin/membership_status.png
deleted file mode 100644
index ad278bac3e6477a001bdd178819cd3d845e7d213..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2502
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
Q^8f$<07*qoM6N<$f`^ZslmGw#

diff --git a/civicrm/i/admin/membership_type.png b/civicrm/i/admin/membership_type.png
deleted file mode 100644
index c645a9b99e5d1417d250e02827cbc06f71e307c9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2666
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
Y0Ct<)k}4}ii2wiq07*qoM6N<$f~a2g>Hq)$

diff --git a/civicrm/i/admin/online_contribution_pages.png b/civicrm/i/admin/online_contribution_pages.png
deleted file mode 100644
index c72ea3dce1800ec44e9efd73fea083b7868aeb80..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2779
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

diff --git a/civicrm/i/admin/option.png b/civicrm/i/admin/option.png
deleted file mode 100644
index 7727d88883e6815f4bb9e24d927d43e4979ec0cf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3251
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

diff --git a/civicrm/i/admin/parti_role.png b/civicrm/i/admin/parti_role.png
deleted file mode 100644
index 63ad8f9d8527fc1ecc6ab5cd43425b17f0e70fdf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 897
zcmV-{1AhF8P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#6G=otRCwBA
z{Qv(y12(|O$jCqlY`SpGVCU6a_0K+h3IOq?1o$?%YpXT-8E9R=rXHJJEDU4<pkV@T
zeRKC;dh%QVNjTv2{U;7UIYXca9uQ*=6S)qUd-!w$n&n{d@a=nn`i;Bui8Y6b2%kD&
z6F+h9kv}dyz$h`GiUWX_E4cK|-aqHisRDF4V0>S|rB8s1^8r;H(6jSU!j-2l8LHRs
z?2ntf^8Cfe&jMg_jsC6^WrZ+efB__Cr=~cOSO+lT%LO1ycV4-L5}Zz&$`82N*dFk3
zunR0dc>zUEPe$@XtfgUMoR#qgigN)dl>>txBQEz{zpDVG6tL;hmzCUrZaK&tP=eKz
z5(7oq0ir_y2plAeTK1EgJ3t|1BqzNP#Qys0m;T{f_X9xD7-FKkVM>&LASva*2P+kM
z6oF6Qe=vXy!v{bi1jO}Naz+3)^*9{>Oaq`GV?+y11NG{j^B;i@p%x&iAObncLRszt
zITo=nF@2y)NvJC=u@RRXKPLyn#7Mu!7kxF3t%2@^pm+!643L}{AI|}jqJSJw=3!qL
zVWvMJ0>TAZI02LkHeb9R@ZsC{4<wfZpg0E=Y-okk{9|_?Vq`-rW%&ms?slL`=mVat
zO}qn6KU<t|>E*ilKmUFqDHLS*j6eFTcM1^e0Gw&y<=5-=q*@LFPd=UHr%EpP`|p<m
z104X~M99v}!|>&cF~h@`5KldL1qoRRfiDakY=0QofmlNDD}#dA2ZlG_?lO=QVt5?@
zGVtULX<+I06e{u&R|U-AsT0LuW4Mg^1(CYU8=?#n<a+^jFsY$H&;c4UZ;3KUU+E=n
zisH9F&oX%Fi{n)TlK=YeB<<<~LcX)teMsBNh==DagRz1zR=FrEezJW}v;#m1%g+om
z6ja4|7!1`<QdABQT^s&oIm!@ZB8*b=rMll?`26!FeH;J+mbyp5z6M#I?e&7;%b%OH
zEeX*9$hT=;XBfW!5MlVkc$M}=F)l|iFur7<7GPo+V1P3O_&H=gpf^T{2YZNC2@qfa
XI;uT;a|QH&00000NkvXXu0mjfdrN{}

diff --git a/civicrm/i/admin/parti_status.png b/civicrm/i/admin/parti_status.png
deleted file mode 100644
index 07e4f5da61ccafacff9454fe0fb6bf2683f2027b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 857
zcmV-f1E&0mP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!>q$gGRCwBA
z{Qv(y0|h{!boI9WyRY9SfH=b3TnGFNv<iLoH7^ir03!ts5b&G4aQ~_Mj}4Fo<%I=5
zoUG0^1Tr5GV+a$uwr{?8JpkQu5P10ZJt$P_i8Y6y1CHH&=zvZ9=8M+~xb%GZ_FaK$
z4w$m<*nFUm=7WM9SzM5d^8+qD?5r#wsN#T2Po4+tyM9+;@$qvBUK8e@2L^irOfK2h
zbb+3XB!)%&oE!{M<^~gqbpQ)K$;HRd`@`7h9z9h^UAT6>otk1l(2@&09P9$1_(oO_
za*&(0YN3^~`~j*s;OU2t81aAT)_strSkr}?gvfysce@4Xxn=I*(+QeVVi&ME46g%z
z{QjdrO3qkw=5oNhuix$)$w@B+@xT81rGNO={eUY^UowQ4=x!j{0m`DnACME@r|&-)
zK!)K1pfm%-7}@aIhfe_{M?rU}mmqp@y7kSy4@{f_3{(Q77DONPWhFO|V-X7z(+8@Q
zguq;I5SJV%3r>vmYkbjH<JcPLUI>bJpn9;yVthOYNR9$*Kwek?XCaenXVw^Qs@DK5
zCqNcXfEL>cz|!#pxs{Ou6obLkeaHLv-nfHN2LMz4hZ-NJKxifOfLIUVb->;ChYXHC
znX~`XPvR3DAG_p-7~MtGsSO{0I+st1<>0IeRDb%};smOcgg^g$#wdtBeC1&H2*i*|
z=MRH~;1>*i@4i2<r-}p6Enc)oA55bZ4BS5$!tAbMbqH0<0S=&VIoSR%*y}!I2nSl|
zZhRNa2RUffA#Jh?BBDb8WLcW$Sq$H=1X>Pq#EbVlWQ79RO)_w0^$X#CnnwXT0Qq?5
zIb|>#6fN|s3*eS7+N%!^0ez(xKnFaauLCxnP={OYZ*h~ZwIRd9R|4P=00DQSyL7LP
z5fy~^2XM}y6p&mSiVJ*Uh<CXNE(NIpNOl0o*YaW?7^nr97zP*&xC8J;0WZ7w2Weh?
jk`3iy6D7KP4iI1fDAgV9HTtH)00000NkvXXu0mjfJ4Sh0

diff --git a/civicrm/i/admin/payment_instruments.png b/civicrm/i/admin/payment_instruments.png
deleted file mode 100644
index 457e8b007c4cfcf179d3c1f781300e1d2a6ec8b1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2850
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
A2LJ#7

diff --git a/civicrm/i/admin/price_sets.png b/civicrm/i/admin/price_sets.png
deleted file mode 100644
index fc7a3feadcf1a7969815e4e43751234e1a677bac..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2095
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
R-b;Ll3*61=jpMC^e*@~=`P~2j

diff --git a/civicrm/i/admin/rela_type.png b/civicrm/i/admin/rela_type.png
deleted file mode 100644
index 494054e4e650dfd11539337d931be533c14e2194..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3101
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

diff --git a/civicrm/i/admin/small/01.png b/civicrm/i/admin/small/01.png
deleted file mode 100644
index 04717e2c5d9dfa5e2822b46db0927fc305ea304f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1746
zcmV;@1}*uCP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00uNkL_t(Y
z$CZ^^j8u0W$3Opb&Rou%nc1Da@31%6g@v-+<yMe2wpyzYvGu`fMU=M2(w2l!8Z@Xc
zCcf}cHSzM&2Ys+a&_s*Gtf|-vaw)KsP$;`l7M8uRm)V`2IdkTmGw139Y1|Mo_<j36
zee(N%|G(c?aG&~DrkI#_Qr%f~cOoji=9zxe?6e)^3eIUKCLJ_1<!|wdAI$0=4<mW8
zNyH>>%~V8RYvTLMvWXwp*Tt%QH>6VbMBoPPy*=s2YLfD`zE17-mD}b+0i?yIDJIjA
zR5nFJzUzBI#56rzC&2SUd?AoRu_ErV=g_-z>7*ha3ZN`Dtv-x9!Ro@C(}oX{0M`ka
z(>*pko<;&L9ycD<U<F<{_<sR*Z?7g@uV}5;D%<W(dIS+cTW1xPCy^V<^PRm}GNOd)
zmfNR&_3@)8jKTi3an4+_9}bXCz}Tpxe13BzvGIvo-_fe%Ta!`#ax}*ef7HxpR)aEY
z@Y-{DzZ;aKf1Qsu6lO*H^17H~+5X6c;Tiuk<U6-*PW>@cIdCw4=E+S`S7+K?5j8Eo
z)F0tfoj%IMEaq&{ICst6KX5WW(%qK$b!%OGpDKyx13Oq3R{R@{ad~>d3;#Pnx8di<
zvRoT#D9V8`*Ok_vT9q!Rs+|(#3Ka4t?_Sp4{^=3zY$hfDs<}z+iNz(=wS3hzyj70r
z_ZHmXTrJG%5BR2H%kI5>spYF)e{W>nD|IcjcC`6QSr-&MiQf-*@x9~UY)lo0o~}*0
z*|-)V@I#D}OTOshTV87zqE5p*Rp5P+jIwImHyHZs;mEUZ9^Tp5(!GE9t&81yG$Q^v
z8s*zBlt@J*l#P!#ec@581*c9n^Vn7lz331I;JP6-Eh^=LLnH{lPzCiWj4gaJLGH#C
zj!R3PU%B<^HyV=h*1i@=#9f{DFNE~>B<bsEW^%5?8%H{5aZh1Q+`w_bvqSPZhq~qj
zYd=@RxeE)VG(p=V>Ip3-ZcY^adyCfk+{=CG^&9v3sF_Hjfi;h>=hc^1qsj_r&*uq(
zOPm-K_yxh9ujbfyppn&^tElZrP`fP2GcPUy1nF9M^+h?=+Z{f!^XvcFUnR43`x;A0
z_7qDdaaHB|e1sHD)MZng{_qa-H&1i+;(Cf&k|Xc<{NjMb_E(y4Dk=y;Byf0pO6Sd=
zM7VX`5d#BmCfBv-R2VglQr-*1jA=4umKiJA+?8th^v=ha)iwU{hfzKrjq=E6I~ksd
z^2?vi;$9u6dS;yJsc{mcci6G9M6Gc7?VmyxipcL>TC`}hhJg`N@xl<x^C(svG&4dx
zn<ceo1p|W-+@&4Rx0Il<nadL+9Q(V)7kdlTL_<73V8)O*b}>aBciM_thia=7$hr4I
zcB^Y+m4G#NqAFtsfl~GZQF1+sUVs;ikiR%cZuK*CXYR6pi@{g=WfZl<)Pl$4oXeQ5
zFh!E~WsU6Gu_SnDYa(6~^XA8|+7mB-IT6ZSIyDt)+Mg@8hCZ?p#j@?V#j+{o%a)p#
zQ$lzBaL2L_#lhb5^mV1k&+GWcC=jCC0lq8|*Azq~L05Ao)~I=X?HOlVOO2<$e#p9d
z|IL+H($UJsr`lM)wqB^&^#15udw;M+Uz4e=Cseac<^>-QU&hK^M|S7&!Wc@jp7tdT
zbX7~p`aHs#XJ#^=8#rh0k?#Y9lnO<LKN!3I!quU5*AKh9o^*CqRVC7)6h%lfsdP2X
zOV?q$DwXmmiJGNs*w9Bd86epPSY<@HjE1RIf?%b>17yd2NXcJQVqTU~8A62+5P^dl
zU7#W3qUWlqsaB~%CoGr1GQqLHu@R0(Zv#CK1f;AoU7E8@){7D`5P?tVRtRGTA`&Ix
zxhN484TrFp1EU0H3Cbm?m=J^{BKI}gV$GKgMsmT}YBTWTt}lnagRo7A#0V9Im<NFq
zpxQbja0yKlVHsc<5O^Sg<=t2Mi`A407`PJNXqG)k5pFVYDm97FQiNwADkhR`aC_RK
zMJl0IiU>=;_dNJ4*!bf*!|#tU@G#9SKf8(L-&!a7MNHbPC8dqcDbZc45xY4T(peoK
z5l}EgciLbyXYxVB=giT|oczs6hW`zx`1PKG;~Gi;001I-R9JLVZ)S9NVRB^v0C?JS
oOvz75Rq)JBOiv9;O-!i-056;c)UFJvO#lD@07*qoM6N<$f;x&+7XSbN

diff --git a/civicrm/i/admin/small/02.png b/civicrm/i/admin/small/02.png
deleted file mode 100644
index 56433c8b478243c098e1bf04a1d156b841b2d2e6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1721
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
P00000NkvXXu0mjfHMB*K

diff --git a/civicrm/i/admin/small/03.png b/civicrm/i/admin/small/03.png
deleted file mode 100644
index 59ae2277e2d2ee5fc4afb1d244c546b73a01d9bf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1635
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

diff --git a/civicrm/i/admin/small/04.png b/civicrm/i/admin/small/04.png
deleted file mode 100644
index 15cacc2589c4f542be48b90f2d61fe2d2a776442..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1740
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

diff --git a/civicrm/i/admin/small/05.png b/civicrm/i/admin/small/05.png
deleted file mode 100644
index 2f370c2cda3af202198707a4b927a6b900cf369e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2033
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
P00000NkvXXu0mjfi>Sc7

diff --git a/civicrm/i/admin/small/06.png b/civicrm/i/admin/small/06.png
deleted file mode 100644
index fe213c6f9c0d0bee797a0bf766b68c0e17a20db2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1919
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
FV1l;bmLUKD

diff --git a/civicrm/i/admin/small/07.png b/civicrm/i/admin/small/07.png
deleted file mode 100644
index 1730ce7e629975c1a760023ae7bdae3244fc1034..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1385
zcmV-v1(y1WP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00hfPL_t(Y
z$EB7{Y+Th9$A9PE_vxAO%$V3t94EAD8`L(SfP$!n8j9Kqv4J3=O6{VnO4)bGhAmsv
z6+7CBRm1`WVnGnJ0!xLM20P@#b%KfGI*z|)2G8f4cMpsAJn=Y{kjjzX$JM*<{LlZ~
z|2g*xATPXg;j9=lgQ5uE-}K(A2bjW<sXusO^rEVwPKRgwKPG}PW&n`+6Jh=1kLa)5
z#8~^i!gm-7ryi$z;-@)4Zncju@RRLD;zFE*<^k=yXD)PTEGW8<bgP?iv(={h(9d!J
zV^k4*-(!4iltOU?r%JciCrup+bh-(tbNHSi3=N=I1I{^I8ZcUnb6{w;6TV9OSin0{
z4Ntb;`RkGK2ahrxw}~q;rO^oIQjS%M6k>~zQZ4)Vp5ob*C{S=ca0wSa_?o3#F{NTW
zV4<q`szlD=J$L58m(QJU{$lD>Oz`Y87!nK#xCGy(Sm}dH@N9~ZK-vYDplO%d$`02H
z0aw+4F{o2SK#j#yh@IjcuSoI7$+B0wX(|2uBqMQ*rWTyZqjVqwsY6|wjn%Pzw?(qH
zi!TP_`KYm3iUg1p4~U(^fN05gR5usdzI2hsP9u|*9=HY>hE6Bpo0U3cf!!`dQ3PVa
zSP+{tP-3STtU&{xLLp$RwMy;sC3ZGyxkz-M+e|G^9h)n4s?H(SP;V<<5TJ6;IeCgA
zRScd7VFY1FTpD4@Z_-)1!q%NFoMwfcfn@Y|wp!TT9;4+E66@3G31Jv!DKdL33_ckH
z56^=r1eZl>fk{=?SC-jI4l_1UWUuTx?S$rfi^Js+#4{vasC9&q@dy<I0y?zFE(ZuB
z_B5t|0VYGo=Jo~~NtZ*DMbMP>)dmxz5kZhGXusuXCPFC)(ENW90WtSfbdZ7Ufv7Sb
zL9N+geKo;Yh{O<;qQN{DICi^v_GGwA8o;9WGZ=v6`LBdvnq3;ZJ&sP45hK}L5t?ZS
z%uu(v&vJlp2!O%jW?<zgq&${u++=N{-Rd#FR3``{j5!d!$iSb62v|D|u+KRngSOU7
z`rNp&&FAxL%zk>C%h&5nPENCacWbD_x7uCesiQf-K=FdyV~??dI^~;2n>!m#E?=)R
zzu2Z@r@6Crj5IpV!@n$Gj2w)O2;reqkAo_nh_w2t!?Pw=0kk^_*Z#A~)ujfDE5e<6
zkz*&GWa{*fD3;2c4uVXQs#(z=*q}rNYb~mZ=UKB{uXpf$%hpb-^RKzvyK|TRd*#+@
z{jJXyb~k5!b9SUMHGT5mSC^jm*K5;J<pH{l8oiy(yN3@Qdiw{*j(;&eG1+jcRu8Nr
zfcNFKyWMx+UtIorr8fVM+2xNmwp#BkTv=ZO>XVPooV-zZ;9R9TeYW!GQ{%?>Nv(%X
z`^5dEy0&)vxyzr=#jA6(uilvb@FM?Xua!e%@u{Tm!g{0o1<)C(jPc6cE&lfBKb`sE
z%&-13_1MfKaj}F&2imrKPXX6zvbHd{^vRoVymaxOADll}5BHrRp7`}MEMHlec=~sL
zJpb@hzdaKMAx0erFgb|H4<C|CGVS+S_;mKmH(!74_dysftbDb!uMQ4au~ed18B3+t
z{`>Z|`SYUsokt8~3_F_}rc|zWecvDY_AO9;Ml1$NiOc{103v!+SaefwW^{L9a%BJj
rc-nJJ$xljE@XSq2PYp^<OsNC_FPsI`t_-P700000NkvXXu0mjfQv{r@

diff --git a/civicrm/i/admin/small/08.png b/civicrm/i/admin/small/08.png
deleted file mode 100644
index 4f64c210b5366f923fd115158819d5d6e0cc4a32..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1896
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

diff --git a/civicrm/i/admin/small/09.png b/civicrm/i/admin/small/09.png
deleted file mode 100644
index dce5bd766bd34b7ae9009d10ce4ed39ce1b630d1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1808
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

diff --git a/civicrm/i/admin/small/10.png b/civicrm/i/admin/small/10.png
deleted file mode 100644
index a36d4cfef172fb05202c250269f5af42d3a398fd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1658
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
Ef=N#;J^%m!

diff --git a/civicrm/i/admin/small/11.png b/civicrm/i/admin/small/11.png
deleted file mode 100644
index b99fa780f4733082858778c1084dd0281d13649e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1484
zcmV;-1vC1IP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00k~dL_t(Y
z$EB57Y*bYk$N%S^bMKvv&UBV`ZVS^XZ5e7|I;AL^u|&WnzPLR3pieGMaOVLNAJoJc
z<xM39MV1(r5FP}AL?SR$kbqE1u?VF*t)1z#y)&Jq%y#ebfhi1ONh4o!lJni=`+fiO
zKldJDFc^?dr%_c^wb1Es_>!qqxV)^ai*uejb^0_OHRwX04~#K$ZEfx11$A{@ld5WB
zqUZ_)0wIUfiQeAcM*;{+MFo_K3YVfNT5D_TST>XCCWN?p`}#`KH*Y?&0>NsvVs2%n
zmr`1ys;bu9+?<$-#X_lM(jGi{5}fl#0x*#=<g(d>K#2dH_dbvY`g@g9N4adWSpCaa
zu2BI@0i^(<{|i9YtXT&_sWmyJuCEm@Rj;bfHsm#kogpKc&g2Jk+1!os1jeUsVl1yA
z9Ggb(a1?z2v{@;b`1cw@lPQ}|F|2!OrP#8@ZzE~RgXfYdn9}{tk_JAVgBDLCH!+QT
z=Lkj)ci_ik|6sSrf$<xY4+qdsU#o^_w0`*hGyL`Olu5Wgy<9yXTHKz12Z~88aT`@)
zGYLXj2}G}x$W0#NTA+{?qlDVa!x%_q5Pm4&t2fF}?zFx6WX-t$a(_O5`bzxFh4aB9
zmXg~2lgaqXDo3J3Hp<Wi2|5wMs0fdXiH-AFz1v1xk{M)&CU_5k%zXi`K3{{YA@Rk<
zUfwu4rRTED+s=@<29d-fk<hcv3z^MiF+gK7xF~}&89J3Q$1D^7e91Xq5nBX7m^&27
z_oj2WXThj@UNsK>5iu>QSJnk;@}|(3>d^$Vl8BGJvSJbO2I{RuFBI2V0l;KvOokxJ
z@G3?*P-hG{tZY>@p~pgMzF%U<YkC1Ns#09JIxuK;Rn#qScKREAg2AH*o)rO$y{W-Q
zZWWfmMG2fq(3u3iXs%HSR;!Wt>&%L`!niu8!8tmSzkYUWLu|`05zuHfhUO)W*$Z8f
zVNZ2sOGCZIVY3@xv6-N=qONBYh<8-X<QkPB$OhDSEhhhhlE=+vw)FFDBjL$dZkPf<
zC=^CK9vkDV)X?CsY_T~R&5>JO7kAH#y63Fue&M=CCD<KiA@EpfmEC4|DwE@v>5Li6
zmNoJdZM{8}o{A-ln%p(iK%r9^oEZwsVki_X<ONl?)f5!wsRY?#LV3BxI%keC$YucN
z&UIosb1t&>>DF&*d@f(hYDX0{=Ah?w5O9DO1~^F39K4X<eny8TGF<DLj{n-$A7jN^
z$|NrXfTP(={_W8C(ofdD;8|Yg7Q}omf2+_eK$HT5BShbOpl8o7hyM;z+#7s!G}3pq
zD|#xKpt4hO*V`+t5|_lgOfNQm#%xG3rZZ;j-PLn?=eFR+rBBp{?gsz>xXNtm??=zJ
z#U_LagR#`7c+2e6EJ34U!4tV)e&HJtB|xy?w*y0iJAMdm_;S;R_U||E#sdM-=oA2C
zuXhi040gvaL6fVLO6R;ec3IE~0Ve{uKnp_vqXu-IQB&JDAOE7`;+6e}4j$tG9t<c7
zearT*2S5AxyS9YNWryA7bGgk1!uajOh*64APg>jY?TMX74z_J_E9IGFGKJX!uy4-+
zI34A&;IT8O)Nn3h6fN}?o>IGH5<mn2=@`Mjt$+Qw`=_HDon_8&ICSR+J1YPH#HOME
zknQUk>KN#ryr^ZRd3F<@OH*+gJUlS4earEW-g@`t_9KUacfChu3%F~WaSnI++}dSL
z=Jh3J?(ZH*{CvJ6ybB;2aQ7MhAIC6PR&_^PVE_OCB6?I<bW?9;ba!ELWdHzp+H*|F
mPfAtr%uP&B4N6T+sRRHooCVab45>{30000<MNUMnLSTYiJ++nq

diff --git a/civicrm/i/admin/small/12.png b/civicrm/i/admin/small/12.png
deleted file mode 100644
index 758609e4eb680767a2caa69805ecf1c566991c8c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1544
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

diff --git a/civicrm/i/admin/small/13.png b/civicrm/i/admin/small/13.png
deleted file mode 100644
index 1eed2c87c87e3da0c5ad996b74534a83a1a2776d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1503
zcmV<51t9u~P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00luwL_t(Y
z$F-GNXk29!$A8~lX3sL2Ok$d(+NNpRqP4XqT8-8n1yQsrf)6eTE$V}cf(1oz0TDqE
zUtFGiP@!OP0hP8|Z0TZKC{?>8ZI))zOgfoNX1jCeF5l<FZEMpi;)53smwP#!-#!2T
zIroGA`4WHkQoXR8!OuoI`pWLgHb<tD(Aoj1E@+NJWDk7%JbZT#$nXCv@%=m2@X%Fl
zJ>NXA?(2gqx=MMdR-j%1zXr+%bsWaug$Duc-|FcXK74p@FWbf@FMsapRqx)~x#E7a
zH5HkgnKDzQnjQgR00xkRrZimJ4ddJ3_+7xse*?U6OCOt$PAqt3VBozQ+xpf=iRiIt
zBh_@2;&g_ls&`&b5kOknV4xF5KZapI{Uc!G>K+bE71}oSuYKdDj-JPC&(@DtPhg_c
z*4W8xla4)cng&OnhiE_xBvY`a3r4rY&~3oz#ei1_m+|A+snlz0uYdFAjwMf;=;qeh
z9UQg~kgu0n8eL2>xq#^isL3f}o|@N53#8J}zYxYhfs+j&oeKf3vYR*Eux8V`1-%=a
z^;p=GKEt(9iZV|^Z)91lmoNsgRGQP+gs09Bk@Lqe3e9<l{{lNwP@cU2U~E|3_tp*R
zB~Qeq9(H9F6O)@8`x&<v(j9FlOc<pUF)c#ZHES8N%4lPw7<!<3$%Oqr-yE9Zl?qJ9
zE|SQYwyfd3rBl25mM^(8qM>1x5h_GlUx?#4OgOV3B&x1(TtQ)_fpH5Y!hsLU2Qkdl
z*fEU3DE&gv+EHWn_yqgYO}IiS#XHZee|f{B&%PZuLZ;)CDCAG!DS_kEu*zqs)GCw<
zC&<ra=(diKjrfG(kV-&00f{+EnFy75Gm+*v=Exc5KK+5$Ki|O@#(~d1BBYtZ6gsA6
zl9?W-VprL@?-0c^JGuS3GVL*!1)X)wZlA`I#7Th>0+T={CrRT%MWf|Gz5vpup(D;a
zOWQ~ooJ|sdD?Lh;GRez&8UFoC#IaM1#9?q9xIPr?kX2x3p;`;VszI#|whfL8o)<XZ
zY|z%z%6-QCpAaZCe8<MKN+cxYESQu~EC<CrAEXR&wHP!sLW=>R5QNO&js|;o1~~yh
zi1Rb22@R`K!YdaLI&>_8WD*J$=<EbT2cdx`g4LBO0D3ZjyE5pg?tu_U!;vmhI$B-%
zLSUflf?{zFYzIvTGZe6^4rms*ULb?#2jR;A;QIkgNpM|oJTMHTaq!SCj-LEu&+dI&
zKW<6HF3V1jCPy;mZr!ObMngNdwlf8oEe2kxvl5*P=?C4P+i=$bT?50!yYM^^Km>?i
z9_H}}ns_U!6B&34maT%Hc7vw=@+y!eiU_x3#@exq8KgCdRNy!e*J0N&wixp*ruImZ
z+Tj|Q0$r&<4xxeXfL-PMXSyDA_dm(teJ>$|#?N2ANNxNpOcO#PSU?2c{3!yu!Z75}
zstF7M_%4J^=(z&2S%}A>ArVZAmdcSku^B7>8y(@@n2W)w2OU(ZpzEkh0FSl9b_-ns
zh6(@xeLb+WCzu`t2nBY13-!zv;+{u15@-)#8c?>N?vc|k2J9_CrcN;`xH75HneIh&
z_Xfs_vqlO5ng)g`F--{q92Zr!@n?$EMy4q5A7bZ$6MS$<2Zw9$a5KMdE%CG+<-H!8
zyA2(I2u8B*K*d58$~eUeg;JI2T!HDaNybJd8O;?q>9~w$XBo+tDO>^o*gOZz(;V56
zW7DD>sm|jJ%*;_eog*__V#u-?&gL09I>y-W1d~#d1qy(FajicA_b^`jS6d@>0000Y
zdQ@0+Q*UN;cVTj6004N}b4<xkN>%X8O-xS>N=;0u1OP9b1=Ow#sZ9U?002ovPDHLk
FV1lC=s}}$O

diff --git a/civicrm/i/admin/small/36.png b/civicrm/i/admin/small/36.png
deleted file mode 100644
index 2f1a6d9b3f0b8c68899221d87a722349e3159a5f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1427
zcmV;E1#J3>P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00lEiL_t(Y$CZ^!Y#Y}VhQB);ksOjD
zDNzr~rX)*|Asev+<sm1o(G)I{wm^XdF3_S`1ObAiC>jLa6a~ENCRt_GuF_ST1PJ<C
z1ZavBXwftd1SfG?z?Nhye#O?qq$s|`#|(#a@9BbyP02wM|GPVw`=2xa|DQAJm%n~f
zCPxMk5x#&@3Q*iTWY_6Np^WVmZZcV1#&#SK0TgbnLdSJc_fSL-tWbz>JdS8X>cA9?
zPGWDbuOUMbGWX43v_>h#(x)GjUs}WpS@+a@G?^s#@H{36sENRXli2BFk705t3hGX`
z!_U9SFbX5`^_5ZzqYZ)9Y}Z<3M~0DV2Rob_$NAm~J}H)H8-1HkfWyfYeN90J29)a2
zSRu&Hy9%YCvR&i)^#WoEmu_5UAYaAmw6L|-6zdIMTU({FZ{O{1D3$ny>+w)Hjjwgr
zbh+DmV}x3*$@}jvkV}N|MDfy-N4aoygHJEJ*ntSH)`;UkF4v=};5S=n5w!Fqq$em=
zNU>QebN;{ANJaX1`RU^%ViC0Okxhg+d1QZ2fiIEOH-@IxcfR1ZKwWq(pK~89abkR!
z<Hu(S<Fj3E(DZ!lkVP!ghaDK9rS+~k=q(V4>6*Qx`Ywemg^O@-e}?f?AH_<Ye=e?b
zp;#x3@WgBuI}n3s46#N7ec^nUKq;ivLMQrZ1e!pbJ&6H@V)aU%kk=s@i_i%)7uU+1
zDK|NE@+kgBnZN(%Dt1S@ojn^HM%q0@p)gK3ir+Ci19-Q`wOXCSg9&CQhG|x|DAqlq
zBPn9p6jSjqXFk4+9T<bF4VGm=pLLr=fVMHT0|VwxJbR<sKc3;Eg#zbR*113HaA2sP
zzn;CyQar-NN`s+9q-%1^1cXKQt`Y)c2#KIX_K<^8LL?T&?`Z6hMbwEhGnVGLxd|37
zZ!nsQ@vUzh>=x(*8ebcf>6u)CKwH>>bf5R2xz)gLcti%{L{biaT3Dvunr41F!?A-F
zkIamq=q^n=5W&|POS<z(PmQ)1>hZ3jy4_)Oc^!Y-B~olK;Y3*eT;p{Dik71A@AG7n
z$7nU1jHVr2KVY-g!qy_VMq_C~?P^rvY6ui4%c6W^i}XsKXHGo8{zu{rB_mwP*IE3$
zz+bMfaSOw%@0_Ip{OHg=N_CG9FRgdyz|)4PfF-I&Wx+Q>+kn4Sr@pwx4-QZ8ow*$K
z+BSi1^YBDJGuafMtQNR39Azt;Mz=e>ap@L^1``~eNMUQFn-&e$9+TS|+7?uo);Kkq
z;rsJ5+{za@b8&;4<pz(>j&W#wh@U?($E)w1qdGlI;=mx@c$$%Dl&O`Q*hU0b3@t}`
z)!FevfdMZZ!V^U@YIEjNiQiu<P)SB<EU%NxB#0?ZInan><0BX+jEdM@lVjz2e&6|P
zeCaaU+01&QnvPFTIw%PDg@}6{T-U=H%V1dwBZmG!6IouZ#-brt1l0^#+^96L<CXf{
z;A-*iIr@U%Xfv9-@AbCZKDA!lW@c=FpFKLmW~Ir|sS!e!#o}s-BSQmB#gnI(|M9Os
zCNcwkRU?$*(Xakr{qR?B@$H9Z=700&51)H#e(I%X9-qYt+b9Lv2v=`a`Q7^~)%~M`
zr(ZsG;$6@0tlmGBy=(LSU!4B!-vIUF%~JL4WHiLVu{6`8Db9YDXLYO2$k0H3{_y17
zR<%+1$y1N*-HTt1rRxRyY-{SZKYVcVy^mH*Ch7ciC>ecptKNRy^Mi#~Uihwm>YGR2
hX}G@IAB*g|`#-fOoJKx)Hl+Xn002ovPDHLkV1g>7va<jH

diff --git a/civicrm/i/admin/small/Premiums.png b/civicrm/i/admin/small/Premiums.png
deleted file mode 100644
index eb1c688b0c01d35dc101868de8e84ae8bdf922f9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1947
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

diff --git a/civicrm/i/admin/small/Profile.png b/civicrm/i/admin/small/Profile.png
deleted file mode 100644
index 09c0736e2c64e39b098ad9b5767784719d02d9ae..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1589
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

diff --git a/civicrm/i/admin/small/Synch_user.png b/civicrm/i/admin/small/Synch_user.png
deleted file mode 100644
index 5be37f91a070816aa02c534e4696263638212b9c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1649
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

diff --git a/civicrm/i/admin/small/accepted_creditcards.png b/civicrm/i/admin/small/accepted_creditcards.png
deleted file mode 100644
index b421a4a951cd8071a668d72d6177869114e5a939..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1237
zcmV;`1S<Q9P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00cKlL_t(Y
z$F-GBY*j@VhM#ZF+}rlv(%zO9YFj8jRs{q>5QJbb(G7{wxHl#)Tq%hrCI%Mn*lXgF
zjfx2|Mlq4ZMB_?{NHjoj!H-rYDA<-3?&Y3)&-{EY&S@z@p)Q=w%$zyj`_B9Q4gAkT
zfNj<$JB*PMp#K#>?^qOD)!=>jLH6$5er)H?O?#|0$-jXZlLJJZLy`pqf+~dKBq~G|
zyw`a0#M$F^_wG$k9yst~B|pAXz;xa6)#+}Qb_X6CZxNyp3Nj<$g5V>xoFM|4ht6`O
zvkQ`UkL<EZVq(r8{_*zbFPHh`co)O{9@R**WpN?DdsM*(!3U+3Ku~aAsZ=8C*R~02
zqP;yFifS%DYOZI+pyR2{4f>Y^##f~HAoD6*0M%T90zTv<s?Z8T7GR!0HTP$T`A;F{
zhSf^o`CT`PZ(!`LGZVo_L5evsIZlX>W+hyZoFFo1B=bN%fR9DMROa_{<RL=Tgu&`C
z9ky#ez^cMbv(BX(Q@8-uM`(Lt>e@}(ZI26z^Gav6g7-?Z<#1k6F(joj&P7_8#|Ka~
z42+J^X{xld3~K~Yu%Sfi3|SDYk3usOuKd-Y*>bd6j%J!MI5dclP_L)7+a6;}bai)=
zwj9n!G8bsnQ${PZ*j~fb^fcC5%B2#SHMG3s3bFvH7i!A}skm5V2DqSD70TUx_`+pT
z1zR;l3_e0F8v2$GQ0=JF(Om@rBf^zN19vTthxI{7oiOp+B-2yZk)(tV5yg;{J7_jr
zC<f;vF~Y#`FkL;p_@KBb96oo6MleOe<#kjwk<re4ZC!-a3D{0bl?ak2bUX8ilqpp@
za6TeQq^q|ddirQ$a52!zJn#LUaq*^t$XttHOONo%>JkE2S171A1GDuuNK#}`#JGf@
zkhU_andiX^6O7Ex5Ul0TbsIT9x|%@5&(~2t#|4FIT@*>3q1lc!TM?5OTu>rHB0`$B
z@y4>Iah>g-9mUMvAesJyRlPmPYx|+L4aCn0$UBu3gd$?o)M+F2*lI6Jk_u6UvI-G{
zVz8A!6sXr~e7o;;+Fcbk9{ZS)58r3_>}j5P_EBak3-1gAC5YbRvJ89X<f%gevo*0L
zi7G`mELz_!*P?(EqswZwzLhhx4~_KnnxCg8&tLug$Ry6mLW0W(zlNaaemr$XfKH$f
zF!y>79(jCc$43v3y*c*vmoIm$-*DoK?N7Y1_pO5yxApH^jV%H*i+EBB1us2^e)_={
z-Lm$wZd^5~hu(f#i>$fZu#1BS28N)kdkJgDud;gl0xL(q=g>Qd$X(4APcSkDm}{)t
z@EyyC&T{{THo+{~{O;~i&4a#w-$5OzMcuP`LXRGPKwo{~p0<lu0MNhmA}iNiWZBRK
ztgTb)yQhgP0ybB1@*B8sw8FWcHqpCulC3*_0rXxm_!|W^OSOxH%wzxn03v!+Saefw
zW^{L9a%BJjc-nJJ$xljE@XSq2PYp^<OsNC_FPsI`t_-P700000NkvXXu0mjfCYnCk

diff --git a/civicrm/i/admin/small/case_type.gif b/civicrm/i/admin/small/case_type.gif
deleted file mode 100644
index 9a1d1ad73f82b63b3a9814a0b50f27d11f0d407c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 320
zcmZ?wbhEHb6k!lyXklPrVPVnNVX-o|^7m%(_x4YTXGw`q$<NHMDyix(Vd<aLKWomc
z^^;iEFI&HBnaZw>yN>Mkzjd?!*3DbLSbqI_yzAGyTfg4@`i~nZ{$ycfV323fVE_V<
zoeZpdAE=vkBuaTGuUoT1f<=M3W#N`JLh_*^s_eITuNyFMiF&g<(%@iV3*~mSP^s~D
zXDU!oC~$L3Jegu4A7CIdp};~Sx>@zEkzP-$3*)XC(pQZA{f$d>LfFMR#e{l<*qP#W
zT^V>gdwGS7m=dgFdizY68D{Ia=^Hk>7c5@NAf%$M;m;!yy+q#4sDN?xVumf-l=#*5
xbM7f*+q`v+lH2Ol_420<?l^kw;-&o})o0zSS*vf{WMy2kv!zw3iA#~e8UWbMf^z@>

diff --git a/civicrm/i/admin/small/case_type.png b/civicrm/i/admin/small/case_type.png
deleted file mode 100644
index 21b5f745105d5fb43750969e84e35db7d88e052b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1008
zcmV<M0}uR(P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004b3#c}2nYxW
zd<bNS000B0Nkl<Zc$}S;UrbYX6vscmdn;VzPxvEI89GR27_yCNNims~xd#$Jcv|8T
z_prG6;FbW%_MkjzvKY6_O&D=Z7dAB!_OL7)2}Er}R?rA3VfY8xmQAKuy0)RrYS%)0
ze|x~P0+*)ao1EO-bI&>7bI$MF^FvBWyto|*w}b574r=#RVcVETKvmE;<`LLeg{`-P
zTDOC2w*#@<*GN_<+z!%uJE$$(gtw%a&^IUe=k^cGU;3Efvjv0;H{rc}mKwK%w6zj!
zt>25Sq?pjpw|<dQN*Ve6I~nzym2K@W$dY10^?R|o9c)d8Kw%~FhsLNpdI(uw_8b7-
zxoJFMm0e|dG`@)(zDXsJZ{WKECIg-3nIWU1j0n@8;`XO7_MnF}C4};59P@V8`TV2;
zS~3Ji6@>D0c;dW6#1nBbBNUWqCdJwWdU%GBappJV@B|30wF2+1m$`BB9Itq0+o-QD
zr64N<U&u%26}a4sYI%ukfHxTeA*Ez^cq9eb0Bkl%SMFoiS3BNn>}!ceqw9|xLhdZZ
zbYqOjsq+X`RfAujt~rra_|9lV6wCnAfX`wv&m|%#ICG}`sNHTqAcR<#o2|;C%^@`q
zm`xe~Ev$NHbdjH{$nD!wqgh$mbN5_Y^l?y;Qp)h2J+F2hKK$-S7K_=Hh`?M~S>fEh
z+e&d!8T;R8z$5~sDi6^V7m5g>OO23TKv;i<h|J{M?jN}~d56Kl0fvU06&8zmB+(h9
z$1CgVYF6#(@UUT=bR%Uvfk+}qB8b&K7){X%NGTCQ(9&`QyWNHmVqpy=ff&IO>%d>X
z((>Uctk!A<2CiVWR@2$}1%Cf5(rI3rdc_Fs?QNwOE}Z|#h+xSfH#dJkwe>}5zdj*O
ze|B=wNPoJsB4c%^^X?@9CMLs_zJ7ao#fvSARWN<<;M;9|eLee~{oNVYZce2)HU8(&
z+9nn<UlttT`Jz;$)6D1BUjsD!evdAMkTH^21?zzlpscH_`(kVBC-Ux9RSfnE9^Q&@
ztVb|9dWrJ#3gGX!t_l`*UM$ZXrl$JYvZZdZ3KM|EVh#eMz-U)j_eG;#8g%#RGk#+P
z@%d(#SS2+@0GgJ{!nn^Tuu4bMQr1TB=i~!SrX1i=0;^2!-*<<BssBYFrKI`2W+whf
zDwn&!&e)65ePD?1zf?HaqH?TWf|N8hy^pTz!a#P&xW6!If;D6LC4IbsDi&sNRS_VM
eH&B(#rT;Hh%QsGZ-f`ss0000<MNUMnLSTZ&S>ycx

diff --git a/civicrm/i/admin/small/communication.png b/civicrm/i/admin/small/communication.png
deleted file mode 100644
index a6a913c36010b7103529af89ede41f2e7163eadf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1314
zcmV+-1>O3IP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00e|dL_t(Y
z$F-DOXdG1-$Ny)}%<RnW?6ui$H<vcC+nZ8tOjWE<q1IS0tqO`zrKqU*Vxj1RB7G3W
zC+&kG+6NJ;2-XW|5k!i#)!JJ~Nn)Eex3*~$lkBFOy=Lcf&gVmHP0el~pnn)Rb2;B{
zzW;x|0sd$4dG4{st;<qNpG@qEw^w!mZZ^3Um$D}p22lTfA=zG!^wDuM^}?!0lADsR
z@t|l+cZ~`~NB@Pr>Yy*qbZ#(J^)pop!R@q{b8{F2;8uOhYYVeMN8gp7vF`3|%Nw^g
zy^`3t^yxsORp;aiC=88BF)fF<4--U=268x&tCcPn)Z)n0<@_1E&J>&;`>93;YLH=i
z#0lK9{n3Y7b}W81wl3CY))^`Z0ykAeRwooGDk<{ploSf206>8BI9!*-_z;DeQp2L;
zV+{5LEsx&r+Zk;&w+EYzI;Jv^ATVX75J?G=bp3z;i17D0JW+wmYNV-JD;StgPgtwj
zi@rEBNzN2qkk~A*{|(6X0L4D+(?g`IntVx1p|MuG^VF|N;H3eA>gUDG5%+gSN{=2f
znvJ+suLlF1F$E+&Fh&3bh&+Hi5D9<;oT&=zT%}OHh;P7fxj0Y-003Tr06-S{oI$T3
z4=cLL%tUaF7SauAyC{$5$jv)t@<dsBo=ct(fFS#-%_^D7Sn(XbCV|oNr5az+Y$@C~
z)V=%co6b(wnQU*^r3J;ht7m(?^snWQ;f4<|RYc&EA<aV6E7`&FFnS9EIL}m6)tu~0
z7fS%a%^XknkfdX7emYu7XYG9N^xk+`9I^)BZX<Tz#!0VI>~_ECZjX2DK3H_TLXD8;
z$&RLC)7>MVkG?Dw;S+x%^WcUEWDAyTdAR<$P<cApFp%G}tH*g4z;V==<T-%5;tIw~
zQfp19_bxk@ZO{^`ruqH4akHlD0aXjejO8m+VJi|(a<e7(K=}OCm5HX%M+f^#pEiWl
z+`b>L%n#UHui#9Y0?)42-q@5fHo!80kiif%8HEf*37gCasR}n$tZZAtLKeR%8q2?(
zXb#_T^pD&g03G#<4H})OR0n7ZgTerlL$f$Dz!{)05NEiy1^_7u8i1y_fnYZ0x17pT
zb*uEXOCMkS-l0>O??%LmJmdXy0YreL>cdR*&pa{AJi`cx_!t6So`o}oTMR!wn2hr~
z8Sj7Vwiw3e0LmVawLwC{sha#Oz-%!FxE|rklo-!e=)3{gx>Cg=j{rvy31G$!j_cMi
z<;I^513(OzvI*TKv)JMA1HX;u_I%%4J{|INaVjI`0tO2blMdVy6XLMc9oHXLg24z2
z1)|KdY!>hnH^Qbb;Ny%tl5k<TBs<Sl`cDkY509L)zieIGkVQuh`Ld|m>2>LVuQ{mb
zZB0I2AJg>;=K)7i{F+~1zw`MO@5C1wja^-ng;SlGA5IRI-v73{*tKbmC4V`QzR@}?
zK%3Xc;0bDd=Kdw0AzP;2{`@EVJM;TDv>4g1x=K~|EC>*f>Hx4P?qj$5Z1>{ntQ=MV
zAs15Qzt&$`FA4d|$*Mg7001I-R9JLVZ)S9NVRB^v0C?JSOvz75Rq)JBOiv9;O-!i-
Y056;c)UFJvO#lD@07*qoM6N<$f*V_DcmMzZ

diff --git a/civicrm/i/admin/small/contribution_types.png b/civicrm/i/admin/small/contribution_types.png
deleted file mode 100644
index 00e28d4491eaa112c1a5767d69d49a1af9e147c5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1833
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
XFPsI`t_-P700000NkvXXu0mjfVEthp

diff --git a/civicrm/i/admin/small/custm_data.png b/civicrm/i/admin/small/custm_data.png
deleted file mode 100644
index acb13b72e25205784677e37383a7dc0fdda18a18..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1498
zcmV<01tt24P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00lfrL_t(Y
z$CZ^$h@Dp*#((F$=Y8+zd+&VDWM<N&W7CA@W729|Xj0pf#6qiybkR^Pg0zZ3@M9qg
zf+7VMB6T6yg&V0Lg1cH=nN_6$O|gm9u?%JslTK$cbMKw|^?sdm{w}7rO)ENi;4IFw
zI1kS`|K~i4|ANO3k8rb-&rXbl=j&DTbdmYpopyeCvz7m1wO72@jP%y^+_Mt|A0!@_
zt#D%_8<}cEKbe~<KRY>D8jp-pF7-3{pg8VR&zh50Yv8gS2<Q(Im%hA@vf_)CKs{-U
zDjA~*0)<BqPa}e_O~9jvfbyLRG=cgLF3)KzPq^GiS>ot-3zC6D0*#6^0gMOmxl2%~
z??Ax3e{*0mq?P%j6mn=duyi{)S?0)7&-h#grG@2<j9NW7JX;BxWsziKqu7~)&p%q@
zdQq5j=O#})er9wu9@TgOYlWy9aQe&)%@IRfh0`Z13lASJJ#hB3|KG#A4*q^MW3_|3
zy1X?wdot#$&+cVCE#pi?y{b@o&eD|S-1(5@wIqDu_fkK2m)g0&YyYqS{NY04{g&rb
zM*==}R|7%|-qT<2@!h9{n=6i=|HiAe4We}84&I;yWZPF3zWzqRuYTL%OOJPH)B+Gs
zy(oCQW%>2Rm@KXZCr&nw?Kw16I9Dj~77+{Fo{hi0eyjDa$8SHg9~03C#e8Ray!NfY
zte5tUw`mju%F2?6;mT%}>!k;I==3qtyhm;moK5jA#rq5qw|$rh0{rRXYCAY_{|MJs
zpJ(OLpYJ<)eAkc9e&)azre@=c(W?sMXs1FeS0rJHRuM6}=LnxXz6jb;s%V-c5!Fh7
z358nCP^}uKrfbaXs?pj^D(1Pb?B=Im|Iz+4r{;e)ztDI%tX7D}niN-?7#R|T3K5M8
zG~Q`M6lvmEUb;o6*Fne;m(y--VT?z-=g{IL(=#=^7tHzR-l+cad-r@}c2qrNlt;W}
za(s*<A3ep&Kd+J9c$G>y!RdJ>rXq$xNV5@h?Bn|wW<AophxaMA7~))tcuN#%MBd54
zGpFOlnYuewl3YoaAXyi(O{T|SadCn2$Q+dF96Y#}yLUGTv?kCYN*R<2P|6?#Xl+0=
zN-3O`_onE+8UGQJ5B88mD5Vkch|N(^7wrP#s-a~oj7BLp2VE43WN2CX+bXSgi`*r6
z$q=7291N&dg*Xn`yU^SgkSswG4}A^Rp^6;RA%rEgSGe95<eH$j34<=GDg@dP*Qyjn
zN<VQVS%D4$;zor^#WS<3jMm!&YW}rmugo?4g}U*N)ElWG8$eiwFhqHUY$fPa(Ct2|
zmqG;sWe9YL)`m*C4BC-p9)(8-3KPE90>Mj{S(}OF6<4_BPOm6bk&T2dRd$$YNe60k
zeW-k|&unSPjkSc%*kSJ7e}J2B-J;takY*Xy7FcKL_fy6v%8ZUifUt6PYdgu`e~A^4
z7ryz3eK88{{QP)!cws{A8>y<j?Sxpo$dzR;m#zm>%?16SQbb`G5=9ZpIh6B=vP4lx
zzh_x}%Q7`x`p|bR&tISqEP*V6+!p&MpT3_zzVhZLe)#F|cVTFvxK=~Nveow(5lVmw
zp;YpOk)XBya3B0n2nZ;EEGy`24QRIqBzevt86dhK%TwZpX4h<t*7o*3xKoH1M8E`w
zxLzeR2IpXOtVXR~2BiUY2M*qcIIeQ^=sj3#$z4Kb2Mn_=!>or2a+E4i+Mtx)xj<_p
zr^saO&879_mtVek>_5D9Ihjq!-&uuCa6U&|#$R4rzxHp&xPK<|q^;@z001I-R9JLV
zZ)S9NVRB^v0C?JSOvz75Rq)JBOiv9;O-!i-056;c)UFJvO#lD@07*qoM6N<$f)xwK
As{jB1

diff --git a/civicrm/i/admin/small/domain.png b/civicrm/i/admin/small/domain.png
deleted file mode 100644
index 57a2b1ab4b4e0b34a3b471cd297c86cd04601fba..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1277
zcmV<Z1OoesP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00du2L_t(Y
z$HkRPY*kehhQGb{>3z4ow+~vN6e^Tw1L6aDq$n7O#KZxbILDa-2gW!y4jq^fLrm1f
zkrPdfXktPjjXV-Xpf#705?XF)p{1qo+xzN0=j`R+wiWCtnmBL`_g?G&*T2@<d#NMs
zYc98@;u<RinNl!U_Dt{S?6>_Bxzo`^V%_co`#)^nxUtoWwFHD|qh%yBSTmZ*eB`{b
zYu%w&w>Bf54J6Q7aW7j`UtAfu)jyGQLXmK)WB<O__8#us;<;X6R>m>(Uj1DV`>Att
zdR8$ih%c)WJj#_BD;5DL<x6t?O1HiLAdB^V6{uQkCLavR*w7fxvEwbAINX9N`@sZ8
z(?6bPxLD-c;0!txA-Uy6n)Y^LJ$IED2S0X=x%m=KC|ONSQ#~vM6DUU$^Fo+Nc(Er6
z9jU@eM6jL-jxi288bVh&IK&f>N+Bg5R4@TKg@i%?hyrWCcZ9$W1KJ2y3s!+cI0UgM
zN_&CMI0hmml=D}%qCm7lbYKe>?*Ii(dBLMlaACnCNP>1OrILr|Sw+P|VXYAnM4nWz
z6fGiPE#i4NUw(b9>)eHY<GX$cr97?hmw*IBDJ66Hvg*Axb^~x13Wce`s~68s4QE=h
z7Nt-kLVdC})!w?HL$vm_QpV5pPLB2WO)H=VU~`1%?gTr|PSRtk6gL*GGP}1l*VaVB
zvBvtiHA>}gq(@2}+Z*Z|>ti*!d~v$F@4-a+Ue?{YZL9Ojp#$N_t**UZ%dWoe(b@c!
zUw_Lk*W`oERBOdC;QJk?-lQ%WGq*Dn2RCd^o!s+M%T|PVsqDF~@6Ec!g*sc7nujCV
z^x&PDpS0-ng5;-vI0tYNI1kK!au=K>0$(s%kp#Gq9${=OyY`(^``_<;x$VT-_0f>l
zC_%8k#rJ)zFE%$n-;uuVAMCmMXgC^ox~D7YCV}ONc$~nkf<b`R`Y17RQ*CRTwy$q)
z3tO>R3*e$~G1|izs~Z|3k&bPuJ*n$bRUyMSUv)tRqr8GZD>RS-$PHd1JL!vmcigH?
zFQ6LsAn_JNr9cu0C6qiwEev7rU$)+z0a20A5>zTs!Qx@E@>&Hn;LSk32VFe{iA~__
z1hxZtkU=Qj1a}m%CGeNOjo=a~aDlr(d-SHwCzCuYq75qan7;))z^5{34k$yW*W2^U
zcZI%G6NyEPl_j#3oNEEZFzfg{v#8^5w&F3WLRL0~V>B+7r#4W*=?wG0j{xtzZkU|%
zeXV$#e>Ukj7&`mh(OCNVcjs1I>VE<7pX~o3FdC{13XMTMC0c<}Xrp13kM)T$UAD=r
zFgissS7g=)j8j2+5?p~%Oc$8DeczU%@!*{vxRQn^q3<E{?dz-NY&f(bR$sj)noMb>
zn}H_4C7T_Q^dI*!7cWhm`S|mhpZmvI7#d%>6`xiB0Q1)I+V%sTjYpz&Yxczxt!-Mb
zGsWWkc(E|lGti&u`s~a=8py8(@F#-+;?aB{`h@@h03v!+SaefwW^{L9a%BJjc-nJJ
n$xljE@XSq2PYp^<OsNC_FPsI`t_-P700000NkvXXu0mjflkrcg

diff --git a/civicrm/i/admin/small/duplicate_matching.png b/civicrm/i/admin/small/duplicate_matching.png
deleted file mode 100644
index 20eb405360e83231f10e3d4edac9bca20e3b5397..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1803
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

diff --git a/civicrm/i/admin/small/event_manage.png b/civicrm/i/admin/small/event_manage.png
deleted file mode 100644
index 2f7342e58f1f0cb4dac39a8d79b3e89b248f3693..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1796
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

diff --git a/civicrm/i/admin/small/event_type.png b/civicrm/i/admin/small/event_type.png
deleted file mode 100644
index 67d20f60528b84efe036ecfe2b27fd6046d4e673..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1770
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
M07*qoM6N<$g4h5$O#lD@

diff --git a/civicrm/i/admin/small/grant_type.png b/civicrm/i/admin/small/grant_type.png
deleted file mode 100644
index 95fc4608dd4803590f3f846c094a47514fd6f3de..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 635
zcmV->0)+jEP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt006O%
z3;baP00006VoOIv0RI600RN!9r;`8x010qNS#tmY3labT3lag+-G2N4000McNliru
z&<h?H1q<phKMDW<0r*KoK~#90m6JPc(@+$KKZ9390SVfL47eF!iMui2c&ocqS-PUi
zT@eEVOh|WP1ElVlwNfoHFyKZ4rDl&k1cug?I(WEKkxUo>p)mMSJ9en~CF`DZ&$*xe
z`>-NtCjnc41!#Z)_&@}B0`~L1%VvAnBVb_LbnFdSS)~&M=)kQJ{4n8bE1-Z4U=tX;
z+l6OOC*164^zW~uEgkUTGacaj2!5LoU23;sG~0&3!wFoy2S6MTx!YUCw$pmv*cNE$
z%WxVGIsNjwQqY&v`u_s`KvFo1;~~G26B2n$Ht*++7oMRB(Fh&{0lKzy!1Zeie|~-=
zk;lXmUhD$!QNYVqK!6e4&~^Q`voBZFD`%+FGY+E^rt5kjrF2aQ0Tl5MkbpOUU7j-x
z1K;<HaZZl90Cbpz5kQh8wH_&DCGU2-z~W0WvQNtwd!E+_3&XIoP!;L6YO=f;o~0Q1
zBG+}XEUV_sbzOSBUXd%nY!MK^vlI-&U^=axSE0SVqkPNh8NQm#7{<-bnN!x*;Q2Ph
zRfD|ss<{gA<kLwV)V-5BJW6ZhF|d6O$>HPi`Gpif9&6O(%~Due^C|sa4RW&4RZB@(
z_8crK1Iuo63D|-3mUrf90_+?npf47@geEmU?93Gc`sK;@VRL*Ta2}M)ahl_@{sN72
Vzj-^m+vxxR002ovPDHLkV1nHm71sa&

diff --git a/civicrm/i/admin/small/import_export_map.png b/civicrm/i/admin/small/import_export_map.png
deleted file mode 100644
index 920734118976e8b716ed339f82723c759279f4a7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1901
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

diff --git a/civicrm/i/admin/small/membership_status.png b/civicrm/i/admin/small/membership_status.png
deleted file mode 100644
index bf7e712a776669016c7d75713d8ddf8f41a82610..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1826
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
QO#lD@07*qoM6N<$f+1jN+5i9m

diff --git a/civicrm/i/admin/small/membership_type.png b/civicrm/i/admin/small/membership_type.png
deleted file mode 100644
index 2efe7026c5ef977d848853f9e55443d4702d6676..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1866
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
Ef@r;sCjbBd

diff --git a/civicrm/i/admin/small/online_contribution_pages.png b/civicrm/i/admin/small/online_contribution_pages.png
deleted file mode 100644
index a854f4115f45e8424d33535cc09496e59c386333..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1856
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

diff --git a/civicrm/i/admin/small/option.png b/civicrm/i/admin/small/option.png
deleted file mode 100644
index 887a66a7117abf538e8ce1543df6f5dc380c7405..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1861
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

diff --git a/civicrm/i/admin/small/parti_role.png b/civicrm/i/admin/small/parti_role.png
deleted file mode 100644
index f16850d0ffbc05bf51b07f4267849357e52dd6f2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1210
zcmV;r1V#IaP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00bOKL_t(Y
z$CZ^^XdGn}$Ny)(nc11$OtRhGG%;&)Yc5SgYD`VhV6BuwPzqiP`XC|{@ktPTl7guC
zpkP6vLNU~Wh(+)g#TNz93Wi!tnlz0uq$Zn7vrV$u>?V7e+4+tS*_6g4o6UKf8P5NA
z{^y+eK0*<}%m9E_KKtgGNNnj$%68gKO&h2zv)=vmrBh!6kVLd)u38M>(v@ofP}?7w
zeLWIeYR~i9!~W7YKK|v85dg#6<!%D}Iyw$j5juk#j@0cN)r4?gyYxL6=uD(Djjm)U
zM3Br#*-qW?O!U4&0OkKLPJVO|m&g9?c&qp43#TuB_2PE}!xdj%9Ym<aH?6B8PWhG*
z08J=K%k)Go)7aMiCI`uL@8IvlZI6xIx_x+JG5+DyQv9h$n(BT^q%*FnC`?3PW&}&T
ztM%o<&yO|L_qkHyy=?#+CX*kgapHqdz8#sp-EF%r6e9L}O-B`qlSpR_JLd`_LR+}<
zx5p1Pzx-r->%?DEGurj(XoKHtRJDdHE~jiK`9yo`)(#|dDC^{cmf-;ia9m08R9a_1
zCjjdXMx*ncJjfUNZcYs{bJbXMp{vBu7jMqTo=-VWf1xdk*Odp(hb-TZL?i`K)zyjV
z7gDxkuCF2yA?xJKq3O9UBI?Q)hU$PnIG0!n+PU1;Gsp|90O$dL?z27UYN*{imsmM6
z7F}q+yOl)5x+>COxBv{tbu}VnHK91n0)-shiAS6F<9N&d#L)DuE2DGs8vs>h*7&Ih
z4!vJydZPW2+55+$i$_Zg-K`1kiKc9Odw?r*ASeL<77<}4zU-?kvubLB{=7I~8G5Fp
zI(+ub$>Tk}12_296A$<HjZX$5vG_eH+leT5{nZ<`==aEZ0DK^_{O8-5T%r+xWROU#
zdYe|W(gXko!_<Uhd6Po{Z^aMKww!x&yJKRLgQfHY0PapXv8OY+B|$_WVi*R)FbQCQ
z0Wg!6W2IvuwYvDl_0xsAyb+L-S%BadqzgM+kCn8E)r<zo1fStRS6%phSr~d888-=6
zI*6qwiU+J&W#ptl|5yvIO-f`P0S4evT?oN2bO*H|4G*^5fY+P{vr;@@Jrr``GgmMh
z7r4`2UUvzU8U#`t<k;R3u<0u^pePQ)p*fUWdLBqn6ao=o85$bHF?c+2NC_~@-2ni=
zWeLBvfaWR}%xgyjGea_AUr3_)-Y8s|#o7|k?g3zesxIST^*jPT75NJWWv0N<gE6Su
zESL)m7X|=ur9^md1Z_202t|Ra2y`7tp{8;i40p%M*Q3BuK>#h|p_WNR<BbTFX3*LE
z4;V=>14ZiZd?$OoGkETp4ap9Kx(LZAy80~v8<Ppl5+tG!`R83|Zw7d^AOP5V3<tJM
zfv`)pE#f~7CC|;rSVblP001I-R9JLVZ)S9NVRB^v0C?JSOvz75Rq)JBOiv9;O-!i-
Y056;c)UFJvO#lD@07*qoM6N<$f+)5g3IG5A

diff --git a/civicrm/i/admin/small/parti_status.png b/civicrm/i/admin/small/parti_status.png
deleted file mode 100644
index 6cdbc5e4b84fb263269bcba5c690a872fbb3a289..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1153
zcmV-{1b+L8P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00ZMmL_t(Y
z$E}r3Ok7nI$N%TOH#2WOcsv*>GDATqDYTSAt<eOCHq=;aqKzgcaalJmbm!8vx+Jm2
zg~k{|&@^pgH8yHD5<e0(q@<V%lt={vlrLxC4GawPX6Aj|<ASlR!oZk#RyX(FbARXj
z?>YApiZEsd0K9hjtIpZPT2I=tI(&*UURA2S_30~TzXTwNXh&bA7{CwXQy?IEYi{Yn
zY+|(|&pTwK(r;eu|9JwyNFm>CfU83z0N`cjhIG!JVrJ`3Yz1J{uV=Ciu3$(+5X>+w
zyKZXPIJz4^`uD`eZ-2sM+=yJdaqGkWv57bQUeEs5`@TR(^%|<8tV=}qB$FjdYkoDM
z`PG8iZ_8ll-ClI{_H>QT#~$~}@)JwRjjryF<Nd>POR1pGt4Ks}nGp^K%>8Bh)t4SU
zG9Z}oPO$(aM==>UIvMOwWwV%w=bm0pZJrogid&mmOLc_+5h0>$w>u9$(z~xDlo_61
z488sJcMW<#jWkCqe=#jPb*8O(X8<#!`=cw>WdT2I*M;K>B+ZP%fI<L}muPa?XeGkO
zqYJT7W{yn8jrNf0O-!$>zHHj|Z@X4eMA!P5`G(6Za<)@Cy|Q|4HErtmN|6XT+fi>X
z#M+6d9RP%2)P(hLY-2NQIZk1T@`ro|0Iy!UhMID{gqa)H%*=BSW=TZsRpbm9E&$ab
z;UPlKBTF{3j9oMM+s?Ed#_5*E%(*^eNHG5cP^Fd3oPDgNM-Qm+;rTz0%^0igK1D%o
zxGZj3R$)NC1c{l;i4e+ImRhNW4%CMA{5lZwd7TqY^_R~-fAaHB27X<Cq3!TDGEqs!
zwrfnwo|7Kv>TUh~{>?5Nd$_xKHaXa1x#<W%@`f2`*vz^?0AK*BM{&!7*(pse?SH2J
z`~?8(x<6W6nZ7spBR)9&<cphD{FEbd9!UaZg%AozkR*mzaUlfctV@lOWe3Mru3rc6
zeIc2*0j942&Z%q#gJnm^xO2Ax3x)>EmLbamH5Kb<sy5(J959R0R4yJZ^w8~m$<lr8
zm<jVM8eAbE<hSt0!bAA|ZUq3KwJwHYtY8%}0FUhAWZMj6i6N0dRe1{61`c5{q2Wkv
zyr{Q$&n-UBR?}FHjKzcoud)S_Ww8~-9wzO*1+ZNiHz%SPnXW`@eGE<21_V<vu6qLr
zz=EM+aJ(7^qX|6KG7Ht~0RIPo2oOwIP6pu$2}kSV@cW#i4lW9i|5s4EFNtT5PobjJ
z%+D1UJy7JIT&br~si*%_<b?rrf3R}{6(9YMfCJq?&{Li*_t!GBTUb6YJd)p36>V)d
zz+X{Gw@Ro=>m~pI03v!+SaefwW^{L9a%BJjc-nJJ$xljE@XSq2PYp^<OsNC_FPsI`
Tt_-P700000NkvXXu0mjfxY7&w

diff --git a/civicrm/i/admin/small/payment_instruments.png b/civicrm/i/admin/small/payment_instruments.png
deleted file mode 100644
index 57c61a33efee75c9e96d583e8ce4529703d56968..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1680
zcmV;B25<R^P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00r_%L_t(Y
z$EB5NXk6DBhTn6~xy#JlSu~>=$r@QB%UE`**rUiY!9=R1*5IU#X$hjH1jj$>QV7&w
z=&wK<+7eQlrj$Y#f=!?cZAzQa#@HrF9mQ50IU$L)*c#iy)?zIq&n9WMd+%BLBTd>8
zJ1Xr5hx6y-eR$8|`(EJxsNM%GXd3K;2bz1nd1PxEh|oYV`X4>yf6yfZ4@LZ)TLNuO
zaeHrXIy~6Y64||0GfS5~EI$40b0g;tfBk;(%M+9TJ>cPoTTv)Dk->eNcJ*|{cLi;0
zpkuRtPdpJxm_FMyOdpX-SM&2ra~DQ#{N&_sGrtK1jkPnc&w_0ve(=#0UOhFdpLn7F
z$^M5@$KsL3SkUihAPQ1(DCI(kJP5H!D%F&-1N50_)ZB6QjrkudrRFwt@W<bO5fc-4
z+J=ViKb^j>waY6NA?qbLl{LU!1<^QIBnaXUftbypG>&?uEG|#Xocrsk>p$Gk!It&}
zrZSaudu!w7TCRX=Bj=G@&O=t~Fd0W%Du6_18>ndlVi5uqmM=*6^tSH5oh^8u0$4r^
z^;+F%-?BN`o$iYN^yg)NdrE(7CBGiv%QtcT(ku+=z>|QGfV0jK3K!sy#i20)qAh`|
z3YeymrUdKy1h8*k8e?NO%tyb}*Vq5~Jwu(_ckH%<vAE~Cfn0VrIC9}KU7T7#ON~P@
z0zg42AX^Y9=T{N%ToBC<O|Ao~2B8@IJ}<xk;E@A8C>G1H?;IaG*5BXrt(IhK-10YQ
zmM@A*)kALi1GGeMqxX?Un5q%gk^@mK1H6uqO%P4kP$ULOAE0uesDV-)u8<BpG_)5Z
z7c=&;C%^pk;6VClC=&7s;lOpOAjHJ{+#JFUStJ_U5YqB!X|SMR15!aM1r7tC28gCZ
z@f<(^qA3tfL$SzjvzPw-4mtkq14s5g*zpa^)O?=nfa(N7)FDM3p`ag79jLkM$QN^P
zDk}glLMaKuAc#c`5T-*Z0-_u!=0WK?R!dU3cgj~;_s-<@-gN7cfRFk;&jlkCL@+>c
zEG{nKr9Ta$yQdr7-MiqCO}Md=hZG!&*Dyab&rut{+Ow_hYf0Lh48Mh{gtzX{>dooe
z-1L>=%WVHZ=RjlB+9`zx0tzV@blt@0=oo(e!fA|-PNJ`G3eW!NDQxLTqmW-jy;=eY
zkXw(?*Z+>U$3|cNl^wIUIa1SHK~^YZIqJB@k&*lzW(R1m-$yLYT~JVH8iSG^B=@jw
zYYU>$5MF!j5>B4{1Ag%R<FG70Jhu$V9W;au(%cl?_T2B(QY4ItQZe_bInoGZQiFgL
z-bY7za2*Fd4{XKvzIzy7{YpP9%K)VWx?#ff*)R-0Kr|R81Jg-3(HIMc!@;`_s-~pi
zLV6#)>pyQPJrD>iE@biIi?1S?Y{H?h9e}107)Ai5WrHyTPzq2=aL$F`;_d*?<I_&v
zfl~i+AcY4)1kSzrJ|?f+!qKA#ao>(sxK0(iZou*dVOloojzq2QtrQBmVzE@bJ79UG
zd~tQHR)pk`l0ym)N_ya)i{?ZKhacaM2YWl=Iu!^}10Y~n0T@;QYwMgZEZlidDYafH
zSMCn@%c*M@ZZEFB{qY|t;Xz3b&#5DGeIDZzH<4Y*K}rXL*CDtAT{qxyid(a}+3D$-
zza4(!&^?zWd*-Qq%Wqwr`$coy?nx%~mXBRXXqcH<MkX_dLcRngJqT5Y)E!7+U~=+i
zZDQiai4Q-xe1&`7JppuirGhuk&)iBh`qyF&zTM%F6$GK6l%cCDg)a<tqw90+&?p6E
z3_>Wp`|j2H=`$Bj4i8^^zPUM3otnCKZ@^Nv3;^oA%S)31pMIS&nhXZ5IAe^3LVnWR
z6oW=7xB#-*H8FgCeD2JdcYb#E?C|p)9jW~I_~d8i$tQ^xvQ4a&9qj2&ZrZWEX)wJr
z)fbC}J2j>UU60o07b>OkD~pqv%={~v%<PzMTHJG1H_EHe41F53(HIGlP@$x%l`7T%
zQ~`($RsXI20ha65qPaJ^IRF3vB6?I<bW?9;ba!ELWdHzp+H*|FPfAtr%uP&B4N6T+
asRRHooCVab45>{30000<MNUMnLSTYwvJh$j

diff --git a/civicrm/i/admin/small/price_sets.png b/civicrm/i/admin/small/price_sets.png
deleted file mode 100644
index b6c3b98719bdcd089f5c6fe7ef161582af6732b0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1641
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

diff --git a/civicrm/i/admin/small/redaction_type.png b/civicrm/i/admin/small/redaction_type.png
deleted file mode 100644
index 8d9239552c5bd291304a362d48c1cdffacf5c30c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1138
zcmV-&1daQNP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004b3#c}2nYxW
zd<bNS000CjNkl<Zc$}q`TWpj?6vuxv-?!V{?xGZ0xrk^{Y@mP_8o)@|@L&@z<;{Rm
z6N4dWV!%X<z>^qn(I`p?A!rO>6dv@UkhFmm!9|QLR4!G5Mj?$*mTuD)w!8b?X2yqt
zwB6MdJju!Toyj@ppZ}Tv%wUXRu&0xVbdu4{+gZFcLF>4&WG#svH<s+u1g*{6S)5KX
zI-NueuPx<83+W`$=Itz=G@eXNHO|g=Dg4re|Mdst@1KY}X*`(&J6M!X61`J^$&CwX
zt*OR2-Ts>~#+cyGZ;k5OVYY0YVQQ*z8W+-<PBM8U0Fq*>I(~+^8&+W+seK55jCX}D
z*J57nSk^p;Nu6abP*tL~$m|kpk**%%b+rUs`IvNXm@|LvCn_D}^>fUgPN=(=G9WS%
zfKm*cstR%^e<kP&I_VJ-sYX#9IgfUGXgh~rSwRkP?vz1h-lP2V{%1Vd)whMlhG|T^
zD^9o5%@+sZKr_~ySsVj0BLNV`7*eUWFi;6huubQf{?5-Idtpt>Mx|8w`c;_6r(qxO
zeqKJYU^cGbj~^6J%Ec%LZCs2|1Ko_l0H@nJdpEq+JZ3P1%5B@WZa8%4(6d5_(3sJd
znKixA%4Yk-TiaYa)1$@SZz_0j%0x0f8C*Y%lpem9$8~ZDp#VdyJWROEqAQ)P7(Sv2
zyLRn-W&ZqnsvoFj`HE%OB1@UPOhk4fg+oVH;5wR)3*B7rzlOoXXpg?WYuJ{;Xid%Z
zd#J38p|vU6gV^A?Em^XtXqK0n-e6Qb#>`n$aJ+t8zaOn#RFFq$7o!8hA&D_V>uv&w
z!HcO>TM>XIB~pYC!bS)SA#4l*QralxBZNRHgB+&IQYtEG0&tyx3x8at?^-XuE}+f8
zm<stE(WoIF4{`5(cb5bhLM(grcQ(HL5%u*A96frF`uYYE36RnzRvsk?Tyl=W@dBh}
z5g!#L646vuMUX<21jqr@)y<`$ex_;pzFnM1wQ=Ics8Xpm5)0O22@6Yv5Yi%276Ga7
zJdHpjrNFYSBIY*%uB=@7;+B?{{mV}t-Wxx5=2C3!+FMDVd<qy12wXS7%_}_Rv*f9F
ziW;7~`1+9e=9cuWUj6dU-Mhb9SGRCQ4B(|kiy3j7ii-mY>W1`eJ47fHA{;I&Y7U@>
z$;bwnGiP=lI0c;AvuE#@B`YmMC}b0hmSapnHm^DS<9jF^9JfGOSQ9HZNHJ7KBUTZB
z=lM*X`t*P1obOmaBrbKE{y!6v!N=;h7{p>xa=9ZY72qoePZe;yECsJ0VR_hAfYy10
zxTU5M17t2=;K-4m|B03Ma03TFDB!DsuQnb=xwM~6cks+@0xWpAi66e($L02bH}}EX
zSJ$z5^M|5j^729d!yoBQ%SbSAvj5cum`%$_jO5Y(8>?w<H1OW~f&c&j07*qoM6N<$
Eg6)<Qi2wiq

diff --git a/civicrm/i/admin/small/rela_type.png b/civicrm/i/admin/small/rela_type.png
deleted file mode 100644
index 7a02c626e97316da9a208f9bb416b5b886982fca..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1917
zcmV-@2ZH#CP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00!SlL_t(Y
z$9<MrY+MHwhQGVbojaSy9((L~PvSUnHe1<~I!yvC3XrHsC80$?9|AO>f{>7+il_3>
zBE$>gDSc=WAP{s3LZ}ehMoQ8s`_`t^ZW71wIy3g{b7$^;FAp}*7K!t6bflyI*EvV$
zKS$y-wtFy6G$f{n`(s~Ql~%vquF2aY;5RIPu1ysK-3vaMo&tUZ3<I|S|Fd|~CxhXR
zFg4xl>}?Cb)YTq7(VA5D2yU>?*1b_IZ+^}V#*`%#3D^Ss6gUnf01Gex9q|5#pjVT)
zTXvM*nDTrop?p8ps)iIrq*il<dc{sThPO2YH)AkegZ;p-S@H_d3w#;)D$ov$0o6|t
zw21<OAFN8q!p~z-xkU+yICg+xd6cRyPQz>QU||l<0s$ZcJwOvM348?f1N(qZ;0$2>
zhoC<xvubtZ$=afGR1yT)51^sDv~_AA3oK+zl5L^t`mKq-1eTwx)V(WlReT7n@B?lG
z&jJ^K)ytLL0X~xdP4MKACL&R3dudBJoG%JkzKpDhjD9Y~xzjo5g>^eZTW;q3baP1Q
z7~T;-uFAq_Zr*5}%NT9C?SG*;9e!gxXPy9F1=h1%CII7ObtY$>{IMfV!HMVE1ve5$
zR3z%92JwnZ=e`gp|6G@EToy)ltc@K@C6t4TA_zv=p&|+-QtGcddn3wt&ipO#4<PfY
z88qfy=JWm`yX@@VJ!rEcVxXE8Vn&HI$vPLVJN)5vQ1k<Yge*Rx$f9f+9_50KVS04-
zMk10ZcBvw#7HX~tya!Yyfb|1$O0uBr+1R?Pt+VA3G3<(AtBjqmQYkbTUy%7Qn<5qu
zeP9@F+^D*1^r}Op<lu_}hoA1IwMFEEE9K}+$vI>A!5N?gAphp2Va6vaiGv4vez<n1
z=j-LVDNf$I$^*kC(Cheuh!~Hu_dqL89g=tc^>WT>ZI5wxS|E~$GQ2Ix_F<9CttsX|
z4m3N<ra@mge`$7UA?15x+2mIq>-x#Y4aw&s?M<4QjZ&zDzz8ViMVgx>qMA%t3)9jh
zE8A8p%E(R?k}U|Dh9tNMg#z(Jm2Z71m@?lDu5a#!OMhHyy}W%ed}MHibUYFYG*fSI
z^Lml<XI)Aem&sX|oqJP!=b81aX_tstWmd)oO5^jS`)VM{U^w8^vGNr&<hdtbyTG-!
z&;M5)<j$D$bV9P?n04NMXMwl=K8t{lq01OG0ZW&NDIyWk#xoi;Y?(WA5!O}~=#APa
zrccfjxR7tlyk6~`rK_NvNw-^YZAmJA@R;;sM^Z?Xb&pqmKgaa6f$s%W$_}BZM6GPm
z6msZpg=>WtCYyIrZ{LOyiXf+=<m4DvYb&{(dbG*z?;1^RX&x%tW~Ov`X0G+AO~_VN
z&r$KavQ-O5bm&>B;z|m+lEZh8rLpoAW-1NdTwIUVH%w1D&AMa~uik?eFCtnw<b=j5
zB_;+|t+O2CnL=C~ZGK_z^Z6IvJ0<NK@Mj#$!7!cnmTpzr|9FcWX;y{(yELBIFVig5
z7}t8J_m7Z{Cuj<5G(|L`;W)No(Xc!UW*kQdD0w#Jz!gfW-%^siO;&gGhIHx{_Y+?5
zxAAHBt$96E8}70;@9J%YH+NeY^LhVIV@dmJ$B5jVZYC;-sDgw51OjB{#wb+ExZzd`
zj>&>&vEZ64cs4~fX!T4tBp-h9RjyQP;WdK;2L}4u_Kf9UR-(Z<^0^u}iX+@w_hYJ5
zn8=P3N*jQH;W~sBg~dz_!!`-J8)RLReBh9qDv);?I6Yy3m~v2_&P;c0c;xY)4Q?Dd
zI@Ic@Dg7{!a3`8l#C)(*?1&vwYsDht**?mdvuy0Bk#tQ&%VTCNOAu2~+jVlD$(&^{
z_4db<`Za>SZji*ZtgRaQp4z+ms1%N<0X2NJ8^gbcWt$k<dPD&b1q`j5tFs#@O}~kh
z%Tu_Mp)i$a;2T?s8x`^uo%yp9<j+1Jcy=>_7X;YeLs<{UzFGEBvvn7lC{=ZU?Br==
zyUcWA1&fYB$+D<9Hf3Gp>MQRPOx-7N0|Z4PxcC6>%%YDiV&2U|cia;q@?0=eyU2L)
zHF?3ZyF)b{&-W?Y8i`N{Zz_#i$uP4uM7CC8R@W(*CSGbqz|fw%Oxz0teSzbVf9F2S
z$KC*LBMZL^W@@)N`Tjo{ZqwyrcJ^gE96elWNp&S-aUr58cz!RkUZhwkP%sV3mW^c^
z0oCFZy#v2k2Kyy24t%(*oHu|=OjI&V+*#6z`8ooFBQat0i#ybG*Q23me3ztY>wL%Q
zvZn9L!O9`mv8{)`Wj>^#pQE&Ro_Alr#`L`aIJW$%T;%`QzW~&yLQY*=>NNlW03v!+
zSaefwW^{L9a%BJjc-nJJ$xljE@XSq2PYp^<OsNC_FPsI`t_-P700000NkvXXu0mjf
DEPaC8

diff --git a/civicrm/i/admin/small/report_list.gif b/civicrm/i/admin/small/report_list.gif
deleted file mode 100644
index 328a91d78d547a6046e074a973895a779ce9e2c9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 828
zcmV-C1H=4BNk%v~VG{ru0LFg+YKNxq@bT>I?D6&b?eh4Jr@_|T<>>A5<mv9);p0VS
zih-QA#Kgnq>+pP*vf}3J`T6<b;o-f(!-k^0y1Ki{(A1=;t=HGrrL@N4+}u50ftIMg
zb&;*g%+7I)s^#V7xWv=d+1l>u?yIr5+~C~W+S*%sn}(RH>+kjQ^Y5Ocr`+7!<mlv6
za+S=_(c$6Tv$M1G`Sa-G>fz+z^X&5W_4d=%*4o$DyuH8t{`O;opGs_x>E-6BuCUS4
z((m!?_w?~OT7TWz+QGxf<>BJDy}!`Y)=+MgzrnxN+SKCV=Elm+(AM5qcAH&*n)mSY
z=Hlns+}l)hm-+Vk;oacb+SbX$%JK2_-{|sWfuvr1pjdL3Sb3DNwz}x+=-S%euDs1a
zVTEIVo%Z(e+}+yX<mZu|xsIQ%`1$@+ca~3al;`K?+TGvZ*xcsl<mcn#<K*G-_4S;e
zqfBy(R&kHU$H&ga#q;y@?d|RB>+9&~=<4d~?(_NY_4)Ai`Tzg_EC2ui022Ti000O6
zfP4>wgoI@X4StG?7b`0fkROthB^`^3j*%a0YkF%DYc78_i+z!udwP4Tc^^1`e?ESF
zrkkpHc)56ac`&e}w6=S=cme@ecY74Se;s`vs<{Dp0V#1QcnozBcd#LA!_)y!HB%{Q
z0SwwUoJM-M0ReX@2n7Wr1Y_~7YwpC;DL_oHmqLUa5ncrBaVIW7jT|5rESP`-O9BJC
z@)+48?#@FH4mdbCFt7lM4-1D)t5E|27!Mpc9FVvGg_nNs@Svzr;Q$5z9sr;a>7a%l
z8U6wkm@pATmMl6R0QHbZj}jx`ek}0dzyXF9Vw@xpqXU2*9x^IG^8%nPfDNK)OmHz^
zqOP7dO4NSHW5S7(EM}za*pWbui6&m4WN;DT0}m;4(zGz6AWWDL3XbfEpt!>$D4N44
zI1xsJ1{)emN05=ha|9|`Gz6i8A&6-bL2`#6a-&0|3=!BQh+wr0kq=4?g!mHS!jcsi
z*pMLcB0&P`31*OaQKEa5B{o*H8DFAJ1}ZD4jK9#GeVsZCBuGFazX%QrMeO6ifrJ75
GKma>*$<7S`

diff --git a/civicrm/i/admin/small/report_template.gif b/civicrm/i/admin/small/report_template.gif
deleted file mode 100644
index 3505bbda9ea1fe6910054902de829b5d38a0abc6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 833
zcmV-H1HSx6Nk%w1VHyA$0OoQ4|6u@vnU>Gf(|?weovp0i-rn!;@Amfg?Ck9E@$vfl
z`se58<KyGv;^OG&=<e?B|FD1m&9DE7K=kzV^78WS?d|`QQ2+Js>+9=^pPm0}5ai_K
z+2G*y_4VrN>gnm}|8*ed=H~41@8ICzj-j95-{1N9`A(IkRi?PP!ofgyfr_7;Qk}0!
zikC`_n^U5+|LfmPl%qs{i(9hD|HPl3u&!39yosKi<>=_EySYDfeM5YQoUE!^u*Iy}
z<xP~LM}?7Hw#-tVut$ZGKy`le^YifV@a5&@S+2r}otvw-w*TSJkE5Z9o}2ji`2VJG
zkD8I3t*gPv$K2rGkfWiXv9GGw<kQ;O*Vx#px3&NO|A?KM;o;%;_xIc3;Og-4hMSqw
z+1RqZyzA`j*xcKy*yEF@rH7oFf0mT(@9zJ9FqNjI<>%*&p`W(G!RYGh|GJO8$;kiz
z{{R30000000000000000000000000000000000000000000000A^8LW0043TEC2ui
z02%-q000O7fO3L^goTEN0Eqw~5*82<Fo%+Iii!c3n3<Sbh?M~cprKbaHC`R30iBiy
z2?=j*Z8$h-W~~XSg_Q)myu4!+QBxHa0T362Ac<%V8w(B}9v&YA0c>Ge4h{hT8peVW
ziCaew7zhsr4;2Io0c2DS4cmzzf)<HM4(16IMMV_r><FYNAP;~VK@bw%z+iyFgir<u
zJW#-HV8IB2Xe3(kAi;z#CPGf=6@Y{Qc@hRKNtD5WfR_S-1c52QzyKvYwrPkoh^3JU
zPADQlV!%fk12(0Q*oKi1xC{wsqCg>F#*CT+3WzCY=m~%fM!s0_VSoh-12$|R%}Vf4
z1OO|ZT=wW8;KT_5LWBsYz?O%ILjZ0dK=9%P0v9e2#E5|b16u((4q0g8LBNk60)PM!
z(4vKa4{QrCIYcALf(1i{AlR`3feaZTLa@a`;;*4I3<Ri9AwY)?0Yr!hV32i96%LZX
zj9?bR+36!28k882!?vWXC6+VT&Vb8^5(NezpCl&^lmY0|s~1mx&;<>NEF5b;366%Q
L^z-W%6bJx20KAp*

diff --git a/civicrm/i/admin/small/soft_credit_type.png b/civicrm/i/admin/small/soft_credit_type.png
deleted file mode 100644
index a1b1e10274b4cd1d15942d1277c62cfe4a9b3c6a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 489
zcmV<F0T%v=P)<h;3K|Lk000e1NJLTq000;O000;W1^@s7mv9Yk0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzi%CR5RCwBAV88}k)_6HE0_p!y{s({n
z!m0!;i>!<RAb@bHVt}gpkEGfFUGaHj1pom=96~mq37<l+x#~$;1wdK=CW!8KLm<w_
zsuSj1fB+)KLGzLMEX24R2oi}g*#WQbuwamz-y>m=(-iQ96Ug@mpg|-6jra$+6dNGf
zB!Dad5J1HE1w{iB5t`N$8?606ssQQ_{5Bvd27!shI0>ehVNb}m4a8_z0K|eo#f-#6
z+<u^wU<u8E*qDaJ?tdiOfl$%_Ww!f3+>e~;aAoEPNXftfDf3_e2OQ2L2w-`CJ-P%y
zfH5&p2ta8K8qrt*3k3!nKm*VLJ-Lx>0W@dq$5P;2pq3A?MaTnS3N6H?fz&uab}1-W
z41tC#;?n@~K?9QJ4_J~vD6?IF7J?gr1{#tYU;l~3?~%ej04Yn|hsH|)r4}G(L0AcW
zA1x2BN6HiX$+6%)nneOom)}P(abSfv3!XGAfF(H!AjOvfmQ<ApE&E6Y4FrNrfq{yk
f0qXL8ViW@aIgh=;Za`ZP00000NkvXXu0mjfJpsG2

diff --git a/civicrm/i/admin/small/template.png b/civicrm/i/admin/small/template.png
deleted file mode 100644
index 18f3c4fa21b9fd1ce187ecb8b3175ea453135280..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1248
zcmV<61Rwi}P)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00004XF*Lt007q5
z)K6G400006VoOIv0RI600RN!9r;`8x010qNS#tmY07w7;07w8v$!k6U00crwL_t(Y
z$DNbQZ<J*e#((F%eKXVP^d@xLf?SG}YeQ6QC~Bf6gapwIiZLNE@gE>A@So5aHwp_k
zZU}Kj+>i(XYq-P!0ydxmLhX&Vv`nWRX1<y4`(77Q6GLPWPVy%2;+*{QJkL3@xBrFj
z`kJ5L-Mz9UTPuYmVT6wpyyuxpDaAx#F}xE@9?X`qht1Bl>-O#H{g{<|wlZ?`BKI%c
zp=C=RlXXuI5vYt7nT$t*)Y_rfx~5hiHj>Jc+qQ<>E2~Kj-@`r#$-LEz>(1hnrz40K
z^lx(nLsi5Yf@Q6k?COn(PceOZ43}-AZD2joj3=2XKa)j9W$74Lj~>m?l+R=Cb%dOF
z?hHvS#^f!10~_!`jfH3dk!L{&m13FXcrV3GY0SCX=b4^A$(HU-T)O)Udk6QR@+Gd^
zJWD(mkvv5Zf?#us=9XpT;~p*-E@3>L_XhTHX!j=^JoYI{1gjM*#$pc4cM%x*UttSC
z3}+YSxtQ}P5uDbTz&Wl?T;a%1N4PV4iya*=<5dOY6`OO-EYBF~gal|n5+M#f!?hyT
zfD(^2U{cmGwJ^@m%^xY0XUGJOn${SlAoj#@jrmf6Uwt1nY(o`E0+Xr@nNL$p@~dWV
z^uKSEhW*?3abWvLe0lnFtPw<Oj1q`IJQT}we3k5B!oG;m*e{7e{s6S!neih#P0Cv4
zE7M$?xJWrFkaw+wN})xdIl;GheB{xU6gu05j~W_<UwTS|EZ)bYo#W5BVWt*Fn6DJr
zys{6kHAV!M33M$@jsTG-YZ3zcc!&VC2o|gL<uFDGZ)|*<H`l$x@!@ZAMp4tMZjp14
z)({v_9%W<p?|^}|^~nFL6mWe4zCM#cCBZmr&^qE_t$;P2l(W>7u3O|BWE=zro2!vs
zGsDl-h+CsPc6CLdSb<Eh!0ix|wvNAwSDE_#7UkLkJ?*bkRdog4IY_7Rfx$S)wj^Yn
zkkO{0MX`%%%Eg4vV~i2Dbq}(>eUNKYKM)wf$x;SO0GviCMOp>y=yddVq)7bIaXk{S
z61ZKgGJUs1gvJEc(4NiF*3?Q{wi#yvO0mIc0c#-@Kv2I6F_zO4Aw&174OcbxV6{an
zjnT2;?$l+*r*9BOC6;G45JpvWWI?I=6G4k2FpjP5h80b^p+z(0gv$>+i=r_1M`}mU
z9h<=W7!i$?0<lVx-l%I0!r(vBwSu%U<gBOF>4plzI3Z;`S}DvIpMCS;qYbAH?jnhj
z54_|DMF~pk-WsJDE<{|Pj~fEK2Q8{T)2Q)bC8AiW@~|A^eI4>@r)FJFHN58WQo^aJ
z`v0*2(NY;dKQ=viRVA}?RTcH<4nW^7Cd`Ju;VCavJ>IJ)07OodZ$9X^m5RThUh1r^
zYB{Mb%f~`tG;HV)f?%xF_k$<YyNA9fELA#NdpfQ(=iBo>dD6tcluXU>H`!aRWbnOb
z`2YX_B6?I<bW?9;ba!ELWdHzp+H*|FPfAtr%uP&B4N6T+sRRHooCVab45>{30000<
KMNUMnLSTX~5<YzZ

diff --git a/civicrm/i/admin/small/title.png b/civicrm/i/admin/small/title.png
deleted file mode 100644
index 3c2aa2403f065e15d03c49d82f0dc10326393b60..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1712
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
GLSTZJm^}6X

diff --git a/civicrm/i/admin/small/updatepath.png b/civicrm/i/admin/small/updatepath.png
deleted file mode 100644
index 293abb304b02676ba49db323e2a15cb832a7ec30..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3218
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
Ef-vzPivR!s

diff --git a/civicrm/i/admin/template.png b/civicrm/i/admin/template.png
deleted file mode 100644
index e3f348a9377589098a4cfab3a0861436a5e75a56..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1617
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
P00000NkvXXu0mjf-9hda

diff --git a/civicrm/i/admin/title.png b/civicrm/i/admin/title.png
deleted file mode 100644
index 71b94c4ecc41cb4de28b9e482555555f6e3e97dd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2300
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
Wp6(3^-6dE60000<MNUMnLSTX?UtVbd

diff --git a/civicrm/i/check.gif b/civicrm/i/check.gif
deleted file mode 100644
index 7e21249cb8bc055f172ea2eaace1d29e9fcf2650..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 519
zcmZ?wbhEHb6krfwIOfP;UTtVmV`N!tY*lAsRc~V5U~1E7X4_<L+idR8YU$qR5ID;-
zaE@otT(97H-XZh7!{_^lF7OFk=o`5pFnp0;)S{r6#lbO)Lt>YNL@f)9UmBLMEIe^}
zM9P}z^tCY=>*A6(L}sp!&)SfXwJ9NIQ&QU2=-kc8Y1?9Qw<PCoO)lG;U3nn4?nFuB
z$+FfHRm~?W8c&rqoholVS=Dy3vgve1>*>n2Gd1mJs@u=jbe^s4JXhCsuD<tNL-+am
z-t&$97n>$rYWY8uf#OdVMlObW1|0?<0L2LddrCunQ*%peTYE=`NN1~%nqp6rpo+bo
zbPvChovjRKC!eCVl{9;cx^^?KyrqQ{TZ^i(jbuHKoSCTvYpa5mgORd^zKIx1yQHR-
hxq+@Ib0@c~p^h-qL@sdw#)(ZF40j$pY-(h%1^}yFIgkJV

diff --git a/civicrm/i/copy.png b/civicrm/i/copy.png
deleted file mode 100644
index cd918ab1970cb5999e83eb462f9a8a62da196527..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 471
zcmV;|0Vw{7P)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt006O%
z3;baP00006VoOIv0RI600RN!9r;`8x010qNS#tmY3labT3lag+-G2N4000McNliru
z&<h?G3kjQl8J_?E0aQsuK~#90om4SygD@0*ROv=`GIX@mZZKrERCNhUPJ)b@xr0v-
z32p)lUZNhLLq;MpGUNapz#TBujtp*ik|q58{CNK%z6T%%u!9?d1C@)kQex~Mg5dp{
z6@3~Wj#5Gv1qvz0MJYwoG+>N@Qpy1Ac;As*@U`k+{C2(Kz3Z@7bwUV|BtaO4P@T+*
zdH^y2>?kEZ%M#_jmwK)$2qCPO@;uMAt&#1@<}e5Xd<g;bo&h6sj=yZjmM?MNMNJ64
z*Xxn|Xtt9X-q&BwXKZh`@oXwvr^BJ%MiG8C8{=#c)iIgj$>J~w0{Fg<Qy3ymQ`j&H
zUg8*WS)wKcwMH1~Z4{wZwT~<_MD&lh$l+RRyVLSs?9hNFZU`Pc4+rglF}B#D^><LY
zu!kLTpyD>78fl9%<d%`dmEhtGr*NOG3v+_@QRCoye1^dt!_>mBegPq#zw@=m;pYGV
N002ovPDHLkV1oa>z?uL6

diff --git a/civicrm/i/feed-icon.png b/civicrm/i/feed-icon.png
deleted file mode 100644
index fadd43ee1ddb28124bcd593e2051de8297a0acb6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1300
zcmV+v1?&2WP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00001b5ch_0Itp)
z=>Px(&PhZ;R5;6BluK-0#TCbY=gi!DKYxB;;>M0i3N*nAii?nvB4}kQ+De8Z5UNm+
z*tEbZVgWl?&_#AEK;p4RLVc)WmkNor>Y^oSX$uP!HIIhiI0kHN$B7-kzQ?^YbGo=+
z63T4m-g8F(`Jey)%#l;i-Zmh}&t2Yl8j%Nq91IXl3^4%11cW*R&`b1|VGvFI*%0Nu
zs<nO03-WlDH~!E+JVuszR0UB171V(!sIOz<1oet@iun3l-SzWOSuwS;v^}-**?)I?
z&5CCRhR1N_CSj`uL_`hm9b_K$j^q__g3A<~U|tZf;1yGW-o?4k866*Cb;hQ>h&+^K
z8C9!I$CSaJJVV|;OtpNTv~&)(7ja@Z2hIzUxgOK{GI4^4fC!c%4Id$fdpwY<3aHYJ
zF#f~C4D8;2L%r_hi<C1bu!|><E2mMly8Lf}BGR))0dfx@j=I!jh&aBviqU-(qx*;l
z4--E9J?X-6q_u!(hNuG9K?Tgf3^T($f8UOy1H;2mZQ&GR>l&TK^OURePz>Okw*a8N
zz<u{VWONd?7Le_QnvrS^3V=h3CX2HRcrerp&IyGx`1~)#nS^Pi<ulygDF*NV6^+{u
zqQ1c2b}woAb*jJp8n^T@n6DcyMl6&_y9FuXp8vtEM~6m+N#zzDQ~G}NOB(whBpV(j
zql;fTP3Qavbgs;i?>U6#O~e=I9aE&QPr>EW(A^?+wy^dF;&PVfSE)7Dx}-81je}3p
z+;tZK)$%#grITbA-lx2HjJ5U(gAct-V|)_L2eCs(2+L>S+E*mWv80H3%s@>H=LO9a
zmw7bryJ1{5c7Wo6BNUImL1X*?*~Rx+|MM$!*S@TE-+c%@aF}EnRv9Tms<>|6tw(o^
z?}W6C%api%m9RMv2HLm<aT(hD4u0|}^ve$kU;KmC`Wnr<r&0CD*d%f86XNPTDJtYc
ztSntYYsZz$3;o(AKlfYg_={}*<}ubjc$so-fnHnSr(dHnx}WOoF<P_#uEWI;I`J?u
zLJEcjutX1-0OeJryoRI>E`vTc(6hf|{rF3Cug=yWWA~CDe2#{9T>JYwHzd=EpOS(Q
zDkD^NJ1ayat|O^KJ0;o^zo2pC6wMbtqkrENdg)KBpLmm0w(3sZ_cQX*{d8wOq_c9V
z_G0H<(7%V+O~jtYN{Tp2aE_Mc3_bEHZpZhK!Ey2@-l6G@^6Ve!e0`>7H!^|SIf)Bh
zHZT0^<`dmDN$f^a1td@e#JL-zPh9qm2klTCuIkX9`{ZWnBNK?_lvn3(p4@eyW?Wup
zOm9v&N1ubukKQ77Hi@C6{O21W1zDaG7SB+wE>K;WCAGKlnqez*v=?XSESx89tdoN4
zNdfYoBfGobe_&6ZHWrD=C_@6tYNoLwnGk|eRS=^CGbBLl2Fl8jq7o}0CQ>)yhwoti
z^0`tirIYQgi1;Q>l!nX5F`NaG2^IxOibwG&p~0|VSaN6ri3tq}E5Y0#-KvYF^s%ox
zowt|fmiLa`xodCV&<J9JL`VrNf`r~4L8|&+0!RrOfB=@&u^75+tj*7cvi+`n^wdz1
z7dq{W;swwj8<v|HX4JDa)n?SAwzsEV?*C(@SvncZ_S=#0*Z%<?1yC{y;%*-R0000<
KMNUMnLSTX@1$FoU

diff --git a/civicrm/i/geotag_16.png b/civicrm/i/geotag_16.png
deleted file mode 100644
index 8df245699d4d0240e58e67287e0a043f0fcbe75b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 894
zcmV-^1A+XBP)<h;3K|Lk000e1NJLTq000mG000mO1^@s7X!Otb00004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#5J^NqRCwBA
zn8v`szLkODF~fQw@gE2P0*G-VkipKtz{K!k`SSm}85sTp1P}vAWDAgSSV97%;y)8J
zP+B7;h2iJNj|}S>85sZqh!LpyCJO@t7b61$!z%`c`3!4;%C`YA2pnc(`wwPa_4NFI
zEiMi$0g(a%kipA=7$AT^X59V8z@WqdGy`Zq1JDu%w;w+kj&pD@a01yZKnvKofeZl|
z83y~uj~U=VLW1Gr`}Yhi|AB1(|Nj{t*Vi-Ljf-RW3UuDbD_0mky?DX!8z{&0mVsfx
zbu%*tHlPWd*47L!Po89Wd+#2@XQ*`m0mQg~fuTu&fgzcRf#Dw$NC2b@i2pG#e0#{i
zpvS_-z)<@OD8L5A!nU>y5&;1W&x?zJeqy-B!U~mOf$COmYh&QIu>rgDZE-OhSOLf`
z=O<4X*rlbx60g^;Wq7)DDaaZIhI>6d|9^k@@c)#q?*Bg@KY{~kCoq7v12HhL9y2lh
z{>{L`&(HAt@@0lIT3QTWu3lyM3)J`%;!tovF<dk>WU%`Cm*MNJTMUOZHNpOeI-H5|
z7|<xi$&(rWF*7s#{`HIDVnG2|@;3yx00d~7iggl(qUfPk&}d7EVuFznFgSG}3{J8z
z7?>GcnEVaPWL)?N5+~wB(y(Eo#KeiX$wVF0MdM;xL6TxUuRcj%a+7zHckaFCoOjhr
z;5-Fbo@AlQq1DJeuItd*WjY*&c|sN#vw)HWPQT>icqCS32vOGz17^32BU+YgxA6_}
zFMwTQV>X$R)ZVf?M@^PW*sfLq-^Wg)fg~;bKeNdMiEI`R)cS2SdKDO?OcU$*Jmyqr
zMxQq_85CMAtZ3R2_|fa(k)Or)Jou7sXuB9C*KFd@wo!2$9CJ*AO5T(AxL(J?b;APh
z{XV7=>_==+!qF8)Yyn;@3wPWU(WSy%tJQGLLO1C&o;#foFpq@Dg$B-kxm-9H44_gh
zh+>g*TP(sQ??855NC!k?Zp>3mEH^J_TfhmSn|$~aNR<O=BO-b5N89@ZuDFU9zg}`A
U^mAafZvX%Q07*qoM6N<$f=b7W*#H0l

diff --git a/civicrm/i/grippie.png b/civicrm/i/grippie.png
deleted file mode 100644
index 6524d4167d2d6e3939cfcf3111ce520acd66bc21..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 162
zcmeAS@N?(olHy`uVBq!ia0vp^(m>40!3-puuch|@DVB6cUq=Rp^(V|(yIunMk|nMY
zCBgY=CFO}lsSJ)O`AMk?p1FzXsX?iUDV2pMQ*D5X*aCb)TzBu@{r~^}iVZzqfg(&L
zL4Lvi8J=!8@B;EgJY5_^DsCku9AK6xWM-3k!OUU6z#qV1KKathOF(%BPgg&ebxsLQ
E0Ke)mAOHXW

diff --git a/civicrm/i/group.png b/civicrm/i/group.png
deleted file mode 100644
index 6f7f75cbd11f2f50025daa3a07e5c505c8144a65..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 678
zcmV;X0$KfuP)<h;3K|Lk000e1NJLTq000yK000yS1^@s6jfou%00004XF*Lt006O%
z3;baP00006VoOIv0RI600RN!9r;`8x010qNS#tmY3labT3lag+-G2N4000McNliru
z&<p_*4GaJrd6NJD0wYO8K~#90t&=fq(?A%7zm$xiq*Q`Nf@X0&qzfJyVk{P*V#oqZ
zB?PWuiWoscLU=%^3m}y>4GU9<VCaxE5>aSbiGy0Q#FaXD@Ip~sIuwLpNaFa;4qbTC
z$-eLIp8k7xm#`33$>pAOyWKfJ0d!y!aE8MQpr=x)Fa3W1Gf=nSZFv0&BWiXTD3~T$
z^BQF4$=Ws=aIm<De*Xqc&mGMU+1VBx8qkdx_Li33G@H$nK;iu=JbbXjnXJO4i&s$6
z8`QSQ=JRm(-V1>N2QBzz40kal?N~8QDBRkC)B*sm+aPyg9@7LcgNb8?5;l+xb!`^*
z+y;AJUkU@-EI7^}O8;;-V8fgPB_+d6+e5!TtPJ3%zl-nnusu)|1=no|jKQG=3NoD8
z-hS7DyltZ?=?zX#C-{Bz9pCHWdhl!&G|gt=d_rKr2MeA@3;|j&1AMD(p(Ri4ll-yI
zM<-ZFCIe{%Rt7#9&<RYe!DkKl6K=Y$3*WdgsjXRZhQ9A3%kw;;uc|7=Vv$m*B(RZ$
zQ}#TMdc7WN*6DPR702XjL$z9st!%`PWAe4ZaVi)_B{FfKrvR+1+>Ee^h5(OmgDV!u
z>v0m?xf*3730qcGm3CV+IX8F>wA<tG<Ct7wI1G~sdi99W>j<kH_Lu^&pk~3cJTqMF
zsIqcdo&^>xTTlxO|EFRPWxez7|Mlqg3zV=z9c%CeCuTT7Wh)fdUvI<W?E09jLjV8(
M07*qoM6N<$f+BezHUIzs

diff --git a/civicrm/i/ical_feed.gif b/civicrm/i/ical_feed.gif
deleted file mode 100644
index e31788a7713c1e3921f0b8cdf99664695b38c9f9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 683
zcmZ?wbhEHbRAJy_c*elMa7Fyn-_Hy-%rkz?Wmsm*@Lh?af_vkq9SkQF9rxxs-V56J
z>@dTAO@__Jh36(2+;wI+s(k6=t-|NE45#G<uB$R!lv225^61C2z=sKmPx1o~S2e!s
zz4ZMW!y1dklWh}kuQJ#Z%do+eVYfDeJTt>N8HSk>jo0QDUhOS>(9C_uxbRlTp-(3Z
zFHLZ~8#3|j>_^|9GaOR8^!0|oG2=(So=$wSxbSIx<JEbN*CG}6_!#U+47`%_=;zbG
z^Z9{yQylka3v6-~*kw2I&dNh?&M*A1>iD0d3m<F)`e_IO#h)x-*Xn>sP@FKZ|8H<%
zZf<F9Ywu{+WM$~>>z^=j(nPkN$-Vqs{L|+!Ozjn7T*Np-X0i2b28l%yee8@}Q>Jm5
zFbeXqh#52LaLNhV2{Sk^auw)Z&&e@iey=$rw=9n|qZ$hjhmk#p2&1?@qr(ZtQ)i|z
za9!YKIH}YpDk{k+@5m@8`sT^${<AM${d_97_tF7oDV~PkGGD#7C&-#g|JDfDV2~xk
z*YZqCvmo&`3j?<}(~5uzjn3Ut7i26V1P(BEhRX+dOjvLsXhk3o!<P;NEw&C(MiY~S
z1<DNqZ0oh2eJSZ<Y+TMF<;XBmfxVGW*h#>Gje)6AfI-Tk_STB~OF21ON++c(XldA9
Q!14IhT<`LC9S#iE0H<osKL7v#

diff --git a/civicrm/i/office-calendar.png b/civicrm/i/office-calendar.png
deleted file mode 100644
index 60ad82b236e3414dfbadaff7853deacc9d918ed5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 807
zcmV+?1K9kDP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00006VoOIv0EhsJ
z0EG#qsnq}g010qNS#tmY3labT3lag+-G2N4000McNliru)&~U&8WzMOv+Mu>06ug@
zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj1+3MgYKATls8GayP~Yjt8ECu(VJ
zZDC_4AX9W@X>Mh5Co}I@0007NNkl<ZILoz_&r1|x7{@>J&W^IOo94zGItU^K9yFZk
zX4mZxFk*?wlOENZ3~At@pi&U&79L_FLc}_F5xR;Sq;4ghVhKc0VqnzW1=*b)JGAex
z&W=A?>4D*y_nG(oyx)1A=beH7WD3Cj)V<fh@FiJK7Z;YE$U&s)hv#NrQ7jf4raqpu
zCV@IInx?V0x7QFf8jaS)d~l&qpslT~A+V~dr-Kg;4#;FO|5hMHA(2R+>v}lYG!44D
zyNSo+c%J7kl3rfHxJ+Rz7Q-|R78jO$um~y$gI@G`Xew$Kp9MHeeXWHmPNh=x_xID=
z+so+aD4yq`C<@7B62ma)=;-h}==k{fVqhTz>2#V*Cd0_c2rDZqet$17FEc$oePX`c
z^xRYcWV2bu#>TL1o1vj0T3cID6or<SmO4matOLJ86}zsBX_~CBuVYyj^YimKjuV<o
zMN!Z+4Iu<Zp9ygNRK@%I`wR>WP%4!ul}Zc_4$|J<4nR*&53cJ1kW41Y<#GVnwvEwu
zn|JTuW*<IybPM=i2iA3+)z#I|R@>UzA`<z#q`A2nfTpG<G)?31@Q|*~8}{>;&%RmX
z6G|lbYO=}_DnY8M`Y|B{uIu{not+(u#Ui<1Kd)Ki6L)1QM6Fs`<w~Uj;QMm9?01c-
zs(7A<<2dZ@?vl^v+5GwiYkXoD_;dn1J2!KwkMYLFCcvAz;&pZ2<ml+=+*2ogxm-pF
zf#W!AZ*Nnnct3)D?5(YRo&u&CReLpYg%2-2-T}N5zozO2F(6*`YS_uFF$t&u1t4Gb
lZV)UXA^<xNEbqNQj6cvC&Sd$l659X(002ovPDHLkV1iZiWs?8^

diff --git a/civicrm/i/stop-icon.png b/civicrm/i/stop-icon.png
deleted file mode 100644
index e00eea441f7bf8d0e9b1b51a617e36d47405c6f1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 595
zcmV-Z0<8UsP)<h;3K|Lk000e1NJLTq000jF000jN1^@s6JJyv-0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz^+`lQRCwBA{Qv(y13Ea%$mGg^39cLe
z|Mvu0fCWvHB41+SJ!UCM1|}f?KLaCF=05|gqXS4@7TEwsn9U%Kym7JjJ}p|rfDM3*
z;Rp+7__1mg+yJm<WQ~k)+pvNEC<cHv-%d*Y|9<{Fur@}p5`=C4p)?5pgNk!UMlyU~
zzCxA-6gVv6;tb+>c?|5zN(?{m-ecg@(qj1c=MTfXdGi>AlM)%eU%$cddCL|C$&Plg
z=9lG_AW9PyE)48SN(_S0Q4H@EEMoYuc{2ltp#j6Yx$_ugrcYydJ9j>VP+Tknvyd<Y
zySzNZ_X`&p_<ViAhJZEydiapx<HpSl67_Wq|Gs<$OR&kvFnl|D6wLm0?;e9-csRt#
z=H?7PZ{J2l6%#i%!<PdG7&tXG82H^iApT`#V_=b#gap&iUkvY8t^~SJk>OE6Ap`T@
zzX+TE|NhM&5a0(?^n>Bk?ww$XpZD)EJk2j)5GyKV_<rRo!~b7D8CYec8Gb!`%E0*V
zA0nQw#l-yox^yYrwEt+KjtoHZ%)ucHf7Y&*1>5|6=`vaF@Cb-Az%k7Trx6gMk;y**
ztPvj1&=e-a84>>Y`-&BCn-NI^rqQ3_@5W82DGVuX%W%a+KmN0KFNXGiR@QJEG14}&
h0iXmxOs)b5FaTjm*1nmHHmCpq002ovPDHLkV1lX93f2Gs

diff --git a/civicrm/i/tel.gif b/civicrm/i/tel.gif
deleted file mode 100644
index c8b0e4d9ad4355fdc5bc794fe74c77ddd3aeadfa..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 617
zcmaix?Jv{;0LOpb-S6%=r}LCVh*gs1^kC$ehjpSfl62C8BT{lYEt+ZixzjwX*rmLR
zwWV$y)7_M|mabVlyCYuoz}!?fW{%p8<afAl=^yC(;`8eB=Cf~dia07dPe2HWX@UR{
zBKy6k2I3Cf8AYo~Wi*bN&E^R^9Dth)V>V>zFgyd(Pw2ne9*kpU4SrSV8pqM65Vb&}
zg`gPeO(^O_q6#}Ikf%X;HyRD#=P!p>&^1Q9utKlzZ~p+@6x#F<WLasNKBvaqoGqyx
z{htxqf-cjK$$3mIfS0qR{RE@Y7~hP*QdlhCM&=RMhTwX*6s+cUBIf3ZU*U>S38fai
z+$C`<$_C&fS;+3eyJ@ILQPMhlu@k@SYd18|7%;yGRqtAGB}_v$(+uwFR;sJ3pS>JY
zyoO}~q6U2Yn>I<`t~b*()Z;K<ac~L|O7srdd%hr20m&mc9I#rETIUETg|F1E&_VVb
z!s|=&CwTa3x$irqeaL8X2&<6UjmkHOy^q9uApW;)H0z%dw$AlW2+sQ&f~r+0DW@|T
zKKrk2k(FJ_OAB)%@{3PgJ?mK>743WQa!hQX8?zuQvG73Lu_Eu(oS@wSBBn5W)5%?>
zTcv&;JP)SxP9{t4fBp!E!`>&^ewyJN;qK*mg`YXhW|RCwjQAvm`-OB@4iOp>N%CC1
zHYB@=4`*|O$yM?=m(LLSELzwUxzWE*_?Em?Pt>{_xCs=&YGmz|a+?cAyn~pVUAQS)
hav-6E;+`6mKc-YvTZdD;t}rdEPCh%45+WdC{s4~{HWdH>

diff --git a/civicrm/install/civicrm.php b/civicrm/install/civicrm.php
index 0932b1902b..ed2df94303 100644
--- a/civicrm/install/civicrm.php
+++ b/civicrm/install/civicrm.php
@@ -200,7 +200,7 @@ function civicrm_config(&$config) {
   global $tplPath, $installType;
 
   // Ex: $extraSettings[] = '$civicrm_settings["domain"]["foo"] = "bar";';
-  $extraSettings = array();
+  $extraSettings = [];
 
   $params = array(
     'crmRoot' => $crmPath,
diff --git a/civicrm/js/Common.js b/civicrm/js/Common.js
index f4c2a60a6f..0ed3e38c67 100644
--- a/civicrm/js/Common.js
+++ b/civicrm/js/Common.js
@@ -387,7 +387,7 @@ if (!CRM.vars) CRM.vars = {};
       description = row.description || $(row.element).data('description'),
       ret = '';
     if (icon) {
-      ret += '<i class="crm-i ' + icon + '"></i> ';
+      ret += '<i class="crm-i ' + icon + '" aria-hidden="true"></i> ';
     }
     if (color) {
       ret += '<span class="crm-select-item-color" style="background-color: ' + color + '"></span> ';
@@ -395,6 +395,35 @@ if (!CRM.vars) CRM.vars = {};
     return ret + _.escape(row.text) + (description ? '<div class="crm-select2-row-description"><p>' + _.escape(description) + '</p></div>' : '');
   }
 
+  /**
+   * Helper to generate an icon with alt text.
+   *
+   * See also smarty `{icon}` and CRM_Core_Page::crmIcon() functions
+   *
+   * @param string icon
+   *   The Font Awesome icon class to use.
+   * @param string text
+   *   Alt text to display.
+   * @param mixed condition
+   *   This will only display if this is truthy.
+   *
+   * @return string
+   *   The formatted icon markup.
+   */
+  CRM.utils.formatIcon = function (icon, text, condition) {
+    if (typeof condition !== 'undefined' && !condition) {
+      return '';
+    }
+    var title = '';
+    var sr = '';
+    if (text) {
+      text = _.escape(text);
+      title = ' title="' + text + '"';
+      sr = '<span class="sr-only">' + text + '</span>';
+    }
+    return '<i class="crm-i ' + icon + '"' + title + ' aria-hidden="true"></i>' + sr;
+  };
+
   /**
    * Wrapper for select2 initialization function; supplies defaults
    * @param options object
@@ -434,7 +463,7 @@ if (!CRM.vars) CRM.vars = {};
             placeholder = settings.placeholder || $el.data('placeholder') || $el.attr('placeholder') || $('option[value=""]', $el).text();
           if (m.length && placeholder === m) {
             iconClass = $el.attr('class').match(/(fa-\S*)/)[1];
-            out = '<i class="crm-i ' + iconClass + '"></i> ' + out;
+            out = '<i class="crm-i ' + iconClass + '" aria-hidden="true"></i> ' + out;
           }
           return out;
         };
@@ -704,7 +733,7 @@ if (!CRM.vars) CRM.vars = {};
     }
     _.each(createLinks, function(link) {
       markup += ' <a class="crm-add-entity crm-hover-button" href="' + link.url + '">' +
-        '<i class="crm-i ' + (link.icon || 'fa-plus-circle') + '"></i> ' +
+        '<i class="crm-i ' + (link.icon || 'fa-plus-circle') + '" aria-hidden="true"></i> ' +
         _.escape(link.label) + '</a>';
     });
     markup += '</div>';
diff --git a/civicrm/js/crm.datepicker.js b/civicrm/js/crm.datepicker.js
index e1a15f85d0..95663c0949 100644
--- a/civicrm/js/crm.datepicker.js
+++ b/civicrm/js/crm.datepicker.js
@@ -29,7 +29,7 @@
         type = hasDatepicker ? 'text' : 'number';
 
       if (settings.allowClear !== undefined ? settings.allowClear : !$dataField.is('.required, [required]')) {
-        $clearLink = $('<a class="crm-hover-button crm-clear-link" title="'+ _.escape(ts('Clear')) +'"><i class="crm-i fa-times"></i></a>')
+        $clearLink = $('<a class="crm-hover-button crm-clear-link" title="'+ _.escape(ts('Clear')) +'"><i class="crm-i fa-times" aria-hidden="true"></i></a>')
           .insertAfter($dataField);
       }
       if (settings.time !== false) {
diff --git a/civicrm/js/crm.drupal7.js b/civicrm/js/crm.drupal7.js
new file mode 100644
index 0000000000..8f172f23b9
--- /dev/null
+++ b/civicrm/js/crm.drupal7.js
@@ -0,0 +1,18 @@
+// https://civicrm.org/licensing
+(function($) {
+  "use strict";
+
+  $(document).on('crmLoad', '#civicrm-menu', hideMenuToggleButtonForNonAdminUsers);
+
+  /**
+   * Hides the Menu Toggle Button when the Admin Menu is not available for the user.
+   */
+  function hideMenuToggleButtonForNonAdminUsers() {
+    $(document).ready(function() {
+      if (!$('#toolbar').length) {
+        CRM.menubar.removeToggleButton();
+      }
+    });
+  }
+
+})(CRM.$);
diff --git a/civicrm/js/crm.menubar.js b/civicrm/js/crm.menubar.js
index eba37ed3c4..d28f098349 100644
--- a/civicrm/js/crm.menubar.js
+++ b/civicrm/js/crm.menubar.js
@@ -8,6 +8,7 @@
     data: null,
     settings: {collapsibleBehavior: 'accordion'},
     position: 'over-cms-menu',
+    toggleButton: true,
     attachTo: (CRM.menubar && CRM.menubar.position === 'above-crm-container') ? '#crm-container' : 'body',
     initialize: function() {
       var cache = CRM.cache.get('menubar');
@@ -231,17 +232,24 @@
       }
     },
     initializePosition: function() {
-      if (CRM.menubar.position === 'over-cms-menu' || CRM.menubar.position === 'below-cms-menu') {
+      if (CRM.menubar.toggleButton && (CRM.menubar.position === 'over-cms-menu' || CRM.menubar.position === 'below-cms-menu')) {
         $('#civicrm-menu')
           .on('click', 'a[href="#toggle-position"]', function(e) {
             e.preventDefault();
             CRM.menubar.togglePosition();
           })
-          .append('<li id="crm-menubar-toggle-position"><a href="#toggle-position" title="' + ts('Adjust menu position') + '"><i class="crm-i fa-arrow-up"></i></a>');
+          .append('<li id="crm-menubar-toggle-position"><a href="#toggle-position" title="' + ts('Adjust menu position') + '"><i class="crm-i fa-arrow-up" aria-hidden="true"></i></a>');
         CRM.menubar.position = CRM.cache.get('menubarPosition', CRM.menubar.position);
       }
       $('body').addClass('crm-menubar-visible crm-menubar-' + CRM.menubar.position);
     },
+    removeToggleButton: function() {
+      $('#crm-menubar-toggle-position').remove();
+      CRM.menubar.toggleButton = false;
+      if (CRM.menubar.position === 'below-cms-menu') {
+        CRM.menubar.togglePosition();
+      }
+    },
     initializeResponsive: function() {
       var $mainMenuState = $('#crm-menubar-state');
       // hide mobile menu beforeunload
@@ -357,10 +365,6 @@
         var $selection = $('.crm-quickSearchField input:checked'),
           label = $selection.parent().text(),
           value = $selection.val();
-        // These fields are not supported by advanced search
-        if (!value || value === 'first_name' || value === 'last_name') {
-          value = 'sort_name';
-        }
         $('#crm-qsearch-input').attr({name: value, placeholder: '\uf002 ' + label});
       }
       $('.crm-quickSearchField').click(function() {
diff --git a/civicrm/js/jquery/jquery.crmEditable.js b/civicrm/js/jquery/jquery.crmEditable.js
index b68b27f0a2..7d0da65ba1 100644
--- a/civicrm/js/jquery/jquery.crmEditable.js
+++ b/civicrm/js/jquery/jquery.crmEditable.js
@@ -108,10 +108,10 @@
 
       var settings = {
         tooltip: $i.data('tooltip') || ts('Click to edit'),
-        placeholder: $i.data('placeholder') || '<i class="crm-i fa-pencil crm-editable-placeholder"></i>',
+        placeholder: $i.data('placeholder') || '<i class="crm-i fa-pencil crm-editable-placeholder" aria-hidden="true"></i>',
         onblur: 'cancel',
-        cancel: '<button type="cancel"><i class="crm-i fa-times"></i></button>',
-        submit: '<button type="submit"><i class="crm-i fa-check"></i></button>',
+        cancel: '<button type="cancel"><i class="crm-i fa-times" aria-hidden="true"></i></button>',
+        submit: '<button type="submit"><i class="crm-i fa-check" aria-hidden="true"></i></button>',
         cssclass: 'crm-editable-form',
         data: getData,
         onreset: restoreContainer
diff --git a/civicrm/js/jquery/jquery.crmIconPicker.js b/civicrm/js/jquery/jquery.crmIconPicker.js
index 19f50f6b22..2cc4bd536c 100644
--- a/civicrm/js/jquery/jquery.crmIconPicker.js
+++ b/civicrm/js/jquery/jquery.crmIconPicker.js
@@ -90,7 +90,7 @@
             '<div class="icon-ctrls crm-clearfix">' +
             '<input class="crm-form-text" name="search" placeholder="&#xf002"/>' +
             '<select class="crm-form-select"></select>' +
-            '<button type="button" class="cancel" title=""><i class="crm-i fa-ban"></i> ' + ts('No icon') + '</button>' +
+            '<button type="button" class="cancel" title=""><i class="crm-i fa-ban" aria-hidden="true"></i> ' + ts('No icon') + '</button>' +
             '</div>' +
             '<div class="icons"></div>'
           );
diff --git a/civicrm/js/jquery/jquery.dashboard.js b/civicrm/js/jquery/jquery.dashboard.js
index b757e27f6c..4191285449 100644
--- a/civicrm/js/jquery/jquery.dashboard.js
+++ b/civicrm/js/jquery/jquery.dashboard.js
@@ -364,7 +364,7 @@
 
       // Adds controls to a widget.  id is for internal use and image file name in images/dashboard/ (a .gif).
       widget.addControl = function(id, control) {
-          var markup = '<a class="crm-i ' + control.icon + '" alt="' + control.description + '" title="' + control.description + '"></a>';
+          var markup = '<a class="crm-i ' + control.icon + '" alt="' + control.description + '" title="' + control.description + '" aria-hidden="true"></a>';
           control.element = $(markup).prependTo($('.widget-controls', widget.element)).click(control.callback);
       };
 
diff --git a/civicrm/js/view/crm.designer.js b/civicrm/js/view/crm.designer.js
index 9d43b92bf0..b00a2964f1 100644
--- a/civicrm/js/view/crm.designer.js
+++ b/civicrm/js/view/crm.designer.js
@@ -675,7 +675,7 @@
       });
       var form1 = CRM.loadForm(url)
         .on('crmFormLoad', function() {
-          $(this).prepend('<div class="messages status"><i class="crm-i fa-info-circle"></i> ' + ts('Note: This will modify the field system-wide, not just in this profile form.') + '</div>');
+          $(this).prepend('<div class="messages status"><i class="crm-i fa-info-circle" aria-hidden="true"></i> ' + ts('Note: This will modify the field system-wide, not just in this profile form.') + '</div>');
         });
     },
     onChangeIsDuplicate: function(model, value, options) {
diff --git a/civicrm/package.json b/civicrm/package.json
index f3abb57f52..0dffff7c40 100644
--- a/civicrm/package.json
+++ b/civicrm/package.json
@@ -12,7 +12,7 @@
     "bower": "^1.8.8",
     "civicrm-cv": "^0.1.2",
     "jasmine-core": "~3.3.0",
-    "karma": "^4.1.0",
+    "karma": "^5.0.9",
     "karma-jasmine": "~2.0.1",
     "karma-ng-html2js-preprocessor": "^1.0.0",
     "karma-phantomjs-launcher": "^1.0.4"
diff --git a/civicrm/packages/HTTP/Request.php b/civicrm/packages/HTTP/Request.php
deleted file mode 100644
index 230a6a6ea7..0000000000
--- a/civicrm/packages/HTTP/Request.php
+++ /dev/null
@@ -1,1521 +0,0 @@
-<?php
-/**
- * Class for performing HTTP requests
- *
- * PHP versions 4 and 5
- *
- * LICENSE:
- *
- * Copyright (c) 2002-2007, Richard Heyes
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * o Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * o Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * o The names of the authors may not be used to endorse or promote
- *   products derived from this software without specific prior written
- *   permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category    HTTP
- * @package     HTTP_Request
- * @author      Richard Heyes <richard@phpguru.org>
- * @author      Alexey Borzov <avb@php.net>
- * @copyright   2002-2007 Richard Heyes
- * @license     http://opensource.org/licenses/bsd-license.php New BSD License
- * @version     CVS: $Id: Request.php,v 1.63 2008/10/11 11:07:10 avb Exp $
- * @link        http://pear.php.net/package/HTTP_Request/
- */
-
-/**
- * PEAR and PEAR_Error classes (for error handling)
- */
-require_once 'PEAR.php';
-/**
- * Socket class
- */
-require_once 'Net/Socket.php';
-/**
- * URL handling class
- */
-require_once 'Net/URL.php';
-
-/**#@+
- * Constants for HTTP request methods
- */
-define('HTTP_REQUEST_METHOD_GET',     'GET',     true);
-define('HTTP_REQUEST_METHOD_HEAD',    'HEAD',    true);
-define('HTTP_REQUEST_METHOD_POST',    'POST',    true);
-define('HTTP_REQUEST_METHOD_PUT',     'PUT',     true);
-define('HTTP_REQUEST_METHOD_DELETE',  'DELETE',  true);
-define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true);
-define('HTTP_REQUEST_METHOD_TRACE',   'TRACE',   true);
-/**#@-*/
-
-/**#@+
- * Constants for HTTP request error codes
- */
-define('HTTP_REQUEST_ERROR_FILE',             1);
-define('HTTP_REQUEST_ERROR_URL',              2);
-define('HTTP_REQUEST_ERROR_PROXY',            4);
-define('HTTP_REQUEST_ERROR_REDIRECTS',        8);
-define('HTTP_REQUEST_ERROR_RESPONSE',        16);
-define('HTTP_REQUEST_ERROR_GZIP_METHOD',     32);
-define('HTTP_REQUEST_ERROR_GZIP_READ',       64);
-define('HTTP_REQUEST_ERROR_GZIP_DATA',      128);
-define('HTTP_REQUEST_ERROR_GZIP_CRC',       256);
-/**#@-*/
-
-/**#@+
- * Constants for HTTP protocol versions
- */
-define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true);
-define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true);
-/**#@-*/
-
-if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
-   /**
-    * Whether string functions are overloaded by their mbstring equivalents
-    */
-    define('HTTP_REQUEST_MBSTRING', true);
-} else {
-   /**
-    * @ignore
-    */
-    define('HTTP_REQUEST_MBSTRING', false);
-}
-
-/**
- * Class for performing HTTP requests
- *
- * Simple example (fetches yahoo.com and displays it):
- * <code>
- * $a = &new HTTP_Request('http://www.yahoo.com/');
- * $a->sendRequest();
- * echo $a->getResponseBody();
- * </code>
- *
- * @category    HTTP
- * @package     HTTP_Request
- * @author      Richard Heyes <richard@phpguru.org>
- * @author      Alexey Borzov <avb@php.net>
- * @version     Release: 1.4.4
- */
-class HTTP_Request
-{
-   /**#@+
-    * @access private
-    */
-    /**
-    * Instance of Net_URL
-    * @var Net_URL
-    */
-    var $_url;
-
-    /**
-    * Type of request
-    * @var string
-    */
-    var $_method;
-
-    /**
-    * HTTP Version
-    * @var string
-    */
-    var $_http;
-
-    /**
-    * Request headers
-    * @var array
-    */
-    var $_requestHeaders;
-
-    /**
-    * Basic Auth Username
-    * @var string
-    */
-    var $_user;
-
-    /**
-    * Basic Auth Password
-    * @var string
-    */
-    var $_pass;
-
-    /**
-    * Socket object
-    * @var Net_Socket
-    */
-    var $_sock;
-
-    /**
-    * Proxy server
-    * @var string
-    */
-    var $_proxy_host;
-
-    /**
-    * Proxy port
-    * @var integer
-    */
-    var $_proxy_port;
-
-    /**
-    * Proxy username
-    * @var string
-    */
-    var $_proxy_user;
-
-    /**
-    * Proxy password
-    * @var string
-    */
-    var $_proxy_pass;
-
-    /**
-    * Post data
-    * @var array
-    */
-    var $_postData;
-
-   /**
-    * Request body
-    * @var string
-    */
-    var $_body;
-
-   /**
-    * A list of methods that MUST NOT have a request body, per RFC 2616
-    * @var array
-    */
-    var $_bodyDisallowed = array('TRACE');
-
-   /**
-    * Methods having defined semantics for request body
-    *
-    * Content-Length header (indicating that the body follows, section 4.3 of
-    * RFC 2616) will be sent for these methods even if no body was added
-    *
-    * @var array
-    */
-    var $_bodyRequired = array('POST', 'PUT');
-
-   /**
-    * Files to post
-    * @var array
-    */
-    var $_postFiles = array();
-
-    /**
-    * Connection timeout.
-    * @var float
-    */
-    var $_timeout;
-
-    /**
-    * HTTP_Response object
-    * @var HTTP_Response
-    */
-    var $_response;
-
-    /**
-    * Whether to allow redirects
-    * @var boolean
-    */
-    var $_allowRedirects;
-
-    /**
-    * Maximum redirects allowed
-    * @var integer
-    */
-    var $_maxRedirects;
-
-    /**
-    * Current number of redirects
-    * @var integer
-    */
-    var $_redirects;
-
-   /**
-    * Whether to append brackets [] to array variables
-    * @var bool
-    */
-    var $_useBrackets = true;
-
-   /**
-    * Attached listeners
-    * @var array
-    */
-    var $_listeners = array();
-
-   /**
-    * Whether to save response body in response object property
-    * @var bool
-    */
-    var $_saveBody = true;
-
-   /**
-    * Timeout for reading from socket (array(seconds, microseconds))
-    * @var array
-    */
-    var $_readTimeout = null;
-
-   /**
-    * Options to pass to Net_Socket::connect. See stream_context_create
-    * @var array
-    */
-    var $_socketOptions = null;
-   /**#@-*/
-
-    /**
-    * Constructor
-    *
-    * Sets up the object
-    * @param    string  The url to fetch/access
-    * @param    array   Associative array of parameters which can have the following keys:
-    * <ul>
-    *   <li>method         - Method to use, GET, POST etc (string)</li>
-    *   <li>http           - HTTP Version to use, 1.0 or 1.1 (string)</li>
-    *   <li>user           - Basic Auth username (string)</li>
-    *   <li>pass           - Basic Auth password (string)</li>
-    *   <li>proxy_host     - Proxy server host (string)</li>
-    *   <li>proxy_port     - Proxy server port (integer)</li>
-    *   <li>proxy_user     - Proxy auth username (string)</li>
-    *   <li>proxy_pass     - Proxy auth password (string)</li>
-    *   <li>timeout        - Connection timeout in seconds (float)</li>
-    *   <li>allowRedirects - Whether to follow redirects or not (bool)</li>
-    *   <li>maxRedirects   - Max number of redirects to follow (integer)</li>
-    *   <li>useBrackets    - Whether to append [] to array variable names (bool)</li>
-    *   <li>saveBody       - Whether to save response body in response object property (bool)</li>
-    *   <li>readTimeout    - Timeout for reading / writing data over the socket (array (seconds, microseconds))</li>
-    *   <li>socketOptions  - Options to pass to Net_Socket object (array)</li>
-    * </ul>
-    * @access public
-    */
-    function __construct($url = '', $params = array())
-    {
-        $this->_method         =  HTTP_REQUEST_METHOD_GET;
-        $this->_http           =  HTTP_REQUEST_HTTP_VER_1_1;
-        $this->_requestHeaders = array();
-        $this->_postData       = array();
-        $this->_body           = null;
-
-        $this->_user = null;
-        $this->_pass = null;
-
-        $this->_proxy_host = null;
-        $this->_proxy_port = null;
-        $this->_proxy_user = null;
-        $this->_proxy_pass = null;
-
-        $this->_allowRedirects = false;
-        $this->_maxRedirects   = 3;
-        $this->_redirects      = 0;
-
-        $this->_timeout  = null;
-        $this->_response = null;
-
-        foreach ($params as $key => $value) {
-            $this->{'_' . $key} = $value;
-        }
-
-        if (!empty($url)) {
-            $this->setURL($url);
-        }
-
-        // Default useragent
-        $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )');
-
-        // We don't do keep-alives by default
-        $this->addHeader('Connection', 'close');
-
-        // Basic authentication
-        if (!empty($this->_user)) {
-            $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass));
-        }
-
-        // Proxy authentication (see bug #5913)
-        if (!empty($this->_proxy_user)) {
-            $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass));
-        }
-
-        // Use gzip encoding if possible
-        if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) {
-            $this->addHeader('Accept-Encoding', 'gzip');
-        }
-    }
-
-    /**
-    * Generates a Host header for HTTP/1.1 requests
-    *
-    * @access private
-    * @return string
-    */
-    function _generateHostHeader()
-    {
-        if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) {
-            $host = $this->_url->host . ':' . $this->_url->port;
-
-        } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) {
-            $host = $this->_url->host . ':' . $this->_url->port;
-
-        } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) {
-            $host = $this->_url->host . ':' . $this->_url->port;
-
-        } else {
-            $host = $this->_url->host;
-        }
-
-        return $host;
-    }
-
-    /**
-    * Resets the object to its initial state (DEPRECATED).
-    * Takes the same parameters as the constructor.
-    *
-    * @param  string $url    The url to be requested
-    * @param  array  $params Associative array of parameters
-    *                        (see constructor for details)
-    * @access public
-    * @deprecated deprecated since 1.2, call the constructor if this is necessary
-    */
-    function reset($url, $params = array())
-    {
-        $this->__construct($url, $params);
-    }
-
-    /**
-    * Sets the URL to be requested
-    *
-    * @param  string The url to be requested
-    * @access public
-    */
-    function setURL($url)
-    {
-        $this->_url = new Net_URL($url, $this->_useBrackets);
-
-        if (!empty($this->_url->user) || !empty($this->_url->pass)) {
-            $this->setBasicAuth($this->_url->user, $this->_url->pass);
-        }
-
-        if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) {
-            $this->addHeader('Host', $this->_generateHostHeader());
-        }
-
-        // set '/' instead of empty path rather than check later (see bug #8662)
-        if (empty($this->_url->path)) {
-            $this->_url->path = '/';
-        }
-    }
-
-   /**
-    * Returns the current request URL
-    *
-    * @return   string  Current request URL
-    * @access   public
-    */
-    function getUrl()
-    {
-        return empty($this->_url)? '': $this->_url->getUrl();
-    }
-
-    /**
-    * Sets a proxy to be used
-    *
-    * @param string     Proxy host
-    * @param int        Proxy port
-    * @param string     Proxy username
-    * @param string     Proxy password
-    * @access public
-    */
-    function setProxy($host, $port = 8080, $user = null, $pass = null)
-    {
-        $this->_proxy_host = $host;
-        $this->_proxy_port = $port;
-        $this->_proxy_user = $user;
-        $this->_proxy_pass = $pass;
-
-        if (!empty($user)) {
-            $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
-        }
-    }
-
-    /**
-    * Sets basic authentication parameters
-    *
-    * @param string     Username
-    * @param string     Password
-    */
-    function setBasicAuth($user, $pass)
-    {
-        $this->_user = $user;
-        $this->_pass = $pass;
-
-        $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
-    }
-
-    /**
-    * Sets the method to be used, GET, POST etc.
-    *
-    * @param string     Method to use. Use the defined constants for this
-    * @access public
-    */
-    function setMethod($method)
-    {
-        $this->_method = $method;
-    }
-
-    /**
-    * Sets the HTTP version to use, 1.0 or 1.1
-    *
-    * @param string     Version to use. Use the defined constants for this
-    * @access public
-    */
-    function setHttpVer($http)
-    {
-        $this->_http = $http;
-    }
-
-    /**
-    * Adds a request header
-    *
-    * @param string     Header name
-    * @param string     Header value
-    * @access public
-    */
-    function addHeader($name, $value)
-    {
-        $this->_requestHeaders[strtolower($name)] = $value;
-    }
-
-    /**
-    * Removes a request header
-    *
-    * @param string     Header name to remove
-    * @access public
-    */
-    function removeHeader($name)
-    {
-        if (isset($this->_requestHeaders[strtolower($name)])) {
-            unset($this->_requestHeaders[strtolower($name)]);
-        }
-    }
-
-    /**
-    * Adds a querystring parameter
-    *
-    * @param string     Querystring parameter name
-    * @param string     Querystring parameter value
-    * @param bool       Whether the value is already urlencoded or not, default = not
-    * @access public
-    */
-    function addQueryString($name, $value, $preencoded = false)
-    {
-        $this->_url->addQueryString($name, $value, $preencoded);
-    }
-
-    /**
-    * Sets the querystring to literally what you supply
-    *
-    * @param string     The querystring data. Should be of the format foo=bar&x=y etc
-    * @param bool       Whether data is already urlencoded or not, default = already encoded
-    * @access public
-    */
-    function addRawQueryString($querystring, $preencoded = true)
-    {
-        $this->_url->addRawQueryString($querystring, $preencoded);
-    }
-
-    /**
-    * Adds postdata items
-    *
-    * @param string     Post data name
-    * @param string     Post data value
-    * @param bool       Whether data is already urlencoded or not, default = not
-    * @access public
-    */
-    function addPostData($name, $value, $preencoded = false)
-    {
-        if ($preencoded) {
-            $this->_postData[$name] = $value;
-        } else {
-            $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value);
-        }
-    }
-
-   /**
-    * Recursively applies the callback function to the value
-    *
-    * @param    mixed   Callback function
-    * @param    mixed   Value to process
-    * @access   private
-    * @return   mixed   Processed value
-    */
-    function _arrayMapRecursive($callback, $value)
-    {
-        if (!is_array($value)) {
-            return call_user_func($callback, $value);
-        } else {
-            $map = array();
-            foreach ($value as $k => $v) {
-                $map[$k] = $this->_arrayMapRecursive($callback, $v);
-            }
-            return $map;
-        }
-    }
-
-   /**
-    * Adds a file to form-based file upload
-    *
-    * Used to emulate file upload via a HTML form. The method also sets
-    * Content-Type of HTTP request to 'multipart/form-data'.
-    *
-    * If you just want to send the contents of a file as the body of HTTP
-    * request you should use setBody() method.
-    *
-    * @access public
-    * @param  string    name of file-upload field
-    * @param  mixed     file name(s)
-    * @param  mixed     content-type(s) of file(s) being uploaded
-    * @return bool      true on success
-    * @throws PEAR_Error
-    */
-    function addFile($inputName, $fileName, $contentType = 'application/octet-stream')
-    {
-        if (!is_array($fileName) && !is_readable($fileName)) {
-            return PEAR::raiseError("File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE);
-        } elseif (is_array($fileName)) {
-            foreach ($fileName as $name) {
-                if (!is_readable($name)) {
-                    return PEAR::raiseError("File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE);
-                }
-            }
-        }
-        $this->addHeader('Content-Type', 'multipart/form-data');
-        $this->_postFiles[$inputName] = array(
-            'name' => $fileName,
-            'type' => $contentType
-        );
-        return true;
-    }
-
-    /**
-    * Adds raw postdata (DEPRECATED)
-    *
-    * @param string     The data
-    * @param bool       Whether data is preencoded or not, default = already encoded
-    * @access public
-    * @deprecated       deprecated since 1.3.0, method setBody() should be used instead
-    */
-    function addRawPostData($postdata, $preencoded = true)
-    {
-        $this->_body = $preencoded ? $postdata : urlencode($postdata);
-    }
-
-   /**
-    * Sets the request body (for POST, PUT and similar requests)
-    *
-    * @param    string  Request body
-    * @access   public
-    */
-    function setBody($body)
-    {
-        $this->_body = $body;
-    }
-
-    /**
-    * Clears any postdata that has been added (DEPRECATED).
-    *
-    * Useful for multiple request scenarios.
-    *
-    * @access public
-    * @deprecated deprecated since 1.2
-    */
-    function clearPostData()
-    {
-        $this->_postData = null;
-    }
-
-    /**
-    * Appends a cookie to "Cookie:" header
-    *
-    * @param string $name cookie name
-    * @param string $value cookie value
-    * @access public
-    */
-    function addCookie($name, $value)
-    {
-        $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : '';
-        $this->addHeader('Cookie', $cookies . $name . '=' . $value);
-    }
-
-    /**
-    * Clears any cookies that have been added (DEPRECATED).
-    *
-    * Useful for multiple request scenarios
-    *
-    * @access public
-    * @deprecated deprecated since 1.2
-    */
-    function clearCookies()
-    {
-        $this->removeHeader('Cookie');
-    }
-
-    /**
-    * Sends the request
-    *
-    * @access public
-    * @param  bool   Whether to store response body in Response object property,
-    *                set this to false if downloading a LARGE file and using a Listener
-    * @return mixed  PEAR error on error, true otherwise
-    */
-    function sendRequest($saveBody = true)
-    {
-        if (!is_a($this->_url, 'Net_URL')) {
-            return PEAR::raiseError('No URL given', HTTP_REQUEST_ERROR_URL);
-        }
-
-        $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host;
-        $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port;
-
-        if (strcasecmp($this->_url->protocol, 'https') == 0) {
-            // Bug #14127, don't try connecting to HTTPS sites without OpenSSL
-            if (version_compare(PHP_VERSION, '4.3.0', '<') || !extension_loaded('openssl')) {
-                return PEAR::raiseError('Need PHP 4.3.0 or later with OpenSSL support for https:// requests',
-                                        HTTP_REQUEST_ERROR_URL);
-            } elseif (isset($this->_proxy_host)) {
-                return PEAR::raiseError('HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY);
-            }
-            $host = 'ssl://' . $host;
-        }
-
-        // magic quotes may fuck up file uploads and chunked response processing
-        $magicQuotes = ini_get('magic_quotes_runtime');
-        ini_set('magic_quotes_runtime', false);
-
-        // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
-        // connection token to a proxy server...
-        if (isset($this->_proxy_host) && !empty($this->_requestHeaders['connection']) &&
-            'Keep-Alive' == $this->_requestHeaders['connection'])
-        {
-            $this->removeHeader('connection');
-        }
-
-        $keepAlive = (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty($this->_requestHeaders['connection'])) ||
-                     (!empty($this->_requestHeaders['connection']) && 'Keep-Alive' == $this->_requestHeaders['connection']);
-        $sockets   = PEAR::getStaticProperty('HTTP_Request', 'sockets');
-        $sockKey   = $host . ':' . $port;
-        unset($this->_sock);
-
-        // There is a connected socket in the "static" property?
-        if ($keepAlive && !empty($sockets[$sockKey]) &&
-            !empty($sockets[$sockKey]->fp))
-        {
-            $this->_sock =& $sockets[$sockKey];
-            $err = null;
-        } else {
-            $this->_notify('connect');
-            $this->_sock = new Net_Socket();
-            $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions);
-        }
-        PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest());
-
-        if (!PEAR::isError($err)) {
-            if (!empty($this->_readTimeout)) {
-                $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]);
-            }
-
-            $this->_notify('sentRequest');
-
-            // Read the response
-            $this->_response = new HTTP_Response($this->_sock, $this->_listeners);
-            $err = $this->_response->process(
-                $this->_saveBody && $saveBody,
-                HTTP_REQUEST_METHOD_HEAD != $this->_method
-            );
-
-            if ($keepAlive) {
-                $keepAlive = (isset($this->_response->_headers['content-length'])
-                              || (isset($this->_response->_headers['transfer-encoding'])
-                                  && strtolower($this->_response->_headers['transfer-encoding']) == 'chunked'));
-                if ($keepAlive) {
-                    if (isset($this->_response->_headers['connection'])) {
-                        $keepAlive = strtolower($this->_response->_headers['connection']) == 'keep-alive';
-                    } else {
-                        $keepAlive = 'HTTP/'.HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol;
-                    }
-                }
-            }
-        }
-
-        ini_set('magic_quotes_runtime', $magicQuotes);
-
-        if (PEAR::isError($err)) {
-            return $err;
-        }
-
-        if (!$keepAlive) {
-            $this->disconnect();
-        // Store the connected socket in "static" property
-        } elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) {
-            $sockets[$sockKey] =& $this->_sock;
-        }
-
-        // Check for redirection
-        if (    $this->_allowRedirects
-            AND $this->_redirects <= $this->_maxRedirects
-            AND $this->getResponseCode() > 300
-            AND $this->getResponseCode() < 399
-            AND !empty($this->_response->_headers['location'])) {
-
-
-            $redirect = $this->_response->_headers['location'];
-
-            // Absolute URL
-            if (preg_match('/^https?:\/\//i', $redirect)) {
-                $this->_url = new Net_URL($redirect);
-                $this->addHeader('Host', $this->_generateHostHeader());
-            // Absolute path
-            } elseif ($redirect{0} == '/') {
-                $this->_url->path = $redirect;
-
-            // Relative path
-            } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') {
-                if (substr($this->_url->path, -1) == '/') {
-                    $redirect = $this->_url->path . $redirect;
-                } else {
-                    $redirect = dirname($this->_url->path) . '/' . $redirect;
-                }
-                $redirect = Net_URL::resolvePath($redirect);
-                $this->_url->path = $redirect;
-
-            // Filename, no path
-            } else {
-                if (substr($this->_url->path, -1) == '/') {
-                    $redirect = $this->_url->path . $redirect;
-                } else {
-                    $redirect = dirname($this->_url->path) . '/' . $redirect;
-                }
-                $this->_url->path = $redirect;
-            }
-
-            $this->_redirects++;
-            return $this->sendRequest($saveBody);
-
-        // Too many redirects
-        } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
-            return PEAR::raiseError('Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS);
-        }
-
-        return true;
-    }
-
-    /**
-     * Disconnect the socket, if connected. Only useful if using Keep-Alive.
-     *
-     * @access public
-     */
-    function disconnect()
-    {
-        if (!empty($this->_sock) && !empty($this->_sock->fp)) {
-            $this->_notify('disconnect');
-            $this->_sock->disconnect();
-        }
-    }
-
-    /**
-    * Returns the response code
-    *
-    * @access public
-    * @return mixed     Response code, false if not set
-    */
-    function getResponseCode()
-    {
-        return isset($this->_response->_code) ? $this->_response->_code : false;
-    }
-
-    /**
-    * Returns the response reason phrase
-    *
-    * @access public
-    * @return mixed     Response reason phrase, false if not set
-    */
-    function getResponseReason()
-    {
-        return isset($this->_response->_reason) ? $this->_response->_reason : false;
-    }
-
-    /**
-    * Returns either the named header or all if no name given
-    *
-    * @access public
-    * @param string     The header name to return, do not set to get all headers
-    * @return mixed     either the value of $headername (false if header is not present)
-    *                   or an array of all headers
-    */
-    function getResponseHeader($headername = null)
-    {
-        if (!isset($headername)) {
-            return isset($this->_response->_headers)? $this->_response->_headers: array();
-        } else {
-            $headername = strtolower($headername);
-            return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false;
-        }
-    }
-
-    /**
-    * Returns the body of the response
-    *
-    * @access public
-    * @return mixed     response body, false if not set
-    */
-    function getResponseBody()
-    {
-        return isset($this->_response->_body) ? $this->_response->_body : false;
-    }
-
-    /**
-    * Returns cookies set in response
-    *
-    * @access public
-    * @return mixed     array of response cookies, false if none are present
-    */
-    function getResponseCookies()
-    {
-        return isset($this->_response->_cookies) ? $this->_response->_cookies : false;
-    }
-
-    /**
-    * Builds the request string
-    *
-    * @access private
-    * @return string The request string
-    */
-    function _buildRequest()
-    {
-        $separator = ini_get('arg_separator.output');
-        ini_set('arg_separator.output', '&');
-        $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : '';
-        ini_set('arg_separator.output', $separator);
-
-        $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : '';
-        $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : '';
-        $path = $this->_url->path . $querystring;
-        $url  = $host . $port . $path;
-
-        if (!strlen($url)) {
-            $url = '/';
-        }
-
-        $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
-
-        if (in_array($this->_method, $this->_bodyDisallowed) ||
-            (0 == strlen($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method ||
-             (empty($this->_postData) && empty($this->_postFiles)))))
-        {
-            $this->removeHeader('Content-Type');
-        } else {
-            if (empty($this->_requestHeaders['content-type'])) {
-                // Add default content-type
-                $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
-            } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) {
-                $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime());
-                $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
-            }
-        }
-
-        // Request Headers
-        if (!empty($this->_requestHeaders)) {
-            foreach ($this->_requestHeaders as $name => $value) {
-                $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
-                $request      .= $canonicalName . ': ' . $value . "\r\n";
-            }
-        }
-
-        // Method does not allow a body, simply add a final CRLF
-        if (in_array($this->_method, $this->_bodyDisallowed)) {
-
-            $request .= "\r\n";
-
-        // Post data if it's an array
-        } elseif (HTTP_REQUEST_METHOD_POST == $this->_method &&
-                  (!empty($this->_postData) || !empty($this->_postFiles))) {
-
-            // "normal" POST request
-            if (!isset($boundary)) {
-                $postdata = implode('&', array_map(
-                    create_function('$a', 'return $a[0] . \'=\' . $a[1];'),
-                    $this->_flattenArray('', $this->_postData)
-                ));
-
-            // multipart request, probably with file uploads
-            } else {
-                $postdata = '';
-                if (!empty($this->_postData)) {
-                    $flatData = $this->_flattenArray('', $this->_postData);
-                    foreach ($flatData as $item) {
-                        $postdata .= '--' . $boundary . "\r\n";
-                        $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"';
-                        $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n";
-                    }
-                }
-                foreach ($this->_postFiles as $name => $value) {
-                    if (is_array($value['name'])) {
-                        $varname       = $name . ($this->_useBrackets? '[]': '');
-                    } else {
-                        $varname       = $name;
-                        $value['name'] = array($value['name']);
-                    }
-                    foreach ($value['name'] as $key => $filename) {
-                        $fp       = fopen($filename, 'r');
-                        $basename = basename($filename);
-                        $type     = is_array($value['type'])? @$value['type'][$key]: $value['type'];
-
-                        $postdata .= '--' . $boundary . "\r\n";
-                        $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"';
-                        $postdata .= "\r\nContent-Type: " . $type;
-                        $postdata .= "\r\n\r\n" . fread($fp, filesize($filename)) . "\r\n";
-                        fclose($fp);
-                    }
-                }
-                $postdata .= '--' . $boundary . "--\r\n";
-            }
-            $request .= 'Content-Length: ' .
-                        (HTTP_REQUEST_MBSTRING? mb_strlen($postdata, 'iso-8859-1'): strlen($postdata)) .
-                        "\r\n\r\n";
-            $request .= $postdata;
-
-        // Explicitly set request body
-        } elseif (0 < strlen($this->_body)) {
-
-            $request .= 'Content-Length: ' .
-                        (HTTP_REQUEST_MBSTRING? mb_strlen($this->_body, 'iso-8859-1'): strlen($this->_body)) .
-                        "\r\n\r\n";
-            $request .= $this->_body;
-
-        // No body: send a Content-Length header nonetheless (request #12900),
-        // but do that only for methods that require a body (bug #14740)
-        } else {
-
-            if (in_array($this->_method, $this->_bodyRequired)) {
-                $request .= "Content-Length: 0\r\n";
-            }
-            $request .= "\r\n";
-        }
-
-        return $request;
-    }
-
-   /**
-    * Helper function to change the (probably multidimensional) associative array
-    * into the simple one.
-    *
-    * @param    string  name for item
-    * @param    mixed   item's values
-    * @return   array   array with the following items: array('item name', 'item value');
-    * @access   private
-    */
-    function _flattenArray($name, $values)
-    {
-        if (!is_array($values)) {
-            return array(array($name, $values));
-        } else {
-            $ret = array();
-            foreach ($values as $k => $v) {
-                if (empty($name)) {
-                    $newName = $k;
-                } elseif ($this->_useBrackets) {
-                    $newName = $name . '[' . $k . ']';
-                } else {
-                    $newName = $name;
-                }
-                $ret = array_merge($ret, $this->_flattenArray($newName, $v));
-            }
-            return $ret;
-        }
-    }
-
-
-   /**
-    * Adds a Listener to the list of listeners that are notified of
-    * the object's events
-    *
-    * Events sent by HTTP_Request object
-    * - 'connect': on connection to server
-    * - 'sentRequest': after the request was sent
-    * - 'disconnect': on disconnection from server
-    *
-    * Events sent by HTTP_Response object
-    * - 'gotHeaders': after receiving response headers (headers are passed in $data)
-    * - 'tick': on receiving a part of response body (the part is passed in $data)
-    * - 'gzTick': on receiving a gzip-encoded part of response body (ditto)
-    * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
-    *
-    * @param    HTTP_Request_Listener   listener to attach
-    * @return   boolean                 whether the listener was successfully attached
-    * @access   public
-    */
-    function attach(&$listener)
-    {
-        if (!is_a($listener, 'HTTP_Request_Listener')) {
-            return false;
-        }
-        $this->_listeners[$listener->getId()] =& $listener;
-        return true;
-    }
-
-
-   /**
-    * Removes a Listener from the list of listeners
-    *
-    * @param    HTTP_Request_Listener   listener to detach
-    * @return   boolean                 whether the listener was successfully detached
-    * @access   public
-    */
-    function detach(&$listener)
-    {
-        if (!is_a($listener, 'HTTP_Request_Listener') ||
-            !isset($this->_listeners[$listener->getId()])) {
-            return false;
-        }
-        unset($this->_listeners[$listener->getId()]);
-        return true;
-    }
-
-
-   /**
-    * Notifies all registered listeners of an event.
-    *
-    * @param    string  Event name
-    * @param    mixed   Additional data
-    * @access   private
-    * @see      HTTP_Request::attach()
-    */
-    function _notify($event, $data = null)
-    {
-        foreach (array_keys($this->_listeners) as $id) {
-            $this->_listeners[$id]->update($this, $event, $data);
-        }
-    }
-}
-
-
-/**
- * Response class to complement the Request class
- *
- * @category    HTTP
- * @package     HTTP_Request
- * @author      Richard Heyes <richard@phpguru.org>
- * @author      Alexey Borzov <avb@php.net>
- * @version     Release: 1.4.4
- */
-class HTTP_Response
-{
-    /**
-    * Socket object
-    * @var Net_Socket
-    */
-    var $_sock;
-
-    /**
-    * Protocol
-    * @var string
-    */
-    var $_protocol;
-
-    /**
-    * Return code
-    * @var string
-    */
-    var $_code;
-
-    /**
-    * Response reason phrase
-    * @var string
-    */
-    var $_reason;
-
-    /**
-    * Response headers
-    * @var array
-    */
-    var $_headers;
-
-    /**
-    * Cookies set in response
-    * @var array
-    */
-    var $_cookies;
-
-    /**
-    * Response body
-    * @var string
-    */
-    var $_body = '';
-
-   /**
-    * Used by _readChunked(): remaining length of the current chunk
-    * @var string
-    */
-    var $_chunkLength = 0;
-
-   /**
-    * Attached listeners
-    * @var array
-    */
-    var $_listeners = array();
-
-   /**
-    * Bytes left to read from message-body
-    * @var null|int
-    */
-    var $_toRead;
-
-    /**
-    * Constructor
-    *
-    * @param  Net_Socket    socket to read the response from
-    * @param  array         listeners attached to request
-    */
-    function __construct(&$sock, &$listeners)
-    {
-        $this->_sock      =& $sock;
-        $this->_listeners =& $listeners;
-    }
-
-
-   /**
-    * Processes a HTTP response
-    *
-    * This extracts response code, headers, cookies and decodes body if it
-    * was encoded in some way
-    *
-    * @access public
-    * @param  bool      Whether to store response body in object property, set
-    *                   this to false if downloading a LARGE file and using a Listener.
-    *                   This is assumed to be true if body is gzip-encoded.
-    * @param  bool      Whether the response can actually have a message-body.
-    *                   Will be set to false for HEAD requests.
-    * @throws PEAR_Error
-    * @return mixed     true on success, PEAR_Error in case of malformed response
-    */
-    function process($saveBody = true, $canHaveBody = true)
-    {
-        do {
-            $line = $this->_sock->readLine();
-            if (!preg_match('!^(HTTP/\d\.\d) (\d{3})(?: (.+))?!', $line, $s)) {
-                return PEAR::raiseError('Malformed response', HTTP_REQUEST_ERROR_RESPONSE);
-            } else {
-                $this->_protocol = $s[1];
-                $this->_code     = intval($s[2]);
-                $this->_reason   = empty($s[3])? null: $s[3];
-            }
-            while ('' !== ($header = $this->_sock->readLine())) {
-                $this->_processHeader($header);
-            }
-        } while (100 == $this->_code);
-
-        $this->_notify('gotHeaders', $this->_headers);
-
-        // RFC 2616, section 4.4:
-        // 1. Any response message which "MUST NOT" include a message-body ...
-        // is always terminated by the first empty line after the header fields
-        // 3. ... If a message is received with both a
-        // Transfer-Encoding header field and a Content-Length header field,
-        // the latter MUST be ignored.
-        $canHaveBody = $canHaveBody && $this->_code >= 200 &&
-                       $this->_code != 204 && $this->_code != 304;
-
-        // If response body is present, read it and decode
-        $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']);
-        $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']);
-        $hasBody = false;
-        if ($canHaveBody && ($chunked || !isset($this->_headers['content-length']) ||
-                0 != $this->_headers['content-length']))
-        {
-            if ($chunked || !isset($this->_headers['content-length'])) {
-                $this->_toRead = null;
-            } else {
-                $this->_toRead = $this->_headers['content-length'];
-            }
-            while (!$this->_sock->eof() && (is_null($this->_toRead) || 0 < $this->_toRead)) {
-                if ($chunked) {
-                    $data = $this->_readChunked();
-                } elseif (is_null($this->_toRead)) {
-                    $data = $this->_sock->read(4096);
-                } else {
-                    $data = $this->_sock->read(min(4096, $this->_toRead));
-                    $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
-                }
-                if ('' == $data && (!$this->_chunkLength || $this->_sock->eof())) {
-                    break;
-                } else {
-                    $hasBody = true;
-                    if ($saveBody || $gzipped) {
-                        $this->_body .= $data;
-                    }
-                    $this->_notify($gzipped? 'gzTick': 'tick', $data);
-                }
-            }
-        }
-
-        if ($hasBody) {
-            // Uncompress the body if needed
-            if ($gzipped) {
-                $body = $this->_decodeGzip($this->_body);
-                if (PEAR::isError($body)) {
-                    return $body;
-                }
-                $this->_body = $body;
-                $this->_notify('gotBody', $this->_body);
-            } else {
-                $this->_notify('gotBody');
-            }
-        }
-        return true;
-    }
-
-
-   /**
-    * Processes the response header
-    *
-    * @access private
-    * @param  string    HTTP header
-    */
-    function _processHeader($header)
-    {
-        if (false === strpos($header, ':')) {
-            return;
-        }
-        list($headername, $headervalue) = explode(':', $header, 2);
-        $headername  = strtolower($headername);
-        $headervalue = ltrim($headervalue);
-
-        if ('set-cookie' != $headername) {
-            if (isset($this->_headers[$headername])) {
-                $this->_headers[$headername] .= ',' . $headervalue;
-            } else {
-                $this->_headers[$headername]  = $headervalue;
-            }
-        } else {
-            $this->_parseCookie($headervalue);
-        }
-    }
-
-
-   /**
-    * Parse a Set-Cookie header to fill $_cookies array
-    *
-    * @access private
-    * @param  string    value of Set-Cookie header
-    */
-    function _parseCookie($headervalue)
-    {
-        $cookie = array(
-            'expires' => null,
-            'domain'  => null,
-            'path'    => null,
-            'secure'  => false
-        );
-
-        // Only a name=value pair
-        if (!strpos($headervalue, ';')) {
-            $pos = strpos($headervalue, '=');
-            $cookie['name']  = trim(substr($headervalue, 0, $pos));
-            $cookie['value'] = trim(substr($headervalue, $pos + 1));
-
-        // Some optional parameters are supplied
-        } else {
-            $elements = explode(';', $headervalue);
-            $pos = strpos($elements[0], '=');
-            $cookie['name']  = trim(substr($elements[0], 0, $pos));
-            $cookie['value'] = trim(substr($elements[0], $pos + 1));
-
-            for ($i = 1; $i < count($elements); $i++) {
-                if (false === strpos($elements[$i], '=')) {
-                    $elName  = trim($elements[$i]);
-                    $elValue = null;
-                } else {
-                    list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
-                }
-                $elName = strtolower($elName);
-                if ('secure' == $elName) {
-                    $cookie['secure'] = true;
-                } elseif ('expires' == $elName) {
-                    $cookie['expires'] = str_replace('"', '', $elValue);
-                } elseif ('path' == $elName || 'domain' == $elName) {
-                    $cookie[$elName] = urldecode($elValue);
-                } else {
-                    $cookie[$elName] = $elValue;
-                }
-            }
-        }
-        $this->_cookies[] = $cookie;
-    }
-
-
-   /**
-    * Read a part of response body encoded with chunked Transfer-Encoding
-    *
-    * @access private
-    * @return string
-    */
-    function _readChunked()
-    {
-        // at start of the next chunk?
-        if (0 == $this->_chunkLength) {
-            $line = $this->_sock->readLine();
-            if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
-                $this->_chunkLength = hexdec($matches[1]);
-                // Chunk with zero length indicates the end
-                if (0 == $this->_chunkLength) {
-                    $this->_sock->readLine(); // make this an eof()
-                    return '';
-                }
-            } else {
-                return '';
-            }
-        }
-        $data = $this->_sock->read($this->_chunkLength);
-        $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
-        if (0 == $this->_chunkLength) {
-            $this->_sock->readLine(); // Trailing CRLF
-        }
-        return $data;
-    }
-
-
-   /**
-    * Notifies all registered listeners of an event.
-    *
-    * @param    string  Event name
-    * @param    mixed   Additional data
-    * @access   private
-    * @see HTTP_Request::_notify()
-    */
-    function _notify($event, $data = null)
-    {
-        foreach (array_keys($this->_listeners) as $id) {
-            $this->_listeners[$id]->update($this, $event, $data);
-        }
-    }
-
-
-   /**
-    * Decodes the message-body encoded by gzip
-    *
-    * The real decoding work is done by gzinflate() built-in function, this
-    * method only parses the header and checks data for compliance with
-    * RFC 1952
-    *
-    * @access   private
-    * @param    string  gzip-encoded data
-    * @return   string  decoded data
-    */
-    function _decodeGzip($data)
-    {
-        if (HTTP_REQUEST_MBSTRING) {
-            $oldEncoding = mb_internal_encoding();
-            mb_internal_encoding('iso-8859-1');
-        }
-        $length = strlen($data);
-        // If it doesn't look like gzip-encoded data, don't bother
-        if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
-            return $data;
-        }
-        $method = ord(substr($data, 2, 1));
-        if (8 != $method) {
-            return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD);
-        }
-        $flags = ord(substr($data, 3, 1));
-        if ($flags & 224) {
-            return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA);
-        }
-
-        // header is 10 bytes minimum. may be longer, though.
-        $headerLength = 10;
-        // extra fields, need to skip 'em
-        if ($flags & 4) {
-            if ($length - $headerLength - 2 < 8) {
-                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
-            }
-            $extraLength = unpack('v', substr($data, 10, 2));
-            if ($length - $headerLength - 2 - $extraLength[1] < 8) {
-                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
-            }
-            $headerLength += $extraLength[1] + 2;
-        }
-        // file name, need to skip that
-        if ($flags & 8) {
-            if ($length - $headerLength - 1 < 8) {
-                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
-            }
-            $filenameLength = strpos(substr($data, $headerLength), chr(0));
-            if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {
-                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
-            }
-            $headerLength += $filenameLength + 1;
-        }
-        // comment, need to skip that also
-        if ($flags & 16) {
-            if ($length - $headerLength - 1 < 8) {
-                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
-            }
-            $commentLength = strpos(substr($data, $headerLength), chr(0));
-            if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {
-                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
-            }
-            $headerLength += $commentLength + 1;
-        }
-        // have a CRC for header. let's check
-        if ($flags & 1) {
-            if ($length - $headerLength - 2 < 8) {
-                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
-            }
-            $crcReal   = 0xffff & crc32(substr($data, 0, $headerLength));
-            $crcStored = unpack('v', substr($data, $headerLength, 2));
-            if ($crcReal != $crcStored[1]) {
-                return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
-            }
-            $headerLength += 2;
-        }
-        // unpacked data CRC and size at the end of encoded data
-        $tmp = unpack('V2', substr($data, -8));
-        $dataCrc  = $tmp[1];
-        $dataSize = $tmp[2];
-
-        // finally, call the gzinflate() function
-        // don't pass $dataSize to gzinflate, see bugs #13135, #14370
-        $unpacked = gzinflate(substr($data, $headerLength, -8));
-        if (false === $unpacked) {
-            return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ);
-        } elseif ($dataSize != strlen($unpacked)) {
-            return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ);
-        } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
-            return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
-        }
-        if (HTTP_REQUEST_MBSTRING) {
-            mb_internal_encoding($oldEncoding);
-        }
-        return $unpacked;
-    }
-} // End class HTTP_Response
-?>
diff --git a/civicrm/packages/HTTP/Request/Listener.php b/civicrm/packages/HTTP/Request/Listener.php
deleted file mode 100644
index 7bc837cb8e..0000000000
--- a/civicrm/packages/HTTP/Request/Listener.php
+++ /dev/null
@@ -1,106 +0,0 @@
-<?php
-/**
- * Listener for HTTP_Request and HTTP_Response objects
- *
- * PHP versions 4 and 5
- * 
- * LICENSE:
- *
- * Copyright (c) 2002-2007, Richard Heyes
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * o Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * o Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * o The names of the authors may not be used to endorse or promote
- *   products derived from this software without specific prior written
- *   permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category    HTTP
- * @package     HTTP_Request
- * @author      Alexey Borzov <avb@php.net>
- * @copyright   2002-2007 Richard Heyes
- * @license     http://opensource.org/licenses/bsd-license.php New BSD License
- * @version     CVS: $Id: Listener.php,v 1.3 2007/05/18 10:33:31 avb Exp $
- * @link        http://pear.php.net/package/HTTP_Request/ 
- */
-
-/**
- * Listener for HTTP_Request and HTTP_Response objects
- *
- * This class implements the Observer part of a Subject-Observer
- * design pattern.
- *
- * @category    HTTP
- * @package     HTTP_Request
- * @author      Alexey Borzov <avb@php.net>
- * @version     Release: 1.4.4
- */
-class HTTP_Request_Listener 
-{
-   /**
-    * A listener's identifier
-    * @var string
-    */
-    var $_id;
-
-   /**
-    * Constructor, sets the object's identifier
-    *
-    * @access public
-    */
-    function __construct()
-    {
-        $this->_id = md5(uniqid('http_request_', 1));
-    }
-
-
-   /**
-    * Returns the listener's identifier
-    *
-    * @access public
-    * @return string
-    */
-    function getId()
-    {
-        return $this->_id;
-    }
-
-
-   /**
-    * This method is called when Listener is notified of an event
-    *
-    * @access   public
-    * @param    object  an object the listener is attached to
-    * @param    string  Event name
-    * @param    mixed   Additional data
-    * @abstract
-    */
-    function update(&$subject, $event, $data = null)
-    {
-        echo "Notified of event: '$event'\n";
-        if (null !== $data) {
-            echo "Additional data: ";
-            var_dump($data);
-        }
-    }
-}
-?>
diff --git a/civicrm/packages/VERSIONS.php b/civicrm/packages/VERSIONS.php
index dfe70e54f2..bb33761e99 100644
--- a/civicrm/packages/VERSIONS.php
+++ b/civicrm/packages/VERSIONS.php
@@ -114,7 +114,6 @@
  * HTML_QuickForm_advmultiselect 1.5.1      BSD 3-cl.      local changes
  * HTML_QuickForm_Controller     1.0.9      PHP 3          local changes
  * HTML_Template_IT              1.2.1      BSD 3-cl.
- * HTTP_Request                  1.4.4      BSD 3-cl.
  * Log                           1.11.5     X11
  * Mail                          1.2.0      PHP 2          local changes
  * Mail_Mime                     1.8.0      BSD 3-cl.      local changes
diff --git a/civicrm/release-notes.md b/civicrm/release-notes.md
index b9c69e516a..e405b78517 100644
--- a/civicrm/release-notes.md
+++ b/civicrm/release-notes.md
@@ -15,9 +15,20 @@ Other resources for identifying changes are:
     * https://github.com/civicrm/civicrm-joomla
     * https://github.com/civicrm/civicrm-wordpress
 
+## CiviCRM 5.27.0
+
+Released July 1, 2020
+
+- **[Synopsis](release-notes/5.27.0.md#synopsis)**
+- **[Features](release-notes/5.27.0.md#features)**
+- **[Bugs resolved](release-notes/5.27.0.md#bugs)**
+- **[Miscellany](release-notes/5.27.0.md#misc)**
+- **[Credits](release-notes/5.27.0.md#credits)**
+- **[Feedback](release-notes/5.27.0.md#feedback)**
+
 ## CiviCRM 5.26.2
 
-Released June 16, 2020
+Released June 15, 2020
 
 - **[Synopsis](release-notes/5.26.2.md#synopsis)**
 - **[Bugs resolved](release-notes/5.26.2.md#bugs)**
diff --git a/civicrm/release-notes/5.26.2.md b/civicrm/release-notes/5.26.2.md
index 7e73ac5d14..6c66442c27 100644
--- a/civicrm/release-notes/5.26.2.md
+++ b/civicrm/release-notes/5.26.2.md
@@ -1,6 +1,6 @@
 # CiviCRM 5.26.2
 
-Released June 16, 2020
+Released June 15, 2020
 
 - **[Synopsis](#synopsis)**
 - **[Bugs resolved](#bugs)**
@@ -35,7 +35,7 @@ This release was developed by the following authors and reviewers:
 
 Wikimedia Foundation - Eileen McNaughton; Tapas Datta; Semper IT - Karin Gerritsen; 
 MJCO - Mikey O'Toole; MJW Consulting - Matt Wire; Megaphone Technology Consulting - Jon Goldberg; 
-JMA Consulting - Seamus Lee; Francesc Bassas i Bullich; CiviCRM - Coleman Watts, Tim Otten
+Francesc Bassas i Bullich; JMA Consulting - Seamus Lee; CiviCRM - Coleman Watts, Tim Otten
 
 ## <a name="feedback"></a>Feedback
 
diff --git a/civicrm/release-notes/5.27.0.md b/civicrm/release-notes/5.27.0.md
new file mode 100644
index 0000000000..b2f7bd71b9
--- /dev/null
+++ b/civicrm/release-notes/5.27.0.md
@@ -0,0 +1,885 @@
+# CiviCRM 5.27.0
+
+Released July 1, 2020
+
+- **[Synopsis](#synopsis)**
+- **[Features](#features)**
+- **[Bugs resolved](#bugs)**
+- **[Miscellany](#misc)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="synopsis"></a>Synopsis
+
+| *Does this version...?*                                         |         |
+|:--------------------------------------------------------------- |:-------:|
+| Fix security vulnerabilities?                                   |   no    |
+| **Change the database schema?**                                 | **yes** |
+| **Alter the API?**                                              | **yes** |
+| **Require attention to configuration options?**                 | **yes** |
+| **Fix problems installing or upgrading to a previous version?** | **yes** |
+| **Introduce features?**                                         | **yes** |
+| **Fix bugs?**                                                   | **yes** |
+
+## <a name="features"></a>Features
+
+### Core CiviCRM
+
+- **Warn users who lack PHP-Intl extension (Work Towards
+  [dev/translation#48](https://lab.civicrm.org/dev/translation/-/issues/48):
+  [17668](https://github.com/civicrm/civicrm-core/pull/17668), [17728](https://github.com/civicrm/civicrm-core/pull/17728))**
+
+  A system check warning will now appear on sites that lack the PHP
+  Internationalization extension.  This is in preparation for changes that will
+  appear in CiviCRM 5.28 and require the extension.
+
+- **Advanced Search - Allow searching by first/last name; pass values from
+  quicksearch ([dev/core#1722](https://lab.civicrm.org/dev/core/-/issues/1722):
+  [17118](https://github.com/civicrm/civicrm-core/pull/17118))**
+
+  This makes separate First Name and Last Name fields available on the Advanced
+  Search form, and it ensures quick search filters are passed to the appropriate
+  field.
+
+- **Add more search options
+  ([17372](https://github.com/civicrm/civicrm-core/pull/17372))**
+
+  Improves the search form for individuals in contact reference fields by adding
+  fields for Employer Name, First Name, Last Name, and Nick Name.
+
+- **End of life planning for MySQL server 5.0 - 5.6
+  ([dev/core#1681](https://lab.civicrm.org/dev/core/-/issues/1681):
+  [17518](https://github.com/civicrm/civicrm-core/pull/17518) and
+  [17496](https://github.com/civicrm/civicrm-core/pull/17496))**
+
+  Sites running MySQL 5.5 and below will have a pre-upgrade message and a system
+  check warning to say that CiviCRM 5.28 will require MySQL 5.6 or MariaDB 10.1.
+
+- **APIv4 - Improve pseudoconstant suffix support
+  ([17368](https://github.com/civicrm/civicrm-core/pull/17368) and
+  [17482](https://github.com/civicrm/civicrm-core/pull/17482))**
+
+  APIv4 allows pseudoconstant fields to be specified with the pseudoconstant
+  name followed by a suffix, such as `activity_type_id:label`.  This now works
+  for retrieval and sort.
+
+- **APIv4 - Support custom entity joins
+  ([17394](https://github.com/civicrm/civicrm-core/pull/17394))**
+
+  Improves APIv4 so that it supports implicit and explicit joins onto custom
+  entities.
+
+- **Make reCAPTCHA settings clearer
+  ([17426](https://github.com/civicrm/civicrm-core/pull/17426))**
+
+  The help text for reCAPTCHA settings now specifies the type of reCAPTCHA
+  supported.
+
+- **Configurable logfile size and hashing
+  ([17192](https://github.com/civicrm/civicrm-core/pull/17192))**
+
+  Allows a system administrator to give logs a predictable name, allowing them
+  to be more easily ingested into other tools, and be handled by external log
+  rotation tools.
+
+- **Allow for installation on Symfony 4.4
+  ([17380](https://github.com/civicrm/civicrm-core/pull/17380))**
+
+  Makes it so CiviCRM plays nicely with Symfony 4.4.
+
+- **Add domain tokens to the Message Template admin interface
+  ([17388](https://github.com/civicrm/civicrm-core/pull/17388))**
+
+  This adds the domain tokens (the domain organization name, address, email, and
+  phone) to the available listed tokens for editing message templates.
+
+- **Hide icon elements from screen readers and add handling for
+  screen-reader-only text
+  ([17318](https://github.com/civicrm/civicrm-core/pull/17318),
+  [17293](https://github.com/civicrm/civicrm-core/pull/17293),
+  [17294](https://github.com/civicrm/civicrm-core/pull/17294), and
+  [17310](https://github.com/civicrm/civicrm-core/pull/17310))**
+
+  CiviCRM uses empty `<i>` elements to provide most icons.  Screen readers,
+  which won't render the visual icon anyway, will either skip over an empty
+  element or announce it in a way that would be confusing.  This makes it
+  explicit that screen readers and other ARIA devices should skip them.
+
+  Meanwhile, if the icon is the only way a piece of information is displayed, a
+  screen reader user won't get that information.  This adds a `sr-only` class
+  that makes the element invisible on screen without being ignored by a screen
+  reader.
+
+  Screen reader text is added for the field option wrench icons, relationship
+  permissions, and membership auto-renew status.
+
+- **Add icon helper functions and remove most uses of check.gif
+  ([17279](https://github.com/civicrm/civicrm-core/pull/17279) and
+  [17289](https://github.com/civicrm/civicrm-core/pull/17289))**
+
+  This adds helper functions in PHP and Smarty to render consistent icons with a
+  minimum of code.  It also replaces most instances of the green checkmark image
+  with a checkmark icon.
+
+- **Separate icon markup from labels and add JS icon helper
+  ([17319](https://github.com/civicrm/civicrm-core/pull/17319) and
+  [17285](https://github.com/civicrm/civicrm-core/pull/17285))**
+
+  These changes improve `CRM_Core_Action::formLink()`, `hook_civicrm_links`, and
+  certain listing pages so that HTML icon markup is added at the point of
+  display rather than during the processing of values.
+
+  It also adds a helper function in Javascript similar to those in PHP and
+  Smarty to render icons.
+
+- **crmButton: Support icon=0 for no icon
+  ([17303](https://github.com/civicrm/civicrm-core/pull/17303))**
+
+  Makes it possible to create a button without an icon using {crmButton}.
+
+- **Replace stop-icon.png with fa-ban over a relevant icon for privacy
+  ([17283](https://github.com/civicrm/civicrm-core/pull/17283) and
+  [17307](https://github.com/civicrm/civicrm-core/pull/17307))**
+
+  The communication preference icons are standardized and more specific than the
+  old stop sign.
+
+- **Replace image icons with Font Awesome icons
+  ([17296]([17280](https://github.com/civicrm/civicrm-core/pull/17280),
+  [17281](https://github.com/civicrm/civicrm-core/pull/17281),
+  [17282](https://github.com/civicrm/civicrm-core/pull/17282),
+  [17295](https://github.com/civicrm/civicrm-core/pull/17295),
+  https://github.com/civicrm/civicrm-core/pull/17296),
+  [17297](https://github.com/civicrm/civicrm-core/pull/17297))**
+
+  Nearly all image icons have been replaced with the corresponding icons from
+  the Font Awesome library.
+
+- **Simplify admin console and remove superfluous icons
+  ([17284](https://github.com/civicrm/civicrm-core/pull/17284))**
+
+  The Administration console has been redesigned to have a simpler layout,
+  display more information, dynamically include all enabled components, display
+  responsively on small screens, and remove a slew of 15-year-old image icons.
+
+- **Dedupe performance - hard-remove financial_item from list of dymnamic  refs
+  to contact table
+  ([17567](https://github.com/civicrm/civicrm-core/pull/17567))**
+
+  This improves performance when deduping by no longer querying the financial
+  item table.
+
+- **Trigger fatalErrorHandler for PEAR errors and for logs with severity ERROR
+  or higher ([17277](https://github.com/civicrm/civicrm-core/pull/17277))**
+
+  This allows extensions that implement `$config->fatalErrorHandler` to react to
+  a wider variety of errors that CiviCRM may generate.
+
+### CiviContribute
+
+- **Wrap separators in price field in spans with classes
+  ([dev/user-interface#18](https://lab.civicrm.org/dev/user-interface/-/issues/18):
+  [17078](https://github.com/civicrm/civicrm-core/pull/17078))**
+
+  Colons separating pre- and post-field help text from price fields are now
+  wrapped in `<span>` elements.
+
+- **Allow to search on contribution ID
+  ([dev/core#1580](https://lab.civicrm.org/dev/core/-/issues/1580):
+  [16484](https://github.com/civicrm/civicrm-core/pull/16484))**
+
+  This improves the "Find Contributions" search form by adding a field to search
+  by Contribution ID.
+
+- **APIv4 - Add "Price"-related entities
+  ([17363](https://github.com/civicrm/civicrm-core/pull/17363))**
+
+  Priceset, PriceField, and PriceOption entities are added to APIv4.
+
+- **APIv4 - Add ContributionRecur entity
+  ([17299](https://github.com/civicrm/civicrm-core/pull/17299))**
+
+  Adds Contribution Recur to APIv4.
+
+### CiviMail
+
+- **Allow click-through and open tracking to be enabled/disabled by default
+  ([17291](https://github.com/civicrm/civicrm-core/pull/17291))**
+
+  Adds a setting to CiviMail which allows for setting the click-through and open
+  tracking defaults.
+
+- **Extend content array of hook_civicrm_alterMailContent
+  ([dev/core#1620](https://lab.civicrm.org/dev/core/-/issues/1620):
+  [16629](https://github.com/civicrm/civicrm-core/pull/16629))**
+
+  Adds campaign_id to template for `alterMailContent` hook.
+
+- **Migrate CiviMail "extern" scripts to conventional routes
+  ([17312](https://github.com/civicrm/civicrm-core/pull/17312))**
+
+  Updates CiviMail's default behavior to replace `extern/open.php` and
+  `extern/url.php` with `civicrm/mailing/open` and `civicrm/mailing/url`.
+
+- **Make `is_archived` work as a url-search parameter
+  ([17328](https://github.com/civicrm/civicrm-core/pull/17328))**
+
+  The Find Mailings URL can now have `is_archived` as a parameter to only find
+  archived mailings.
+
+### CiviMember
+
+- **Add MembershipType to Api4
+  ([17448](https://github.com/civicrm/civicrm-core/pull/17448))**
+
+  Adds a Membership Type entity to APIv4.
+
+### Drupal Integration
+
+- **CiviCRM menu toggle "adjust menu position" customisable
+  ([dev/core#1757](https://lab.civicrm.org/dev/core/-/issues/1757):
+  [17362](https://github.com/civicrm/civicrm-core/pull/17362))**
+
+  This hides the "adjust menu position" icon in the CiviCRM Menu for non admin
+  users to avoid confusion for users who do not have access to the Drupal admin
+  menu.
+
+- **Provide "Calendar" module with an end-date when a duration is provided
+  ([601](https://github.com/civicrm/civicrm-drupal/pull/601))**
+
+  Improves display of activities in calendar views.
+
+## <a name="bugs"></a>Bugs resolved
+
+### Core CiviCRM
+
+- **CRM_Utils_Time::setTime and getTime() and their use in unit tests
+  ([dev/core#1781](https://lab.civicrm.org/dev/core/-/issues/1781):
+  [17414](https://github.com/civicrm/civicrm-core/pull/17414))**
+
+  This allows the CRM_Utils_Time functions used in unit tests to use TIME_FUNC
+  to better isolate timing bugs.
+
+- **Confusing popups when importing activities
+  ([dev/user-interface#17](https://lab.civicrm.org/dev/user-interface/-/issues/17):
+  [17067](https://github.com/civicrm/civicrm-core/pull/17067))**
+
+  This fixes a bug where the confirmation popup would appear when hitting the
+  back/cancel buttons, not just the import button, on most import forms.
+
+- **Installing CiviCRM in another language, with civicrm-setup
+  ([dev/translation#39](https://lab.civicrm.org/dev/translation/-/issues/39):
+  [17244](https://github.com/civicrm/civicrm-core/pull/17244))**
+
+  Fixes a bug when installing CiviCRM in another language with civicrm-setup.
+
+- **Replace all instances of CRM_Core_Fatal with throw new CRM_Core_Exception
+  ([dev/core#560](https://lab.civicrm.org/dev/core/-/issues/560):
+  [17421](https://github.com/civicrm/civicrm-core/pull/17421),
+  [17343](https://github.com/civicrm/civicrm-core/pull/17343),
+  [17336](https://github.com/civicrm/civicrm-core/pull/17336) and
+  [17341](https://github.com/civicrm/civicrm-core/pull/17341))**
+
+- **CiviCRM 5.13.4 - smart groups with contact subtypes: subtype is not in
+  Contact Type field on edit criteria mode
+  ([dev/core#991](https://lab.civicrm.org/dev/core/-/issues/991):
+  [16541](https://github.com/civicrm/civicrm-core/pull/16541))**
+
+  Fixes contact subtypes not being carried over when editing a smart group
+  created in Advanced Search.
+
+- **Unable to import relationship
+  ([dev/core#1731](https://lab.civicrm.org/dev/core/-/issues/1731):
+  [17163](https://github.com/civicrm/civicrm-core/pull/17163))**
+
+  Ensures that importing relationships works as expected when the same field is
+  to be imported for the main imported contact and a related contact.
+
+- **Apostrophes in richtext fields don't get exported properly in CiviReport
+  ([dev/core#1743](https://lab.civicrm.org/dev/core/-/issues/1743):
+  [17260](https://github.com/civicrm/civicrm-core/pull/17260))**
+
+- **Statically added members of a smart group are not found
+  ([dev/core#1745](https://lab.civicrm.org/dev/core/-/issues/1745):
+  [17419](https://github.com/civicrm/civicrm-core/pull/17419))**
+
+- **Deleting an activity with attachments doesn't delete the file or entries in
+  civicrm_file/civicrm_entity_file
+  ([dev/core#1753](https://lab.civicrm.org/dev/core/-/issues/1753):
+  [17298](https://github.com/civicrm/civicrm-core/pull/17298))**
+
+- **Deselected checkbox settings are not saved
+  ([dev/core#1794](https://lab.civicrm.org/dev/core/-/issues/1794):
+  [17493](https://github.com/civicrm/civicrm-core/pull/17493))**
+
+  Ensures deselected values are saved on custom field settings forms.
+
+- **Added activity types don't appear in the type dropdown on New Activity
+  ([dev/core#1822](https://lab.civicrm.org/dev/core/-/issues/1822):
+  [17625](https://github.com/civicrm/civicrm-core/pull/17625))**
+
+- **API doesn't allow passing option values by label
+  ([dev/core#1816](https://lab.civicrm.org/dev/core/-/issues/1816):
+  [17628](https://github.com/civicrm/civicrm-core/pull/17628))**
+
+  Updates APIv4 so that it matches based on label if name is not found.
+
+- **APIv4 - Improve custom field spec gathering
+  ([17471](https://github.com/civicrm/civicrm-core/pull/17471))**
+
+- **APIv4 - Remove implicit multi joins & add explicit joins
+ ([17332](https://github.com/civicrm/civicrm-core/pull/17332))**
+
+- **APIv4 - Fix entity name on custom groups in schemaMapper
+  ([17425](https://github.com/civicrm/civicrm-core/pull/17425))**
+
+- **APIv4 - fix returning custom field values with API4
+  ([17399](https://github.com/civicrm/civicrm-core/pull/17399))**
+
+- **Attempting to access Multi-Record Custom Field import results
+  in crash
+  ([dev/core#1841](https://lab.civicrm.org/dev/core/-/issues/1841):
+  [17713](https://github.com/civicrm/civicrm-core/pull/17713))**
+
+- **Fix issue with building smart groups when $contactQueries is empty
+  ([17622](https://github.com/civicrm/civicrm-core/pull/17622))**
+
+  If a clause of a contact query used to build a smart group is empty, it would
+  result in a database error.
+
+- **Replace deprecated `money_format()` fn to support PHP 7.4
+  (Work Towards [dev/core#1494](https://lab.civicrm.org/dev/core/-/issues/1494):
+  [17577](https://github.com/civicrm/civicrm-core/pull/17577), [17730](https://github.com/civicrm/civicrm-core/pull/17730))**
+
+  Adds a deprecation notice and a status check for a money value format
+  configuration other than the default.
+
+- **QueueTest - Be more forgiving about slow execution
+  ([17532](https://github.com/civicrm/civicrm-core/pull/17532))**
+
+- **CommunityMessages - Define more consistent behavior in the face of slow
+  execution ([17529](https://github.com/civicrm/civicrm-core/pull/17529))**
+
+  This helps avoid test failures on broadcast messages when the system is
+  running slowly.
+
+- **Scheduled Reminders - Set boolean fields to false if not set.
+  ([17494](https://github.com/civicrm/civicrm-core/pull/17494))**
+
+- **Allow bidirectional assignment of relationships from search results
+  ([17413](https://github.com/civicrm/civicrm-core/pull/17413))**
+
+  Previously relationships could only be created from search results where the
+  contacts would be valid in the "A" side of the relationship type.
+
+- **Navigation menu - Fix translation of new-subtype entries
+  ([17451](https://github.com/civicrm/civicrm-core/pull/17451))**
+
+  The "New" in menu items for creating a new contact of a subtype was not
+  translated.
+
+- **utf8mb4 - If strict mode enabled query will fail if KEY_BLOCK_SIZE is not 0
+  ([17253](https://github.com/civicrm/civicrm-core/pull/17253))**
+
+- **Update DAO and l10n schema file
+  ([17395](https://github.com/civicrm/civicrm-core/pull/17395))**
+
+  Price option name and value are now required in the database.
+
+- **Fix adding languages in multilingual
+  ([17228](https://github.com/civicrm/civicrm-core/pull/17228))**
+
+  This resolves a database error when adding or removing a language on a
+  multilingual site.
+
+- **Don't exclude deleted contacts from ACL cache when user has permission
+  ([17379](https://github.com/civicrm/civicrm-core/pull/17379))**
+
+- **SMTP page appears broken when language is French (JS issue)
+  ([dev/core#1760](https://lab.civicrm.org/dev/core/-/issues/1760):
+  [17317](https://github.com/civicrm/civicrm-core/pull/17317))**
+
+  Javascript strings that appear in Smarty are now escaped more thoroughly to
+  avoid markup problems.
+
+- **Add serialize column to civicrm_custom_field, remove "Multi-Select" html
+  type ([16992](https://github.com/civicrm/civicrm-core/pull/16992), [17722](https://github.com/civicrm/civicrm-core/pull/17722))**
+
+  Work towards making custom select and multi-select fields more similar to
+  core select/multi-select fields.
+
+- **Respect file fields that have been configured as view only in profiles
+  ([17079](https://github.com/civicrm/civicrm-core/pull/17079))**
+
+- **Tag create - Respect created_date and created_id params
+  ([17257](https://github.com/civicrm/civicrm-core/pull/17257))**
+
+- **Public status messages should show correct class/icon like error
+  ([17376](https://github.com/civicrm/civicrm-core/pull/17376))**
+
+- **Decorative chevrons should be icons not angle quotes
+  ([17245](https://github.com/civicrm/civicrm-core/pull/17245))**
+
+- **A/B Test - Icon should be Erlenmeyer flask, not bar chart
+  ([17316](https://github.com/civicrm/civicrm-core/pull/17316))**
+
+- **Proceeding to confirmation page should be a "next" button not a check
+  ([17246](https://github.com/civicrm/civicrm-core/pull/17246))**
+
+### CiviCase
+
+- **Case Activity: Follow-up activity assignee does not receive email
+  ([dev/core#1721](https://lab.civicrm.org/dev/core/-/issues/1721):
+  [17116](https://github.com/civicrm/civicrm-core/pull/17116))**
+
+  Ensures when a follow up case activity is created the assignee is sent an
+  email.
+
+### CiviContribute
+
+- **Custom fields disappear on page refresh
+  ([dev/core#1728](https://lab.civicrm.org/dev/core/-/issues/1728):
+  [17301](https://github.com/civicrm/civicrm-core/pull/17301))**
+
+  This ensures that financial type specific custom fields are displayed on the
+  backend contribution form when it is refreshed.
+
+- **Fix pricefield pseudoconstant.
+  ([17364](https://github.com/civicrm/civicrm-core/pull/17364))**
+
+  Fixes `PriceField` entity to build options for the `price_set_id`
+  pseudoconstant field.
+
+- **Nuance cancel options for processors
+  ([17430](https://github.com/civicrm/civicrm-core/pull/17430))**
+
+  This allows payment processors to specify the way they allow cancellation of
+  recurring contributions.
+
+- **[regression] Contribution amount choices don't appear for anonymous users
+  ([dev/core#1823](https://lab.civicrm.org/dev/core/-/issues/1823):
+  [17619](https://github.com/civicrm/civicrm-core/pull/17619))**
+
+- **Import Contribution of custom fields only accepts "Numeric Value" rather
+  than "Label" ([dev/core#1806](https://lab.civicrm.org/dev/core/-/issues/1806):
+  [17632](https://github.com/civicrm/civicrm-core/pull/17632))**
+
+- **"Financial Type" listed twice in contribution export
+  ([dev/core#1650](https://lab.civicrm.org/dev/core/-/issues/1650):
+  [17147](https://github.com/civicrm/civicrm-core/pull/17147))**
+
+- **Record Payment does not update check_number & trxn id on main contribution.
+  ([dev/core#1758](https://lab.civicrm.org/dev/core/-/issues/1758):
+  [17314](https://github.com/civicrm/civicrm-core/pull/17314))**
+
+- **civicrm_financial_trxn.fee_amount reversals mixed up
+  ([dev/core#1775](https://lab.civicrm.org/dev/core/-/issues/1775):
+  [17386](https://github.com/civicrm/civicrm-core/pull/17386))**
+
+- **jquery validation type error on the credit card field
+  ([dev/core#1797](https://lab.civicrm.org/dev/core/-/issues/1797):
+  [17497](https://github.com/civicrm/civicrm-core/pull/17497))**
+
+  Fixes a jQuery error when submitting a front end contribution form with a
+  credit card field.
+
+- **Fix payment instrument bug by using correct payment instrument
+  ([17607](https://github.com/civicrm/civicrm-core/pull/17607))**
+
+  When a backend payment form records a payment it now will use a
+  processor-specific default payment instrument rather than the site-wide
+  default if it is set.
+
+- **Payment PropertyBag - Fix setAmount
+  ([17505](https://github.com/civicrm/civicrm-core/pull/17505))**
+
+  Ensures "Amount" is set correctly on PropertyBag.
+
+- **Fixed hide show of start date
+  ([17446](https://github.com/civicrm/civicrm-core/pull/17446))**
+
+  Fix hide/show of receive date for recurring contributions.
+
+- **Don't allow Contribution.repeattransaction to be used without a recurring
+  contribution ([17447](https://github.com/civicrm/civicrm-core/pull/17447))**
+
+- **Add actual field name for processor_id to getSubscriptionDetails
+  ([17466](https://github.com/civicrm/civicrm-core/pull/17466))**
+
+- **Make 'Pending' the default status for Contribution.repeattransaction
+  ([17432](https://github.com/civicrm/civicrm-core/pull/17432))**
+
+- **Fetch line items from correct contribution when repeating a contribution
+  ([17220](https://github.com/civicrm/civicrm-core/pull/17220))**
+
+- **Support order_reference param in API3 Payment.create
+  ([17278](https://github.com/civicrm/civicrm-core/pull/17278))**
+
+- **E_WARNINGS when viewing list of pledge payments
+  ([dev/core#1791](https://lab.civicrm.org/dev/core/-/issues/1791):
+  [17434](https://github.com/civicrm/civicrm-core/pull/17434))**
+
+- **Add propertyBag handling for getEmail when incoming uses email-5
+  ([17267](https://github.com/civicrm/civicrm-core/pull/17267))**
+
+  Payment processors can now retrieve billing email using the `propertyBag`
+  class methods.
+
+### CiviMail
+
+- **Don't log subscription_history
+  ([dev/core#1762](https://lab.civicrm.org/dev/core/-/issues/1762):
+  [17323](https://github.com/civicrm/civicrm-core/pull/17323))**
+
+  The `civicrm_subscription_history` table is effectively a log of contacts
+  being added to and removed from groups.  Rows do not change value; each change
+  in group subscription results in a new row.  Consequently, there is no reason
+  to attach detailed logging to this table.
+
+- **Unsubscribe generates 500 server error responses, logs say "missing
+  parameters" ([dev/core#1773](https://lab.civicrm.org/dev/core/-/issues/1773):
+  [17402](https://github.com/civicrm/civicrm-core/pull/17402))**
+
+  Ensures the unsubscribe form can only be submitted once.
+
+### CiviMember
+
+- **Recurring contribution fails with "ipn_payment_callback_exception", for
+  membership auto-renewal via PayPalPro.
+  ([dev/core#1608](https://lab.civicrm.org/dev/core/-/issues/1608):
+  [17355](https://github.com/civicrm/civicrm-core/pull/17355))**
+
+- **Don't hide disabled memberships from the contact membership tab
+  ([dev/membership#24](https://lab.civicrm.org/dev/membership/-/issues/24):
+  [17143](https://github.com/civicrm/civicrm-core/pull/17143) and
+  [17435](https://github.com/civicrm/civicrm-core/pull/17435))**
+
+  This resolves a problem where memberships of disabled membership types would
+  not appear on the membership tab but would throw a duplicate membership
+  warning when creating a new membership with the same membership organization.
+  This also adds a unit test to lock in the correct behavior.
+
+- **Update MembershipType.name to be a required field
+  ([17463](https://github.com/civicrm/civicrm-core/pull/17463))**
+
+- **Fix PHP notice when is_override is not set
+  ([17273](https://github.com/civicrm/civicrm-core/pull/17273))**
+
+### Joomla Integration
+
+- **Upgrade from 5.26.2 to 5.27 RC Fails
+  ([dev/joomla/#28](https://lab.civicrm.org/dev/joomla/-/issues/28):
+  [17710](https://github.com/civicrm/civicrm-core/pull/17710))**
+
+### WordPress Integration
+
+- **Styling issues after upgrade to WordPress 5.3
+  ([dev/wordpress#46](https://lab.civicrm.org/dev/wordpress/-/issues/46):
+  [16967](https://github.com/civicrm/civicrm-core/pull/16967))**
+
+- **WP - Change definitions of `cms.root`, `civicrm.root`
+  ([17360](https://github.com/civicrm/civicrm-core/pull/17360))**
+
+  The base logic for computing path/URL defaults is in Civi/Core/Paths.php.
+
+  For CiviCRM on WordPress, certain variables (which are easier to compute via
+  WordPress APIs) are overridden in `CRM_Utils_System_WordPress`.
+
+  On WordPress, the path/URL logic for has been split: there is one code path
+  for normal CiviCRM pages which is based on WordPress APIs, and there is
+  another for older, standalone scripts in the `extern` folder which is based on
+  the same logic as before.
+
+- **Declare minimum WP and PHP versions required for installation
+  ([201](https://github.com/civicrm/civicrm-wordpress/pull/201))**
+
+- **wp-rest - Adjust extern URL. Be more defensive about 'query' part.
+  ([192](https://github.com/civicrm/civicrm-wordpress/pull/192))**
+
+  This resolves issues with tracking URLs via the `wp-rest` endpoint that are
+  then modified with `hook_civicrm_alterExternUrl`.
+
+## <a name="misc"></a>Miscellany
+
+- **Handle less common dynamic reference cases
+  ([17653](https://github.com/civicrm/civicrm-core/pull/17653))**
+
+- **Use apiv4, cache infra for basicTypes
+  ([17387](https://github.com/civicrm/civicrm-core/pull/17387))**
+
+- **Cleanup PriceFieldValue BAO
+  ([17306](https://github.com/civicrm/civicrm-core/pull/17306))**
+
+- **Clarify definition of amount field in civicrm_contribution_recur table.
+  ([17311](https://github.com/civicrm/civicrm-core/pull/17311))**
+
+- **Call completeOrder directly from contribute status update form
+  ([17347](https://github.com/civicrm/civicrm-core/pull/17347))**
+
+- **Switch docblock code to use markdown syntax.
+  ([17304](https://github.com/civicrm/civicrm-core/pull/17304))**
+
+- **Preliminary cleanup on form
+  ([17345](https://github.com/civicrm/civicrm-core/pull/17345))**
+
+- **Add getBAOClassName utiltiy function
+  ([17268](https://github.com/civicrm/civicrm-core/pull/17268))**
+
+- **CRM/Logging - Remove obsolete cache static clear in test
+  ([17269](https://github.com/civicrm/civicrm-core/pull/17269))**
+
+- **Remove incorrect retrievals of tax-term setting
+  ([17183](https://github.com/civicrm/civicrm-core/pull/17183))**
+
+- **CiviEvent Dashboard and Manage Events: clean up disused url template vars
+  ([17378](https://github.com/civicrm/civicrm-core/pull/17378))**
+
+- **Set default using spec for activity_date_time
+  ([17390](https://github.com/civicrm/civicrm-core/pull/17390))**
+
+- **Convert remaining Authorize.net test to use guzzle
+  ([17473](https://github.com/civicrm/civicrm-core/pull/17473))**
+
+- **Various BAO create/add cleanups to use writeRecord()
+  ([17308](https://github.com/civicrm/civicrm-core/pull/17308))**
+
+- **Remove instantiation of transaction from payment express ipn class
+  ([17348](https://github.com/civicrm/civicrm-core/pull/17348))**
+
+- **Remove null code
+  ([17381](https://github.com/civicrm/civicrm-core/pull/17381))**
+
+- **Remove validation bypass
+  ([17384](https://github.com/civicrm/civicrm-core/pull/17384))**
+
+- **Simplify recurring contribution template inheritance
+  ([17178](https://github.com/civicrm/civicrm-core/pull/17178))**
+
+- **Remove $_REQUEST passed into CRM_Utils_Request::retrieve NFC
+  ([17377](https://github.com/civicrm/civicrm-core/pull/17377))**
+
+- **Use now instead of date for activity API3 spec
+  ([17411](https://github.com/civicrm/civicrm-core/pull/17411))**
+
+- **Typo Fix ([17409](https://github.com/civicrm/civicrm-core/pull/17409))**
+
+- **Fix logic for job log cleanup and make SQL safer
+  ([17203](https://github.com/civicrm/civicrm-core/pull/17203))**
+
+- **Remove always-true if block.
+  ([17415](https://github.com/civicrm/civicrm-core/pull/17415))**
+
+- **Remove No longer required HTTP_Request Package
+  ([293](https://github.com/civicrm/civicrm-packages/pull/293))**
+
+- **Remove code that still seems unnecessary.
+  ([17342](https://github.com/civicrm/civicrm-core/pull/17342))**
+
+- **Undo variable variable.
+  ([17371](https://github.com/civicrm/civicrm-core/pull/17371))**
+
+- **Use non-deprecated method
+  ([17370](https://github.com/civicrm/civicrm-core/pull/17370))**
+
+- **Remove last reference to Payment->_processorName in core & remove from
+  processors ([17474](https://github.com/civicrm/civicrm-core/pull/17474))**
+
+- **Remove unused singleton from core payment processors
+  ([17468](https://github.com/civicrm/civicrm-core/pull/17468))**
+
+- **Test fixes to support apiv4 add of MembershipType
+  ([17488](https://github.com/civicrm/civicrm-core/pull/17488))**
+
+- **Merge code - remove UPDATE IGNORE+Delete & just use reliable update
+  ([17072](https://github.com/civicrm/civicrm-core/pull/17072))**
+
+- **Remove unneeded parameters in {ts} on membership form
+  ([17326](https://github.com/civicrm/civicrm-core/pull/17326))**
+
+- **Remove unused 'reset' param, other NFC tidy up:
+  ([17392](https://github.com/civicrm/civicrm-core/pull/17392))**
+
+- **Fix setLanguage docblock, other nfc changes
+  ([17356](https://github.com/civicrm/civicrm-core/pull/17356))**
+
+- **[REF] Simplify contributionIDs code
+  ([17441](https://github.com/civicrm/civicrm-core/pull/17441))**
+
+- **[REF] Extract getAttachments
+  ([17405](https://github.com/civicrm/civicrm-core/pull/17405))**
+
+- **[REF] Preliminary cleanup for #17339
+  ([17417](https://github.com/civicrm/civicrm-core/pull/17417))**
+
+- **[REF] Remove unreachable block.
+  ([17407](https://github.com/civicrm/civicrm-core/pull/17407))**
+
+- **[REF] Pass an array of correct params to the function to create a recurring
+  contribution. ([17398](https://github.com/civicrm/civicrm-core/pull/17398))**
+
+- **[REF] Code simplification & unit test on suppressed emails in task
+  ([17393](https://github.com/civicrm/civicrm-core/pull/17393))**
+
+- **[REF] duplicate function.
+  ([17400](https://github.com/civicrm/civicrm-core/pull/17400))**
+
+- **[REF] Pass params not-by-reference
+  ([17406](https://github.com/civicrm/civicrm-core/pull/17406))**
+
+- **[REF] Refactor to switch from pear HTTP Request class to using Guzzle
+  ([17420](https://github.com/civicrm/civicrm-core/pull/17420))**
+
+- **[REF] [Reports] Ensure that all contribution pages including disabled ones
+  are return… ([17357](https://github.com/civicrm/civicrm-core/pull/17357))**
+
+- **[REF] Cleanup and extract string functions specific to entity names.
+  ([17330](https://github.com/civicrm/civicrm-core/pull/17330))**
+
+- **[REF] Stop passing  by reference.
+  ([17349](https://github.com/civicrm/civicrm-core/pull/17349))**
+
+- **[REF] Simplify subject code.
+  ([17436](https://github.com/civicrm/civicrm-core/pull/17436))**
+
+- **[REF] Implement required fields database changes that have occured du…
+  ([17465](https://github.com/civicrm/civicrm-core/pull/17465), [17725](https://github.com/civicrm/civicrm-core/pull/17725))**
+
+- **[REF] Bump Pear Log version to fix compatability with Drupal 8 / Drup…
+  ([17460](https://github.com/civicrm/civicrm-core/pull/17460))**
+
+- **[REF] Convert one of the http calls in Authorize.net class to use guzzle.
+  ([17449](https://github.com/civicrm/civicrm-core/pull/17449))**
+
+- **[REF] Minor simplification
+  ([17443](https://github.com/civicrm/civicrm-core/pull/17443))**
+
+- **[REF] Grant BAO cleanup
+  ([17264](https://github.com/civicrm/civicrm-core/pull/17264))**
+
+- **[REF] CRM_Core_DAO_AllCoreTables::getBriefName to accept BAO name
+  ([17331](https://github.com/civicrm/civicrm-core/pull/17331))**
+
+- **[REF] Missing semicolon on smtp settings page, code cleanup in file-on-case,
+  add test ([17335](https://github.com/civicrm/civicrm-core/pull/17335))**
+
+- **[REF] Extract createFollowUpActivities
+  ([17481](https://github.com/civicrm/civicrm-core/pull/17481))**
+
+- **[REF] Switch to an api call to get the contact details.
+  ([17442](https://github.com/civicrm/civicrm-core/pull/17442))**
+
+- **[REF] Minor code simplification
+  ([17373](https://github.com/civicrm/civicrm-core/pull/17373))**
+
+- **[REF] Call completeOrder directly from event status update form
+  ([17346](https://github.com/civicrm/civicrm-core/pull/17346))**
+
+- **[REF] Remove never-passed params from function signature
+  ([17464](https://github.com/civicrm/civicrm-core/pull/17464))**
+
+- **[REF] Fix serialized membership field handling in RelationshipTest
+  ([17469](https://github.com/civicrm/civicrm-core/pull/17469))**
+
+- **[REF] Minor tidy up
+  ([17302](https://github.com/civicrm/civicrm-core/pull/17302))**
+
+- **[REF] Remove always NULL param modified_id
+  ([17489](https://github.com/civicrm/civicrm-core/pull/17489))**
+
+- **[REF] Add contribution_id field to search using metadata instead of h…
+  ([17286](https://github.com/civicrm/civicrm-core/pull/17286))**
+
+- **[REF] Fix unit test failures on MySQL 5.6 due to Custom Field table being
+  created without Dynamic Row Format
+  ([17586](https://github.com/civicrm/civicrm-core/pull/17586))**
+
+- **[REF] Start to convert Dummy processor to use PropertyBag
+  ([17452](https://github.com/civicrm/civicrm-core/pull/17452))**
+
+- **[Ref] remove calls to, and deprecate, pending function
+  ([17490](https://github.com/civicrm/civicrm-core/pull/17490))**
+
+- **[REF] Cleanup MailingAB BAO
+  ([17309](https://github.com/civicrm/civicrm-core/pull/17309))**
+
+- **[TEST] Update test to support for 8.0.19 change
+  ([17354](https://github.com/civicrm/civicrm-core/pull/17354))**
+
+- **[TEST] Fix test failure on Drupal 8 E2E PrevNextTest by only includin…
+  ([17358](https://github.com/civicrm/civicrm-core/pull/17358))**
+
+- **[TEST] dev/core#1766 - Remove flakiness from testGetFromTo tests
+  ([dev/core#1766](https://lab.civicrm.org/dev/core/-/issues/1766):
+  [17338](https://github.com/civicrm/civicrm-core/pull/17338))**
+
+- **[NFC/TEST] dev/core#1784 - Unit tests for contact delete/restore
+  ([dev/core#1784](https://lab.civicrm.org/dev/core/-/issues/1784):
+  [17437](https://github.com/civicrm/civicrm-core/pull/17437))**
+
+- **NFC - Change array() to short syntax []
+  ([17470](https://github.com/civicrm/civicrm-core/pull/17470))**
+
+- **[NFC] Update Karma to be latest version
+  ([17439](https://github.com/civicrm/civicrm-core/pull/17439))**
+
+- **(NFC) CRM_Utils_Url - Fix declared type
+  ([17320](https://github.com/civicrm/civicrm-core/pull/17320))**
+
+- **[NFC] Remove some more of the old  cvs blocks
+  ([17383](https://github.com/civicrm/civicrm-core/pull/17383))**
+
+- **NFC Add a bit more clarity to createEmailActivity function
+  ([17391](https://github.com/civicrm/civicrm-core/pull/17391))**
+
+- **[NFC] Add comment that deprecated code is actually still reachable
+  ([17340](https://github.com/civicrm/civicrm-core/pull/17340))**
+
+- **(NFC) Remove some cvs docblock help
+  ([17322](https://github.com/civicrm/civicrm-core/pull/17322))**
+
+- **[NFC] Add comment regarding lower case for Polish states
+  ([17327](https://github.com/civicrm/civicrm-core/pull/17327))**
+
+- **(NFC) RegionTest - Small cleanups
+  ([17270](https://github.com/civicrm/civicrm-core/pull/17270))**
+
+- **[NFC] Add sr-only class for content only for screen readers
+  ([17255](https://github.com/civicrm/civicrm-core/pull/17255))**
+
+- **NFC Change hardcoded ID to constant
+  ([17275](https://github.com/civicrm/civicrm-core/pull/17275))**
+
+- **[NFC] Fix use of single quotes, strict operator
+  ([17492](https://github.com/civicrm/civicrm-core/pull/17492))**
+
+## <a name="credits"></a>Credits
+
+This release was developed by the following code authors:
+
+a-n The Artists Information Company - William Mortada; AGH Strategies - Alice
+Frumin, Andrew Hunt; Andrei Mondoc; British Humanist Association - Andrew West;
+Caltha - Tomasz Pietrzkowski; Christian Wach; Circle Interactive - Pradeep
+Nayak; CiviCRM - Coleman Watts, Tim Otten; CiviDesk - Yashodha Chaku;
+CompuCorp - René Olivo; Coop SymbioTIC - Mathieu Lutfy; Dave D; Dominic Hargreaves;
+Electronic Frontier Foundation - Mark Burdett; Freeform Solutions - Herb van den
+Dool; Fuzion - Jitendra Purohit; Greenpeace Central and Eastern Europe - Patrick
+Figel; JMA Consulting - Edsel Lopez, Seamus Lee; John Kingsnorth; Joinery -
+Allen Shaw; Kartik Kathuria; Lighthouse Design and Consulting - Brian
+Shaughnessy; Megaphone Technology Consulting - Jon Goldberg; MJCO - Mikey
+O'Toole; MJW Consulting - Matthew Wire; Palante Technology Cooperative - Morgan
+Robinson; Semper IT - Karin Gerritsen; Tadpole Collective - Kevin Cristiano;
+Wikimedia Foundation - Eileen McNaughton
+
+Most authors also reviewed code for this release; in addition, the following
+reviewers contributed their comments:
+
+Agileware - Justin Freeman; Artful Robot - Rich Lott; Betty Dolfing; CiviCoop -
+Jaap Jansma; iXiam - Luciano Spiegel; JMA Consulting - Monish Deb; Kartik
+Kathuria; Korlon - Stuart Gaston; Megaphone Technology Consulting - Dennis P.
+Osorio; Squiffle Consulting - Aidan Saunders
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Alice Frumin and Andrew Hunt.  If you'd like
+to provide feedback on them, please log in to https://chat.civicrm.org/civicrm
+and contact `@agh1`.
diff --git a/civicrm/settings/Core.setting.php b/civicrm/settings/Core.setting.php
index 349f266bde..0f1f8aab13 100644
--- a/civicrm/settings/Core.setting.php
+++ b/civicrm/settings/Core.setting.php
@@ -239,6 +239,28 @@ return [
     'description' => NULL,
     'help_text' => NULL,
   ],
+  'defaultExternUrl' => [
+    'group_name' => 'CiviCRM Preferences',
+    'group' => 'core',
+    'name' => 'defaultExternUrl',
+    'type' => 'String',
+    'quick_form_type' => 'Select',
+    'html_type' => 'Select',
+    'html_attributes' => [
+      'class' => 'crm-select2',
+    ],
+    'default' => 'router',
+    'add' => '5.27',
+    'title' => ts('Extern URL Style'),
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'description' => ts('This setting provides transitional support. It should be set to "Prefer normal router." If your deployment requires "Prefer standalone script", then please ensure that the issue is tracked in <code>lab.civicrm.org</code>.'),
+    'help_text' => NULL,
+    'options' => [
+      'standalone' => ts('Prefer standalone scripts'),
+      'router' => ts('Prefer normal router'),
+    ],
+  ],
   'activity_assignee_notification' => [
     'group_name' => 'CiviCRM Preferences',
     'group' => 'core',
@@ -522,7 +544,7 @@ return [
     'html_type' => 'text',
     'default' => NULL,
     'add' => '4.3',
-    'title' => ts('Recaptcha Options'),
+    'title' => ts('reCAPTCHA Options'),
     'is_domain' => 1,
     'is_contact' => 0,
     'description' => ts('You can specify the reCAPTCHA theme options as comma separated data.(eg: theme:\'blackglass\', lang : \'fr\' ). Check the available options at <a href="https://developers.google.com/recaptcha/docs/display#config">Customizing the Look and Feel of reCAPTCHA</a>.'),
@@ -541,7 +563,7 @@ return [
     'html_type' => 'text',
     'default' => NULL,
     'add' => '4.3',
-    'title' => ts('Recaptcha Site Key'),
+    'title' => ts('reCAPTCHA Site Key'),
     'is_domain' => 1,
     'is_contact' => 0,
     'description' => NULL,
@@ -575,7 +597,7 @@ return [
     'html_type' => 'text',
     'default' => NULL,
     'add' => '4.3',
-    'title' => ts('Recaptcha Secret Key'),
+    'title' => ts('reCAPTCHA Secret Key'),
     'is_domain' => 1,
     'is_contact' => 0,
     'description' => NULL,
diff --git a/civicrm/settings/Mailing.setting.php b/civicrm/settings/Mailing.setting.php
index a2a5bc06c8..2e2640956a 100644
--- a/civicrm/settings/Mailing.setting.php
+++ b/civicrm/settings/Mailing.setting.php
@@ -341,4 +341,32 @@ return [
     'description' => ts('Allow sending email from the logged in contact\'s email address.'),
     'help_text' => 'CiviCRM allows you to send email from the domain from email addresses and the logged in contact id addresses by default. Disable this if you only want to allow the domain from addresses to be used.',
   ],
+  'url_tracking_default' => [
+    'group_name' => 'Mailing Preferences',
+    'group' => 'mailing',
+    'name' => 'url_tracking_default',
+    'type' => 'Boolean',
+    'html_type' => 'checkbox',
+    'quick_form_type' => 'CheckBox',
+    'default' => '1',
+    'title' => ts('Enable click-through tracking by default'),
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'description' => ts('If checked, mailings will have click-through tracking enabled by default.'),
+    'help_text' => NULL,
+  ],
+  'open_tracking_default' => [
+    'group_name' => 'Mailing Preferences',
+    'group' => 'mailing',
+    'name' => 'open_tracking_default',
+    'type' => 'Boolean',
+    'html_type' => 'checkbox',
+    'quick_form_type' => 'CheckBox',
+    'default' => '1',
+    'title' => ts('Enable open tracking by default'),
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'description' => ts('If checked, mailings will have open tracking enabled by default.'),
+    'help_text' => NULL,
+  ],
 ];
diff --git a/civicrm/settings/Search.setting.php b/civicrm/settings/Search.setting.php
index 427bc8a6c6..c9a02e963e 100644
--- a/civicrm/settings/Search.setting.php
+++ b/civicrm/settings/Search.setting.php
@@ -65,7 +65,7 @@ return [
     'html_type' => 'text',
     'default' => 'simple',
     'add' => '4.5',
-    'title' => ts('How to handle full-tet queries'),
+    'title' => ts('How to handle full-text queries'),
     'is_domain' => 1,
     'is_contact' => 0,
     'help_text' => NULL,
diff --git a/civicrm/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php b/civicrm/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php
index b2c0a17446..3592e35435 100644
--- a/civicrm/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php
+++ b/civicrm/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php
@@ -2,7 +2,15 @@
 /**
  * @file
  *
- * Perform the first system bootstrap.
+ * Perform the full bootstrap.
+ *
+ * GOAL: All the standard services (database, DAOs, translations, settings, etc) should be loaded.
+ *
+ * MECHANICS: This basically calls `CRM_Core_Config::singleton(TRUE,TRUE)`.
+ *
+ * NOTE: This is technically a *reboot*. `Preboot` started things off, but it
+ * booted with `CRM_Core_Config::singleton($loadFromDB==FALSE)`. Now, the DB is
+ * populated, so we can teardown the preboot stuff and start again with `$loadFromDB==TRUE`.
  */
 
 if (!defined('CIVI_SETUP')) {
@@ -13,19 +21,9 @@ if (!defined('CIVI_SETUP')) {
   ->addListener('civi.setup.installDatabase', function (\Civi\Setup\Event\InstallDatabaseEvent $e) {
     \Civi\Setup::log()->info(sprintf('[%s] Bootstrap CiviCRM', basename(__FILE__)));
 
-    if (!defined('CIVICRM_SETTINGS_PATH')) {
-      define('CIVICRM_SETTINGS_PATH', $e->getModel()->settingsPath);
-    }
-
-    if (realpath(CIVICRM_SETTINGS_PATH) !== realpath($e->getModel()->settingsPath)) {
-      throw new \RuntimeException(sprintf("Cannot boot: The civicrm.settings.php path appears inconsistent (%s vs %s)", CIVICRM_SETTINGS_PATH, $e->getModel()->settingsPath));
-    }
-
-    include_once CIVICRM_SETTINGS_PATH;
-
-    require_once 'CRM/Core/ClassLoader.php';
-    CRM_Core_ClassLoader::singleton()->register();
+    \CRM_Core_I18n::$SQL_ESCAPER = NULL;
+    unset(\Civi::$statics['testPreInstall']);
 
-    CRM_Core_Config::singleton(TRUE);
+    CRM_Core_Config::singleton(TRUE, TRUE);
 
   }, \Civi\Setup::PRIORITY_MAIN - 200);
diff --git a/civicrm/setup/plugins/installDatabase/InstallSchema.civi-setup.php b/civicrm/setup/plugins/installDatabase/InstallSchema.civi-setup.php
index fec273ce07..1455edab09 100644
--- a/civicrm/setup/plugins/installDatabase/InstallSchema.civi-setup.php
+++ b/civicrm/setup/plugins/installDatabase/InstallSchema.civi-setup.php
@@ -68,11 +68,6 @@ class InstallSchemaPlugin implements \Symfony\Component\EventDispatcher\EventSub
     $sqlPath = $model->srcPath . DIRECTORY_SEPARATOR . 'sql';
     $spec = $this->loadSpecification($model->srcPath);
 
-    $conn = \Civi\Setup\DbUtil::connect($model->db);
-    \CRM_Core_I18n::$SQL_ESCAPER = function($text) use ($conn) {
-      return $conn->escape_string($text);
-    };
-
     \Civi\Setup::log()->info(sprintf('[%s] Load basic tables', basename(__FILE__)));
     \Civi\Setup\DbUtil::sourceSQL($model->db, \Civi\Setup\SchemaGenerator::generateCreateSql($model->srcPath, $spec->database, $spec->tables));
 
@@ -89,11 +84,6 @@ class InstallSchemaPlugin implements \Symfony\Component\EventDispatcher\EventSub
       \Civi\Setup::log()->info(sprintf('[%s] Load basic data', basename(__FILE__)));
       \Civi\Setup\DbUtil::sourceSQL($model->db, \Civi\Setup\SchemaGenerator::generateBasicData($model->srcPath));
     }
-
-    require_once $model->settingsPath;
-    \Civi\Core\Container::boot(TRUE);
-
-    \CRM_Core_I18n::$SQL_ESCAPER = NULL;
   }
 
   /**
diff --git a/civicrm/setup/plugins/installDatabase/Preboot.civi-setup.php b/civicrm/setup/plugins/installDatabase/Preboot.civi-setup.php
new file mode 100644
index 0000000000..116a502467
--- /dev/null
+++ b/civicrm/setup/plugins/installDatabase/Preboot.civi-setup.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @file
+ *
+ * Perform an initial, partial bootstrap.
+ *
+ * GOAL: This should provide sufficient services for `InstallSchema` to generate
+ * For example, `ts()` needs to be online.
+ *
+ * MECHANICS: This basically loads `civicrm.settings.php` and calls
+ * `CRM_Core_Config::singleton(FALSE,TRUE)`.
+ */
+
+if (!defined('CIVI_SETUP')) {
+  exit("Installation plugins must only be loaded by the installer.\n");
+}
+
+\Civi\Setup::dispatcher()
+  ->addListener('civi.setup.checkRequirements', function (\Civi\Setup\Event\CheckRequirementsEvent $e) {
+
+  });
+
+\Civi\Setup::dispatcher()
+  ->addListener('civi.setup.installDatabase', function (\Civi\Setup\Event\InstallDatabaseEvent $e) {
+    \Civi\Setup::log()->info(sprintf('[%s] Load minimal (non-DB) services', basename(__FILE__)));
+
+    if (!defined('CIVICRM_SETTINGS_PATH')) {
+      define('CIVICRM_SETTINGS_PATH', $e->getModel()->settingsPath);
+    }
+
+    if (realpath(CIVICRM_SETTINGS_PATH) !== realpath($e->getModel()->settingsPath)) {
+      throw new \RuntimeException(sprintf("Cannot boot: The civicrm.settings.php path appears inconsistent (%s vs %s)", CIVICRM_SETTINGS_PATH, $e->getModel()->settingsPath));
+    }
+
+    include_once CIVICRM_SETTINGS_PATH;
+
+    require_once 'CRM/Core/ClassLoader.php';
+    CRM_Core_ClassLoader::singleton()->register();
+
+    $conn = \Civi\Setup\DbUtil::connect($e->getModel()->db);
+    \CRM_Core_I18n::$SQL_ESCAPER = function($text) use ($conn) {
+      return $conn->escape_string($text);
+    };
+
+    \Civi::$statics['testPreInstall'] = 1;
+
+    CRM_Core_Config::singleton(FALSE, TRUE);
+
+  }, \Civi\Setup::PRIORITY_PREPARE);
diff --git a/civicrm/sql/civicrm.mysql b/civicrm/sql/civicrm.mysql
index 22d81d0476..0f15db4a6e 100644
--- a/civicrm/sql/civicrm.mysql
+++ b/civicrm/sql/civicrm.mysql
@@ -940,7 +940,7 @@ CREATE TABLE `civicrm_mailing_abtest` (
      `mailing_id_a` int unsigned    COMMENT 'The first experimental mailing (\"A\" condition)',
      `mailing_id_b` int unsigned    COMMENT 'The second experimental mailing (\"B\" condition)',
      `mailing_id_c` int unsigned    COMMENT 'The final, general mailing (derived from A or B)',
-     `domain_id` int unsigned    COMMENT 'Which site is this mailing for',
+     `domain_id` int unsigned NOT NULL   COMMENT 'Which site is this mailing for',
      `testing_criteria` varchar(32)    ,
      `winner_criteria` varchar(32)    ,
      `specific_url` varchar(255)    COMMENT 'What specific url to track',
@@ -1815,6 +1815,7 @@ CREATE TABLE `civicrm_custom_field` (
      `note_rows` int unsigned    COMMENT 'Number of rows in Note Field',
      `column_name` varchar(255)    COMMENT 'Name of the column that holds the values for this field.',
      `option_group_id` int unsigned    COMMENT 'For elements with options, the option group id that is used',
+     `serialize` int unsigned    COMMENT 'Serialization method - a non-null value indicates a multi-valued field.',
      `filter` varchar(255)    COMMENT 'Stores Contact Get API params contact reference custom fields. May be used for other filters in the future.',
      `in_selector` tinyint   DEFAULT 0 COMMENT 'Should the multi-record custom field values be displayed in tab table listing' 
 ,
@@ -2219,7 +2220,7 @@ CREATE TABLE `civicrm_option_value` (
      `value` varchar(512) NOT NULL   COMMENT 'The actual value stored (as a foreign key) in the data record. Functions which need lookup option_value.title should use civicrm_option_value.option_group_id plus civicrm_option_value.value as the key.',
      `name` varchar(255)    COMMENT 'Stores a fixed (non-translated) name for this option value. Lookup functions should use the name as the key for the option value row.',
      `grouping` varchar(255)    COMMENT 'Use to sort and/or set display properties for sub-set(s) of options within an option group. EXAMPLE: Use for college_interest field, to differentiate partners from non-partners.',
-     `filter` int unsigned   DEFAULT NULL COMMENT 'Bitwise logic can be used to create subsets of options within an option_group for different uses.',
+     `filter` int unsigned   DEFAULT 0 COMMENT 'Bitwise logic can be used to create subsets of options within an option_group for different uses.',
      `is_default` tinyint   DEFAULT 0 COMMENT 'Is this the default option for the group?',
      `weight` int unsigned NOT NULL   COMMENT 'Controls display sort order.',
      `description` text    COMMENT 'Optional description.',
@@ -3039,7 +3040,7 @@ CREATE TABLE `civicrm_membership_type` (
 
      `id` int unsigned NOT NULL AUTO_INCREMENT  COMMENT 'Membership Id',
      `domain_id` int unsigned NOT NULL   COMMENT 'Which Domain is this match entry for',
-     `name` varchar(128)    COMMENT 'Name of Membership Type',
+     `name` varchar(128) NOT NULL   COMMENT 'Name of Membership Type',
      `description` varchar(255)    COMMENT 'Description of Membership Type',
      `member_of_contact_id` int unsigned NOT NULL   COMMENT 'Owner organization for this membership type. FK to Contact ID',
      `financial_type_id` int unsigned NOT NULL   COMMENT 'If membership is paid by a contribution - what financial type should be used. FK to civicrm_financial_type.id',
@@ -4041,7 +4042,7 @@ CREATE TABLE `civicrm_contribution_recur` (
 
      `id` int unsigned NOT NULL AUTO_INCREMENT  COMMENT 'Contribution Recur ID',
      `contact_id` int unsigned NOT NULL   COMMENT 'Foreign key to civicrm_contact.id.',
-     `amount` decimal(20,2) NOT NULL   COMMENT 'Amount to be contributed or charged each recurrence.',
+     `amount` decimal(20,2) NOT NULL   COMMENT 'Amount to be collected (including any sales tax) by payment processor each recurrence.',
      `currency` varchar(3)   DEFAULT NULL COMMENT '3 character string, value from config setting or input via user.',
      `frequency_unit` varchar(8)   DEFAULT 'month' COMMENT 'Time units for recurrence of payment.',
      `frequency_interval` int unsigned NOT NULL   COMMENT 'Number of time units for recurrence of payment.',
@@ -4355,8 +4356,8 @@ CREATE TABLE `civicrm_price_field_value` (
 
      `id` int unsigned NOT NULL AUTO_INCREMENT  COMMENT 'Price Field Value',
      `price_field_id` int unsigned NOT NULL   COMMENT 'FK to civicrm_price_field',
-     `name` varchar(255)    COMMENT 'Price field option name',
-     `label` varchar(255)    COMMENT 'Price field option label',
+     `name` varchar(255) NOT NULL   COMMENT 'Price field option name',
+     `label` varchar(255) NOT NULL   COMMENT 'Price field option label',
      `description` text   DEFAULT NULL COMMENT 'Price field option description.',
      `help_pre` text   DEFAULT NULL COMMENT 'Price field option pre help text.',
      `help_post` text   DEFAULT NULL COMMENT 'Price field option post field help.',
diff --git a/civicrm/sql/civicrm_data.mysql b/civicrm/sql/civicrm_data.mysql
index 477f8b1bd5..e8692dec6f 100644
--- a/civicrm/sql/civicrm_data.mysql
+++ b/civicrm/sql/civicrm_data.mysql
@@ -399,6 +399,7 @@ INSERT INTO civicrm_state_province (id, country_id, abbreviation, name) VALUES
 (1231, 1101, "DL", "Delhi"),
 (1232, 1101, "LD", "Lakshadweep"),
 (1233, 1101, "PY", "Pondicherry"),
+-- Note we believe all lower-case is correct for Poland. See https://github.com/civicrm/civicrm-core/pull/17107
 (1300, 1172, "MZ", "mazowieckie"),
 (1301, 1172, "PM", "pomorskie"),
 (1302, 1172, "DS", "dolnośląskie"),
@@ -23896,4 +23897,4 @@ INSERT INTO `civicrm_report_instance`
     ( `domain_id`, `title`, `report_id`, `description`, `permission`, `form_values`)
 VALUES
     (  @domainID, 'Survey Details', 'survey/detail', 'Detailed report for canvassing, phone-banking, walk lists or other surveys.', 'access CiviReport', 'a:39:{s:6:"fields";a:2:{s:9:"sort_name";s:1:"1";s:6:"result";s:1:"1";}s:22:"assignee_contact_id_op";s:2:"eq";s:25:"assignee_contact_id_value";s:0:"";s:12:"sort_name_op";s:3:"has";s:15:"sort_name_value";s:0:"";s:17:"street_number_min";s:0:"";s:17:"street_number_max";s:0:"";s:16:"street_number_op";s:3:"lte";s:19:"street_number_value";s:0:"";s:14:"street_name_op";s:3:"has";s:17:"street_name_value";s:0:"";s:15:"postal_code_min";s:0:"";s:15:"postal_code_max";s:0:"";s:14:"postal_code_op";s:3:"lte";s:17:"postal_code_value";s:0:"";s:7:"city_op";s:3:"has";s:10:"city_value";s:0:"";s:20:"state_province_id_op";s:2:"in";s:23:"state_province_id_value";a:0:{}s:13:"country_id_op";s:2:"in";s:16:"country_id_value";a:0:{}s:12:"survey_id_op";s:2:"in";s:15:"survey_id_value";a:0:{}s:12:"status_id_op";s:2:"eq";s:15:"status_id_value";s:1:"1";s:11:"custom_1_op";s:2:"in";s:14:"custom_1_value";a:0:{}s:11:"custom_2_op";s:2:"in";s:14:"custom_2_value";a:0:{}s:17:"custom_3_relative";s:1:"0";s:13:"custom_3_from";s:0:"";s:11:"custom_3_to";s:0:"";s:11:"description";s:75:"Detailed report for canvassing, phone-banking, walk lists or other surveys.";s:13:"email_subject";s:0:"";s:8:"email_to";s:0:"";s:8:"email_cc";s:0:"";s:10:"permission";s:17:"access CiviReport";s:6:"groups";s:0:"";s:9:"domain_id";i:1;}');
-UPDATE civicrm_domain SET version = '5.26.2';
+UPDATE civicrm_domain SET version = '5.27.0';
diff --git a/civicrm/sql/civicrm_generated.mysql b/civicrm/sql/civicrm_generated.mysql
index 55c163ab73..64fb5084e4 100644
--- a/civicrm/sql/civicrm_generated.mysql
+++ b/civicrm/sql/civicrm_generated.mysql
@@ -399,7 +399,7 @@ UNLOCK TABLES;
 
 LOCK TABLES `civicrm_domain` WRITE;
 /*!40000 ALTER TABLE `civicrm_domain` DISABLE KEYS */;
-INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,'5.26.2',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
+INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,'5.27.0',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
 /*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */;
 UNLOCK TABLES;
 
diff --git a/civicrm/templates/CRM/ACL/Page/ACLBasic.tpl b/civicrm/templates/CRM/ACL/Page/ACLBasic.tpl
index 1c3787efd0..8ecb0eee8a 100644
--- a/civicrm/templates/CRM/ACL/Page/ACLBasic.tpl
+++ b/civicrm/templates/CRM/ACL/Page/ACLBasic.tpl
@@ -39,7 +39,7 @@
 
         {if $action ne 1 and $action ne 2}
       <div class="action-link">
-      <a href="{crmURL q="action=add&reset=1"}" id="newACL"><i class="crm-i fa-plus-circle"></i> {ts}Add ACL{/ts}</a>
+      <a href="{crmURL q="action=add&reset=1"}" id="newACL"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add ACL{/ts}</a>
         </div>
         {/if}
     </div>
diff --git a/civicrm/templates/CRM/Activity/Form/Activity.tpl b/civicrm/templates/CRM/Activity/Form/Activity.tpl
index a013a7cb74..a6f20a3450 100644
--- a/civicrm/templates/CRM/Activity/Form/Activity.tpl
+++ b/civicrm/templates/CRM/Activity/Form/Activity.tpl
@@ -80,12 +80,12 @@
         {if $action neq 4}
           {if !$form.target_contact_id.frozen}
             <a href="#" class="crm-hover-button" id="swap_target_assignee" title="{ts}Swap Target and Assignee Contacts{/ts}" style="position:relative; bottom: 1em;">
-              <i class="crm-i fa-random"></i>
+              <i class="crm-i fa-random" aria-hidden="true"></i>
             </a>
           {/if}
           {if $activityAssigneeNotification}
             <br />
-            <span id="notify_assignee_msg" class="description"><i class="crm-i fa-paper-plane"></i> {ts}A copy of this activity will be emailed to each Assignee.{/ts} {help id="sent_copy_email"}</span>
+            <span id="notify_assignee_msg" class="description"><i class="crm-i fa-paper-plane" aria-hidden="true"></i> {ts}A copy of this activity will be emailed to each Assignee.{/ts} {help id="sent_copy_email"}</span>
           {/if}
         {/if}
       </td>
@@ -244,7 +244,7 @@
       {if ($context eq 'fulltext' || $context eq 'search') && $searchKey}
         {assign var='urlParams' value="reset=1&atype=$atype&action=update&reset=1&id=$entityID&cid=$contactId&context=$context&key=$searchKey"}
       {/if}
-      <a href="{crmURL p='civicrm/activity/add' q=$urlParams}" class="edit button" title="{ts}Edit{/ts}"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+      <a href="{crmURL p='civicrm/activity/add' q=$urlParams}" class="edit button" title="{ts}Edit{/ts}"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
     {/if}
 
     {if call_user_func(array('CRM_Core_Permission','check'), 'delete activities')}
@@ -252,11 +252,11 @@
       {if ($context eq 'fulltext' || $context eq 'search') && $searchKey}
         {assign var='urlParams' value="reset=1&atype=$atype&action=delete&reset=1&id=$entityID&cid=$contactId&context=$context&key=$searchKey"}
       {/if}
-      <a href="{crmURL p='civicrm/contact/view/activity' q=$urlParams}" class="delete button" title="{ts}Delete{/ts}"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+      <a href="{crmURL p='civicrm/contact/view/activity' q=$urlParams}" class="delete button" title="{ts}Delete{/ts}"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
     {/if}
   {/if}
   {if $action eq 4 and $context != 'case' and call_user_func(array('CRM_Case_BAO_Case','checkPermission'), $activityId, 'File On Case', $atype)}
-    <a href="#" onclick="fileOnCase('file', {$activityId}, null, this); return false;" class="cancel button" title="{ts}File On Case{/ts}"><span><i class="crm-i fa-clipboard"></i> {ts}File on Case{/ts}</span></a>
+    <a href="#" onclick="fileOnCase('file', {$activityId}, null, this); return false;" class="cancel button" title="{ts}File On Case{/ts}"><span><i class="crm-i fa-clipboard" aria-hidden="true"></i> {ts}File on Case{/ts}</span></a>
     {include file="CRM/Case/Form/ActivityToCase.tpl"}
   {/if}
   {include file="CRM/common/formButtons.tpl" location="bottom"}
diff --git a/civicrm/templates/CRM/Activity/Form/ActivityLinks.tpl b/civicrm/templates/CRM/Activity/Form/ActivityLinks.tpl
index 1b734956cc..689b4e3cf1 100644
--- a/civicrm/templates/CRM/Activity/Form/ActivityLinks.tpl
+++ b/civicrm/templates/CRM/Activity/Form/ActivityLinks.tpl
@@ -43,7 +43,7 @@
 {foreach from=$activityTypes key=k item=act}
 <li class="crm-activity-type_{$k}">
   <a href="{$act.url}" data-tab="activity">
-    <i class="crm-i {$act.icon}"></i> {$act.label}
+    <i class="crm-i {$act.icon}" aria-hidden="true"></i> {$act.label}
   </a>
 </li>
 {/foreach}
diff --git a/civicrm/templates/CRM/Activity/Form/ActivityView.tpl b/civicrm/templates/CRM/Activity/Form/ActivityView.tpl
index b19a243c02..4f68416e21 100644
--- a/civicrm/templates/CRM/Activity/Form/ActivityView.tpl
+++ b/civicrm/templates/CRM/Activity/Form/ActivityView.tpl
@@ -22,7 +22,7 @@
        {/if}
        {if $values.mailingId}
            <tr>
-                <td class="label">{ts}With Contact{/ts}</td><td class="view-value"><a href="{$values.mailingId}" title="{ts}View Mailing Report{/ts}">&raquo;{ts}Mailing Report{/ts}</a></td>
+                <td class="label">{ts}With Contact{/ts}</td><td class="view-value"><a href="{$values.mailingId}" title="{ts}View Mailing Report{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>{ts}Mailing Report{/ts}</a></td>
            </tr>
        {/if}
         <tr>
@@ -84,7 +84,7 @@
                                   {$mailingReport.mailing.body_text|mb_truncate:30|escape|nl2br}
                                   <br />
                                   {if $values.mailingId}
-                                    <strong><a class="crm-popup" href='{$textViewURL}'>&raquo; {ts}View complete message{/ts}</a></strong>
+                                    <strong><a class="crm-popup" href='{$textViewURL}'><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}View complete message{/ts}</a></strong>
                                   {/if}
                               </td>
                           </tr>
@@ -97,7 +97,7 @@
                                   {$mailingReport.mailing.body_html|mb_truncate:30|escape|nl2br}
                                   <br/>
                                   {if $values.mailingId}
-                                    <strong><a class="crm-popup" href='{$htmlViewURL}'>&raquo; {ts}View complete message{/ts}</a></strong>
+                                    <strong><a class="crm-popup" href='{$htmlViewURL}'><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}View complete message{/ts}</a></strong>
                                   {/if}
                               </td>
                           </tr>
@@ -130,4 +130,3 @@
      </table>
      <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
 </div>
-
diff --git a/civicrm/templates/CRM/Activity/Form/Task/Batch.tpl b/civicrm/templates/CRM/Activity/Form/Task/Batch.tpl
index fc002b7879..992de310c2 100644
--- a/civicrm/templates/CRM/Activity/Form/Task/Batch.tpl
+++ b/civicrm/templates/CRM/Activity/Form/Task/Batch.tpl
@@ -21,7 +21,7 @@
            {/foreach}
 
              {foreach from=$fields item=field key=fieldName}
-                <td><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</td>
+                <td>{copyIcon name=$field.name title=$field.title}{$field.title}</td>
              {/foreach}
             </tr>
           </thead>
diff --git a/civicrm/templates/CRM/Activity/Import/Form/Preview.tpl b/civicrm/templates/CRM/Activity/Import/Form/Preview.tpl
index f0a3568a14..5b846a62cc 100644
--- a/civicrm/templates/CRM/Activity/Import/Form/Preview.tpl
+++ b/civicrm/templates/CRM/Activity/Import/Form/Preview.tpl
@@ -48,7 +48,7 @@
         <td class="data">{$invalidRowCount}</td>
         <td class="explanation">{ts}Rows with invalid data in one or more fields. These rows will be skipped (not imported).{/ts}
             {if $invalidRowCount}
-                <div class="action-link"><a href="{$downloadErrorRecordsUrl}">&raquo; {ts}Download Errors{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadErrorRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Errors{/ts}</a></div>
             {/if}
         </td>
     </tr>
diff --git a/civicrm/templates/CRM/Admin/Form/Options.tpl b/civicrm/templates/CRM/Admin/Form/Options.tpl
index b41ad148ab..2a566c9b65 100644
--- a/civicrm/templates/CRM/Admin/Form/Options.tpl
+++ b/civicrm/templates/CRM/Admin/Form/Options.tpl
@@ -58,7 +58,7 @@
           <td class="label">{$form.value.label}</td>
           <td>{$form.value.html}<br />
             {if $action == 2}
-              <span class="description"><i class="crm-i fa-exclamation-triangle"></i> {ts}Changing the Value field will unlink records which have been marked with this option. This change can not be undone except by restoring the previous value.{/ts}</span>
+              <span class="description"><i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i> {ts}Changing the Value field will unlink records which have been marked with this option. This change can not be undone except by restoring the previous value.{/ts}</span>
             {/if}
           </td>
         </tr>
diff --git a/civicrm/templates/CRM/Admin/Form/Preferences/Display.tpl b/civicrm/templates/CRM/Admin/Form/Preferences/Display.tpl
index 2f86a7039d..049a5ebf99 100644
--- a/civicrm/templates/CRM/Admin/Form/Preferences/Display.tpl
+++ b/civicrm/templates/CRM/Admin/Form/Preferences/Display.tpl
@@ -162,7 +162,7 @@
         {$form.editor_id.html}
         &nbsp;
         <span class="crm-button crm-icon-button" style="display:inline-block;vertical-align:middle;float:none!important;">
-          <i class="crm-i fa-wrench" style="margin: 0 -18px 0 2px;"></i>
+          <i class="crm-i fa-wrench" style="margin: 0 -18px 0 2px;" aria-hidden="true"></i>
           {$form.ckeditor_config.html}
         </span>
       </td>
diff --git a/civicrm/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl b/civicrm/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl
index fc86332955..68ace19f26 100644
--- a/civicrm/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl
+++ b/civicrm/templates/CRM/Admin/Form/Setting/Miscellaneous.tpl
@@ -77,10 +77,10 @@
       </tr>
     </table>
 
-    <h3>{ts}reCAPTCHA Keys{/ts}</h3>
-
+    <h3>{ts}reCAPTCHA v2{/ts}</h3>
     <div class="description">
-      {ts 1='href="https://www.google.com/recaptcha" target="_blank"'}reCAPTCHA is a free service that helps prevent automated abuse of your site. To use reCAPTCHA on public-facing CiviCRM forms: sign up at <a %1>Google's reCaptcha site</a>; enter the provided public and private reCAPTCHA keys here; then enable reCAPTCHA under Advanced Settings in any Profile.{/ts}
+      {ts 1='href="https://www.google.com/recaptcha" target="_blank"'}reCAPTCHA is a free service that helps prevent automated abuse of your site. To use it on public-facing CiviCRM forms: sign up at <a %1>Google's reCaptcha site</a>; enter the provided public and private keys here; then enable reCAPTCHA under Advanced Settings in any Profile.{/ts}
+      <br/><strong>{ts}Only the reCAPTCHA v2 checkbox type is supported.{/ts}</strong>
     </div>
     <table class="form-layout">
       <tr class="crm-miscellaneous-form-block-recaptchaPublicKey">
diff --git a/civicrm/templates/CRM/Admin/Form/Setting/Smtp.tpl b/civicrm/templates/CRM/Admin/Form/Setting/Smtp.tpl
index bde961cb5a..789a85bd57 100644
--- a/civicrm/templates/CRM/Admin/Form/Setting/Smtp.tpl
+++ b/civicrm/templates/CRM/Admin/Form/Setting/Smtp.tpl
@@ -93,7 +93,7 @@
     CRM.$(function($) {
       var mailSetting = $("input[name='outBound_option']:checked").val( );
 
-      var archiveWarning = "{/literal}{ts escape='js'}WARNING: You are switching from a testing mode (Redirect to Database) to a live mode. Check Mailings > Archived Mailings, and delete any test mailings that are not in Completed status prior to running the mailing cron job for the first time. This will ensure that test mailings are not actually sent out.{/ts}{literal}"
+      var archiveWarning = "{/literal}{ts escape='js'}WARNING: You are switching from a testing mode (Redirect to Database) to a live mode. Check Mailings > Archived Mailings, and delete any test mailings that are not in Completed status prior to running the mailing cron job for the first time. This will ensure that test mailings are not actually sent out.{/ts}{literal}";
 
         showHideMailOptions( $("input[name='outBound_option']:checked").val( ) ) ;
 
diff --git a/civicrm/templates/CRM/Admin/Form/Setting/Url.hlp b/civicrm/templates/CRM/Admin/Form/Setting/Url.hlp
index a2d1b1a86b..e01986593a 100644
--- a/civicrm/templates/CRM/Admin/Form/Setting/Url.hlp
+++ b/civicrm/templates/CRM/Admin/Form/Setting/Url.hlp
@@ -70,6 +70,16 @@
 <p>{ts}You can modify the look and feel of CiviCRM by adding your own stylesheet. For small to medium sized modifications, use your css file to override some of the styles in civicrm.css. Or if you need to make drastic changes, you can choose to disable civicrm.css completely.{/ts}</p>
 {/htxt}
 
+{htxt id='id-defaultExternUrl'}
+<p>{ts}CiviCRM generates callback URLs for external services.{/ts}</p>
+<p>{ts}Some callback URLs are being migrated to a different style. During the transition, you may indicate a preferred style, such as:{/ts}</p>
+<ul>
+    <li>{ts}"Standalone Scripts" - In the traditional style, each callback URL is a standalone PHP script. You may wish to use this style if you need to maximize performance or if you need continuity.{/ts}</li>
+    <li>{ts}"Router" - In the newer style, each callback URL is defined like a normal CiviCRM page. You may wish to use this style for greater consistency or portability.{/ts}</li>
+</ul>
+<p>{ts}This setting only affects the default URL produced by "civicrm-core". Extensions and add-ons may override specific URLs.{/ts}</p>
+{/htxt}
+
 {htxt id='id-url_vars'}
 {ts}URL Variables{/ts}
   <table>
diff --git a/civicrm/templates/CRM/Admin/Form/Setting/Url.tpl b/civicrm/templates/CRM/Admin/Form/Setting/Url.tpl
index 3ecb7699b7..c6df140ff6 100644
--- a/civicrm/templates/CRM/Admin/Form/Setting/Url.tpl
+++ b/civicrm/templates/CRM/Admin/Form/Setting/Url.tpl
@@ -77,6 +77,15 @@
             <p class="description font-red">{ts}{$verifySSL_description}{/ts}</p>
         </td>
     </tr>
+    <tr class="crm-url-form-block-defaultExternUrl">
+        <td class="label">
+            {$form.defaultExternUrl.label} {help id='id-defaultExternUrl'}
+        </td>
+        <td>
+            {$form.defaultExternUrl.html}<br/>
+            <p class="description font-red">{ts}{$settings_fields.defaultExternUrl.description}{/ts}</p>
+        </td>
+    </tr>
 </table>
 <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
 </div>
diff --git a/civicrm/templates/CRM/Admin/Form/WordReplacements.tpl b/civicrm/templates/CRM/Admin/Form/WordReplacements.tpl
index 1ae4182ddc..ead2551283 100644
--- a/civicrm/templates/CRM/Admin/Form/WordReplacements.tpl
+++ b/civicrm/templates/CRM/Admin/Form/WordReplacements.tpl
@@ -45,7 +45,7 @@
               {/section}
             </tbody>
           </table>
-          &nbsp;&nbsp;&nbsp;<a class="action-item crm-hover-button buildStringOverrideRow" href="#"><i class="crm-i fa-plus-circle"></i> {ts}Add row{/ts}</a>
+          &nbsp;&nbsp;&nbsp;<a class="action-item crm-hover-button buildStringOverrideRow" href="#"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add row{/ts}</a>
         </td>
       </tr>
     </table>
diff --git a/civicrm/templates/CRM/Admin/Page/APIExplorer.js b/civicrm/templates/CRM/Admin/Page/APIExplorer.js
index 7b8e83d499..4d6df95b2b 100644
--- a/civicrm/templates/CRM/Admin/Page/APIExplorer.js
+++ b/civicrm/templates/CRM/Admin/Page/APIExplorer.js
@@ -200,10 +200,10 @@
     var $row = $('tr:last-child', '#api-params');
     $('.api-chain-entity', $row).crmSelect2({
       formatSelection: function(item) {
-        return '<i class="crm-i fa-link"></i> API ' +
+        return '<i class="crm-i fa-link" aria-hidden="true"></i> API ' +
           ($(item.element).hasClass('strikethrough') ? '<span class="strikethrough">' + item.text + '</span>' : item.text);
       },
-      placeholder: '<i class="crm-i fa-link"></i> ' + ts('Entity'),
+      placeholder: '<i class="crm-i fa-link" aria-hidden="true"></i> ' + ts('Entity'),
       allowClear: false,
       escapeMarkup: function(m) {return m;}
     })
@@ -677,7 +677,7 @@
         .addClass('crm-error')
         .css('width', '82%')
         .attr('title', msg)
-        .before('<i class="crm-i fa-exclamation-triangle crm-i-red" title="'+msg+'"></i> ')
+        .before('<i class="crm-i fa-exclamation-triangle crm-i-red" title="'+msg+'" aria-hidden="true"></i> ')
         .tooltip();
     }
   }
diff --git a/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl b/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl
index 7234f9f13d..1e1b8eb497 100644
--- a/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl
+++ b/civicrm/templates/CRM/Admin/Page/APIExplorer.tpl
@@ -210,13 +210,13 @@
 <div id="mainTabContainer">
   <ul>
     <li class="ui-corner-all" title="GUI to build and execute API calls">
-      <a href="#explorer-tab"><i class="crm-i fa-search"></i> {ts}Explorer{/ts}</a>
+      <a href="#explorer-tab"><i class="crm-i fa-search" aria-hidden="true"></i> {ts}Explorer{/ts}</a>
     </li>
     <li class="ui-corner-all" title="Auto-generated examples from the test suite">
-      <a href="#examples-tab"><i class="crm-i fa-book"></i> {ts}Examples{/ts}</a>
+      <a href="#examples-tab"><i class="crm-i fa-book" aria-hidden="true"></i> {ts}Examples{/ts}</a>
     </li>
     <li class="ui-corner-all" title="API source-code and code-level documentation">
-      <a href="#docs-tab"><i class="crm-i fa-code"></i> {ts}Code Docs{/ts}</a>
+      <a href="#docs-tab"><i class="crm-i fa-code" aria-hidden="true"></i> {ts}Code Docs{/ts}</a>
     </li>
   </ul>
 
@@ -263,9 +263,9 @@
         <tbody id="api-params"></tbody>
       </table>
       <div id="api-param-buttons" style="display: none;">
-        <a href="#" class="crm-hover-button" id="api-params-add"><i class="crm-i fa-plus"></i> {ts}Add Parameter{/ts}</a>
-        <a href="#" class="crm-hover-button" id="api-option-add"><i class="crm-i fa-cog"></i> {ts}Add Option{/ts}</a>
-        <a href="#" class="crm-hover-button" id="api-chain-add"><i class="crm-i fa-link"></i> {ts}Chain API Call{/ts}</a>
+        <a href="#" class="crm-hover-button" id="api-params-add"><i class="crm-i fa-plus" aria-hidden="true"></i> {ts}Add Parameter{/ts}</a>
+        <a href="#" class="crm-hover-button" id="api-option-add"><i class="crm-i fa-cog" aria-hidden="true"></i> {ts}Add Option{/ts}</a>
+        <a href="#" class="crm-hover-button" id="api-chain-add"><i class="crm-i fa-link" aria-hidden="true"></i> {ts}Chain API Call{/ts}</a>
         {help id="api-chain"}
       </div>
       <div id="api-generated-wraper">
@@ -286,7 +286,7 @@
       </div>
       <div class="crm-submit-buttons">
         <span class="crm-button crm-i-button">
-          <i class="crm-i fa-bolt"></i><input type="submit" value="{ts}Execute{/ts}" class="crm-form-submit" accesskey="S" title="{ts}Execute API call and display results{/ts}"/>
+          <i class="crm-i fa-bolt" aria-hidden="true"></i><input type="submit" value="{ts}Execute{/ts}" class="crm-form-submit" accesskey="S" title="{ts}Execute API call and display results{/ts}"/>
         </span>
       </div>
 
@@ -350,9 +350,9 @@
 <script type="text/template" id="api-param-tpl">
   <tr class="api-param-row">
     <td>
-      <i class="crm-i api-sort-handle fa-arrows"></i>
+      <i class="crm-i api-sort-handle fa-arrows" aria-hidden="true"></i>
       <input style="width: 90%;" class="crm-form-text api-param-name api-input" value="<%= name %>" placeholder="{ts}Parameter{/ts}" />
-      <div class="api-and-or"><span><span class="api-and">{ts}AND{/ts}</span> <i class="crm-i fa-toggle-on"></i> <span class="api-or">{ts}OR{/ts}</span></span></div>
+      <div class="api-and-or"><span><span class="api-and">{ts}AND{/ts}</span> <i class="crm-i fa-toggle-on" aria-hidden="true"></i> <span class="api-or">{ts}OR{/ts}</span></span></div>
     </td>
     <td>
       {literal}
@@ -371,7 +371,7 @@
     </td>
     <td>
       <input style="width: 85%;" class="crm-form-text api-param-value api-input" placeholder="{ts}Value{/ts}"/>
-      <a class="crm-hover-button api-param-remove" href="#"><i class="crm-i fa-times"></i></a>
+      <a class="crm-hover-button api-param-remove" href="#"><i class="crm-i fa-times" aria-hidden="true"></i></a>
     </td>
   </tr>
 </script>
@@ -399,7 +399,7 @@
     </td>
     <td>
       <input style="width: 85%;" class="crm-form-text api-option-value api-input" placeholder="{ts}Value{/ts}"/>
-      <a class="crm-hover-button api-param-remove" href="#"><i class="crm-i fa-times"></i></a>
+      <a class="crm-hover-button api-param-remove" href="#"><i class="crm-i fa-times" aria-hidden="true"></i></a>
     </td>
   </tr>
 </script>
@@ -407,7 +407,7 @@
 <script type="text/template" id="api-chain-tpl">
   <tr class="api-chain-row">
     <td>
-      <i class="crm-i api-sort-handle fa-arrows"></i>
+      <i class="crm-i api-sort-handle fa-arrows" aria-hidden="true"></i>
       <select style="width: 90%;" class="crm-form-select api-chain-entity">
         <option value=""></option>
         {foreach from=$entities.values item=entity}
@@ -424,7 +424,7 @@
     </td>
     <td>
       <input style="width: 85%;" class="crm-form-text api-param-value api-input" value="{ldelim}{rdelim}" placeholder="{ts}API Params{/ts}"/>
-      <a class="crm-hover-button api-param-remove" href="#"><i class="crm-i fa-times"></i></a>
+      <a class="crm-hover-button api-param-remove" href="#"><i class="crm-i fa-times" aria-hidden="true"></i></a>
     </td>
   </tr>
 </script>
@@ -444,7 +444,7 @@
   <ul class="fa-ul">
     <% _.forEach(joins, function(join, name) { %>
       <li <% if(join.checked) { %>class="join-enabled"<% } if(join.disabled) { %>class="join-not-available"<% }%>>
-        <i class="fa-li crm-i fa-reply fa-rotate-180"></i>
+        <i class="fa-li crm-i fa-reply fa-rotate-180" aria-hidden="true"></i>
         <label for="select-join-<%= name %>" class="api-checkbox-label">
           <input type="checkbox" id="select-join-<%= name %>" value="<%= name %>" data-entity="<%= join.entity %>" <% if(join.checked) { %>checked<% } if(join.disabled) { %>disabled<% } %>/>
           <%- join.title %>
diff --git a/civicrm/templates/CRM/Admin/Page/Access.tpl b/civicrm/templates/CRM/Admin/Page/Access.tpl
index bbb735156f..e71a822732 100644
--- a/civicrm/templates/CRM/Admin/Page/Access.tpl
+++ b/civicrm/templates/CRM/Admin/Page/Access.tpl
@@ -18,20 +18,20 @@
 
     <table class="report">
         <tr>
-            <td class="nowrap"><a href="{$ufAccessURL}" {$jAccessParams} id="adminAccess">&raquo; {ts 1=$config->userFramework}%1 Access Control{/ts}</a></td>
+            <td class="nowrap"><a href="{$ufAccessURL}" {$jAccessParams} id="adminAccess"><i class="crm-i fa-chevron-right fa-fw" aria-hidden="true"></i> {ts 1=$config->userFramework}%1 Access Control{/ts}</a></td>
             <td>{ts}Grant access to CiviCRM components and other CiviCRM permissions.{/ts}</td>
         </tr>
         <tr><td colspan="2" class="separator"><strong>{ts}Use following steps if you need to control View and/or Edit permissions for specific contact groups, specific profiles or specific custom data fields.{/ts}</strong></td></tr>
     <tr>
-        <td class="nowrap"><a href="{crmURL p='civicrm/admin/options/acl_role' q="reset=1"}" id="editACLRoles">&raquo; {ts}1. Manage Roles{/ts}</a></td>
+        <td class="nowrap"><a href="{crmURL p='civicrm/admin/options/acl_role' q="reset=1"}" id="editACLRoles"><i class="crm-i fa-users fa-fw" aria-hidden="true"></i> {ts}1. Manage Roles{/ts}</a></td>
         <td>{ts}Each CiviCRM ACL Role is assigned a set of permissions. Use this link to create or edit the different roles needed for your site.{/ts}</td>
     </tr>
     <tr>
-        <td class="nowrap"><a href="{crmURL p='civicrm/acl/entityrole' q="reset=1"}" id="editRoleAssignments">&raquo; {ts}2. Assign Users to CiviCRM ACL Roles{/ts}</a></td>
+        <td class="nowrap"><a href="{crmURL p='civicrm/acl/entityrole' q="reset=1"}" id="editRoleAssignments"><i class="crm-i fa-user-plus fa-fw" aria-hidden="true"></i> {ts}2. Assign Users to CiviCRM ACL Roles{/ts}</a></td>
         <td>{ts}Once you have defined CiviCRM ACL Roles and granted ACLs to those Roles, use this link to assign users to role(s).{/ts}</td>
     </tr>
     <tr>
-        <td class="nowrap"><a href="{crmURL p='civicrm/acl' q="reset=1"}" id="editACLs">&raquo; {ts}3. Manage ACLs{/ts}</a></td>
+        <td class="nowrap"><a href="{crmURL p='civicrm/acl' q="reset=1"}" id="editACLs"><i class="crm-i fa-id-card-o fa-fw" aria-hidden="true"></i> {ts}3. Manage ACLs{/ts}</a></td>
         <td>{ts}ACLs define permission to do an operation on a set of data, and grant that permission to a CiviCRM ACL Role. Use this link to create or edit the ACLs for your site.{/ts}</td>
     </tr>
     </table>
diff --git a/civicrm/templates/CRM/Admin/Page/Admin.tpl b/civicrm/templates/CRM/Admin/Page/Admin.tpl
index d88e58c923..8c9154b7f8 100644
--- a/civicrm/templates/CRM/Admin/Page/Admin.tpl
+++ b/civicrm/templates/CRM/Admin/Page/Admin.tpl
@@ -18,61 +18,18 @@
     </div>
 {/if}
 
-<div id="help" class="description section-hidden-border">
-{capture assign=plusImg}<img src="{$config->resourceBase}i/TreePlus.gif" alt="{ts}plus sign{/ts}" style="vertical-align: bottom; height: 20px; width: 20px;" />{/capture}
-{ts 1=$plusImg}Administer your CiviCRM site using the links on this page. Click %1 for descriptions of the options in each section.{/ts}
-</div>
-
-{strip}
 <div class="crm-content-block">
-{foreach from=$adminPanel key=groupName item=group name=adminLoop}
- <div id="id_{$groupName}_show" class="section-hidden{if $smarty.foreach.adminLoop.last eq false} section-hidden-border{/if}">
-    <table class="form-layout">
-    <tr>
-        <td width="20%" class="font-size11pt" style="vertical-align: top;">{$group.show} {$group.title}</td>
-        <td width="80%" style="white-space: nowrap;">
-
-            <table class="form-layout" width="100%">
-            <tr>
-         <td width="50%" style="padding: 0px;">
-                {foreach from=$group.fields item=panelItem  key=panelName name=groupLoop}
-                    &raquo;&nbsp;<a href="{$panelItem.url}"{if $panelItem.extra} {$panelItem.extra}{/if} id="idc_{$panelItem.id}">{$panelItem.title}</a><br />
-                    {if $smarty.foreach.groupLoop.iteration EQ $group.perColumn}
-                         </td><td width="50%" style="padding: 0px;">
-                    {/if}
-                {/foreach}
-                </td>
-            </tr>
-            </table>
-        </td>
-    </tr>
-    </table>
- </div>
-
- <div id="id_{$groupName}">
-    <fieldset><legend><strong>{$group.hide}{$group.title}</strong></legend>
-        <table class="form-layout">
-
-        {foreach from=$group.fields item=panelItem  key=panelName name=groupLoop}
-            <tr class="{cycle values="odd-row,even-row" name=$groupName}">
-                <td style="vertical-align: top; width:24px;">
-                    <a href="{$panelItem.url}"{if $panelItem.extra} {$panelItem.extra}{/if} ><img src="{$config->resourceBase}i/{if $panelItem.icon}{$panelItem.icon}{else}admin/small/option.png{/if}" alt="{$panelItem.title|escape}"/></a>
-                </td>
-                <td class="report font-size11pt" style="vertical-align: text-top;" width="20%">
-                    <a href="{$panelItem.url}"{if $panelItem.extra} {$panelItem.extra}{/if} id="id_{$panelItem.id}">{$panelItem.title}</a>
-                </td>
-                <td class="description"  style="vertical-align: text-top;" width="75%">
-                    {$panelItem.desc}
-                </td>
-            </tr>
-        {/foreach}
-
-        </table>
-    </fieldset>
+{foreach from=$adminPanel key=groupName item=group}
+<div id="admin-section-{$groupName}">
+  <h3>{$group.title}</h3>
+  <div class="admin-section-items">
+    {foreach from=$group.fields item=panelItem  key=panelName}
+    <dl>
+      <dt><a href="{$panelItem.url}"{if $panelItem.extra} {$panelItem.extra}{/if} id="id_{$panelItem.id}">{$panelItem.title}</a></dt>
+      <dd>{$panelItem.desc}</dd>
+    </dl>
+    {/foreach}
   </div>
+</div>
 {/foreach}
-{/strip}
-
-{* Include Javascript to hide and display the appropriate blocks as directed by the php code *}
-{include file="CRM/common/showHide.tpl"}
 </div>
diff --git a/civicrm/templates/CRM/Admin/Page/CKEditorConfig.tpl b/civicrm/templates/CRM/Admin/Page/CKEditorConfig.tpl
index abc2c1fc3c..14af566be2 100644
--- a/civicrm/templates/CRM/Admin/Page/CKEditorConfig.tpl
+++ b/civicrm/templates/CRM/Admin/Page/CKEditorConfig.tpl
@@ -100,10 +100,10 @@
 
     <div class="crm-submit-buttons">
       <span class="crm-button crm-i-button">
-        <i class="crm-i fa-wrench"></i> <input type="submit" value="{ts}Save{/ts}" name="save" class="crm-form-submit" accesskey="S"/>
+        <i class="crm-i fa-wrench" aria-hidden="true"></i> <input type="submit" value="{ts}Save{/ts}" name="save" class="crm-form-submit" accesskey="S"/>
       </span>
       <span class="crm-button crm-i-button">
-        <i class="crm-i fa-times"></i> <input type="submit" value="{ts}Revert to Default{/ts}" name="revert" class="crm-form-submit" onclick="return confirm('{$revertConfirm}');"/>
+        <i class="crm-i fa-times" aria-hidden="true"></i> <input type="submit" value="{ts}Revert to Default{/ts}" name="revert" class="crm-form-submit" onclick="return confirm('{$revertConfirm}');"/>
       </span>
     </div>
     <input type="hidden" value="{$preset}" name="preset" />
diff --git a/civicrm/templates/CRM/Admin/Page/Job.tpl b/civicrm/templates/CRM/Admin/Page/Job.tpl
index c0812feff1..cb2d310b7c 100644
--- a/civicrm/templates/CRM/Admin/Page/Job.tpl
+++ b/civicrm/templates/CRM/Admin/Page/Job.tpl
@@ -67,7 +67,7 @@
         {ts}There are no jobs configured.{/ts}
      </div>
      <div class="action-link">
-       <a href="{crmURL p='civicrm/admin/job' q="action=add&reset=1"}" id="newJob-nojobs" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add New Scheduled Job{/ts}</span></a>
+       <a href="{crmURL p='civicrm/admin/job' q="action=add&reset=1"}" id="newJob-nojobs" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add New Scheduled Job{/ts}</span></a>
      </div>
 
 {/if}
diff --git a/civicrm/templates/CRM/Admin/Page/JobLog.tpl b/civicrm/templates/CRM/Admin/Page/JobLog.tpl
index d3547dd037..12b1b687b7 100644
--- a/civicrm/templates/CRM/Admin/Page/JobLog.tpl
+++ b/civicrm/templates/CRM/Admin/Page/JobLog.tpl
@@ -18,7 +18,7 @@
 {/if}
 
   <div class="action-link">
-    <a href="{crmURL p='civicrm/admin/job' q="reset=1"}" id="jobsList-top" class="button"><span><i class="crm-i fa-chevron-left"></i> {ts}Back to Scheduled Jobs Listing{/ts}</span></a>
+    <a href="{crmURL p='civicrm/admin/job' q="reset=1"}" id="jobsList-top" class="button"><span><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {ts}Back to Scheduled Jobs Listing{/ts}</span></a>
   </div>
 
 {if $rows}
@@ -59,6 +59,6 @@
 {/if}
 
   <div class="action-link">
-    <a href="{crmURL p='civicrm/admin/job' q="reset=1"}" id="jobsList-bottom" class="button"><span><i class="crm-i fa-chevron-left"></i> {ts}Back to Scheduled Jobs Listing{/ts}</span></a>
+    <a href="{crmURL p='civicrm/admin/job' q="reset=1"}" id="jobsList-bottom" class="button"><span><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {ts}Back to Scheduled Jobs Listing{/ts}</span></a>
   </div>
 </div>
diff --git a/civicrm/templates/CRM/Admin/Page/LabelFormats.tpl b/civicrm/templates/CRM/Admin/Page/LabelFormats.tpl
index 2baf4ae13d..d2dd488eea 100644
--- a/civicrm/templates/CRM/Admin/Page/LabelFormats.tpl
+++ b/civicrm/templates/CRM/Admin/Page/LabelFormats.tpl
@@ -53,8 +53,7 @@
               <td class="crm-labelFormat-name">{$row.groupName}</td>
               <td class="crm-labelFormat-order nowrap">{$row.weight}</td>
               <td class="crm-labelFormat-description">{$row.grouping}</td>
-              <td class="crm-labelFormat-is_default">{if $row.is_default eq 1}
-              <img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}"/>{/if}&nbsp;</td>
+              <td class="crm-labelFormat-is_default">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;</td>
               <td class="crm-labelFormat-is_reserved">{if $row.is_reserved eq 1}{ts}Yes{/ts}{else}{ts}No{/ts}{/if}
                 &nbsp;</td>
               <td>{$row.action|replace:'xx':$row.id}</td>
diff --git a/civicrm/templates/CRM/Admin/Page/LocationType.tpl b/civicrm/templates/CRM/Admin/Page/LocationType.tpl
index 5d891e12b2..1eb9600caa 100644
--- a/civicrm/templates/CRM/Admin/Page/LocationType.tpl
+++ b/civicrm/templates/CRM/Admin/Page/LocationType.tpl
@@ -40,7 +40,7 @@
         <td class="crmf-vcard_name crm-editable">{$row.vcard_name}</td>
         <td class="crmf-description crm-editable">{$row.description}</td>
         <td id="row_{$row.id}_status" class="crmf-is_active">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
-        <td class="crmf-is_default" >{if $row.is_default eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" />{/if}&nbsp;</td>
+        <td class="crmf-is_default">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;</td>
         <td>{$row.action|replace:'xx':$row.id}</td>
     </tr>
     {/foreach}
diff --git a/civicrm/templates/CRM/Admin/Page/Navigation.tpl b/civicrm/templates/CRM/Admin/Page/Navigation.tpl
index 76b9f95112..b101137c5b 100644
--- a/civicrm/templates/CRM/Admin/Page/Navigation.tpl
+++ b/civicrm/templates/CRM/Admin/Page/Navigation.tpl
@@ -29,7 +29,7 @@
     <div>
       <a href="#" class="nav-reset crm-hover-button">
         {* TODO: fa-broom would be better, but not implemented yet. https://github.com/FortAwesome/Font-Awesome/issues/239 *}
-        <i class="crm-i fa-undo"></i> {ts}Cleanup reports menu{/ts}
+        <i class="crm-i fa-undo" aria-hidden="true"></i> {ts}Cleanup reports menu{/ts}
       </a>
     </div>
     <div class="spacer"></div>
diff --git a/civicrm/templates/CRM/Admin/Page/OptionGroup.tpl b/civicrm/templates/CRM/Admin/Page/OptionGroup.tpl
index 87ddaf9846..ca9abf7251 100644
--- a/civicrm/templates/CRM/Admin/Page/OptionGroup.tpl
+++ b/civicrm/templates/CRM/Admin/Page/OptionGroup.tpl
@@ -13,7 +13,7 @@
 {else}
 <div class="help">
     {ts}CiviCRM stores configurable choices for various drop-down fields as 'option groups'. You can click <strong>Options</strong> to view the available choices.{/ts}
-    <p><i class="crm-i fa-exclamation-triangle"></i> {ts}WARNING: Many option groups are used programatically and values should be added or modified with caution.{/ts}</p>
+    <p><i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i> {ts}WARNING: Many option groups are used programatically and values should be added or modified with caution.{/ts}</p>
 </div>
 {/if}
 
diff --git a/civicrm/templates/CRM/Admin/Page/Options.tpl b/civicrm/templates/CRM/Admin/Page/Options.tpl
index 6c8a0e709d..1ecc70b42f 100644
--- a/civicrm/templates/CRM/Admin/Page/Options.tpl
+++ b/civicrm/templates/CRM/Admin/Page/Options.tpl
@@ -115,7 +115,7 @@
         {foreach from=$rows item=row}
           <tr id="option_value-{$row.id}" class="crm-admin-options crm-admin-options_{$row.id} crm-entity {cycle values="odd-row,even-row"}{if NOT $row.is_active} disabled{/if}">
             {if !empty($hasIcons)}
-              <td class="crm-admin-options-icon"><i class="crm-i {$row.icon}"></i></td>
+              <td class="crm-admin-options-icon"><i class="crm-i {$row.icon}" aria-hidden="true"></i></td>
             {/if}
             {if $showComponent}
               <td class="crm-admin-options-component_name">{$row.component_name}</td>
@@ -131,13 +131,13 @@
               <td>{$row.financial_account}</td>
             {/if}
             {if $showCounted}
-              <td class="center crm-admin-options-filter">{if $row.filter eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Counted{/ts}" />{/if}</td>
+              <td class="center crm-admin-options-filter">{icon condition=$row.filter}{ts}Counted{/ts}{/icon}</td>
             {/if}
             {if $showVisibility}<td class="crm-admin-visibility_label">{$row.visibility_label}</td>{/if}
             <td class="crm-admin-options-description crm-editable" data-field="description" data-type="textarea">{$row.description}</td>
             <td class="nowrap crm-admin-options-order">{$row.weight}</td>
             {if $showIsDefault}
-              <td class="crm-admin-options-is_default" align="center">{if $row.is_default eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" />{/if}&nbsp;</td>
+              <td class="crm-admin-options-is_default" align="center">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;</td>
             {/if}
             <td class="crm-admin-options-is_reserved">{if $row.is_reserved eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
             <td class="crm-admin-options-is_active" id="row_{$row.id}_status">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
diff --git a/civicrm/templates/CRM/Admin/Page/ParticipantStatusType.tpl b/civicrm/templates/CRM/Admin/Page/ParticipantStatusType.tpl
index 620e411f71..92e1eedec3 100644
--- a/civicrm/templates/CRM/Admin/Page/ParticipantStatusType.tpl
+++ b/civicrm/templates/CRM/Admin/Page/ParticipantStatusType.tpl
@@ -33,9 +33,9 @@
           <td class="crmf-label crm-editable" data-field="label">{$row.label}</td>
           <td class="crmf-name">{$row.name} ({$row.id})</td>
           <td class="crmf-class {if !$row.is_reserved} crm-editable {/if}" data-type="select">{$row.class}</td>
-          <td class="center crmf-is_reserved">{if $row.is_reserved}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Reserved{/ts}" />{/if}</td>
+          <td class="center crmf-is_reserved">{icon condition=$row.is_reserved}{ts}Reserved{/ts}{/icon}</td>
         <td id="row_{$row.id}_status" class="crmf-is_active">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
-          <td class="center crmf-is_counted">{if $row.is_counted} <img src="{$config->resourceBase}i/check.gif" alt="{ts}Counted{/ts}" />{/if}</td>
+          <td class="center crmf-is_counted">{icon condition=$row.is_counted}{ts}Counted{/ts}{/icon}</td>
           <td class="crmf-weight">{$row.weight}</td>
           <td class="crmf-visibility">{$row.visibility}</td>
           <td>{$row.action|replace:'xx':$row.id}</td>
diff --git a/civicrm/templates/CRM/Admin/Page/PaymentProcessor.tpl b/civicrm/templates/CRM/Admin/Page/PaymentProcessor.tpl
index 308e508d9e..ba6d55da20 100644
--- a/civicrm/templates/CRM/Admin/Page/PaymentProcessor.tpl
+++ b/civicrm/templates/CRM/Admin/Page/PaymentProcessor.tpl
@@ -42,8 +42,7 @@
             <td class="crmf-description">{$row.description}</td>
             <td class="crmf-financial_account_id">{$row.financialAccount}</td>
             <td class="crmf-is_active center">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
-            <td class="crmf-is_default center">
-              {if $row.is_default eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}"/>{/if}&nbsp;
+            <td class="crmf-is_default center">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;
             </td>
             <td>{$row.action|replace:'xx':$row.id}</td>
         </tr>
diff --git a/civicrm/templates/CRM/Admin/Page/PaymentProcessorType.tpl b/civicrm/templates/CRM/Admin/Page/PaymentProcessorType.tpl
index b1261e7dac..7580755844 100644
--- a/civicrm/templates/CRM/Admin/Page/PaymentProcessorType.tpl
+++ b/civicrm/templates/CRM/Admin/Page/PaymentProcessorType.tpl
@@ -36,7 +36,7 @@
           <td class="crm-paymentProcessorType-title crm-editable" data-field="title">{$row.title}</td>
             <td class="crm-paymentProcessorType-description">{$row.description}</td>
           <td id="row_{$row.id}_status" class="crm-paymentProcessorType-is_active">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
-            <td class="crm-paymentProcessorType-is_default">{if $row.is_default eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" />{/if}&nbsp;</td>
+            <td class="crm-paymentProcessorType-is_default">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;</td>
           <td>{$row.action}</td>
         </tr>
         {/foreach}
@@ -45,7 +45,7 @@
 
         {if $action ne 1 and $action ne 2}
         <div class="action-link">
-          <a href="{crmURL q="action=add&reset=1"}" id="newPaymentProcessor">&raquo; {ts}New Payment Processor{/ts}</a>
+          <a href="{crmURL q="action=add&reset=1"}" id="newPaymentProcessor"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}New Payment Processor{/ts}</a>
           {crmButton p="civicrm/admin" q="reset=1" class="cancel" icon="times"}{ts}Done{/ts}{/crmButton}
         </div>
         {/if}
diff --git a/civicrm/templates/CRM/Admin/Page/PdfFormats.tpl b/civicrm/templates/CRM/Admin/Page/PdfFormats.tpl
index 5b58ded34b..1b419c5752 100644
--- a/civicrm/templates/CRM/Admin/Page/PdfFormats.tpl
+++ b/civicrm/templates/CRM/Admin/Page/PdfFormats.tpl
@@ -50,7 +50,7 @@
         <tr id="row_{$row.id}" class="crm-pdfFormat {cycle values="odd-row,even-row"} {$row.class}">
             <td class="crm-pdfFormat-name">{$row.name}</td>
             <td class="crm-pdfFormat-description">{$row.description}</td>
-            <td class="crm-pdfFormat-is_default">{if $row.is_default eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" />{/if}&nbsp;</td>
+            <td class="crm-pdfFormat-is_default">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;</td>
           <td class="crm-pdfFormat-order nowrap">{$row.weight}</td>
           <td>{$row.action|replace:'xx':$row.id}</td>
         </tr>
diff --git a/civicrm/templates/CRM/Admin/Page/Setting.tpl b/civicrm/templates/CRM/Admin/Page/Setting.tpl
index 2a79269458..fe2a904ad5 100644
--- a/civicrm/templates/CRM/Admin/Page/Setting.tpl
+++ b/civicrm/templates/CRM/Admin/Page/Setting.tpl
@@ -13,72 +13,72 @@
 </div>
 <table class="report">
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/component' q='reset=1'}" id="idComponents">&raquo; {ts}Enable Components{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/component' q='reset=1'}" id="idComponents"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Enable Components{/ts}</a></td>
     <td>{ts}Enable CiviContribute, CiviPledge, CiviEvent, CiviMember, CiviMail, CiviCase, CiviReport and/or CiviGrant components.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/preferences/display' q='reset=1'}" id="idPreferences">&raquo; {ts}Site Preferences{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/preferences/display' q='reset=1'}" id="idPreferences"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Site Preferences{/ts}</a></td>
     <td>{ts}Configure screen and form elements for Viewing Contacts, Editing Contacts, Advanced Search, Contact Dashboard and WYSIWYG Editor.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/path' q='reset=1'}" id="idPath">&raquo; {ts}Directories{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/path' q='reset=1'}" id="idPath"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Directories{/ts}</a></td>
     <td>{ts}Configure directories in your file system for temporary uploads, images, custom files and custom templates.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/url' q='reset=1'}" id="idUrls">&raquo; {ts}Resource URLs{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/url' q='reset=1'}" id="idUrls"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Resource URLs{/ts}</a></td>
     <td>{ts}URLs used to access CiviCRM resources (CSS files, Javascript files, images, etc.). Enable secure URLs.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/smtp' q='reset=1'}" id="idSMTP">&raquo; {ts}Outbound Email (SMTP/Sendmail){/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/smtp' q='reset=1'}" id="idSMTP"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Outbound Email (SMTP/Sendmail){/ts}</a></td>
     <td>{ts}Settings for outbound email - either SMTP server, port and authentication or Sendmail path and argument.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/mapping' q='reset=1'}" id="idMapping">&raquo; {ts}Mapping and Geocoding{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/mapping' q='reset=1'}" id="idMapping"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Mapping and Geocoding{/ts}</a></td>
     <td>{ts}Configure a mapping provider (e.g. Google or Yahoo) to display maps for contact addresses and event locations.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/paymentProcessor' q='reset=1'}" id="idPayments">&raquo; {ts}Payment Processors{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/paymentProcessor' q='reset=1'}" id="idPayments"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Payment Processors{/ts}</a></td>
     <td>{ts}Select and configure one or more payment processing services for online contributions, events and / or membership fees.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/localization' q='reset=1'}" id="idLocale">&raquo; {ts}Localization{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/localization' q='reset=1'}" id="idLocale"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Localization{/ts}</a></td>
     <td>{ts}Localization settings include user language, default currency and available countries for address input.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/preferences/address' q='reset=1'}" id="idAddress">&raquo; {ts}Address Settings{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/preferences/address' q='reset=1'}" id="idAddress"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Address Settings{/ts}</a></td>
     <td>{ts}Format addresses in mailing labels, input forms and screen display. Configure optional Address Standardization provider.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/search' q='reset=1'}" id="idMisc">&raquo; {ts}Search Settings{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/search' q='reset=1'}" id="idMisc"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Search Settings{/ts}</a></td>
     <td>{ts}Configure Contact Search behavior.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/date' q='reset=1'}" id="idDates">&raquo; {ts}Date Formats{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/date' q='reset=1'}" id="idDates"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Date Formats{/ts}</a></td>
     <td>{ts}Configure input and display formats for Date fields.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/uf' q='reset=1'}" id="idUF">&raquo; {ts 1=$config->userFramework}%1 Integration Settings{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/uf' q='reset=1'}" id="idUF"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts 1=$config->userFramework}%1 Integration Settings{/ts}</a></td>
     <td>{ts 1=$config->userFramework}%1 version and user table name.{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/misc' q='reset=1'}" id="idMisc">&raquo; {ts}Miscellaneous Settings{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/misc' q='reset=1'}" id="idMisc"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Miscellaneous Settings{/ts}</a></td>
     <td>{ts}Dashboard caching time, move to trash / undelete, change logging, version checking and reCAPTCHA (prevents automated abuse of public forms).{/ts}</td>
 </tr>
 
 <tr>
-    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/debug' q='reset=1'}" id="idDebug">&raquo; {ts}Debugging{/ts}</a></td>
+    <td class="nowrap"><a href="{crmURL p='civicrm/admin/setting/debug' q='reset=1'}" id="idDebug"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Debugging{/ts}</a></td>
     <td>{ts}Enable debugging features including display of template variables and backtracing.{/ts}</td>
 </tr>
 </table>
diff --git a/civicrm/templates/CRM/Badge/Form/Layout.tpl b/civicrm/templates/CRM/Badge/Form/Layout.tpl
index da1b73149e..3aeda9184f 100644
--- a/civicrm/templates/CRM/Badge/Form/Layout.tpl
+++ b/civicrm/templates/CRM/Badge/Form/Layout.tpl
@@ -36,7 +36,7 @@
          <table>
            <tr>
             <td>{$form.image_1.html}
-               <a href="#" class="crm-hover-button clear-image" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a>
+               <a href="#" class="crm-hover-button clear-image" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
              <br/>
              <span class="description">{ts}Click above and select a file by double clicking on it.{/ts}</span>
             </td>
@@ -56,7 +56,7 @@
          <table>
           <tr>
            <td>{$form.image_2.html}
-              <a href="#" class="crm-hover-button clear-image" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a>
+              <a href="#" class="crm-hover-button clear-image" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
             <br/>
             <span class="description">{ts}Click above and select a file by double clicking on it.{/ts}</span>
            </td>
diff --git a/civicrm/templates/CRM/Badge/Page/Layout.tpl b/civicrm/templates/CRM/Badge/Page/Layout.tpl
index a2ab0d69d2..a69b549b34 100644
--- a/civicrm/templates/CRM/Badge/Page/Layout.tpl
+++ b/civicrm/templates/CRM/Badge/Page/Layout.tpl
@@ -38,10 +38,7 @@
               <td id="row_{$row.id}_status" class="crm-badge-layout-is_active">
                 {if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}
               </td>
-              <td class="crm-badge-layout-is_default">
-                {if $row.is_default eq 1}
-                <img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}"/>
-                {/if}&nbsp;
+              <td class="crm-badge-layout-is_default">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;
               </td>
               <td>{$row.action|replace:'xx':$row.id}</td>
             </tr>
diff --git a/civicrm/templates/CRM/Batch/Form/Entry.tpl b/civicrm/templates/CRM/Batch/Form/Entry.tpl
index 31c3e6963e..70c0a1c350 100644
--- a/civicrm/templates/CRM/Batch/Form/Entry.tpl
+++ b/civicrm/templates/CRM/Batch/Form/Entry.tpl
@@ -20,7 +20,7 @@
   </div>
   {if $batchAmountMismatch}
     <div class="status message status-warning">
-      <i class="crm-i fa-exclamation-triangle"></i> {ts}Total for amounts entered below does not match the expected batch total.{/ts}
+      <i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i> {ts}Total for amounts entered below does not match the expected batch total.{/ts}
     </div>
     <span class="crm-button crm-button_qf_Entry_upload_force-save">
       {$form._qf_Entry_upload_force.html}
@@ -55,10 +55,7 @@
       {foreach from=$fields item=field key=fieldName}
         <div class="crm-grid-cell">
           {if $field.name|substr:0:11 ne 'soft_credit' and $field.name ne 'trxn_id'}
-          <img src="{$config->resourceBase}i/copy.png"
-               alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}"
-               fname="{$field.name}" class="action-icon"
-               title="{ts}Click here to copy the value in row one to ALL rows.{/ts}"/>
+          {copyIcon name=$field.name title=$field.title}
           {/if}{$field.title}
         </div>
       {/foreach}
diff --git a/civicrm/templates/CRM/Campaign/Form/ResultOptions.tpl b/civicrm/templates/CRM/Campaign/Form/ResultOptions.tpl
index b94652962c..32b4ae8c59 100644
--- a/civicrm/templates/CRM/Campaign/Form/ResultOptions.tpl
+++ b/civicrm/templates/CRM/Campaign/Form/ResultOptions.tpl
@@ -43,7 +43,7 @@
   <tr id="optionField_{$index}" class="form-item {cycle values="odd-row,even-row"}">
         <td>
         {if $index GT 1}
-            <a onclick="showHideRow({$index}); return false;" name="optionField_{$index}" href="#" class="form-link"><i class="crm-i fa-trash" title="{ts}hide field or section{/ts}"></i></a>
+            <a onclick="showHideRow({$index}); return false;" name="optionField_{$index}" href="#" class="form-link"><i class="crm-i fa-trash" title="{ts}hide field or section{/ts}" aria-hidden="true"></i></a>
         {/if}
         </td>
       <td>
@@ -60,7 +60,7 @@
     {/section}
     </table>
   <div id="optionFieldLink" class="add-remove-link">
-        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus-circle"></i> {ts}add another choice{/ts}</a>
+        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}add another choice{/ts}</a>
     </div>
   <span id="additionalOption" class="description">
     {ts}If you need additional options - you can add them after you Save your current entries.{/ts}
diff --git a/civicrm/templates/CRM/Campaign/Form/Search/Petition.tpl b/civicrm/templates/CRM/Campaign/Form/Search/Petition.tpl
index e14be7e538..3541466891 100644
--- a/civicrm/templates/CRM/Campaign/Form/Search/Petition.tpl
+++ b/civicrm/templates/CRM/Campaign/Form/Search/Petition.tpl
@@ -198,6 +198,7 @@ function loadPetitionList( )
 
          //add id for yes/no column.
          CRM.$(nRow).children().eq(8).attr( 'id', rowId + '_status' );
+         CRM.$(nRow).children().eq(6).html(CRM.utils.formatIcon('fa-check', ts('Default'), nRow.cells[6].innerText));
 
          return nRow;
     },
diff --git a/civicrm/templates/CRM/Campaign/Form/Search/Survey.tpl b/civicrm/templates/CRM/Campaign/Form/Search/Survey.tpl
index 1177d3a5ce..09a53a4ece 100644
--- a/civicrm/templates/CRM/Campaign/Form/Search/Survey.tpl
+++ b/civicrm/templates/CRM/Campaign/Form/Search/Survey.tpl
@@ -210,6 +210,7 @@ function loadSurveyList( )
 
          //add id for yes/no column.
          CRM.$(nRow).children().eq(11).attr( 'id', rowId + '_status' );
+         CRM.$(nRow).children().eq(9).html(CRM.utils.formatIcon('fa-check', ts('Default'), nRow.cells[9].innerText));
 
          return nRow;
     },
diff --git a/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl b/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl
index 7da55ab1e4..9c927d7b4c 100644
--- a/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl
+++ b/civicrm/templates/CRM/Campaign/Form/Task/Interview.tpl
@@ -51,7 +51,7 @@
           <tr id="optionField_{$index}" class="form-item {cycle values="odd-row,even-row"}">
             <td>
               {if $index GT 1}
-                <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}hide field or section{/ts}"/></a>
+                <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link">{icon icon="fa-trash"}{ts}hide field or section{/ts}{/icon}</a>
               {/if}
             </td>
             <td> {$form.order_bys.$index.column.html}</td>
@@ -65,7 +65,7 @@
         {/section}
       </table>
       <div id="optionFieldLink" class="add-remove-link">
-        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><img src="{$config->resourceBase}i/TreePlus.gif" class="action-icon" alt="{ts}show field or section{/ts}"/>{ts}another column{/ts}</a>
+        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus action-icon" aria-hidden="true"></i> {ts}another column{/ts}</a>
       </div>
 
       <script type="text/javascript">
@@ -116,12 +116,12 @@
             {if $field.skipDisplay}
               {continue}
             {/if}
-            <th><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</th>
+            <th>{copyIcon name=$field.name title=$field.title}{$field.title}</th>
           {/foreach}
         {/if}
 
-        <th><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=note}Click to copy %1 from row one to all rows.{/ts}" fname="note" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{ts}Note{/ts}</th>
-        <th><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=result}Click to copy %1 from row one to all rows.{/ts}" fname="result" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{ts}Result{/ts}</th>
+        <th>{capture assign="tsNote"}{ts}Note{/ts}{/capture}{copyIcon name=note title=$tsNote}{$tsNote}</th>
+        <th>{capture assign="tsResult"}{ts}Result{/ts}{/capture}{copyIcon name=result title=$tsResult}{$tsResult}</th>
         <th><a id="interview_voter_button" class='button' style="float:left;" href="#" title={ts}Vote{/ts} onclick="registerInterviewforall( ); return false;">{ts}Record Responses for All{/ts}</a></th>
       </tr>
       </thead>
@@ -311,7 +311,7 @@ var surveyActivityIds = {/literal}{$surveyActivityIds}{literal};
         if (interview.errors[error]) errorList =  errorList + '<li>' + interview.errors[error] + '</li>';
       }
       if ( errorList ) {
-        var allErrors = '<i class="crm-i fa-exclamation-triangle crm-i-red"></i> {/literal}{ts}Please correct the following errors in the survey fields below:{/ts}{literal}<ul>' + errorList + '</ul>';
+        var allErrors = '<i class="crm-i fa-exclamation-triangle crm-i-red" aria-hidden="true"></i> {/literal}{ts}Please correct the following errors in the survey fields below:{/ts}{literal}<ul>' + errorList + '</ul>';
         CRM.$('#responseErrors').show( ).html(allErrors);
       }
     }
diff --git a/civicrm/templates/CRM/Campaign/Page/Petition.tpl b/civicrm/templates/CRM/Campaign/Page/Petition.tpl
index 1dfd26a368..595c8582e7 100644
--- a/civicrm/templates/CRM/Campaign/Page/Petition.tpl
+++ b/civicrm/templates/CRM/Campaign/Page/Petition.tpl
@@ -12,7 +12,7 @@
 {if $surveys}
   <div class="action-link">
     <a href="{$addSurveyUrl}" class="button">
-      <span><i class="crm-i fa-plus-circle"></i> {ts}Add Survey{/ts}</span>
+      <span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Survey{/ts}</span>
     </a>
   </div>
  {include file="CRM/common/enableDisableApi.tpl"}
@@ -40,7 +40,7 @@
           <td>{$survey.release_frequency}</td>
           <td>{$survey.max_number_of_contacts}</td>
           <td>{$survey.default_number_of_contacts}</td>
-          <td>{if $survey.is_default}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" /> {/if}</td>
+          <td>{icon condition=$survey.is_default}{ts}Default{/ts}{/icon}</td>
           <td id="row_{$survey.id}_status">{if $survey.is_active}{ts}Yes{/ts}{else}{ts}No{/ts}{/if}</td>
      <td class="crm-report-optionList-action">{$survey.action}</td>
         </tr>
@@ -55,6 +55,6 @@
 {/if}
 <div class="action-link">
   <a href="{$addSurveyUrl}" class="button">
-    <span><i class="crm-i fa-plus-circle"></i> {ts}Add Survey{/ts}</span>
+    <span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Survey{/ts}</span>
   </a>
 </div>
diff --git a/civicrm/templates/CRM/Case/Form/Activity.tpl b/civicrm/templates/CRM/Case/Form/Activity.tpl
index 285153e6db..7df7770d70 100644
--- a/civicrm/templates/CRM/Case/Form/Activity.tpl
+++ b/civicrm/templates/CRM/Case/Form/Activity.tpl
@@ -18,7 +18,7 @@
 
   {if $action eq 8 or $action eq 32768 }
   <div class="messages status no-popup">
-    <i class="crm-i fa-info-circle"></i> &nbsp;
+    <i class="crm-i fa-info-circle" aria-hidden="true"></i> &nbsp;
     {if $action eq 8}
       {* activityTypeName means label here not name, but it's ok because label is desired here (dev/core#1116-ok-label) *}
       {ts 1=$activityTypeName}Click Delete to move this &quot;%1&quot; activity to the Trash.{/ts}
@@ -75,7 +75,7 @@
 
                     {if $action eq 1 or $action eq 2}
                       <br />
-                      <a href="#" class="crm-with-contact">&raquo; {ts}With other contact(s){/ts}</a>
+                      <a href="#" class="crm-with-contact"><i class="crm-i fa-user-plus" aria-hidden="true"></i> {ts}With other contact(s){/ts}</a>
                     {/if}
                   </td>
                 </tr>
@@ -87,7 +87,7 @@
                       {$form.target_contact_id.html}
                       <br/>
                       <a href="#" class="crm-with-contact">
-                        &raquo; {if not $multiClient}{ts}With client{/ts}{else}{ts}With client(s){/ts}{/if}
+                        <i class="crm-i fa-user" aria-hidden="true"></i> {if not $multiClient}{ts}With client{/ts}{else}{ts}With client(s){/ts}{/if}
                       </a>
                     </td>
                   </tr>
@@ -110,7 +110,7 @@
                   <td>{$form.assignee_contact_id.html}
                     {if $activityAssigneeNotification}
                       <br />
-                      <span id="notify_assignee_msg" class="description"><i class="crm-i fa-paper-plane"></i> {ts}A copy of this activity will be emailed to each Assignee.{/ts}</span>
+                      <span id="notify_assignee_msg" class="description"><i class="crm-i fa-paper-plane" aria-hidden="true"></i> {ts}A copy of this activity will be emailed to each Assignee.{/ts}</span>
                     {/if}
                   </td>
                 </tr>
diff --git a/civicrm/templates/CRM/Case/Form/ActivityTab.tpl b/civicrm/templates/CRM/Case/Form/ActivityTab.tpl
index b489a8037a..32ee2e9409 100644
--- a/civicrm/templates/CRM/Case/Form/ActivityTab.tpl
+++ b/civicrm/templates/CRM/Case/Form/ActivityTab.tpl
@@ -15,46 +15,44 @@
       {ts}Activities{/ts}
     </div>
 
-    <div id="activities" class="crm-accordion-body">
-    <div class="crm-accordion-wrapper crm-accordion-inner crm-search_filters-accordion collapsed">
-      <div class="crm-accordion-header">
+    <div id="activities" class="crm-accordion-body padded">
+    <div class="crm-collapsible crm-search_filters-accordion collapsed">
+      <div class="collapsible-title">
         {ts}Search Filters{/ts}
-      </div><!-- /.crm-accordion-header -->
-      <div class="crm-accordion-body">
-        <table class="no-border form-layout-compressed" id="searchOptions">
-          <tr>
-            <td class="crm-case-caseview-form-block-repoter_id"colspan="2"><label for="reporter_id">{ts}Reporter/Role{/ts}</label><br />
-              {$form.reporter_id.html|crmAddClass:twenty}
-            </td>
-            <td class="crm-case-caseview-form-block-status_id"><label for="status_id">{$form.status_id.label}</label><br />
-              {$form.status_id.html}
-            </td>
-          </tr>
-          <tr>
-            <td class="crm-case-caseview-form-block-activity_date_low">
-              {assign var=activitylow  value=activity_date_low_$caseID}
-              {$form.$activitylow.label}<br />
-              {$form.$activitylow.html}
-            </td>
-            <td class="crm-case-caseview-form-block-activity_date_high">
-              {assign var=activityhigh  value=activity_date_high_$caseID}
-              {$form.$activityhigh.label}<br />
-              {$form.$activityhigh.html}
-            </td>
-            <td class="crm-case-caseview-form-block-activity_type_filter_id">
-              {$form.activity_type_filter_id.label}<br />
-              {$form.activity_type_filter_id.html}
+      </div>
+      <table class="no-border form-layout-compressed" id="searchOptions">
+        <tr>
+          <td class="crm-case-caseview-form-block-repoter_id"colspan="2"><label for="reporter_id">{ts}Reporter/Role{/ts}</label><br />
+            {$form.reporter_id.html|crmAddClass:twenty}
+          </td>
+          <td class="crm-case-caseview-form-block-status_id"><label for="status_id">{$form.status_id.label}</label><br />
+            {$form.status_id.html}
+          </td>
+        </tr>
+        <tr>
+          <td class="crm-case-caseview-form-block-activity_date_low">
+            {assign var=activitylow  value=activity_date_low_$caseID}
+            {$form.$activitylow.label}<br />
+            {$form.$activitylow.html}
+          </td>
+          <td class="crm-case-caseview-form-block-activity_date_high">
+            {assign var=activityhigh  value=activity_date_high_$caseID}
+            {$form.$activityhigh.label}<br />
+            {$form.$activityhigh.html}
+          </td>
+          <td class="crm-case-caseview-form-block-activity_type_filter_id">
+            {$form.activity_type_filter_id.label}<br />
+            {$form.activity_type_filter_id.html}
+          </td>
+        </tr>
+        {if $form.activity_deleted}
+          <tr class="crm-case-caseview-form-block-activity_deleted">
+            <td>
+              {$form.activity_deleted.html}{$form.activity_deleted.label}
             </td>
           </tr>
-          {if $form.activity_deleted}
-            <tr class="crm-case-caseview-form-block-activity_deleted">
-              <td>
-                {$form.activity_deleted.html}{$form.activity_deleted.label}
-              </td>
-            </tr>
-          {/if}
-        </table>
-      </div><!-- /.crm-accordion-body -->
+        {/if}
+      </table>
     </div><!-- /.crm-accordion-wrapper -->
 {/if}
 
diff --git a/civicrm/templates/CRM/Case/Form/ActivityToCase.tpl b/civicrm/templates/CRM/Case/Form/ActivityToCase.tpl
index 0bc1ad634b..8d9b695252 100644
--- a/civicrm/templates/CRM/Case/Form/ActivityToCase.tpl
+++ b/civicrm/templates/CRM/Case/Form/ActivityToCase.tpl
@@ -73,7 +73,7 @@
             var caseUrl = destUrl + selectedCaseId + '&cid=' + contactId + context;
 
             var statusMsg = {/literal}'{ts escape='js' 1='%1'}Activity has been filed to %1 case.{/ts}'{literal};
-            CRM.alert(ts(statusMsg, {1: '<a href="' + caseUrl + '">' + caseTitle + '</a>'}), '{/literal}{ts escape="js"}Saved{/ts}{literal}', 'success');
+            CRM.alert(ts(statusMsg, {1: '<a href="' + caseUrl + '">' + CRM._.escape(caseTitle) + '</a>'}), '{/literal}{ts escape="js"}Saved{/ts}{literal}', 'success');
             CRM.refreshParent(a);
           }
         }
diff --git a/civicrm/templates/CRM/Case/Form/ActivityView.tpl b/civicrm/templates/CRM/Case/Form/ActivityView.tpl
index 5a5e145549..9bc3c3d781 100644
--- a/civicrm/templates/CRM/Case/Form/ActivityView.tpl
+++ b/civicrm/templates/CRM/Case/Form/ActivityView.tpl
@@ -36,9 +36,9 @@
             {if $smarty.foreach.report.first AND ( $activityID OR $parentID OR $latestRevisionID )} {* Add a cell to first row with links to prior revision listing and Prompted by (parent) as appropriate *}
               <td>{$row.value}</td>
               <td style="padding-right: 50px; text-align: right; font-size: .9em;">
-                {if $activityID}<a class="open-inline-noreturn" href="{crmURL p='civicrm/case/activity/view' h=0 q="cid=$contactID&aid=$activityID&revs=1"}">&raquo; {ts}List all revisions{/ts}</a>{if !$latestRevisionID}<br />{ts}(this is the current revision){/ts}{/if}<br />{/if}
-                {if $latestRevisionID}<a class="open-inline-noreturn" href="{crmURL p='civicrm/case/activity/view' h=0 q="cid=$contactID&aid=$latestRevisionID"}">&raquo; {ts}View current revision{/ts}</a><br /><span style="color: red;">{ts}(this is not the current revision){/ts}</span><br />{/if}
-                {if $parentID}<a class="open-inline-noreturn" href="{crmURL p='civicrm/case/activity/view' h=0 q="cid=$contactID&aid=$parentID"}">&raquo; {ts}Prompted by{/ts}</a>{/if}
+                {if $activityID}<a class="open-inline-noreturn" href="{crmURL p='civicrm/case/activity/view' h=0 q="cid=$contactID&aid=$activityID&revs=1"}"><i class="crm-i fa-history" aria-hidden="true"></i> {ts}List all revisions{/ts}</a>{if !$latestRevisionID}<br />{ts}(this is the current revision){/ts}{/if}<br />{/if}
+                {if $latestRevisionID}<a class="open-inline-noreturn" href="{crmURL p='civicrm/case/activity/view' h=0 q="cid=$contactID&aid=$latestRevisionID"}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}View current revision{/ts}</a><br /><span style="color: red;">{ts}(this is not the current revision){/ts}</span><br />{/if}
+                {if $parentID}<a class="open-inline-noreturn" href="{crmURL p='civicrm/case/activity/view' h=0 q="cid=$contactID&aid=$parentID"}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Prompted by{/ts}</a>{/if}
               </td>
             {else}
               <td colspan="2">{if $row.label eq 'Details'}{$row.value|crmStripAlternatives|nl2br|purify}{elseif $row.type eq 'Date'}{$row.value|crmDate}{else}{$row.value}{/if}</td>
diff --git a/civicrm/templates/CRM/Case/Form/CaseView.tpl b/civicrm/templates/CRM/Case/Form/CaseView.tpl
index 524da11842..86e23f57af 100644
--- a/civicrm/templates/CRM/Case/Form/CaseView.tpl
+++ b/civicrm/templates/CRM/Case/Form/CaseView.tpl
@@ -27,7 +27,7 @@
             <a href="{crmURL p='civicrm/contact/view' q="action=view&reset=1&cid=`$client.contact_id`"}" title="{ts}View contact record{/ts}">{$client.display_name}</a>{if not $smarty.foreach.clients.last}, &nbsp; {/if}
           {/foreach}
           <a href="#addClientDialog" class="crm-hover-button case-miniform" title="{ts}Add Client{/ts}" data-key="{crmKey name='civicrm/case/ajax/addclient'}">
-            <i class="crm-i fa-user-plus"></i>
+            <i class="crm-i fa-user-plus" aria-hidden="true"></i>
           </a>
           <div id="addClientDialog" class="hiddenElement">
             <input name="add_client_id" placeholder="{ts}- select contact -{/ts}" class="huge" data-api-params='{ldelim}"params": {ldelim}"contact_type": "{$contactType}"{rdelim}{rdelim}' />
@@ -45,7 +45,7 @@
             {foreach from=$caseRoles.client item=client}
               <tr class="crm-case-caseview-display_name">
                 <td class="label-left bold" style="padding: 0px; border: none;">
-                  <a href="{crmURL p='civicrm/contact/view' q="action=view&reset=1&cid=`$client.contact_id`"}" title="{ts}View contact record{/ts}">{$client.display_name}</a>{if $client.email}{crmAPI var='email_type_id' entity='OptionValue' action='getsingle' return="value" name="Email" option_group_id="activity_type"}<span class="crm-case-caseview-email"><a class="crm-hover-button crm-popup" href="{crmURL p='civicrm/activity/email/add' q="reset=1&action=add&atype=`$email_type_id.value`&cid=`$client.contact_id`&caseid=`$caseId`"}" title="{ts 1=$client.email|escape}Email: %1{/ts}"><i class="crm-i fa-envelope"></i></a></span>{/if}
+                  <a href="{crmURL p='civicrm/contact/view' q="action=view&reset=1&cid=`$client.contact_id`"}" title="{ts}View contact record{/ts}">{$client.display_name}</a>{if $client.email}{crmAPI var='email_type_id' entity='OptionValue' action='getsingle' return="value" name="Email" option_group_id="activity_type"}<span class="crm-case-caseview-email"><a class="crm-hover-button crm-popup" href="{crmURL p='civicrm/activity/email/add' q="reset=1&action=add&atype=`$email_type_id.value`&cid=`$client.contact_id`&caseid=`$caseId`"}" title="{ts 1=$client.email|escape}Email: %1{/ts}"><i class="crm-i fa-envelope" aria-hidden="true"></i></a></span>{/if}
                 </td>
               </tr>
               {if $client.phone}
@@ -69,13 +69,13 @@
         <span class="crm-case-summary-label">{ts}Subject{/ts}:</span>&nbsp;<span class="crm-editable" data-field="subject">{$caseDetails.case_subject}</span>
       </td>
       <td class="crm-case-caseview-case_type label">
-        <span class="crm-case-summary-label">{ts}Type{/ts}:</span>&nbsp;{$caseDetails.case_type}&nbsp;<a class="crm-hover-button crm-popup"  href="{crmURL p='civicrm/case/activity' q="action=add&reset=1&cid=`$contactId`&caseid=`$caseId`&selectedChild=activity&atype=`$changeCaseTypeId`"}" title="{ts}Change case type (creates activity record){/ts}"><i class="crm-i fa-pencil"></i></a>
+        <span class="crm-case-summary-label">{ts}Type{/ts}:</span>&nbsp;{$caseDetails.case_type}&nbsp;<a class="crm-hover-button crm-popup"  href="{crmURL p='civicrm/case/activity' q="action=add&reset=1&cid=`$contactId`&caseid=`$caseId`&selectedChild=activity&atype=`$changeCaseTypeId`"}" title="{ts}Change case type (creates activity record){/ts}"><i class="crm-i fa-pencil" aria-hidden="true"></i></a>
       </td>
       <td class="crm-case-caseview-case_status label">
-        <span class="crm-case-summary-label">{ts}Status{/ts}:</span>&nbsp;{$caseDetails.case_status}&nbsp;<a class="crm-hover-button crm-popup"  href="{crmURL p='civicrm/case/activity' q="action=add&reset=1&cid=`$contactId`&caseid=`$caseId`&selectedChild=activity&atype=`$changeCaseStatusId`"}" title="{ts}Change case status (creates activity record){/ts}"><i class="crm-i fa-pencil"></i></a>
+        <span class="crm-case-summary-label">{ts}Status{/ts}:</span>&nbsp;{$caseDetails.case_status}&nbsp;<a class="crm-hover-button crm-popup"  href="{crmURL p='civicrm/case/activity' q="action=add&reset=1&cid=`$contactId`&caseid=`$caseId`&selectedChild=activity&atype=`$changeCaseStatusId`"}" title="{ts}Change case status (creates activity record){/ts}"><i class="crm-i fa-pencil" aria-hidden="true"></i></a>
       </td>
       <td class="crm-case-caseview-case_start_date label">
-        <span class="crm-case-summary-label">{ts}Open Date{/ts}:</span>&nbsp;{$caseDetails.case_start_date|crmDate}&nbsp;<a class="crm-hover-button crm-popup"  href="{crmURL p='civicrm/case/activity' q="action=add&reset=1&cid=`$contactId`&caseid=`$caseId`&selectedChild=activity&atype=`$changeCaseStartDateId`"}" title="{ts}Change case start date (creates activity record){/ts}"><i class="crm-i fa-pencil"></i></a>
+        <span class="crm-case-summary-label">{ts}Open Date{/ts}:</span>&nbsp;{$caseDetails.case_start_date|crmDate}&nbsp;<a class="crm-hover-button crm-popup"  href="{crmURL p='civicrm/case/activity' q="action=add&reset=1&cid=`$contactId`&caseid=`$caseId`&selectedChild=activity&atype=`$changeCaseStartDateId`"}" title="{ts}Change case start date (creates activity record){/ts}"><i class="crm-i fa-pencil" aria-hidden="true"></i></a>
       </td>
       <td class="crm-case-caseview-{$caseID} label">
         <span class="crm-case-summary-label">{ts}ID{/ts}:</span>&nbsp;{$caseID}
@@ -103,15 +103,15 @@
     <div>
       <p>
         {if $hasAccessToAllCases}
-          <a class="crm-hover-button action-item no-popup" href="{crmURL p='civicrm/case/report/print' q="all=1&redact=0&cid=$contactID&caseID=$caseId&asn="}"><i class="crm-i fa-print"></i> {ts}Print Report{/ts}</a>
+          <a class="crm-hover-button action-item no-popup" href="{crmURL p='civicrm/case/report/print' q="all=1&redact=0&cid=$contactID&caseID=$caseId&asn="}"><i class="crm-i fa-print" aria-hidden="true"></i> {ts}Print Report{/ts}</a>
         {/if}
 
         {if !empty($exportDoc)}
-          <a class="crm-hover-button action-item" href="{$exportDoc}"><i class="crm-i fa-file-pdf-o"></i> {ts}Export Document{/ts}</a>
+          <a class="crm-hover-button action-item" href="{$exportDoc}"><i class="crm-i fa-file-pdf-o" aria-hidden="true"></i> {ts}Export Document{/ts}</a>
         {/if}
 
         {if $mergeCases}
-          <a href="#mergeCasesDialog" class="action-item no-popup crm-hover-button case-miniform"><i class="crm-i fa-compress"></i> {ts}Merge Case{/ts}</a>
+          <a href="#mergeCasesDialog" class="action-item no-popup crm-hover-button case-miniform"><i class="crm-i fa-compress" aria-hidden="true"></i> {ts}Merge Case{/ts}</a>
           {$form._qf_CaseView_next_merge_case.html}
           <span id="mergeCasesDialog" class="hiddenElement">
             {$form.merge_case_id.html}
@@ -119,7 +119,7 @@
         {/if}
 
         {if call_user_func(array('CRM_Core_Permission','giveMeAllACLs'))}
-          <a class="action-item crm-hover-button medium-popup" href="{crmURL p='civicrm/contact/view/case/editClient' h=1 q="reset=1&action=update&id=$caseID&cid=$contactID"}"><i class="crm-i fa-user"></i> {ts}Assign to Another Client{/ts}</a>
+          <a class="action-item crm-hover-button medium-popup" href="{crmURL p='civicrm/contact/view/case/editClient' h=1 q="reset=1&action=update&id=$caseID&cid=$contactID"}"><i class="crm-i fa-user" aria-hidden="true"></i> {ts}Assign to Another Client{/ts}</a>
         {/if}
       </p>
     </div>
@@ -136,7 +136,7 @@
 
       {if $hasAccessToAllCases}
         <div class="crm-submit-buttons">
-          <a class="button case-miniform" href="#addCaseRoleDialog" data-key="{crmKey name='civicrm/ajax/relation'}" rel="#caseRoles-selector-{$caseID}"><i class="crm-i fa-plus-circle"></i> {ts}Add new role{/ts}</a>
+          <a class="button case-miniform" href="#addCaseRoleDialog" data-key="{crmKey name='civicrm/ajax/relation'}" rel="#caseRoles-selector-{$caseID}"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add new role{/ts}</a>
         </div>
         <div id="addCaseRoleDialog" class="hiddenElement">
           <div>{$form.role_type.label}</div>
@@ -219,7 +219,7 @@
   {if !empty($globalGroupInfo.id)}
     <div class="crm-submit-buttons">
       <a class="button case-miniform" href="#addMembersToGroupDialog" rel="#globalRelationships-selector-{$caseId}" data-group_id="{$globalGroupInfo.id}">
-        <i class="crm-i fa-plus-circle"></i> {ts 1=$globalGroupInfo.title}Add members to %1{/ts}
+        <i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts 1=$globalGroupInfo.title}Add members to %1{/ts}
       </a>
     </div>
     <div id="addMembersToGroupDialog" class="hiddenElement">
diff --git a/civicrm/templates/CRM/Case/Form/Selector.tpl b/civicrm/templates/CRM/Case/Form/Selector.tpl
index bba4976b9f..e84e64afbb 100644
--- a/civicrm/templates/CRM/Case/Form/Selector.tpl
+++ b/civicrm/templates/CRM/Case/Form/Selector.tpl
@@ -61,7 +61,7 @@
     {* Dashboard only lists 10 most recent cases. *}
     {if $context EQ 'dashboard' and $limit and $pager->_totalItems GT $limit }
       <tr class="even-row">
-        <td colspan="10"><a href="{crmURL p='civicrm/case/search' q='reset=1'}">&raquo; {ts}Find more cases{/ts}... </a></td>
+        <td colspan="10"><a href="{crmURL p='civicrm/case/search' q='reset=1'}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Find more cases{/ts}... </a></td>
       </tr>
     {/if}
 
diff --git a/civicrm/templates/CRM/Case/Page/DashBoard.tpl b/civicrm/templates/CRM/Case/Page/DashBoard.tpl
index 9d83c4c0f1..f8bcfce4db 100644
--- a/civicrm/templates/CRM/Case/Page/DashBoard.tpl
+++ b/civicrm/templates/CRM/Case/Page/DashBoard.tpl
@@ -18,9 +18,9 @@
 
     <div class="crm-submit-buttons crm-case-dashboard-buttons">
       {if $newClient and $allowToAddNewCase}
-        <a href="{$newCaseURL}" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Case{/ts}</span></a>
+        <a href="{$newCaseURL}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Case{/ts}</span></a>
       {/if}
-      <a class="button no-popup" name="find_my_cases" href="{crmURL p="civicrm/case/search" q="reset=1&case_owner=2&force=1"}"><span><i class="crm-i fa-search"></i> {ts}Find My Cases{/ts}</span></a>
+      <a class="button no-popup" name="find_my_cases" href="{crmURL p="civicrm/case/search" q="reset=1&case_owner=2&force=1"}"><span><i class="crm-i fa-search" aria-hidden="true"></i> {ts}Find My Cases{/ts}</span></a>
 
       <div class="crm-case-dashboard-switch-view-buttons">
         {if $myCases}
diff --git a/civicrm/templates/CRM/Case/Page/DashboardSelector.tpl b/civicrm/templates/CRM/Case/Page/DashboardSelector.tpl
index c9d46d9b46..30392c8d53 100644
--- a/civicrm/templates/CRM/Case/Page/DashboardSelector.tpl
+++ b/civicrm/templates/CRM/Case/Page/DashboardSelector.tpl
@@ -7,7 +7,6 @@
  | and copyright information, see https://civicrm.org/licensing       |
  +--------------------------------------------------------------------+
 *}
-{capture assign=expandIconURL}<img src="{$config->resourceBase}i/TreePlus.gif" alt="{ts}open section{/ts}"/>{/capture}
 {strip}
 <table class="case-selector-{$list} crm-ajax-table" data-page-length='10'>
 <thead>
diff --git a/civicrm/templates/CRM/Case/Page/Tab.tpl b/civicrm/templates/CRM/Case/Page/Tab.tpl
index 971157d0f3..047fd3dc37 100644
--- a/civicrm/templates/CRM/Case/Page/Tab.tpl
+++ b/civicrm/templates/CRM/Case/Page/Tab.tpl
@@ -44,7 +44,7 @@
           call_user_func(array('CRM_Core_Permission','check'), 'add cases') ) AND
         $allowToAddNewCase}
         <div class="action-link">
-        <a accesskey="N" href="{$newCaseURL}" class="button no-popup"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Case{/ts}</span></a>
+        <a accesskey="N" href="{$newCaseURL}" class="button no-popup"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Case{/ts}</span></a>
         </div>
     {/if}
 
diff --git a/civicrm/templates/CRM/Contact/Form/Contact.tpl b/civicrm/templates/CRM/Contact/Form/Contact.tpl
index f69d5afb2b..2acbff7dcc 100644
--- a/civicrm/templates/CRM/Contact/Form/Contact.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Contact.tpl
@@ -16,7 +16,7 @@
   {/if}
   <div class="crm-form-block crm-search-form-block">
     {if call_user_func(array('CRM_Core_Permission','check'), 'administer CiviCRM') }
-      <a href='{crmURL p="civicrm/admin/setting/preferences/display" q="reset=1"}' title="{ts}Click here to configure the panes.{/ts}"><i class="crm-i fa-wrench"></i></a>
+      <a href='{crmURL p="civicrm/admin/setting/preferences/display" q="reset=1"}' title="{ts}Click here to configure the panes.{/ts}"><i class="crm-i fa-wrench" aria-hidden="true"></i></a>
     {/if}
     <span style="float:right;"><a href="#expand" id="expand">{ts}Expand all tabs{/ts}</a></span>
     <div class="crm-submit-buttons">
diff --git a/civicrm/templates/CRM/Contact/Form/Domain.tpl b/civicrm/templates/CRM/Contact/Form/Domain.tpl
index c5543452ca..258107b9b8 100644
--- a/civicrm/templates/CRM/Contact/Form/Domain.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Domain.tpl
@@ -46,7 +46,7 @@
 
     {if ($action eq 4)}
     <div class="action-link">
-    <a href="{crmURL q="action=update&reset=1"}" id="editDomainInfo">&raquo; {ts}Edit Domain Information{/ts}</a>
+    <a href="{crmURL q="action=update&reset=1"}" id="editDomainInfo"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Edit Domain Information{/ts}</a>
     </div>
     {/if}
 {if !($action eq 4)}
diff --git a/civicrm/templates/CRM/Contact/Form/Edit/Address.tpl b/civicrm/templates/CRM/Contact/Form/Edit/Address.tpl
index 05e1c38222..0181f55f95 100644
--- a/civicrm/templates/CRM/Contact/Form/Edit/Address.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Edit/Address.tpl
@@ -65,7 +65,7 @@
 
   {if $className eq 'CRM_Contact_Form_Contact'}
       <div id="addMoreAddress{$blockId}" class="crm-add-address-wrapper">
-          <a href="#" class="button" onclick="buildAdditionalBlocks( 'Address', '{$className}' );return false;"><span><i class="crm-i fa-plus-circle"></i> {ts}Another Address{/ts}</span></a>
+          <a href="#" class="button" onclick="buildAdditionalBlocks( 'Address', '{$className}' );return false;"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Another Address{/ts}</span></a>
       </div>
   {/if}
 
diff --git a/civicrm/templates/CRM/Contact/Form/Merge.tpl b/civicrm/templates/CRM/Contact/Form/Merge.tpl
index 9b56d73ec7..6c2902a06b 100644
--- a/civicrm/templates/CRM/Contact/Form/Merge.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Merge.tpl
@@ -31,24 +31,24 @@
   </div>
 
   <div class="action-link">
-    {if $prev}<a href="{$prev}" class="crm-hover-button action-item"><i class="crm-i fa-chevron-left"></i> {ts}Previous{/ts}</a>{/if}
-    {if $next}<a href="{$next}" class="crm-hover-button action-item">{ts}Next{/ts} <i class="crm-i fa-chevron-right"></i></a>{/if}
+    {if $prev}<a href="{$prev}" class="crm-hover-button action-item"><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {ts}Previous{/ts}</a>{/if}
+    {if $next}<a href="{$next}" class="crm-hover-button action-item">{ts}Next{/ts} <i class="crm-i fa-chevron-right" aria-hidden="true"></i></a>{/if}
     <a href="{$flip}" class="action-item crm-hover-button">
-      <i class="crm-i fa-random"></i>
+      <i class="crm-i fa-random" aria-hidden="true"></i>
       {ts}Flip between original and duplicate contacts.{/ts}
     </a>
   </div>
 
   <div class="action-link">
     <a href="#" class="action-item crm-hover-button crm-notDuplicate" title={ts}Mark this pair as not a duplicate.{/ts} onClick="processDupes( {$main_cid|escape}, {$other_cid|escape}, 'dupe-nondupe', 'merge-contact', '{$browseUrl}' );return false;">
-      <i class="crm-i fa-times-circle"></i>
+      <i class="crm-i fa-times-circle" aria-hidden="true"></i>
       {ts}Mark this pair as not a duplicate.{/ts}
     </a>
   </div>
 
   <div class="action-link">
     <a href="javascript:void(0);" class="action-item crm-hover-button toggle_equal_rows">
-      <i class="crm-i fa-eye-slash"></i>
+      <i class="crm-i fa-eye-slash" aria-hidden="true"></i>
       {ts}Show/hide rows with the same data on each contact record.{/ts}
     </a>
   </div>
diff --git a/civicrm/templates/CRM/Contact/Form/Search/AdvancedCriteria.tpl b/civicrm/templates/CRM/Contact/Form/Search/AdvancedCriteria.tpl
index 99f5d2e0ed..8c7807c4b0 100644
--- a/civicrm/templates/CRM/Contact/Form/Search/AdvancedCriteria.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Search/AdvancedCriteria.tpl
@@ -67,7 +67,7 @@ CRM.$(function($) {
     var body = $('.crm-accordion-body.' + id);
     if (header.length > 0 && body.length > 0 && !body.html()) {
       body.html('<div class="crm-loading-element"><span class="loading-text">{/literal}{ts escape='js'}Loading{/ts}{literal}...</span></div>');
-      header.append('{/literal}<a href="#" class="crm-close-accordion crm-hover-button css_right" title="{ts escape='js'}Remove from search criteria{/ts}"><i class="crm-i fa-times"></i></a>{literal}');
+      header.append('{/literal}<a href="#" class="crm-close-accordion crm-hover-button css_right" title="{ts escape='js'}Remove from search criteria{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>{literal}');
       header.addClass('active');
       CRM.loadPage(url, {target: body, block: false});
     }
@@ -126,7 +126,7 @@ CRM.$(function($) {
         {include file="CRM/common/formButtons.tpl" location="bottom"}
         <div class="crm-submit-buttons reset-advanced-search">
           <a href="{crmURL p='civicrm/contact/search/advanced' q='reset=1'}" id="resetAdvancedSearch" class="crm-hover-button" title="{ts}Clear all search criteria{/ts}">
-            <i class="crm-i fa-undo"></i>
+            <i class="crm-i fa-undo" aria-hidden="true"></i>
             &nbsp;{ts}Reset Form{/ts}
           </a>
         </div>
diff --git a/civicrm/templates/CRM/Contact/Form/Search/Criteria/Fields/sort_name.tpl b/civicrm/templates/CRM/Contact/Form/Search/Criteria/Fields/sort_name.tpl
new file mode 100644
index 0000000000..cdda1797a9
--- /dev/null
+++ b/civicrm/templates/CRM/Contact/Form/Search/Criteria/Fields/sort_name.tpl
@@ -0,0 +1,39 @@
+<div id="sortnameselect">
+  <label>{ts}Complete OR Partial Name{/ts} <span class="description">(<a href="#" id='searchbyindivflds'>{ts}search by individual name fields{/ts}</a>)</span></label><br />
+  {$form.sort_name.html}
+</div>
+<div id="indivfldselect">
+  <label>{ts}First/Last Name{/ts}<span class="description"> (<a href="#" id='searchbysortname'>{ts}search by complete or partial name{/ts}</a>)</span></label><br />
+  {$form.first_name.html} {$form.last_name.html}
+</div>
+
+{literal}
+  <script type="text/javascript">
+    CRM.$(function($) {
+      function showIndivFldsSearch() {
+        $('#sortnameselect').hide();
+        $('#indivfldselect').show();
+        $('#sort_name').val('');
+        $('#first_name').removeClass('big').addClass('eight');
+        $('#last_name').removeClass('big').addClass('eight');
+        return false;
+      }
+      function showSortNameSearch() {
+        $('#indivfldselect').hide();
+        $('#sortnameselect').show();
+        $('#first_name').val('');
+        $('#last_name').val('');
+        return false;
+      }
+      $('#searchbyindivflds').click(showIndivFldsSearch);
+      $('#searchbysortname').click(showSortNameSearch);
+
+      if ($('#first_name').val() || $('#last_name').val()) {
+        showIndivFldsSearch();
+      }
+      else {
+        showSortNameSearch();
+      }
+    });
+  </script>
+{/literal}
diff --git a/civicrm/templates/CRM/Contact/Form/Search/Criteria/SearchSettings.tpl b/civicrm/templates/CRM/Contact/Form/Search/Criteria/SearchSettings.tpl
index 47a34fcb0d..c835f8c263 100644
--- a/civicrm/templates/CRM/Contact/Form/Search/Criteria/SearchSettings.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Search/Criteria/SearchSettings.tpl
@@ -11,7 +11,7 @@
         </div>
         <div class="crm-submit-buttons reset-advanced-search">
           <a href="{crmURL p='civicrm/contact/search/advanced' q='reset=1'}" id="resetAdvancedSearch" class="crm-hover-button css_right" title="{ts}Clear all search criteria{/ts}">
-            <i class="crm-i fa-undo"></i>
+            <i class="crm-i fa-undo" aria-hidden="true"></i>
             {ts}Reset Form{/ts}
           </a>
         </div>
diff --git a/civicrm/templates/CRM/Contact/Form/Search/Custom/EventDetails.tpl b/civicrm/templates/CRM/Contact/Form/Search/Custom/EventDetails.tpl
index 42a7bc6904..2ad2a0bea4 100644
--- a/civicrm/templates/CRM/Contact/Form/Search/Custom/EventDetails.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Search/Custom/EventDetails.tpl
@@ -11,40 +11,39 @@
 {assign var="showBlock" value="'searchForm'"}
 {assign var="hideBlock" value="'searchForm_show','searchForm_hide'"}
 <div class="crm-block crm-form-block crm-search-form-block">
-<div id="searchForm_show" class="form-item">
-    <a href="#" onclick="cj('#searchForm_show').hide(); cj('#searchForm').show(); return false;"><img src="{$config->resourceBase}i/TreePlus.gif" class="action-icon" alt="{ts}open section{/ts}" /></a>
-    <label>{ts}Edit Search Criteria{/ts}</label>
-</div>
-
-<div id="searchForm" class="crm-block crm-form-block crm-contact-custom-search-eventDetails-form-block">
-    <fieldset>
-        <legend><span id="searchForm_hide"><a href="#" onclick="cj('#searchForm').hide(); cj('#searchForm_show').show(); return false;"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}close section{/ts}" /></a></span>{ts}Search Criteria{/ts}</legend>
-      <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
-        <table class="form-layout-compressed">
-            {* Loop through all defined search criteria fields (defined in the buildForm() function). *}
-            {foreach from=$elements item=element}
-                <tr class="crm-contact-custom-search-eventDetails-form-block-{$element}">
-                    <td class="label">{$form.$element.label}</td>
-                    <td>{$form.$element.html}</td>
+  <div class="crm-accordion-wrapper crm-eventDetails_search-accordion {if $rows}collapsed{/if}">
+    <div class="crm-accordion-header crm-master-accordion-header">
+      {ts}Edit Search Criteria{/ts}
+    </div><!-- /.crm-accordion-header -->
+    <div class="crm-accordion-body">
+      <div id="searchForm" class="crm-block crm-form-block crm-contact-custom-search-eventDetails-form-block">
+          <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
+            <table class="form-layout-compressed">
+                {* Loop through all defined search criteria fields (defined in the buildForm() function). *}
+                {foreach from=$elements item=element}
+                    <tr class="crm-contact-custom-search-eventDetails-form-block-{$element}">
+                        <td class="label">{$form.$element.label}</td>
+                        <td>{$form.$element.html}</td>
+                    </tr>
+                {/foreach}
+                <tr class="crm-contact-custom-search-eventDetails-form-block-event_type">
+                    <td class="label">{ts}Event Type{/ts}</td>
+                    <td>
+                        <div class="listing-box">
+                            {foreach from=$form.event_type_id item="event_val"}
+                                <div class="{cycle values="odd-row,even-row"}">
+                                    {$event_val.html}
+                                </div>
+                            {/foreach}
+                        </div>
+                        <div class="spacer"></div>
+                    </td>
                 </tr>
-            {/foreach}
-            <tr class="crm-contact-custom-search-eventDetails-form-block-event_type">
-                <td class="label">{ts}Event Type{/ts}</td>
-                <td>
-                    <div class="listing-box">
-                        {foreach from=$form.event_type_id item="event_val"}
-                            <div class="{cycle values="odd-row,even-row"}">
-                                {$event_val.html}
-                            </div>
-                        {/foreach}
-                    </div>
-                    <div class="spacer"></div>
-                </td>
-            </tr>
-        </table>
-      <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
-    </fieldset>
-</div>
+            </table>
+          <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
+      </div>
+    </div>
+  </div>
 
 {if $rowsEmpty}
     {include file="CRM/Contact/Form/Search/Custom/EmptyResults.tpl"}
@@ -118,12 +117,4 @@
     </fieldset>
     {* END Actions/Results section *}
 {/if}
-
-<script type="text/javascript">
-    var showBlock = new Array({$showBlock});
-    var hideBlock = new Array({$hideBlock});
-
-    {* hide and display the appropriate blocks *}
-    on_load_init_blocks( showBlock, hideBlock );
-</script>
 </div>
diff --git a/civicrm/templates/CRM/Contact/Form/Search/Custom/FullText.tpl b/civicrm/templates/CRM/Contact/Form/Search/Custom/FullText.tpl
index 6d15896a9a..6a7d8b516a 100644
--- a/civicrm/templates/CRM/Contact/Form/Search/Custom/FullText.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Search/Custom/FullText.tpl
@@ -62,7 +62,7 @@
     {if !$table and $summary.addShowAllLink.Contact}
       <div class="crm-section full-text-view-all-section">
         <a href="{crmURL p='civicrm/contact/search/custom' q="csid=`$csID`&reset=1&force=1&table=Contact&text=$text"}"
-        title="{ts}View all results for contacts{/ts}">&raquo;&nbsp;{ts}View all results for contacts{/ts}</a>
+        title="{ts}View all results for contacts{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;{ts}View all results for contacts{/ts}</a>
       </div>{/if}
     {* note we using location="below" because we don't want to use rows per page for now. And therefore don't put location="bottom" for now. *}
     {if $table}{include file="CRM/common/pager.tpl" location="below"}{/if}
@@ -125,7 +125,7 @@
     {if !$table and $summary.addShowAllLink.Activity}
       <div class="crm-section full-text-view-all-section">
         <a href="{crmURL p='civicrm/contact/search/custom' q="csid=`$csID`&reset=1&force=1&table=Activity&text=$text"}"
-        title="{ts}View all results for activities{/ts}">&raquo;&nbsp;{ts}View all results for activities{/ts}</a>
+        title="{ts}View all results for activities{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;{ts}View all results for activities{/ts}</a>
       </div>
     {/if}
     {if $table}{include file="CRM/common/pager.tpl" location="below"}{/if}
@@ -182,7 +182,7 @@
     {if !$table and $summary.addShowAllLink.Case}
       <div class="crm-section full-text-view-all-section">
         <a href="{crmURL p='civicrm/contact/search/custom' q="csid=`$csID`&reset=1&force=1&table=Case&text=$text"}"
-        title="{ts}View all results for cases{/ts}">&raquo;&nbsp;{ts}View all results for cases{/ts}</a>
+        title="{ts}View all results for cases{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;{ts}View all results for cases{/ts}</a>
       </div>
     {/if}
     {if $table}{include file="CRM/common/pager.tpl" location="below"}{/if}
@@ -236,7 +236,7 @@
     {if !$table and $summary.addShowAllLink.Contribution}
       <div class="crm-section full-text-view-all-section">
         <a href="{crmURL p='civicrm/contact/search/custom' q="csid=`$csID`&reset=1&force=1&table=Contribution&text=$text"}"
-        title="{ts}View all results for contributions{/ts}">&raquo;&nbsp;{ts}View all results for contributions{/ts}</a>
+        title="{ts}View all results for contributions{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;{ts}View all results for contributions{/ts}</a>
       </div>
     {/if}
     {if $table}{include file="CRM/common/pager.tpl" location="below"}{/if}
@@ -293,7 +293,7 @@
     {if !$table and $summary.addShowAllLink.Participant}
       <div class="crm-section full-text-view-all-section"><a
         href="{crmURL p='civicrm/contact/search/custom' q="csid=`$csID`&reset=1&force=1&table=Participant&text=$text"}"
-        title="{ts}View all results for participants{/ts}">&raquo;&nbsp;{ts}View all results for participants{/ts}</a>
+        title="{ts}View all results for participants{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;{ts}View all results for participants{/ts}</a>
       </div>{/if}
     {if $table}{include file="CRM/common/pager.tpl" location="below"}{/if}
     {* END Actions/Results section *}
@@ -349,7 +349,7 @@
     {if !$table and $summary.addShowAllLink.Membership}
       <div class="crm-section full-text-view-all-section">
         <a href="{crmURL p='civicrm/contact/search/custom' q="csid=`$csID`&reset=1&force=1&table=Membership&text=$text"}"
-        title="{ts}View all results for memberships{/ts}">&raquo;&nbsp;{ts}View all results for memberships{/ts}</a>
+        title="{ts}View all results for memberships{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;{ts}View all results for memberships{/ts}</a>
       </div>
     {/if}
     {if $table}{include file="CRM/common/pager.tpl" location="below"}{/if}
@@ -395,7 +395,7 @@
   {if !$table and $summary.addShowAllLink.File}
   <div class="crm-section full-text-view-all-section">
     <a href="{crmURL p='civicrm/contact/search/custom' q="csid=`$csID`&reset=1&force=1&table=File&text=$text"}"
-          title="{ts}View all results for files{/ts}">&raquo;&nbsp;{ts}View all results for files{/ts}</a>
+          title="{ts}View all results for files{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;{ts}View all results for files{/ts}</a>
   </div>{/if}
   {if $table}{include file="CRM/common/pager.tpl" location="below"}{/if}
 {* END Actions/Results section *}
diff --git a/civicrm/templates/CRM/Contact/Form/Search/Intro.tpl b/civicrm/templates/CRM/Contact/Form/Search/Intro.tpl
index 8ee7f07c71..d5d791c3b8 100644
--- a/civicrm/templates/CRM/Contact/Form/Search/Intro.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Search/Intro.tpl
@@ -20,7 +20,7 @@
             {capture assign=editSmartGroupURL}{crmURL p="civicrm/contact/search/advanced" q="reset=1&ssID=`$ssID`"}{/capture}
         {/if}
         <div class="crm-submit-buttons">
-            <a href="{$editSmartGroupURL}" class="button no-popup"><span><i class="crm-i fa-pencil"></i> {ts 1=$group.title}Edit Smart Group Search Criteria for %1{/ts}</span></a>
+            <a href="{$editSmartGroupURL}" class="button no-popup"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts 1=$group.title}Edit Smart Group Search Criteria for %1{/ts}</span></a>
             {help id="id-edit-smartGroup"}
         </div>
     {/if}
@@ -28,7 +28,7 @@
     {if $permissionedForGroup}
         {capture assign=addMembersURL}{crmURL q="context=amtg&amtgID=`$group.id`&reset=1"}{/capture}
         <div class="crm-submit-buttons">
-            <a href="{$addMembersURL}" class="button no-popup"><span><i class="crm-i fa-user-plus"></i> {ts 1=$group.title}Add Contacts to %1{/ts}</span></a>
+            <a href="{$addMembersURL}" class="button no-popup"><span><i class="crm-i fa-user-plus" aria-hidden="true"></i> {ts 1=$group.title}Add Contacts to %1{/ts}</span></a>
             {if $ssID}{help id="id-add-to-smartGroup"}{/if}
         </div>
     {/if}
diff --git a/civicrm/templates/CRM/Contact/Form/Search/ResultTasks.tpl b/civicrm/templates/CRM/Contact/Form/Search/ResultTasks.tpl
index aeb50dc254..1e3e0df3cc 100644
--- a/civicrm/templates/CRM/Contact/Form/Search/ResultTasks.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Search/ResultTasks.tpl
@@ -18,9 +18,9 @@
  <div id="search-status">
   <div class="float-right right">
     {if $action eq 256}
-        <a href="{$advSearchURL}">&raquo; {ts}Advanced Search{/ts}</a><br />
+        <a href="{$advSearchURL}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Advanced Search{/ts}</a><br />
         {if $context eq 'search'} {* Only show Search Builder link for basic search. *}
-            <a href="{$searchBuilderURL}">&raquo; {ts}Search Builder{/ts}</a><br />
+            <a href="{$searchBuilderURL}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Search Builder{/ts}</a><br />
         {/if}
         {if $context eq 'smog'}
             {help id="id-smog-criteria" group_id=$group.id group_title=$group.title ssID=$ssID ssMappingID=$ssMappingID permissionedForGroup=$permissionedForGroup}
@@ -30,9 +30,9 @@
             {help id="id-basic-criteria"}
         {/if}
     {elseif $action eq 512}
-        <a href="{$searchBuilderURL}">&raquo; {ts}Search Builder{/ts}</a><br />
+        <a href="{$searchBuilderURL}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Search Builder{/ts}</a><br />
     {elseif $action eq 8192}
-        <a href="{$advSearchURL}">&raquo; {ts}Advanced Search{/ts}</a><br />
+        <a href="{$advSearchURL}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Advanced Search{/ts}</a><br />
     {/if}
   </div>
 
diff --git a/civicrm/templates/CRM/Contact/Form/Search/table.tpl b/civicrm/templates/CRM/Contact/Form/Search/table.tpl
index beedaa55d7..b3c094596d 100644
--- a/civicrm/templates/CRM/Contact/Form/Search/table.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Search/table.tpl
@@ -25,7 +25,7 @@
                 {$form.value[$x][$i].html|crmAddClass:'required'}
               </span>
               {if $i gt 0 or $x gt 1}
-                &nbsp;<a href="#" class="crm-reset-builder-row crm-hover-button" title="{ts}Remove this row{/ts}"><i class="crm-i fa-times"></i></a>
+                &nbsp;<a href="#" class="crm-reset-builder-row crm-hover-button" title="{ts}Remove this row{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
               {/if}
             </td>
           </tr>
diff --git a/civicrm/templates/CRM/Contact/Form/Selector.tpl b/civicrm/templates/CRM/Contact/Form/Selector.tpl
index 338c6e0883..0641bebefb 100644
--- a/civicrm/templates/CRM/Contact/Form/Selector.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Selector.tpl
@@ -10,7 +10,7 @@
 {include file="CRM/common/pager.tpl" location="top"}
 
 {include file="CRM/common/pagerAToZ.tpl"}
-<a href="#" class="crm-selection-reset crm-hover-button"><i class="crm-i fa-times-circle-o"></i> {ts}Reset all selections{/ts}</a>
+<a href="#" class="crm-selection-reset crm-hover-button"><i class="crm-i fa-times-circle-o" aria-hidden="true"></i> {ts}Reset all selections{/ts}</a>
 
 <table summary="{ts}Search results listings.{/ts}" class="selector row-highlight">
   <thead class="sticky">
@@ -81,7 +81,7 @@
             <td><a href="{crmURL p='civicrm/contact/view' q="reset=1&cid=`$row.contact_id`&key=`$qfKey`&context=`$context`"}">{if $row.is_deleted}<del>{/if}{$row.sort_name}{if $row.is_deleted}</del>{/if}</a></td>
             {if $action eq 512 or $action eq 256}
               {if !empty($columnHeaders.street_address)}
-          <td><span title="{$row.street_address|escape}">{$row.street_address|mb_truncate:22:"...":true}{if $row.do_not_mail} <span class="icon privacy-flag do-not-mail"></span>{/if}</span></td>
+          <td><span title="{$row.street_address|escape}">{$row.street_address|mb_truncate:22:"...":true}{privacyFlag field=do_not_mail condition=$row.do_not_mail}</span></td>
         {/if}
         {if !empty($columnHeaders.city)}
                 <td>{$row.city}</td>
@@ -99,20 +99,16 @@
                 {if $row.email}
                     <span title="{$row.email|escape}">
                         {$row.email|mb_truncate:17:"...":true}
-                        {if $row.on_hold}
-                          (On Hold)<span class="status-hold" title="{ts}This email is on hold (probably due to bouncing).{/ts}"></span>
-                        {elseif $row.do_not_email}
-                          <span class="icon privacy-flag do-not-email" title="{ts}Do Not Email{/ts}"></span>
-                        {/if}
+                        {privacyFlag field=do_not_email condition=$row.do_not_email}
+                        {privacyFlag field=on_hold condition=$row.on_hold}
                     </span>
                 {/if}
               </td>
               <td>
                 {if $row.phone}
                   {$row.phone}
-                  {if $row.do_not_phone}
-                    <span class="icon privacy-flag do-not-phone" title="{ts}Do Not Phone{/ts}" ></span>
-                  {/if}
+                  {privacyFlag field=do_not_phone condition=$row.do_not_phone}
+                  {privacyFlag field=do_not_sms condition=$row.do_not_sms}
                 {/if}
               </td>
            {else}
diff --git a/civicrm/templates/CRM/Contact/Form/Task/Batch.tpl b/civicrm/templates/CRM/Contact/Form/Task/Batch.tpl
index 8c62574ea5..2cd61d93b1 100644
--- a/civicrm/templates/CRM/Contact/Form/Task/Batch.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Task/Batch.tpl
@@ -19,7 +19,7 @@
       {if $field.skipDisplay}
         {continue}
       {/if}
-      <td><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</td>
+      <td>{copyIcon name=$field.name title=$field.title}{$field.title}</td>
     {/foreach}
     </tr>
     </thead>
@@ -78,4 +78,3 @@
 
 {*include batch copy js js file*}
 {include file="CRM/common/batchCopy.tpl"}
-
diff --git a/civicrm/templates/CRM/Contact/Form/Task/Email.tpl b/civicrm/templates/CRM/Contact/Form/Task/Email.tpl
index 9d1bf5989d..0ab5a8930e 100644
--- a/civicrm/templates/CRM/Contact/Form/Task/Email.tpl
+++ b/civicrm/templates/CRM/Contact/Form/Task/Email.tpl
@@ -30,14 +30,14 @@
       <td class="label">{$form.cc_id.label}</td>
       <td>
         {$form.cc_id.html}
-        <a class="crm-hover-button clear-cc-link" rel="cc_id" title="{ts}Clear{/ts}" href="#"><i class="crm-i fa-times"></i></a>
+        <a class="crm-hover-button clear-cc-link" rel="cc_id" title="{ts}Clear{/ts}" href="#"><i class="crm-i fa-times" aria-hidden="true"></i></a>
       </td>
     </tr>
     <tr class="crm-contactEmail-form-block-bcc_id" {if !$form.bcc_id.value}style="display:none;"{/if}>
       <td class="label">{$form.bcc_id.label}</td>
       <td>
         {$form.bcc_id.html}
-        <a class="crm-hover-button clear-cc-link" rel="bcc_id" title="{ts}Clear{/ts}" href="#"><i class="crm-i fa-times"></i></a>
+        <a class="crm-hover-button clear-cc-link" rel="bcc_id" title="{ts}Clear{/ts}" href="#"><i class="crm-i fa-times" aria-hidden="true"></i></a>
       </td>
     </tr>
     <tr>
diff --git a/civicrm/templates/CRM/Contact/Import/Form/Preview.tpl b/civicrm/templates/CRM/Contact/Import/Form/Preview.tpl
index ff88428d86..15b30f1fbc 100644
--- a/civicrm/templates/CRM/Contact/Import/Form/Preview.tpl
+++ b/civicrm/templates/CRM/Contact/Import/Form/Preview.tpl
@@ -48,7 +48,7 @@
         <td class="data">{$invalidRowCount}</td>
         <td class="explanation">{ts}Rows with invalid data in one or more fields (for example, invalid email address formatting). These rows will be skipped (not imported).{/ts}
             {if $invalidRowCount}
-                <div class="action-link"><a href="{$downloadErrorRecordsUrl}">&raquo; {ts}Download Errors{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadErrorRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Errors{/ts}</a></div>
             {/if}
         </td>
     </tr>
@@ -59,7 +59,7 @@
         <td class="data">{$conflictRowCount}</td>
         <td class="explanation">{ts}Rows with conflicting email addresses within this file. These rows will be skipped (not imported).{/ts}
             {if $conflictRowCount}
-                <div class="action-link"><a href="{$downloadConflictRecordsUrl}">&raquo; {ts}Download Conflicts{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadConflictRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Conflicts{/ts}</a></div>
             {/if}
         </td>
     </tr>
diff --git a/civicrm/templates/CRM/Contact/Import/Form/Summary.tpl b/civicrm/templates/CRM/Contact/Import/Form/Summary.tpl
index 7b4a540ea9..0b3577e65c 100644
--- a/civicrm/templates/CRM/Contact/Import/Form/Summary.tpl
+++ b/civicrm/templates/CRM/Contact/Import/Form/Summary.tpl
@@ -75,7 +75,7 @@
         <td class="data">{$invalidRowCount}</td>
         <td class="explanation">{ts}Rows with invalid data in one or more fields (for example, invalid email address formatting). These rows will be skipped (not imported).{/ts}
             {if $invalidRowCount}
-                <div class="action-link"><a href="{$downloadErrorRecordsUrl}">&raquo; {ts}Download Errors{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadErrorRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Errors{/ts}</a></div>
             {/if}
         </td>
     </tr>
@@ -86,7 +86,7 @@
         <td class="data">{$unMatchCount}</td>
         <td class="explanation">{ts}Rows with mismatched contact IDs... (NOT updated).{/ts}
             {if $unMatchCount}
-                <<div class="action-link"><a href="{$downloadMismatchRecordsUrl}">&raquo; {ts}Download Mismatched Contacts{/ts}</a></div>
+                <<div class="action-link"><a href="{$downloadMismatchRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Mismatched Contacts{/ts}</a></div>
             {/if}
         </td>
     </tr>
@@ -97,7 +97,7 @@
         <td class="data">{$conflictRowCount}</td>
         <td class="explanation">{ts}Rows with conflicting email addresses (NOT imported).{/ts}
             {if $conflictRowCount}
-                <div class="action-link"><a href="{$downloadConflictRecordsUrl}">&raquo; {ts}Download Conflicts{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadConflictRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Conflicts{/ts}</a></div>
             {/if}
         </td>
     </tr>
@@ -108,7 +108,7 @@
         <td class="data">{$duplicateRowCount}</td>
         <td class="explanation">{ts}Rows which are duplicates of existing CiviCRM contact records.{/ts} {$dupeActionString}
             {if $duplicateRowCount}
-                <div class="action-link"><a href="{$downloadDuplicateRecordsUrl}">&raquo; {ts}Download Duplicates{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadDuplicateRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Duplicates{/ts}</a></div>
             {/if}
         </td>
     </tr>
@@ -151,4 +151,3 @@
 
  <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
 </div>
-
diff --git a/civicrm/templates/CRM/Contact/Page/CustomSearch.tpl b/civicrm/templates/CRM/Contact/Page/CustomSearch.tpl
index f308f92478..4d9a9600d6 100644
--- a/civicrm/templates/CRM/Contact/Page/CustomSearch.tpl
+++ b/civicrm/templates/CRM/Contact/Page/CustomSearch.tpl
@@ -16,7 +16,7 @@
 {if $rows}
     {foreach from=$rows item=customTitle key=csid}
         <div class="action-link">
-            <a href="{crmURL p="civicrm/contact/search/custom" q="csid=`$csid`&reset=1"}" title="{ts}Use this search{/ts}">&raquo; {$customTitle}</a>
+            <a href="{crmURL p="civicrm/contact/search/custom" q="csid=`$csid`&reset=1"}" title="{ts}Use this search{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {$customTitle}</a>
         </div>
     {/foreach}
 {else}
diff --git a/civicrm/templates/CRM/Contact/Page/DashBoardDashlet.tpl b/civicrm/templates/CRM/Contact/Page/DashBoardDashlet.tpl
index 694dc6cb08..54b2634077 100644
--- a/civicrm/templates/CRM/Contact/Page/DashBoardDashlet.tpl
+++ b/civicrm/templates/CRM/Contact/Page/DashBoardDashlet.tpl
@@ -13,11 +13,11 @@
 {$communityMessages}
 <div class="crm-submit-buttons crm-dashboard-controls">
 <a href="#" id="crm-dashboard-configure" class="crm-hover-button show-add">
-  <i class="crm-i fa-wrench"></i> {ts}Configure Your Dashboard{/ts}
+  <i class="crm-i fa-wrench" aria-hidden="true"></i> {ts}Configure Your Dashboard{/ts}
 </a>
 
 <a style="float:right;" href="#" class="crm-hover-button show-refresh" style="margin-left: 6px;">
-  <i class="crm-i fa-refresh"></i> {ts}Refresh Dashboard Data{/ts}
+  <i class="crm-i fa-refresh" aria-hidden="true"></i> {ts}Refresh Dashboard Data{/ts}
 </a>
 
 </div>
diff --git a/civicrm/templates/CRM/Contact/Page/Dashlet.tpl b/civicrm/templates/CRM/Contact/Page/Dashlet.tpl
index 91256848cf..fa1dcfa47c 100644
--- a/civicrm/templates/CRM/Contact/Page/Dashlet.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Dashlet.tpl
@@ -16,7 +16,7 @@
     <div id="available-dashlets" class="dash-column">
         {foreach from=$availableDashlets item=row key=dashID}
       <div class="portlet">
-        <div class="portlet-header" id="{$dashID}">{$row.label}{if $admin and !$row.is_reserved}&nbsp;<a class="crm-i fa-times delete-dashlet"></a>{/if}</div>
+        <div class="portlet-header" id="{$dashID}">{$row.label}{if $admin and !$row.is_reserved}&nbsp;<a class="crm-i fa-times delete-dashlet" aria-hidden="true"></a>{/if}</div>
       </div>
         {/foreach}
     </div>
@@ -27,7 +27,7 @@
     <div id="existing-dashlets-col-0" class="dash-column">
         {foreach from=$contactDashlets.0 item=row key=dashID}
       <div class="portlet">
-        <div class="portlet-header" id="{$dashID}">{$row.label}{if $admin and !$row.is_reserved}&nbsp;<a class="crm-i fa-times delete-dashlet"></a>{/if}</div>
+        <div class="portlet-header" id="{$dashID}">{$row.label}{if $admin and !$row.is_reserved}&nbsp;<a class="crm-i fa-times delete-dashlet" aria-hidden="true"></a>{/if}</div>
       </div>
         {/foreach}
     </div>
@@ -35,7 +35,7 @@
     <div id="existing-dashlets-col-1" class="dash-column">
         {foreach from=$contactDashlets.1 item=row key=dashID}
       <div class="portlet">
-        <div class="portlet-header" id="{$dashID}">{$row.label}{if $admin and !$row.is_reserved}&nbsp;<a class="crm-i fa-times delete-dashlet"></a>{/if}</div>
+        <div class="portlet-header" id="{$dashID}">{$row.label}{if $admin and !$row.is_reserved}&nbsp;<a class="crm-i fa-times delete-dashlet" aria-hidden="true"></a>{/if}</div>
       </div>
         {/foreach}
     </div>
diff --git a/civicrm/templates/CRM/Contact/Page/DedupeException.tpl b/civicrm/templates/CRM/Contact/Page/DedupeException.tpl
index 26898114f8..2c69cc063c 100644
--- a/civicrm/templates/CRM/Contact/Page/DedupeException.tpl
+++ b/civicrm/templates/CRM/Contact/Page/DedupeException.tpl
@@ -21,7 +21,7 @@
         </td>
         <td class="crm-contact-form-block-search">
           <label>&nbsp;</label><br />
-          <button type="submit" class="button crm-button filtercontacts"><span><i class="crm-i fa-search"></i> Find Contacts</span></button>
+          <button type="submit" class="button crm-button filtercontacts"><span><i class="crm-i fa-search" aria-hidden="true"></i> Find Contacts</span></button>
         </td>
       </tr>
     </table>
@@ -60,7 +60,7 @@
             <a href="{crmURL p='civicrm/contact/view' q="reset=1&cid=`$exception.contact_id2`"}" target="_blank">{ $exception.$contact2name }</a>
           </td>
           <td>
-            <a id='duplicateContacts' href="#" title={ts}Remove Exception{/ts} onClick="processDupes( {$exception.contact_id1}, {$exception.contact_id2}, 'nondupe-dupe', 'dedupe-exception' );return false;">&raquo; {ts}Remove Exception{/ts}</a>
+            <a id='duplicateContacts' href="#" title={ts}Remove Exception{/ts} onClick="processDupes( {$exception.contact_id1}, {$exception.contact_id2}, 'nondupe-dupe', 'dedupe-exception' );return false;"><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Remove Exception{/ts}</a>
           </td>
         </tr>
 
diff --git a/civicrm/templates/CRM/Contact/Page/DedupeFind.tpl b/civicrm/templates/CRM/Contact/Page/DedupeFind.tpl
index d285385846..9f811b99d2 100644
--- a/civicrm/templates/CRM/Contact/Page/DedupeFind.tpl
+++ b/civicrm/templates/CRM/Contact/Page/DedupeFind.tpl
@@ -107,31 +107,31 @@
 {elseif $context eq 'conflicts'}
   {if call_user_func(array('CRM_Core_Permission','check'), 'force merge duplicate contacts')}
      {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q="`$urlQuery`&action=map&mode=aggressive" a=1}{/capture}
-     <a href="{$backURL}" title="{ts}Force Merge Selected Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in force merge mode - all selected duplicates will be merged into main contacts even in case of any conflicts. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-bolt"></i> {ts}Force Merge Selected Duplicates{/ts}</span></a>
+     <a href="{$backURL}" title="{ts}Force Merge Selected Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in force merge mode - all selected duplicates will be merged into main contacts even in case of any conflicts. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-bolt" aria-hidden="true"></i> {ts}Force Merge Selected Duplicates{/ts}</span></a>
 
      {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q="`$urlQuery`&action=map" a=1}{/capture}
-     <a href="{$backURL}" title="{ts}Safe Merge Selected Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress"></i> {ts}Safe Merge Selected Duplicates{/ts}</span></a>
+     <a href="{$backURL}" title="{ts}Safe Merge Selected Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress" aria-hidden="true"></i> {ts}Safe Merge Selected Duplicates{/ts}</span></a>
   {/if}
 
   {capture assign=backURL}{crmURL p="civicrm/contact/dedupefind" q="`$urlQuery`&action=update&selected=0" a=1}{/capture}
-   <a href="{$backURL}" title="{ts}List All Duplicates{/ts}" class="button"><span><i class="crm-i fa-refresh"></i> {ts}List All Duplicates{/ts}</span></a>
+   <a href="{$backURL}" title="{ts}List All Duplicates{/ts}" class="button"><span><i class="crm-i fa-refresh" aria-hidden="true"></i> {ts}List All Duplicates{/ts}</span></a>
 {else}
    {capture assign=backURL}{crmURL p="civicrm/contact/dedupefind" q="`$urlQuery`&action=renew" a=1}{/capture}
    <a href="{$backURL}" title="{ts}Refresh List of Duplicates{/ts}" onclick="return confirm('{ts escape="js"}This will refresh the duplicates list. Click OK to proceed.{/ts}');" class="button">
-     <span><i class="crm-i fa-refresh"></i> {ts}Refresh Duplicates{/ts}</span>
+     <span><i class="crm-i fa-refresh" aria-hidden="true"></i> {ts}Refresh Duplicates{/ts}</span>
    </a>
 
   {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q="`$urlQuery`&action=map" a=1}{/capture}
-   <a href="{$backURL}" title="{ts}Batch Merge Duplicate Contacts{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress"></i> {ts}Batch Merge Selected Duplicates{/ts}</span></a>
+   <a href="{$backURL}" title="{ts}Batch Merge Duplicate Contacts{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the selected duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress" aria-hidden="true"></i> {ts}Batch Merge Selected Duplicates{/ts}</span></a>
 
    {capture assign=backURL}{crmURL p="civicrm/contact/dedupemerge" q=$urlQuery a=1}{/capture}
-   <a href="{$backURL}" title="{ts}Batch Merge Duplicate Contacts{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the listed duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress"></i> {ts}Batch Merge All Duplicates{/ts}</span></a>
+   <a href="{$backURL}" title="{ts}Batch Merge Duplicate Contacts{/ts}" onclick="return confirm('{ts escape="js"}This will run the batch merge process on the listed duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation.{/ts}');" class="button"><span><i class="crm-i fa-compress" aria-hidden="true"></i> {ts}Batch Merge All Duplicates{/ts}</span></a>
 
-   <a href='#' title="{ts}Flip Selected Duplicates{/ts}" class="crm-dedupe-flip-selections button"><span><i class="crm-i fa-exchange"></i> {ts}Flip Selected Duplicates{/ts}</span></a>
+   <a href='#' title="{ts}Flip Selected Duplicates{/ts}" class="crm-dedupe-flip-selections button"><span><i class="crm-i fa-exchange" aria-hidden="true"></i> {ts}Flip Selected Duplicates{/ts}</span></a>
 
    {capture assign=backURL}{crmURL p="civicrm/contact/deduperules" q="reset=1" a=1}{/capture}
    <a href="{$backURL}" class="button crm-button-type-cancel">
-     <span><i class="crm-i fa-times"></i> {ts}Done{/ts}</span>
+     <span><i class="crm-i fa-times" aria-hidden="true"></i> {ts}Done{/ts}</span>
    </a>
 {/if}
 <div style="clear: both;"></div>
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/Address.tpl b/civicrm/templates/CRM/Contact/Page/Inline/Address.tpl
index d507e76d3f..8861f0ba0f 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/Address.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/Address.tpl
@@ -12,7 +12,7 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{if $add}{ts}Edit address{/ts}{else}{ts}Add address{/ts}{/if}"{/if}>
     {if $permission EQ 'edit'}
       <div class="crm-edit-help">
-        <span class="crm-i fa-pencil"></span> {if $add}{ts}Edit address{/ts}{else}{ts}Add address{/ts}{/if}
+        <span class="crm-i fa-pencil" aria-hidden="true"></span> {if $add}{ts}Edit address{/ts}{else}{ts}Add address{/ts}{/if}
       </div>
     {/if}
     {if !$add}
@@ -24,14 +24,14 @@
       <div class="crm-summary-row {if $add.is_primary eq 1} primary{/if}">
         <div class="crm-label">
           {ts 1=$add.location_type}%1 Address{/ts}
-          {if $privacy.do_not_mail}<span class="icon privacy-flag do-not-mail" title="{ts}Privacy flag: Do Not Mail{/ts}"></span>{/if}
+          {privacyFlag field=do_not_mail condition=$privacy.do_not_mail}
           {if $config->mapProvider AND
               !empty($add.geo_code_1) AND
               is_numeric($add.geo_code_1) AND
               !empty($add.geo_code_2) AND
               is_numeric($add.geo_code_2)
           }
-          <br /><a href="{crmURL p='civicrm/contact/map' q="reset=1&cid=`$contactId`&lid=`$add.location_type_id`"}" title="{ts 1=`$add.location_type`}Map %1 Address{/ts}"><span class="geotag">{ts}Map{/ts}</span></a>
+          <br /><a href="{crmURL p='civicrm/contact/map' q="reset=1&cid=`$contactId`&lid=`$add.location_type_id`"}" title="{ts 1=`$add.location_type`}Map %1 Address{/ts}"><i class="crm-i fa-map-marker" aria-hidden="true"></i> {ts}Map{/ts}</a>
           {/if}
         </div>
         <div class="crm-content">
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/CommunicationPreferences.tpl b/civicrm/templates/CRM/Contact/Page/Inline/CommunicationPreferences.tpl
index bacf3cad18..1093e03c92 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/CommunicationPreferences.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/CommunicationPreferences.tpl
@@ -12,7 +12,7 @@
   <div class="crm-clear crm-inline-block-content"{if $permission EQ 'edit'} title="{ts}Edit communication preferences{/ts}"{/if}>
     {if $permission EQ 'edit'}
     <div class="crm-edit-help">
-      <span class="crm-i fa-pencil"></span> {ts}Edit communication preferences{/ts}
+      <span class="crm-i fa-pencil" aria-hidden="true"></span> {ts}Edit communication preferences{/ts}
     </div>
     {/if}
     <div class="crm-summary-row">
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/ContactInfo.tpl b/civicrm/templates/CRM/Contact/Page/Inline/ContactInfo.tpl
index 9c76fe0673..e6f23db339 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/ContactInfo.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/ContactInfo.tpl
@@ -12,7 +12,7 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Edit info{/ts}"{/if}>
     {if $permission EQ 'edit'}
     <div class="crm-edit-help">
-      <span class="crm-i fa-pencil"></span> {ts}Edit info{/ts}
+      <span class="crm-i fa-pencil" aria-hidden="true"></span> {ts}Edit info{/ts}
     </div>
     {/if}
 
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/ContactName.tpl b/civicrm/templates/CRM/Contact/Page/Inline/ContactName.tpl
index 715c7c5bb9..f32f169cf7 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/ContactName.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/ContactName.tpl
@@ -11,7 +11,7 @@
   <div class="crm-inline-block-content"{if $permission EQ 'edit'} title="{ts}Edit Contact Name{/ts}"{/if}>
     {if $permission EQ 'edit'}
       <div class="crm-edit-help">
-        <span class="crm-i fa-pencil"></span> {ts}Edit name{/ts}
+        <span class="crm-i fa-pencil" aria-hidden="true"></span> {ts}Edit name{/ts}
       </div>
     {/if}
 
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/Demographics.tpl b/civicrm/templates/CRM/Contact/Page/Inline/Demographics.tpl
index 3746377aaf..dee1ed5c2d 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/Demographics.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/Demographics.tpl
@@ -11,7 +11,7 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Edit demographics{/ts}"{/if}>
     {if $permission EQ 'edit'}
     <div class="crm-edit-help">
-      <span class="crm-i fa-pencil"></span> {ts}Edit demographics{/ts}
+      <span class="crm-i fa-pencil" aria-hidden="true"></span> {ts}Edit demographics{/ts}
     </div>
     {/if}
     <div class="crm-summary-row">
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/Email.tpl b/civicrm/templates/CRM/Contact/Page/Inline/Email.tpl
index 48aa7263cf..ee977d4314 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/Email.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/Email.tpl
@@ -12,14 +12,14 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Add or edit email{/ts}"{/if}>
   {if $permission EQ 'edit'}
     <div class="crm-edit-help">
-      <span class="crm-i fa-pencil"></span> {if empty($email)}{ts}Add email{/ts}{else}{ts}Add or edit email{/ts}{/if}
+      <span class="crm-i fa-pencil" aria-hidden="true"></span> {if empty($email)}{ts}Add email{/ts}{else}{ts}Add or edit email{/ts}{/if}
     </div>
   {/if}
   {if empty($email)}
     <div class="crm-summary-row">
       <div class="crm-label">
         {ts}Email{/ts}
-        {if $privacy.do_not_email}<span class="icon privacy-flag do-not-email" title="{ts}Privacy flag: Do Not Email{/ts}"></span>{/if}
+        {if $privacy.do_not_email}{privacyFlag field=do_not_email}{/if}
       </div>
       <div class="crm-content"></div>
     </div>
@@ -29,7 +29,7 @@
     <div class="crm-summary-row {if $item.is_primary eq 1}primary{/if}">
       <div class="crm-label">
         {$item.location_type} {ts}Email{/ts}
-        {if $privacy.do_not_email}<span class="icon privacy-flag do-not-email" title="{ts}Privacy flag: Do Not Email{/ts}"></span>{elseif $item.on_hold}<span class="icon privacy-flag email-hold" title="{ts}Email on hold - generally due to bouncing.{/ts}"></span>{/if}
+        {privacyFlag field=do_not_email condition=$privacy.do_not_email}{privacyFlag field=on_hold condition=$item.on_hold}
       </div>
       <div class="crm-content crm-contact_email">
         {if !$item.on_hold and !$privacy.do_not_email}
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/IM.tpl b/civicrm/templates/CRM/Contact/Page/Inline/IM.tpl
index 120589befe..1dc0675caf 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/IM.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/IM.tpl
@@ -12,7 +12,7 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Add or edit IM{/ts}"{/if}>
     {if $permission EQ 'edit'}
       <div class="crm-edit-help">
-        <span class="crm-i fa-pencil"></span> {if empty($im)}{ts}Add IM{/ts}{else}{ts}Add or edit IM{/ts}{/if}
+        <span class="crm-i fa-pencil" aria-hidden="true"></span> {if empty($im)}{ts}Add IM{/ts}{else}{ts}Add or edit IM{/ts}{/if}
       </div>
     {/if}
     {if empty($im)}
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/OpenID.tpl b/civicrm/templates/CRM/Contact/Page/Inline/OpenID.tpl
index 9fa4ead72e..2964d8c46f 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/OpenID.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/OpenID.tpl
@@ -12,7 +12,7 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Add or edit OpenID{/ts}"{/if}>
     {if $permission EQ 'edit'}
       <div class="crm-edit-help">
-        <span class="crm-i fa-pencil"></span> {if empty($openid)}{ts}Add OpenID{/ts}{else}{ts}Add or edit OpenID{/ts}{/if}
+        <span class="crm-i fa-pencil" aria-hidden="true"></span> {if empty($openid)}{ts}Add OpenID{/ts}{else}{ts}Add or edit OpenID{/ts}{/if}
       </div>
     {/if}
     {if empty($openid)}
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/Phone.tpl b/civicrm/templates/CRM/Contact/Page/Inline/Phone.tpl
index 2b788cb177..953fa202e4 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/Phone.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/Phone.tpl
@@ -12,14 +12,15 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Add or edit phone{/ts}"{/if}>
     {if $permission EQ 'edit'}
       <div class="crm-edit-help">
-        <span class="crm-i fa-pencil"></span> {if empty($phone)}{ts}Add phone{/ts}{else}{ts}Add or edit phone{/ts}{/if}
+        <span class="crm-i fa-pencil" aria-hidden="true"></span> {if empty($phone)}{ts}Add phone{/ts}{else}{ts}Add or edit phone{/ts}{/if}
       </div>
     {/if}
     {if empty($phone)}
       <div class="crm-summary-row">
         <div class="crm-label">
           {ts}Phone{/ts}
-          {if $privacy.do_not_phone}<span class="icon privacy-flag do-not-phone" title="{ts}Privacy flag: Do Not Phone{/ts}"></span>{/if}
+          {privacyFlag field=do_not_sms condition=$privacy.do_not_sms}
+          {privacyFlag field=do_not_phone condition=$privacy.do_not_phone}
         </div>
         <div class="crm-content"></div>
       </div>
@@ -28,7 +29,8 @@
       {if $item.phone || $item.phone_ext}
         <div class="crm-summary-row {if $item.is_primary eq 1}primary{/if}">
           <div class="crm-label">
-            {if $privacy.do_not_phone}<span class="icon privacy-flag do-not-phone" title="{ts}Privacy flag: Do Not Phone{/ts}"></span>{/if}
+            {privacyFlag field=do_not_sms condition=$privacy.do_not_sms}
+            {privacyFlag field=do_not_phone condition=$privacy.do_not_phone}
             {$item.location_type} {$item.phone_type}
           </div>
           <div class="crm-content crm-contact_phone">
diff --git a/civicrm/templates/CRM/Contact/Page/Inline/Website.tpl b/civicrm/templates/CRM/Contact/Page/Inline/Website.tpl
index 79e1b75819..d509655b4d 100644
--- a/civicrm/templates/CRM/Contact/Page/Inline/Website.tpl
+++ b/civicrm/templates/CRM/Contact/Page/Inline/Website.tpl
@@ -12,7 +12,7 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Add or edit website{/ts}"{/if}>
     {if $permission EQ 'edit'}
       <div class="crm-edit-help">
-        <span class="crm-i fa-pencil"></span> {if empty($website)}{ts}Add website{/ts}{else}{ts}Add or edit website{/ts}{/if}
+        <span class="crm-i fa-pencil" aria-hidden="true"></span> {if empty($website)}{ts}Add website{/ts}{else}{ts}Add or edit website{/ts}{/if}
       </div>
     {/if}
     {if empty($website)}
diff --git a/civicrm/templates/CRM/Contact/Page/View/CustomDataFieldView.tpl b/civicrm/templates/CRM/Contact/Page/View/CustomDataFieldView.tpl
index 50cf674c88..e9042f2157 100644
--- a/civicrm/templates/CRM/Contact/Page/View/CustomDataFieldView.tpl
+++ b/civicrm/templates/CRM/Contact/Page/View/CustomDataFieldView.tpl
@@ -11,7 +11,7 @@
   <div class="crm-clear crm-inline-block-content" {if $permission EQ 'edit'}title="{ts}Edit{/ts}"{/if}>
     {if $permission EQ 'edit'}
       <div class="crm-edit-help">
-        <span class="crm-i fa-pencil"></span> {ts}Edit{/ts}
+        <span class="crm-i fa-pencil" aria-hidden="true"></span> {ts}Edit{/ts}
       </div>
     {/if}
 
diff --git a/civicrm/templates/CRM/Contact/Page/View/Note.tpl b/civicrm/templates/CRM/Contact/Page/View/Note.tpl
index 5ff7c4c761..6e8c11ab7f 100644
--- a/civicrm/templates/CRM/Contact/Page/View/Note.tpl
+++ b/civicrm/templates/CRM/Contact/Page/View/Note.tpl
@@ -84,7 +84,7 @@
 
 {if ($permission EQ 'edit' OR $canAddNotes) AND ($action eq 16)}
    <div class="action-link">
-   <a accesskey="N" href="{crmURL p='civicrm/contact/view/note' q="cid=`$contactId`&action=add"}" class="button medium-popup"><span><i class="crm-i fa-comment"></i> {ts}Add Note{/ts}</span></a>
+   <a accesskey="N" href="{crmURL p='civicrm/contact/view/note' q="cid=`$contactId`&action=add"}" class="button medium-popup"><span><i class="crm-i fa-comment" aria-hidden="true"></i> {ts}Add Note{/ts}</span></a>
    </div>
    <div class="clear"></div>
 {/if}
@@ -204,13 +204,13 @@
             <td class="crm-note-comment">
                 {if $note.comment_count}
                     <span id="{$note.id}_show" style="display:block" class="icon_comments_show">
-                        <a href="#" onclick="showHideComments({$note.id}); return false;" title="{ts}Show comments for this note.{/ts}"><i class="crm-i fa-caret-right"></i></span></a>
+                        <a href="#" onclick="showHideComments({$note.id}); return false;" title="{ts}Show comments for this note.{/ts}"><i class="crm-i fa-caret-right" aria-hidden="true"></i></span></a>
                     </span>
                     <span id="{$note.id}_hide" style="display:none" class="icon_comments_hide">
-                        <a href="#" onclick="showHideComments({$note.id}); return false;" title="{ts}Hide comments for this note.{/ts}"><i class="crm-i fa-caret-down"></i></span></a>
+                        <a href="#" onclick="showHideComments({$note.id}); return false;" title="{ts}Hide comments for this note.{/ts}"><i class="crm-i fa-caret-down" aria-hidden="true"></i></span></a>
                     </span>
                 {else}
-                    <span class="crm-i fa-caret-right" id="{$note.id}_hide" style="display:none"></span>
+                    <span class="crm-i fa-caret-right" id="{$note.id}_hide" style="display:none" aria-hidden="true"></span>
                 {/if}
             </td>
             <td class="crm-note-note">
diff --git a/civicrm/templates/CRM/Contact/Page/View/RelationshipPerm.tpl b/civicrm/templates/CRM/Contact/Page/View/RelationshipPerm.tpl
index bf582d84c5..709b0265c8 100644
--- a/civicrm/templates/CRM/Contact/Page/View/RelationshipPerm.tpl
+++ b/civicrm/templates/CRM/Contact/Page/View/RelationshipPerm.tpl
@@ -24,9 +24,12 @@
 {/if}
 
 <span class="fa-stack" title="{$permText}">
-  <i class="crm-i fa-square fa-stack-2x {if $permType eq 1}crm-i-blue{else}crm-i-green{/if}"></i>
-  <i class="crm-i {if $permType eq 1}fa-pencil{else}fa-eye{/if} fa-inverse fa-stack-1x"></i>
+  <i class="crm-i fa-square fa-stack-2x {if $permType eq 1}crm-i-blue{else}crm-i-green{/if}" aria-hidden="true"></i>
+  <i class="crm-i {if $permType eq 1}fa-pencil{else}fa-eye{/if} fa-inverse fa-stack-1x" aria-hidden="true"></i>
 </span>
+{if !$displayText}
+<span class="sr-only">{$permText}</span>
+{/if}
 
 {* Used for viewing a relationship *}
 {if $displayText}
diff --git a/civicrm/templates/CRM/Contact/Page/View/Summary.tpl b/civicrm/templates/CRM/Contact/Page/View/Summary.tpl
index 2fd815c233..bad21b98b2 100644
--- a/civicrm/templates/CRM/Contact/Page/View/Summary.tpl
+++ b/civicrm/templates/CRM/Contact/Page/View/Summary.tpl
@@ -110,7 +110,7 @@
         {foreach from=$allTabs key=tabName item=tabValue}
           <li id="tab_{$tabValue.id}" class="crm-tab-button ui-corner-all crm-count-{$tabValue.count}{if isset($tabValue.class)} {$tabValue.class}{/if}">
             <a href="{$tabValue.url}" title="{$tabValue.title|escape}">
-              <i class="{if $tabValue.icon}{$tabValue.icon}{else}crm-i fa-puzzle-piece{/if}"></i>
+              <i class="{if $tabValue.icon}{$tabValue.icon}{else}crm-i fa-puzzle-piece{/if}" aria-hidden="true"></i>
               <span>{$tabValue.title}</span>
               {if empty($tabValue.hideCount)}<em>{$tabValue.count}</em>{/if}
             </a>
diff --git a/civicrm/templates/CRM/Contribute/Form/AdditionalPayment.tpl b/civicrm/templates/CRM/Contribute/Form/AdditionalPayment.tpl
index 3fd811d48c..d3403fae9b 100644
--- a/civicrm/templates/CRM/Contribute/Form/AdditionalPayment.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/AdditionalPayment.tpl
@@ -29,7 +29,7 @@
     {/if}
     {if $paymentType eq 'owed'}
       <div class="action-link css_right crm-link-credit-card-mode">
-        <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}">&raquo; {ts}submit credit card payment{/ts}</a>
+        <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}submit credit card payment{/ts}</a>
       </div>
     {/if}
   {/if}
diff --git a/civicrm/templates/CRM/Contribute/Form/CancelSubscription.tpl b/civicrm/templates/CRM/Contribute/Form/CancelSubscription.tpl
index 74e5e2f186..c193513b62 100644
--- a/civicrm/templates/CRM/Contribute/Form/CancelSubscription.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/CancelSubscription.tpl
@@ -12,7 +12,7 @@
 <div class="help">
   <div class="icon inform-icon"></div>&nbsp;
   {$cancelRecurDetailText}
-  {if !$cancelSupported}
+  {if $cancelRecurNotSupportedText}
     <div class="status-warning">{$cancelRecurNotSupportedText}</div>
   {/if}
 </div>
diff --git a/civicrm/templates/CRM/Contribute/Form/Contribution.tpl b/civicrm/templates/CRM/Contribute/Form/Contribution.tpl
index c4c8815b5f..0df23f41bd 100644
--- a/civicrm/templates/CRM/Contribute/Form/Contribution.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/Contribution.tpl
@@ -50,7 +50,7 @@
       {else}
         {capture assign=ccModeLink}{crmURL p='civicrm/contact/view/contribution' q="reset=1&action=add&context=standalone&mode=live"}{/capture}
       {/if}
-     <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}">&raquo; {ts}submit credit card contribution{/ts}</a>
+     <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}"><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}submit credit card contribution{/ts}</a>
     </div>
     {/if}
   <div class="crm-submit-buttons">
@@ -148,7 +148,7 @@
         <td>
         {if !$isUsePaymentBlock && $contactId && $contribID && $contributionMode EQ null && $contribution_status_id eq 2}
           {capture assign=payNowLink}{crmURL p='civicrm/contact/view/contribution' q="reset=1&action=update&id=`$contribID`&cid=`$contactId`&context=`$context`&mode=live"}{/capture}
-          <a class="open-inline action-item crm-hover-button" href="{$payNowLink}">&raquo; {ts}Pay with Credit Card{/ts}</a>
+          <a class="open-inline action-item crm-hover-button" href="{$payNowLink}"><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}Pay with Credit Card{/ts}</a>
         {/if}
       </td>
       </tr>
@@ -549,14 +549,14 @@ function adjustPayment( ) {
 }
 
 {/literal}{if $processorSupportsFutureStartDate}{literal}
-cj ('input:radio[name="is_recur"]').click( function( ) {
+cj ('#is_recur').click( function( ) {
   showStartDate( );
 });
 
 showStartDate( );
 
 function showStartDate( ) {
-  if (cj( 'input:radio[name="is_recur"]:checked').val( ) == 0 ) {
+  if (!cj('#is_recur').is(':checked')) {
     cj('#start_date').hide( );
   }
   else {
diff --git a/civicrm/templates/CRM/Contribute/Form/Contribution/PreviewHeader.tpl b/civicrm/templates/CRM/Contribute/Form/Contribution/PreviewHeader.tpl
index 48fd5158f5..fe160753f4 100644
--- a/civicrm/templates/CRM/Contribute/Form/Contribution/PreviewHeader.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/Contribution/PreviewHeader.tpl
@@ -9,7 +9,7 @@
 *}
 {* Displays Test-drive mode header for Contribution pages. *}
 <div class="messages status no-popup">
-    <i class="crm-i fa-cogs"></i>
+    <i class="crm-i fa-cogs" aria-hidden="true"></i>
     <strong>{ts}Test-drive Your Contribution Page{/ts}</strong>
     <p>{ts}This page is currently running in <strong>test-drive mode</strong>. Transactions will be sent to your payment processor's test server. <strong>No live financial transactions will be submitted. However, a contact record will be created or updated and a test contribution record will be saved to the database. Use obvious test contact names so you can review and delete these records as needed. Test contributions are not visible on the Contributions tab, but can be viewed by searching for 'Test Contributions' in the CiviContribute search form.</strong> Refer to your payment processor's documentation for information on values to use for test credit card number, security code, postal code, etc.{/ts}</p>
 </div>
diff --git a/civicrm/templates/CRM/Contribute/Form/Contribution/ThankYou.tpl b/civicrm/templates/CRM/Contribute/Form/Contribution/ThankYou.tpl
index 020ba6265d..bc238abd49 100644
--- a/civicrm/templates/CRM/Contribute/Form/Contribution/ThankYou.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/Contribution/ThankYou.tpl
@@ -23,13 +23,13 @@
   {* Show link to Tell a Friend (CRM-2153) *}
   {if $friendText}
     <div id="tell-a-friend" class="crm-section friend_link-section">
-      <a href="{$friendURL}" title="{$friendText|escape:'html'}" class="button"><span>&raquo; {$friendText}</span></a>
+      <a href="{$friendURL}" title="{$friendText|escape:'html'}" class="button"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {$friendText}</span></a>
     </div>{if !$linkText}<br /><br />{/if}
   {/if}
   {* Add button for donor to create their own Personal Campaign page *}
   {if $linkText}
     <div class="crm-section create_pcp_link-section">
-      <a href="{$linkTextUrl}" title="{$linkText|escape:'html'}" class="button"><span>&raquo; {$linkText}</span></a>
+      <a href="{$linkTextUrl}" title="{$linkText|escape:'html'}" class="button"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {$linkText}</span></a>
     </div><br /><br />
   {/if}
 
diff --git a/civicrm/templates/CRM/Contribute/Form/ContributionPage/Tab.hlp b/civicrm/templates/CRM/Contribute/Form/ContributionPage/Tab.hlp
index 0da4ccdfbc..74944271f7 100644
--- a/civicrm/templates/CRM/Contribute/Form/ContributionPage/Tab.hlp
+++ b/civicrm/templates/CRM/Contribute/Form/ContributionPage/Tab.hlp
@@ -13,49 +13,49 @@
 {htxt id="id-configure-contrib-pages"}
 <table>
 <tr>
-    <td><a href="{crmURL p='civicrm/admin/contribute/settings' q="reset=1&action=update&id=`$contributionPageID`"}" id="idContribPageSettings">&raquo; {ts}Title and Settings{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/admin/contribute/settings' q="reset=1&action=update&id=`$contributionPageID`"}" id="idContribPageSettings"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Title and Settings{/ts}</a></td>
     <td>{ts}Use this form to edit the page title, financial type (e.g. donation, campaign contribution, etc.), goal amount, introduction, and status (active/inactive) for this online contribution page.{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/admin/contribute/amount' q="reset=1&action=update&id=`$contributionPageID`"}" id="idAmount">&raquo; {ts}Amount{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/admin/contribute/amount' q="reset=1&action=update&id=`$contributionPageID`"}" id="idAmount"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Amount{/ts}</a></td>
     <td>{ts}Use this form to configure Contribution Amount options. You can give contributors the ability to enter their own contribution amounts and/or provide a fixed list of amounts. For fixed amounts, you can enter a label for each 'level' of contribution (e.g. Friend, Sustainer, etc.). If you allow people to enter their own dollar amounts, you can also set minimum and maximum values. Depending on your choice of Payment Processor, you may be able to offer a recurring contribution option.{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/admin/contribute/membership' q="reset=1&action=update&id=`$contributionPageID`"}" id="idMembership">&raquo; {ts}Memberships{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/admin/contribute/membership' q="reset=1&action=update&id=`$contributionPageID`"}" id="idMembership"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Memberships{/ts}</a></td>
      <td>{ts}Use this form to enable and configure a Membership Signup and Renewal section for this Online Contribution Page. If you're not using this page for membership signup, leave the Enabled box un-checked.{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/admin/contribute/thankYou' q="reset=1&action=update&id=`$contributionPageID`"}" id="idThanks">&raquo; {ts}Thank-you and Receipting{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/admin/contribute/thankYou' q="reset=1&action=update&id=`$contributionPageID`"}" id="idThanks"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Thank-you and Receipting{/ts}</a></td>
     <td>{ts}Use this form to configure the thank-you message and receipting options. Contributors will see a confirmation and thank-you page after whenever an online contribution is successfully processed. You provide the content and layout of the thank-you section below. You also control whether an electronic receipt is automatically emailed to each contributor, and you can add a custom message to that receipt.{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/admin/contribute/friend' q="reset=1&action=update&id=`$contributionPageID`"}" id="idFriend">&raquo; {ts}Tell a Friend{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/admin/contribute/friend' q="reset=1&action=update&id=`$contributionPageID`"}" id="idFriend"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Tell a Friend{/ts}</a></td>
     <td>{ts}Tell a Friend gives your contributors an easy way to spread the word about this fundraising campaign. The contribution thank-you page will include a link to a form where they can enter their friends' email addresses, along with a personalized message. CiviCRM will record these solicitation activities, and will add the friends to your database.{/ts}</td>
 </tr>
 <tr>
-   <td><a href="{crmURL p='civicrm/admin/contribute/custom' q="reset=1&action=update&id=`$contributionPageID`"}" id="idCustom">&raquo; {ts}Include Profiles{/ts}</a></td>
+   <td><a href="{crmURL p='civicrm/admin/contribute/custom' q="reset=1&action=update&id=`$contributionPageID`"}" id="idCustom"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Include Profiles{/ts}</a></td>
     <td>{ts}You may want to collect information from contributors beyond what is required to make a contribution. For example, you may want to inquire about volunteer availability and skills. Add any number of fields to your contribution form by selecting CiviCRM Profiles (collections of fields) to include at the beginning of the page, and/or at the bottom.{/ts}<br />
 {capture assign=adminGroupURL}{crmURL p="civicrm/admin/uf/group" q="reset=1&action=browse"}{/capture}
 {ts 1=$adminGroupURL}You can use existing CiviCRM Profiles on your page or create profile(s) specifically for use in Online Contribution pages. Go to <a href="%1"><strong>Administer CiviCRM Profiles</strong></a> if you need to review, modify or create profiles (you can come back at any time to select or update the Profile(s) used for this page).{/ts}</td>
 </tr>
 <tr>
-   <td><a href="{crmURL p='civicrm/admin/contribute/premium q="reset=1&action=update&id=`$contributionPageID`"}" id="idPremium">&raquo; {ts}Premiums{/ts}</a></td>
+   <td><a href="{crmURL p='civicrm/admin/contribute/premium q="reset=1&action=update&id=`$contributionPageID`"}" id="idPremium"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Premiums{/ts}</a></td>
     <td>{ts}Enable the Premiums section for this Online Contribution Page, and customize the title and introductory message (e.g ...in appreciation of your support, you will be able to select from a number of exciting thank-you gifts...). You can optionally provide a contact email address and/or phone number for inquiries. Then select and review the premiums that you want to offer on this contribution page.{/ts}</td>
 </tr>
 <tr>
-   <td><a href="{crmURL p='civicrm/admin/contribute/widget' q="reset=1&action=update&id=`$contributionPageID`"}" id="idWidget">&raquo; {ts}Widget{/ts}</a></td>
+   <td><a href="{crmURL p='civicrm/admin/contribute/widget' q="reset=1&action=update&id=`$contributionPageID`"}" id="idWidget"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Widget{/ts}</a></td>
    <td>{ts}Widgets allow you and your supporters to easily promote this fund-raising campaign. Widget code can be added to any web page.  They will provide a real-time display of current contribution results, and a direct link to this contribution page.{/ts}</td>
 </tr>
 <tr>
-  <td><a href="{crmURL p='civicrm/admin/contribute/pcp' q="reset=1&action=update&id=`$contributionPageID`"}" id="idPCP">&raquo; {ts}Personal Campaign Pages{/ts}</a></td>
+  <td><a href="{crmURL p='civicrm/admin/contribute/pcp' q="reset=1&action=update&id=`$contributionPageID`"}" id="idPCP"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Personal Campaign Pages{/ts}</a></td>
   <td>{ts}Allow constituents to create their own personal fundraising pages linked to this contribution page.{/ts}</td>
 </tr>
 <tr>
-  <td><a href="{crmURL p='civicrm/contribute/transact' q="reset=1&action=preview&id=`$contributionPageID`"}" id="idTest">&raquo; {ts}Online Contribution{/ts}</a><br /> ({ts}Test-drive{/ts})</td>
+  <td><a href="{crmURL p='civicrm/contribute/transact' q="reset=1&action=preview&id=`$contributionPageID`"}" id="idTest"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Online Contribution{/ts}</a><br /> ({ts}Test-drive{/ts})</td>
   <td>{ts}Test-drive the entire contribution process&mdash;including custom fields, confirmation, thank-you page, and receipting. Transactions will be directed to your payment processor's test server. No live financial transactions will be submitted. However, a contact record will be created or updated and a test contribution record will be saved to the database. Use obvious test contact names so you can review and delete these records as needed. Test contributions are not visible on the Contributions tab, but can be viewed by searching for 'Test Contributions' in the CiviContribute search form.{/ts}</td>
 </tr>
 <tr>
-  <td><a href="{crmURL p='civicrm/contribute/transact' q="reset=1&id=`$contributionPageID`"}" id="idLive">&raquo; {ts}Online Contribution{/ts}</a><br /> ({ts}Live{/ts})</td>
+  <td><a href="{crmURL p='civicrm/contribute/transact' q="reset=1&id=`$contributionPageID`"}" id="idLive"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Online Contribution{/ts}</a><br /> ({ts}Live{/ts})</td>
   <td>{ts}Review your customized <strong>LIVE</strong> online contribution page here. Use the following URL in links and buttons on any website to send visitors to this live page:{/ts}<br />
       <strong>{crmURL a=1 fe=1 p="civicrm/contribute/transact" q="reset=1&id=`$contributionPageID`"}</strong></td>
 </tr>
diff --git a/civicrm/templates/CRM/Contribute/Form/ContributionPage/Widget.tpl b/civicrm/templates/CRM/Contribute/Form/ContributionPage/Widget.tpl
index 0d47f6ee58..2f8eb10031 100644
--- a/civicrm/templates/CRM/Contribute/Form/ContributionPage/Widget.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/ContributionPage/Widget.tpl
@@ -60,7 +60,7 @@
                     </div>
                     <textarea rows="8" cols="50" name="widget_code" id="widget_code">{include file="CRM/Contribute/Page/Widget.tpl" widgetId=$widget_id cpageId=$cpageId}</textarea>
                     <br />
-                    <strong><a href="#" onclick="Widget.widget_code.select(); return false;">&raquo; {ts}Select Code{/ts}</a></strong>
+                    <strong><a href="#" onclick="Widget.widget_code.select(); return false;"><i class="crm-i fa-code" aria-hidden="true"></i> {ts}Select Code{/ts}</a></strong>
                 {else}
                     <div class="description">
                         {ts}The code for adding this widget to web pages will be displayed here after you click <strong>Save and Preview</strong>.{/ts}
diff --git a/civicrm/templates/CRM/Contribute/Form/ContributionView.tpl b/civicrm/templates/CRM/Contribute/Form/ContributionView.tpl
index 439d97e660..c7e0c8fe9c 100644
--- a/civicrm/templates/CRM/Contribute/Form/ContributionView.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/ContributionView.tpl
@@ -17,10 +17,10 @@
         {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=update&context=$context&key=$searchKey"}
       {/if}
       <a class="button" href="{crmURL p='civicrm/contact/view/contribution' q=$urlParams}" accesskey="e"><span>
-          <i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span>
+          <i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span>
       </a>
       {if $paymentButtonName}
-        <a class="button" href='{crmURL p="civicrm/payment" q="action=add&reset=1&component=`$component`&id=`$id`&cid=`$contact_id`"}'><i class="crm-i fa-plus-circle"></i> {ts}{$paymentButtonName}{/ts}</a>
+        <a class="button" href='{crmURL p="civicrm/payment" q="action=add&reset=1&component=`$component`&id=`$id`&cid=`$contact_id`"}'><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}{$paymentButtonName}{/ts}</a>
       {/if}
     {/if}
     {if (call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviContribute') && call_user_func(array('CRM_Core_Permission', 'check'), "delete contributions of type $financial_type") && $canDelete)     || (call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviContribute') && $noACL)}
@@ -29,7 +29,7 @@
         {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&key=$searchKey"}
       {/if}
       <a class="button" href="{crmURL p='civicrm/contact/view/contribution' q=$urlParams}"><span>
-          <i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span>
+          <i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span>
       </a>
     {/if}
     {include file="CRM/common/formButtons.tpl" location="top"}
@@ -38,14 +38,14 @@
     {if $invoicing}
       <div class="css_right">
         <a class="button no-popup" href="{crmURL p='civicrm/contribute/invoice' q=$pdfUrlParams}">
-          <i class="crm-i fa-print"></i>
+          <i class="crm-i fa-print" aria-hidden="true"></i>
         {if $contribution_status != 'Refunded' && $contribution_status != 'Cancelled' }
           {ts}Print Invoice{/ts}</a>
         {else}
           {ts}Print Invoice and Credit Note{/ts}</a>
         {/if}
         <a class="button" href="{crmURL p='civicrm/contribute/invoice/email' q=$emailUrlParams}">
-          <i class="crm-i fa-paper-plane"></i>
+          <i class="crm-i fa-paper-plane" aria-hidden="true"></i>
           {ts}Email Invoice{/ts}</a>
       </div>
     {/if}
@@ -341,9 +341,9 @@
     {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
       {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=update&context=$context&key=$searchKey"}
     {/if}
-    <a class="button" href="{crmURL p='civicrm/contact/view/contribution' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+    <a class="button" href="{crmURL p='civicrm/contact/view/contribution' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
     {if $paymentButtonName}
-      <a class="button" href='{crmURL p="civicrm/payment" q="action=add&reset=1&component=`$component`&id=`$id`&cid=`$contact_id`"}'><i class="crm-i fa-plus-circle"></i> {ts}{$paymentButtonName}{/ts}</a>
+      <a class="button" href='{crmURL p="civicrm/payment" q="action=add&reset=1&component=`$component`&id=`$id`&cid=`$contact_id`"}'><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}{$paymentButtonName}{/ts}</a>
     {/if}
   {/if}
   {if (call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviContribute') && call_user_func(array('CRM_Core_Permission', 'check'), "delete contributions of type $financial_type") && $canDelete)     || (call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviContribute') && $noACL)}
@@ -351,7 +351,7 @@
     {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
       {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&key=$searchKey"}
     {/if}
-    <a class="button" href="{crmURL p='civicrm/contact/view/contribution' q=$urlParams}"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+    <a class="button" href="{crmURL p='civicrm/contact/view/contribution' q=$urlParams}"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
   {/if}
   {include file="CRM/common/formButtons.tpl" location="bottom"}
 </div>
diff --git a/civicrm/templates/CRM/Contribute/Form/PCP/PCPAccount.tpl b/civicrm/templates/CRM/Contribute/Form/PCP/PCPAccount.tpl
index 310a064a56..9914571235 100644
--- a/civicrm/templates/CRM/Contribute/Form/PCP/PCPAccount.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/PCP/PCPAccount.tpl
@@ -16,7 +16,7 @@
 
 {if $profileDisplay}
 <div class="messages status no-popup">
-  <i class="crm-i fa-exclamation-triangle"></i>
+  <i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i>
   <strong>{ts}Profile is not configured with Email address.{/ts}</strong>
 </div>
 {else}
diff --git a/civicrm/templates/CRM/Contribute/Form/PaymentInfoBlock.tpl b/civicrm/templates/CRM/Contribute/Form/PaymentInfoBlock.tpl
index afcc8c3c60..bcb23f9a56 100644
--- a/civicrm/templates/CRM/Contribute/Form/PaymentInfoBlock.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/PaymentInfoBlock.tpl
@@ -41,7 +41,7 @@
 {/if}
 
   {foreach from=$paymentLinks item=paymentLink}
-    <a class="open-inline action-item crm-hover-button" href="{$paymentLink.url}">&raquo; {ts}{$paymentLink.title}{/ts}</a>
+    <a class="open-inline action-item crm-hover-button" href="{$paymentLink.url}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}{$paymentLink.title}{/ts}</a>
   {/foreach}
 
 {/crmRegion}
diff --git a/civicrm/templates/CRM/Contribute/Form/Search/Common.tpl b/civicrm/templates/CRM/Contribute/Form/Search/Common.tpl
index c5594dcabd..657fb77251 100644
--- a/civicrm/templates/CRM/Contribute/Form/Search/Common.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/Search/Common.tpl
@@ -157,6 +157,9 @@
     {$form.cancel_reason.html}
   </td>
 </tr>
+<tr>
+  <td><label>{$form.contribution_id.label}</label> {$form.contribution_id.html}</td>
+</tr>
 
 {* campaign in contribution search *}
 {include file="CRM/Campaign/Form/addCampaignToComponent.tpl" campaignContext="componentSearch"
diff --git a/civicrm/templates/CRM/Contribute/Form/SoftCredit.tpl b/civicrm/templates/CRM/Contribute/Form/SoftCredit.tpl
index 817ad26bc0..824ed7c0e5 100644
--- a/civicrm/templates/CRM/Contribute/Form/SoftCredit.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/SoftCredit.tpl
@@ -28,7 +28,7 @@
   {/section}
   <tr>
     <td>
-      <a href="#" class="crm-hover-button" id="addMoreSoftCredit"><i class="crm-i fa-plus-circle"></i> {ts}another soft credit{/ts}</a>
+      <a href="#" class="crm-hover-button" id="addMoreSoftCredit"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}another soft credit{/ts}</a>
     </td>
   </tr>
 </table>
diff --git a/civicrm/templates/CRM/Contribute/Form/Task/Batch.tpl b/civicrm/templates/CRM/Contribute/Form/Task/Batch.tpl
index 2a5c48cb2c..23effd2f50 100644
--- a/civicrm/templates/CRM/Contribute/Form/Task/Batch.tpl
+++ b/civicrm/templates/CRM/Contribute/Form/Task/Batch.tpl
@@ -20,7 +20,7 @@
             {/foreach}
 
              {foreach from=$fields item=field key=fieldName}
-                <td><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</td>
+                <td>{copyIcon name=$field.name title=$field.title}{$field.title}</td>
              {/foreach}
             </tr>
           </thead>
diff --git a/civicrm/templates/CRM/Contribute/Page/ContributionPage.tpl b/civicrm/templates/CRM/Contribute/Page/ContributionPage.tpl
index 39ab184744..a4665f8026 100644
--- a/civicrm/templates/CRM/Contribute/Page/ContributionPage.tpl
+++ b/civicrm/templates/CRM/Contribute/Page/ContributionPage.tpl
@@ -16,7 +16,7 @@
     {if NOT ($action eq 1 or $action eq 2) }
       <table class="form-layout-compressed">
       <tr>
-      <td><a href="{$newPageURL}" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Contribution Page{/ts}</span></a></td>
+      <td><a href="{$newPageURL}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Contribution Page{/ts}</span></a></td>
             <td style="vertical-align: top"><a class="button" href="{crmURL p="civicrm/admin/pcp" q="reset=1"}"><span>{ts}Manage Personal Campaign Pages{/ts}</span></a> {help id="id-pcp-intro" file="CRM/PCP/Page/PCP.hlp"}</td>
       </tr>
       </table>
diff --git a/civicrm/templates/CRM/Contribute/Page/ContributionRecur.tpl b/civicrm/templates/CRM/Contribute/Page/ContributionRecur.tpl
index f57c33199b..1c8b4dca28 100644
--- a/civicrm/templates/CRM/Contribute/Page/ContributionRecur.tpl
+++ b/civicrm/templates/CRM/Contribute/Page/ContributionRecur.tpl
@@ -8,80 +8,73 @@
  +--------------------------------------------------------------------+
 *}
 
-{include file="CRM/common/enableDisableApi.tpl"}
+{if $recur}
+  {if $recur.is_test}
+    <div class="help">
+      <strong>{ts}This is a TEST transaction{/ts}</strong>
+    </div>
+  {/if}
+  <div class="crm-block crm-content-block crm-recurcontrib-view-block">
+    <table class="crm-info-panel">
+      <tr>
+        <td class="label">{ts}From{/ts}</td>
+        <td class="bold"><a href="{crmURL p='civicrm/contact/view' q="cid=`$recur.contact_id`"}">{$displayName}</a></td>
+      </tr>
+      <tr><td class="label">{ts}Amount{/ts}</td><td>{$recur.amount|crmMoney:$recur.currency}{if $is_test} ({ts}test{/ts}){/if}</td></tr>
+      <tr><td class="label">{ts}Frequency{/ts}</td><td>every {$recur.frequency_interval} {$recur.frequency_unit}</td></tr>
+      <tr><td class="label">{ts}Installments{/ts}</td><td>{$recur.installments}</td></tr>
+      <tr><td class="label">{ts}Status{/ts}</td><td>{$recur.contribution_status}</td></tr>
+      <tr><td class="label">{ts}Start Date{/ts}</td><td>{$recur.start_date|crmDate}</td></tr>
+      <tr><td class="label">{ts}Created Date{/ts}</td><td>{$recur.create_date|crmDate}</td></tr>
+      {if $recur.modified_date}<tr><td class="label">{ts}Modified Date{/ts}</td><td>{$recur.modified_date|crmDate}</td></tr>{/if}
+      {if $recur.cancel_date}<tr><td class="label">{ts}Cancelled Date{/ts}</td><td>{$recur.cancel_date|crmDate}</td></tr>{/if}
+      {if $recur.cancel_reason}<tr><td class="label">{ts}Cancel Reason{/ts}</td><td>{$recur.cancel_reason}</td></tr>{/if}
+      {if $recur.end_date}<tr><td class="label">{ts}End Date{/ts}</td><td>{$recur.end_date|crmDate}</td></tr>{/if}
+      {if $recur.processor_id}<tr><td class="label">{ts}Processor ID{/ts}</td><td>{$recur.processor_id}</td></tr>{/if}
+      <tr><td class="label">{ts}Transaction ID{/ts}</td><td>{$recur.trxn_id}</td></tr>
+      {if $recur.invoice_id}<tr><td class="label">{ts}Invoice ID{/ts}</td><td>{$recur.invoice_id}</td></tr>{/if}
+      <tr><td class="label">{ts}Cycle Day{/ts}</td><td>{$recur.cycle_day}</td></tr>
+      {if $recur.contribution_status_id neq 3}<tr><td class="label">{ts}Next Contribution{/ts}</td><td>{$recur.next_sched_contribution_date|crmDate}</td></tr>{/if}
+      <tr><td class="label">{ts}Failure Count{/ts}</td><td>{$recur.failure_count}</td></tr>
+      {if $recur.invoice_id}<tr><td class="label">{ts}Failure Retry Date{/ts}</td><td>{$recur.next_sched_contribution_date|crmDate}</td></tr>{/if}
+      <tr><td class="label">{ts}Auto Renew?{/ts}</td><td>{if $recur.auto_renew}{ts}Yes{/ts}{else}{ts}No{/ts}{/if}</td></tr>
+      <tr><td class="label">{ts}Send receipt for each contribution?{/ts}</td><td>{if $recur.is_email_receipt}{ts}Yes{/ts}{else}{ts}No{/ts}{/if}</td></tr>
+      {if $recur.payment_processor}<tr><td class="label">{ts}Payment Processor{/ts}</td><td>{$recur.payment_processor}</td></tr>{/if}
+      {if $recur.financial_type}<tr><td class="label">{ts}Financial Type{/ts}</td><td>{$recur.financial_type}</td></tr>{/if}
+      {if $recur.campaign}<tr><td class="label">{ts}Campaign{/ts}</td><td>{$recur.campaign}</td></tr>{/if}
+      {if $recur.membership_id}<tr>
+        <td class="label">{ts}Membership{/ts}</td>
+        <td><a class="crm-hover-button action-item" href='{crmURL p="civicrm/contact/view/membership" q="action=view&reset=1&cid=`$contactId`&id=`$recur.membership_id`&context=membership&selectedChild=member"}'>{$recur.membership_name}</a></td>
+        </tr>
+      {/if}
+      {include file="CRM/Custom/Page/CustomDataView.tpl"}
 
-{if $action eq 4} {* when action is view *}
-    {if $recur}
-        {if $recur.is_test}
-        <div class="help">
-          <strong>{ts}This is a TEST transaction{/ts}</strong>
-        </div>
-        {/if}
-        <div class="crm-block crm-content-block crm-recurcontrib-view-block">
-          <table class="crm-info-panel">
-            <tr>
-              <td class="label">{ts}From{/ts}</td>
-              <td class="bold"><a href="{crmURL p='civicrm/contact/view' q="cid=`$recur.contact_id`"}">{$displayName}</a></td>
-            </tr>
-            <tr><td class="label">{ts}Amount{/ts}</td><td>{$recur.amount|crmMoney:$recur.currency}{if $is_test} ({ts}test{/ts}){/if}</td></tr>
-            <tr><td class="label">{ts}Frequency{/ts}</td><td>every {$recur.frequency_interval} {$recur.frequency_unit}</td></tr>
-            <tr><td class="label">{ts}Installments{/ts}</td><td>{$recur.installments}</td></tr>
-            <tr><td class="label">{ts}Status{/ts}</td><td>{$recur.contribution_status}</td></tr>
-            <tr><td class="label">{ts}Start Date{/ts}</td><td>{$recur.start_date|crmDate}</td></tr>
-            <tr><td class="label">{ts}Created Date{/ts}</td><td>{$recur.create_date|crmDate}</td></tr>
-            {if $recur.modified_date}<tr><td class="label">{ts}Modified Date{/ts}</td><td>{$recur.modified_date|crmDate}</td></tr>{/if}
-            {if $recur.cancel_date}<tr><td class="label">{ts}Cancelled Date{/ts}</td><td>{$recur.cancel_date|crmDate}</td></tr>{/if}
-            {if $recur.cancel_reason}<tr><td class="label">{ts}Cancel Reason{/ts}</td><td>{$recur.cancel_reason}</td></tr>{/if}
-            {if $recur.end_date}<tr><td class="label">{ts}End Date{/ts}</td><td>{$recur.end_date|crmDate}</td></tr>{/if}
-            {if $recur.processor_id}<tr><td class="label">{ts}Processor ID{/ts}</td><td>{$recur.processor_id}</td></tr>{/if}
-            <tr><td class="label">{ts}Transaction ID{/ts}</td><td>{$recur.trxn_id}</td></tr>
-            {if $recur.invoice_id}<tr><td class="label">{ts}Invoice ID{/ts}</td><td>{$recur.invoice_id}</td></tr>{/if}
-            <tr><td class="label">{ts}Cycle Day{/ts}</td><td>{$recur.cycle_day}</td></tr>
-            {if $recur.contribution_status_id neq 3}<tr><td class="label">{ts}Next Contribution{/ts}</td><td>{$recur.next_sched_contribution_date|crmDate}</td></tr>{/if}
-            <tr><td class="label">{ts}Failure Count{/ts}</td><td>{$recur.failure_count}</td></tr>
-            {if $recur.invoice_id}<tr><td class="label">{ts}Failure Retry Date{/ts}</td><td>{$recur.next_sched_contribution_date|crmDate}</td></tr>{/if}
-            <tr><td class="label">{ts}Auto Renew?{/ts}</td><td>{if $recur.auto_renew}{ts}Yes{/ts}{else}{ts}No{/ts}{/if}</td></tr>
-            <tr><td class="label">{ts}Send receipt for each contribution?{/ts}</td><td>{if $recur.is_email_receipt}{ts}Yes{/ts}{else}{ts}No{/ts}{/if}</td></tr>
-            {if $recur.payment_processor}<tr><td class="label">{ts}Payment Processor{/ts}</td><td>{$recur.payment_processor}</td></tr>{/if}
-            {if $recur.financial_type}<tr><td class="label">{ts}Financial Type{/ts}</td><td>{$recur.financial_type}</td></tr>{/if}
-            {if $recur.campaign}<tr><td class="label">{ts}Campaign{/ts}</td><td>{$recur.campaign}</td></tr>{/if}
-            {if $recur.membership_id}<tr>
-              <td class="label">{ts}Membership{/ts}</td>
-              <td><a class="crm-hover-button action-item" href='{crmURL p="civicrm/contact/view/membership" q="action=view&reset=1&cid=`$contactId`&id=`$recur.membership_id`&context=membership&selectedChild=member"}'>{$recur.membership_name}</a></td>
-              </tr>
-            {/if}
-            {include file="CRM/Custom/Page/CustomDataView.tpl"}
-
-          </table>
-          <div class="crm-submit-buttons"><a class="button cancel crm-form-submit" href="{crmURL p='civicrm/contact/view' q='action=browse&selectedChild=contribute'}">{ts}Done{/ts}</a></div>
-        </div>
-    {/if}
-
-  <script type="text/javascript">
-    var recurContribID = {$recur.id};
-    var contactID = {$contactId};
-    {literal}
-    CRM.$(function($) {
-      CRM.loadPage(
-        CRM.url(
-          'civicrm/contribute/contributionrecur-payments',
-          {
-            reset: 1,
-            id: recurContribID,
-            cid: contactID
-          },
-          'back'
-        ),
-        {
-          target : '#recurring-contribution-payments',
-          dialog : false
-        }
-      );
-    });
-    {/literal}
-  </script>
-  <div id="recurring-contribution-payments"></div>
-{/if}
-{if $recurRows}
-  {include file="CRM/Contribute/Page/ContributionRecurSelector.tpl"}
+    </table>
+    <div class="crm-submit-buttons"><a class="button cancel crm-form-submit" href="{crmURL p='civicrm/contact/view' q='action=browse&selectedChild=contribute'}">{ts}Done{/ts}</a></div>
+  </div>
 {/if}
+
+<script type="text/javascript">
+  var recurContribID = {$recur.id};
+  var contactID = {$contactId};
+  {literal}
+  CRM.$(function($) {
+    CRM.loadPage(
+            CRM.url(
+                    'civicrm/contribute/contributionrecur-payments',
+                    {
+                      reset: 1,
+                      id: recurContribID,
+                      cid: contactID
+                    },
+                    'back'
+            ),
+            {
+              target : '#recurring-contribution-payments',
+              dialog : false
+            }
+    );
+  });
+  {/literal}
+</script>
+<div id="recurring-contribution-payments"></div>
diff --git a/civicrm/templates/CRM/Contribute/Page/DashBoard.tpl b/civicrm/templates/CRM/Contribute/Page/DashBoard.tpl
index aed10c2c55..5dfc47df28 100644
--- a/civicrm/templates/CRM/Contribute/Page/DashBoard.tpl
+++ b/civicrm/templates/CRM/Contribute/Page/DashBoard.tpl
@@ -55,7 +55,7 @@
       <a href="{$configPagesURL}" class="button no-popup"><span>{ts}Manage Contribution Pages{/ts}</span></a>
     </td>
     <td>
-      <a href="{$newPageURL}" class="button no-popup"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Contribution Page{/ts}</span></a>
+      <a href="{$newPageURL}" class="button no-popup"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Contribution Page{/ts}</span></a>
     </td>
   </tr>
 </table>
diff --git a/civicrm/templates/CRM/Contribute/Page/Premium.tpl b/civicrm/templates/CRM/Contribute/Page/Premium.tpl
index a226f68833..3737acf5ae 100644
--- a/civicrm/templates/CRM/Contribute/Page/Premium.tpl
+++ b/civicrm/templates/CRM/Contribute/Page/Premium.tpl
@@ -43,7 +43,7 @@
     </div>
     {if $products}
       <div class="action-link">
-        <a href="{crmURL p='civicrm/admin/contribute/addProductToPage' q="reset=1&action=update&id=$id"}">&raquo; {ts}Offer Another Premium on this Contribution Page{/ts}</a>
+        <a href="{crmURL p='civicrm/admin/contribute/addProductToPage' q="reset=1&action=update&id=$id"}"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Offer Another Premium on this Contribution Page{/ts}</a>
       </div>
     {/if}
 </div>
diff --git a/civicrm/templates/CRM/Contribute/Page/Tab.tpl b/civicrm/templates/CRM/Contribute/Page/Tab.tpl
index f154d5d1bf..8e17896d60 100644
--- a/civicrm/templates/CRM/Contribute/Page/Tab.tpl
+++ b/civicrm/templates/CRM/Contribute/Page/Tab.tpl
@@ -48,9 +48,9 @@
 
           {if $action eq 16 and $permission EQ 'edit'}
             <div class="action-link">
-              <a accesskey="N" href="{$newContribURL}" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Record Contribution (Check, Cash, EFT ...){/ts}</span></a>
+              <a accesskey="N" href="{$newContribURL}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Record Contribution (Check, Cash, EFT ...){/ts}</span></a>
               {if $newCredit}
-                <a accesskey="N" href="{$newCreditURL}" class="button"><span><i class="crm-i fa-credit-card"></i> {ts}Submit Credit Card Contribution{/ts}</span></a>
+                <a accesskey="N" href="{$newCreditURL}" class="button"><span><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}Submit Credit Card Contribution{/ts}</span></a>
               {/if}
               <br /><br />
             </div>
@@ -79,11 +79,11 @@
           {if $recur}
             <div class="crm-block crm-contact-contribute-recur crm-contact-contribute-recur-active">
               <h3>{ts}Active Recurring Contributions{/ts}</h3>
-              {include file="CRM/Contribute/Page/ContributionRecur.tpl" recurRows=$activeRecurRows}
+              {include file="CRM/Contribute/Page/ContributionRecurSelector.tpl" recurRows=$activeRecurRows}
             </div>
             <div class="crm-block crm-contact-contribute-recur crm-contact-contribute-recur-inactive">
               <h3>{ts}Inactive Recurring Contributions{/ts}</h3>
-              {include file="CRM/Contribute/Page/ContributionRecur.tpl" recurRows=$inactiveRecurRows}
+              {include file="CRM/Contribute/Page/ContributionRecurSelector.tpl" recurRows=$inactiveRecurRows}
             </div>
           {/if}
         </div>
diff --git a/civicrm/templates/CRM/Contribute/Page/UserDashboard.tpl b/civicrm/templates/CRM/Contribute/Page/UserDashboard.tpl
index eb95300e2b..29ae828479 100644
--- a/civicrm/templates/CRM/Contribute/Page/UserDashboard.tpl
+++ b/civicrm/templates/CRM/Contribute/Page/UserDashboard.tpl
@@ -49,7 +49,7 @@
                             {if call_user_func(array('CRM_Core_Permission','check'), 'view my invoices') OR call_user_func(array('CRM_Core_Permission','check'), 'access CiviContribute')}
                                 <a class="button no-popup nowrap"
                                    href="{crmURL p='civicrm/contribute/invoice' q=$urlParams}">
-                                    <i class="crm-i fa-print"></i>
+                                    <i class="crm-i fa-print" aria-hidden="true"></i>
                                     {if $row.contribution_status_name != 'Refunded' && $row.contribution_status_name != 'Cancelled' }
                                         <span>{ts}Print Invoice{/ts}</span>
                                     {else}
diff --git a/civicrm/templates/CRM/Core/Form/Task/Batch.tpl b/civicrm/templates/CRM/Core/Form/Task/Batch.tpl
index 5be7cbb1ab..ed23171394 100644
--- a/civicrm/templates/CRM/Core/Form/Task/Batch.tpl
+++ b/civicrm/templates/CRM/Core/Form/Task/Batch.tpl
@@ -22,7 +22,7 @@
            {/foreach}
 
               {foreach from=$fields item=field key=fieldName}
-                <td><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</td>
+                <td>{copyIcon name=$field.name title=$field.title}{$field.title}</td>
              {/foreach}
             </tr>
           </thead>
diff --git a/civicrm/templates/CRM/Core/I18n/Dialog.tpl b/civicrm/templates/CRM/Core/I18n/Dialog.tpl
index 429952a664..a63991513d 100644
--- a/civicrm/templates/CRM/Core/I18n/Dialog.tpl
+++ b/civicrm/templates/CRM/Core/I18n/Dialog.tpl
@@ -9,6 +9,6 @@
 *}
 {if $config->languageLimit && $config->languageLimit|@count >= 2 and $translatePermission }
   <a href="{crmURL p='civicrm/i18n' q="reset=1&table=$table&field=$field&id=$id"}" data-field="{$field}" class="crm-hover-button crm-multilingual-edit-button" title="{ts}Languages{/ts}">
-    <i class="crm-i fa-language fa-lg"></i>
+    <i class="crm-i fa-language fa-lg" aria-hidden="true"></i>
   </a>
 {/if}
diff --git a/civicrm/templates/CRM/Core/Page/RecurringEntityPreview.tpl b/civicrm/templates/CRM/Core/Page/RecurringEntityPreview.tpl
index ec36313d52..9b83796ba9 100644
--- a/civicrm/templates/CRM/Core/Page/RecurringEntityPreview.tpl
+++ b/civicrm/templates/CRM/Core/Page/RecurringEntityPreview.tpl
@@ -9,7 +9,7 @@
 *}
 {if !empty($participantData)}
   <div class="messages status no-popup">
-    <i class="crm-i fa-exclamation-triangle"></i>
+    <i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i>
     {ts}There are participants registered for repeating events being removed from the set. Those with participants will be converted to standalone events, and those without registration will be deleted.{/ts}
   </div>
   <table class="display">
diff --git a/civicrm/templates/CRM/Custom/Form/Edit/CustomData.tpl b/civicrm/templates/CRM/Custom/Form/Edit/CustomData.tpl
index 4af5020783..8228791b3c 100644
--- a/civicrm/templates/CRM/Custom/Form/Edit/CustomData.tpl
+++ b/civicrm/templates/CRM/Custom/Form/Edit/CustomData.tpl
@@ -34,7 +34,7 @@
   {else}
     <div id="add-more-link-{$cgCount}" class="add-more-link-{$group_id} add-more-link-{$group_id}-{$cgCount}">
       <a href="#" class="crm-hover-button" onclick="CRM.buildCustomData('{$cd_edit.extends}',{if $cd_edit.subtype}'{$cd_edit.subtype}'{else}'{$cd_edit.extends_entity_column_id}'{/if}, '', {$cgCount}, {$group_id}, true ); return false;">
-        <i class="crm-i fa-plus-circle"></i>
+        <i class="crm-i fa-plus-circle" aria-hidden="true"></i>
         {ts 1=$cd_edit.title}Another %1 record{/ts}
       </a>
     </div>
diff --git a/civicrm/templates/CRM/Custom/Form/Field.tpl b/civicrm/templates/CRM/Custom/Form/Field.tpl
index 040dc348cb..f6be9fb9c3 100644
--- a/civicrm/templates/CRM/Custom/Form/Field.tpl
+++ b/civicrm/templates/CRM/Custom/Form/Field.tpl
@@ -27,13 +27,17 @@
         {if $action eq 2 and $changeFieldType}
           <br />
           <a class="action-item crm-hover-button" href='{crmURL p="civicrm/admin/custom/group/field/changetype" q="reset=1&id=`$id`"}'>
-            <i class="crm-i fa-wrench"></i>
+            <i class="crm-i fa-wrench" aria-hidden="true"></i>
             {ts}Change Input Field Type{/ts}
           </a>
           <div class='clear'></div>
         {/if}
       </td>
     </tr>
+    <tr class="crm-custom-field-form-block-serialize">
+      <td class="label">{$form.serialize.label}</td>
+      <td class="html-adjust">{$form.serialize.html}</td>
+    </tr>
     {if $form.in_selector}
       <tr class='crm-custom-field-form-block-in_selector'>
         <td class='label'>{$form.in_selector.label}</td>
@@ -59,7 +63,7 @@
         {$form.group_id.html}
         &nbsp;&nbsp;<span><a class="crm-hover-button toggle-contact-ref-mode" href="#Advance">{ts}Advanced Filter{/ts}</a></span>
         {capture assign=searchPreferences}{crmURL p="civicrm/admin/setting/search" q="reset=1"}{/capture}
-        <div class="messages status no-popup"><i class="crm-i fa-exclamation-triangle"></i> {ts 1=$searchPreferences}If you are planning on using this field in front-end profile, event registration or contribution forms, you should 'Limit List to Group' or configure an 'Advanced Filter'  (so that you do not unintentionally expose your entire set of contacts). Users must have either 'access contact reference fields' OR 'access CiviCRM' permission in order to use contact reference autocomplete fields. You can assign 'access contact reference fields' to the anonymous role if you want un-authenticated visitors to use this field. Use <a href='%1'>Search Preferences - Contact Reference Options</a> to control the fields included in the search results.{/ts}
+        <div class="messages status no-popup"><i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i> {ts 1=$searchPreferences}If you are planning on using this field in front-end profile, event registration or contribution forms, you should 'Limit List to Group' or configure an 'Advanced Filter'  (so that you do not unintentionally expose your entire set of contacts). Users must have either 'access contact reference fields' OR 'access CiviCRM' permission in order to use contact reference autocomplete fields. You can assign 'access contact reference fields' to the anonymous role if you want un-authenticated visitors to use this field. Use <a href='%1'>Search Preferences - Contact Reference Options</a> to control the fields included in the search results.{/ts}
       </td>
     </tr>
     <tr id='field_advance_filter'>
@@ -262,6 +266,8 @@
       $("#textLength", $form).toggle(dataType === 'String');
 
       $("#noteColumns, #noteRows, #noteLength", $form).toggle(dataType === 'Memo');
+
+      $(".crm-custom-field-form-block-serialize", $form).toggle(htmlType === 'Select' || htmlType === 'Country' || htmlType === 'StateProvince');
     }
 
     $('[name^="data_type"]', $form).change(customOptionHtmlType);
diff --git a/civicrm/templates/CRM/Custom/Form/Optionfields.tpl b/civicrm/templates/CRM/Custom/Form/Optionfields.tpl
index c4cf3c8b31..0b14545951 100644
--- a/civicrm/templates/CRM/Custom/Form/Optionfields.tpl
+++ b/civicrm/templates/CRM/Custom/Form/Optionfields.tpl
@@ -42,7 +42,7 @@
   <tr id="optionField_{$index}" class="form-item {cycle values="odd-row,even-row"}">
         <td>
         {if $index GT 1}
-            <a onclick="showHideRow({$index}); return false;" name="optionField_{$index}" href="#" class="form-link"><i class="crm-i fa-trash" title="{ts}hide field or section{/ts}"></i></a>
+            <a onclick="showHideRow({$index}); return false;" name="optionField_{$index}" href="#" class="form-link"><i class="crm-i fa-trash" title="{ts}hide field or section{/ts}" aria-hidden="true"></i></a>
         {/if}
         </td>
       <td>
@@ -61,7 +61,7 @@
     {/section}
     </table>
   <div id="optionFieldLink" class="add-remove-link">
-        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus-circle"></i> {ts}add another choice{/ts}</a>
+        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}add another choice{/ts}</a>
     </div>
   <span id="additionalOption" class="description">
     {ts}If you need additional options - you can add them after you Save your current entries.{/ts}
diff --git a/civicrm/templates/CRM/Custom/Page/CustomDataView.tpl b/civicrm/templates/CRM/Custom/Page/CustomDataView.tpl
index 3cddab39b4..fafb2fd82d 100644
--- a/civicrm/templates/CRM/Custom/Page/CustomDataView.tpl
+++ b/civicrm/templates/CRM/Custom/Page/CustomDataView.tpl
@@ -24,7 +24,7 @@
           <td>
             <a
               href="{crmURL p="civicrm/contact/view/cd/edit" q="tableId=`$contactId`&cid=`$contactId`&groupID=`$groupId`&action=update&reset=1"}"
-              class="button" style="margin-left: 6px;"><span><i class="crm-i fa-pencil"></i> {ts 1=$cd_edit.title}Edit %1{/ts}</span></a><br/><br/>
+              class="button" style="margin-left: 6px;"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts 1=$cd_edit.title}Edit %1{/ts}</span></a><br/><br/>
           </td>
         </tr>
       {/if}
@@ -43,7 +43,7 @@
                   <a href="#" class="crm-hover-button crm-custom-value-del"
                      data-post='{ldelim}"valueID": "{$cvID}", "groupID": "{$customGroupId}", "contactId": "{$contactId}", "key": "{crmKey name='civicrm/ajax/customvalue'}"{rdelim}'
                      title="{ts 1=$cd_edit.title|cat:" `$rowCount`"}Delete %1{/ts}">
-                    <i class="crm-i fa-trash"></i> {ts}Delete{/ts}
+                    <i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}
                   </a>
                 </div>
               {/if}
diff --git a/civicrm/templates/CRM/Custom/Page/Option.tpl b/civicrm/templates/CRM/Custom/Page/Option.tpl
index f47cafc27e..41b49ac784 100644
--- a/civicrm/templates/CRM/Custom/Page/Option.tpl
+++ b/civicrm/templates/CRM/Custom/Page/Option.tpl
@@ -54,8 +54,8 @@
               "aoColumns"  : [
                               {sClass:'crm-custom_option-label'},
                               {sClass:'crm-custom_option-value'},
+                              {sClass:'crm-custom_option-description'},
                               {sClass:'crm-custom_option-default_value'},
-                              {sClass:'crm-custom_option-default_description'},
                               {sClass:'crm-custom_option-is_active'},
                               {sClass:'crm-custom_option-links'},
                               {sClass:'hiddenElement'}
@@ -87,7 +87,7 @@
                 $(nRow).addClass(cl).attr({id: 'OptionValue-' + id});
                 $('td:eq(0)', nRow).wrapInner('<span class="crm-editable crmf-label" />');
                 $('td:eq(0)', nRow).prepend('<span class="crm-i fa-arrows crm-grip" />');
-                $('td:eq(2)', nRow).addClass('crmf-default_value');
+                $('td:eq(3)', nRow).addClass('crmf-default_value').html(CRM.utils.formatIcon('fa-check', ts('Default'), nRow.cells[3].innerText));
                 return nRow;
               },
               "fnDrawCallback": function() {
diff --git a/civicrm/templates/CRM/Dashlet/Page/Blog.tpl b/civicrm/templates/CRM/Dashlet/Page/Blog.tpl
index df8e45a04d..16d33ff2de 100644
--- a/civicrm/templates/CRM/Dashlet/Page/Blog.tpl
+++ b/civicrm/templates/CRM/Dashlet/Page/Blog.tpl
@@ -52,7 +52,7 @@
         </div>
         <div class="crm-accordion-body">
           <div>{$article.description}</div>
-          <p class="crm-news-feed-item-link"><a target="_blank" href="{$article.link}" title="{$article.title|escape}"><i class="crm-i fa-external-link"></i> {ts}read more{/ts}…</a></p>
+          <p class="crm-news-feed-item-link"><a target="_blank" href="{$article.link}" title="{$article.title|escape}"><i class="crm-i fa-external-link" aria-hidden="true"></i> {ts}read more{/ts}…</a></p>
         </div>
       </div>
     {/foreach}
diff --git a/civicrm/templates/CRM/Dashlet/Page/CaseDashboard.tpl b/civicrm/templates/CRM/Dashlet/Page/CaseDashboard.tpl
index 14a1250015..36811b2db9 100644
--- a/civicrm/templates/CRM/Dashlet/Page/CaseDashboard.tpl
+++ b/civicrm/templates/CRM/Dashlet/Page/CaseDashboard.tpl
@@ -18,7 +18,7 @@
     <tr>
       <td>
         <a href="{$newCaseURL}" class="button">
-          <span><i class="crm-i fa-plus-circle"></i> {ts}New Case{/ts}</span>
+          <span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}New Case{/ts}</span>
         </a>
       </td>
     </tr>
@@ -26,19 +26,19 @@
    {if $myCases}
     <tr>
       <td class="right">
-        <a href="{crmURL p="civicrm/case" q="reset=1&all=1"}"><span>&raquo; {ts}Show ALL Cases with Upcoming Activities{/ts}</span></a>
+        <a href="{crmURL p="civicrm/case" q="reset=1&all=1"}"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Show ALL Cases with Upcoming Activities{/ts}</span></a>
       </td>
     </tr>
    {else}
     <tr>
       <td class="right">
-        <a href="{crmURL p="civicrm/case" q="reset=1&all=0"}"><span>&raquo; {ts}Show My Cases with Upcoming Activities{/ts}</span></a>
+        <a href="{crmURL p="civicrm/case" q="reset=1&all=0"}"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Show My Cases with Upcoming Activities{/ts}</span></a>
       </td>
     </tr>
    {/if}
    <tr>
      <td class="right">
-       <a href="{crmURL p="civicrm/case/search" q="reset=1&case_owner=1&force=1"}"><span>&raquo; {ts}Show My Cases{/ts}</span></a>
+       <a href="{crmURL p="civicrm/case/search" q="reset=1&case_owner=1&force=1"}"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Show My Cases{/ts}</span></a>
      </td>
    </tr>
   </table>
diff --git a/civicrm/templates/CRM/Event/Cart/Page/ViewCart.tpl b/civicrm/templates/CRM/Event/Cart/Page/ViewCart.tpl
index 2e84d4965e..0cfd2c1db4 100644
--- a/civicrm/templates/CRM/Event/Cart/Page/ViewCart.tpl
+++ b/civicrm/templates/CRM/Event/Cart/Page/ViewCart.tpl
@@ -30,7 +30,7 @@
       {/foreach}
       </tbody>
     </table>
-    <a href="{crmURL p='civicrm/event/cart_checkout'}" class="button crm-check-out-button"><i class="crm-i fa-credit-card"></i> {ts}Checkout{/ts}</a>
+    <a href="{crmURL p='civicrm/event/cart_checkout'}" class="button crm-check-out-button"><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}Checkout{/ts}</a>
   </div>
 {/if}
-<a href="{crmURL p="civicrm/event/ical" q="reset=1&page=1&html=1"}">&laquo; Back to Event List</a>
+<a href="{crmURL p="civicrm/event/ical" q="reset=1&page=1&html=1"}"><i class="crm-i fa-chevron-left" aria-hidden="true"></i> Back to Event List</a>
diff --git a/civicrm/templates/CRM/Event/Form/EventFees.tpl b/civicrm/templates/CRM/Event/Form/EventFees.tpl
index a786cb2310..355e821caa 100644
--- a/civicrm/templates/CRM/Event/Form/EventFees.tpl
+++ b/civicrm/templates/CRM/Event/Form/EventFees.tpl
@@ -32,7 +32,7 @@
           <tr>
             <td></td>
             <td>
-              <a class="action-item crm-hover-button" href='{crmURL p="civicrm/event/participant/feeselection" q="reset=1&id=`$participantId`&cid=`$contactId`&action=update"}'><i class="crm-i fa-pencil"></i> {ts}Change Selections{/ts}</a>
+              <a class="action-item crm-hover-button" href='{crmURL p="civicrm/event/participant/feeselection" q="reset=1&id=`$participantId`&cid=`$contactId`&action=update"}'><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Change Selections{/ts}</a>
             </td>
          </tr>
       {else} {* New participant *}
diff --git a/civicrm/templates/CRM/Event/Form/ManageEvent/ConfirmRepeatMode.tpl b/civicrm/templates/CRM/Event/Form/ManageEvent/ConfirmRepeatMode.tpl
index 5038b97660..8d48983cc5 100644
--- a/civicrm/templates/CRM/Event/Form/ManageEvent/ConfirmRepeatMode.tpl
+++ b/civicrm/templates/CRM/Event/Form/ManageEvent/ConfirmRepeatMode.tpl
@@ -25,7 +25,7 @@
         <label for="recur-all-entity">{ts 1=$entity_type}Every %1{/ts}</label>
         <div class="description">{ts 1=$entity_type}Change applies to every %1 in the series.{/ts}</div>
       </div>
-      <div class="status help"><i class="crm-i fa-info-circle"></i> {ts}Changes to date or time will <em>not</em> be applied to others in the series.{/ts}</div>
+      <div class="status help"><i class="crm-i fa-info-circle" aria-hidden="true"></i> {ts}Changes to date or time will <em>not</em> be applied to others in the series.{/ts}</div>
     </div>
   </script>
 {literal}
diff --git a/civicrm/templates/CRM/Event/Form/ManageEvent/EventInfo.tpl b/civicrm/templates/CRM/Event/Form/ManageEvent/EventInfo.tpl
index ca6cfbc87b..8e1b0645c1 100644
--- a/civicrm/templates/CRM/Event/Form/ManageEvent/EventInfo.tpl
+++ b/civicrm/templates/CRM/Event/Form/ManageEvent/EventInfo.tpl
@@ -74,7 +74,7 @@
       <td>
         {$form.max_participants.html|crmAddClass:four}
         {if call_user_func(array('CRM_Core_Permission','check'), 'administer CiviCRM') }
-          <a class="crm-popup crm-hover-button" target="_blank" title="{ts}Edit Participant Status Options{/ts}" href="{crmURL p='civicrm/admin/participant_status' q='reset=1'}"><i class="crm-i fa-wrench"></i></a>
+          <a class="crm-popup crm-hover-button" target="_blank" title="{ts}Edit Participant Status Options{/ts}" href="{crmURL p='civicrm/admin/participant_status' q='reset=1'}"><i class="crm-i fa-wrench" aria-hidden="true"></i></a>
         {/if}
       </td>
     </tr>
diff --git a/civicrm/templates/CRM/Event/Form/ManageEvent/Fee.tpl b/civicrm/templates/CRM/Event/Form/ManageEvent/Fee.tpl
index 2e93012d01..e397febb8c 100644
--- a/civicrm/templates/CRM/Event/Form/ManageEvent/Fee.tpl
+++ b/civicrm/templates/CRM/Event/Form/ManageEvent/Fee.tpl
@@ -174,7 +174,7 @@
   {section name=rowLoop start=1 loop=6}
      {assign var=index value=$smarty.section.rowLoop.index}
      <tr id="discount_{$index}" class=" crm-event-manage-fee-form-block-discount_{$index} {if $index GT 1 AND empty( $form.discount_name[$index].value) } hiddenElement {/if} form-item {cycle values="odd-row,even-row"}">
-           <td>{if $index GT 1} <a onclick="showHideDiscountRow('discount_{$index}', false, {$index}); return false;" name="discount_{$index}" href="#" class="form-link"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}hide field or section{/ts}"/></a>{/if}
+           <td>{if $index GT 1} <a onclick="showHideDiscountRow('discount_{$index}', false, {$index}); return false;" name="discount_{$index}" href="#" class="form-link">{icon icon="fa-trash"}{ts}remove discount set{/ts}{/icon}</span></a>{/if}
            </td>
            <td class="crm-event-manage-fee-form-block-discount_name"> {$form.discount_name.$index.html}</td>
            <td class="crm-event-manage-fee-form-block-discount_start_date"> {$form.discount_start_date.$index.html} </td>
@@ -183,7 +183,7 @@
     {/section}
     </table>
         <div id="discountLink" class="add-remove-link">
-           <a onclick="showHideDiscountRow( 'discount', true);return false;" id="discountLink" href="#" class="form-link"><img src="{$config->resourceBase}i/TreePlus.gif" class="action-icon" alt="{ts}show field or section{/ts}"/>{ts}another discount set{/ts}</a>
+           <a onclick="showHideDiscountRow( 'discount', true);return false;" id="discountLink" href="#" class="form-link"><i class="crm-i fa-plus action-icon" aria-hidden="true"></i> {ts}another discount set{/ts}</a>
         </div>
         {$form._qf_Fee_submit.html}
 
diff --git a/civicrm/templates/CRM/Event/Form/ManageEvent/Registration.tpl b/civicrm/templates/CRM/Event/Form/ManageEvent/Registration.tpl
index 7c60d0a5a0..4858e98032 100644
--- a/civicrm/templates/CRM/Event/Form/ManageEvent/Registration.tpl
+++ b/civicrm/templates/CRM/Event/Form/ManageEvent/Registration.tpl
@@ -12,8 +12,8 @@
       width="20%">{if $addProfileBottomAdd }{$form.additional_custom_post_id_multiple[$profileBottomNumAdd].label}
     {else}{$form.custom_post_id_multiple[$profileBottomNum].label}{/if}</td>
   <td>{if $addProfileBottomAdd }{$form.additional_custom_post_id_multiple[$profileBottomNumAdd].html}{else}{$form.custom_post_id_multiple[$profileBottomNum].html}{/if}
-    <span class='profile_bottom_link_remove'><a href="#" class="crm-hover-button crm-button-rem-profile" data-addtlPartc="{$addProfileBottomAdd}"><i class="crm-i fa-trash"></i> {ts}remove profile{/ts}</a></span>
-    <span class='profile_bottom_link'>&nbsp;<a href="#" class="crm-hover-button crm-button-add-profile"><i class="crm-i fa-plus-circle"></i> {ts}add another profile (bottom of page){/ts}</a></span>
+    <span class='profile_bottom_link_remove'><a href="#" class="crm-hover-button crm-button-rem-profile" data-addtlPartc="{$addProfileBottomAdd}"><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}remove profile{/ts}</a></span>
+    <span class='profile_bottom_link'>&nbsp;<a href="#" class="crm-hover-button crm-button-add-profile"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}add another profile (bottom of page){/ts}</a></span>
     {if $addProfileBottomAdd }
       <div
         class="description">{ts}Change this if you want to use a different profile for additional participants.{/ts}</div>
@@ -140,7 +140,7 @@
         <td scope="row" class="label" width="20%">{$form.custom_post_id.label}</td>
         <td>{$form.custom_post_id.html}
           <div class="description">{ts}Include additional fields on this registration form by selecting and configuring a CiviCRM Profile to be included at the bottom of the page.{/ts}</div>
-          <span class='profile_bottom_link_main {if $profilePostMultiple}hiddenElement{/if}'><a href="#" class="crm-hover-button crm-button-add-profile"><i class="crm-i fa-plus-circle"></i> {ts}add another profile (bottom of page){/ts}</a></span>
+          <span class='profile_bottom_link_main {if $profilePostMultiple}hiddenElement{/if}'><a href="#" class="crm-hover-button crm-button-add-profile"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}add another profile (bottom of page){/ts}</a></span>
           <br/>
         </td>
       </tr>
@@ -154,13 +154,13 @@
               &nbsp;
               <span class='profile_bottom_link_remove'>
                 <a href="#" class="crm-hover-button crm-button-rem-profile">
-                  <i class="crm-i fa-trash"></i> {ts}remove profile{/ts}
+                  <i class="crm-i fa-trash" aria-hidden="true"></i> {ts}remove profile{/ts}
                 </a>
               </span>
               &nbsp;&nbsp;
               <span class='profile_bottom_link' {if !$smarty.foreach.profilePostIdName.last} style="display: none"{/if}>
                 <a href="#" class="crm-hover-button crm-button-add-profile">
-                  <i class="crm-i fa-plus-circle"></i>
+                  <i class="crm-i fa-plus-circle" aria-hidden="true"></i>
                   {ts}add another profile (bottom of page){/ts}
                 </a>
               </span>
@@ -185,7 +185,7 @@
           <div
             class="description">{ts}Change this if you want to use a different profile for additional participants.{/ts}
           </div>
-          <span class='profile_bottom_add_link_main{if $profilePostMultipleAdd} hiddenElement{/if}'><a href="#" class="crm-hover-button crm-button-add-profile"><i class="crm-i fa-plus-circle"></i> {ts}add another profile (bottom of page){/ts}</a></span>
+          <span class='profile_bottom_add_link_main{if $profilePostMultipleAdd} hiddenElement{/if}'><a href="#" class="crm-hover-button crm-button-add-profile"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}add another profile (bottom of page){/ts}</a></span>
           <br/><span class="profile-links"></span>
         </td>
       </tr>
@@ -199,12 +199,12 @@
               &nbsp;
               <span class='profile_bottom_add_link_remove'>
                 <a href="#" class="crm-hover-button crm-button-rem-profile">
-                  <i class="crm-i fa-trash"></i> {ts}remove profile{/ts}
+                  <i class="crm-i fa-trash" aria-hidden="true"></i> {ts}remove profile{/ts}
                 </a>
               </span>
               <span class='profile_bottom_add_link' {if !$smarty.foreach.profilePostIdAName.last} style="display: none"{/if}>
                 <a href="#" class="crm-hover-button crm-button-add-profile">
-                  <i class="crm-i fa-plus-circle"></i>
+                  <i class="crm-i fa-plus-circle" aria-hidden="true"></i>
                   {ts}add another profile (bottom of page){/ts}
                 </a>
               </span>
diff --git a/civicrm/templates/CRM/Event/Form/ManageEvent/Tab.hlp b/civicrm/templates/CRM/Event/Form/ManageEvent/Tab.hlp
index b19e1ea1ab..026ceeeda1 100644
--- a/civicrm/templates/CRM/Event/Form/ManageEvent/Tab.hlp
+++ b/civicrm/templates/CRM/Event/Form/ManageEvent/Tab.hlp
@@ -11,56 +11,56 @@
   {ts}Event Configuration{/ts}
 {/htxt}
 {htxt id="id-configure-events"}
-<table> 
+<table>
 <tr>
-    <td><a href="{crmURL p='civicrm/event/manage/settings' q="reset=1&action=update&id=`$params.eventId`"}" id="idEventInformationandSettings">&raquo; {ts}Info &amp; Settings{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/event/manage/settings' q="reset=1&action=update&id=`$params.eventId`"}" id="idEventInformationandSettings"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Info &amp; Settings{/ts}</a></td>
     <td>{ts}Set event title, type (conference, performance etc.), description, start and end dates, maximum number of participants, and activate the event. Enable the public participant listing feature.{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/event/manage/location' q="reset=1&action=update&id=`$params.eventId`"}" id="idLocation">&raquo; {ts}Location{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/event/manage/location' q="reset=1&action=update&id=`$params.eventId`"}" id="idLocation"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Location{/ts}</a></td>
     <td>{ts}Set event location and event contact information (email and phone).{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/event/manage/fee' q="reset=1&action=update&id=`$params.eventId`"}" id="idFee">&raquo; {ts}Fees{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/event/manage/fee' q="reset=1&action=update&id=`$params.eventId`"}" id="idFee"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Fees{/ts}</a></td>
      <td>{ts}Determine if the event is free or paid. For paid events, set the payment processor, fee level(s) and discounts. Give online registrants the option to 'pay later' (e.g. mail in a check, call in a credit card, etc.).{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/event/manage/registration' q="reset=1&action=update&id=`$params.eventId`"}" id="idRegistration">&raquo; {ts}Online Registration{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/event/manage/registration' q="reset=1&action=update&id=`$params.eventId`"}" id="idRegistration"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Online Registration{/ts}</a></td>
     <td>{ts}Determine whether an online registration page is available. If so, configure registration, confirmation and thank you page elements and confirmation email details.{/ts}</td>
 </tr>
 <tr>
-    <td><a href="{crmURL p='civicrm/event/manage/friend' q="reset=1&action=update&id=`$params.eventId`"}" id="idFriend">&raquo; {ts}Tell a Friend{/ts}</a></td>
+    <td><a href="{crmURL p='civicrm/event/manage/friend' q="reset=1&action=update&id=`$params.eventId`"}" id="idFriend"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Tell a Friend{/ts}</a></td>
     <td>{ts}Make it easy for participants to spread the word about this event to friends and colleagues.{/ts}</td>
 </tr>
 
 {if !$params.isTemplate}
     <tr>
     {if $params.participantListingURL}
-        <td><a href="{$params.participantListingURL}" id="idParticipantListing">&raquo; {ts}Participant Listing{/ts}</a></td>
+        <td><a href="{$params.participantListingURL}" id="idParticipantListing"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Participant Listing{/ts}</a></td>
         {if $config->userSystem->is_drupal}
           <td>{ts 1=$params.participantListingURL}The following URL will display a list of registered participants for this event to users whose role includes "view event participants" permission: <a href="%1">%1</a>{/ts}</td>
         {else}
           <td>{ts 1=$params.participantListingURL}The following URL will display a list of registered participants for this event: <a href="%1">%1</a>{/ts}</td>
         {/if}
     {else}
-        <td>&raquo; {ts}Participant Listing{/ts}</td>
+        <td><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Participant Listing{/ts}</td>
         <td>{ts}Participant Listing is not enabled for this event. You can enable it from{/ts} <a href="{crmURL p='civicrm/event/manage/settings' q="reset=1&action=update&id=`$params.eventId`"}">{ts}Event Information and Settings{/ts}</a>.
     {/if}
     </tr>
 
     <tr>
-        <td><a href="{crmURL p='civicrm/event/info' q="reset=1&id=`$params.eventId`" fe=1}" id="idDisplayEvent">&raquo; {ts}Event Info{/ts}</a></td>
+        <td><a href="{crmURL p='civicrm/event/info' q="reset=1&id=`$params.eventId`" fe=1}" id="idDisplayEvent"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Event Info{/ts}</a></td>
         <td>{ts}View the Event Information page as it will be displayed to site visitors.{/ts}</td>
     </tr>
 
     {if $params.isOnlineRegistration}
     <tr>
-        <td><a href="{crmURL p='civicrm/event/register' q="reset=1&action=preview&id=`$params.eventId`" a=1 fe=1}" id="idTest-drive">&raquo; {ts}Registration{/ts}</a><br />({ts}test-drive{/ts})</td>
+        <td><a href="{crmURL p='civicrm/event/register' q="reset=1&action=preview&id=`$params.eventId`" a=1 fe=1}" id="idTest-drive"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Registration{/ts}</a><br />({ts}test-drive{/ts})</td>
         <td>{ts}Test-drive the entire online registration process - including custom fields, confirmation, thank-you page, and receipting. Fee payment transactions will be directed to your payment processor's test server. <strong>No live financial transactions will be submitted. However, a contact record will be created or updated and participant and contribution records will be saved to the database. Use obvious test contact names so you can review and delete these records as needed.</strong>{/ts}</td>
     </tr>
 
     <tr>
-        <td><a href="{crmURL a=1 fe=1 p='civicrm/event/register' q="reset=1&id=`$params.eventId`"}" id="idLive">&raquo; {ts}Registration{/ts}</a><br />({ts}live{/ts})</td>
+        <td><a href="{crmURL a=1 fe=1 p='civicrm/event/register' q="reset=1&id=`$params.eventId`"}" id="idLive"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Registration{/ts}</a><br />({ts}live{/ts})</td>
         <td>{ts}Review your customized <strong>LIVE</strong> online event registration page here. Use the following URL in links and buttons on any website to send visitors to this live page{/ts}:<br />
             <strong>{crmURL a=1 fe=1 p='civicrm/event/register' q="reset=1&id=`$params.eventId`"}</strong>
         </td>
diff --git a/civicrm/templates/CRM/Event/Form/Participant.tpl b/civicrm/templates/CRM/Event/Form/Participant.tpl
index 9cded07e8e..069ad4e287 100644
--- a/civicrm/templates/CRM/Event/Form/Participant.tpl
+++ b/civicrm/templates/CRM/Event/Form/Participant.tpl
@@ -106,7 +106,7 @@
           }
 
         if ( showError ) {
-          cj('#validate_pricefield').show().html('<i class="crm-i fa-exclamation-triangle crm-i-red"></i>{/literal} {ts escape='js'}This Option is already full for this event.{/ts}{literal}');
+          cj('#validate_pricefield').show().html('<i class="crm-i fa-exclamation-triangle crm-i-red" aria-hidden="true"></i>{/literal} {ts escape='js'}This Option is already full for this event.{/ts}{literal}');
         }
         else {
           cj('#validate_pricefield').hide( ).html('');
@@ -175,7 +175,7 @@
         {else}
           {capture assign=ccModeLink}{crmURL p='civicrm/contact/view/participant' q="reset=1&action=add&context=standalone&mode=live"}{/capture}
         {/if}
-        <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}">&raquo; {ts}submit credit card event registration{/ts}</a>
+        <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}"><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}submit credit card event registration{/ts}</a>
       </div>
     {/if}
     <div class="view-content">
diff --git a/civicrm/templates/CRM/Event/Form/ParticipantFeeSelection.tpl b/civicrm/templates/CRM/Event/Form/ParticipantFeeSelection.tpl
index 3aed291cf0..02246d54cb 100644
--- a/civicrm/templates/CRM/Event/Form/ParticipantFeeSelection.tpl
+++ b/civicrm/templates/CRM/Event/Form/ParticipantFeeSelection.tpl
@@ -87,7 +87,7 @@ CRM.$(function($) {
   <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
   {if !$email}
   <div class="messages status no-popup">
-    <i class="crm-i fa-info-circle"></i>&nbsp;{ts}You will not be able to send an automatic email receipt for this payment because there is no email address recorded for this contact. If you want a receipt to be sent when this payment is recorded, click Cancel and then click Edit from the Summary tab to add an email address before recording the payment.{/ts}
+    <i class="crm-i fa-info-circle" aria-hidden="true"></i>&nbsp;{ts}You will not be able to send an automatic email receipt for this payment because there is no email address recorded for this contact. If you want a receipt to be sent when this payment is recorded, click Cancel and then click Edit from the Summary tab to add an email address before recording the payment.{/ts}
   </div>
   {/if}
   <table class="form-layout">
@@ -123,7 +123,7 @@ CRM.$(function($) {
          <div class='label'>{ts}Total Paid{/ts}</div>
          <div class='content'>
            {$paymentInfo.paid|crmMoney}<br/>
-           <a class="crm-hover-button action-item crm-popup medium-popup" href='{crmURL p="civicrm/payment" q="view=transaction&action=browse&cid=`$contactId`&id=`$paymentInfo.id`&component=`$paymentInfo.component`&context=transaction"}'><i class="crm-i fa-list-alt"></i> {ts}view payments{/ts}</a>
+           <a class="crm-hover-button action-item crm-popup medium-popup" href='{crmURL p="civicrm/payment" q="view=transaction&action=browse&cid=`$contactId`&id=`$paymentInfo.id`&component=`$paymentInfo.component`&context=transaction"}'><i class="crm-i fa-list-alt" aria-hidden="true"></i> {ts}view payments{/ts}</a>
          </div>
          <div class='label'><strong>{ts}Balance Owed{/ts}</strong></div><div class='content'><strong id='balance-fee'></strong></div>
           </div>
diff --git a/civicrm/templates/CRM/Event/Form/ParticipantView.tpl b/civicrm/templates/CRM/Event/Form/ParticipantView.tpl
index 64d9e84363..0a49832e64 100644
--- a/civicrm/templates/CRM/Event/Form/ParticipantView.tpl
+++ b/civicrm/templates/CRM/Event/Form/ParticipantView.tpl
@@ -16,14 +16,14 @@
          {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
          {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=update&context=$context&selectedChild=event&key=$searchKey"}
          {/if}
-               <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+               <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
             {/if}
             {if call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviEvent')}
                 {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&selectedChild=event"}
           {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
           {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&selectedChild=event&key=$searchKey"}
           {/if}
-                <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+                <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
             {/if}
             {include file="CRM/common/formButtons.tpl" location="top"}
         </div>
@@ -34,7 +34,7 @@
       <td>
         <strong><a href="{crmURL p='civicrm/contact/view' q="reset=1&cid=$contact_id"}" title="{ts}View contact record{/ts}">{$displayName}</a></strong>
         <div>
-            <a class="action-item crm-hover-button" href="{crmURL p='civicrm/event/badge' q="reset=1&context=view&id=$id&cid=$contact_id"}"><i class="crm-i fa-print"></i> {ts}Print Name Badge{/ts}</a>
+            <a class="action-item crm-hover-button" href="{crmURL p='civicrm/event/badge' q="reset=1&context=view&id=$id&cid=$contact_id"}"><i class="crm-i fa-print" aria-hidden="true"></i> {ts}Print Name Badge{/ts}</a>
         </div>
       </td>
   </tr>
@@ -99,10 +99,10 @@
                 <td>{include file="CRM/Price/Page/LineItem.tpl" context="Event"}
                 {if call_user_func(array('CRM_Core_Permission','check'), 'edit event participants')}
                     {if $hasPayment or $parentHasPayment}
-                        <a class="action-item crm-hover-button" href='{crmURL p="civicrm/event/participant/feeselection" q="reset=1&id=`$participantId`&cid=`$contactId`&action=update"}'><i class="crm-i fa-pencil"></i> {ts}Change Selections{/ts}</a>
+                        <a class="action-item crm-hover-button" href='{crmURL p="civicrm/event/participant/feeselection" q="reset=1&id=`$participantId`&cid=`$contactId`&action=update"}'><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Change Selections{/ts}</a>
                     {/if}
                     {if $transferOrCancelLink}
-                      <a class="action-item crm-hover-button" href={$transferOrCancelLink}><i class="crm-i fa-times"></i> {ts}Transfer or Cancel{/ts}</a>
+                      <a class="action-item crm-hover-button" href={$transferOrCancelLink}><i class="crm-i fa-times" aria-hidden="true"></i> {ts}Transfer or Cancel{/ts}</a>
                     {/if}
                 {/if}
                 </td>
@@ -132,14 +132,14 @@
     {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=update&context=$context&selectedChild=event&key=$searchKey"}
     {/if}
 
-           <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+           <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
         {/if}
         {if call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviEvent')}
     {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&selectedChild=event"}
     {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
     {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&selectedChild=event&key=$searchKey"}
     {/if}
-            <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+            <a class="button" href="{crmURL p='civicrm/contact/view/participant' q=$urlParams}"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
         {/if}
         {include file="CRM/common/formButtons.tpl" location="bottom"}
     </div>
diff --git a/civicrm/templates/CRM/Event/Form/Registration/PreviewHeader.tpl b/civicrm/templates/CRM/Event/Form/Registration/PreviewHeader.tpl
index 8ede044020..395974c33d 100644
--- a/civicrm/templates/CRM/Event/Form/Registration/PreviewHeader.tpl
+++ b/civicrm/templates/CRM/Event/Form/Registration/PreviewHeader.tpl
@@ -9,7 +9,7 @@
 *}
 {* Displays Test-drive mode header for Event Registration pages. *}
 <div class="messages status section test_drive-section">
-  <i class="crm-i fa-cogs"></i>
+  <i class="crm-i fa-cogs" aria-hidden="true"></i>
      <strong>{ts}Test-drive Your Event Registration Page{/ts}</strong>
          {ts}This page is currently running in <strong>test-drive mode</strong>. If this is a paid event, transactions will be sent to your payment processor's test server. <strong>No live financial transactions will be submitted. However, a contact record will be created or updated and test event registration and contribution records will be saved to the database. Use obvious test contact names so you can review and delete these records as needed. </strong> Refer to your payment processor's documentation for information on values to use for test credit card number, security code, postal code, etc.{/ts}
 </div>
diff --git a/civicrm/templates/CRM/Event/Form/Registration/ThankYou.tpl b/civicrm/templates/CRM/Event/Form/Registration/ThankYou.tpl
index 7d43c8ac19..0929bc97c9 100644
--- a/civicrm/templates/CRM/Event/Form/Registration/ThankYou.tpl
+++ b/civicrm/templates/CRM/Event/Form/Registration/ThankYou.tpl
@@ -26,14 +26,14 @@
     {* Show link to Tell a Friend (CRM-2153) *}
     {if $friendText}
         <div id="tell-a-friend" class="crm-section tell_friend_link-section">
-            <a href="{$friendURL}" title="{$friendText|escape:'html'}" class="button"><span>&raquo; {$friendText}</span></a>
+            <a href="{$friendURL}" title="{$friendText|escape:'html'}" class="button"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {$friendText}</span></a>
        </div><br /><br />
     {/if}
 
     {* Add button for donor to create their own Personal Campaign page *}
     {if $pcpLink}
       <div class="crm-section create_pcp_link-section">
-            <a href="{$pcpLink}" title="{$pcpLinkText|escape:'html'}" class="button"><span>&raquo; {$pcpLinkText}</span></a>
+            <a href="{$pcpLink}" title="{$pcpLinkText|escape:'html'}" class="button"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {$pcpLinkText}</span></a>
         </div><br /><br />
     {/if}
 
@@ -195,11 +195,13 @@
     {/if}
 
     <div class="action-link section event_info_link-section">
-        <a href="{crmURL p='civicrm/event/info' q="reset=1&id=`$event.id`"}">&raquo; {ts 1=$event.event_title}Back to "%1" event information{/ts}</a>
+        <a href="{crmURL p='civicrm/event/info' q="reset=1&id=`$event.id`"}"><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {ts 1=$event.event_title}Back to "%1" event information{/ts}</a>
     </div>
 
     {if $event.is_public }
+      <div class="action-link section iCal_links-section">
         {include file="CRM/Event/Page/iCalLinks.tpl"}
+      </div>
     {/if}
     {if $event.is_share}
     {capture assign=eventUrl}{crmURL p='civicrm/event/info' q="id=`$event.id`&amp;reset=1" a=1 fe=1 h=1}{/capture}
diff --git a/civicrm/templates/CRM/Event/Form/Selector.tpl b/civicrm/templates/CRM/Event/Form/Selector.tpl
index 919fddb155..e0cdefac6e 100644
--- a/civicrm/templates/CRM/Event/Form/Selector.tpl
+++ b/civicrm/templates/CRM/Event/Form/Selector.tpl
@@ -73,11 +73,11 @@
 {if $limit and $pager->_totalItems GT $limit }
   {if $context EQ 'event_dashboard' }
     <tr class="even-row">
-    <td colspan="10"><a href="{crmURL p='civicrm/event/search' q='reset=1'}">&raquo; {ts}Find more event participants{/ts}...</a></td></tr>
+    <td colspan="10"><a href="{crmURL p='civicrm/event/search' q='reset=1'}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Find more event participants{/ts}...</a></td></tr>
     </tr>
   {elseif $context eq 'participant' }
     <tr class="even-row">
-    <td colspan="7"><a href="{crmURL p='civicrm/contact/view' q="reset=1&force=1&selectedChild=participant&cid=$contactId"}">&raquo; {ts}View all events for this contact{/ts}...</a></td></tr>
+    <td colspan="7"><a href="{crmURL p='civicrm/contact/view' q="reset=1&force=1&selectedChild=participant&cid=$contactId"}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}View all events for this contact{/ts}...</a></td></tr>
     </tr>
   {/if}
 {/if}
diff --git a/civicrm/templates/CRM/Event/Form/Task/Batch.tpl b/civicrm/templates/CRM/Event/Form/Task/Batch.tpl
index eef2066924..895ec862e6 100644
--- a/civicrm/templates/CRM/Event/Form/Task/Batch.tpl
+++ b/civicrm/templates/CRM/Event/Form/Task/Batch.tpl
@@ -42,7 +42,7 @@
 
              <td>{ts}Event{/ts}</td>
              {foreach from=$fields item=field key=fieldName}
-                <td><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</td>
+                <td>{copyIcon name=$field.name title=$field.title}{$field.title}</td>
              {/foreach}
 
          </tr>
diff --git a/civicrm/templates/CRM/Event/Page/DashBoard.tpl b/civicrm/templates/CRM/Event/Page/DashBoard.tpl
index 74fb0ecd03..b5db9cad5e 100644
--- a/civicrm/templates/CRM/Event/Page/DashBoard.tpl
+++ b/civicrm/templates/CRM/Event/Page/DashBoard.tpl
@@ -10,21 +10,15 @@
 {* CiviEvent DashBoard (launch page) *}
 {capture assign=newEventURL}{crmURL p="civicrm/event/add" q="action=add&reset=1"}{/capture}
 {capture assign=configPagesURL}{crmURL p="civicrm/event/manage" q="reset=1"}{/capture}
-{capture assign=icalFile}{crmURL p='civicrm/event/ical' q="reset=1" fe=1 a=1}{/capture}
-{capture assign=icalFeed}{crmURL p='civicrm/event/ical' q="reset=1&list=1" fe=1 a=1}{/capture}
-{capture assign=rssFeed}{crmURL p='civicrm/event/ical' q="reset=1&list=1&rss=1" fe=1 a=1}{/capture}
-{capture assign=htmlFeed}{crmURL p='civicrm/event/ical' q="reset=1&list=1&html=1" fe=1 a=1}{/capture}
 
 {if $eventSummary.total_events}
-    <a href="{$configPagesURL}" class="button no-popup"><span><i class="crm-i fa-th-list"></i> {ts}Manage Events{/ts}</span></a>
-    <a href="{$newEventURL}" class="button"><span><i class="crm-i fa-calendar-plus-o"></i> {ts}New Event{/ts}</span></a>
+    <a href="{$configPagesURL}" class="button no-popup"><span><i class="crm-i fa-th-list" aria-hidden="true"></i> {ts}Manage Events{/ts}</span></a>
+    <a href="{$newEventURL}" class="button"><span><i class="crm-i fa-calendar-plus-o" aria-hidden="true"></i> {ts}New Event{/ts}</span></a>
     <div class="clear">&nbsp;</div>
     <h3 id="crm-event-dashboard-heading">{ts}Event Summary{/ts}
       {help id="id-event-intro"}
-      <a href="{$htmlFeed}"  target="_blank" title="{ts}HTML listing of current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-calendar"></i></a>
-      <a href="{$rssFeed}"  target="_blank" title="{ts}Get RSS 2.0 feed for current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-rss"></i></a>
-      <a href="{$icalFile}" title="{ts}Download iCalendar file for current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-download"></i></a>
-      <a href="{$icalFeed}"  target="_blank" title="{ts}Get iCalendar feed for current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-calendar-o"></i></a></h3>
+      {include file="CRM/Event/Page/iCalLinks.tpl"}
+    </h3>
     {include file="CRM/common/jsortable.tpl"}
     <table id="options" class="display">
     <thead>
@@ -93,7 +87,7 @@
       {if $actionColumn}
         <td class="crm-event-isMap">
           {if $values.isMap}
-            <a href="{$values.isMap}" title="{ts}Map event location{/ts}">&raquo;&nbsp;{ts}Map{/ts}</a>
+            <a href="{$values.isMap}" title="{ts}Map event location{/ts}"><i class="crm-i fa-map-marker" aria-hidden="true"></i>&nbsp;{ts}Map{/ts}</a>
             &nbsp;|&nbsp;
           {/if}
           {if $values.configure}
@@ -124,7 +118,7 @@
     </tbody>
     </table>
     {if $eventSummary.total_events GT 10}
-     <div><a href="{crmURL p='civicrm/admin/event' q='reset=1'}">&raquo; {ts}Browse more events{/ts}...</a></div>
+     <div><a href="{crmURL p='civicrm/admin/event' q='reset=1'}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Browse more events{/ts}...</a></div>
     {/if}
 {else}
     <br />
diff --git a/civicrm/templates/CRM/Event/Page/EventInfo.tpl b/civicrm/templates/CRM/Event/Page/EventInfo.tpl
index 530476eb8d..6bb4cc6d24 100644
--- a/civicrm/templates/CRM/Event/Page/EventInfo.tpl
+++ b/civicrm/templates/CRM/Event/Page/EventInfo.tpl
@@ -12,7 +12,7 @@
 {if $registerClosed }
 <div class="spacer"></div>
 <div class="messages status no-popup">
-  <i class="crm-i fa-info-circle"></i>
+  <i class="crm-i fa-info-circle" aria-hidden="true"></i>
      &nbsp;{ts}Registration is closed for this event{/ts}
   </div>
 {/if}
@@ -23,7 +23,7 @@
   <li>
     <div id="crm-event-links-wrapper">
       <span id="crm-event-configure-link" class="crm-hover-button">
-        <span title="{ts}Configure this event.{/ts}" class="crm-i fa-wrench"></span>
+        <span title="{ts}Configure this event.{/ts}" class="crm-i fa-wrench" aria-hidden="true"></span>
       </span>
       <div class="ac_results" id="crm-event-links-list" style="margin-left: -25px;">
         <div class="crm-event-links-list-inner">
@@ -47,7 +47,7 @@
   <li>
     <div id="crm-participant-wrapper">
       <span id="crm-participant-links" class="crm-hover-button">
-        <span title="{ts}Participant listing links.{/ts}" class="crm-i fa-search"></span>
+        <span title="{ts}Participant listing links.{/ts}" class="crm-i fa-search" aria-hidden="true"></span>
       </span>
       <div class="ac_results" id="crm-participant-list" style="margin-left: -25px;">
         <div class="crm-participant-list-inner">
@@ -217,7 +217,10 @@
       {/crmRegion}
     </div>
     {if $event.is_public }
-        <br />{include file="CRM/Event/Page/iCalLinks.tpl"}
+        <br />
+        <div class="action-link section iCal_links-section">
+          {include file="CRM/Event/Page/iCalLinks.tpl"}
+        </div>
     {/if}
 
     {if $event.is_share }
diff --git a/civicrm/templates/CRM/Event/Page/List.tpl b/civicrm/templates/CRM/Event/Page/List.tpl
index 94a2b12913..e5f5fa182f 100644
--- a/civicrm/templates/CRM/Event/Page/List.tpl
+++ b/civicrm/templates/CRM/Event/Page/List.tpl
@@ -11,8 +11,8 @@
 {include file="CRM/common/jsortable.tpl"}
 <div class="crm-section crm-event-list">
   {if $eventCartEnabled}
-    <a href="{crmURL p='civicrm/event/view_cart' }" class="button crm-shoppingcart-button"><i class="crm-i fa-shopping-cart"></i> {ts}View Cart{/ts}</a>
-    <a href="{crmURL p='civicrm/event/cart_checkout'}" class="button crm-check-out-button"><i class="crm-i fa-credit-card"></i> {ts}Checkout{/ts}</a>
+    <a href="{crmURL p='civicrm/event/view_cart' }" class="button crm-shoppingcart-button"><i class="crm-i fa-shopping-cart" aria-hidden="true"></i> {ts}View Cart{/ts}</a>
+    <a href="{crmURL p='civicrm/event/cart_checkout'}" class="button crm-check-out-button"><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}Checkout{/ts}</a>
   {/if}
 
   <table id="options" class="display">
diff --git a/civicrm/templates/CRM/Event/Page/ManageEvent.tpl b/civicrm/templates/CRM/Event/Page/ManageEvent.tpl
index 0f8812f83e..0f4a98d4aa 100644
--- a/civicrm/templates/CRM/Event/Page/ManageEvent.tpl
+++ b/civicrm/templates/CRM/Event/Page/ManageEvent.tpl
@@ -8,23 +8,15 @@
  +--------------------------------------------------------------------+
 *}
 {capture assign=newEventURL}{crmURL p='civicrm/event/add' q="action=add&reset=1"}{/capture}
-{capture assign=icalFile}{crmURL p='civicrm/event/ical' q="reset=1" fe=1}{/capture}
-{capture assign=icalFeed}{crmURL p='civicrm/event/ical' q="reset=1&list=1" fe=1}{/capture}
-{capture assign=rssFeed}{crmURL p='civicrm/event/ical' q="reset=1&list=1&rss=1" fe=1}{/capture}
-{capture assign=htmlFeed}{crmURL p='civicrm/event/ical' q="reset=1&list=1&html=1" fe=1}{/capture}
 
 <div class="crm-block crm-content-block">
 <div class="float-right">
-  <a href="{$htmlFeed}"  target="_blank" title="{ts}HTML listing of current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-calendar"></i></a>
-  <a href="{$rssFeed}"  target="_blank" title="{ts}Get RSS 2.0 feed for current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-rss"></i></a>
-  <a href="{$icalFile}" title="{ts}Download iCalendar file for current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-download"></i></a>
-  <a href="{$icalFeed}"  target="_blank" title="{ts}Get iCalendar feed for current and future public events.{/ts}" class="crm-event-feed-link"><i class="crm-i fa-lg fa-calendar-o"></i></a>
-  {help id='icalendar'}
+  {include file="CRM/Event/Page/iCalLinks.tpl"}
 </div>
 
 <div class="action-link">
   <a accesskey="N" href="{$newEventURL}" id="newManageEvent" class="button crm-popup">
-    <span><i class="crm-i fa-calendar-plus-o"></i> {ts}Add Event{/ts}</span>
+    <span><i class="crm-i fa-calendar-plus-o" aria-hidden="true"></i> {ts}Add Event{/ts}</span>
   </a>
   <div class="clear"></div>
 </div>
diff --git a/civicrm/templates/CRM/Event/Page/Tab.tpl b/civicrm/templates/CRM/Event/Page/Tab.tpl
index d1807ecb37..a85621d558 100644
--- a/civicrm/templates/CRM/Event/Page/Tab.tpl
+++ b/civicrm/templates/CRM/Event/Page/Tab.tpl
@@ -28,9 +28,9 @@
     </div>
     {if $action eq 16 and $permission EQ 'edit'}
        <div class="action-link">
-           <a accesskey="N" href="{$newEventURL}" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Event Registration{/ts}</span></a>
+           <a accesskey="N" href="{$newEventURL}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Event Registration{/ts}</span></a>
             {if $accessContribution and $newCredit}
-                <a accesskey="N" href="{$newCreditURL}" class="button"><span><i class="crm-i fa-credit-card"></i> {ts}Submit Credit Card Event Registration{/ts}</a></span>
+                <a accesskey="N" href="{$newCreditURL}" class="button"><span><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}Submit Credit Card Event Registration{/ts}</a></span>
             {/if}
             <br/ ><br/ >
        </div>
diff --git a/civicrm/templates/CRM/Event/Page/iCalLinks.tpl b/civicrm/templates/CRM/Event/Page/iCalLinks.tpl
index 610f98a91d..b122b06378 100644
--- a/civicrm/templates/CRM/Event/Page/iCalLinks.tpl
+++ b/civicrm/templates/CRM/Event/Page/iCalLinks.tpl
@@ -7,9 +7,10 @@
  | and copyright information, see https://civicrm.org/licensing       |
  +--------------------------------------------------------------------+
 *}
-{* Display icons / links for ical download and feed for EventInfo.tpl and ThankYou.tpl *}
-{capture assign=icalFile}{crmURL p='civicrm/event/ical' q="reset=1&id=`$event.id`" fe=1 a=1}{/capture}
-{capture assign=icalFeed}{crmURL p='civicrm/event/ical' q="reset=1&list=1&id=`$event.id`" fe=1 a=1}{/capture}
-<div class="action-link section iCal_links-section">
-    <a href="{$icalFile}" title="{ts}Download iCalendar entry for this event.{/ts}"><img src="{$config->resourceBase}i/office-calendar.png" alt="{ts}Download iCalendar entry for this event.{/ts}"></a>&nbsp;&nbsp;<a href="{$icalFeed}" title="{ts}iCalendar feed for this event.{/ts}"><img src="{$config->resourceBase}i/ical_feed.gif" alt="{ts}iCalendar feed for this event.{/ts}" style="margin-bottom: 4px;" /></a>
-</div>
+{* Display icons / links for ical download and feed for EventInfo.tpl, ThankYou.tpl, DashBoard.tpl, and ManageEvent.tpl *}
+  {foreach from=$iCal item="iCalItem"}
+  <a href="{$iCalItem.url}" title="{$iCalItem.text}"{if !$event} class="crm-event-feed-link"{/if}>
+    <span class="fa-stack" aria-hidden="true"><i class="crm-i fa-calendar-o fa-stack-2x"></i><i style="top: 15%;" class="crm-i {$iCalItem.icon} fa-stack-1x"></i></span>
+    <span class="sr-only">{$iCalItem.text}</span>
+  </a>
+  {/foreach}
diff --git a/civicrm/templates/CRM/Financial/Form/Search.tpl b/civicrm/templates/CRM/Financial/Form/Search.tpl
index 6839b0d0f1..3cc7b90473 100644
--- a/civicrm/templates/CRM/Financial/Form/Search.tpl
+++ b/civicrm/templates/CRM/Financial/Form/Search.tpl
@@ -11,7 +11,7 @@
 {* Financial search component. *}
 <div id="enableDisableStatusMsg" class="crm-container" style="display:none"></div>
 <div class="action-link">
-  <a accesskey="N" href="{crmURL p='civicrm/financial/batch' q="reset=1&action=add&context=$batchStatus"}" id="newBatch" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}New Accounting Batch{/ts}</span></a>
+  <a accesskey="N" href="{crmURL p='civicrm/financial/batch' q="reset=1&action=add&context=$batchStatus"}" id="newBatch" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}New Accounting Batch{/ts}</span></a>
 </div>
 <div class="crm-form-block crm-search-form-block">
   <div class="crm-accordion-wrapper crm-activity_search-accordion">
diff --git a/civicrm/templates/CRM/Financial/Page/FinancialAccount.tpl b/civicrm/templates/CRM/Financial/Page/FinancialAccount.tpl
index 264ab9ff45..711003614e 100644
--- a/civicrm/templates/CRM/Financial/Page/FinancialAccount.tpl
+++ b/civicrm/templates/CRM/Financial/Page/FinancialAccount.tpl
@@ -20,7 +20,7 @@
 <div class="crm-content-block crm-block">
   {if $action ne 1 and $action ne 2}
     <div class="action-link">
-      <a href="{crmURL q="action=add&reset=1"}" id="newFinancialAccount-top" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Financial Account{/ts}</span></a>
+      <a href="{crmURL q="action=add&reset=1"}" id="newFinancialAccount-top" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Financial Account{/ts}</span></a>
     </div>
   {/if}
 
@@ -52,7 +52,7 @@
           <td>{$row.financial_account_type_id}{if $row.account_type_code} ({$row.account_type_code}){/if}</td>
           <td>{if $row.is_deductible eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
           <td>{if $row.is_reserved eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
-          <td>{if $row.is_default eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" /> {/if}</td>
+          <td>{icon condition=$row.is_default}{ts}Default{/ts}{/icon}</td>
           <td id="row_{$row.id}_status">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
           <td>{$row.action|replace:'xx':$row.id}</td>
         </tr>
@@ -62,7 +62,7 @@
 
       {if $action ne 1 and $action ne 2}
         <div class="action-link">
-          <a href="{crmURL q="action=add&reset=1"}" id="newFinancialAccount-bottom" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Financial Account{/ts}</span></a>
+          <a href="{crmURL q="action=add&reset=1"}" id="newFinancialAccount-bottom" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Financial Account{/ts}</span></a>
         </div>
       {/if}
       </div>
diff --git a/civicrm/templates/CRM/Form/attachment.tpl b/civicrm/templates/CRM/Form/attachment.tpl
index bbe6bf8a23..687751331d 100644
--- a/civicrm/templates/CRM/Form/attachment.tpl
+++ b/civicrm/templates/CRM/Form/attachment.tpl
@@ -15,7 +15,7 @@
           {foreach from=$currentAttachmentInfo key=attKey item=attVal}
                 <div id="attachStatusMesg" class="status hiddenElement"></div>
                 <div id="attachFileRecord_{$attVal.fileID}">
-                  <strong><a href="{$attVal.url}"><i class="crm-i {$attVal.icon}"></i> {$attVal.cleanName}</a></strong>
+                  <strong><a href="{$attVal.url}"><i class="crm-i {$attVal.icon}" aria-hidden="true"></i> {$attVal.cleanName}</a></strong>
                   {if $attVal.description}&nbsp;-&nbsp;{$attVal.description}{/if}
                   {if !empty($attVal.tag)}
                     <br />
@@ -47,7 +47,7 @@
         {/if}
         <tr>
           <td class="label">{$form.attachFile_1.label}</td>
-          <td>{$form.attachFile_1.html}&nbsp;{$form.attachDesc_1.html}<a href="#" class="crm-hover-button crm-clear-attachment" style="visibility: hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a>
+          <td>{$form.attachFile_1.html}&nbsp;{$form.attachDesc_1.html}<a href="#" class="crm-hover-button crm-clear-attachment" style="visibility: hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
             <div class="description">{ts}Browse to the <strong>file</strong> you want to upload.{/ts}{if $maxAttachments GT 1} {ts 1=$maxAttachments}You can have a maximum of %1 attachment(s).{/ts}{/if} {ts 1=$config->maxFileSize}Each file must be less than %1M in size. You can also add a short description.{/ts}</div>
           </td>
         </tr>
@@ -68,7 +68,7 @@
             <tr class="attachment-fieldset solid-border-top"><td colspan="2"></td></tr>
             <tr>
                 <td class="label">{$form.attachFile_1.label}</td>
-                <td>{$form.$attachName.html}&nbsp;{$form.$attachDesc.html}<a href="#" class="crm-hover-button crm-clear-attachment" style="visibility: hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a></td>
+                <td>{$form.$attachName.html}&nbsp;{$form.$attachDesc.html}<a href="#" class="crm-hover-button crm-clear-attachment" style="visibility: hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a></td>
             </tr>
             <tr>
               <td class="label">{$form.$tagElement.label}</td>
diff --git a/civicrm/templates/CRM/Form/body.tpl b/civicrm/templates/CRM/Form/body.tpl
index 07193943f8..40162fb009 100644
--- a/civicrm/templates/CRM/Form/body.tpl
+++ b/civicrm/templates/CRM/Form/body.tpl
@@ -17,7 +17,7 @@
 
 {if ($snippet !== 'json') and !$suppressForm and count($form.errors) gt 0}
    <div class="messages crm-error">
-       <i class="crm-i fa-exclamation-triangle crm-i-red"></i>
+       <i class="crm-i fa-exclamation-triangle crm-i-red" aria-hidden="true"></i>
      {ts}Please correct the following errors in the form fields below:{/ts}
      <ul id="errorList">
      {foreach from=$form.errors key=errorName item=error}
diff --git a/civicrm/templates/CRM/Friend/Form.tpl b/civicrm/templates/CRM/Friend/Form.tpl
index 5781f1b06c..3adbc78260 100644
--- a/civicrm/templates/CRM/Friend/Form.tpl
+++ b/civicrm/templates/CRM/Friend/Form.tpl
@@ -16,7 +16,7 @@
     {* Add button for donor to create their own Personal Campaign page *}
     {if $linkText}
    <div class="crm-section create_pcp_link-section">
-        <a href="{$linkTextUrl}" title="{$linkText|escape}" class="button"><span>&raquo; {$linkText}</span></a>
+        <a href="{$linkTextUrl}" title="{$linkText|escape}" class="button"><span><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {$linkText}</span></a>
     </div><br /><br />
     {/if}
 
diff --git a/civicrm/templates/CRM/Grant/Form/GrantView.tpl b/civicrm/templates/CRM/Grant/Form/GrantView.tpl
index 97d1b9a64f..c30e777d4c 100644
--- a/civicrm/templates/CRM/Grant/Form/GrantView.tpl
+++ b/civicrm/templates/CRM/Grant/Form/GrantView.tpl
@@ -15,14 +15,14 @@
             {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
                 {assign var='urlParams' value="reset=1&id=$id&cid=$contactId&action=update&context=$context&key=$searchKey"}
             {/if}
-            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
         {/if}
         {if call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviGrant')}
           {assign var='urlParams' value="reset=1&id=$id&cid=$contactId&action=delete&context=$context"}
             {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
                 {assign var='urlParams' value="reset=1&id=$id&cid=$contactId&action=delete&context=$context&key=$searchKey"}
             {/if}
-            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
         {/if}
         {include file="CRM/common/formButtons.tpl" location="top"}
     </div>
@@ -52,14 +52,14 @@
           {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
               {assign var='urlParams' value="reset=1&id=$id&cid=$contactId&action=update&context=$context&key=$searchKey"}
           {/if}
-            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}" accesskey="e"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
         {/if}
         {if call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviGrant')}
         {assign var='urlParams' value="reset=1&id=$id&cid=$contactId&action=delete&context=$context"}
           {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
               {assign var='urlParams' value="reset=1&id=$id&cid=$contactId&action=delete&context=$context&key=$searchKey"}
           {/if}
-            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+            <a class="button" href="{crmURL p='civicrm/contact/view/grant' q=$urlParams}"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
         {/if}
         {include file="CRM/common/formButtons.tpl" location="bottom"}
     </div>
diff --git a/civicrm/templates/CRM/Grant/Form/Selector.tpl b/civicrm/templates/CRM/Grant/Form/Selector.tpl
index 4a163ccd13..d3a1311fbe 100644
--- a/civicrm/templates/CRM/Grant/Form/Selector.tpl
+++ b/civicrm/templates/CRM/Grant/Form/Selector.tpl
@@ -56,7 +56,7 @@
 
 {if ($context EQ 'dashboard') AND $pager->_totalItems GT $limit}
   <tr class="even-row">
-    <td colspan="9"><a href="{crmURL p='civicrm/grant/search' q='reset=1&force=1'}">&raquo; {ts}List more Grants{/ts}...</a></td></tr>
+    <td colspan="9"><a href="{crmURL p='civicrm/grant/search' q='reset=1&force=1'}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}List more Grants{/ts}...</a></td></tr>
   </tr>
 {/if}
 </table>
diff --git a/civicrm/templates/CRM/Grant/Page/Tab.tpl b/civicrm/templates/CRM/Grant/Page/Tab.tpl
index 1e517ba1f5..8ad0066174 100644
--- a/civicrm/templates/CRM/Grant/Page/Tab.tpl
+++ b/civicrm/templates/CRM/Grant/Page/Tab.tpl
@@ -27,7 +27,7 @@
     </div>
 {if $action eq 16 and $permission EQ 'edit'}
             <div class="action-link">
-            <a href="{$newGrantURL}" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Grant{/ts}</span></a><br/><br/>
+            <a href="{$newGrantURL}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Grant{/ts}</span></a><br/><br/>
             </div>
         {/if}
     {if $rows}
diff --git a/civicrm/templates/CRM/Group/Form/Edit.tpl b/civicrm/templates/CRM/Group/Form/Edit.tpl
index 2598bf54fc..42b82ac93e 100644
--- a/civicrm/templates/CRM/Group/Form/Edit.tpl
+++ b/civicrm/templates/CRM/Group/Form/Edit.tpl
@@ -82,15 +82,15 @@
   <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
   {if $action neq 1}
     <div class="action-link">
-      <a {$crmURL}>&raquo; {ts}Contacts in this Group{/ts}</a>
+      <a {$crmURL}><i class="crm-i fa-users" aria-hidden="true"></i> {ts}Contacts in this Group{/ts}</a>
       {if $group.saved_search_id}
         <br />
         {if $group.mapping_id}
-          <a class="no-popup" href="{crmURL p="civicrm/contact/search/builder" q="reset=1&ssID=`$group.saved_search_id`"}">&raquo; {ts}Edit Smart Group Criteria{/ts}</a>
+          <a class="no-popup" href="{crmURL p="civicrm/contact/search/builder" q="reset=1&ssID=`$group.saved_search_id`"}"><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit Smart Group Criteria{/ts}</a>
         {elseif $group.search_custom_id}
-          <a class="no-popup" href="{crmURL p="civicrm/contact/search/custom" q="reset=1&ssID=`$group.saved_search_id`"}">&raquo; {ts}Edit Smart Group Criteria{/ts}</a>
+          <a class="no-popup" href="{crmURL p="civicrm/contact/search/custom" q="reset=1&ssID=`$group.saved_search_id`"}"><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit Smart Group Criteria{/ts}</a>
         {else}
-          <a class="no-popup" href="{crmURL p="civicrm/contact/search/advanced" q="reset=1&ssID=`$group.saved_search_id`"}">&raquo; {ts}Edit Smart Group Criteria{/ts}</a>
+          <a class="no-popup" href="{crmURL p="civicrm/contact/search/advanced" q="reset=1&ssID=`$group.saved_search_id`"}"><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit Smart Group Criteria{/ts}</a>
         {/if}
 
       {/if}
diff --git a/civicrm/templates/CRM/Group/Page/Group.tpl b/civicrm/templates/CRM/Group/Page/Group.tpl
index c5eaf2861b..f36bfdc743 100644
--- a/civicrm/templates/CRM/Group/Page/Group.tpl
+++ b/civicrm/templates/CRM/Group/Page/Group.tpl
@@ -10,7 +10,7 @@
 {* Actions: 1=add, 2=edit, browse=16, delete=8 *}
 {if $action ne 1 and $action ne 2 and $action ne 8 and $groupPermission eq 1}
 <div class="crm-submit-buttons">
-    <a accesskey="N" href="{crmURL p='civicrm/group/add' q='reset=1'}" class="newGroup button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Group{/ts}</span></a><br/>
+    <a accesskey="N" href="{crmURL p='civicrm/group/add' q='reset=1'}" class="newGroup button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Group{/ts}</span></a><br/>
 </div>
 {/if} {* action ne add or edit *}
 <div class="crm-block crm-content-block">
@@ -31,7 +31,7 @@
 
 {if $action ne 1 and $action ne 2 and $action ne 8 and $groupPermission eq 1}
 <div class="crm-submit-buttons">
-        <a accesskey="N" href="{crmURL p='civicrm/group/add' q='reset=1'}" class="newGroup button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Group{/ts}</span></a><br/>
+        <a accesskey="N" href="{crmURL p='civicrm/group/add' q='reset=1'}" class="newGroup button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Group{/ts}</span></a><br/>
 </div>
 {/if} {* action ne add or edit *}
 </div>
diff --git a/civicrm/templates/CRM/Logging/ReportDetail.tpl b/civicrm/templates/CRM/Logging/ReportDetail.tpl
index dbe64961a7..63b3e7c1a0 100644
--- a/civicrm/templates/CRM/Logging/ReportDetail.tpl
+++ b/civicrm/templates/CRM/Logging/ReportDetail.tpl
@@ -32,8 +32,8 @@
   {/if}
   {if $layout neq 'overlay'}
   <div class="action-link">
-      <a href="{$backURL}"   class="button"><span><i class="crm-i fa-chevron-left"></i> {ts}Back to Logging Summary{/ts}</span></a>
-      <a href="{$revertURL}" class="button" onclick="return confirm('{$revertConfirm}');"><span><i class="crm-i fa-undo"></i> {ts}Revert These Changes{/ts}</span></a>
+      <a href="{$backURL}"   class="button"><span><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {ts}Back to Logging Summary{/ts}</span></a>
+      <a href="{$revertURL}" class="button" onclick="return confirm('{$revertConfirm}');"><span><i class="crm-i fa-undo" aria-hidden="true"></i> {ts}Revert These Changes{/ts}</span></a>
   </div>
   {/if}
 </div>
diff --git a/civicrm/templates/CRM/Mailing/Form/ForwardMailing.tpl b/civicrm/templates/CRM/Mailing/Form/ForwardMailing.tpl
index a899116428..e8e6205d8e 100644
--- a/civicrm/templates/CRM/Mailing/Form/ForwardMailing.tpl
+++ b/civicrm/templates/CRM/Mailing/Form/ForwardMailing.tpl
@@ -21,11 +21,11 @@
 
 </table>
 <div id="comment_show">
-    <a href="#" class="button" onclick="cj('#comment_show').hide(); cj('#comment').show(); document.getElementById('forward_comment').focus(); return false;"><span>&raquo; {ts}Add Comment{/ts}</span></a>
+    <a href="#" class="button" onclick="cj('#comment_show').hide(); cj('#comment').show(); document.getElementById('forward_comment').focus(); return false;"><span><i class="crm-i fa-plus" aria-hidden="true"></i> {ts}Add Comment{/ts}</span></a>
 </div><div class="spacer"></div>
 <div id="comment" style="display:none">
             <table class="form-layout">
-            <tr class="crm-mailing-forward-form-block-forward_comment"><td><a href="#" onclick="cj('#comment').hide(); cj('#comment_show').show(); return false;"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}close section{/ts}"/></a>
+            <tr class="crm-mailing-forward-form-block-forward_comment"><td><a href="#" onclick="cj('#comment').hide(); cj('#comment_show').show(); return false;">{icon icon="fa-caret-down action-icon"}{ts}close section{/ts}{/icon}</a>
                 <label>{$form.forward_comment.label}</label></td>
                 <td>{$form.forward_comment.html}<br /><br />
               &nbsp;{$form.html_comment.html}<br /></td>
@@ -35,4 +35,3 @@
 <br />
 <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
 </div>
-
diff --git a/civicrm/templates/CRM/Mailing/Page/Component.tpl b/civicrm/templates/CRM/Mailing/Page/Component.tpl
index 25ee1557b7..ee7b47880d 100644
--- a/civicrm/templates/CRM/Mailing/Page/Component.tpl
+++ b/civicrm/templates/CRM/Mailing/Page/Component.tpl
@@ -35,7 +35,7 @@
            <td>{$row.subject}</td>
            <td>{$row.body_html|escape}</td>
            <td>{$row.body_text|escape}</td>
-           <td>{if $row.is_default eq 1}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" />{/if}&nbsp;</td>
+           <td>{icon condition=$row.is_default}{ts}Default{/ts}{/icon}&nbsp;</td>
      <td id="row_{$row.id}_status">{if $row.is_active eq 1} {ts}Yes{/ts} {else} {ts}No{/ts} {/if}</td>
            <td>{$row.action|replace:'xx':$row.id}</td>
         </tr>
diff --git a/civicrm/templates/CRM/Mailing/Page/Event.tpl b/civicrm/templates/CRM/Mailing/Page/Event.tpl
index 101689a37e..7c66c8be0e 100644
--- a/civicrm/templates/CRM/Mailing/Page/Event.tpl
+++ b/civicrm/templates/CRM/Mailing/Page/Event.tpl
@@ -46,7 +46,7 @@
 {/if}
 
 <div class="action-link">
-  <a href="{$backUrl}">&raquo; {$backUrlTitle}</a>
+  <a href="{$backUrl}"><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {$backUrlTitle}</a>
 </div>
 
 {include file="CRM/common/pager.tpl" location="bottom"}
diff --git a/civicrm/templates/CRM/Mailing/Page/Report.tpl b/civicrm/templates/CRM/Mailing/Page/Report.tpl
index 3a9b37e59b..703fe253c1 100644
--- a/civicrm/templates/CRM/Mailing/Page/Report.tpl
+++ b/civicrm/templates/CRM/Mailing/Page/Report.tpl
@@ -158,7 +158,7 @@
   <td>
     {$report.mailing.body_text|mb_truncate:30|escape|nl2br}
     <br />
-    <strong><a class="crm-popup" href='{$textViewURL}'>&raquo; {ts}View complete message{/ts}</a></strong>
+    <strong><a class="crm-popup" href='{$textViewURL}'><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}View complete message{/ts}</a></strong>
   </td>
 </tr>
 {/if}
@@ -167,7 +167,7 @@
 <tr>
   <td class="label nowrap">{ts}HTML Message{/ts}</td>
   <td>
-    <a class="crm-popup" href='{$htmlViewURL}'>&raquo; {ts}View complete message{/ts}</a>
+    <a class="crm-popup" href='{$htmlViewURL}'><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}View complete message{/ts}</a>
   </td>
 </tr>
 {/if}
@@ -213,10 +213,5 @@
 {/strip}
 </fieldset>
 <div class="action-link">
-    <a href="{$backUrl}" >&raquo; {$backUrlTitle}</a>
+    <a href="{$backUrl}" ><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {$backUrlTitle}</a>
 </div>
-
-
-
-
-
diff --git a/civicrm/templates/CRM/Member/Form/Membership.tpl b/civicrm/templates/CRM/Member/Form/Membership.tpl
index ca9071bb70..36e5d8678f 100644
--- a/civicrm/templates/CRM/Member/Form/Membership.tpl
+++ b/civicrm/templates/CRM/Member/Form/Membership.tpl
@@ -59,7 +59,7 @@
       {else}
         {capture assign=ccModeLink}{crmURL p='civicrm/contact/view/membership' q="reset=1&action=add&context=standalone&mode=live"}{/capture}
       {/if}
-     <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}">&raquo; {ts}submit credit card membership{/ts}</a>
+     <a class="open-inline-noreturn action-item crm-hover-button" href="{$ccModeLink}"><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}submit credit card membership{/ts}</a>
     </div>
     {/if}
     <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
@@ -532,7 +532,7 @@
 
           alert = CRM.alert(
             // Mixing client-side variables with a translated string in smarty is awkward!
-            ts({/literal}'{ts escape='js' 1='%1' 2='%2' 3='%3' 4='%4'}This contact has an existing %1 membership at %2 with %3 status%4.{/ts}'{literal}, {1:memberorgs[selectedorg].membership_type, 2: org, 3: memberorgs[selectedorg].membership_status, 4: andEndDate})
+            ts({/literal}'{ts escape='js'}This contact has an existing %1 membership at %2 with %3 status%4.{/ts}'{literal}, {1:memberorgs[selectedorg].membership_type, 2: org, 3: memberorgs[selectedorg].membership_status, 4: andEndDate})
               + '<ul><li><a href="' + memberorgs[selectedorg].renewUrl + '">'
               + {/literal}'{ts escape='js'}Renew the existing membership instead{/ts}'
               + '</a></li><li><a href="' + memberorgs[selectedorg].membershipTab + '">'
diff --git a/civicrm/templates/CRM/Member/Form/MembershipView.tpl b/civicrm/templates/CRM/Member/Form/MembershipView.tpl
index 546c295236..f6b073d2ff 100644
--- a/civicrm/templates/CRM/Member/Form/MembershipView.tpl
+++ b/civicrm/templates/CRM/Member/Form/MembershipView.tpl
@@ -17,7 +17,7 @@
       {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
       {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=update&context=$context&key=$searchKey"}
       {/if}
-            <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" accesskey="e" id="crm-membership-edit-button-top"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+            <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" accesskey="e" id="crm-membership-edit-button-top"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
         {/if}
         {if ! ($owner_contact_id AND call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviMember'))
           && (call_user_func(array('CRM_Core_Permission', 'check'), "delete contributions of type $financialTypeId") || $noACL)}
@@ -25,7 +25,7 @@
       {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
       {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&key=$searchKey"}
       {/if}
-            <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" id="crm-membership-delete-button-top"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+            <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" id="crm-membership-delete-button-top"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
         {/if}
         {include file="CRM/common/formButtons.tpl" location="bottom"}
     </div>
@@ -119,7 +119,7 @@
           {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
             {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=update&context=$context&key=$searchKey"}
           {/if}
-          <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" accesskey="e" id="crm-membership-edit-button-bottom"><span><i class="crm-i fa-pencil"></i> {ts}Edit{/ts}</span></a>
+          <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" accesskey="e" id="crm-membership-edit-button-bottom"><span><i class="crm-i fa-pencil" aria-hidden="true"></i> {ts}Edit{/ts}</span></a>
         {/if}
         {if ! ($owner_contact_id AND call_user_func(array('CRM_Core_Permission','check'), 'delete in CiviMember'))
           && (call_user_func(array('CRM_Core_Permission', 'check'), "delete contributions of type $financialTypeId") || $noACL)}
@@ -127,7 +127,7 @@
           {if ( $context eq 'fulltext' || $context eq 'search' ) && $searchKey}
             {assign var='urlParams' value="reset=1&id=$id&cid=$contact_id&action=delete&context=$context&key=$searchKey"}
           {/if}
-          <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" id="crm-membership-delete-button-bottom"><span><i class="crm-i fa-trash"></i> {ts}Delete{/ts}</span></a>
+          <a class="button" href="{crmURL p='civicrm/contact/view/membership' q=$urlParams}" id="crm-membership-delete-button-bottom"><span><i class="crm-i fa-trash" aria-hidden="true"></i> {ts}Delete{/ts}</span></a>
         {/if}
         {include file="CRM/common/formButtons.tpl" location="bottom"}
     </div>
diff --git a/civicrm/templates/CRM/Member/Form/Selector.tpl b/civicrm/templates/CRM/Member/Form/Selector.tpl
index b9148fae70..7ddcfc02a6 100644
--- a/civicrm/templates/CRM/Member/Form/Selector.tpl
+++ b/civicrm/templates/CRM/Member/Form/Selector.tpl
@@ -69,12 +69,12 @@
 {* Link to "View all memberships" for Contact Summary selector display *}
 {if ($context EQ 'membership') AND $pager->_totalItems GT $limit}
   <tr class="even-row">
-    <td colspan="7"><a href="{crmURL p='civicrm/contact/view' q="reset=1&force=1&selectedChild=member&cid=$contactId"}">&raquo; {ts}View all memberships for this contact{/ts}...</a></td></tr>
+    <td colspan="7"><a href="{crmURL p='civicrm/contact/view' q="reset=1&force=1&selectedChild=member&cid=$contactId"}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}View all memberships for this contact{/ts}...</a></td></tr>
   </tr>
 {/if}
 {if ($context EQ 'dashboard') AND $pager->_totalItems GT $limit}
   <tr class="even-row">
-    <td colspan="10"><a href="{crmURL p='civicrm/member/search' q='reset=1'}">&raquo; {ts}Find more members{/ts}...</a></td></tr>
+    <td colspan="10"><a href="{crmURL p='civicrm/member/search' q='reset=1'}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Find more members{/ts}...</a></td></tr>
   </tr>
 {/if}
 </table>
diff --git a/civicrm/templates/CRM/Member/Form/Task/Batch.tpl b/civicrm/templates/CRM/Member/Form/Task/Batch.tpl
index b9ddfefe7e..28ed5aa243 100644
--- a/civicrm/templates/CRM/Member/Form/Task/Batch.tpl
+++ b/civicrm/templates/CRM/Member/Form/Task/Batch.tpl
@@ -22,7 +22,7 @@
            {/foreach}
 
               {foreach from=$fields item=field key=fieldName}
-                <td><img  src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</td>
+                <td>{copyIcon name=$field.name title=$field.title}{$field.title}</td>
              {/foreach}
             </tr>
           </thead>
diff --git a/civicrm/templates/CRM/Member/Import/Form/Preview.tpl b/civicrm/templates/CRM/Member/Import/Form/Preview.tpl
index b86ad221ae..e4465552d5 100644
--- a/civicrm/templates/CRM/Member/Import/Form/Preview.tpl
+++ b/civicrm/templates/CRM/Member/Import/Form/Preview.tpl
@@ -48,7 +48,7 @@
         <td class="data">{$invalidRowCount}</td>
         <td class="explanation">{ts}Rows with invalid data in one or more fields. These rows will be skipped (not imported).{/ts}
             {if $invalidRowCount}
-                <div class="action-link"><a href="{$downloadErrorRecordsUrl}">&raquo; {ts}Download Errors{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadErrorRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Errors{/ts}</a></div>
             {/if}
         </td>
     </tr>
@@ -59,7 +59,7 @@
         <td class="data">{$conflictRowCount}</td>
         <td class="explanation">{ts}Rows with conflicting transaction ids within this file. These rows will be skipped (not imported).{/ts}
             {if $conflictRowCount}
-                <div class="action-link"><a href="{$downloadConflictRecordsUrl}">&raquo; {ts}Download Conflicts{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadConflictRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Conflicts{/ts}</a></div>
             {/if}
         </td>
     </tr>
diff --git a/civicrm/templates/CRM/Member/Import/Form/Summary.tpl b/civicrm/templates/CRM/Member/Import/Form/Summary.tpl
index f42c29ba8d..70fd4ccdc1 100644
--- a/civicrm/templates/CRM/Member/Import/Form/Summary.tpl
+++ b/civicrm/templates/CRM/Member/Import/Form/Summary.tpl
@@ -68,7 +68,7 @@
         <td class="data">{$invalidRowCount}</td>
         <td class="explanation">{ts}Rows with invalid data in one or more fields. These rows will be skipped (not imported).{/ts}
             {if $invalidRowCount}
-                <div class="action-link"><a href="{$downloadErrorRecordsUrl}">&raquo; {ts}Download Errors{/ts}</a></div>
+                <div class="action-link"><a href="{$downloadErrorRecordsUrl}"><i class="crm-i fa-download" aria-hidden="true"></i> {ts}Download Errors{/ts}</a></div>
             {/if}
         </td>
     </tr>
diff --git a/civicrm/templates/CRM/Member/Page/RecurringContributions.tpl b/civicrm/templates/CRM/Member/Page/RecurringContributions.tpl
index 4d11e7aa17..326eee90e3 100644
--- a/civicrm/templates/CRM/Member/Page/RecurringContributions.tpl
+++ b/civicrm/templates/CRM/Member/Page/RecurringContributions.tpl
@@ -2,5 +2,5 @@
   <div class="solid-border-top">
     <br /><label>{ts 1=$displayName}Recurring Contributions{/ts}</label>
   </div>
-  {include file="CRM/Contribute/Page/ContributionRecur.tpl" action=16}
+  {include file="CRM/Contribute/Page/ContributionRecurSelector.tpl" action=16}
 {/if}
diff --git a/civicrm/templates/CRM/Member/Page/Tab.tpl b/civicrm/templates/CRM/Member/Page/Tab.tpl
index b4dd598370..d4abafedf5 100644
--- a/civicrm/templates/CRM/Member/Page/Tab.tpl
+++ b/civicrm/templates/CRM/Member/Page/Tab.tpl
@@ -34,9 +34,9 @@
         </div>
 
         <div class="action-link">
-            <a accesskey="N" href="{$newURL}" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Membership{/ts}</span></a>
+            <a accesskey="N" href="{$newURL}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Membership{/ts}</span></a>
             {if $accessContribution and $newCredit}
-                <a accesskey="N" href="{$newCreditURL}" class="button"><span><i class="crm-i fa-credit-card"></i> {ts}Submit Credit Card Membership{/ts}</span></a><br /><br />
+                <a accesskey="N" href="{$newCreditURL}" class="button"><span><i class="crm-i fa-credit-card" aria-hidden="true"></i> {ts}Submit Credit Card Membership{/ts}</span></a><br /><br />
             {else}
                 <br/ ><br/ >
             {/if}
@@ -80,9 +80,9 @@
                 <td class="crm-membership-source">{$activeMember.source}</td>
                 <td class="crm-membership-auto_renew">
                   {if $activeMember.auto_renew eq 1}
-                      <i class="crm-i fa-check" aria-hidden="true" title="{ts}Auto-renew active{/ts}"></i>
+                      {icon icon="fa-check"}{ts}Auto-renew active{/ts}{/icon}
                   {elseif $activeMember.auto_renew eq 2}
-                      <i class="crm-i fa-ban" aria-hidden="true" title="{ts}Auto-renew error{/ts}"></i>
+                      {icon icon="fa-exclamation-triangle"}{ts}Auto-renew error{/ts}{/icon}
                   {/if}
                 </td>
                 <td class="crm-membership-related_count">{$activeMember.related_count}</td>
@@ -130,9 +130,9 @@
                 <td class="crm-membership-source">{$inActiveMember.source}</td>
                 <td class="crm-membership-auto_renew">
                   {if $inActiveMember.auto_renew eq 1}
-                    <i class="crm-i fa-check" aria-hidden="true" title="{ts}Auto-renew active{/ts}"></i>
+                    {icon icon="fa-check"}{ts}Auto-renew active{/ts}{/icon}
                   {elseif $inActiveMember.auto_renew eq 2}
-                    <i class="crm-i fa-ban" aria-hidden="true" title="{ts}Auto-renew error{/ts}"></i>
+                    {icon icon="fa-exclamation-triangle"}{ts}Auto-renew error{/ts}{/icon}
                   {/if}
                 </td>
     <td>{$inActiveMember.action|replace:'xx':$inActiveMember.id}
diff --git a/civicrm/templates/CRM/PCP/Form/PCPAccount.tpl b/civicrm/templates/CRM/PCP/Form/PCPAccount.tpl
index 1ab7341e59..fb205cad3f 100644
--- a/civicrm/templates/CRM/PCP/Form/PCPAccount.tpl
+++ b/civicrm/templates/CRM/PCP/Form/PCPAccount.tpl
@@ -20,7 +20,7 @@
 
 {if $profileDisplay}
 <div class="messages status no-popup">
-  <i class="crm-i fa-exclamation-triangle"></i>
+  <i class="crm-i fa-exclamation-triangle" aria-hidden="true"></i>
   <strong>{ts}Profile is not configured with Email address.{/ts}</strong>
 </div>
 {else}
diff --git a/civicrm/templates/CRM/PCP/Page/PCPInfo.tpl b/civicrm/templates/CRM/PCP/Page/PCPInfo.tpl
index 6f006f4eaa..450f685bf5 100644
--- a/civicrm/templates/CRM/PCP/Page/PCPInfo.tpl
+++ b/civicrm/templates/CRM/PCP/Page/PCPInfo.tpl
@@ -25,13 +25,13 @@
     {foreach from = $links key = k item = v}
           <tr>
             <td>
-                <a href="{crmURL p=$v.url q=$v.qs|replace:'%%pcpId%%':$replace.id|replace:'%%pageComponent%%':$replace.pageComponent|replace:'%%pcpBlock%%':$replace.block}" title="{$v.title|escape:'html'}" {if $v.extra}{$v.extra}{/if}><strong>&raquo; {$v.name}</strong></a>
+                <a href="{crmURL p=$v.url q=$v.qs|replace:'%%pcpId%%':$replace.id|replace:'%%pageComponent%%':$replace.pageComponent|replace:'%%pcpBlock%%':$replace.block}" title="{$v.title|escape:'html'}" {if $v.extra}{$v.extra}{/if}><strong><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {$v.name}</strong></a>
        </td>
          <td>&nbsp;<cite>{$hints.$k}</cite></td>
       </tr>
         {/foreach}
        </table>
-     <i class="crm-i fa-lightbulb-o"></i>
+     <i class="crm-i fa-lightbulb-o" aria-hidden="true"></i>
      <strong>{ts}Tip{/ts}</strong> - <span class="description">{ts}You must be logged in to your account to access the editing options above. (If you visit this page without logging in, you will be viewing the page in "live" mode - as your visitors and friends see it.){/ts}</span>
 </div>
 {/if}
diff --git a/civicrm/templates/CRM/Pledge/Form/Selector.tpl b/civicrm/templates/CRM/Pledge/Form/Selector.tpl
index dd6ebc91a9..4df4985e81 100644
--- a/civicrm/templates/CRM/Pledge/Form/Selector.tpl
+++ b/civicrm/templates/CRM/Pledge/Form/Selector.tpl
@@ -62,7 +62,7 @@
     {* Dashboard only lists 10 most recent pledges. *}
     {if $context EQ 'dashboard' and $limit and $pager->_totalItems GT $limit }
         <tr class="even-row">
-            <td colspan="10"><a href="{crmURL p='civicrm/pledge/search' q='reset=1'}">&raquo; {ts}Find more pledges{/ts}... </a></td>
+            <td colspan="10"><a href="{crmURL p='civicrm/pledge/search' q='reset=1'}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> {ts}Find more pledges{/ts}... </a></td>
         </tr>
     {/if}
 
diff --git a/civicrm/templates/CRM/Pledge/Page/Payment.tpl b/civicrm/templates/CRM/Pledge/Page/Payment.tpl
index 19350bcabf..0da77a1503 100644
--- a/civicrm/templates/CRM/Pledge/Page/Payment.tpl
+++ b/civicrm/templates/CRM/Pledge/Page/Payment.tpl
@@ -31,7 +31,7 @@
     <td>{$row.reminder_date|truncate:10:''|crmDate}</td>
     <td class="right">{if $row.reminder_count}{$row.reminder_count}{/if}</td>
     <td {if ! ($permission EQ 'edit' and ($row.status eq 'Pending' or $row.status eq 'Overdue' or $row.status eq 'Completed')) } colspan="2"{/if} >{$row.label}</td>
-{if $context neq user}
+{if $context neq 'user'}
     {if $permission EQ 'edit' and ($row.status eq 'Pending' or $row.status eq 'Overdue' or $row.status eq 'Completed') }
         <td class="nowrap">
         {if $row.status eq 'Completed'} {* Link to view contribution record for completed payment.*}
diff --git a/civicrm/templates/CRM/Pledge/Page/Tab.tpl b/civicrm/templates/CRM/Pledge/Page/Tab.tpl
index b143f37b67..38740278c9 100644
--- a/civicrm/templates/CRM/Pledge/Page/Tab.tpl
+++ b/civicrm/templates/CRM/Pledge/Page/Tab.tpl
@@ -24,7 +24,7 @@
 
 {if $action eq 16 and $permission EQ 'edit'}
     <div class="action-link">
-       <a accesskey="N" href="{$newContribURL}" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Pledge{/ts}</a></span>
+       <a accesskey="N" href="{$newContribURL}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Pledge{/ts}</a></span>
        <br/><br/>
     </div>
 {/if}
diff --git a/civicrm/templates/CRM/Price/Form/OptionFields.tpl b/civicrm/templates/CRM/Price/Form/OptionFields.tpl
index 09a2336d54..80deab4666 100644
--- a/civicrm/templates/CRM/Price/Form/OptionFields.tpl
+++ b/civicrm/templates/CRM/Price/Form/OptionFields.tpl
@@ -41,7 +41,7 @@
   <tr id="optionField_{$index}" class="form-item {cycle values="odd-row,even-row"}">
         <td>
         {if $index GT 1}
-            <a onclick="showHideRow({$index}); return false;" name="optionField_{$index}" href="#" class="form-link"><i class="crm-i fa-trash" title="{ts}hide field or section{/ts}"></i></a>
+            <a onclick="showHideRow({$index}); return false;" name="optionField_{$index}" href="#" class="form-link"><i class="crm-i fa-trash" title="{ts}hide field or section{/ts}" aria-hidden="true"></i></a>
         {/if}
         </td>
       <td>
@@ -71,7 +71,7 @@
     {/section}
     </table>
   <div id="optionFieldLink" class="add-remove-link">
-        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus-circle"></i> {ts}add another choice{/ts}</a>
+        <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}add another choice{/ts}</a>
     </div>
   <div id="additionalOption" class="description">
     {ts}If you need additional options - you can add them after you Save your current entries.{/ts}
diff --git a/civicrm/templates/CRM/Price/Page/Option.tpl b/civicrm/templates/CRM/Price/Page/Option.tpl
index 0b3ddcbe33..22f82229a4 100644
--- a/civicrm/templates/CRM/Price/Page/Option.tpl
+++ b/civicrm/templates/CRM/Price/Page/Option.tpl
@@ -68,7 +68,7 @@
                 <td class="crm-price-option-count">{$row.count}</td>
                 <td class="crm-price-option-max">{$row.max_value}</td>
               {/if}
-              <td class="crm-price-option-is_default">{if $row.is_default}<img src="{$config->resourceBase}i/check.gif" alt="{ts}Default{/ts}" />{/if}</td>
+              <td class="crm-price-option-is_default">{icon condition=$row.is_default}{ts}Default{/ts}{/icon}</td>
               <td class="nowrap crm-price-option-financial-type-id">{$row.financial_type_id}</td>
               <td class="nowrap crm-price-option-order">{$row.weight}</td>
               {if $getTaxDetails}
diff --git a/civicrm/templates/CRM/Profile/Form/Dynamic.tpl b/civicrm/templates/CRM/Profile/Form/Dynamic.tpl
index f97cbd59a1..206ec5444d 100644
--- a/civicrm/templates/CRM/Profile/Form/Dynamic.tpl
+++ b/civicrm/templates/CRM/Profile/Form/Dynamic.tpl
@@ -157,7 +157,9 @@
                 &nbsp;{$form.$phone_ext_field.html}
                 {/if}
               {else}
-                {$form.$n.html}
+                {if $field.html_type neq 'File' || ($field.html_type eq 'File' && !$field.is_view)}
+                   {$form.$n.html}
+                {/if}
                 {if $field.html_type eq 'Autocomplete-Select'}
                   {if $field.data_type eq 'ContactReference'}
                     {include file="CRM/Custom/Form/ContactReference.tpl" element_name = $n}
@@ -170,7 +172,9 @@
 
           {if $form.$n.type eq 'file'}
             <div class="crm-section file_displayURL-section file_displayURL{$n}-section"><div class="content">{$customFiles.$n.displayURL}</div></div>
-            <div class="crm-section file_deleteURL-section file_deleteURL{$n}-section"><div class="content">{$customFiles.$n.deleteURL}</div></div>
+            {if !$fields.$n.is_view}
+               <div class="crm-section file_deleteURL-section file_deleteURL{$n}-section"><div class="content">{$customFiles.$n.deleteURL}</div></div>
+            {/if}
           {/if}
         {/if}
 
@@ -207,7 +211,7 @@
         {if $includeCancelButton}
           <a class="button cancel" href="{$cancelURL}">
             <span>
-              <i class="crm-i fa-times"></i>
+              <i class="crm-i fa-times" aria-hidden="true"></i>
               {$cancelButtonText}
             </span>
           </a>
diff --git a/civicrm/templates/CRM/Profile/Page/Listings.tpl b/civicrm/templates/CRM/Profile/Page/Listings.tpl
index a6fc3a7c1e..bd02d534e2 100644
--- a/civicrm/templates/CRM/Profile/Page/Listings.tpl
+++ b/civicrm/templates/CRM/Profile/Page/Listings.tpl
@@ -28,7 +28,7 @@
      <div id="search-status">
         {ts}Displaying contacts where:{/ts}
         {include file="CRM/common/displaySearchCriteria.tpl"}
-        {if $mapURL}<a href="{$mapURL}">&raquo; {ts}Map these contacts{/ts}</a>{/if}
+        {if $mapURL}<a href="{$mapURL}"><i class="crm-i fa-map-marker" aria-hidden="true"></i> {ts}Map these contacts{/ts}</a>{/if}
     </div>
     </div>
     {/if}
diff --git a/civicrm/templates/CRM/Profile/Page/MultipleRecordFieldsListing.tpl b/civicrm/templates/CRM/Profile/Page/MultipleRecordFieldsListing.tpl
index 7853199db8..bd740966b6 100644
--- a/civicrm/templates/CRM/Profile/Page/MultipleRecordFieldsListing.tpl
+++ b/civicrm/templates/CRM/Profile/Page/MultipleRecordFieldsListing.tpl
@@ -102,10 +102,10 @@
     <div class="action-link">
       {if $pageViewType eq 'customDataView'}
         <br/><a accesskey="N" title="{ts 1=$customGroupTitle}Add %1 Record{/ts}" href="{crmURL p='civicrm/contact/view/cd/edit' q="reset=1&type=$ctype&groupID=$customGroupId&entityID=$contactId&cgcount=$newCgCount&multiRecordDisplay=single&mode=add"}"
-         class="button action-item"><span><i class="crm-i fa-plus-circle"></i> {ts 1=$customGroupTitle}Add %1 Record{/ts}</span></a>
+         class="button action-item"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts 1=$customGroupTitle}Add %1 Record{/ts}</span></a>
       {else}
         <a accesskey="N" href="{crmURL p='civicrm/profile/edit' q="reset=1&id=`$contactId`&multiRecord=add&gid=`$gid`&context=multiProfileDialog&onPopupClose=`$onPopupClose`"}"
-         class="button action-item"><span><i class="crm-i fa-plus-circle"></i> {ts}Add New Record{/ts}</span></a>
+         class="button action-item"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add New Record{/ts}</span></a>
       {/if}
     </div>
     <br />
diff --git a/civicrm/templates/CRM/Profile/Page/View.tpl b/civicrm/templates/CRM/Profile/Page/View.tpl
index 88cba5ef72..052bffd021 100644
--- a/civicrm/templates/CRM/Profile/Page/View.tpl
+++ b/civicrm/templates/CRM/Profile/Page/View.tpl
@@ -25,10 +25,10 @@
     {/foreach}
     <div class="action-link">
         {if $listingURL}
-            <a href="{$listingURL}">&raquo; {ts}Back to Listings{/ts}</a>&nbsp;&nbsp;&nbsp;&nbsp;
+            <a href="{$listingURL}"><i class="crm-i fa-chevron-left" aria-hidden="true"></i> {ts}Back to Listings{/ts}</a>&nbsp;&nbsp;&nbsp;&nbsp;
         {/if}
         {if $mapURL}
-            <a href="{$mapURL}">&raquo; {ts}Map Primary Address{/ts}</a>
+            <a href="{$mapURL}"><i class="crm-i fa-map-marker" aria-hidden="true"></i> {ts}Map Primary Address{/ts}</a>
         {/if}
     </div>
 {/if}
diff --git a/civicrm/templates/CRM/Report/Form/Actions.tpl b/civicrm/templates/CRM/Report/Form/Actions.tpl
index 7ba2c5f917..9aee8f6695 100644
--- a/civicrm/templates/CRM/Report/Form/Actions.tpl
+++ b/civicrm/templates/CRM/Report/Form/Actions.tpl
@@ -20,7 +20,7 @@
               <tr>
                 {include file="CRM/common/tasks.tpl" location="botton"}
                 {if $instanceUrl}
-                  <td>&nbsp;&nbsp;&raquo;&nbsp;<a href="{$instanceUrl}">{ts}Existing report(s) from this template{/ts}</a></td>
+                  <td>&nbsp;&nbsp;<i class="crm-i fa-chevron-right" aria-hidden="true"></i>&nbsp;<a href="{$instanceUrl}">{ts}Existing report(s) from this template{/ts}</a></td>
                 {/if}
               </tr>
             </table>
@@ -42,7 +42,7 @@
                       (function($) {
                         $('#groups').val('').change(function() {
                           CRM.confirm({
-                            message: ts({/literal}'{ts escape='js' 1='<em>%1</em>'}Add all contacts to %1 group?{/ts}'{literal}, {1: $('option:selected', '#groups').text()})
+                            message: ts({/literal}'{ts escape='js' 1='<em>%1</em>'}Add all contacts to %1 group?{/ts}'{literal}, {1: CRM._.escape($('option:selected', '#groups').text())})
                           })
                             .on({
                               'crmConfirm:yes': function() {
diff --git a/civicrm/templates/CRM/Report/Form/Tabs/OrderBy.tpl b/civicrm/templates/CRM/Report/Form/Tabs/OrderBy.tpl
index 413d66e14e..f881c58d2a 100644
--- a/civicrm/templates/CRM/Report/Form/Tabs/OrderBy.tpl
+++ b/civicrm/templates/CRM/Report/Form/Tabs/OrderBy.tpl
@@ -24,7 +24,7 @@
         <tr id="optionField_{$index}" class="form-item {cycle values="odd-row,even-row"}">
           <td>
             {if $index GT 1}
-              <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link"><img src="{$config->resourceBase}i/TreeMinus.gif" class="action-icon" alt="{ts}hide field or section{/ts}"/></a>
+              <a onclick="hideRow({$index}); return false;" name="orderBy_{$index}" href="#" class="form-link">{icon icon="fa-trash"}{ts}remove sort by column{/ts}{/icon}</a>
             {/if}
           </td>
           <td> {$form.order_bys.$index.column.html}</td>
@@ -35,7 +35,7 @@
       {/section}
     </table>
     <div id="optionFieldLink" class="add-remove-link">
-      <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><img src="{$config->resourceBase}i/TreePlus.gif" class="action-icon" alt="{ts}show field or section{/ts}"/>{ts}another column{/ts}</a>
+      <a onclick="showHideRow(); return false;" name="optionFieldLink" href="#" class="form-link"><i class="crm-i fa-plus action-icon" aria-hidden="true"></i> {ts}another column{/ts}</a>
     </div>
     <script type="text/javascript">
       var showRows   = new Array({$showBlocks});
diff --git a/civicrm/templates/CRM/Report/Page/InstanceList.tpl b/civicrm/templates/CRM/Report/Page/InstanceList.tpl
index 2da9bdfe97..354edd5444 100644
--- a/civicrm/templates/CRM/Report/Page/InstanceList.tpl
+++ b/civicrm/templates/CRM/Report/Page/InstanceList.tpl
@@ -10,7 +10,7 @@
 {strip}
   <div class="action-link">
     {if $templateUrl}
-      <a href="{$templateUrl}" class="button"><span><i class="crm-i fa-plus-circle"></i> {$newButton}</span></a>
+      <a href="{$templateUrl}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {$newButton}</span></a>
     {/if}
     {if $reportUrl}
       <a href="{$reportUrl}" class="button"><span>{ts}View All Reports{/ts}</span></a>
@@ -29,7 +29,7 @@
               <table class="report-layout">
                 {foreach from=$rows item=row}
                   <tr id="row_{counter}" class="crm-report-instanceList">
-                    <td class="crm-report-instanceList-title" style="width:35%"><a href="{$row.url}" title="{ts}Run this report{/ts}">&raquo; <strong>{$row.title}</strong></a></td>
+                    <td class="crm-report-instanceList-title" style="width:35%"><a href="{$row.url}" title="{ts}Run this report{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> <strong>{$row.title}</strong></a></td>
                     <td class="crm-report-instanceList-description">{$row.description}</td>
                     <td>
                     <a href="{$row.viewUrl}" class="action-item crm-hover-button">{ts}View Results{/ts}</a>
@@ -54,7 +54,7 @@
 
     <div class="action-link">
       {if $templateUrl}
-        <a href="{$templateUrl}" class="button"><span><i class="crm-i fa-plus-circle"></i> {$newButton}</span></a>
+        <a href="{$templateUrl}" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {$newButton}</span></a>
       {/if}
       {if $reportUrl}
         <a href="{$reportUrl}" class="button"><span>{ts}View All Reports{/ts}</span></a>
diff --git a/civicrm/templates/CRM/Report/Page/Options.tpl b/civicrm/templates/CRM/Report/Page/Options.tpl
index 42e6aed765..6cb81d5e18 100644
--- a/civicrm/templates/CRM/Report/Page/Options.tpl
+++ b/civicrm/templates/CRM/Report/Page/Options.tpl
@@ -12,7 +12,7 @@
 </div>
 {if $action ne 1 and $action ne 2}
   <div class="action-link">
-    <a href="{$newReport}"  id="new"|cat:$GName class="button"><span><i class="crm-i fa-plus-circle"></i> {ts 1=$GName}Register New %1{/ts}</span></a>
+    <a href="{$newReport}"  id="new"|cat:$GName class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts 1=$GName}Register New %1{/ts}</span></a>
   </div>
   <div class="spacer"></div>
 {/if}
@@ -58,7 +58,7 @@
 
     {if $action ne 1 and $action ne 2}
       <div class="action-link">
-        <a href="{$newReport}"  id="new"|cat:$GName class="button"><span><i class="crm-i fa-plus-circle"></i> {ts 1=$GName}Register New %1{/ts}</span></a>
+        <a href="{$newReport}"  id="new"|cat:$GName class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts 1=$GName}Register New %1{/ts}</span></a>
       </div>
     {/if}
   </div>
diff --git a/civicrm/templates/CRM/Report/Page/TemplateList.tpl b/civicrm/templates/CRM/Report/Page/TemplateList.tpl
index 55eafeb22a..497157d074 100644
--- a/civicrm/templates/CRM/Report/Page/TemplateList.tpl
+++ b/civicrm/templates/CRM/Report/Page/TemplateList.tpl
@@ -27,7 +27,7 @@
                 {foreach from=$rows item=row}
                   <tr id="row_{counter}" class="crm-report-templateList">
                     <td class="crm-report-templateList-title" style="width:35%;">
-                      <a href="{$row.url}" title="{ts}Create report from this template{/ts}">&raquo; <strong>{$row.title}</strong></a>
+                      <a href="{$row.url}" title="{ts}Create report from this template{/ts}"><i class="crm-i fa-chevron-right" aria-hidden="true"></i> <strong>{$row.title}</strong></a>
                       {if $row.instanceUrl}
                         <div style="font-size:10px;text-align:right;margin-top:3px;">
                           <a href="{$row.instanceUrl}">{ts}Existing Report(s){/ts}</a>
diff --git a/civicrm/templates/CRM/Tag/Form/Tag.tpl b/civicrm/templates/CRM/Tag/Form/Tag.tpl
index 63066cedb1..892ac1a8aa 100644
--- a/civicrm/templates/CRM/Tag/Form/Tag.tpl
+++ b/civicrm/templates/CRM/Tag/Form/Tag.tpl
@@ -87,7 +87,7 @@
       <tr>
         <td>
           <input class="crm-form-text big" name="filter_tag_tree" placeholder="{ts}Filter List{/ts}" allowclear="1"/>
-          <a class="crm-hover-button crm-clear-link" style="visibility:hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a>
+          <a class="crm-hover-button crm-clear-link" style="visibility:hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
           <div id="tagtree">
             {include file="CRM/Tag/Form/Tagtree.tpl" level=1}
           </div>
diff --git a/civicrm/templates/CRM/Tag/Page/Tag.tpl b/civicrm/templates/CRM/Tag/Page/Tag.tpl
index 4d4702ea92..e59f24246a 100644
--- a/civicrm/templates/CRM/Tag/Page/Tag.tpl
+++ b/civicrm/templates/CRM/Tag/Page/Tag.tpl
@@ -20,7 +20,7 @@
   <div id="mainTabContainer">
     <ul>
       <li class="ui-corner-all crm-tab-button" title="{ts}Main Tag List{/ts}">
-        <a href="#tree"><i class="crm-i fa-tags"></i> {ts}Tag Tree{/ts}</a>
+        <a href="#tree"><i class="crm-i fa-tags" aria-hidden="true"></i> {ts}Tag Tree{/ts}</a>
       </li>
       {foreach from=$tagsets item=set}
         <li class="ui-corner-all crm-tab-button {if ($set.is_reserved)}is-reserved{/if}" title="{ts 1=', '|implode:$set.used_for_label}Tag Set for %1{/ts}">
@@ -29,7 +29,7 @@
       {/foreach}
       {if call_user_func(array('CRM_Core_Permission','check'), 'administer Tagsets')}
         <li class="ui-corner-all crm-tab-button" title="{ts}Add Tag Set{/ts}">
-          <a href="#new-tagset"><i class="crm-i fa-plus"></i></a>
+          <a href="#new-tagset"><i class="crm-i fa-plus" aria-hidden="true"></i></a>
         </li>
       {/if}
     </ul>
@@ -38,7 +38,7 @@
         {ts}Organize the tag hierarchy by clicking and dragging. Shift-click to select multiple tags to merge/move/delete.{/ts}
       </div>
       <input class="crm-form-text big" name="filter_tag_tree" placeholder="{ts}Filter List{/ts}" allowclear="1"/>
-      <a class="crm-hover-button crm-clear-link" style="visibility:hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a>
+      <a class="crm-hover-button crm-clear-link" style="visibility:hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
     </div>
     {foreach from=$tagsets item=set}
       <div id="tagset-{$set.id}">
@@ -463,16 +463,16 @@
   <% {rdelim} %>
   <div class="crm-submit-buttons">
     <a href="{crmURL p="civicrm/tag/edit" q="action=add&parent_id="}<%= tagset || '' %>" class="button crm-popup">
-      <span><i class="crm-i fa-plus"></i>&nbsp; {ts}Add Tag{/ts}</span>
+      <span><i class="crm-i fa-plus" aria-hidden="true"></i>&nbsp; {ts}Add Tag{/ts}</span>
     </a>
     <% if(tagset && adminTagsets) {ldelim} %>
       <a href="{crmURL p="civicrm/tag/edit" q="action=update&id="}<%= tagset %>" class="button crm-popup tagset-action-update">
-        <span><i class="crm-i fa-pencil"></i>&nbsp; {ts}Edit Set{/ts}</span>
+        <span><i class="crm-i fa-pencil" aria-hidden="true"></i>&nbsp; {ts}Edit Set{/ts}</span>
       </a>
     <% {rdelim} %>
     <% if(tagset && !length && adminTagsets && (!is_reserved || adminReserved)) {ldelim} %>
       <a href="{crmURL p="civicrm/tag/edit" q="action=delete&id="}<%= tagset %>" class="button crm-popup small-popup tagset-action-delete">
-        <span><i class="crm-i fa-trash"></i>&nbsp; {ts}Delete Set{/ts}</span>
+        <span><i class="crm-i fa-trash" aria-hidden="true"></i>&nbsp; {ts}Delete Set{/ts}</span>
       </a>
     <% {rdelim} %>
   </div>
@@ -499,7 +499,7 @@
         <span class="tdl">{ts}Used For:{/ts}</span>
         {literal}
           <span class="<% if (!data.is_reserved || adminReserved) { %>crm-editable-enabled used-for-toggle<% } %>">
-            <% if (!data.used_for.length) { %><i class="crm-i fa-pencil crm-editable-placeholder"></i><% } %>
+            <% if (!data.used_for.length) { %><i class="crm-i fa-pencil crm-editable-placeholder" aria-hidden="true"></i><% } %>
             <% _.forEach(data.used_for, function(key, i) { %><%- (i ? ', ' : '') + usedFor[key] %><% }) %>
           </span>
           <span style="display: none">
@@ -514,26 +514,26 @@
       </div>
     <% {rdelim} %>
     <div><span class="tdl">{ts}Usage Count:{/ts}</span> <%= data.usages %></div>
-    <a class="clear-tag-selection" href="#" title="{ts}Clear selection{/ts}"><i class="crm-i fa-ban"></i></a>
+    <a class="clear-tag-selection" href="#" title="{ts}Clear selection{/ts}"><i class="crm-i fa-ban" aria-hidden="true"></i></a>
   </div>
   <div class="crm-submit-buttons">
     <% if(!tagset) {ldelim} %>
       <a href="{crmURL p="civicrm/tag/edit" q="action=add&parent_id="}<%= id %>" class="button crm-popup" title="{ts}Create new tag under this one{/ts}">
-        <span><i class="crm-i fa-plus"></i>&nbsp; {ts}Add Child{/ts}</span>
+        <span><i class="crm-i fa-plus" aria-hidden="true"></i>&nbsp; {ts}Add Child{/ts}</span>
       </a>
     <% {rdelim} %>
     <a href="{crmURL p="civicrm/tag/edit" q="action=add&clone_from="}<%= id %>" class="button crm-popup" title="{ts}Duplicate this tag{/ts}">
-      <span><i class="crm-i fa-copy"></i>&nbsp; {ts}Clone Tag{/ts}</span>
+      <span><i class="crm-i fa-copy" aria-hidden="true"></i>&nbsp; {ts}Clone Tag{/ts}</span>
     </a>
     <% if(!data.is_reserved || adminReserved) {ldelim} %>
       <% if(tagsetCount) {ldelim} %>
         <a href="#move" class="button move-tag-button" title="{ts}Move to a different tagset{/ts}">
-          <span><i class="crm-i fa-share-square-o"></i>&nbsp; {ts}Move Tag{/ts}</span>
+          <span><i class="crm-i fa-share-square-o" aria-hidden="true"></i>&nbsp; {ts}Move Tag{/ts}</span>
         </a>
       <% {rdelim} %>
       <% if(!hasChildren) {ldelim} %>
         <a href="{crmURL p="civicrm/tag/edit" q="action=delete&id="}<%= id %>" class="button crm-popup small-popup">
-          <span><i class="crm-i fa-trash"></i>&nbsp; {ts}Delete{/ts}</span>
+          <span><i class="crm-i fa-trash" aria-hidden="true"></i>&nbsp; {ts}Delete{/ts}</span>
         </a>
       <% {rdelim} %>
     <% {rdelim} %>
@@ -547,20 +547,20 @@
       <p>* {ts 1="<%= reserved %>"}%1 reserved.{/ts}</p>
     <% {rdelim} %>
   <p><span class="tdl">{ts}Total Usage:{/ts}</span> <%= usages %></p>
-  <a class="clear-tag-selection" href="#" title="{ts}Clear selection{/ts}"><i class="crm-i fa-ban"></i></a>
+  <a class="clear-tag-selection" href="#" title="{ts}Clear selection{/ts}"><i class="crm-i fa-ban" aria-hidden="true"></i></a>
   <div class="crm-submit-buttons">
     <% if(!reserved || adminReserved) {ldelim} %>
       <a href="{crmURL p="civicrm/tag/merge" q="id="}<%= items.join() %>" class="button crm-popup small-popup" title="{ts}Combine tags into one{/ts}">
-        <span><i class="crm-i fa-compress"></i>&nbsp; {ts}Merge Tags{/ts}</span>
+        <span><i class="crm-i fa-compress" aria-hidden="true"></i>&nbsp; {ts}Merge Tags{/ts}</span>
       </a>
       <% if(tagsetCount) {ldelim} %>
         <a href="#move" class="button move-tag-button" title="{ts}Move to a different tagset{/ts}">
-          <span><i class="crm-i fa-share-square-o"></i>&nbsp; {ts}Move Tags{/ts}</span>
+          <span><i class="crm-i fa-share-square-o" aria-hidden="true"></i>&nbsp; {ts}Move Tags{/ts}</span>
         </a>
       <% {rdelim} %>
       <% if(!hasChildren) {ldelim} %>
         <a href="{crmURL p="civicrm/tag/edit" q="action=delete&id="}<%= items.join() %>" class="button crm-popup small-popup">
-          <span><i class="crm-i fa-trash"></i>&nbsp; {ts}Delete All{/ts}</span>
+          <span><i class="crm-i fa-trash" aria-hidden="true"></i>&nbsp; {ts}Delete All{/ts}</span>
         </a>
       <% {rdelim} %>
     <% {rdelim} %>
@@ -576,6 +576,6 @@
       <% if(typeof description === 'string' && description.length) {ldelim} %><p><em><%- description %></em></p><% {rdelim} %>
     </div>
     <input class="crm-form-text big" name="filter_tag_tree" placeholder="{ts}Filter List{/ts}" allowclear="1"/>
-    <a class="crm-hover-button crm-clear-link" style="visibility:hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a>
+    <a class="crm-hover-button crm-clear-link" style="visibility:hidden;" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
   </div>
 </script>
diff --git a/civicrm/templates/CRM/UF/Page/Group.tpl b/civicrm/templates/CRM/UF/Page/Group.tpl
index 62469563a9..1eb5ee8ef0 100644
--- a/civicrm/templates/CRM/UF/Page/Group.tpl
+++ b/civicrm/templates/CRM/UF/Page/Group.tpl
@@ -26,7 +26,7 @@
         <a href="#" onclick="html_code.profile.select(); return false;" class="button"><span>Select HTML Code</span></a>
     </div>
     <div class="action-link">
-        &nbsp; <a href="{crmURL p='civicrm/admin/uf/group' q="reset=1"}">&raquo;  {ts}Back to Profile Listings{/ts}</a>
+        &nbsp; <a href="{crmURL p='civicrm/admin/uf/group' q="reset=1"}"><i class="crm-i fa-chevron-left" aria-hidden="true"></i>  {ts}Back to Profile Listings{/ts}</a>
     </div>
     </form>
 
@@ -38,7 +38,7 @@
 <div class="crm-content-block crm-block">
     {if NOT ($action eq 1 or $action eq 2)}
     <div class="crm-submit-buttons">
-        <a href="{crmURL p='civicrm/admin/uf/group/add' q="action=add&reset=1"}" id="newCiviCRMProfile-top" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Profile{/ts}</span></a>
+        <a href="{crmURL p='civicrm/admin/uf/group/add' q="action=add&reset=1"}" id="newCiviCRMProfile-top" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Profile{/ts}</span></a>
     </div>
     {/if}
     {if $rows}
@@ -90,7 +90,7 @@
 
             {if NOT ($action eq 1 or $action eq 2)}
             <div class="crm-submit-buttons">
-                <a href="{crmURL p='civicrm/admin/uf/group/add' q='action=add&reset=1'}" id="newCiviCRMProfile-bottom" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Profile{/ts}</span></a>
+                <a href="{crmURL p='civicrm/admin/uf/group/add' q='action=add&reset=1'}" id="newCiviCRMProfile-bottom" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Profile{/ts}</span></a>
             </div>
             {/if}
             </div>
@@ -135,7 +135,7 @@
 
             {if NOT ($action eq 1 or $action eq 2)}
             <div class="crm-submit-buttons">
-                <a href="{crmURL p='civicrm/admin/uf/group/add' q='action=add&reset=1'}" id="newCiviCRMProfile-bottom" class="button"><span><i class="crm-i fa-plus-circle"></i> {ts}Add Profile{/ts}</span></a>
+                <a href="{crmURL p='civicrm/admin/uf/group/add' q='action=add&reset=1'}" id="newCiviCRMProfile-bottom" class="button"><span><i class="crm-i fa-plus-circle" aria-hidden="true"></i> {ts}Add Profile{/ts}</span></a>
             </div>
             {/if}
             </div>
diff --git a/civicrm/templates/CRM/UF/Page/ProfileTemplates.tpl b/civicrm/templates/CRM/UF/Page/ProfileTemplates.tpl
index b5e8a1b400..c6fdeff238 100644
--- a/civicrm/templates/CRM/UF/Page/ProfileTemplates.tpl
+++ b/civicrm/templates/CRM/UF/Page/ProfileTemplates.tpl
@@ -36,7 +36,7 @@
       </div>
       <hr>
       <input type="text" class="crm-form-text" placeholder="{ts}Search Fields{/ts}" />
-      <a class="crm-designer-palette-clear-search crm-hover-button" href="#" style="visibility:hidden" title="{ts}Clear search{/ts}"><i class="crm-i fa-times"></i></a>
+      <a class="crm-designer-palette-clear-search crm-hover-button" href="#" style="visibility:hidden" title="{ts}Clear search{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
       <div class="crm-designer-palette-controls">
         <a href="#" class="crm-designer-palette-toggle" rel="open_all">{ts}Open All{/ts}</a>&nbsp; |&nbsp;
         <a href="#" class="crm-designer-palette-toggle" rel="close_all">{ts}Close All{/ts}</a>
@@ -65,8 +65,8 @@
  *}
 <script type="text/template" id="field_summary_template">
   <span class="crm-designer-buttons">
-    <a class="crm-i fa-pencil crm-designer-action-settings" title="{ts}Settings{/ts}"></a>
-    <a class="crm-i fa-trash crm-designer-action-remove" title="{ts}Remove{/ts}"></a>
+    <a class="crm-i fa-pencil crm-designer-action-settings" title="{ts}Settings{/ts}" aria-hidden="true"></a>
+    <a class="crm-i fa-trash crm-designer-action-remove" title="{ts}Remove{/ts}" aria-hidden="true"></a>
   </span>
   <div class="description"><%= help_pre %></div>
   <div class="crm-designer-row-label">
@@ -93,7 +93,7 @@
 <script type="text/template" id="form_summary_template">
   <h3><%= title %></h3>
   <div class="crm-designer-buttons">
-    <a class="crm-designer-action-settings crm-i fa-pencil" title="{ts}Settings{/ts}"></a>
+    <a class="crm-designer-action-settings crm-i fa-pencil" title="{ts}Settings{/ts}" aria-hidden="true"></a>
   </div>
 </script>
 
@@ -114,7 +114,7 @@
 <script type="text/template" id="profile_selector_template">
     <div>
         <span class="crm-profile-selector-select"></span>
-        <button type="button" class="crm-profile-selector-preview" title="{ts}Preview{/ts}"><i class="crm-i fa-television"></i> {ts}Preview{/ts}</button>
+        <button type="button" class="crm-profile-selector-preview" title="{ts}Preview{/ts}"><i class="crm-i fa-television" aria-hidden="true"></i> {ts}Preview{/ts}</button>
         {if $perm}
           <button class="crm-profile-selector-edit">{ts}Edit{/ts}</button>
           <button class="crm-profile-selector-copy">{ts}Copy{/ts}</button>
diff --git a/civicrm/templates/CRM/common/CMSPrint.tpl b/civicrm/templates/CRM/common/CMSPrint.tpl
index e5a3823e79..9edb297aba 100644
--- a/civicrm/templates/CRM/common/CMSPrint.tpl
+++ b/civicrm/templates/CRM/common/CMSPrint.tpl
@@ -17,7 +17,7 @@
   <div class="breadcrumb">
     {foreach from=$breadcrumb item=crumb key=key}
       {if $key != 0}
-        &raquo;
+        <i class="crm-i fa-angle-double-right" aria-hidden="true"></i>
       {/if}
       {$crumb}
     {/foreach}
diff --git a/civicrm/templates/CRM/common/civicrm.settings.php.template b/civicrm/templates/CRM/common/civicrm.settings.php.template
index a89b04864a..6bdab4ec76 100644
--- a/civicrm/templates/CRM/common/civicrm.settings.php.template
+++ b/civicrm/templates/CRM/common/civicrm.settings.php.template
@@ -483,6 +483,25 @@ if (CIVICRM_UF === 'UnitTests') {
   if (!defined('CIVICRM_MYSQL_STRICT')) define('CIVICRM_MYSQL_STRICT', true);
 }
 
+/**
+ * Whether to include the hash in config log filenames. Defaults to TRUE.
+ * Disable only if you have configured the logfiles to be outside the docroot
+ * using the civicrm.log path setting.
+ *
+ */
+// if (!defined('CIVICRM_LOG_HASH'))  {
+//   define('CIVICRM_LOG_HASH', FALSE );
+// }
+
+/**
+ * The maximum size a log file may be before it's rotated, in bytes.
+ * Set to 0 to disable rotation (only recommended if you have an
+ * external logrotate configuration).
+ */
+// if (!defined('CIVICRM_LOG_ROTATESIZE')) {
+//   define('CIVICRM_LOG_ROTATESIZE', 0 );
+// }
+
 /**
  *
  * Do not change anything below this line. Keep as is
diff --git a/civicrm/templates/CRM/common/contactFooter.tpl b/civicrm/templates/CRM/common/contactFooter.tpl
index bae700d6b3..76eaaae07d 100644
--- a/civicrm/templates/CRM/common/contactFooter.tpl
+++ b/civicrm/templates/CRM/common/contactFooter.tpl
@@ -17,7 +17,7 @@
   {if !empty($lastModified)}
     {ts}Last Change by{/ts}: <a href="{crmURL p='civicrm/contact/view' q="action=view&reset=1&cid=`$lastModified.id`"}">{$lastModified.name}</a> ({$lastModified.date|crmDate}) &nbsp;
     {if !empty($changeLog)}
-      <a href="{crmURL p='civicrm/contact/view' q="reset=1&action=browse&selectedChild=log&cid=`$contactId`"}" class="crm-log-view">&raquo; {ts}View Change Log{/ts}</a>
+      <a href="{crmURL p='civicrm/contact/view' q="reset=1&action=browse&selectedChild=log&cid=`$contactId`"}" class="crm-log-view"><i class="crm-i fa-history" aria-hidden="true"></i> {ts}View Change Log{/ts}</a>
     {/if}
   {/if}
   {if !empty($created_date)}<div class="contact-created-date">{ts}Created{/ts}: {$created_date|crmDate}</div>{/if}
diff --git a/civicrm/templates/CRM/common/fatal.tpl b/civicrm/templates/CRM/common/fatal.tpl
index 7a8e82130a..870180bb0a 100644
--- a/civicrm/templates/CRM/common/fatal.tpl
+++ b/civicrm/templates/CRM/common/fatal.tpl
@@ -32,7 +32,7 @@
     @import url({$config->resourceBase}bower_components/font-awesome/css/font-awesome.min.css);
   </style>
 {/if}
-<div class="messages status no-popup">  <i class="crm-i fa-exclamation-triangle crm-i-red"></i>
+<div class="messages status no-popup">  <i class="crm-i fa-exclamation-triangle crm-i-red" aria-hidden="true"></i>
  <span class="status-fatal">{ts}Sorry, due to an error, we are unable to fulfill your request at the moment. You may want to contact your administrator or service provider with more details about what action you were performing when this occurred.{/ts}</span>
     <div class="crm-section crm-error-message">{$message|escape}</div>
     {if $error.message && $message != $error.message}
diff --git a/civicrm/templates/CRM/common/formButtons.tpl b/civicrm/templates/CRM/common/formButtons.tpl
index 2a1260011c..92b41f4dff 100644
--- a/civicrm/templates/CRM/common/formButtons.tpl
+++ b/civicrm/templates/CRM/common/formButtons.tpl
@@ -17,7 +17,7 @@
     {else}{assign var="accessKey" value=""}
     {/if}
     {if $linkButton.icon}
-      {capture assign=icon}<i class="crm-i {$linkButton.icon}"></i> {/capture}
+      {capture assign=icon}<i class="crm-i {$linkButton.icon}" aria-hidden="true"></i> {/capture}
     {else}{assign var="icon" value=""}
     {/if}
     {if $linkButton.ref}
@@ -42,7 +42,7 @@
     {capture assign=iconPrefix}{$icon|truncate:3:"":true}{/capture}
     {if $icon && $iconPrefix eq 'fa-'}
       {assign var='buttonClass' value=' crm-i-button'}
-      {capture assign=iconDisp}<i class="crm-i {$icon}"></i>{/capture}
+      {capture assign=iconDisp}<i class="crm-i {$icon}" aria-hidden="true"></i>{/capture}
     {elseif $icon}
       {assign var='buttonClass' value=' crm-icon-button'}
       {capture assign=iconDisp}<span class="crm-button-icon ui-icon-{$icon}"> </span>{/capture}
diff --git a/civicrm/templates/CRM/common/jcalendar.tpl b/civicrm/templates/CRM/common/jcalendar.tpl
index 1e978a5160..64153189bb 100644
--- a/civicrm/templates/CRM/common/jcalendar.tpl
+++ b/civicrm/templates/CRM/common/jcalendar.tpl
@@ -50,7 +50,7 @@
 {/if}
 
 {if $action neq 1028}
-    <a href="#" class="crm-hover-button crm-clear-link" title="{ts}Clear{/ts}"><i class="crm-i fa-times"></i></a>
+    <a href="#" class="crm-hover-button crm-clear-link" title="{ts}Clear{/ts}"><i class="crm-i fa-times" aria-hidden="true"></i></a>
 {/if}
 
 <script type="text/javascript">
diff --git a/civicrm/templates/CRM/common/joomla.tpl b/civicrm/templates/CRM/common/joomla.tpl
index e9d30f4adc..4d05e688f2 100644
--- a/civicrm/templates/CRM/common/joomla.tpl
+++ b/civicrm/templates/CRM/common/joomla.tpl
@@ -26,7 +26,7 @@
     <div class="breadcrumb">
       {foreach from=$breadcrumb item=crumb key=key}
         {if $key != 0}
-           &raquo;
+           <i class="crm-i fa-angle-double-right" aria-hidden="true"></i>
         {/if}
         <a href="{$crumb.url}">{$crumb.title}</a>
       {/foreach}
diff --git a/civicrm/templates/CRM/common/navigation.js.tpl b/civicrm/templates/CRM/common/navigation.js.tpl
index 25d5b910bd..866769185c 100644
--- a/civicrm/templates/CRM/common/navigation.js.tpl
+++ b/civicrm/templates/CRM/common/navigation.js.tpl
@@ -144,10 +144,6 @@ $('#civicrm-menu').ready(function() {
     var $selection = $('.crm-quickSearchField input:checked'),
       label = $selection.parent().text(),
       value = $selection.val();
-    // These fields are not supported by advanced search
-    if (!value || value === 'first_name' || value === 'last_name') {
-      value = 'sort_name';
-    }
     $('#sort_name_navigation').attr({name: value, placeholder: label});
   }
   $('.crm-quickSearchField').click(function() {
diff --git a/civicrm/templates/CRM/common/status.tpl b/civicrm/templates/CRM/common/status.tpl
index c2d81be5a2..27f5fbc0fa 100644
--- a/civicrm/templates/CRM/common/status.tpl
+++ b/civicrm/templates/CRM/common/status.tpl
@@ -13,7 +13,7 @@
   {assign var="status" value=$session->getStatus(true)}
   {foreach name=statLoop item=statItem from=$status}
     {if $urlIsPublic}
-      {assign var="infoType" value="no-popup"}
+      {assign var="infoType" value="no-popup `$statItem.type`"}
     {else}
       {assign var="infoType" value=$statItem.type}
     {/if}
diff --git a/civicrm/templates/CRM/common/success.tpl b/civicrm/templates/CRM/common/success.tpl
index 28fe6435e3..a1fbfb3702 100644
--- a/civicrm/templates/CRM/common/success.tpl
+++ b/civicrm/templates/CRM/common/success.tpl
@@ -30,11 +30,11 @@
             {ts 1=$docLink}This process may change your database structure and values. In case of emergency you may need to revert to a backup. For more detailed information, refer to the %1.{/ts}</p>
         <input type="hidden" name="action" value="begin" />
         <button type="submit" class="crm-button" name="upgrade" onclick="return confirm('{ts escape="js"}Are you sure you are ready to upgrade now?{/ts}');" >
-          <i class="crm-i fa-rocket"></i>
+          <i class="crm-i fa-rocket" aria-hidden="true"></i>
           {ts}Upgrade Now{/ts}
         </button>&nbsp;&nbsp;
         <a class="button cancel crm-form-submit" href="{$cancelURL}">
-          <i class="crm-i fa-times"></i>
+          <i class="crm-i fa-times" aria-hidden="true"></i>
           {ts}Cancel{/ts}
         </a>
     </form>
diff --git a/civicrm/vendor/autoload.php b/civicrm/vendor/autoload.php
index cc9a6cbbfd..8eb61a144a 100644
--- a/civicrm/vendor/autoload.php
+++ b/civicrm/vendor/autoload.php
@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer/autoload_real.php';
 
-return ComposerAutoloaderInitb2582f114b1248d5a20a7411671eea43::getLoader();
+return ComposerAutoloaderInitabd80a2472ebcf6a6e6e8989d45a577c::getLoader();
diff --git a/civicrm/vendor/composer/autoload_classmap.php b/civicrm/vendor/composer/autoload_classmap.php
index 885b3807f7..00e85ad083 100644
--- a/civicrm/vendor/composer/autoload_classmap.php
+++ b/civicrm/vendor/composer/autoload_classmap.php
@@ -23,6 +23,7 @@ return array(
     'HTML5_TreeBuilder' => $vendorDir . '/dompdf/dompdf/lib/html5lib/TreeBuilder.php',
     'ICallbackNamed' => $vendorDir . '/electrolinux/phpquery/phpQuery/phpQuery/Callback.php',
     'PDF417' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
+    'PEAR_Exception' => $vendorDir . '/pear/pear_exception/PEAR/Exception.php',
     'PclZip' => $vendorDir . '/pclzip/pclzip/pclzip.lib.php',
     'QRcode' => $vendorDir . '/tecnickcom/tcpdf/include/barcodes/qrcode.php',
     'TCPDF' => $vendorDir . '/tecnickcom/tcpdf/tcpdf.php',
diff --git a/civicrm/vendor/composer/autoload_namespaces.php b/civicrm/vendor/composer/autoload_namespaces.php
index 9d6930636c..2fc96bee6a 100644
--- a/civicrm/vendor/composer/autoload_namespaces.php
+++ b/civicrm/vendor/composer/autoload_namespaces.php
@@ -11,7 +11,6 @@ return array(
     'System' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
     'Sabberworm\\CSS' => array($vendorDir . '/sabberworm/php-css-parser/lib'),
     'PHPUnit_' => array($baseDir . '/packages'),
-    'PEAR' => array($vendorDir . '/pear/pear_exception'),
     'Net' => array($vendorDir . '/phpseclib/phpseclib/phpseclib', $vendorDir . '/pear/net_socket', $vendorDir . '/pear/net_smtp'),
     'Math' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
     'Mail' => array($vendorDir . '/pear/mail'),
diff --git a/civicrm/vendor/composer/autoload_psr4.php b/civicrm/vendor/composer/autoload_psr4.php
index 04aff2ed58..d2f8e023fc 100644
--- a/civicrm/vendor/composer/autoload_psr4.php
+++ b/civicrm/vendor/composer/autoload_psr4.php
@@ -23,6 +23,7 @@ return array(
     'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
     'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
     'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
+    'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
     'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
     'PhpOffice\\PhpWord\\' => array($vendorDir . '/phpoffice/phpword/src/PhpWord'),
     'PhpOffice\\Common\\' => array($vendorDir . '/phpoffice/common/src/Common'),
diff --git a/civicrm/vendor/composer/autoload_real.php b/civicrm/vendor/composer/autoload_real.php
index c4f799abb5..dcb5fefc09 100644
--- a/civicrm/vendor/composer/autoload_real.php
+++ b/civicrm/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
 
 // autoload_real.php @generated by Composer
 
-class ComposerAutoloaderInitb2582f114b1248d5a20a7411671eea43
+class ComposerAutoloaderInitabd80a2472ebcf6a6e6e8989d45a577c
 {
     private static $loader;
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInitb2582f114b1248d5a20a7411671eea43
             return self::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInitb2582f114b1248d5a20a7411671eea43', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInitabd80a2472ebcf6a6e6e8989d45a577c', 'loadClassLoader'), true, true);
         self::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInitb2582f114b1248d5a20a7411671eea43', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInitabd80a2472ebcf6a6e6e8989d45a577c', 'loadClassLoader'));
 
         $includePaths = require __DIR__ . '/include_paths.php';
         $includePaths[] = get_include_path();
@@ -31,7 +31,7 @@ class ComposerAutoloaderInitb2582f114b1248d5a20a7411671eea43
         if ($useStaticLoader) {
             require_once __DIR__ . '/autoload_static.php';
 
-            call_user_func(\Composer\Autoload\ComposerStaticInitb2582f114b1248d5a20a7411671eea43::getInitializer($loader));
+            call_user_func(\Composer\Autoload\ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c::getInitializer($loader));
         } else {
             $map = require __DIR__ . '/autoload_namespaces.php';
             foreach ($map as $namespace => $path) {
@@ -52,19 +52,19 @@ class ComposerAutoloaderInitb2582f114b1248d5a20a7411671eea43
         $loader->register(true);
 
         if ($useStaticLoader) {
-            $includeFiles = Composer\Autoload\ComposerStaticInitb2582f114b1248d5a20a7411671eea43::$files;
+            $includeFiles = Composer\Autoload\ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c::$files;
         } else {
             $includeFiles = require __DIR__ . '/autoload_files.php';
         }
         foreach ($includeFiles as $fileIdentifier => $file) {
-            composerRequireb2582f114b1248d5a20a7411671eea43($fileIdentifier, $file);
+            composerRequireabd80a2472ebcf6a6e6e8989d45a577c($fileIdentifier, $file);
         }
 
         return $loader;
     }
 }
 
-function composerRequireb2582f114b1248d5a20a7411671eea43($fileIdentifier, $file)
+function composerRequireabd80a2472ebcf6a6e6e8989d45a577c($fileIdentifier, $file)
 {
     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
         require $file;
diff --git a/civicrm/vendor/composer/autoload_static.php b/civicrm/vendor/composer/autoload_static.php
index ea47737905..bad16bf434 100644
--- a/civicrm/vendor/composer/autoload_static.php
+++ b/civicrm/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
 
 namespace Composer\Autoload;
 
-class ComposerStaticInitb2582f114b1248d5a20a7411671eea43
+class ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c
 {
     public static $files = array (
         '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
@@ -56,6 +56,7 @@ class ComposerStaticInitb2582f114b1248d5a20a7411671eea43
             'Psr\\SimpleCache\\' => 16,
             'Psr\\Log\\' => 8,
             'Psr\\Http\\Message\\' => 17,
+            'Psr\\Container\\' => 14,
             'Psr\\Cache\\' => 10,
             'PhpOffice\\PhpWord\\' => 18,
             'PhpOffice\\Common\\' => 17,
@@ -163,6 +164,10 @@ class ComposerStaticInitb2582f114b1248d5a20a7411671eea43
         array (
             0 => __DIR__ . '/..' . '/psr/http-message/src',
         ),
+        'Psr\\Container\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/container/src',
+        ),
         'Psr\\Cache\\' => 
         array (
             0 => __DIR__ . '/..' . '/psr/cache/src',
@@ -266,10 +271,6 @@ class ComposerStaticInitb2582f114b1248d5a20a7411671eea43
             array (
                 0 => __DIR__ . '/../..' . '/packages',
             ),
-            'PEAR' => 
-            array (
-                0 => __DIR__ . '/..' . '/pear/pear_exception',
-            ),
         ),
         'N' => 
         array (
@@ -366,6 +367,7 @@ class ComposerStaticInitb2582f114b1248d5a20a7411671eea43
         'HTML5_TreeBuilder' => __DIR__ . '/..' . '/dompdf/dompdf/lib/html5lib/TreeBuilder.php',
         'ICallbackNamed' => __DIR__ . '/..' . '/electrolinux/phpquery/phpQuery/phpQuery/Callback.php',
         'PDF417' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/pdf417.php',
+        'PEAR_Exception' => __DIR__ . '/..' . '/pear/pear_exception/PEAR/Exception.php',
         'PclZip' => __DIR__ . '/..' . '/pclzip/pclzip/pclzip.lib.php',
         'QRcode' => __DIR__ . '/..' . '/tecnickcom/tcpdf/include/barcodes/qrcode.php',
         'TCPDF' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf.php',
@@ -495,11 +497,11 @@ class ComposerStaticInitb2582f114b1248d5a20a7411671eea43
     public static function getInitializer(ClassLoader $loader)
     {
         return \Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInitb2582f114b1248d5a20a7411671eea43::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInitb2582f114b1248d5a20a7411671eea43::$prefixDirsPsr4;
-            $loader->prefixesPsr0 = ComposerStaticInitb2582f114b1248d5a20a7411671eea43::$prefixesPsr0;
-            $loader->fallbackDirsPsr0 = ComposerStaticInitb2582f114b1248d5a20a7411671eea43::$fallbackDirsPsr0;
-            $loader->classMap = ComposerStaticInitb2582f114b1248d5a20a7411671eea43::$classMap;
+            $loader->prefixLengthsPsr4 = ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c::$prefixDirsPsr4;
+            $loader->prefixesPsr0 = ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c::$prefixesPsr0;
+            $loader->fallbackDirsPsr0 = ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c::$fallbackDirsPsr0;
+            $loader->classMap = ComposerStaticInitabd80a2472ebcf6a6e6e8989d45a577c::$classMap;
 
         }, null, ClassLoader::class);
     }
diff --git a/civicrm/vendor/composer/installed.json b/civicrm/vendor/composer/installed.json
index 3ff584c8a2..f335899ddd 100644
--- a/civicrm/vendor/composer/installed.json
+++ b/civicrm/vendor/composer/installed.json
@@ -917,21 +917,21 @@
     },
     {
         "name": "pear/log",
-        "version": "1.13.1",
-        "version_normalized": "1.13.1.0",
+        "version": "1.13.2",
+        "version_normalized": "1.13.2.0",
         "source": {
             "type": "git",
             "url": "https://github.com/pear/Log.git",
-            "reference": "c4be9ded2353c7c231d4c35cc3da75b209453803"
+            "reference": "d8cde3dba893a36ec561bf6188fdc39f4221c4d3"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/pear/Log/zipball/c4be9ded2353c7c231d4c35cc3da75b209453803",
-            "reference": "c4be9ded2353c7c231d4c35cc3da75b209453803",
+            "url": "https://api.github.com/repos/pear/Log/zipball/d8cde3dba893a36ec561bf6188fdc39f4221c4d3",
+            "reference": "d8cde3dba893a36ec561bf6188fdc39f4221c4d3",
             "shasum": ""
         },
         "require": {
-            "pear/pear_exception": "1.0.0",
+            "pear/pear_exception": "1.0.1",
             "php": ">5.2"
         },
         "require-dev": {
@@ -940,7 +940,7 @@
         "suggest": {
             "pear/db": "Install optionally via your project's composer.json"
         },
-        "time": "2016-04-16T00:49:33+00:00",
+        "time": "2020-06-02T00:04:03+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
@@ -1205,17 +1205,17 @@
     },
     {
         "name": "pear/pear_exception",
-        "version": "v1.0.0",
-        "version_normalized": "1.0.0.0",
+        "version": "v1.0.1",
+        "version_normalized": "1.0.1.0",
         "source": {
             "type": "git",
             "url": "https://github.com/pear/PEAR_Exception.git",
-            "reference": "8c18719fdae000b690e3912be401c76e406dd13b"
+            "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/8c18719fdae000b690e3912be401c76e406dd13b",
-            "reference": "8c18719fdae000b690e3912be401c76e406dd13b",
+            "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
+            "reference": "dbb42a5a0e45f3adcf99babfb2a1ba77b8ac36a7",
             "shasum": ""
         },
         "require": {
@@ -1224,7 +1224,7 @@
         "require-dev": {
             "phpunit/phpunit": "*"
         },
-        "time": "2015-02-10T20:07:52+00:00",
+        "time": "2019-12-10T10:24:42+00:00",
         "type": "class",
         "extra": {
             "branch-alias": {
@@ -1233,9 +1233,9 @@
         },
         "installation-source": "dist",
         "autoload": {
-            "psr-0": {
-                "PEAR": ""
-            }
+            "classmap": [
+                "PEAR/"
+            ]
         },
         "notification-url": "https://packagist.org/downloads/",
         "include-path": [
@@ -1712,6 +1712,57 @@
             "psr-6"
         ]
     },
+    {
+        "name": "psr/container",
+        "version": "1.0.0",
+        "version_normalized": "1.0.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/php-fig/container.git",
+            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+            "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "time": "2017-02-14T16:28:37+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "1.0.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-4": {
+                "Psr\\Container\\": "src/"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/",
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "PHP-FIG",
+                "homepage": "http://www.php-fig.org/"
+            }
+        ],
+        "description": "Common Container Interface (PHP FIG PSR-11)",
+        "homepage": "https://github.com/php-fig/container",
+        "keywords": [
+            "PSR-11",
+            "container",
+            "container-interface",
+            "container-interop",
+            "psr"
+        ]
+    },
     {
         "name": "psr/http-message",
         "version": "1.0.1",
@@ -1912,35 +1963,42 @@
     },
     {
         "name": "symfony/config",
-        "version": "v2.8.50",
-        "version_normalized": "2.8.50.0",
+        "version": "v3.4.40",
+        "version_normalized": "3.4.40.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/config.git",
-            "reference": "7dd5f5040dc04c118d057fb5886563963eb70011"
+            "reference": "3634991bea549e73c45a964c38f30ceeae6ed877"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/config/zipball/7dd5f5040dc04c118d057fb5886563963eb70011",
-            "reference": "7dd5f5040dc04c118d057fb5886563963eb70011",
+            "url": "https://api.github.com/repos/symfony/config/zipball/3634991bea549e73c45a964c38f30ceeae6ed877",
+            "reference": "3634991bea549e73c45a964c38f30ceeae6ed877",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.9",
-            "symfony/filesystem": "~2.3|~3.0.0",
+            "php": "^5.5.9|>=7.0.8",
+            "symfony/filesystem": "~2.8|~3.0|~4.0",
             "symfony/polyfill-ctype": "~1.8"
         },
+        "conflict": {
+            "symfony/dependency-injection": "<3.3",
+            "symfony/finder": "<3.3"
+        },
         "require-dev": {
-            "symfony/yaml": "~2.7|~3.0.0"
+            "symfony/dependency-injection": "~3.3|~4.0",
+            "symfony/event-dispatcher": "~3.3|~4.0",
+            "symfony/finder": "~3.3|~4.0",
+            "symfony/yaml": "~3.0|~4.0"
         },
         "suggest": {
             "symfony/yaml": "To use the yaml reference dumper"
         },
-        "time": "2018-11-26T09:38:12+00:00",
+        "time": "2020-04-12T14:33:46+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "2.8-dev"
+                "dev-master": "3.4-dev"
             }
         },
         "installation-source": "dist",
@@ -1971,41 +2029,49 @@
     },
     {
         "name": "symfony/dependency-injection",
-        "version": "v2.8.50",
-        "version_normalized": "2.8.50.0",
+        "version": "v3.4.40",
+        "version_normalized": "3.4.40.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/dependency-injection.git",
-            "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8"
+            "reference": "d10ff5503b0b27711087eef4ac7835a752fe42fd"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c306198fee8f872a8f5f031e6e4f6f83086992d8",
-            "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8",
+            "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d10ff5503b0b27711087eef4ac7835a752fe42fd",
+            "reference": "d10ff5503b0b27711087eef4ac7835a752fe42fd",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.9"
+            "php": "^5.5.9|>=7.0.8",
+            "psr/container": "^1.0"
         },
         "conflict": {
-            "symfony/expression-language": "<2.6"
+            "symfony/config": "<3.3.7",
+            "symfony/finder": "<3.3",
+            "symfony/proxy-manager-bridge": "<3.4",
+            "symfony/yaml": "<3.4"
+        },
+        "provide": {
+            "psr/container-implementation": "1.0"
         },
         "require-dev": {
-            "symfony/config": "~2.2|~3.0.0",
-            "symfony/expression-language": "~2.6|~3.0.0",
-            "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7"
+            "symfony/config": "~3.3|~4.0",
+            "symfony/expression-language": "~2.8|~3.0|~4.0",
+            "symfony/yaml": "~3.4|~4.0"
         },
         "suggest": {
             "symfony/config": "",
             "symfony/expression-language": "For using expressions in service container configuration",
+            "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required",
             "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
             "symfony/yaml": ""
         },
-        "time": "2019-04-16T11:33:46+00:00",
+        "time": "2020-04-13T09:33:40+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "2.8-dev"
+                "dev-master": "3.4-dev"
             }
         },
         "installation-source": "dist",
@@ -2036,38 +2102,41 @@
     },
     {
         "name": "symfony/event-dispatcher",
-        "version": "v2.8.50",
-        "version_normalized": "2.8.50.0",
+        "version": "v3.4.40",
+        "version_normalized": "3.4.40.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/event-dispatcher.git",
-            "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0"
+            "reference": "9d4e22943b73acc1ba50595b7de1a01fe9dbad48"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0",
-            "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0",
+            "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9d4e22943b73acc1ba50595b7de1a01fe9dbad48",
+            "reference": "9d4e22943b73acc1ba50595b7de1a01fe9dbad48",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.9"
+            "php": "^5.5.9|>=7.0.8"
+        },
+        "conflict": {
+            "symfony/dependency-injection": "<3.3"
         },
         "require-dev": {
             "psr/log": "~1.0",
-            "symfony/config": "^2.0.5|~3.0.0",
-            "symfony/dependency-injection": "~2.6|~3.0.0",
-            "symfony/expression-language": "~2.6|~3.0.0",
-            "symfony/stopwatch": "~2.3|~3.0.0"
+            "symfony/config": "~2.8|~3.0|~4.0",
+            "symfony/dependency-injection": "~3.3|~4.0",
+            "symfony/expression-language": "~2.8|~3.0|~4.0",
+            "symfony/stopwatch": "~2.8|~3.0|~4.0"
         },
         "suggest": {
             "symfony/dependency-injection": "",
             "symfony/http-kernel": ""
         },
-        "time": "2018-11-21T14:20:20+00:00",
+        "time": "2020-03-15T09:38:08+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "2.8-dev"
+                "dev-master": "3.4-dev"
             }
         },
         "installation-source": "dist",
@@ -2098,28 +2167,28 @@
     },
     {
         "name": "symfony/filesystem",
-        "version": "v2.8.50",
-        "version_normalized": "2.8.50.0",
+        "version": "v3.4.40",
+        "version_normalized": "3.4.40.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/filesystem.git",
-            "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080"
+            "reference": "78a93e5606a19d0fb490afc3c4a9b7ecd86e1515"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/filesystem/zipball/7ae46872dad09dffb7fe1e93a0937097339d0080",
-            "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080",
+            "url": "https://api.github.com/repos/symfony/filesystem/zipball/78a93e5606a19d0fb490afc3c4a9b7ecd86e1515",
+            "reference": "78a93e5606a19d0fb490afc3c4a9b7ecd86e1515",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.9",
+            "php": "^5.5.9|>=7.0.8",
             "symfony/polyfill-ctype": "~1.8"
         },
-        "time": "2018-11-11T11:18:13+00:00",
+        "time": "2020-04-12T16:54:01+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "2.8-dev"
+                "dev-master": "3.4-dev"
             }
         },
         "installation-source": "dist",
@@ -2150,27 +2219,27 @@
     },
     {
         "name": "symfony/finder",
-        "version": "v2.8.50",
-        "version_normalized": "2.8.50.0",
+        "version": "v3.4.40",
+        "version_normalized": "3.4.40.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/finder.git",
-            "reference": "1444eac52273e345d9b95129bf914639305a9ba4"
+            "reference": "5ec813ccafa8164ef21757e8c725d3a57da59200"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/finder/zipball/1444eac52273e345d9b95129bf914639305a9ba4",
-            "reference": "1444eac52273e345d9b95129bf914639305a9ba4",
+            "url": "https://api.github.com/repos/symfony/finder/zipball/5ec813ccafa8164ef21757e8c725d3a57da59200",
+            "reference": "5ec813ccafa8164ef21757e8c725d3a57da59200",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.9"
+            "php": "^5.5.9|>=7.0.8"
         },
-        "time": "2018-11-11T11:18:13+00:00",
+        "time": "2020-02-14T07:34:21+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "2.8-dev"
+                "dev-master": "3.4-dev"
             }
         },
         "installation-source": "dist",
@@ -2201,17 +2270,17 @@
     },
     {
         "name": "symfony/polyfill-ctype",
-        "version": "v1.12.0",
-        "version_normalized": "1.12.0.0",
+        "version": "v1.17.0",
+        "version_normalized": "1.17.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/polyfill-ctype.git",
-            "reference": "550ebaac289296ce228a706d0867afc34687e3f4"
+            "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
-            "reference": "550ebaac289296ce228a706d0867afc34687e3f4",
+            "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
+            "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
             "shasum": ""
         },
         "require": {
@@ -2220,11 +2289,11 @@
         "suggest": {
             "ext-ctype": "For best performance"
         },
-        "time": "2019-08-06T08:03:45+00:00",
+        "time": "2020-05-12T16:14:59+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.12-dev"
+                "dev-master": "1.17-dev"
             }
         },
         "installation-source": "dist",
@@ -2261,17 +2330,17 @@
     },
     {
         "name": "symfony/polyfill-iconv",
-        "version": "v1.12.0",
-        "version_normalized": "1.12.0.0",
+        "version": "v1.17.0",
+        "version_normalized": "1.17.0.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/polyfill-iconv.git",
-            "reference": "685968b11e61a347c18bf25db32effa478be610f"
+            "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/685968b11e61a347c18bf25db32effa478be610f",
-            "reference": "685968b11e61a347c18bf25db32effa478be610f",
+            "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/c4de7601eefbf25f9d47190abe07f79fe0a27424",
+            "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424",
             "shasum": ""
         },
         "require": {
@@ -2280,11 +2349,11 @@
         "suggest": {
             "ext-iconv": "For best performance"
         },
-        "time": "2019-08-06T08:03:45+00:00",
+        "time": "2020-05-12T16:47:27+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "1.12-dev"
+                "dev-master": "1.17-dev"
             }
         },
         "installation-source": "dist",
@@ -2322,27 +2391,27 @@
     },
     {
         "name": "symfony/process",
-        "version": "v2.8.50",
-        "version_normalized": "2.8.50.0",
+        "version": "v3.4.40",
+        "version_normalized": "3.4.40.0",
         "source": {
             "type": "git",
             "url": "https://github.com/symfony/process.git",
-            "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8"
+            "reference": "f5104c9dcbc2cfad45d01d5150c1da9836967271"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/symfony/process/zipball/c3591a09c78639822b0b290d44edb69bf9f05dc8",
-            "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8",
+            "url": "https://api.github.com/repos/symfony/process/zipball/f5104c9dcbc2cfad45d01d5150c1da9836967271",
+            "reference": "f5104c9dcbc2cfad45d01d5150c1da9836967271",
             "shasum": ""
         },
         "require": {
-            "php": ">=5.3.9"
+            "php": "^5.5.9|>=7.0.8"
         },
-        "time": "2018-11-11T11:18:13+00:00",
+        "time": "2020-04-12T14:33:46+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
-                "dev-master": "2.8-dev"
+                "dev-master": "3.4-dev"
             }
         },
         "installation-source": "dist",
diff --git a/civicrm/vendor/pear/log/.travis.yml b/civicrm/vendor/pear/log/.travis.yml
index 92ccd8c1bb..1aa5a70287 100644
--- a/civicrm/vendor/pear/log/.travis.yml
+++ b/civicrm/vendor/pear/log/.travis.yml
@@ -1,10 +1,20 @@
 language: php
-php:
-  - 5.4
-  - 5.5
-  - 5.6
-  - 7.0
-  - nightly
+matrix:
+  fast_finish: true
+  allow_failures:
+    - php: nightly
+  include:
+  - php: 5.4
+    dist: trusty
+  - php: 5.5
+    dist: trusty
+  - php: 5.6
+  - php: 7.0
+  - php: 7.1
+  - php: 7.2
+  - php: 7.3
+  - php: 7.4
+  - php: nightly
 install:
   - pear install package.xml
 script: pear run-tests tests/
diff --git a/civicrm/vendor/pear/log/composer.json b/civicrm/vendor/pear/log/composer.json
index 87378215a9..d7c0db084f 100644
--- a/civicrm/vendor/pear/log/composer.json
+++ b/civicrm/vendor/pear/log/composer.json
@@ -9,7 +9,7 @@
     "license": "MIT",
     "require": {
         "php": ">5.2",
-        "pear/pear_exception": "1.0.0"
+        "pear/pear_exception": "1.0.1"
     },
     "autoload": {
         "psr-0": {
diff --git a/civicrm/vendor/pear/log/package.xml b/civicrm/vendor/pear/log/package.xml
index 55fca68dbf..6a84b53bc0 100644
--- a/civicrm/vendor/pear/log/package.xml
+++ b/civicrm/vendor/pear/log/package.xml
@@ -25,10 +25,10 @@
   <email>jan@horde.org</email>
   <active>yes</active>
  </lead>
- <date>2016-04-16</date>
+ <date>2020-06-02</date>
  <time>00:00:00</time>
  <version>
-  <release>1.13.1</release>
+  <release>1.13.2</release>
   <api>1.0.0</api>
  </version>
  <stability>
@@ -37,7 +37,7 @@
  </stability>
  <license uri="http://www.opensource.org/licenses/mit-license.php">MIT License</license>
  <notes>
-Use rand() to make instance identifiers more unique than microtime()'s resolution.
+Bump pear/pear_exception dependency to version to 1.0.1.
  </notes>
  <contents>
   <dir baseinstalldir="/" name="/">
@@ -139,6 +139,21 @@ Use rand() to make instance identifiers more unique than microtime()'s resolutio
  </dependencies>
  <phprelease />
  <changelog>
+  <release>
+   <version>
+    <release>1.13.1</release>
+    <api>1.0.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2016-04-16</date>
+   <license uri="http://www.opensource.org/licenses/mit-license.php">MIT License</license>
+   <notes>
+Use rand() to make instance identifiers more unique than microtime()'s resolution.
+   </notes>
+  </release>
   <release>
    <version>
     <release>1.13.0</release>
diff --git a/civicrm/vendor/pear/log/phpdoc.sh b/civicrm/vendor/pear/log/phpdoc.sh
deleted file mode 100755
index f0d45a4577..0000000000
--- a/civicrm/vendor/pear/log/phpdoc.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-phpdoc -f Log.php -d Log -t docs/api -p -ti "Log Package API" -dn Log -dc Log -ed examples -i CVS/*
diff --git a/civicrm/vendor/pear/pear_exception/composer.json b/civicrm/vendor/pear/pear_exception/composer.json
index ce33ed1c80..b923cf7181 100644
--- a/civicrm/vendor/pear/pear_exception/composer.json
+++ b/civicrm/vendor/pear/pear_exception/composer.json
@@ -21,9 +21,7 @@
         "php": ">=4.4.0"
     },
     "autoload": {
-        "psr-0": {
-            "PEAR": ""
-        }
+        "classmap": ["PEAR/"]
     },
     "extra": {
         "branch-alias": {
diff --git a/civicrm/vendor/psr/container/.gitignore b/civicrm/vendor/psr/container/.gitignore
new file mode 100644
index 0000000000..b2395aa055
--- /dev/null
+++ b/civicrm/vendor/psr/container/.gitignore
@@ -0,0 +1,3 @@
+composer.lock
+composer.phar
+/vendor/
diff --git a/civicrm/vendor/psr/container/LICENSE b/civicrm/vendor/psr/container/LICENSE
new file mode 100644
index 0000000000..2877a4894e
--- /dev/null
+++ b/civicrm/vendor/psr/container/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2016 container-interop
+Copyright (c) 2016 PHP Framework Interoperability Group
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/civicrm/vendor/psr/container/README.md b/civicrm/vendor/psr/container/README.md
new file mode 100644
index 0000000000..084f6df51b
--- /dev/null
+++ b/civicrm/vendor/psr/container/README.md
@@ -0,0 +1,5 @@
+# PSR Container
+
+This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md).
+
+Note that this is not a container implementation of its own. See the specification for more details.
diff --git a/civicrm/vendor/psr/container/composer.json b/civicrm/vendor/psr/container/composer.json
new file mode 100644
index 0000000000..b8ee01265d
--- /dev/null
+++ b/civicrm/vendor/psr/container/composer.json
@@ -0,0 +1,27 @@
+{
+    "name": "psr/container",
+    "type": "library",
+    "description": "Common Container Interface (PHP FIG PSR-11)",
+    "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
+    "homepage": "https://github.com/php-fig/container",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "PHP-FIG",
+            "homepage": "http://www.php-fig.org/"
+        }
+    ],
+    "require": {
+        "php": ">=5.3.0"
+    },
+    "autoload": {
+        "psr-4": {
+            "Psr\\Container\\": "src/"
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.0.x-dev"
+        }
+    }
+}
diff --git a/civicrm/vendor/psr/container/src/ContainerExceptionInterface.php b/civicrm/vendor/psr/container/src/ContainerExceptionInterface.php
new file mode 100644
index 0000000000..d35c6b4d86
--- /dev/null
+++ b/civicrm/vendor/psr/container/src/ContainerExceptionInterface.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Psr\Container;
+
+/**
+ * Base interface representing a generic exception in a container.
+ */
+interface ContainerExceptionInterface
+{
+}
diff --git a/civicrm/vendor/psr/container/src/ContainerInterface.php b/civicrm/vendor/psr/container/src/ContainerInterface.php
new file mode 100644
index 0000000000..c3a7206fa0
--- /dev/null
+++ b/civicrm/vendor/psr/container/src/ContainerInterface.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Psr\Container;
+
+/**
+ * Describes the interface of a container that exposes methods to read its entries.
+ */
+interface ContainerInterface
+{
+    /**
+     * Finds an entry of the container by its identifier and returns it.
+     *
+     * @param string $id Identifier of the entry to look for.
+     *
+     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
+     * @throws ContainerExceptionInterface Error while retrieving the entry.
+     *
+     * @return mixed Entry.
+     */
+    public function get($id);
+
+    /**
+     * Returns true if the container can return an entry for the given identifier.
+     * Returns false otherwise.
+     *
+     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
+     * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
+     *
+     * @param string $id Identifier of the entry to look for.
+     *
+     * @return bool
+     */
+    public function has($id);
+}
diff --git a/civicrm/vendor/psr/container/src/NotFoundExceptionInterface.php b/civicrm/vendor/psr/container/src/NotFoundExceptionInterface.php
new file mode 100644
index 0000000000..6566704eda
--- /dev/null
+++ b/civicrm/vendor/psr/container/src/NotFoundExceptionInterface.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
+ */
+
+namespace Psr\Container;
+
+/**
+ * No entry was found in the container.
+ */
+interface NotFoundExceptionInterface extends ContainerExceptionInterface
+{
+}
diff --git a/civicrm/vendor/symfony/config/CHANGELOG.md b/civicrm/vendor/symfony/config/CHANGELOG.md
index 65b602e713..6cb610c478 100644
--- a/civicrm/vendor/symfony/config/CHANGELOG.md
+++ b/civicrm/vendor/symfony/config/CHANGELOG.md
@@ -1,6 +1,30 @@
 CHANGELOG
 =========
 
+3.4.0
+-----
+
+ * added `setDeprecated()` method to indicate a deprecated node
+ * added `XmlUtils::parse()` method to parse an XML string
+ * deprecated `ConfigCachePass`
+
+3.3.0
+-----
+
+ * added `ReflectionClassResource` class
+ * added second `$exists` constructor argument to `ClassExistenceResource`
+ * made `ClassExistenceResource` work with interfaces and traits
+ * added `ConfigCachePass` (originally in FrameworkBundle)
+ * added `castToArray()` helper to turn any config value into an array
+
+3.0.0
+-----
+
+ * removed `ReferenceDumper` class
+ * removed the `ResourceInterface::isFresh()` method
+ * removed `BCResourceInterfaceChecker` class
+ * removed `ResourceInterface::getResource()` method
+
 2.8.0
 -----
 
@@ -10,7 +34,7 @@ The edge case of defining just one value for nodes of type Enum is now allowed:
 $rootNode
     ->children()
         ->enumNode('variable')
-            ->values(array('value'))
+            ->values(['value'])
         ->end()
     ->end()
 ;
@@ -20,7 +44,7 @@ Before: `InvalidArgumentException` (variable must contain at least two
 distinct elements).
 After: the code will work as expected and it will restrict the values of the
 `variable` option to just `value`.
- 
+
  * deprecated the `ResourceInterface::isFresh()` method. If you implement custom resource types and they
    can be validated that way, make them implement the new `SelfCheckingResourceInterface`.
  * deprecated the getResource() method in ResourceInterface. You can still call this method
@@ -37,12 +61,12 @@ After: the code will work as expected and it will restrict the values of the
 2.2.0
 -----
 
- * added ArrayNodeDefinition::canBeEnabled() and ArrayNodeDefinition::canBeDisabled()
+ * added `ArrayNodeDefinition::canBeEnabled()` and `ArrayNodeDefinition::canBeDisabled()`
    to ease configuration when some sections are respectively disabled / enabled
    by default.
  * added a `normalizeKeys()` method for array nodes (to avoid key normalization)
  * added numerical type handling for config definitions
- * added convenience methods for optional configuration sections to ArrayNodeDefinition
+ * added convenience methods for optional configuration sections to `ArrayNodeDefinition`
  * added a utils class for XML manipulations
 
 2.1.0
@@ -50,5 +74,5 @@ After: the code will work as expected and it will restrict the values of the
 
  * added a way to add documentation on configuration
  * implemented `Serializable` on resources
- * LoaderResolverInterface is now used instead of LoaderResolver for type
+ * `LoaderResolverInterface` is now used instead of `LoaderResolver` for type
    hinting
diff --git a/civicrm/vendor/symfony/config/ConfigCache.php b/civicrm/vendor/symfony/config/ConfigCache.php
index 016e014b6c..b2a39076f9 100644
--- a/civicrm/vendor/symfony/config/ConfigCache.php
+++ b/civicrm/vendor/symfony/config/ConfigCache.php
@@ -11,7 +11,6 @@
 
 namespace Symfony\Component\Config;
 
-use Symfony\Component\Config\Resource\BCResourceInterfaceChecker;
 use Symfony\Component\Config\Resource\SelfCheckingResourceChecker;
 
 /**
@@ -21,11 +20,6 @@ use Symfony\Component\Config\Resource\SelfCheckingResourceChecker;
  * \Symfony\Component\Config\Resource\SelfCheckingResourceInterface will
  * be used to check cache freshness.
  *
- * During a transition period, also instances of
- * \Symfony\Component\Config\Resource\ResourceInterface will be checked
- * by means of the isFresh() method. This behaviour is deprecated since 2.8
- * and will be removed in 3.0.
- *
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Matthias Pigulla <mp@webfactory.de>
  */
@@ -39,25 +33,14 @@ class ConfigCache extends ResourceCheckerConfigCache
      */
     public function __construct($file, $debug)
     {
-        parent::__construct($file, array(
-            new SelfCheckingResourceChecker(),
-            new BCResourceInterfaceChecker(),
-        ));
         $this->debug = (bool) $debug;
-    }
 
-    /**
-     * Gets the cache file path.
-     *
-     * @return string The cache file path
-     *
-     * @deprecated since 2.7, to be removed in 3.0. Use getPath() instead.
-     */
-    public function __toString()
-    {
-        @trigger_error('ConfigCache::__toString() is deprecated since Symfony 2.7 and will be removed in 3.0. Use the getPath() method instead.', E_USER_DEPRECATED);
+        $checkers = [];
+        if (true === $this->debug) {
+            $checkers = [new SelfCheckingResourceChecker()];
+        }
 
-        return $this->getPath();
+        parent::__construct($file, $checkers);
     }
 
     /**
diff --git a/civicrm/vendor/symfony/config/Definition/ArrayNode.php b/civicrm/vendor/symfony/config/Definition/ArrayNode.php
index 86eacae40b..83bab205ec 100644
--- a/civicrm/vendor/symfony/config/Definition/ArrayNode.php
+++ b/civicrm/vendor/symfony/config/Definition/ArrayNode.php
@@ -22,8 +22,8 @@ use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
  */
 class ArrayNode extends BaseNode implements PrototypeNodeInterface
 {
-    protected $xmlRemappings = array();
-    protected $children = array();
+    protected $xmlRemappings = [];
+    protected $children = [];
     protected $allowFalse = false;
     protected $allowNewKeys = true;
     protected $addIfNotSet = false;
@@ -38,17 +38,13 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
     }
 
     /**
-     * Normalizes keys between the different configuration formats.
+     * {@inheritdoc}
      *
      * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
      * After running this method, all keys are normalized to foo_bar.
      *
      * If you have a mixed key like foo-bar_moo, it will not be altered.
      * The key will also not be altered if the target key already exists.
-     *
-     * @param mixed $value
-     *
-     * @return array The value with normalized keys
      */
     protected function preNormalize($value)
     {
@@ -56,10 +52,10 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
             return $value;
         }
 
-        $normalized = array();
+        $normalized = [];
 
         foreach ($value as $k => $v) {
-            if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
+            if (false !== strpos($k, '-') && false === strpos($k, '_') && !\array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
                 $normalized[$normalizedKey] = $v;
             } else {
                 $normalized[$k] = $v;
@@ -82,7 +78,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
     /**
      * Sets the xml remappings that should be performed.
      *
-     * @param array $remappings An array of the form array(array(string, string))
+     * @param array $remappings An array of the form [[string, string]]
      */
     public function setXmlRemappings(array $remappings)
     {
@@ -92,7 +88,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
     /**
      * Gets the xml remappings that should be performed.
      *
-     * @return array an array of the form array(array(string, string))
+     * @return array an array of the form [[string, string]]
      */
     public function getXmlRemappings()
     {
@@ -141,7 +137,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
     }
 
     /**
-     * Whether extra keys should just be ignore without an exception.
+     * Whether extra keys should just be ignored without an exception.
      *
      * @param bool $boolean To allow extra keys
      * @param bool $remove  To remove extra keys
@@ -177,7 +173,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
             throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath()));
         }
 
-        $defaults = array();
+        $defaults = [];
         foreach ($this->children as $name => $child) {
             if ($child->hasDefaultValue()) {
                 $defaults[$name] = $child->getDefaultValue();
@@ -219,11 +215,11 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
     protected function finalizeValue($value)
     {
         if (false === $value) {
-            throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)));
+            throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: "%s".', $this->getPath(), json_encode($value)));
         }
 
         foreach ($this->children as $name => $child) {
-            if (!array_key_exists($name, $value)) {
+            if (!\array_key_exists($name, $value)) {
                 if ($child->isRequired()) {
                     $ex = new InvalidConfigurationException(sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()));
                     $ex->setPath($this->getPath());
@@ -238,6 +234,10 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
                 continue;
             }
 
+            if ($child->isDeprecated()) {
+                @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED);
+            }
+
             try {
                 $value[$name] = $child->finalize($value[$name]);
             } catch (UnsetKeyException $e) {
@@ -285,7 +285,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
 
         $value = $this->remapXml($value);
 
-        $normalized = array();
+        $normalized = [];
         foreach ($value as $name => $val) {
             if (isset($this->children[$name])) {
                 try {
@@ -318,9 +318,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
      */
     protected function remapXml($value)
     {
-        foreach ($this->xmlRemappings as $transformation) {
-            list($singular, $plural) = $transformation;
-
+        foreach ($this->xmlRemappings as list($singular, $plural)) {
             if (!isset($value[$singular])) {
                 continue;
             }
@@ -357,7 +355,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
 
         foreach ($rightSide as $k => $v) {
             // no conflict
-            if (!array_key_exists($k, $leftSide)) {
+            if (!\array_key_exists($k, $leftSide)) {
                 if (!$this->allowNewKeys) {
                     $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file. If you are trying to overwrite an element, make sure you redefine it with the same name.', $this->getPath()));
                     $ex->setPath($this->getPath());
diff --git a/civicrm/vendor/symfony/config/Definition/BaseNode.php b/civicrm/vendor/symfony/config/Definition/BaseNode.php
index 7ca956e211..1f6ef7f834 100644
--- a/civicrm/vendor/symfony/config/Definition/BaseNode.php
+++ b/civicrm/vendor/symfony/config/Definition/BaseNode.php
@@ -25,12 +25,13 @@ abstract class BaseNode implements NodeInterface
 {
     protected $name;
     protected $parent;
-    protected $normalizationClosures = array();
-    protected $finalValidationClosures = array();
+    protected $normalizationClosures = [];
+    protected $finalValidationClosures = [];
     protected $allowOverwrite = true;
     protected $required = false;
-    protected $equivalentValues = array();
-    protected $attributes = array();
+    protected $deprecationMessage = null;
+    protected $equivalentValues = [];
+    protected $attributes = [];
 
     /**
      * @param string|null        $name   The name of the node
@@ -48,21 +49,37 @@ abstract class BaseNode implements NodeInterface
         $this->parent = $parent;
     }
 
+    /**
+     * @param string $key
+     */
     public function setAttribute($key, $value)
     {
         $this->attributes[$key] = $value;
     }
 
+    /**
+     * @param string $key
+     *
+     * @return mixed
+     */
     public function getAttribute($key, $default = null)
     {
         return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
     }
 
+    /**
+     * @param string $key
+     *
+     * @return bool
+     */
     public function hasAttribute($key)
     {
         return isset($this->attributes[$key]);
     }
 
+    /**
+     * @return array
+     */
     public function getAttributes()
     {
         return $this->attributes;
@@ -73,6 +90,9 @@ abstract class BaseNode implements NodeInterface
         $this->attributes = $attributes;
     }
 
+    /**
+     * @param string $key
+     */
     public function removeAttribute($key)
     {
         unset($this->attributes[$key]);
@@ -91,7 +111,7 @@ abstract class BaseNode implements NodeInterface
     /**
      * Returns info message.
      *
-     * @return string The info text
+     * @return string|null The info text
      */
     public function getInfo()
     {
@@ -111,7 +131,7 @@ abstract class BaseNode implements NodeInterface
     /**
      * Retrieves the example configuration for this node.
      *
-     * @return string|array The example
+     * @return string|array|null The example
      */
     public function getExample()
     {
@@ -126,7 +146,7 @@ abstract class BaseNode implements NodeInterface
      */
     public function addEquivalentValue($originalValue, $equivalentValue)
     {
-        $this->equivalentValues[] = array($originalValue, $equivalentValue);
+        $this->equivalentValues[] = [$originalValue, $equivalentValue];
     }
 
     /**
@@ -139,6 +159,19 @@ abstract class BaseNode implements NodeInterface
         $this->required = (bool) $boolean;
     }
 
+    /**
+     * Sets this node as deprecated.
+     *
+     * You can use %node% and %path% placeholders in your message to display,
+     * respectively, the node name and its complete path.
+     *
+     * @param string|null $message Deprecated message
+     */
+    public function setDeprecated($message)
+    {
+        $this->deprecationMessage = $message;
+    }
+
     /**
      * Sets if this node can be overridden.
      *
@@ -177,6 +210,29 @@ abstract class BaseNode implements NodeInterface
         return $this->required;
     }
 
+    /**
+     * Checks if this node is deprecated.
+     *
+     * @return bool
+     */
+    public function isDeprecated()
+    {
+        return null !== $this->deprecationMessage;
+    }
+
+    /**
+     * Returns the deprecated message.
+     *
+     * @param string $node the configuration node name
+     * @param string $path the path of the node
+     *
+     * @return string
+     */
+    public function getDeprecationMessage($node, $path)
+    {
+        return strtr($this->deprecationMessage, ['%node%' => $node, '%path%' => $path]);
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -243,9 +299,9 @@ abstract class BaseNode implements NodeInterface
     /**
      * Normalizes the value before any other normalization is applied.
      *
-     * @param $value
+     * @param mixed $value
      *
-     * @return The normalized array value
+     * @return mixed The normalized array value
      */
     protected function preNormalize($value)
     {
@@ -279,7 +335,7 @@ abstract class BaseNode implements NodeInterface
             } catch (Exception $e) {
                 throw $e;
             } catch (\Exception $e) {
-                throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e);
+                throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": '.$e->getMessage(), $this->getPath()), $e->getCode(), $e);
             }
         }
 
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php b/civicrm/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php
index 31e918af1c..29d1e154fc 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php
@@ -25,7 +25,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
     protected $performDeepMerging = true;
     protected $ignoreExtraKeys = false;
     protected $removeExtraKeys = true;
-    protected $children = array();
+    protected $children = [];
     protected $prototype;
     protected $atLeastOne = false;
     protected $allowNewKeys = true;
@@ -43,8 +43,8 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
     {
         parent::__construct($name, $parent);
 
-        $this->nullEquivalent = array();
-        $this->trueEquivalent = array();
+        $this->nullEquivalent = [];
+        $this->trueEquivalent = [];
     }
 
     /**
@@ -75,6 +75,62 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
         return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
     }
 
+    /**
+     * @return VariableNodeDefinition
+     */
+    public function variablePrototype()
+    {
+        return $this->prototype('variable');
+    }
+
+    /**
+     * @return ScalarNodeDefinition
+     */
+    public function scalarPrototype()
+    {
+        return $this->prototype('scalar');
+    }
+
+    /**
+     * @return BooleanNodeDefinition
+     */
+    public function booleanPrototype()
+    {
+        return $this->prototype('boolean');
+    }
+
+    /**
+     * @return IntegerNodeDefinition
+     */
+    public function integerPrototype()
+    {
+        return $this->prototype('integer');
+    }
+
+    /**
+     * @return FloatNodeDefinition
+     */
+    public function floatPrototype()
+    {
+        return $this->prototype('float');
+    }
+
+    /**
+     * @return ArrayNodeDefinition
+     */
+    public function arrayPrototype()
+    {
+        return $this->prototype('array');
+    }
+
+    /**
+     * @return EnumNodeDefinition
+     */
+    public function enumPrototype()
+    {
+        return $this->prototype('enum');
+    }
+
     /**
      * Adds the default value if the node is not set in the configuration.
      *
@@ -158,15 +214,15 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
      * to be the key of the particular item. For example, if "id" is the
      * "key", then:
      *
-     *     array(
-     *         array('id' => 'my_name', 'foo' => 'bar'),
-     *     );
+     *     [
+     *         ['id' => 'my_name', 'foo' => 'bar'],
+     *     ];
      *
      *   becomes
      *
-     *     array(
-     *         'my_name' => array('foo' => 'bar'),
-     *     );
+     *     [
+     *         'my_name' => ['foo' => 'bar'],
+     *     ];
      *
      * If you'd like "'id' => 'my_name'" to still be present in the resulting
      * array, then you can set the second argument of this method to false.
@@ -219,9 +275,9 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
     {
         $this
             ->addDefaultsIfNotSet()
-            ->treatFalseLike(array('enabled' => false))
-            ->treatTrueLike(array('enabled' => true))
-            ->treatNullLike(array('enabled' => true))
+            ->treatFalseLike(['enabled' => false])
+            ->treatTrueLike(['enabled' => true])
+            ->treatNullLike(['enabled' => true])
             ->beforeNormalization()
                 ->ifArray()
                 ->then(function ($v) {
@@ -249,9 +305,9 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
     {
         $this
             ->addDefaultsIfNotSet()
-            ->treatFalseLike(array('enabled' => false))
-            ->treatTrueLike(array('enabled' => true))
-            ->treatNullLike(array('enabled' => true))
+            ->treatFalseLike(['enabled' => false])
+            ->treatTrueLike(['enabled' => true])
+            ->treatNullLike(['enabled' => true])
             ->children()
                 ->booleanNode('enabled')
                     ->defaultTrue()
@@ -276,10 +332,10 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
      * Allows extra config keys to be specified under an array without
      * throwing an exception.
      *
-     * Those config values are simply ignored and removed from the
-     * resulting array. This should be used only in special cases where
-     * you want to send an entire configuration array through a special
-     * tree that processes only part of the array.
+     * Those config values are ignored and removed from the resulting
+     * array. This should be used only in special cases where you want
+     * to send an entire configuration array through a special tree that
+     * processes only part of the array.
      *
      * @param bool $remove Whether to remove the extra keys
      *
@@ -356,6 +412,10 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
                 $node->setKeyAttribute($this->key, $this->removeKeyItem);
             }
 
+            if (false === $this->allowEmptyValue) {
+                @trigger_error(sprintf('Using %s::cannotBeEmpty() at path "%s" has no effect, consider requiresAtLeastOneElement() instead. In 4.0 both methods will behave the same.', __CLASS__, $node->getPath()), E_USER_DEPRECATED);
+            }
+
             if (true === $this->atLeastOne) {
                 $node->setMinNumberOfElements(1);
             }
@@ -381,6 +441,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
         $node->addEquivalentValue(false, $this->falseEquivalent);
         $node->setPerformDeepMerging($this->performDeepMerging);
         $node->setRequired($this->required);
+        $node->setDeprecated($this->deprecationMessage);
         $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys);
         $node->setNormalizeKeys($this->normalizeKeys);
 
@@ -411,19 +472,23 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
         $path = $node->getPath();
 
         if (null !== $this->key) {
-            throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path));
+            throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s".', $path));
+        }
+
+        if (false === $this->allowEmptyValue) {
+            @trigger_error(sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s". In 4.0 it will throw an exception.', $path), E_USER_DEPRECATED);
         }
 
         if (true === $this->atLeastOne) {
-            throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path));
+            throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s".', $path));
         }
 
         if ($this->default) {
-            throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path));
+            throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s".', $path));
         }
 
         if (false !== $this->addDefaultChildren) {
-            throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path));
+            throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s".', $path));
         }
     }
 
@@ -437,20 +502,20 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
         $path = $node->getPath();
 
         if ($this->addDefaults) {
-            throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path));
+            throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s".', $path));
         }
 
         if (false !== $this->addDefaultChildren) {
             if ($this->default) {
-                throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s"', $path));
+                throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s".', $path));
             }
 
             if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
-                throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path));
+                throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s".', $path));
             }
 
             if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) {
-                throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path));
+                throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s".', $path));
             }
         }
     }
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php b/civicrm/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php
index a6292f74d8..28e56579ad 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php
@@ -12,6 +12,7 @@
 namespace Symfony\Component\Config\Definition\Builder;
 
 use Symfony\Component\Config\Definition\BooleanNode;
+use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
 
 /**
  * This class provides a fluent interface for defining a node.
@@ -31,24 +32,22 @@ class BooleanNodeDefinition extends ScalarNodeDefinition
     }
 
     /**
-     * {@inheritdoc}
+     * Instantiate a Node.
      *
-     * @deprecated Deprecated since version 2.8, to be removed in 3.0.
+     * @return BooleanNode The node
      */
-    public function cannotBeEmpty()
+    protected function instantiateNode()
     {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-        return parent::cannotBeEmpty();
+        return new BooleanNode($this->name, $this->parent);
     }
 
     /**
-     * Instantiate a Node.
+     * {@inheritdoc}
      *
-     * @return BooleanNode The node
+     * @throws InvalidDefinitionException
      */
-    protected function instantiateNode()
+    public function cannotBeEmpty()
     {
-        return new BooleanNode($this->name, $this->parent);
+        throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.');
     }
 }
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/ExprBuilder.php b/civicrm/vendor/symfony/config/Definition/Builder/ExprBuilder.php
index ddbe5b0401..5db229dcca 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/ExprBuilder.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/ExprBuilder.php
@@ -88,6 +88,18 @@ class ExprBuilder
         return $this;
     }
 
+    /**
+     * Tests if the value is empty.
+     *
+     * @return ExprBuilder
+     */
+    public function ifEmpty()
+    {
+        $this->ifPart = function ($v) { return empty($v); };
+
+        return $this;
+    }
+
     /**
      * Tests if the value is an array.
      *
@@ -124,6 +136,19 @@ class ExprBuilder
         return $this;
     }
 
+    /**
+     * Transforms variables of any type into an array.
+     *
+     * @return $this
+     */
+    public function castToArray()
+    {
+        $this->ifPart = function ($v) { return !\is_array($v); };
+        $this->thenPart = function ($v) { return [$v]; };
+
+        return $this;
+    }
+
     /**
      * Sets the closure to run if the test pass.
      *
@@ -143,7 +168,7 @@ class ExprBuilder
      */
     public function thenEmptyArray()
     {
-        $this->thenPart = function ($v) { return array(); };
+        $this->thenPart = function ($v) { return []; };
 
         return $this;
     }
@@ -175,7 +200,7 @@ class ExprBuilder
      */
     public function thenUnset()
     {
-        $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); };
+        $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key.'); };
 
         return $this;
     }
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/NodeBuilder.php b/civicrm/vendor/symfony/config/Definition/Builder/NodeBuilder.php
index 95863d68f9..2809cb6c6f 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/NodeBuilder.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/NodeBuilder.php
@@ -23,15 +23,15 @@ class NodeBuilder implements NodeParentInterface
 
     public function __construct()
     {
-        $this->nodeMapping = array(
-            'variable' => __NAMESPACE__.'\\VariableNodeDefinition',
-            'scalar' => __NAMESPACE__.'\\ScalarNodeDefinition',
-            'boolean' => __NAMESPACE__.'\\BooleanNodeDefinition',
-            'integer' => __NAMESPACE__.'\\IntegerNodeDefinition',
-            'float' => __NAMESPACE__.'\\FloatNodeDefinition',
-            'array' => __NAMESPACE__.'\\ArrayNodeDefinition',
-            'enum' => __NAMESPACE__.'\\EnumNodeDefinition',
-        );
+        $this->nodeMapping = [
+            'variable' => VariableNodeDefinition::class,
+            'scalar' => ScalarNodeDefinition::class,
+            'boolean' => BooleanNodeDefinition::class,
+            'integer' => IntegerNodeDefinition::class,
+            'float' => FloatNodeDefinition::class,
+            'array' => ArrayNodeDefinition::class,
+            'enum' => EnumNodeDefinition::class,
+        ];
     }
 
     /**
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/NodeDefinition.php b/civicrm/vendor/symfony/config/Definition/Builder/NodeDefinition.php
index a14161f082..cc245d7489 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/NodeDefinition.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/NodeDefinition.php
@@ -27,13 +27,14 @@ abstract class NodeDefinition implements NodeParentInterface
     protected $defaultValue;
     protected $default = false;
     protected $required = false;
+    protected $deprecationMessage = null;
     protected $merge;
     protected $allowEmptyValue = true;
     protected $nullEquivalent;
     protected $trueEquivalent = true;
     protected $falseEquivalent = false;
     protected $parent;
-    protected $attributes = array();
+    protected $attributes = [];
 
     /**
      * @param string|null              $name   The name of the node
@@ -160,6 +161,23 @@ abstract class NodeDefinition implements NodeParentInterface
         return $this;
     }
 
+    /**
+     * Sets the node as deprecated.
+     *
+     * You can use %node% and %path% placeholders in your message to display,
+     * respectively, the node name and its complete path.
+     *
+     * @param string $message Deprecation message
+     *
+     * @return $this
+     */
+    public function setDeprecated($message = 'The child node "%node%" at path "%path%" is deprecated.')
+    {
+        $this->deprecationMessage = $message;
+
+        return $this;
+    }
+
     /**
      * Sets the equivalent value used when the node contains null.
      *
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php b/civicrm/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php
index 35e30487a6..d3cdca90df 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php
@@ -19,8 +19,8 @@ namespace Symfony\Component\Config\Definition\Builder;
 class NormalizationBuilder
 {
     protected $node;
-    public $before = array();
-    public $remappings = array();
+    public $before = [];
+    public $remappings = [];
 
     public function __construct(NodeDefinition $node)
     {
@@ -37,7 +37,7 @@ class NormalizationBuilder
      */
     public function remap($key, $plural = null)
     {
-        $this->remappings[] = array($key, null === $plural ? $key.'s' : $plural);
+        $this->remappings[] = [$key, null === $plural ? $key.'s' : $plural];
 
         return $this;
     }
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php b/civicrm/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php
index 40c0bfcc6e..390b113656 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\Config\Definition\Builder;
 
+use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
+
 /**
  * Abstract class that contains common code of integer and float node definitions.
  *
@@ -33,7 +35,7 @@ abstract class NumericNodeDefinition extends ScalarNodeDefinition
     public function max($max)
     {
         if (isset($this->min) && $this->min > $max) {
-            throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min));
+            throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s).', $max, $this->min));
         }
         $this->max = $max;
 
@@ -52,7 +54,7 @@ abstract class NumericNodeDefinition extends ScalarNodeDefinition
     public function min($min)
     {
         if (isset($this->max) && $this->max < $min) {
-            throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max));
+            throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s).', $min, $this->max));
         }
         $this->min = $min;
 
@@ -62,12 +64,10 @@ abstract class NumericNodeDefinition extends ScalarNodeDefinition
     /**
      * {@inheritdoc}
      *
-     * @deprecated Deprecated since version 2.8, to be removed in 3.0.
+     * @throws InvalidDefinitionException
      */
     public function cannotBeEmpty()
     {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-        return parent::cannotBeEmpty();
+        throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to NumericNodeDefinition.');
     }
 }
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/TreeBuilder.php b/civicrm/vendor/symfony/config/Definition/Builder/TreeBuilder.php
index 5d02848a09..384477c501 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/TreeBuilder.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/TreeBuilder.php
@@ -22,6 +22,10 @@ class TreeBuilder implements NodeParentInterface
 {
     protected $tree;
     protected $root;
+
+    /**
+     * @deprecated since 3.4. To be removed in 4.0
+     */
     protected $builder;
 
     /**
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/ValidationBuilder.php b/civicrm/vendor/symfony/config/Definition/Builder/ValidationBuilder.php
index bb2b9eb339..4efc726c0c 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/ValidationBuilder.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/ValidationBuilder.php
@@ -19,7 +19,7 @@ namespace Symfony\Component\Config\Definition\Builder;
 class ValidationBuilder
 {
     protected $node;
-    public $rules = array();
+    public $rules = [];
 
     public function __construct(NodeDefinition $node)
     {
diff --git a/civicrm/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php b/civicrm/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php
index a46b7ea61d..26565e1771 100644
--- a/civicrm/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php
+++ b/civicrm/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php
@@ -54,6 +54,7 @@ class VariableNodeDefinition extends NodeDefinition
         $node->addEquivalentValue(true, $this->trueEquivalent);
         $node->addEquivalentValue(false, $this->falseEquivalent);
         $node->setRequired($this->required);
+        $node->setDeprecated($this->deprecationMessage);
 
         if (null !== $this->validation) {
             $node->setFinalValidationClosures($this->validation->rules);
diff --git a/civicrm/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php b/civicrm/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php
index 0e297318d2..744f15fd81 100644
--- a/civicrm/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php
+++ b/civicrm/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php
@@ -42,10 +42,9 @@ class XmlReferenceDumper
     }
 
     /**
-     * @param NodeInterface $node
-     * @param int           $depth
-     * @param bool          $root      If the node is the root node
-     * @param string        $namespace The namespace of the node
+     * @param int    $depth
+     * @param bool   $root      If the node is the root node
+     * @param string $namespace The namespace of the node
      */
     private function writeNode(NodeInterface $node, $depth = 0, $root = false, $namespace = null)
     {
@@ -65,10 +64,10 @@ class XmlReferenceDumper
         }
         $rootName = str_replace('_', '-', $rootName);
 
-        $rootAttributes = array();
-        $rootAttributeComments = array();
-        $rootChildren = array();
-        $rootComments = array();
+        $rootAttributes = [];
+        $rootAttributeComments = [];
+        $rootChildren = [];
+        $rootComments = [];
 
         if ($node instanceof ArrayNode) {
             $children = $node->getChildren();
@@ -96,7 +95,10 @@ class XmlReferenceDumper
                     $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key;
                 }
 
-                if ($prototype instanceof ArrayNode) {
+                if ($prototype instanceof PrototypedArrayNode) {
+                    $prototype->setName($key);
+                    $children = [$key => $prototype];
+                } elseif ($prototype instanceof ArrayNode) {
                     $children = $prototype->getChildren();
                 } else {
                     if ($prototype->hasDefaultValue()) {
@@ -137,7 +139,7 @@ class XmlReferenceDumper
                     $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world
 
                     // comments
-                    $comments = array();
+                    $comments = [];
                     if ($info = $child->getInfo()) {
                         $comments[] = $info;
                     }
@@ -150,6 +152,10 @@ class XmlReferenceDumper
                         $comments[] = 'Required';
                     }
 
+                    if ($child->isDeprecated()) {
+                        $comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $node->getPath()));
+                    }
+
                     if ($child instanceof EnumNode) {
                         $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues()));
                     }
@@ -300,5 +306,7 @@ class XmlReferenceDumper
         if (\is_array($value)) {
             return implode(',', $value);
         }
+
+        return '';
     }
 }
diff --git a/civicrm/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php b/civicrm/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php
index 8945cba005..ba35539460 100644
--- a/civicrm/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php
+++ b/civicrm/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php
@@ -16,6 +16,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface;
 use Symfony\Component\Config\Definition\EnumNode;
 use Symfony\Component\Config\Definition\NodeInterface;
 use Symfony\Component\Config\Definition\PrototypedArrayNode;
+use Symfony\Component\Config\Definition\ScalarNode;
 use Symfony\Component\Yaml\Inline;
 
 /**
@@ -32,6 +33,32 @@ class YamlReferenceDumper
         return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree());
     }
 
+    public function dumpAtPath(ConfigurationInterface $configuration, $path)
+    {
+        $rootNode = $node = $configuration->getConfigTreeBuilder()->buildTree();
+
+        foreach (explode('.', $path) as $step) {
+            if (!$node instanceof ArrayNode) {
+                throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s".', $rootNode->getName(), $path));
+            }
+
+            /** @var NodeInterface[] $children */
+            $children = $node instanceof PrototypedArrayNode ? $this->getPrototypeChildren($node) : $node->getChildren();
+
+            foreach ($children as $child) {
+                if ($child->getName() === $step) {
+                    $node = $child;
+
+                    continue 2;
+                }
+            }
+
+            throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s".', $rootNode->getName(), $path));
+        }
+
+        return $this->dumpNode($node);
+    }
+
     public function dumpNode(NodeInterface $node)
     {
         $this->reference = '';
@@ -43,12 +70,12 @@ class YamlReferenceDumper
     }
 
     /**
-     * @param NodeInterface $node
-     * @param int           $depth
+     * @param int  $depth
+     * @param bool $prototypedArray
      */
-    private function writeNode(NodeInterface $node, $depth = 0)
+    private function writeNode(NodeInterface $node, NodeInterface $parentNode = null, $depth = 0, $prototypedArray = false)
     {
-        $comments = array();
+        $comments = [];
         $default = '';
         $defaultArray = null;
         $children = null;
@@ -59,29 +86,7 @@ class YamlReferenceDumper
             $children = $node->getChildren();
 
             if ($node instanceof PrototypedArrayNode) {
-                $prototype = $node->getPrototype();
-
-                if ($prototype instanceof ArrayNode) {
-                    $children = $prototype->getChildren();
-                }
-
-                // check for attribute as key
-                if ($key = $node->getKeyAttribute()) {
-                    $keyNodeClass = 'Symfony\Component\Config\Definition\\'.($prototype instanceof ArrayNode ? 'ArrayNode' : 'ScalarNode');
-                    $keyNode = new $keyNodeClass($key, $node);
-
-                    $info = 'Prototype';
-                    if (null !== $prototype->getInfo()) {
-                        $info .= ': '.$prototype->getInfo();
-                    }
-                    $keyNode->setInfo($info);
-
-                    // add children
-                    foreach ($children as $childNode) {
-                        $keyNode->addChild($childNode);
-                    }
-                    $children = array($key => $keyNode);
-                }
+                $children = $this->getPrototypeChildren($node);
             }
 
             if (!$children) {
@@ -117,6 +122,11 @@ class YamlReferenceDumper
             $comments[] = 'Required';
         }
 
+        // deprecated?
+        if ($node->isDeprecated()) {
+            $comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $parentNode ? $parentNode->getPath() : $node->getPath()));
+        }
+
         // example
         if ($example && !\is_array($example)) {
             $comments[] = 'Example: '.$example;
@@ -125,7 +135,8 @@ class YamlReferenceDumper
         $default = '' != (string) $default ? ' '.$default : '';
         $comments = \count($comments) ? '# '.implode(', ', $comments) : '';
 
-        $text = rtrim(sprintf('%-21s%s %s', $node->getName().':', $default, $comments), ' ');
+        $key = $prototypedArray ? '-' : $node->getName().':';
+        $text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' ');
 
         if ($info = $node->getInfo()) {
             $this->writeLine('');
@@ -159,7 +170,7 @@ class YamlReferenceDumper
 
         if ($children) {
             foreach ($children as $childNode) {
-                $this->writeNode($childNode, $depth + 1);
+                $this->writeNode($childNode, $node, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute());
             }
         }
     }
@@ -200,4 +211,42 @@ class YamlReferenceDumper
             }
         }
     }
+
+    /**
+     * @return array
+     */
+    private function getPrototypeChildren(PrototypedArrayNode $node)
+    {
+        $prototype = $node->getPrototype();
+        $key = $node->getKeyAttribute();
+
+        // Do not expand prototype if it isn't an array node nor uses attribute as key
+        if (!$key && !$prototype instanceof ArrayNode) {
+            return $node->getChildren();
+        }
+
+        if ($prototype instanceof ArrayNode) {
+            $keyNode = new ArrayNode($key, $node);
+            $children = $prototype->getChildren();
+
+            if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) {
+                $children = $this->getPrototypeChildren($prototype);
+            }
+
+            // add children
+            foreach ($children as $childNode) {
+                $keyNode->addChild($childNode);
+            }
+        } else {
+            $keyNode = new ScalarNode($key, $node);
+        }
+
+        $info = 'Prototype';
+        if (null !== $prototype->getInfo()) {
+            $info .= ': '.$prototype->getInfo();
+        }
+        $keyNode->setInfo($info);
+
+        return [$key => $keyNode];
+    }
 }
diff --git a/civicrm/vendor/symfony/config/Definition/EnumNode.php b/civicrm/vendor/symfony/config/Definition/EnumNode.php
index a214a854b7..15c8db3e66 100644
--- a/civicrm/vendor/symfony/config/Definition/EnumNode.php
+++ b/civicrm/vendor/symfony/config/Definition/EnumNode.php
@@ -22,7 +22,7 @@ class EnumNode extends ScalarNode
 {
     private $values;
 
-    public function __construct($name, NodeInterface $parent = null, array $values = array())
+    public function __construct($name, NodeInterface $parent = null, array $values = [])
     {
         $values = array_unique($values);
         if (empty($values)) {
diff --git a/civicrm/vendor/symfony/config/Definition/Processor.php b/civicrm/vendor/symfony/config/Definition/Processor.php
index 3e0feab869..0a935eeb7f 100644
--- a/civicrm/vendor/symfony/config/Definition/Processor.php
+++ b/civicrm/vendor/symfony/config/Definition/Processor.php
@@ -28,7 +28,7 @@ class Processor
      */
     public function process(NodeInterface $configTree, array $configs)
     {
-        $currentConfig = array();
+        $currentConfig = [];
         foreach ($configs as $config) {
             $config = $configTree->normalize($config);
             $currentConfig = $configTree->merge($currentConfig, $config);
@@ -86,12 +86,12 @@ class Processor
         if (isset($config[$key])) {
             if (\is_string($config[$key]) || !\is_int(key($config[$key]))) {
                 // only one
-                return  array($config[$key]);
+                return  [$config[$key]];
             }
 
             return  $config[$key];
         }
 
-        return array();
+        return [];
     }
 }
diff --git a/civicrm/vendor/symfony/config/Definition/PrototypedArrayNode.php b/civicrm/vendor/symfony/config/Definition/PrototypedArrayNode.php
index eddcb32a77..d18a109abc 100644
--- a/civicrm/vendor/symfony/config/Definition/PrototypedArrayNode.php
+++ b/civicrm/vendor/symfony/config/Definition/PrototypedArrayNode.php
@@ -27,12 +27,12 @@ class PrototypedArrayNode extends ArrayNode
     protected $keyAttribute;
     protected $removeKeyAttribute = false;
     protected $minNumberOfElements = 0;
-    protected $defaultValue = array();
+    protected $defaultValue = [];
     protected $defaultChildren;
     /**
      * @var NodeInterface[] An array of the prototypes of the simplified value children
      */
-    private $valuePrototypes = array();
+    private $valuePrototypes = [];
 
     /**
      * Sets the minimum number of elements that a prototype based node must
@@ -53,15 +53,15 @@ class PrototypedArrayNode extends ArrayNode
      * to be the key of the particular item. For example, if "id" is the
      * "key", then:
      *
-     *     array(
-     *         array('id' => 'my_name', 'foo' => 'bar'),
-     *     );
+     *     [
+     *         ['id' => 'my_name', 'foo' => 'bar'],
+     *     ];
      *
      *  becomes
      *
-     *      array(
-     *          'my_name' => array('foo' => 'bar'),
-     *      );
+     *      [
+     *          'my_name' => ['foo' => 'bar'],
+     *      ];
      *
      * If you'd like "'id' => 'my_name'" to still be present in the resulting
      * array, then you can set the second argument of this method to false.
@@ -78,7 +78,7 @@ class PrototypedArrayNode extends ArrayNode
     /**
      * Retrieves the name of the attribute which value should be used as key.
      *
-     * @return string The name of the attribute
+     * @return string|null The name of the attribute
      */
     public function getKeyAttribute()
     {
@@ -114,10 +114,10 @@ class PrototypedArrayNode extends ArrayNode
      *
      * @param int|string|array|null $children The number of children|The child name|The children names to be added
      */
-    public function setAddChildrenIfNoneSet($children = array('defaults'))
+    public function setAddChildrenIfNoneSet($children = ['defaults'])
     {
         if (null === $children) {
-            $this->defaultChildren = array('defaults');
+            $this->defaultChildren = ['defaults'];
         } else {
             $this->defaultChildren = \is_int($children) && $children > 0 ? range(1, $children) : (array) $children;
         }
@@ -132,8 +132,8 @@ class PrototypedArrayNode extends ArrayNode
     public function getDefaultValue()
     {
         if (null !== $this->defaultChildren) {
-            $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array();
-            $defaults = array();
+            $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : [];
+            $defaults = [];
             foreach (array_values($this->defaultChildren) as $i => $name) {
                 $defaults[null === $this->keyAttribute ? $i : $name] = $default;
             }
@@ -185,7 +185,7 @@ class PrototypedArrayNode extends ArrayNode
     protected function finalizeValue($value)
     {
         if (false === $value) {
-            throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)));
+            throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: "%s".', $this->getPath(), json_encode($value)));
         }
 
         foreach ($value as $k => $v) {
@@ -226,7 +226,7 @@ class PrototypedArrayNode extends ArrayNode
         $value = $this->remapXml($value);
 
         $isAssoc = array_keys($value) !== range(0, \count($value) - 1);
-        $normalized = array();
+        $normalized = [];
         foreach ($value as $k => $v) {
             if (null !== $this->keyAttribute && \is_array($v)) {
                 if (!isset($v[$this->keyAttribute]) && \is_int($k) && !$isAssoc) {
@@ -243,9 +243,9 @@ class PrototypedArrayNode extends ArrayNode
                     }
 
                     // if only "value" is left
-                    if (array_keys($v) === array('value')) {
+                    if (array_keys($v) === ['value']) {
                         $v = $v['value'];
-                        if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && array_key_exists('value', $children)) {
+                        if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && \array_key_exists('value', $children)) {
                             $valuePrototype = current($this->valuePrototypes) ?: clone $children['value'];
                             $valuePrototype->parent = $this;
                             $originalClosures = $this->prototype->normalizationClosures;
@@ -258,7 +258,7 @@ class PrototypedArrayNode extends ArrayNode
                     }
                 }
 
-                if (array_key_exists($k, $normalized)) {
+                if (\array_key_exists($k, $normalized)) {
                     $ex = new DuplicateKeyException(sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath()));
                     $ex->setPath($this->getPath());
 
@@ -301,14 +301,14 @@ class PrototypedArrayNode extends ArrayNode
         }
 
         foreach ($rightSide as $k => $v) {
-            // prototype, and key is irrelevant, so simply append the element
+            // prototype, and key is irrelevant, append the element
             if (null === $this->keyAttribute) {
                 $leftSide[] = $v;
                 continue;
             }
 
             // no conflict
-            if (!array_key_exists($k, $leftSide)) {
+            if (!\array_key_exists($k, $leftSide)) {
                 if (!$this->allowNewKeys) {
                     $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file.', $this->getPath()));
                     $ex->setPath($this->getPath());
@@ -335,30 +335,30 @@ class PrototypedArrayNode extends ArrayNode
      *
      * For example, assume $this->keyAttribute is 'name' and the value array is as follows:
      *
-     *     array(
-     *         array(
+     *     [
+     *         [
      *             'name' => 'name001',
      *             'value' => 'value001'
-     *         )
-     *     )
+     *         ]
+     *     ]
      *
      * Now, the key is 0 and the child node is:
      *
-     *     array(
+     *     [
      *        'name' => 'name001',
      *        'value' => 'value001'
-     *     )
+     *     ]
      *
      * When normalizing the value array, the 'name' element will removed from the child node
      * and its value becomes the new key of the child node:
      *
-     *     array(
-     *         'name001' => array('value' => 'value001')
-     *     )
+     *     [
+     *         'name001' => ['value' => 'value001']
+     *     ]
      *
      * Now only 'value' element is left in the child node which can be further simplified into a string:
      *
-     *     array('name001' => 'value001')
+     *     ['name001' => 'value001']
      *
      * Now, the key becomes 'name001' and the child node becomes 'value001' and
      * the prototype of child node 'name001' should be a ScalarNode instead of an ArrayNode instance.
diff --git a/civicrm/vendor/symfony/config/Definition/ReferenceDumper.php b/civicrm/vendor/symfony/config/Definition/ReferenceDumper.php
deleted file mode 100644
index 047b258ad3..0000000000
--- a/civicrm/vendor/symfony/config/Definition/ReferenceDumper.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Definition;
-
-@trigger_error('The '.__NAMESPACE__.'\ReferenceDumper class is deprecated since Symfony 2.4 and will be removed in 3.0. Use the Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper class instead.', E_USER_DEPRECATED);
-
-use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;
-
-/**
- * @deprecated since version 2.4, to be removed in 3.0.
- *             Use {@link \Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper} instead.
- */
-class ReferenceDumper extends YamlReferenceDumper
-{
-}
diff --git a/civicrm/vendor/symfony/config/DependencyInjection/ConfigCachePass.php b/civicrm/vendor/symfony/config/DependencyInjection/ConfigCachePass.php
new file mode 100644
index 0000000000..128bf7e28c
--- /dev/null
+++ b/civicrm/vendor/symfony/config/DependencyInjection/ConfigCachePass.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\DependencyInjection;
+
+@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Use tagged iterator arguments instead.', ConfigCachePass::class), E_USER_DEPRECATED);
+
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority.
+ *
+ * @author Matthias Pigulla <mp@webfactory.de>
+ * @author Benjamin Klotz <bk@webfactory.de>
+ *
+ * @deprecated since version 3.4, to be removed in 4.0. Use tagged iterator arguments instead.
+ */
+class ConfigCachePass implements CompilerPassInterface
+{
+    use PriorityTaggedServiceTrait;
+
+    private $factoryServiceId;
+    private $resourceCheckerTag;
+
+    public function __construct($factoryServiceId = 'config_cache_factory', $resourceCheckerTag = 'config_cache.resource_checker')
+    {
+        $this->factoryServiceId = $factoryServiceId;
+        $this->resourceCheckerTag = $resourceCheckerTag;
+    }
+
+    public function process(ContainerBuilder $container)
+    {
+        $resourceCheckers = $this->findAndSortTaggedServices($this->resourceCheckerTag, $container);
+
+        if (empty($resourceCheckers)) {
+            return;
+        }
+
+        $container->getDefinition($this->factoryServiceId)->replaceArgument(0, new IteratorArgument($resourceCheckers));
+    }
+}
diff --git a/civicrm/vendor/symfony/config/Exception/FileLoaderLoadException.php b/civicrm/vendor/symfony/config/Exception/FileLoaderLoadException.php
index 819abe6ef1..82d90eb39b 100644
--- a/civicrm/vendor/symfony/config/Exception/FileLoaderLoadException.php
+++ b/civicrm/vendor/symfony/config/Exception/FileLoaderLoadException.php
@@ -23,8 +23,9 @@ class FileLoaderLoadException extends \Exception
      * @param string     $sourceResource The original resource importing the new resource
      * @param int        $code           The error code
      * @param \Exception $previous       A previous exception
+     * @param string     $type           The type of resource
      */
-    public function __construct($resource, $sourceResource = null, $code = null, $previous = null)
+    public function __construct($resource, $sourceResource = null, $code = null, $previous = null, $type = null)
     {
         $message = '';
         if ($previous) {
@@ -60,6 +61,13 @@ class FileLoaderLoadException extends \Exception
             $bundle = substr($parts[0], 1);
             $message .= sprintf(' Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle);
             $message .= sprintf(' If the bundle is registered, make sure the bundle path "%s" is not empty.', $resource);
+        } elseif (null !== $type) {
+            // maybe there is no loader for this specific type
+            if ('annotation' === $type) {
+                $message .= ' Make sure annotations are installed and enabled.';
+            } else {
+                $message .= sprintf(' Make sure there is a loader supporting the "%s" type.', $type);
+            }
         }
 
         parent::__construct($message, $code, $previous);
@@ -72,7 +80,7 @@ class FileLoaderLoadException extends \Exception
         }
 
         if (\is_array($var)) {
-            $a = array();
+            $a = [];
             foreach ($var as $k => $v) {
                 $a[] = sprintf('%s => %s', $k, $this->varToString($v));
             }
diff --git a/civicrm/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php b/civicrm/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php
new file mode 100644
index 0000000000..648cf0e707
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Exception;
+
+/**
+ * File locator exception if a file does not exist.
+ *
+ * @author Leo Feyer <https://github.com/leofeyer>
+ */
+class FileLocatorFileNotFoundException extends \InvalidArgumentException
+{
+    private $paths;
+
+    public function __construct($message = '', $code = 0, $previous = null, array $paths = [])
+    {
+        parent::__construct($message, $code, $previous);
+
+        $this->paths = $paths;
+    }
+
+    public function getPaths()
+    {
+        return $this->paths;
+    }
+}
diff --git a/civicrm/vendor/symfony/config/FileLocator.php b/civicrm/vendor/symfony/config/FileLocator.php
index 368cc19ae6..c125ba0b13 100644
--- a/civicrm/vendor/symfony/config/FileLocator.php
+++ b/civicrm/vendor/symfony/config/FileLocator.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\Config;
 
+use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
+
 /**
  * FileLocator uses an array of pre-defined paths to find files.
  *
@@ -23,7 +25,7 @@ class FileLocator implements FileLocatorInterface
     /**
      * @param string|array $paths A path or an array of paths where to look for resources
      */
-    public function __construct($paths = array())
+    public function __construct($paths = [])
     {
         $this->paths = (array) $paths;
     }
@@ -39,7 +41,7 @@ class FileLocator implements FileLocatorInterface
 
         if ($this->isAbsolutePath($name)) {
             if (!file_exists($name)) {
-                throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $name));
+                throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist.', $name), 0, null, [$name]);
             }
 
             return $name;
@@ -52,7 +54,7 @@ class FileLocator implements FileLocatorInterface
         }
 
         $paths = array_unique($paths);
-        $filepaths = array();
+        $filepaths = $notfound = [];
 
         foreach ($paths as $path) {
             if (@file_exists($file = $path.\DIRECTORY_SEPARATOR.$name)) {
@@ -60,11 +62,13 @@ class FileLocator implements FileLocatorInterface
                     return $file;
                 }
                 $filepaths[] = $file;
+            } else {
+                $notfound[] = $file;
             }
         }
 
         if (!$filepaths) {
-            throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s).', $name, implode(', ', $paths)));
+            throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist (in: "%s").', $name, implode('", "', $paths)), 0, null, $notfound);
         }
 
         return $filepaths;
diff --git a/civicrm/vendor/symfony/config/FileLocatorInterface.php b/civicrm/vendor/symfony/config/FileLocatorInterface.php
index 66057982db..cf3c2e594d 100644
--- a/civicrm/vendor/symfony/config/FileLocatorInterface.php
+++ b/civicrm/vendor/symfony/config/FileLocatorInterface.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\Config;
 
+use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
+
 /**
  * @author Fabien Potencier <fabien@symfony.com>
  */
@@ -25,7 +27,8 @@ interface FileLocatorInterface
      *
      * @return string|array The full path to the file or an array of file paths
      *
-     * @throws \InvalidArgumentException When file is not found
+     * @throws \InvalidArgumentException        If $name is empty
+     * @throws FileLocatorFileNotFoundException If a file is not found
      */
     public function locate($name, $currentPath = null, $first = true);
 }
diff --git a/civicrm/vendor/symfony/config/LICENSE b/civicrm/vendor/symfony/config/LICENSE
index 21d7fb9e2f..9e936ec044 100644
--- a/civicrm/vendor/symfony/config/LICENSE
+++ b/civicrm/vendor/symfony/config/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2018 Fabien Potencier
+Copyright (c) 2004-2020 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/civicrm/vendor/symfony/config/Loader/DelegatingLoader.php b/civicrm/vendor/symfony/config/Loader/DelegatingLoader.php
index 237009d45e..452e81c58b 100644
--- a/civicrm/vendor/symfony/config/Loader/DelegatingLoader.php
+++ b/civicrm/vendor/symfony/config/Loader/DelegatingLoader.php
@@ -34,7 +34,7 @@ class DelegatingLoader extends Loader
     public function load($resource, $type = null)
     {
         if (false === $loader = $this->resolver->resolve($resource, $type)) {
-            throw new FileLoaderLoadException($resource);
+            throw new FileLoaderLoadException($resource, null, null, null, $type);
         }
 
         return $loader->load($resource, $type);
diff --git a/civicrm/vendor/symfony/config/Loader/FileLoader.php b/civicrm/vendor/symfony/config/Loader/FileLoader.php
index 506eb1be08..2f1d471bdd 100644
--- a/civicrm/vendor/symfony/config/Loader/FileLoader.php
+++ b/civicrm/vendor/symfony/config/Loader/FileLoader.php
@@ -13,7 +13,10 @@ namespace Symfony\Component\Config\Loader;
 
 use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;
 use Symfony\Component\Config\Exception\FileLoaderLoadException;
+use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
 use Symfony\Component\Config\FileLocatorInterface;
+use Symfony\Component\Config\Resource\FileExistenceResource;
+use Symfony\Component\Config\Resource\GlobResource;
 
 /**
  * FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -22,7 +25,7 @@ use Symfony\Component\Config\FileLocatorInterface;
  */
 abstract class FileLoader extends Loader
 {
-    protected static $loading = array();
+    protected static $loading = [];
 
     protected $locator;
 
@@ -65,26 +68,75 @@ abstract class FileLoader extends Loader
      *
      * @throws FileLoaderLoadException
      * @throws FileLoaderImportCircularReferenceException
+     * @throws FileLocatorFileNotFoundException
      */
     public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
+    {
+        if (\is_string($resource) && \strlen($resource) !== $i = strcspn($resource, '*?{[')) {
+            $ret = [];
+            $isSubpath = 0 !== $i && false !== strpos(substr($resource, 0, $i), '/');
+            foreach ($this->glob($resource, false, $_, $ignoreErrors || !$isSubpath) as $path => $info) {
+                if (null !== $res = $this->doImport($path, 'glob' === $type ? null : $type, $ignoreErrors, $sourceResource)) {
+                    $ret[] = $res;
+                }
+                $isSubpath = true;
+            }
+
+            if ($isSubpath) {
+                return isset($ret[1]) ? $ret : (isset($ret[0]) ? $ret[0] : null);
+            }
+        }
+
+        return $this->doImport($resource, $type, $ignoreErrors, $sourceResource);
+    }
+
+    /**
+     * @internal
+     */
+    protected function glob($pattern, $recursive, &$resource = null, $ignoreErrors = false)
+    {
+        if (\strlen($pattern) === $i = strcspn($pattern, '*?{[')) {
+            $prefix = $pattern;
+            $pattern = '';
+        } elseif (0 === $i || false === strpos(substr($pattern, 0, $i), '/')) {
+            $prefix = '.';
+            $pattern = '/'.$pattern;
+        } else {
+            $prefix = \dirname(substr($pattern, 0, 1 + $i));
+            $pattern = substr($pattern, \strlen($prefix));
+        }
+
+        try {
+            $prefix = $this->locator->locate($prefix, $this->currentDir, true);
+        } catch (FileLocatorFileNotFoundException $e) {
+            if (!$ignoreErrors) {
+                throw $e;
+            }
+
+            $resource = [];
+            foreach ($e->getPaths() as $path) {
+                $resource[] = new FileExistenceResource($path);
+            }
+
+            return;
+        }
+        $resource = new GlobResource($prefix, $pattern, $recursive);
+
+        foreach ($resource as $path => $info) {
+            yield $path => $info;
+        }
+    }
+
+    private function doImport($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
     {
         try {
             $loader = $this->resolve($resource, $type);
 
             if ($loader instanceof self && null !== $this->currentDir) {
-                // we fallback to the current locator to keep BC
-                // as some some loaders do not call the parent __construct()
-                // @deprecated should be removed in 3.0
-                $locator = $loader->getLocator();
-                if (null === $locator) {
-                    @trigger_error('Not calling the parent constructor in '.\get_class($loader).' which extends '.__CLASS__.' is deprecated since Symfony 2.7 and will not be supported anymore in 3.0.', E_USER_DEPRECATED);
-                    $locator = $this->locator;
-                }
-
-                $resource = $locator->locate($resource, $this->currentDir, false);
+                $resource = $loader->getLocator()->locate($resource, $this->currentDir, false);
             }
 
-            $resources = \is_array($resource) ? $resource : array($resource);
+            $resources = \is_array($resource) ? $resource : [$resource];
             for ($i = 0; $i < $resourcesCount = \count($resources); ++$i) {
                 if (isset(self::$loading[$resources[$i]])) {
                     if ($i == $resourcesCount - 1) {
@@ -99,16 +151,10 @@ abstract class FileLoader extends Loader
 
             try {
                 $ret = $loader->load($resource, $type);
-            } catch (\Exception $e) {
-                unset(self::$loading[$resource]);
-                throw $e;
-            } catch (\Throwable $e) {
+            } finally {
                 unset(self::$loading[$resource]);
-                throw $e;
             }
 
-            unset(self::$loading[$resource]);
-
             return $ret;
         } catch (FileLoaderImportCircularReferenceException $e) {
             throw $e;
@@ -119,8 +165,10 @@ abstract class FileLoader extends Loader
                     throw $e;
                 }
 
-                throw new FileLoaderLoadException($resource, $sourceResource, null, $e);
+                throw new FileLoaderLoadException($resource, $sourceResource, null, $e, $type);
             }
         }
+
+        return null;
     }
 }
diff --git a/civicrm/vendor/symfony/config/Loader/GlobFileLoader.php b/civicrm/vendor/symfony/config/Loader/GlobFileLoader.php
new file mode 100644
index 0000000000..f432b45ba4
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Loader/GlobFileLoader.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Loader;
+
+/**
+ * GlobFileLoader loads files from a glob pattern.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class GlobFileLoader extends FileLoader
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function load($resource, $type = null)
+    {
+        return $this->import($resource);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function supports($resource, $type = null)
+    {
+        return 'glob' === $type;
+    }
+}
diff --git a/civicrm/vendor/symfony/config/Loader/Loader.php b/civicrm/vendor/symfony/config/Loader/Loader.php
index a6f8d9c664..d2f2ec90b9 100644
--- a/civicrm/vendor/symfony/config/Loader/Loader.php
+++ b/civicrm/vendor/symfony/config/Loader/Loader.php
@@ -70,7 +70,7 @@ abstract class Loader implements LoaderInterface
         $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type);
 
         if (false === $loader) {
-            throw new FileLoaderLoadException($resource);
+            throw new FileLoaderLoadException($resource, null, null, null, $type);
         }
 
         return $loader;
diff --git a/civicrm/vendor/symfony/config/Loader/LoaderResolver.php b/civicrm/vendor/symfony/config/Loader/LoaderResolver.php
index 9299bc000f..c99efda4fd 100644
--- a/civicrm/vendor/symfony/config/Loader/LoaderResolver.php
+++ b/civicrm/vendor/symfony/config/Loader/LoaderResolver.php
@@ -24,12 +24,12 @@ class LoaderResolver implements LoaderResolverInterface
     /**
      * @var LoaderInterface[] An array of LoaderInterface objects
      */
-    private $loaders = array();
+    private $loaders = [];
 
     /**
      * @param LoaderInterface[] $loaders An array of loaders
      */
-    public function __construct(array $loaders = array())
+    public function __construct(array $loaders = [])
     {
         foreach ($loaders as $loader) {
             $this->addLoader($loader);
diff --git a/civicrm/vendor/symfony/config/README.md b/civicrm/vendor/symfony/config/README.md
index bf400da196..0bbde55230 100644
--- a/civicrm/vendor/symfony/config/README.md
+++ b/civicrm/vendor/symfony/config/README.md
@@ -8,7 +8,7 @@ may be (YAML, XML, INI files, or for instance a database).
 Resources
 ---------
 
-  * [Documentation](https://symfony.com/doc/current/components/config/index.html)
+  * [Documentation](https://symfony.com/doc/current/components/config.html)
   * [Contributing](https://symfony.com/doc/current/contributing/index.html)
   * [Report issues](https://github.com/symfony/symfony/issues) and
     [send Pull Requests](https://github.com/symfony/symfony/pulls)
diff --git a/civicrm/vendor/symfony/config/Resource/BCResourceInterfaceChecker.php b/civicrm/vendor/symfony/config/Resource/BCResourceInterfaceChecker.php
deleted file mode 100644
index 64c93094ac..0000000000
--- a/civicrm/vendor/symfony/config/Resource/BCResourceInterfaceChecker.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Resource;
-
-/**
- * Resource checker for the ResourceInterface. Exists for BC.
- *
- * @author Matthias Pigulla <mp@webfactory.de>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-class BCResourceInterfaceChecker extends SelfCheckingResourceChecker
-{
-    public function supports(ResourceInterface $metadata)
-    {
-        /* As all resources must be instanceof ResourceInterface,
-           we support them all. */
-        return true;
-    }
-
-    public function isFresh(ResourceInterface $resource, $timestamp)
-    {
-        @trigger_error(sprintf('The class "%s" is performing resource checking through ResourceInterface::isFresh(), which is deprecated since Symfony 2.8 and will be removed in 3.0', \get_class($resource)), E_USER_DEPRECATED);
-
-        return parent::isFresh($resource, $timestamp); // For now, $metadata features the isFresh() method, so off we go (quack quack)
-    }
-}
diff --git a/civicrm/vendor/symfony/config/Resource/ClassExistenceResource.php b/civicrm/vendor/symfony/config/Resource/ClassExistenceResource.php
new file mode 100644
index 0000000000..fc0259f418
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Resource/ClassExistenceResource.php
@@ -0,0 +1,233 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Resource;
+
+/**
+ * ClassExistenceResource represents a class existence.
+ * Freshness is only evaluated against resource existence.
+ *
+ * The resource must be a fully-qualified class name.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializable
+{
+    private $resource;
+    private $exists;
+
+    private static $autoloadLevel = 0;
+    private static $autoloadedClass;
+    private static $existsCache = [];
+
+    /**
+     * @param string    $resource The fully-qualified class name
+     * @param bool|null $exists   Boolean when the existency check has already been done
+     */
+    public function __construct($resource, $exists = null)
+    {
+        $this->resource = $resource;
+        if (null !== $exists) {
+            $this->exists = [(bool) $exists, null];
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __toString()
+    {
+        return $this->resource;
+    }
+
+    /**
+     * @return string The file path to the resource
+     */
+    public function getResource()
+    {
+        return $this->resource;
+    }
+
+    /**
+     * {@inheritdoc}
+     *
+     * @throws \ReflectionException when a parent class/interface/trait is not found
+     */
+    public function isFresh($timestamp)
+    {
+        $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
+
+        if (null !== $exists = &self::$existsCache[$this->resource]) {
+            if ($loaded) {
+                $exists = [true, null];
+            } elseif (0 >= $timestamp && !$exists[0] && null !== $exists[1]) {
+                throw new \ReflectionException($exists[1]);
+            }
+        } elseif ([false, null] === $exists = [$loaded, null]) {
+            if (!self::$autoloadLevel++) {
+                spl_autoload_register(__CLASS__.'::throwOnRequiredClass');
+            }
+            $autoloadedClass = self::$autoloadedClass;
+            self::$autoloadedClass = ltrim($this->resource, '\\');
+
+            try {
+                $exists[0] = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
+            } catch (\Exception $e) {
+                $exists[1] = $e->getMessage();
+
+                try {
+                    self::throwOnRequiredClass($this->resource, $e);
+                } catch (\ReflectionException $e) {
+                    if (0 >= $timestamp) {
+                        throw $e;
+                    }
+                }
+            } catch (\Throwable $e) {
+                $exists[1] = $e->getMessage();
+
+                throw $e;
+            } finally {
+                self::$autoloadedClass = $autoloadedClass;
+                if (!--self::$autoloadLevel) {
+                    spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass');
+                }
+            }
+        }
+
+        if (null === $this->exists) {
+            $this->exists = $exists;
+        }
+
+        return $this->exists[0] xor !$exists[0];
+    }
+
+    /**
+     * @internal
+     */
+    public function serialize()
+    {
+        if (null === $this->exists) {
+            $this->isFresh(0);
+        }
+
+        return serialize([$this->resource, $this->exists]);
+    }
+
+    /**
+     * @internal
+     */
+    public function unserialize($serialized)
+    {
+        list($this->resource, $this->exists) = unserialize($serialized);
+
+        if (\is_bool($this->exists)) {
+            $this->exists = [$this->exists, null];
+        }
+    }
+
+    /**
+     * Throws a reflection exception when the passed class does not exist but is required.
+     *
+     * A class is considered "not required" when it's loaded as part of a "class_exists" or similar check.
+     *
+     * This function can be used as an autoload function to throw a reflection
+     * exception if the class was not found by previous autoload functions.
+     *
+     * A previous exception can be passed. In this case, the class is considered as being
+     * required totally, so if it doesn't exist, a reflection exception is always thrown.
+     * If it exists, the previous exception is rethrown.
+     *
+     * @throws \ReflectionException
+     *
+     * @internal
+     */
+    public static function throwOnRequiredClass($class, \Exception $previous = null)
+    {
+        // If the passed class is the resource being checked, we shouldn't throw.
+        if (null === $previous && self::$autoloadedClass === $class) {
+            return;
+        }
+
+        if (class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) {
+            if (null !== $previous) {
+                throw $previous;
+            }
+
+            return;
+        }
+
+        if ($previous instanceof \ReflectionException) {
+            throw $previous;
+        }
+
+        $message = sprintf('Class "%s" not found.', $class);
+
+        if (self::$autoloadedClass !== $class) {
+            $message = substr_replace($message, sprintf(' while loading "%s"', self::$autoloadedClass), -1, 0);
+        }
+
+        if (null !== $previous) {
+            $message = $previous->getMessage();
+        }
+
+        $e = new \ReflectionException($message, 0, $previous);
+
+        if (null !== $previous) {
+            throw $e;
+        }
+
+        $trace = debug_backtrace();
+        $autoloadFrame = [
+            'function' => 'spl_autoload_call',
+            'args' => [$class],
+        ];
+
+        if (false === $i = array_search($autoloadFrame, $trace, true)) {
+            throw $e;
+        }
+
+        if (isset($trace[++$i]['function']) && !isset($trace[$i]['class'])) {
+            switch ($trace[$i]['function']) {
+                case 'get_class_methods':
+                case 'get_class_vars':
+                case 'get_parent_class':
+                case 'is_a':
+                case 'is_subclass_of':
+                case 'class_exists':
+                case 'class_implements':
+                case 'class_parents':
+                case 'trait_exists':
+                case 'defined':
+                case 'interface_exists':
+                case 'method_exists':
+                case 'property_exists':
+                case 'is_callable':
+                    return;
+            }
+
+            $props = [
+                'file' => isset($trace[$i]['file']) ? $trace[$i]['file'] : null,
+                'line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : null,
+                'trace' => \array_slice($trace, 1 + $i),
+            ];
+
+            foreach ($props as $p => $v) {
+                if (null !== $v) {
+                    $r = new \ReflectionProperty('Exception', $p);
+                    $r->setAccessible(true);
+                    $r->setValue($e, $v);
+                }
+            }
+        }
+
+        throw $e;
+    }
+}
diff --git a/civicrm/vendor/symfony/config/Resource/ComposerResource.php b/civicrm/vendor/symfony/config/Resource/ComposerResource.php
new file mode 100644
index 0000000000..9fb304bea8
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Resource/ComposerResource.php
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Resource;
+
+/**
+ * ComposerResource tracks the PHP version and Composer dependencies.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ComposerResource implements SelfCheckingResourceInterface, \Serializable
+{
+    private $vendors;
+
+    private static $runtimeVendors;
+
+    public function __construct()
+    {
+        self::refresh();
+        $this->vendors = self::$runtimeVendors;
+    }
+
+    public function getVendors()
+    {
+        return array_keys($this->vendors);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __toString()
+    {
+        return __CLASS__;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isFresh($timestamp)
+    {
+        self::refresh();
+
+        return array_values(self::$runtimeVendors) === array_values($this->vendors);
+    }
+
+    /**
+     * @internal
+     */
+    public function serialize()
+    {
+        return serialize($this->vendors);
+    }
+
+    /**
+     * @internal
+     */
+    public function unserialize($serialized)
+    {
+        $this->vendors = unserialize($serialized);
+    }
+
+    private static function refresh()
+    {
+        self::$runtimeVendors = [];
+
+        foreach (get_declared_classes() as $class) {
+            if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
+                $r = new \ReflectionClass($class);
+                $v = \dirname(\dirname($r->getFileName()));
+                if (file_exists($v.'/composer/installed.json')) {
+                    self::$runtimeVendors[$v] = @filemtime($v.'/composer/installed.json');
+                }
+            }
+        }
+    }
+}
diff --git a/civicrm/vendor/symfony/config/Resource/DirectoryResource.php b/civicrm/vendor/symfony/config/Resource/DirectoryResource.php
index b65d40ae44..e79b19ec2d 100644
--- a/civicrm/vendor/symfony/config/Resource/DirectoryResource.php
+++ b/civicrm/vendor/symfony/config/Resource/DirectoryResource.php
@@ -24,11 +24,17 @@ class DirectoryResource implements SelfCheckingResourceInterface, \Serializable
     /**
      * @param string      $resource The file path to the resource
      * @param string|null $pattern  A pattern to restrict monitored files
+     *
+     * @throws \InvalidArgumentException
      */
     public function __construct($resource, $pattern = null)
     {
-        $this->resource = $resource;
+        $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false);
         $this->pattern = $pattern;
+
+        if (false === $this->resource || !is_dir($this->resource)) {
+            throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $resource));
+        }
     }
 
     /**
@@ -36,11 +42,11 @@ class DirectoryResource implements SelfCheckingResourceInterface, \Serializable
      */
     public function __toString()
     {
-        return md5(serialize(array($this->resource, $this->pattern)));
+        return md5(serialize([$this->resource, $this->pattern]));
     }
 
     /**
-     * {@inheritdoc}
+     * @return string The file path to the resource
      */
     public function getResource()
     {
@@ -98,11 +104,17 @@ class DirectoryResource implements SelfCheckingResourceInterface, \Serializable
         return true;
     }
 
+    /**
+     * @internal
+     */
     public function serialize()
     {
-        return serialize(array($this->resource, $this->pattern));
+        return serialize([$this->resource, $this->pattern]);
     }
 
+    /**
+     * @internal
+     */
     public function unserialize($serialized)
     {
         list($this->resource, $this->pattern) = unserialize($serialized);
diff --git a/civicrm/vendor/symfony/config/Resource/FileExistenceResource.php b/civicrm/vendor/symfony/config/Resource/FileExistenceResource.php
index 0e87aabb52..34047651b7 100644
--- a/civicrm/vendor/symfony/config/Resource/FileExistenceResource.php
+++ b/civicrm/vendor/symfony/config/Resource/FileExistenceResource.php
@@ -43,7 +43,7 @@ class FileExistenceResource implements SelfCheckingResourceInterface, \Serializa
     }
 
     /**
-     * {@inheritdoc}
+     * @return string The file path to the resource
      */
     public function getResource()
     {
@@ -59,15 +59,15 @@ class FileExistenceResource implements SelfCheckingResourceInterface, \Serializa
     }
 
     /**
-     * {@inheritdoc}
+     * @internal
      */
     public function serialize()
     {
-        return serialize(array($this->resource, $this->exists));
+        return serialize([$this->resource, $this->exists]);
     }
 
     /**
-     * {@inheritdoc}
+     * @internal
      */
     public function unserialize($serialized)
     {
diff --git a/civicrm/vendor/symfony/config/Resource/FileResource.php b/civicrm/vendor/symfony/config/Resource/FileResource.php
index 11770106e9..bee062377b 100644
--- a/civicrm/vendor/symfony/config/Resource/FileResource.php
+++ b/civicrm/vendor/symfony/config/Resource/FileResource.php
@@ -27,10 +27,16 @@ class FileResource implements SelfCheckingResourceInterface, \Serializable
 
     /**
      * @param string $resource The file path to the resource
+     *
+     * @throws \InvalidArgumentException
      */
     public function __construct($resource)
     {
         $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false);
+
+        if (false === $this->resource) {
+            throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $resource));
+        }
     }
 
     /**
@@ -38,11 +44,11 @@ class FileResource implements SelfCheckingResourceInterface, \Serializable
      */
     public function __toString()
     {
-        return (string) $this->resource;
+        return $this->resource;
     }
 
     /**
-     * {@inheritdoc}
+     * @return string The canonicalized, absolute path to the resource
      */
     public function getResource()
     {
@@ -54,18 +60,20 @@ class FileResource implements SelfCheckingResourceInterface, \Serializable
      */
     public function isFresh($timestamp)
     {
-        if (false === $this->resource || !file_exists($this->resource)) {
-            return false;
-        }
-
-        return filemtime($this->resource) <= $timestamp;
+        return false !== ($filemtime = @filemtime($this->resource)) && $filemtime <= $timestamp;
     }
 
+    /**
+     * @internal
+     */
     public function serialize()
     {
         return serialize($this->resource);
     }
 
+    /**
+     * @internal
+     */
     public function unserialize($serialized)
     {
         $this->resource = unserialize($serialized);
diff --git a/civicrm/vendor/symfony/config/Resource/GlobResource.php b/civicrm/vendor/symfony/config/Resource/GlobResource.php
new file mode 100644
index 0000000000..13d2ee7d70
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Resource/GlobResource.php
@@ -0,0 +1,159 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Resource;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Finder\Glob;
+
+/**
+ * GlobResource represents a set of resources stored on the filesystem.
+ *
+ * Only existence/removal is tracked (not mtimes.)
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface, \Serializable
+{
+    private $prefix;
+    private $pattern;
+    private $recursive;
+    private $hash;
+
+    /**
+     * @param string $prefix    A directory prefix
+     * @param string $pattern   A glob pattern
+     * @param bool   $recursive Whether directories should be scanned recursively or not
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function __construct($prefix, $pattern, $recursive)
+    {
+        $this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false);
+        $this->pattern = $pattern;
+        $this->recursive = $recursive;
+
+        if (false === $this->prefix) {
+            throw new \InvalidArgumentException(sprintf('The path "%s" does not exist.', $prefix));
+        }
+    }
+
+    public function getPrefix()
+    {
+        return $this->prefix;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __toString()
+    {
+        return 'glob.'.$this->prefix.$this->pattern.(int) $this->recursive;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isFresh($timestamp)
+    {
+        $hash = $this->computeHash();
+
+        if (null === $this->hash) {
+            $this->hash = $hash;
+        }
+
+        return $this->hash === $hash;
+    }
+
+    /**
+     * @internal
+     */
+    public function serialize()
+    {
+        if (null === $this->hash) {
+            $this->hash = $this->computeHash();
+        }
+
+        return serialize([$this->prefix, $this->pattern, $this->recursive, $this->hash]);
+    }
+
+    /**
+     * @internal
+     */
+    public function unserialize($serialized)
+    {
+        list($this->prefix, $this->pattern, $this->recursive, $this->hash) = unserialize($serialized);
+    }
+
+    public function getIterator()
+    {
+        if (!file_exists($this->prefix) || (!$this->recursive && '' === $this->pattern)) {
+            return;
+        }
+
+        if (0 !== strpos($this->prefix, 'phar://') && false === strpos($this->pattern, '/**/') && (\defined('GLOB_BRACE') || false === strpos($this->pattern, '{'))) {
+            $paths = glob($this->prefix.$this->pattern, GLOB_NOSORT | (\defined('GLOB_BRACE') ? GLOB_BRACE : 0));
+            sort($paths);
+            foreach ($paths as $path) {
+                if ($this->recursive && is_dir($path)) {
+                    $files = iterator_to_array(new \RecursiveIteratorIterator(
+                        new \RecursiveCallbackFilterIterator(
+                            new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
+                            function (\SplFileInfo $file) { return '.' !== $file->getBasename()[0]; }
+                        ),
+                        \RecursiveIteratorIterator::LEAVES_ONLY
+                    ));
+                    uasort($files, function (\SplFileInfo $a, \SplFileInfo $b) {
+                        return (string) $a > (string) $b ? 1 : -1;
+                    });
+
+                    foreach ($files as $path => $info) {
+                        if ($info->isFile()) {
+                            yield $path => $info;
+                        }
+                    }
+                } elseif (is_file($path)) {
+                    yield $path => new \SplFileInfo($path);
+                }
+            }
+
+            return;
+        }
+
+        if (!class_exists(Finder::class)) {
+            throw new \LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $this->pattern));
+        }
+
+        $finder = new Finder();
+        $regex = Glob::toRegex($this->pattern);
+        if ($this->recursive) {
+            $regex = substr_replace($regex, '(/|$)', -2, 1);
+        }
+
+        $prefixLen = \strlen($this->prefix);
+        foreach ($finder->followLinks()->sortByName()->in($this->prefix) as $path => $info) {
+            if (preg_match($regex, substr('\\' === \DIRECTORY_SEPARATOR ? str_replace('\\', '/', $path) : $path, $prefixLen)) && $info->isFile()) {
+                yield $path => $info;
+            }
+        }
+    }
+
+    private function computeHash()
+    {
+        $hash = hash_init('md5');
+
+        foreach ($this->getIterator() as $path => $info) {
+            hash_update($hash, $path."\n");
+        }
+
+        return hash_final($hash);
+    }
+}
diff --git a/civicrm/vendor/symfony/config/Resource/ReflectionClassResource.php b/civicrm/vendor/symfony/config/Resource/ReflectionClassResource.php
new file mode 100644
index 0000000000..4c8f89cd3f
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Resource/ReflectionClassResource.php
@@ -0,0 +1,250 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Resource;
+
+use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ReflectionClassResource implements SelfCheckingResourceInterface, \Serializable
+{
+    private $files = [];
+    private $className;
+    private $classReflector;
+    private $excludedVendors = [];
+    private $hash;
+
+    public function __construct(\ReflectionClass $classReflector, $excludedVendors = [])
+    {
+        $this->className = $classReflector->name;
+        $this->classReflector = $classReflector;
+        $this->excludedVendors = $excludedVendors;
+    }
+
+    public function isFresh($timestamp)
+    {
+        if (null === $this->hash) {
+            $this->hash = $this->computeHash();
+            $this->loadFiles($this->classReflector);
+        }
+
+        foreach ($this->files as $file => $v) {
+            if (false === $filemtime = @filemtime($file)) {
+                return false;
+            }
+
+            if ($filemtime > $timestamp) {
+                return $this->hash === $this->computeHash();
+            }
+        }
+
+        return true;
+    }
+
+    public function __toString()
+    {
+        return 'reflection.'.$this->className;
+    }
+
+    /**
+     * @internal
+     */
+    public function serialize()
+    {
+        if (null === $this->hash) {
+            $this->hash = $this->computeHash();
+            $this->loadFiles($this->classReflector);
+        }
+
+        return serialize([$this->files, $this->className, $this->hash]);
+    }
+
+    /**
+     * @internal
+     */
+    public function unserialize($serialized)
+    {
+        list($this->files, $this->className, $this->hash) = unserialize($serialized);
+    }
+
+    private function loadFiles(\ReflectionClass $class)
+    {
+        foreach ($class->getInterfaces() as $v) {
+            $this->loadFiles($v);
+        }
+        do {
+            $file = $class->getFileName();
+            if (false !== $file && file_exists($file)) {
+                foreach ($this->excludedVendors as $vendor) {
+                    if (0 === strpos($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
+                        $file = false;
+                        break;
+                    }
+                }
+                if ($file) {
+                    $this->files[$file] = null;
+                }
+            }
+            foreach ($class->getTraits() as $v) {
+                $this->loadFiles($v);
+            }
+        } while ($class = $class->getParentClass());
+    }
+
+    private function computeHash()
+    {
+        if (null === $this->classReflector) {
+            try {
+                $this->classReflector = new \ReflectionClass($this->className);
+            } catch (\ReflectionException $e) {
+                // the class does not exist anymore
+                return false;
+            }
+        }
+        $hash = hash_init('md5');
+
+        foreach ($this->generateSignature($this->classReflector) as $info) {
+            hash_update($hash, $info);
+        }
+
+        return hash_final($hash);
+    }
+
+    private function generateSignature(\ReflectionClass $class)
+    {
+        yield $class->getDocComment();
+        yield (int) $class->isFinal();
+        yield (int) $class->isAbstract();
+
+        if ($class->isTrait()) {
+            yield print_r(class_uses($class->name), true);
+        } else {
+            yield print_r(class_parents($class->name), true);
+            yield print_r(class_implements($class->name), true);
+            yield print_r($class->getConstants(), true);
+        }
+
+        if (!$class->isInterface()) {
+            $defaults = $class->getDefaultProperties();
+
+            foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) {
+                yield $p->getDocComment().$p;
+                yield print_r(isset($defaults[$p->name]) && !\is_object($defaults[$p->name]) ? $defaults[$p->name] : null, true);
+            }
+        }
+
+        if (\defined('HHVM_VERSION')) {
+            foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
+                // workaround HHVM bug with variadics, see https://github.com/facebook/hhvm/issues/5762
+                yield preg_replace('/^  @@.*/m', '', new ReflectionMethodHhvmWrapper($m->class, $m->name));
+            }
+        } else {
+            foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
+                $defaults = [];
+                $parametersWithUndefinedConstants = [];
+                foreach ($m->getParameters() as $p) {
+                    if (!$p->isDefaultValueAvailable()) {
+                        $defaults[$p->name] = null;
+
+                        continue;
+                    }
+
+                    if (!$p->isDefaultValueConstant() || \defined($p->getDefaultValueConstantName())) {
+                        $defaults[$p->name] = $p->getDefaultValue();
+
+                        continue;
+                    }
+
+                    $defaults[$p->name] = $p->getDefaultValueConstantName();
+                    $parametersWithUndefinedConstants[$p->name] = true;
+                }
+
+                if (!$parametersWithUndefinedConstants) {
+                    yield preg_replace('/^  @@.*/m', '', $m);
+                } else {
+                    $stack = [
+                        $m->getDocComment(),
+                        $m->getName(),
+                        $m->isAbstract(),
+                        $m->isFinal(),
+                        $m->isStatic(),
+                        $m->isPublic(),
+                        $m->isPrivate(),
+                        $m->isProtected(),
+                        $m->returnsReference(),
+                        \PHP_VERSION_ID >= 70000 && $m->hasReturnType() ? (\PHP_VERSION_ID >= 70100 ? $m->getReturnType()->getName() : (string) $m->getReturnType()) : '',
+                    ];
+
+                    foreach ($m->getParameters() as $p) {
+                        if (!isset($parametersWithUndefinedConstants[$p->name])) {
+                            $stack[] = (string) $p;
+                        } else {
+                            $stack[] = $p->isOptional();
+                            $stack[] = \PHP_VERSION_ID >= 70000 && $p->hasType() ? (\PHP_VERSION_ID >= 70100 ? $p->getType()->getName() : (string) $p->getType()) : '';
+                            $stack[] = $p->isPassedByReference();
+                            $stack[] = \PHP_VERSION_ID >= 50600 ? $p->isVariadic() : '';
+                            $stack[] = $p->getName();
+                        }
+                    }
+
+                    yield implode(',', $stack);
+                }
+
+                yield print_r($defaults, true);
+            }
+        }
+
+        if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) {
+            return;
+        }
+
+        if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) {
+            yield EventSubscriberInterface::class;
+            yield print_r(\call_user_func([$class->name, 'getSubscribedEvents']), true);
+        }
+
+        if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
+            yield ServiceSubscriberInterface::class;
+            yield print_r(\call_user_func([$class->name, 'getSubscribedServices']), true);
+        }
+    }
+}
+
+/**
+ * @internal
+ */
+class ReflectionMethodHhvmWrapper extends \ReflectionMethod
+{
+    public function getParameters()
+    {
+        $params = [];
+
+        foreach (parent::getParameters() as $i => $p) {
+            $params[] = new ReflectionParameterHhvmWrapper([$this->class, $this->name], $i);
+        }
+
+        return $params;
+    }
+}
+
+/**
+ * @internal
+ */
+class ReflectionParameterHhvmWrapper extends \ReflectionParameter
+{
+    public function getDefaultValue()
+    {
+        return [$this->isVariadic(), $this->isDefaultValueAvailable() ? parent::getDefaultValue() : null];
+    }
+}
diff --git a/civicrm/vendor/symfony/config/Resource/ResourceInterface.php b/civicrm/vendor/symfony/config/Resource/ResourceInterface.php
index 55b3e09648..d98fd427a2 100644
--- a/civicrm/vendor/symfony/config/Resource/ResourceInterface.php
+++ b/civicrm/vendor/symfony/config/Resource/ResourceInterface.php
@@ -30,29 +30,4 @@ interface ResourceInterface
      * @return string A string representation unique to the underlying Resource
      */
     public function __toString();
-
-    /**
-     * Returns true if the resource has not been updated since the given timestamp.
-     *
-     * @param int $timestamp The last time the resource was loaded
-     *
-     * @return bool True if the resource has not been updated, false otherwise
-     *
-     * @deprecated since 2.8, to be removed in 3.0. If your resource can check itself for
-     *             freshness implement the SelfCheckingResourceInterface instead.
-     */
-    public function isFresh($timestamp);
-
-    /**
-     * Returns the tied resource.
-     *
-     * @return mixed The resource
-     *
-     * @deprecated since 2.8, to be removed in 3.0. As there are many different kinds of resource,
-     *             a single getResource() method does not make sense at the interface level. You
-     *             can still call getResource() on implementing classes, probably after performing
-     *             a type check. If you know the concrete type of Resource at hand, the return value
-     *             of this method may make sense to you.
-     */
-    public function getResource();
 }
diff --git a/civicrm/vendor/symfony/config/ResourceCheckerConfigCache.php b/civicrm/vendor/symfony/config/ResourceCheckerConfigCache.php
index 81c1b97273..092b95bf01 100644
--- a/civicrm/vendor/symfony/config/ResourceCheckerConfigCache.php
+++ b/civicrm/vendor/symfony/config/ResourceCheckerConfigCache.php
@@ -29,15 +29,15 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
     private $file;
 
     /**
-     * @var ResourceCheckerInterface[]
+     * @var iterable|ResourceCheckerInterface[]
      */
     private $resourceCheckers;
 
     /**
-     * @param string                     $file             The absolute cache path
-     * @param ResourceCheckerInterface[] $resourceCheckers The ResourceCheckers to use for the freshness check
+     * @param string                              $file             The absolute cache path
+     * @param iterable|ResourceCheckerInterface[] $resourceCheckers The ResourceCheckers to use for the freshness check
      */
-    public function __construct($file, array $resourceCheckers = array())
+    public function __construct($file, $resourceCheckers = [])
     {
         $this->file = $file;
         $this->resourceCheckers = $resourceCheckers;
@@ -68,42 +68,28 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
             return false;
         }
 
-        if (!$this->resourceCheckers) {
+        if ($this->resourceCheckers instanceof \Traversable && !$this->resourceCheckers instanceof \Countable) {
+            $this->resourceCheckers = iterator_to_array($this->resourceCheckers);
+        }
+
+        if (!\count($this->resourceCheckers)) {
             return true; // shortcut - if we don't have any checkers we don't need to bother with the meta file at all
         }
 
         $metadata = $this->getMetaFile();
+
         if (!is_file($metadata)) {
             return false;
         }
 
-        $e = null;
-        $meta = false;
-        $time = filemtime($this->file);
-        $signalingException = new \UnexpectedValueException();
-        $prevUnserializeHandler = ini_set('unserialize_callback_func', '');
-        $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) use (&$prevErrorHandler, $signalingException) {
-            if (E_WARNING === $type && 'Class __PHP_Incomplete_Class has no unserializer' === $msg) {
-                throw $signalingException;
-            }
-
-            return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
-        });
+        $meta = $this->safelyUnserialize($metadata);
 
-        try {
-            $meta = unserialize(file_get_contents($metadata));
-        } catch (\Error $e) {
-        } catch (\Exception $e) {
-        }
-        restore_error_handler();
-        ini_set('unserialize_callback_func', $prevUnserializeHandler);
-        if (null !== $e && $e !== $signalingException) {
-            throw $e;
-        }
         if (false === $meta) {
             return false;
         }
 
+        $time = filemtime($this->file);
+
         foreach ($meta as $resource) {
             /* @var ResourceInterface $resource */
             foreach ($this->resourceCheckers as $checker) {
@@ -135,7 +121,7 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
         $mode = 0666;
         $umask = umask();
         $filesystem = new Filesystem();
-        $filesystem->dumpFile($this->file, $content, null);
+        $filesystem->dumpFile($this->file, $content);
         try {
             $filesystem->chmod($this->file, $mode, $umask);
         } catch (IOException $e) {
@@ -143,7 +129,7 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
         }
 
         if (null !== $metadata) {
-            $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null);
+            $filesystem->dumpFile($this->getMetaFile(), serialize($metadata));
             try {
                 $filesystem->chmod($this->getMetaFile(), $mode, $umask);
             } catch (IOException $e) {
@@ -165,4 +151,33 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
     {
         return $this->file.'.meta';
     }
+
+    private function safelyUnserialize($file)
+    {
+        $e = null;
+        $meta = false;
+        $content = file_get_contents($file);
+        $signalingException = new \UnexpectedValueException();
+        $prevUnserializeHandler = ini_set('unserialize_callback_func', '');
+        $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) {
+            if (__FILE__ === $file) {
+                throw $signalingException;
+            }
+
+            return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
+        });
+
+        try {
+            $meta = unserialize($content);
+        } catch (\Error $e) {
+        } catch (\Exception $e) {
+        }
+        restore_error_handler();
+        ini_set('unserialize_callback_func', $prevUnserializeHandler);
+        if (null !== $e && $e !== $signalingException) {
+            throw $e;
+        }
+
+        return $meta;
+    }
 }
diff --git a/civicrm/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php b/civicrm/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php
index 586c5bf280..c00fa7db1b 100644
--- a/civicrm/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php
+++ b/civicrm/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php
@@ -19,15 +19,12 @@ namespace Symfony\Component\Config;
  */
 class ResourceCheckerConfigCacheFactory implements ConfigCacheFactoryInterface
 {
-    /**
-     * @var ResourceCheckerInterface[]
-     */
-    private $resourceCheckers = array();
+    private $resourceCheckers = [];
 
     /**
-     * @param ResourceCheckerInterface[] $resourceCheckers
+     * @param iterable|ResourceCheckerInterface[] $resourceCheckers
      */
-    public function __construct(array $resourceCheckers = array())
+    public function __construct($resourceCheckers = [])
     {
         $this->resourceCheckers = $resourceCheckers;
     }
diff --git a/civicrm/vendor/symfony/config/Util/Exception/InvalidXmlException.php b/civicrm/vendor/symfony/config/Util/Exception/InvalidXmlException.php
new file mode 100644
index 0000000000..a335bbd2ee
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Util/Exception/InvalidXmlException.php
@@ -0,0 +1,21 @@
+<?php
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Util\Exception;
+
+/**
+ * Exception class for when XML parsing with an XSD schema file path or a callable validator produces errors unrelated
+ * to the actual XML parsing.
+ *
+ * @author Ole Rößner <ole@roessner.it>
+ */
+class InvalidXmlException extends XmlParsingException
+{
+}
diff --git a/civicrm/vendor/symfony/config/Util/Exception/XmlParsingException.php b/civicrm/vendor/symfony/config/Util/Exception/XmlParsingException.php
new file mode 100644
index 0000000000..9bceed660b
--- /dev/null
+++ b/civicrm/vendor/symfony/config/Util/Exception/XmlParsingException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Config\Util\Exception;
+
+/**
+ * Exception class for when XML cannot be parsed properly.
+ *
+ * @author Ole Rößner <ole@roessner.it>
+ */
+class XmlParsingException extends \InvalidArgumentException
+{
+}
diff --git a/civicrm/vendor/symfony/config/Util/XmlUtils.php b/civicrm/vendor/symfony/config/Util/XmlUtils.php
index 5ecbd2efdc..c925f315e5 100644
--- a/civicrm/vendor/symfony/config/Util/XmlUtils.php
+++ b/civicrm/vendor/symfony/config/Util/XmlUtils.php
@@ -11,6 +11,9 @@
 
 namespace Symfony\Component\Config\Util;
 
+use Symfony\Component\Config\Util\Exception\InvalidXmlException;
+use Symfony\Component\Config\Util\Exception\XmlParsingException;
+
 /**
  * XMLUtils is a bunch of utility methods to XML operations.
  *
@@ -18,6 +21,7 @@ namespace Symfony\Component\Config\Util;
  *
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Martin Hasoň <martin.hason@gmail.com>
+ * @author Ole Rößner <ole@roessner.it>
  */
 class XmlUtils
 {
@@ -29,27 +33,23 @@ class XmlUtils
     }
 
     /**
-     * Loads an XML file.
+     * Parses an XML string.
      *
-     * @param string               $file             An XML file path
+     * @param string               $content          An XML string
      * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
      *
      * @return \DOMDocument
      *
-     * @throws \InvalidArgumentException When loading of XML file returns error
-     * @throws \RuntimeException         When DOM extension is missing
+     * @throws XmlParsingException When parsing of XML file returns error
+     * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself
+     * @throws \RuntimeException   When DOM extension is missing
      */
-    public static function loadFile($file, $schemaOrCallable = null)
+    public static function parse($content, $schemaOrCallable = null)
     {
         if (!\extension_loaded('dom')) {
             throw new \RuntimeException('Extension DOM is required.');
         }
 
-        $content = @file_get_contents($file);
-        if ('' === trim($content)) {
-            throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file));
-        }
-
         $internalErrors = libxml_use_internal_errors(true);
         $disableEntities = libxml_disable_entity_loader(true);
         libxml_clear_errors();
@@ -59,7 +59,7 @@ class XmlUtils
         if (!$dom->loadXML($content, LIBXML_NONET | (\defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
             libxml_disable_entity_loader($disableEntities);
 
-            throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors)));
+            throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors)));
         }
 
         $dom->normalizeDocument();
@@ -69,7 +69,7 @@ class XmlUtils
 
         foreach ($dom->childNodes as $child) {
             if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
-                throw new \InvalidArgumentException('Document types are not allowed.');
+                throw new XmlParsingException('Document types are not allowed.');
             }
         }
 
@@ -90,15 +90,15 @@ class XmlUtils
             } else {
                 libxml_use_internal_errors($internalErrors);
 
-                throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
+                throw new XmlParsingException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
             }
 
             if (!$valid) {
                 $messages = static::getXmlErrors($internalErrors);
                 if (empty($messages)) {
-                    $messages = array(sprintf('The XML file "%s" is not valid.', $file));
+                    throw new InvalidXmlException('The XML is not valid.', 0, $e);
                 }
-                throw new \InvalidArgumentException(implode("\n", $messages), 0, $e);
+                throw new XmlParsingException(implode("\n", $messages), 0, $e);
             }
         }
 
@@ -108,6 +108,41 @@ class XmlUtils
         return $dom;
     }
 
+    /**
+     * Loads an XML file.
+     *
+     * @param string               $file             An XML file path
+     * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
+     *
+     * @return \DOMDocument
+     *
+     * @throws \InvalidArgumentException When loading of XML file returns error
+     * @throws XmlParsingException       When XML parsing returns any errors
+     * @throws \RuntimeException         When DOM extension is missing
+     */
+    public static function loadFile($file, $schemaOrCallable = null)
+    {
+        if (!is_file($file)) {
+            throw new \InvalidArgumentException(sprintf('Resource "%s" is not a file.', $file));
+        }
+
+        if (!is_readable($file)) {
+            throw new \InvalidArgumentException(sprintf('File "%s" is not readable.', $file));
+        }
+
+        $content = @file_get_contents($file);
+
+        if ('' === trim($content)) {
+            throw new \InvalidArgumentException(sprintf('File "%s" does not contain valid XML, it is empty.', $file));
+        }
+
+        try {
+            return static::parse($content, $schemaOrCallable);
+        } catch (InvalidXmlException $e) {
+            throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious());
+        }
+    }
+
     /**
      * Converts a \DOMElement object to a PHP array.
      *
@@ -126,15 +161,15 @@ class XmlUtils
      * @param \DOMElement $element     A \DOMElement instance
      * @param bool        $checkPrefix Check prefix in an element or an attribute name
      *
-     * @return array A PHP array
+     * @return mixed
      */
     public static function convertDomElementToArray(\DOMElement $element, $checkPrefix = true)
     {
         $prefix = (string) $element->prefix;
         $empty = true;
-        $config = array();
+        $config = [];
         foreach ($element->attributes as $name => $node) {
-            if ($checkPrefix && !\in_array((string) $node->prefix, array('', $prefix), true)) {
+            if ($checkPrefix && !\in_array((string) $node->prefix, ['', $prefix], true)) {
                 continue;
             }
             $config[$name] = static::phpize($node->value);
@@ -156,7 +191,7 @@ class XmlUtils
                 $key = $node->localName;
                 if (isset($config[$key])) {
                     if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) {
-                        $config[$key] = array($config[$key]);
+                        $config[$key] = [$config[$key]];
                     }
                     $config[$key][] = $value;
                 } else {
@@ -193,7 +228,7 @@ class XmlUtils
 
         switch (true) {
             case 'null' === $lowercaseValue:
-                return;
+                return null;
             case ctype_digit($value):
                 $raw = $value;
                 $cast = (int) $value;
@@ -208,13 +243,13 @@ class XmlUtils
                 return true;
             case 'false' === $lowercaseValue:
                 return false;
-            case isset($value[1]) && '0b' == $value[0].$value[1]:
+            case isset($value[1]) && '0b' == $value[0].$value[1] && preg_match('/^0b[01]*$/', $value):
                 return bindec($value);
             case is_numeric($value):
                 return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value;
             case preg_match('/^0x[0-9a-f]++$/i', $value):
                 return hexdec($value);
-            case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value):
+            case preg_match('/^[+-]?[0-9]+(\.[0-9]+)?$/', $value):
                 return (float) $value;
             default:
                 return $value;
@@ -223,7 +258,7 @@ class XmlUtils
 
     protected static function getXmlErrors($internalErrors)
     {
-        $errors = array();
+        $errors = [];
         foreach (libxml_get_errors() as $error) {
             $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
                 LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
diff --git a/civicrm/vendor/symfony/config/composer.json b/civicrm/vendor/symfony/config/composer.json
index ee1322ccdb..c04294dd4c 100644
--- a/civicrm/vendor/symfony/config/composer.json
+++ b/civicrm/vendor/symfony/config/composer.json
@@ -16,12 +16,19 @@
         }
     ],
     "require": {
-        "php": ">=5.3.9",
-        "symfony/filesystem": "~2.3|~3.0.0",
+        "php": "^5.5.9|>=7.0.8",
+        "symfony/filesystem": "~2.8|~3.0|~4.0",
         "symfony/polyfill-ctype": "~1.8"
     },
     "require-dev": {
-        "symfony/yaml": "~2.7|~3.0.0"
+        "symfony/finder": "~3.3|~4.0",
+        "symfony/yaml": "~3.0|~4.0",
+        "symfony/dependency-injection": "~3.3|~4.0",
+        "symfony/event-dispatcher": "~3.3|~4.0"
+    },
+    "conflict": {
+        "symfony/finder": "<3.3",
+        "symfony/dependency-injection": "<3.3"
     },
     "suggest": {
         "symfony/yaml": "To use the yaml reference dumper"
@@ -35,7 +42,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "2.8-dev"
+            "dev-master": "3.4-dev"
         }
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Alias.php b/civicrm/vendor/symfony/dependency-injection/Alias.php
index eaf7f00ccd..de14c5ea95 100644
--- a/civicrm/vendor/symfony/dependency-injection/Alias.php
+++ b/civicrm/vendor/symfony/dependency-injection/Alias.php
@@ -15,6 +15,7 @@ class Alias
 {
     private $id;
     private $public;
+    private $private;
 
     /**
      * @param string $id     Alias identifier
@@ -22,8 +23,9 @@ class Alias
      */
     public function __construct($id, $public = true)
     {
-        $this->id = strtolower($id);
+        $this->id = (string) $id;
         $this->public = $public;
+        $this->private = 2 > \func_num_args();
     }
 
     /**
@@ -40,10 +42,44 @@ class Alias
      * Sets if this Alias is public.
      *
      * @param bool $boolean If this Alias should be public
+     *
+     * @return $this
      */
     public function setPublic($boolean)
     {
         $this->public = (bool) $boolean;
+        $this->private = false;
+
+        return $this;
+    }
+
+    /**
+     * Sets if this Alias is private.
+     *
+     * When set, the "private" state has a higher precedence than "public".
+     * In version 3.4, a "private" alias always remains publicly accessible,
+     * but triggers a deprecation notice when accessed from the container,
+     * so that the alias can be made really private in 4.0.
+     *
+     * @param bool $boolean
+     *
+     * @return $this
+     */
+    public function setPrivate($boolean)
+    {
+        $this->private = (bool) $boolean;
+
+        return $this;
+    }
+
+    /**
+     * Whether this alias is private.
+     *
+     * @return bool
+     */
+    public function isPrivate()
+    {
+        return $this->private;
     }
 
     /**
diff --git a/civicrm/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php b/civicrm/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php
new file mode 100644
index 0000000000..b46eb77be7
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+/**
+ * Represents a complex argument containing nested values.
+ *
+ * @author Titouan Galopin <galopintitouan@gmail.com>
+ */
+interface ArgumentInterface
+{
+    /**
+     * @return array
+     */
+    public function getValues();
+
+    public function setValues(array $values);
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Argument/BoundArgument.php b/civicrm/vendor/symfony/dependency-injection/Argument/BoundArgument.php
new file mode 100644
index 0000000000..a20698440c
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Argument/BoundArgument.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+/**
+ * @author Guilhem Niot <guilhem.niot@gmail.com>
+ */
+final class BoundArgument implements ArgumentInterface
+{
+    private static $sequence = 0;
+
+    private $value;
+    private $identifier;
+    private $used;
+
+    public function __construct($value)
+    {
+        $this->value = $value;
+        $this->identifier = ++self::$sequence;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getValues()
+    {
+        return [$this->value, $this->identifier, $this->used];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setValues(array $values)
+    {
+        list($this->value, $this->identifier, $this->used) = $values;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Argument/IteratorArgument.php b/civicrm/vendor/symfony/dependency-injection/Argument/IteratorArgument.php
new file mode 100644
index 0000000000..2d796d2d8f
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Argument/IteratorArgument.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Represents a collection of values to lazily iterate over.
+ *
+ * @author Titouan Galopin <galopintitouan@gmail.com>
+ */
+class IteratorArgument implements ArgumentInterface
+{
+    private $values;
+
+    /**
+     * @param Reference[] $values
+     */
+    public function __construct(array $values)
+    {
+        $this->setValues($values);
+    }
+
+    /**
+     * @return array The values to lazily iterate over
+     */
+    public function getValues()
+    {
+        return $this->values;
+    }
+
+    /**
+     * @param Reference[] $values The service references to lazily iterate over
+     */
+    public function setValues(array $values)
+    {
+        foreach ($values as $k => $v) {
+            if (null !== $v && !$v instanceof Reference) {
+                throw new InvalidArgumentException(sprintf('An IteratorArgument must hold only Reference instances, "%s" given.', \is_object($v) ? \get_class($v) : \gettype($v)));
+            }
+        }
+
+        $this->values = $values;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php b/civicrm/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php
new file mode 100644
index 0000000000..b00a36c34f
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+/**
+ * @internal
+ */
+class RewindableGenerator implements \IteratorAggregate, \Countable
+{
+    private $generator;
+    private $count;
+
+    /**
+     * @param int|callable $count
+     */
+    public function __construct(callable $generator, $count)
+    {
+        $this->generator = $generator;
+        $this->count = $count;
+    }
+
+    public function getIterator()
+    {
+        $g = $this->generator;
+
+        return $g();
+    }
+
+    public function count()
+    {
+        if (\is_callable($count = $this->count)) {
+            $this->count = $count();
+        }
+
+        return $this->count;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php b/civicrm/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php
new file mode 100644
index 0000000000..6331affa48
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Represents a service wrapped in a memoizing closure.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ServiceClosureArgument implements ArgumentInterface
+{
+    private $values;
+
+    public function __construct(Reference $reference)
+    {
+        $this->values = [$reference];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getValues()
+    {
+        return $this->values;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setValues(array $values)
+    {
+        if ([0] !== array_keys($values) || !($values[0] instanceof Reference || null === $values[0])) {
+            throw new InvalidArgumentException('A ServiceClosureArgument must hold one and only one Reference.');
+        }
+
+        $this->values = $values;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php b/civicrm/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php
new file mode 100644
index 0000000000..f00e533919
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+/**
+ * Represents a collection of services found by tag name to lazily iterate over.
+ *
+ * @author Roland Franssen <franssen.roland@gmail.com>
+ */
+class TaggedIteratorArgument extends IteratorArgument
+{
+    private $tag;
+
+    /**
+     * @param string $tag
+     */
+    public function __construct($tag)
+    {
+        parent::__construct([]);
+
+        $this->tag = (string) $tag;
+    }
+
+    public function getTag()
+    {
+        return $this->tag;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/CHANGELOG.md b/civicrm/vendor/symfony/dependency-injection/CHANGELOG.md
index 27cb2d58a4..a004161b96 100644
--- a/civicrm/vendor/symfony/dependency-injection/CHANGELOG.md
+++ b/civicrm/vendor/symfony/dependency-injection/CHANGELOG.md
@@ -1,6 +1,65 @@
 CHANGELOG
 =========
 
+3.4.0
+-----
+
+ * moved the `ExtensionCompilerPass` to before-optimization passes with priority -1000
+ * deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0
+ * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars
+ * added support for ignore-on-uninitialized references
+ * deprecated service auto-registration while autowiring
+ * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method
+ * deprecated support for top-level anonymous services in XML
+ * deprecated case insensitivity of parameter names
+ * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass`
+ * added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (`<service type="tagged"/>`) support
+ * deprecated `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead
+
+
+3.3.0
+-----
+
+ * deprecated autowiring services based on the types they implement;
+   rename (or alias) your services to their FQCN id to make them autowirable
+ * added "ServiceSubscriberInterface" - to allow for per-class explicit service-locator definitions
+ * added "container.service_locator" tag for defining service-locator services
+ * added anonymous services support in YAML configuration files using the `!service` tag.
+ * added "TypedReference" and "ServiceClosureArgument" for creating service-locator services
+ * added `ServiceLocator` - a PSR-11 container holding a set of services to be lazily loaded
+ * added "instanceof" section for local interface-defined configs
+ * added prototype services for PSR4-based discovery and registration
+ * added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info
+ * deprecated `ContainerBuilder::getClassResource()`, use `ContainerBuilder::getReflectionClass()` or `ContainerBuilder::addObjectResource()` instead
+ * added `ContainerBuilder::fileExists()` for checking and tracking file or directory existence
+ * deprecated autowiring-types, use aliases instead
+ * added support for omitting the factory class name in a service definition if the definition class is set
+ * deprecated case insensitivity of service identifiers
+ * added "iterator" argument type for lazy iteration over a set of values and services
+ * added file-wide configurable defaults for service attributes "public", "tags",
+   "autowire" and "autoconfigure"
+ * made the "class" attribute optional, using the "id" as fallback
+ * using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and
+   will not be supported anymore in 4.0
+ * deprecated the `DefinitionDecorator` class in favor of `ChildDefinition`
+ * allow config files to be loaded using a glob pattern
+ * [BC BREAK] the `NullDumper` class is now final
+
+3.2.0
+-----
+
+ * allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()`
+ * added support for PHP constants in YAML configuration files
+ * deprecated the ability to set or unset a private service with the `Container::set()` method
+ * deprecated the ability to check for the existence of a private service with the `Container::has()` method
+ * deprecated the ability to request a private service with the `Container::get()` method
+ * deprecated support for generating a dumped `Container` without populating the method map
+
+3.0.0
+-----
+
+ * removed all deprecated codes from 2.x versions
+
 2.8.0
 -----
 
diff --git a/civicrm/vendor/symfony/dependency-injection/ChildDefinition.php b/civicrm/vendor/symfony/dependency-injection/ChildDefinition.php
new file mode 100644
index 0000000000..123b387475
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/ChildDefinition.php
@@ -0,0 +1,126 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
+
+/**
+ * This definition extends another definition.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class ChildDefinition extends Definition
+{
+    private $parent;
+
+    /**
+     * @param string $parent The id of Definition instance to decorate
+     */
+    public function __construct($parent)
+    {
+        $this->parent = $parent;
+        $this->setPrivate(false);
+    }
+
+    /**
+     * Returns the Definition to inherit from.
+     *
+     * @return string
+     */
+    public function getParent()
+    {
+        return $this->parent;
+    }
+
+    /**
+     * Sets the Definition to inherit from.
+     *
+     * @param string $parent
+     *
+     * @return $this
+     */
+    public function setParent($parent)
+    {
+        $this->parent = $parent;
+
+        return $this;
+    }
+
+    /**
+     * Gets an argument to pass to the service constructor/factory method.
+     *
+     * If replaceArgument() has been used to replace an argument, this method
+     * will return the replacement value.
+     *
+     * @param int|string $index
+     *
+     * @return mixed The argument value
+     *
+     * @throws OutOfBoundsException When the argument does not exist
+     */
+    public function getArgument($index)
+    {
+        if (\array_key_exists('index_'.$index, $this->arguments)) {
+            return $this->arguments['index_'.$index];
+        }
+
+        return parent::getArgument($index);
+    }
+
+    /**
+     * You should always use this method when overwriting existing arguments
+     * of the parent definition.
+     *
+     * If you directly call setArguments() keep in mind that you must follow
+     * certain conventions when you want to overwrite the arguments of the
+     * parent definition, otherwise your arguments will only be appended.
+     *
+     * @param int|string $index
+     * @param mixed      $value
+     *
+     * @return $this
+     *
+     * @throws InvalidArgumentException when $index isn't an integer
+     */
+    public function replaceArgument($index, $value)
+    {
+        if (\is_int($index)) {
+            $this->arguments['index_'.$index] = $value;
+        } elseif (0 === strpos($index, '$')) {
+            $this->arguments[$index] = $value;
+        } else {
+            throw new InvalidArgumentException('The argument must be an existing index or the name of a constructor\'s parameter.');
+        }
+
+        return $this;
+    }
+
+    /**
+     * @internal
+     */
+    public function setAutoconfigured($autoconfigured)
+    {
+        throw new BadMethodCallException('A ChildDefinition cannot be autoconfigured.');
+    }
+
+    /**
+     * @internal
+     */
+    public function setInstanceofConditionals(array $instanceof)
+    {
+        throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.');
+    }
+}
+
+class_alias(ChildDefinition::class, DefinitionDecorator::class);
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
new file mode 100644
index 0000000000..27969e7067
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
@@ -0,0 +1,174 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+abstract class AbstractRecursivePass implements CompilerPassInterface
+{
+    /**
+     * @var ContainerBuilder
+     */
+    protected $container;
+    protected $currentId;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        $this->container = $container;
+
+        try {
+            $this->processValue($container->getDefinitions(), true);
+        } finally {
+            $this->container = null;
+        }
+    }
+
+    /**
+     * Processes a value found in a definition tree.
+     *
+     * @param mixed $value
+     * @param bool  $isRoot
+     *
+     * @return mixed The processed value
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if (\is_array($value)) {
+            foreach ($value as $k => $v) {
+                if ($isRoot) {
+                    $this->currentId = $k;
+                }
+                if ($v !== $processedValue = $this->processValue($v, $isRoot)) {
+                    $value[$k] = $processedValue;
+                }
+            }
+        } elseif ($value instanceof ArgumentInterface) {
+            $value->setValues($this->processValue($value->getValues()));
+        } elseif ($value instanceof Definition) {
+            $value->setArguments($this->processValue($value->getArguments()));
+            $value->setProperties($this->processValue($value->getProperties()));
+            $value->setMethodCalls($this->processValue($value->getMethodCalls()));
+
+            $changes = $value->getChanges();
+            if (isset($changes['factory'])) {
+                $value->setFactory($this->processValue($value->getFactory()));
+            }
+            if (isset($changes['configurator'])) {
+                $value->setConfigurator($this->processValue($value->getConfigurator()));
+            }
+        }
+
+        return $value;
+    }
+
+    /**
+     * @param bool $required
+     *
+     * @return \ReflectionFunctionAbstract|null
+     *
+     * @throws RuntimeException
+     */
+    protected function getConstructor(Definition $definition, $required)
+    {
+        if ($definition->isSynthetic()) {
+            return null;
+        }
+
+        if (\is_string($factory = $definition->getFactory())) {
+            if (!\function_exists($factory)) {
+                throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory));
+            }
+            $r = new \ReflectionFunction($factory);
+            if (false !== $r->getFileName() && file_exists($r->getFileName())) {
+                $this->container->fileExists($r->getFileName());
+            }
+
+            return $r;
+        }
+
+        if ($factory) {
+            list($class, $method) = $factory;
+            if ($class instanceof Reference) {
+                $class = $this->container->findDefinition((string) $class)->getClass();
+            } elseif (null === $class) {
+                $class = $definition->getClass();
+            }
+            if ('__construct' === $method) {
+                throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
+            }
+
+            return $this->getReflectionMethod(new Definition($class), $method);
+        }
+
+        $class = $definition->getClass();
+
+        try {
+            if (!$r = $this->container->getReflectionClass($class)) {
+                throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
+            }
+        } catch (\ReflectionException $e) {
+            throw new RuntimeException(sprintf('Invalid service "%s": '.lcfirst($e->getMessage()), $this->currentId));
+        }
+        if (!$r = $r->getConstructor()) {
+            if ($required) {
+                throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class)));
+            }
+        } elseif (!$r->isPublic()) {
+            throw new RuntimeException(sprintf('Invalid service "%s": %s must be public.', $this->currentId, sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class)));
+        }
+
+        return $r;
+    }
+
+    /**
+     * @param string $method
+     *
+     * @throws RuntimeException
+     *
+     * @return \ReflectionFunctionAbstract
+     */
+    protected function getReflectionMethod(Definition $definition, $method)
+    {
+        if ('__construct' === $method) {
+            return $this->getConstructor($definition, true);
+        }
+
+        if (!$class = $definition->getClass()) {
+            throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
+        }
+
+        if (!$r = $this->container->getReflectionClass($class)) {
+            throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
+        }
+
+        if (!$r->hasMethod($method)) {
+            throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
+        }
+
+        $r = $r->getMethod($method);
+        if (!$r->isPublic()) {
+            throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
+        }
+
+        return $r;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
index ce9d556eaf..bff9d42079 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
@@ -11,9 +11,14 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\ExpressionLanguage;
 use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\ExpressionLanguage\Expression;
 
 /**
  * Run this pass before passes that need to know more about the relation of
@@ -24,20 +29,23 @@ use Symfony\Component\DependencyInjection\Reference;
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class AnalyzeServiceReferencesPass implements RepeatablePassInterface
+class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements RepeatablePassInterface
 {
     private $graph;
-    private $container;
-    private $currentId;
     private $currentDefinition;
     private $onlyConstructorArguments;
+    private $hasProxyDumper;
+    private $lazy;
+    private $expressionLanguage;
+    private $byConstructor;
 
     /**
      * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
      */
-    public function __construct($onlyConstructorArguments = false)
+    public function __construct($onlyConstructorArguments = false, $hasProxyDumper = true)
     {
         $this->onlyConstructorArguments = (bool) $onlyConstructorArguments;
+        $this->hasProxyDumper = (bool) $hasProxyDumper;
     }
 
     /**
@@ -56,68 +64,77 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
         $this->container = $container;
         $this->graph = $container->getCompiler()->getServiceReferenceGraph();
         $this->graph->clear();
+        $this->lazy = false;
+        $this->byConstructor = false;
 
-        foreach ($container->getDefinitions() as $id => $definition) {
-            if ($definition->isSynthetic() || $definition->isAbstract()) {
-                continue;
-            }
+        foreach ($container->getAliases() as $id => $alias) {
+            $targetId = $this->getDefinitionId((string) $alias);
+            $this->graph->connect($id, $alias, $targetId, $this->getDefinition($targetId), null);
+        }
 
-            $this->currentId = $id;
-            $this->currentDefinition = $definition;
+        parent::process($container);
+    }
 
-            $this->processArguments($definition->getArguments());
-            if ($definition->getFactoryService(false)) {
-                $this->processArguments(array(new Reference($definition->getFactoryService(false))));
-            }
-            if (\is_array($definition->getFactory())) {
-                $this->processArguments($definition->getFactory());
-            }
+    protected function processValue($value, $isRoot = false)
+    {
+        $lazy = $this->lazy;
 
-            if (!$this->onlyConstructorArguments) {
-                $this->processArguments($definition->getMethodCalls());
-                $this->processArguments($definition->getProperties());
-                if ($definition->getConfigurator()) {
-                    $this->processArguments(array($definition->getConfigurator()));
-                }
-            }
-        }
+        if ($value instanceof ArgumentInterface) {
+            $this->lazy = true;
+            parent::processValue($value->getValues());
+            $this->lazy = $lazy;
 
-        foreach ($container->getAliases() as $id => $alias) {
-            $this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null);
+            return $value;
         }
-    }
+        if ($value instanceof Expression) {
+            $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']);
 
-    /**
-     * Processes service definitions for arguments to find relationships for the service graph.
-     *
-     * @param array $arguments An array of Reference or Definition objects relating to service definitions
-     */
-    private function processArguments(array $arguments)
-    {
-        foreach ($arguments as $argument) {
-            if (\is_array($argument)) {
-                $this->processArguments($argument);
-            } elseif ($argument instanceof Reference) {
-                $this->graph->connect(
-                    $this->currentId,
-                    $this->currentDefinition,
-                    $this->getDefinitionId((string) $argument),
-                    $this->getDefinition((string) $argument),
-                    $argument
-                );
-            } elseif ($argument instanceof Definition) {
-                $this->processArguments($argument->getArguments());
-                $this->processArguments($argument->getMethodCalls());
-                $this->processArguments($argument->getProperties());
-
-                if (\is_array($argument->getFactory())) {
-                    $this->processArguments($argument->getFactory());
-                }
-                if ($argument->getFactoryService(false)) {
-                    $this->processArguments(array(new Reference($argument->getFactoryService(false))));
-                }
+            return $value;
+        }
+        if ($value instanceof Reference) {
+            $targetId = $this->getDefinitionId((string) $value);
+            $targetDefinition = $this->getDefinition($targetId);
+
+            $this->graph->connect(
+                $this->currentId,
+                $this->currentDefinition,
+                $targetId,
+                $targetDefinition,
+                $value,
+                $this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()),
+                ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior(),
+                $this->byConstructor
+            );
+
+            return $value;
+        }
+        if (!$value instanceof Definition) {
+            return parent::processValue($value, $isRoot);
+        }
+        if ($isRoot) {
+            if ($value->isSynthetic() || $value->isAbstract()) {
+                return $value;
             }
+            $this->currentDefinition = $value;
+        } elseif ($this->currentDefinition === $value) {
+            return $value;
         }
+        $this->lazy = false;
+
+        $byConstructor = $this->byConstructor;
+        $this->byConstructor = $isRoot || $byConstructor;
+        $this->processValue($value->getFactory());
+        $this->processValue($value->getArguments());
+        $this->byConstructor = $byConstructor;
+
+        if (!$this->onlyConstructorArguments) {
+            $this->processValue($value->getProperties());
+            $this->processValue($value->getMethodCalls());
+            $this->processValue($value->getConfigurator());
+        }
+        $this->lazy = $lazy;
+
+        return $value;
     }
 
     /**
@@ -129,8 +146,6 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
      */
     private function getDefinition($id)
     {
-        $id = $this->getDefinitionId($id);
-
         return null === $id ? null : $this->container->getDefinition($id);
     }
 
@@ -141,9 +156,37 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
         }
 
         if (!$this->container->hasDefinition($id)) {
-            return;
+            return null;
+        }
+
+        return $this->container->normalizeId($id);
+    }
+
+    private function getExpressionLanguage()
+    {
+        if (null === $this->expressionLanguage) {
+            if (!class_exists(ExpressionLanguage::class)) {
+                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
+            }
+
+            $providers = $this->container->getExpressionLanguageProviders();
+            $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
+                if ('""' === substr_replace($arg, '', 1, -1)) {
+                    $id = stripcslashes(substr($arg, 1, -1));
+                    $id = $this->getDefinitionId($id);
+
+                    $this->graph->connect(
+                        $this->currentId,
+                        $this->currentDefinition,
+                        $id,
+                        $this->getDefinition($id)
+                    );
+                }
+
+                return sprintf('$this->get(%s)', $arg);
+            });
         }
 
-        return $id;
+        return $this->expressionLanguage;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php
index c1f05e03ec..03420683a2 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php
@@ -33,7 +33,7 @@ class AutoAliasServicePass implements CompilerPassInterface
 
                 $aliasId = $container->getParameterBag()->resolveValue($tag['format']);
                 if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) {
-                    $container->setAlias($serviceId, new Alias($aliasId));
+                    $container->setAlias($serviceId, new Alias($aliasId, true));
                 }
             }
         }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php
new file mode 100644
index 0000000000..9a4c74d359
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+@trigger_error('The '.__NAMESPACE__.'\AutowireExceptionPass class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the DefinitionErrorExceptionPass class instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Throws autowire exceptions from AutowirePass for definitions that still exist.
+ *
+ * @deprecated since version 3.4, will be removed in 4.0.
+ *
+ * @author Ryan Weaver <ryan@knpuniversity.com>
+ */
+class AutowireExceptionPass implements CompilerPassInterface
+{
+    private $autowirePass;
+    private $inlineServicePass;
+
+    public function __construct(AutowirePass $autowirePass, InlineServiceDefinitionsPass $inlineServicePass)
+    {
+        $this->autowirePass = $autowirePass;
+        $this->inlineServicePass = $inlineServicePass;
+    }
+
+    public function process(ContainerBuilder $container)
+    {
+        // the pass should only be run once
+        if (null === $this->autowirePass || null === $this->inlineServicePass) {
+            return;
+        }
+
+        $inlinedIds = $this->inlineServicePass->getInlinedServiceIds();
+        $exceptions = $this->autowirePass->getAutowiringExceptions();
+
+        // free up references
+        $this->autowirePass = null;
+        $this->inlineServicePass = null;
+
+        foreach ($exceptions as $exception) {
+            if ($this->doesServiceExistInTheContainer($exception->getServiceId(), $container, $inlinedIds)) {
+                throw $exception;
+            }
+        }
+    }
+
+    private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $container, array $inlinedIds)
+    {
+        if ($container->hasDefinition($serviceId)) {
+            return true;
+        }
+
+        // was the service inlined? Of so, does its parent service exist?
+        if (isset($inlinedIds[$serviceId])) {
+            foreach ($inlinedIds[$serviceId] as $parentId) {
+                if ($this->doesServiceExistInTheContainer($parentId, $container, $inlinedIds)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/AutowirePass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/AutowirePass.php
index b279548553..91b279c77a 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/AutowirePass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/AutowirePass.php
@@ -11,143 +11,249 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
+use Symfony\Component\Config\Resource\ClassExistenceResource;
+use Symfony\Component\DependencyInjection\Config\AutowireServiceResource;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
-use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
+use Symfony\Component\DependencyInjection\TypedReference;
 
 /**
- * Guesses constructor arguments of services definitions and try to instantiate services if necessary.
+ * Inspects existing service definitions and wires the autowired ones using the type hints of their classes.
  *
  * @author Kévin Dunglas <dunglas@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
  */
-class AutowirePass implements CompilerPassInterface
+class AutowirePass extends AbstractRecursivePass
 {
-    private $container;
-    private $reflectionClasses = array();
-    private $definedTypes = array();
+    private $definedTypes = [];
     private $types;
-    private $notGuessableTypes = array();
-    private $autowired = array();
+    private $ambiguousServiceTypes;
+    private $autowired = [];
+    private $lastFailure;
+    private $throwOnAutowiringException;
+    private $autowiringExceptions = [];
+    private $strictMode;
+
+    /**
+     * @param bool $throwOnAutowireException Errors can be retrieved via Definition::getErrors()
+     */
+    public function __construct($throwOnAutowireException = true)
+    {
+        $this->throwOnAutowiringException = $throwOnAutowireException;
+    }
+
+    /**
+     * @deprecated since version 3.4, to be removed in 4.0.
+     *
+     * @return AutowiringFailedException[]
+     */
+    public function getAutowiringExceptions()
+    {
+        @trigger_error('Calling AutowirePass::getAutowiringExceptions() is deprecated since Symfony 3.4 and will be removed in 4.0. Use Definition::getErrors() instead.', E_USER_DEPRECATED);
+
+        return $this->autowiringExceptions;
+    }
 
     /**
      * {@inheritdoc}
      */
     public function process(ContainerBuilder $container)
     {
-        $throwingAutoloader = function ($class) { throw new \ReflectionException(sprintf('Class %s does not exist', $class)); };
-        spl_autoload_register($throwingAutoloader);
+        // clear out any possibly stored exceptions from before
+        $this->autowiringExceptions = [];
+        $this->strictMode = $container->hasParameter('container.autowiring.strict_mode') && $container->getParameter('container.autowiring.strict_mode');
 
         try {
-            $this->container = $container;
-            foreach ($container->getDefinitions() as $id => $definition) {
-                if ($definition->isAutowired()) {
-                    $this->completeDefinition($id, $definition);
-                }
-            }
-        } catch (\Exception $e) {
-        } catch (\Throwable $e) {
+            parent::process($container);
+        } finally {
+            $this->definedTypes = [];
+            $this->types = null;
+            $this->ambiguousServiceTypes = null;
+            $this->autowired = [];
         }
+    }
 
-        spl_autoload_unregister($throwingAutoloader);
+    /**
+     * Creates a resource to help know if this service has changed.
+     *
+     * @return AutowireServiceResource
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.
+     */
+    public static function createResourceForClass(\ReflectionClass $reflectionClass)
+    {
+        @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', E_USER_DEPRECATED);
 
-        // Free memory and remove circular reference to container
-        $this->container = null;
-        $this->reflectionClasses = array();
-        $this->definedTypes = array();
-        $this->types = null;
-        $this->notGuessableTypes = array();
-        $this->autowired = array();
+        $metadata = [];
 
-        if (isset($e)) {
-            throw $e;
+        foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
+            if (!$reflectionMethod->isStatic()) {
+                $metadata[$reflectionMethod->name] = self::getResourceMetadataForMethod($reflectionMethod);
+            }
         }
+
+        return new AutowireServiceResource($reflectionClass->name, $reflectionClass->getFileName(), $metadata);
     }
 
     /**
-     * Wires the given definition.
-     *
-     * @param string     $id
-     * @param Definition $definition
-     *
-     * @throws RuntimeException
+     * {@inheritdoc}
      */
-    private function completeDefinition($id, Definition $definition)
+    protected function processValue($value, $isRoot = false)
     {
-        if ($definition->getFactory() || $definition->getFactoryClass(false) || $definition->getFactoryService(false)) {
-            throw new RuntimeException(sprintf('Service "%s" can use either autowiring or a factory, not both.', $id));
+        try {
+            return $this->doProcessValue($value, $isRoot);
+        } catch (AutowiringFailedException $e) {
+            if ($this->throwOnAutowiringException) {
+                throw $e;
+            }
+
+            $this->autowiringExceptions[] = $e;
+            $this->container->getDefinition($this->currentId)->addError($e->getMessage());
+
+            return parent::processValue($value, $isRoot);
         }
+    }
 
-        if (!$reflectionClass = $this->getReflectionClass($id, $definition)) {
-            return;
+    private function doProcessValue($value, $isRoot = false)
+    {
+        if ($value instanceof TypedReference) {
+            if ($ref = $this->getAutowiredReference($value, $value->getRequiringClass() ? sprintf('for "%s" in "%s"', $value->getType(), $value->getRequiringClass()) : '')) {
+                return $ref;
+            }
+            $this->container->log($this, $this->createTypeNotFoundMessage($value, 'it'));
         }
+        $value = parent::processValue($value, $isRoot);
 
-        $this->container->addClassResource($reflectionClass);
+        if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
+            return $value;
+        }
+        if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) {
+            $this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass()));
 
-        if (!$constructor = $reflectionClass->getConstructor()) {
-            return;
+            return $value;
         }
-        $parameters = $constructor->getParameters();
-        if (method_exists('ReflectionMethod', 'isVariadic') && $constructor->isVariadic()) {
-            array_pop($parameters);
+
+        $methodCalls = $value->getMethodCalls();
+
+        try {
+            $constructor = $this->getConstructor($value, false);
+        } catch (RuntimeException $e) {
+            throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
         }
 
-        $arguments = $definition->getArguments();
-        foreach ($parameters as $index => $parameter) {
-            if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
-                continue;
+        if ($constructor) {
+            array_unshift($methodCalls, [$constructor, $value->getArguments()]);
+        }
+
+        $methodCalls = $this->autowireCalls($reflectionClass, $methodCalls);
+
+        if ($constructor) {
+            list(, $arguments) = array_shift($methodCalls);
+
+            if ($arguments !== $value->getArguments()) {
+                $value->setArguments($arguments);
             }
+        }
 
-            try {
-                if (!$typeHint = $parameter->getClass()) {
-                    if (isset($arguments[$index])) {
+        if ($methodCalls !== $value->getMethodCalls()) {
+            $value->setMethodCalls($methodCalls);
+        }
+
+        return $value;
+    }
+
+    /**
+     * @return array
+     */
+    private function autowireCalls(\ReflectionClass $reflectionClass, array $methodCalls)
+    {
+        foreach ($methodCalls as $i => $call) {
+            list($method, $arguments) = $call;
+
+            if ($method instanceof \ReflectionFunctionAbstract) {
+                $reflectionMethod = $method;
+            } else {
+                $definition = new Definition($reflectionClass->name);
+                try {
+                    $reflectionMethod = $this->getReflectionMethod($definition, $method);
+                } catch (RuntimeException $e) {
+                    if ($definition->getFactory()) {
                         continue;
                     }
+                    throw $e;
+                }
+            }
 
-                    // no default value? Then fail
-                    if (!$parameter->isOptional()) {
-                        throw new RuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id));
-                    }
+            $arguments = $this->autowireMethod($reflectionMethod, $arguments);
 
-                    // specifically pass the default value
-                    $arguments[$index] = $parameter->getDefaultValue();
+            if ($arguments !== $call[1]) {
+                $methodCalls[$i][1] = $arguments;
+            }
+        }
 
-                    continue;
-                }
+        return $methodCalls;
+    }
 
-                if (isset($this->autowired[$typeHint->name])) {
-                    $arguments[$index] = $this->autowired[$typeHint->name] ? new Reference($this->autowired[$typeHint->name]) : null;
-                    continue;
-                }
+    /**
+     * Autowires the constructor or a method.
+     *
+     * @return array The autowired arguments
+     *
+     * @throws AutowiringFailedException
+     */
+    private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments)
+    {
+        $class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
+        $method = $reflectionMethod->name;
+        $parameters = $reflectionMethod->getParameters();
+        if (method_exists('ReflectionMethod', 'isVariadic') && $reflectionMethod->isVariadic()) {
+            array_pop($parameters);
+        }
 
-                if (null === $this->types) {
-                    $this->populateAvailableTypes();
-                }
+        foreach ($parameters as $index => $parameter) {
+            if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
+                continue;
+            }
 
-                if (isset($this->types[$typeHint->name]) && !isset($this->notGuessableTypes[$typeHint->name])) {
-                    $value = new Reference($this->types[$typeHint->name]);
-                } else {
-                    try {
-                        $value = $this->createAutowiredDefinition($typeHint, $id);
-                    } catch (RuntimeException $e) {
-                        if ($parameter->isDefaultValueAvailable()) {
-                            $value = $parameter->getDefaultValue();
-                        } elseif ($parameter->allowsNull()) {
-                            $value = null;
-                        } else {
-                            throw $e;
-                        }
-                        $this->autowired[$typeHint->name] = false;
-                    }
+            $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
+
+            if (!$type) {
+                if (isset($arguments[$index])) {
+                    continue;
                 }
-            } catch (\ReflectionException $e) {
-                // Typehint against a non-existing class
 
+                // no default value? Then fail
                 if (!$parameter->isDefaultValueAvailable()) {
-                    throw new RuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $e->getMessage()), 0, $e);
+                    // For core classes, isDefaultValueAvailable() can
+                    // be false when isOptional() returns true. If the
+                    // argument *is* optional, allow it to be missing
+                    if ($parameter->isOptional()) {
+                        continue;
+                    }
+                    $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false);
+                    $type = $type ? sprintf('is type-hinted "%s"', $type) : 'has no type-hint';
+
+                    throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type));
                 }
 
-                $value = $parameter->getDefaultValue();
+                // specifically pass the default value
+                $arguments[$index] = $parameter->getDefaultValue();
+
+                continue;
+            }
+
+            if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''), 'for '.sprintf('argument "$%s" of method "%s()"', $parameter->name, $class.'::'.$method))) {
+                $failureMessage = $this->createTypeNotFoundMessage($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
+
+                if ($parameter->isDefaultValueAvailable()) {
+                    $value = $parameter->getDefaultValue();
+                } elseif (!$parameter->allowsNull()) {
+                    throw new AutowiringFailedException($this->currentId, $failureMessage);
+                }
+                $this->container->log($this, $failureMessage);
             }
 
             $arguments[$index] = $value;
@@ -166,41 +272,96 @@ class AutowirePass implements CompilerPassInterface
         // it's possible index 1 was set, then index 0, then 2, etc
         // make sure that we re-order so they're injected as expected
         ksort($arguments);
-        $definition->setArguments($arguments);
+
+        return $arguments;
+    }
+
+    /**
+     * @return TypedReference|null A reference to the service matching the given type, if any
+     */
+    private function getAutowiredReference(TypedReference $reference, $deprecationMessage)
+    {
+        $this->lastFailure = null;
+        $type = $reference->getType();
+
+        if ($type !== $this->container->normalizeId($reference) || ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract())) {
+            return $reference;
+        }
+
+        if (null === $this->types) {
+            $this->populateAvailableTypes($this->strictMode);
+        }
+
+        if (isset($this->definedTypes[$type])) {
+            return new TypedReference($this->types[$type], $type);
+        }
+
+        if (!$this->strictMode && isset($this->types[$type])) {
+            $message = 'Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0.';
+            if ($aliasSuggestion = $this->getAliasesSuggestionForType($type = $reference->getType(), $deprecationMessage)) {
+                $message .= ' '.$aliasSuggestion;
+            } else {
+                $message .= sprintf(' You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type);
+            }
+
+            @trigger_error($message, E_USER_DEPRECATED);
+
+            return new TypedReference($this->types[$type], $type);
+        }
+
+        if (!$reference->canBeAutoregistered() || isset($this->types[$type]) || isset($this->ambiguousServiceTypes[$type])) {
+            return null;
+        }
+
+        if (isset($this->autowired[$type])) {
+            return $this->autowired[$type] ? new TypedReference($this->autowired[$type], $type) : null;
+        }
+
+        if (!$this->strictMode) {
+            return $this->createAutowiredDefinition($type);
+        }
+
+        return null;
     }
 
     /**
      * Populates the list of available types.
      */
-    private function populateAvailableTypes()
+    private function populateAvailableTypes($onlyAutowiringTypes = false)
     {
-        $this->types = array();
+        $this->types = [];
+        if (!$onlyAutowiringTypes) {
+            $this->ambiguousServiceTypes = [];
+        }
 
         foreach ($this->container->getDefinitions() as $id => $definition) {
-            $this->populateAvailableType($id, $definition);
+            $this->populateAvailableType($id, $definition, $onlyAutowiringTypes);
         }
     }
 
     /**
      * Populates the list of available types for a given definition.
      *
-     * @param string     $id
-     * @param Definition $definition
+     * @param string $id
      */
-    private function populateAvailableType($id, Definition $definition)
+    private function populateAvailableType($id, Definition $definition, $onlyAutowiringTypes)
     {
         // Never use abstract services
         if ($definition->isAbstract()) {
             return;
         }
 
-        foreach ($definition->getAutowiringTypes() as $type) {
+        foreach ($definition->getAutowiringTypes(false) as $type) {
             $this->definedTypes[$type] = true;
             $this->types[$type] = $id;
-            unset($this->notGuessableTypes[$type]);
+            unset($this->ambiguousServiceTypes[$type]);
         }
 
-        if (!$reflectionClass = $this->getReflectionClass($id, $definition)) {
+        if ($onlyAutowiringTypes) {
+            return;
+        }
+
+        if (preg_match('/^\d+_[^~]++~[._a-zA-Z\d]{7}$/', $id) || $definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), false)) {
             return;
         }
 
@@ -225,110 +386,186 @@ class AutowirePass implements CompilerPassInterface
             return;
         }
 
-        if (!isset($this->types[$type])) {
-            $this->types[$type] = $id;
+        // is this already a type/class that is known to match multiple services?
+        if (isset($this->ambiguousServiceTypes[$type])) {
+            $this->ambiguousServiceTypes[$type][] = $id;
 
             return;
         }
 
-        if ($this->types[$type] === $id) {
+        // check to make sure the type doesn't match multiple services
+        if (!isset($this->types[$type]) || $this->types[$type] === $id) {
+            $this->types[$type] = $id;
+
             return;
         }
 
-        if (!isset($this->notGuessableTypes[$type])) {
-            $this->notGuessableTypes[$type] = true;
-            $this->types[$type] = (array) $this->types[$type];
+        // keep an array of all services matching this type
+        if (!isset($this->ambiguousServiceTypes[$type])) {
+            $this->ambiguousServiceTypes[$type] = [$this->types[$type]];
+            unset($this->types[$type]);
         }
-
-        $this->types[$type][] = $id;
+        $this->ambiguousServiceTypes[$type][] = $id;
     }
 
     /**
      * Registers a definition for the type if possible or throws an exception.
      *
-     * @param \ReflectionClass $typeHint
-     * @param string           $id
-     *
-     * @return Reference A reference to the registered definition
+     * @param string $type
      *
-     * @throws RuntimeException
+     * @return TypedReference|null A reference to the registered definition
      */
-    private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
+    private function createAutowiredDefinition($type)
     {
-        if (isset($this->notGuessableTypes[$typeHint->name])) {
-            $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
-            $matchingServices = implode(', ', $this->types[$typeHint->name]);
-
-            throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices));
+        if (!($typeHint = $this->container->getReflectionClass($type, false)) || !$typeHint->isInstantiable()) {
+            return null;
         }
 
-        if (!$typeHint->isInstantiable()) {
-            $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
-            throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface));
+        $currentId = $this->currentId;
+        $this->currentId = $type;
+        $this->autowired[$type] = $argumentId = sprintf('autowired.%s', $type);
+        $argumentDefinition = new Definition($type);
+        $argumentDefinition->setPublic(false);
+        $argumentDefinition->setAutowired(true);
+
+        try {
+            $originalThrowSetting = $this->throwOnAutowiringException;
+            $this->throwOnAutowiringException = true;
+            $this->processValue($argumentDefinition, true);
+            $this->container->setDefinition($argumentId, $argumentDefinition);
+        } catch (AutowiringFailedException $e) {
+            $this->autowired[$type] = false;
+            $this->lastFailure = $e->getMessage();
+            $this->container->log($this, $this->lastFailure);
+
+            return null;
+        } finally {
+            $this->throwOnAutowiringException = $originalThrowSetting;
+            $this->currentId = $currentId;
         }
 
-        $this->autowired[$typeHint->name] = $argumentId = sprintf('autowired.%s', $typeHint->name);
+        @trigger_error(sprintf('Relying on service auto-registration for type "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Create a service named "%s" instead.', $type, $type), E_USER_DEPRECATED);
 
-        $argumentDefinition = $this->container->register($argumentId, $typeHint->name);
-        $argumentDefinition->setPublic(false);
+        $this->container->log($this, sprintf('Type "%s" has been auto-registered for service "%s".', $type, $this->currentId));
 
+        return new TypedReference($argumentId, $type);
+    }
+
+    private function createTypeNotFoundMessage(TypedReference $reference, $label)
+    {
+        $trackResources = $this->container->isTrackingResources();
+        $this->container->setResourceTracking(false);
         try {
-            $this->completeDefinition($argumentId, $argumentDefinition);
-        } catch (RuntimeException $e) {
-            $classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
-            $message = sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface);
-            throw new RuntimeException($message, 0, $e);
+            if ($r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
+                $alternatives = $this->createTypeAlternatives($reference);
+            }
+        } finally {
+            $this->container->setResourceTracking($trackResources);
+        }
+
+        if (!$r) {
+            // either $type does not exist or a parent class does not exist
+            try {
+                $resource = new ClassExistenceResource($type, false);
+                // isFresh() will explode ONLY if a parent class/trait does not exist
+                $resource->isFresh(0);
+                $parentMsg = false;
+            } catch (\ReflectionException $e) {
+                $parentMsg = $e->getMessage();
+            }
+
+            $message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found');
+        } else {
+            $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
+            $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives);
+
+            if ($r->isInterface() && !$alternatives) {
+                $message .= ' Did you create a class that implements this interface?';
+            }
+        }
+
+        $message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);
+
+        if (null !== $this->lastFailure) {
+            $message = $this->lastFailure."\n".$message;
+            $this->lastFailure = null;
         }
 
-        return new Reference($argumentId);
+        return $message;
     }
 
-    /**
-     * Retrieves the reflection class associated with the given service.
-     *
-     * @param string     $id
-     * @param Definition $definition
-     *
-     * @return \ReflectionClass|false
-     */
-    private function getReflectionClass($id, Definition $definition)
+    private function createTypeAlternatives(TypedReference $reference)
     {
-        if (isset($this->reflectionClasses[$id])) {
-            return $this->reflectionClasses[$id];
+        // try suggesting available aliases first
+        if ($message = $this->getAliasesSuggestionForType($type = $reference->getType())) {
+            return ' '.$message;
+        }
+        if (null === $this->ambiguousServiceTypes) {
+            $this->populateAvailableTypes();
         }
 
-        // Cannot use reflection if the class isn't set
-        if (!$class = $definition->getClass()) {
-            return false;
+        if (isset($this->ambiguousServiceTypes[$type])) {
+            $message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
+        } elseif (isset($this->types[$type])) {
+            $message = sprintf('the existing "%s" service', $this->types[$type]);
+        } elseif ($reference->getRequiringClass() && !$reference->canBeAutoregistered() && !$this->strictMode) {
+            return ' It cannot be auto-registered because it is from a different root namespace.';
+        } else {
+            return '';
         }
 
-        $class = $this->container->getParameterBag()->resolveValue($class);
+        return sprintf(' You should maybe alias this %s to %s.', class_exists($type, false) ? 'class' : 'interface', $message);
+    }
 
-        if ($deprecated = $definition->isDeprecated()) {
-            $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) {
-                return (E_USER_DEPRECATED === $level || !$prevErrorHandler) ? false : $prevErrorHandler($level, $message, $file, $line);
-            });
+    /**
+     * @deprecated since version 3.3, to be removed in 4.0.
+     */
+    private static function getResourceMetadataForMethod(\ReflectionMethod $method)
+    {
+        $methodArgumentsMetadata = [];
+        foreach ($method->getParameters() as $parameter) {
+            try {
+                $class = $parameter->getClass();
+            } catch (\ReflectionException $e) {
+                // type-hint is against a non-existent class
+                $class = false;
+            }
+
+            $isVariadic = method_exists($parameter, 'isVariadic') && $parameter->isVariadic();
+            $methodArgumentsMetadata[] = [
+                'class' => $class,
+                'isOptional' => $parameter->isOptional(),
+                'defaultValue' => ($parameter->isOptional() && !$isVariadic) ? $parameter->getDefaultValue() : null,
+            ];
         }
 
-        $e = null;
+        return $methodArgumentsMetadata;
+    }
 
-        try {
-            $reflector = new \ReflectionClass($class);
-        } catch (\Exception $e) {
-        } catch (\Throwable $e) {
+    private function getAliasesSuggestionForType($type, $extraContext = null)
+    {
+        $aliases = [];
+        foreach (class_parents($type) + class_implements($type) as $parent) {
+            if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) {
+                $aliases[] = $parent;
+            }
         }
 
-        if ($deprecated) {
-            restore_error_handler();
+        $extraContext = $extraContext ? ' '.$extraContext : '';
+        if (1 < $len = \count($aliases)) {
+            $message = sprintf('Try changing the type-hint%s to one of its parents: ', $extraContext);
+            for ($i = 0, --$len; $i < $len; ++$i) {
+                $message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
+            }
+            $message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
+
+            return $message;
         }
 
-        if (null !== $e) {
-            if (!$e instanceof \ReflectionException) {
-                throw $e;
-            }
-            $reflector = false;
+        if ($aliases) {
+            return sprintf('Try changing the type-hint%s to "%s" instead.', $extraContext, $aliases[0]);
         }
 
-        return $this->reflectionClasses[$id] = $reflector;
+        return null;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
new file mode 100644
index 0000000000..efb9df7b94
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Definition;
+
+/**
+ * Looks for definitions with autowiring enabled and registers their corresponding "@required" methods as setters.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class AutowireRequiredMethodsPass extends AbstractRecursivePass
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        $value = parent::processValue($value, $isRoot);
+
+        if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
+            return $value;
+        }
+        if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) {
+            return $value;
+        }
+
+        $alreadyCalledMethods = [];
+
+        foreach ($value->getMethodCalls() as list($method)) {
+            $alreadyCalledMethods[strtolower($method)] = true;
+        }
+
+        foreach ($reflectionClass->getMethods() as $reflectionMethod) {
+            $r = $reflectionMethod;
+
+            if ($r->isConstructor() || isset($alreadyCalledMethods[strtolower($r->name)])) {
+                continue;
+            }
+
+            while (true) {
+                if (false !== $doc = $r->getDocComment()) {
+                    if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) {
+                        $value->addMethodCall($reflectionMethod->name);
+                        break;
+                    }
+                    if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) {
+                        break;
+                    }
+                }
+                try {
+                    $r = $r->getPrototype();
+                } catch (\ReflectionException $e) {
+                    break; // method has no prototype
+                }
+            }
+        }
+
+        return $value;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
new file mode 100644
index 0000000000..30a6f524ad
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
@@ -0,0 +1,87 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * Checks if arguments of methods are properly configured.
+ *
+ * @author Kévin Dunglas <dunglas@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class CheckArgumentsValidityPass extends AbstractRecursivePass
+{
+    private $throwExceptions;
+
+    public function __construct($throwExceptions = true)
+    {
+        $this->throwExceptions = $throwExceptions;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if (!$value instanceof Definition) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        $i = 0;
+        foreach ($value->getArguments() as $k => $v) {
+            if ($k !== $i++) {
+                if (!\is_int($k)) {
+                    $msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k);
+                    $value->addError($msg);
+                    if ($this->throwExceptions) {
+                        throw new RuntimeException($msg);
+                    }
+
+                    break;
+                }
+
+                $msg = sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i);
+                $value->addError($msg);
+                if ($this->throwExceptions) {
+                    throw new RuntimeException($msg);
+                }
+            }
+        }
+
+        foreach ($value->getMethodCalls() as $methodCall) {
+            $i = 0;
+            foreach ($methodCall[1] as $k => $v) {
+                if ($k !== $i++) {
+                    if (!\is_int($k)) {
+                        $msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k);
+                        $value->addError($msg);
+                        if ($this->throwExceptions) {
+                            throw new RuntimeException($msg);
+                        }
+
+                        break;
+                    }
+
+                    $msg = sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i);
+                    $value->addError($msg);
+                    if ($this->throwExceptions) {
+                        throw new RuntimeException($msg);
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php
index 6bde1942ba..55d911c4f3 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php
@@ -36,9 +36,9 @@ class CheckCircularReferencesPass implements CompilerPassInterface
     {
         $graph = $container->getCompiler()->getServiceReferenceGraph();
 
-        $this->checkedNodes = array();
+        $this->checkedNodes = [];
         foreach ($graph->getNodes() as $id => $node) {
-            $this->currentPath = array($id);
+            $this->currentPath = [$id];
 
             $this->checkOutEdges($node->getOutEdges());
         }
@@ -58,8 +58,8 @@ class CheckCircularReferencesPass implements CompilerPassInterface
             $id = $node->getId();
 
             if (empty($this->checkedNodes[$id])) {
-                // don't check circular dependencies for lazy services
-                if (!$node->getValue() || !$node->getValue()->isLazy()) {
+                // Don't check circular references for lazy edges
+                if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) {
                     $searchKey = array_search($id, $this->currentPath);
                     $this->currentPath[] = $id;
 
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
index ea1e089179..4b6d277fe9 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
@@ -12,7 +12,7 @@
 namespace Symfony\Component\DependencyInjection\Compiler;
 
 use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 
 /**
@@ -24,8 +24,6 @@ use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  *
  * - non synthetic, non abstract services always have a class set
  * - synthetic services are always public
- * - synthetic services are always of non-prototype scope
- * - shared services are always of non-prototype scope
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
@@ -40,29 +38,22 @@ class CheckDefinitionValidityPass implements CompilerPassInterface
     {
         foreach ($container->getDefinitions() as $id => $definition) {
             // synthetic service is public
-            if ($definition->isSynthetic() && !$definition->isPublic()) {
+            if ($definition->isSynthetic() && !($definition->isPublic() || $definition->isPrivate())) {
                 throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id));
             }
 
-            // synthetic service has non-prototype scope
-            if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope(false)) {
-                throw new RuntimeException(sprintf('A synthetic service ("%s") cannot be of scope "prototype".', $id));
-            }
-
-            // shared service has non-prototype scope
-            if ($definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope(false)) {
-                throw new RuntimeException(sprintf('A shared service ("%s") cannot be of scope "prototype".', $id));
-            }
-
-            if ($definition->getFactory() && ($definition->getFactoryClass(false) || $definition->getFactoryService(false) || $definition->getFactoryMethod(false))) {
-                throw new RuntimeException(sprintf('A service ("%s") can use either the old or the new factory syntax, not both.', $id));
-            }
-
             // non-synthetic, non-abstract service has class
             if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
-                if ($definition->getFactory() || $definition->getFactoryClass(false) || $definition->getFactoryService(false)) {
+                if ($definition->getFactory()) {
                     throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id));
                 }
+                if (class_exists($id) || interface_exists($id, false)) {
+                    if (0 === strpos($id, '\\') && 1 < substr_count($id, '\\')) {
+                        throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface. Please specify the class attribute explicitly or remove the leading backslash by renaming the service to "%s" to get rid of this error.', $id, substr($id, 1)));
+                    }
+
+                    throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface in the global namespace. Leaving out the "class" attribute is only allowed for namespaced classes. Please specify the class attribute explicitly to get rid of this error.', $id));
+                }
 
                 throw new RuntimeException(sprintf('The definition for "%s" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.', $id));
             }
@@ -77,6 +68,22 @@ class CheckDefinitionValidityPass implements CompilerPassInterface
                     }
                 }
             }
+
+            if ($definition->isPublic() && !$definition->isPrivate()) {
+                $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs);
+                if (null !== $usedEnvs) {
+                    throw new EnvParameterException([$resolvedId], null, 'A service name ("%s") cannot contain dynamic values.');
+                }
+            }
+        }
+
+        foreach ($container->getAliases() as $id => $alias) {
+            if ($alias->isPublic() && !$alias->isPrivate()) {
+                $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs);
+                if (null !== $usedEnvs) {
+                    throw new EnvParameterException([$resolvedId], null, 'An alias name ("%s") cannot contain dynamic values.');
+                }
+            }
         }
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
index f17096f8f3..77b35f1866 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
@@ -11,9 +11,7 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
-use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
 use Symfony\Component\DependencyInjection\Reference;
 
@@ -22,42 +20,17 @@ use Symfony\Component\DependencyInjection\Reference;
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class CheckExceptionOnInvalidReferenceBehaviorPass implements CompilerPassInterface
+class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass
 {
-    private $container;
-    private $sourceId;
-
-    public function process(ContainerBuilder $container)
+    protected function processValue($value, $isRoot = false)
     {
-        $this->container = $container;
-
-        foreach ($container->getDefinitions() as $id => $definition) {
-            $this->sourceId = $id;
-            $this->processDefinition($definition);
+        if (!$value instanceof Reference) {
+            return parent::processValue($value, $isRoot);
         }
-    }
-
-    private function processDefinition(Definition $definition)
-    {
-        $this->processReferences($definition->getArguments());
-        $this->processReferences($definition->getMethodCalls());
-        $this->processReferences($definition->getProperties());
-    }
-
-    private function processReferences(array $arguments)
-    {
-        foreach ($arguments as $argument) {
-            if (\is_array($argument)) {
-                $this->processReferences($argument);
-            } elseif ($argument instanceof Definition) {
-                $this->processDefinition($argument);
-            } elseif ($argument instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $argument->getInvalidBehavior()) {
-                $destId = (string) $argument;
-
-                if (!$this->container->has($destId)) {
-                    throw new ServiceNotFoundException($destId, $this->sourceId);
-                }
-            }
+        if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) {
+            throw new ServiceNotFoundException($id, $this->currentId);
         }
+
+        return $value;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php
index 2b380dd352..8f2a3bdf70 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php
@@ -11,12 +11,8 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
-use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
-use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;
 use Symfony\Component\DependencyInjection\Reference;
 
 /**
@@ -24,132 +20,24 @@ use Symfony\Component\DependencyInjection\Reference;
  *
  * The following checks are performed by this pass:
  * - target definitions are not abstract
- * - target definitions are of equal or wider scope
- * - target definitions are in the same scope hierarchy
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class CheckReferenceValidityPass implements CompilerPassInterface
+class CheckReferenceValidityPass extends AbstractRecursivePass
 {
-    private $container;
-    private $currentId;
-    private $currentScope;
-    private $currentScopeAncestors;
-    private $currentScopeChildren;
-
-    /**
-     * Processes the ContainerBuilder to validate References.
-     */
-    public function process(ContainerBuilder $container)
+    protected function processValue($value, $isRoot = false)
     {
-        $this->container = $container;
-
-        $children = $this->container->getScopeChildren(false);
-        $ancestors = array();
-
-        $scopes = $this->container->getScopes(false);
-        foreach ($scopes as $name => $parent) {
-            $ancestors[$name] = array($parent);
-
-            while (isset($scopes[$parent])) {
-                $ancestors[$name][] = $parent = $scopes[$parent];
-            }
-        }
-
-        foreach ($container->getDefinitions() as $id => $definition) {
-            if ($definition->isSynthetic() || $definition->isAbstract()) {
-                continue;
-            }
-
-            $this->currentId = $id;
-            $this->currentScope = $scope = $definition->getScope(false);
-
-            if (ContainerInterface::SCOPE_CONTAINER === $scope) {
-                $this->currentScopeChildren = array_keys($scopes);
-                $this->currentScopeAncestors = array();
-            } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
-                $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array();
-                $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array();
-            }
-
-            $this->validateReferences($definition->getArguments());
-            $this->validateReferences($definition->getMethodCalls());
-            $this->validateReferences($definition->getProperties());
+        if ($isRoot && $value instanceof Definition && ($value->isSynthetic() || $value->isAbstract())) {
+            return $value;
         }
-    }
+        if ($value instanceof Reference && $this->container->hasDefinition((string) $value)) {
+            $targetDefinition = $this->container->getDefinition((string) $value);
 
-    /**
-     * Validates an array of References.
-     *
-     * @param array $arguments An array of Reference objects
-     *
-     * @throws RuntimeException when there is a reference to an abstract definition
-     */
-    private function validateReferences(array $arguments)
-    {
-        foreach ($arguments as $argument) {
-            if (\is_array($argument)) {
-                $this->validateReferences($argument);
-            } elseif ($argument instanceof Reference) {
-                $targetDefinition = $this->getDefinition((string) $argument);
-
-                if (null !== $targetDefinition && $targetDefinition->isAbstract()) {
-                    throw new RuntimeException(sprintf('The definition "%s" has a reference to an abstract definition "%s". Abstract definitions cannot be the target of references.', $this->currentId, $argument));
-                }
-
-                $this->validateScope($argument, $targetDefinition);
+            if ($targetDefinition->isAbstract()) {
+                throw new RuntimeException(sprintf('The definition "%s" has a reference to an abstract definition "%s". Abstract definitions cannot be the target of references.', $this->currentId, $value));
             }
         }
-    }
-
-    /**
-     * Validates the scope of a single Reference.
-     *
-     * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope
-     * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy
-     */
-    private function validateScope(Reference $reference, Definition $definition = null)
-    {
-        if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) {
-            return;
-        }
-
-        if (!$reference->isStrict(false)) {
-            return;
-        }
-
-        if (null === $definition) {
-            return;
-        }
-
-        if ($this->currentScope === $scope = $definition->getScope(false)) {
-            return;
-        }
-
-        $id = (string) $reference;
-
-        if (\in_array($scope, $this->currentScopeChildren, true)) {
-            throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope);
-        }
-
-        if (!\in_array($scope, $this->currentScopeAncestors, true)) {
-            throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope);
-        }
-    }
-
-    /**
-     * Returns the Definition given an id.
-     *
-     * @param string $id Definition identifier
-     *
-     * @return Definition
-     */
-    private function getDefinition($id)
-    {
-        if (!$this->container->hasDefinition($id)) {
-            return;
-        }
 
-        return $this->container->getDefinition($id);
+        return parent::processValue($value, $isRoot);
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/Compiler.php b/civicrm/vendor/symfony/dependency-injection/Compiler/Compiler.php
index dd9539eeb7..c5f698b012 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/Compiler.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/Compiler.php
@@ -12,6 +12,7 @@
 namespace Symfony\Component\DependencyInjection\Compiler;
 
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
 
 /**
  * This class is used to remove circular dependencies between individual passes.
@@ -21,7 +22,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
 class Compiler
 {
     private $passConfig;
-    private $log = array();
+    private $log = [];
     private $loggingFormatter;
     private $serviceReferenceGraph;
 
@@ -29,7 +30,6 @@ class Compiler
     {
         $this->passConfig = new PassConfig();
         $this->serviceReferenceGraph = new ServiceReferenceGraph();
-        $this->loggingFormatter = new LoggingFormatter();
     }
 
     /**
@@ -56,9 +56,17 @@ class Compiler
      * Returns the logging formatter which can be used by compilation passes.
      *
      * @return LoggingFormatter
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
      */
     public function getLoggingFormatter()
     {
+        if (null === $this->loggingFormatter) {
+            @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), E_USER_DEPRECATED);
+
+            $this->loggingFormatter = new LoggingFormatter();
+        }
+
         return $this->loggingFormatter;
     }
 
@@ -68,21 +76,50 @@ class Compiler
      * @param CompilerPassInterface $pass A compiler pass
      * @param string                $type The type of the pass
      */
-    public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
+    public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
     {
-        $this->passConfig->addPass($pass, $type);
+        if (\func_num_args() >= 3) {
+            $priority = func_get_arg(2);
+        } else {
+            if (__CLASS__ !== static::class) {
+                $r = new \ReflectionMethod($this, __FUNCTION__);
+                if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
+                    @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED);
+                }
+            }
+
+            $priority = 0;
+        }
+
+        $this->passConfig->addPass($pass, $type, $priority);
     }
 
     /**
      * Adds a log message.
      *
      * @param string $string The log message
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
      */
     public function addLogMessage($string)
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), E_USER_DEPRECATED);
+
         $this->log[] = $string;
     }
 
+    /**
+     * @final
+     */
+    public function log(CompilerPassInterface $pass, $message)
+    {
+        if (false !== strpos($message, "\n")) {
+            $message = str_replace("\n", "\n".\get_class($pass).': ', trim($message));
+        }
+
+        $this->log[] = \get_class($pass).': '.$message;
+    }
+
     /**
      * Returns the log.
      *
@@ -98,8 +135,31 @@ class Compiler
      */
     public function compile(ContainerBuilder $container)
     {
-        foreach ($this->passConfig->getPasses() as $pass) {
-            $pass->process($container);
+        try {
+            foreach ($this->passConfig->getPasses() as $pass) {
+                $pass->process($container);
+            }
+        } catch (\Exception $e) {
+            $usedEnvs = [];
+            $prev = $e;
+
+            do {
+                $msg = $prev->getMessage();
+
+                if ($msg !== $resolvedMsg = $container->resolveEnvPlaceholders($msg, null, $usedEnvs)) {
+                    $r = new \ReflectionProperty($prev, 'message');
+                    $r->setAccessible(true);
+                    $r->setValue($prev, $resolvedMsg);
+                }
+            } while ($prev = $prev->getPrevious());
+
+            if ($usedEnvs) {
+                $e = new EnvParameterException($usedEnvs, $e);
+            }
+
+            throw $e;
+        } finally {
+            $this->getServiceReferenceGraph()->clear();
         }
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
index 80eb67a632..bbd857e154 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
@@ -32,11 +32,11 @@ class DecoratorServicePass implements CompilerPassInterface
             if (!$decorated = $definition->getDecoratedService()) {
                 continue;
             }
-            $definitions->insert(array($id, $definition), array($decorated[2], --$order));
+            $definitions->insert([$id, $definition], [$decorated[2], --$order]);
         }
+        $decoratingDefinitions = [];
 
-        foreach ($definitions as $arr) {
-            list($id, $definition) = $arr;
+        foreach ($definitions as list($id, $definition)) {
             list($inner, $renamedId) = $definition->getDecoratedService();
 
             $definition->setDecoratedService(null);
@@ -50,19 +50,32 @@ class DecoratorServicePass implements CompilerPassInterface
             if ($container->hasAlias($inner)) {
                 $alias = $container->getAlias($inner);
                 $public = $alias->isPublic();
-                $container->setAlias($renamedId, new Alias((string) $alias, false));
+                $private = $alias->isPrivate();
+                $container->setAlias($renamedId, new Alias($container->normalizeId($alias), false));
             } else {
                 $decoratedDefinition = $container->getDefinition($inner);
-                $definition->setTags(array_merge($decoratedDefinition->getTags(), $definition->getTags()));
-                $definition->setAutowiringTypes(array_merge($decoratedDefinition->getAutowiringTypes(), $definition->getAutowiringTypes()));
                 $public = $decoratedDefinition->isPublic();
+                $private = $decoratedDefinition->isPrivate();
                 $decoratedDefinition->setPublic(false);
-                $decoratedDefinition->setTags(array());
-                $decoratedDefinition->setAutowiringTypes(array());
                 $container->setDefinition($renamedId, $decoratedDefinition);
+                $decoratingDefinitions[$inner] = $decoratedDefinition;
             }
 
-            $container->setAlias($inner, new Alias($id, $public));
+            if (isset($decoratingDefinitions[$inner])) {
+                $decoratingDefinition = $decoratingDefinitions[$inner];
+                $definition->setTags(array_merge($decoratingDefinition->getTags(), $definition->getTags()));
+                $autowiringTypes = $decoratingDefinition->getAutowiringTypes(false);
+                if ($types = array_merge($autowiringTypes, $definition->getAutowiringTypes(false))) {
+                    $definition->setAutowiringTypes($types);
+                }
+                $decoratingDefinition->setTags([]);
+                if ($autowiringTypes) {
+                    $decoratingDefinition->setAutowiringTypes([]);
+                }
+                $decoratingDefinitions[$inner] = $definition;
+            }
+
+            $container->setAlias($inner, $id)->setPublic($public)->setPrivate($private);
         }
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
new file mode 100644
index 0000000000..73b5d1d57d
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * Throws an exception for any Definitions that have errors and still exist.
+ *
+ * @author Ryan Weaver <ryan@knpuniversity.com>
+ */
+class DefinitionErrorExceptionPass extends AbstractRecursivePass
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if (!$value instanceof Definition || empty($value->getErrors())) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        // only show the first error so the user can focus on it
+        $errors = $value->getErrors();
+        $message = reset($errors);
+
+        throw new RuntimeException($message);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php
new file mode 100644
index 0000000000..d688fb59fd
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @author Guilhem N. <egetick@gmail.com>
+ *
+ * @deprecated since version 3.3, to be removed in 4.0.
+ */
+class FactoryReturnTypePass implements CompilerPassInterface
+{
+    private $resolveClassPass;
+
+    public function __construct(ResolveClassPass $resolveClassPass = null)
+    {
+        if (null === $resolveClassPass) {
+            @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 3.3 and will be removed in 4.0.', E_USER_DEPRECATED);
+        }
+        $this->resolveClassPass = $resolveClassPass;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        // works only since php 7.0 and hhvm 3.11
+        if (!method_exists(\ReflectionMethod::class, 'getReturnType')) {
+            return;
+        }
+        $resolveClassPassChanges = null !== $this->resolveClassPass ? $this->resolveClassPass->getChanges() : [];
+
+        foreach ($container->getDefinitions() as $id => $definition) {
+            $this->updateDefinition($container, $id, $definition, $resolveClassPassChanges);
+        }
+    }
+
+    private function updateDefinition(ContainerBuilder $container, $id, Definition $definition, array $resolveClassPassChanges, array $previous = [])
+    {
+        // circular reference
+        if (isset($previous[$id])) {
+            return;
+        }
+
+        $factory = $definition->getFactory();
+        if (null === $factory || (!isset($resolveClassPassChanges[$id]) && null !== $definition->getClass())) {
+            return;
+        }
+
+        $class = null;
+        if (\is_string($factory)) {
+            try {
+                $m = new \ReflectionFunction($factory);
+                if (false !== $m->getFileName() && file_exists($m->getFileName())) {
+                    $container->fileExists($m->getFileName());
+                }
+            } catch (\ReflectionException $e) {
+                return;
+            }
+        } else {
+            if ($factory[0] instanceof Reference) {
+                $previous[$id] = true;
+                $factoryId = $container->normalizeId($factory[0]);
+                $factoryDefinition = $container->findDefinition($factoryId);
+                $this->updateDefinition($container, $factoryId, $factoryDefinition, $resolveClassPassChanges, $previous);
+                $class = $factoryDefinition->getClass();
+            } else {
+                $class = $factory[0];
+            }
+
+            if (!$m = $container->getReflectionClass($class, false)) {
+                return;
+            }
+            try {
+                $m = $m->getMethod($factory[1]);
+            } catch (\ReflectionException $e) {
+                return;
+            }
+        }
+
+        $returnType = $m->getReturnType();
+        if (null !== $returnType && !$returnType->isBuiltin()) {
+            $returnType = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType->__toString();
+            if (null !== $class) {
+                $declaringClass = $m->getDeclaringClass()->getName();
+                if ('self' === strtolower($returnType)) {
+                    $returnType = $declaringClass;
+                } elseif ('parent' === strtolower($returnType)) {
+                    $returnType = get_parent_class($declaringClass) ?: null;
+                }
+            }
+
+            if (null !== $returnType && (!isset($resolveClassPassChanges[$id]) || $returnType !== $resolveClassPassChanges[$id])) {
+                @trigger_error(sprintf('Relying on its factory\'s return-type to define the class of service "%s" is deprecated since Symfony 3.3 and won\'t work in 4.0. Set the "class" attribute to "%s" on the service definition instead.', $id, $returnType), E_USER_DEPRECATED);
+            }
+            $definition->setClass($returnType);
+        }
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
index b57f48840e..326ee19323 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
@@ -11,9 +11,9 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
 use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
 use Symfony\Component\DependencyInjection\Reference;
 
 /**
@@ -21,12 +21,10 @@ use Symfony\Component\DependencyInjection\Reference;
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class InlineServiceDefinitionsPass implements RepeatablePassInterface
+class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
 {
-    private $graph;
-    private $compiler;
-    private $formatter;
-    private $currentId;
+    private $cloningIds = [];
+    private $inlinedServiceIds = [];
 
     /**
      * {@inheritdoc}
@@ -37,88 +35,90 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
     }
 
     /**
-     * Processes the ContainerBuilder for inline service definitions.
+     * Returns an array of all services inlined by this pass.
+     *
+     * The key is the inlined service id and its value is the list of services it was inlined into.
+     *
+     * @deprecated since version 3.4, to be removed in 4.0.
+     *
+     * @return array
      */
-    public function process(ContainerBuilder $container)
+    public function getInlinedServiceIds()
     {
-        $this->compiler = $container->getCompiler();
-        $this->formatter = $this->compiler->getLoggingFormatter();
-        $this->graph = $this->compiler->getServiceReferenceGraph();
+        @trigger_error('Calling InlineServiceDefinitionsPass::getInlinedServiceIds() is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
 
-        $container->setDefinitions($this->inlineArguments($container, $container->getDefinitions(), true));
+        return $this->inlinedServiceIds;
     }
 
     /**
-     * Processes inline arguments.
-     *
-     * @param ContainerBuilder $container The ContainerBuilder
-     * @param array            $arguments An array of arguments
-     * @param bool             $isRoot    If we are processing the root definitions or not
-     *
-     * @return array
+     * {@inheritdoc}
      */
-    private function inlineArguments(ContainerBuilder $container, array $arguments, $isRoot = false)
+    protected function processValue($value, $isRoot = false)
     {
-        foreach ($arguments as $k => $argument) {
-            if ($isRoot) {
-                $this->currentId = $k;
-            }
-            if (\is_array($argument)) {
-                $arguments[$k] = $this->inlineArguments($container, $argument);
-            } elseif ($argument instanceof Reference) {
-                if (!$container->hasDefinition($id = (string) $argument)) {
-                    continue;
-                }
-
-                if ($this->isInlineableDefinition($container, $id, $definition = $container->getDefinition($id))) {
-                    $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId));
-
-                    if ($definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope(false)) {
-                        $arguments[$k] = $definition;
-                    } else {
-                        $arguments[$k] = clone $definition;
-                    }
-                }
-            } elseif ($argument instanceof Definition) {
-                $argument->setArguments($this->inlineArguments($container, $argument->getArguments()));
-                $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls()));
-                $argument->setProperties($this->inlineArguments($container, $argument->getProperties()));
-
-                $configurator = $this->inlineArguments($container, array($argument->getConfigurator()));
-                $argument->setConfigurator($configurator[0]);
-
-                $factory = $this->inlineArguments($container, array($argument->getFactory()));
-                $argument->setFactory($factory[0]);
+        if ($value instanceof ArgumentInterface) {
+            // Reference found in ArgumentInterface::getValues() are not inlineable
+            return $value;
+        }
+
+        if ($value instanceof Definition && $this->cloningIds) {
+            if ($value->isShared()) {
+                return $value;
             }
+            $value = clone $value;
+        }
+
+        if (!$value instanceof Reference || !$this->container->hasDefinition($id = $this->container->normalizeId($value))) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        $definition = $this->container->getDefinition($id);
+
+        if (!$this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
+            return $value;
         }
 
-        return $arguments;
+        $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
+        $this->inlinedServiceIds[$id][] = $this->currentId;
+
+        if ($definition->isShared()) {
+            return $definition;
+        }
+
+        if (isset($this->cloningIds[$id])) {
+            $ids = array_keys($this->cloningIds);
+            $ids[] = $id;
+
+            throw new ServiceCircularReferenceException($id, \array_slice($ids, array_search($id, $ids)));
+        }
+
+        $this->cloningIds[$id] = true;
+        try {
+            return $this->processValue($definition);
+        } finally {
+            unset($this->cloningIds[$id]);
+        }
     }
 
     /**
      * Checks if the definition is inlineable.
      *
-     * @param ContainerBuilder $container
-     * @param string           $id
-     * @param Definition       $definition
-     *
      * @return bool If the definition is inlineable
      */
-    private function isInlineableDefinition(ContainerBuilder $container, $id, Definition $definition)
+    private function isInlineableDefinition($id, Definition $definition, ServiceReferenceGraph $graph)
     {
-        if ($definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) {
+        if ($definition->getErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) {
             return false;
         }
 
-        if (!$definition->isShared() || ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope(false)) {
+        if (!$definition->isShared()) {
             return true;
         }
 
-        if ($definition->isPublic()) {
+        if ($definition->isPublic() || $definition->isPrivate()) {
             return false;
         }
 
-        if (!$this->graph->hasNode($id)) {
+        if (!$graph->hasNode($id)) {
             return true;
         }
 
@@ -126,23 +126,28 @@ class InlineServiceDefinitionsPass implements RepeatablePassInterface
             return false;
         }
 
-        $ids = array();
-        foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
+        $ids = [];
+        $isReferencedByConstructor = false;
+        foreach ($graph->getNode($id)->getInEdges() as $edge) {
+            $isReferencedByConstructor = $isReferencedByConstructor || $edge->isReferencedByConstructor();
+            if ($edge->isWeak() || $edge->isLazy()) {
+                return false;
+            }
             $ids[] = $edge->getSourceNode()->getId();
         }
 
-        if (\count(array_unique($ids)) > 1) {
-            return false;
+        if (!$ids) {
+            return true;
         }
 
-        if (\count($ids) > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
+        if (\count(array_unique($ids)) > 1) {
             return false;
         }
 
-        if (\count($ids) > 1 && $definition->getFactoryService(false)) {
+        if (\count($ids) > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
             return false;
         }
 
-        return $container->getDefinition(reset($ids))->getScope(false) === $definition->getScope(false);
+        return $this->container->getDefinition($ids[0])->isShared();
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php b/civicrm/vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php
index 64ffc9e478..b058d26238 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php
@@ -11,10 +11,14 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
+@trigger_error('The '.__NAMESPACE__.'\LoggingFormatter class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', E_USER_DEPRECATED);
+
 /**
  * Used to format logging messages during the compilation.
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
  */
 class LoggingFormatter
 {
@@ -38,6 +42,11 @@ class LoggingFormatter
         return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId));
     }
 
+    public function formatUnusedAutowiringPatterns(CompilerPassInterface $pass, $id, array $patterns)
+    {
+        return $this->format($pass, sprintf('Autowiring\'s patterns "%s" for service "%s" don\'t match any method.', implode('", "', $patterns), $id));
+    }
+
     public function format(CompilerPassInterface $pass, $message)
     {
         return sprintf('%s: %s', \get_class($pass), $message);
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
index 9434ac70b5..caa1fd2251 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
@@ -12,8 +12,14 @@
 namespace Symfony\Component\DependencyInjection\Compiler;
 
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\LogicException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
+use Symfony\Component\DependencyInjection\Extension\Extension;
+use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
 use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
+use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
 
 /**
  * Merges extension configs into the container builder.
@@ -43,20 +49,38 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
                 // this extension was not called
                 continue;
             }
-            $config = $container->getParameterBag()->resolveValue($config);
-
-            $tmpContainer = new ContainerBuilder($container->getParameterBag());
-            $tmpContainer->setResourceTracking($container->isTrackingResources());
-            $tmpContainer->addObjectResource($extension);
-            if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) {
-                $tmpContainer->addObjectResource($configuration);
+            $resolvingBag = $container->getParameterBag();
+            if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) {
+                // create a dedicated bag so that we can track env vars per-extension
+                $resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag);
             }
+            $config = $resolvingBag->resolveValue($config);
+
+            try {
+                $tmpContainer = new MergeExtensionConfigurationContainerBuilder($extension, $resolvingBag);
+                $tmpContainer->setResourceTracking($container->isTrackingResources());
+                $tmpContainer->addObjectResource($extension);
+                if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) {
+                    $tmpContainer->addObjectResource($configuration);
+                }
+
+                foreach ($exprLangProviders as $provider) {
+                    $tmpContainer->addExpressionLanguageProvider($provider);
+                }
 
-            foreach ($exprLangProviders as $provider) {
-                $tmpContainer->addExpressionLanguageProvider($provider);
+                $extension->load($config, $tmpContainer);
+            } catch (\Exception $e) {
+                if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
+                    $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag);
+                }
+
+                throw $e;
             }
 
-            $extension->load($config, $tmpContainer);
+            if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
+                // don't keep track of env vars that are *overridden* when configs are merged
+                $resolvingBag->freezeAfterProcessing($extension, $tmpContainer);
+            }
 
             $container->merge($tmpContainer);
             $container->getParameterBag()->add($parameters);
@@ -66,3 +90,117 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
         $container->addAliases($aliases);
     }
 }
+
+/**
+ * @internal
+ */
+class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag
+{
+    private $processedEnvPlaceholders;
+
+    public function __construct(parent $parameterBag)
+    {
+        parent::__construct($parameterBag->all());
+        $this->mergeEnvPlaceholders($parameterBag);
+    }
+
+    public function freezeAfterProcessing(Extension $extension, ContainerBuilder $container)
+    {
+        if (!$config = $extension->getProcessedConfigs()) {
+            // Extension::processConfiguration() wasn't called, we cannot know how configs were merged
+            return;
+        }
+        $this->processedEnvPlaceholders = [];
+
+        // serialize config and container to catch env vars nested in object graphs
+        $config = serialize($config).serialize($container->getDefinitions()).serialize($container->getAliases()).serialize($container->getParameterBag()->all());
+
+        foreach (parent::getEnvPlaceholders() as $env => $placeholders) {
+            foreach ($placeholders as $placeholder) {
+                if (false !== stripos($config, $placeholder)) {
+                    $this->processedEnvPlaceholders[$env] = $placeholders;
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getEnvPlaceholders()
+    {
+        return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders();
+    }
+}
+
+/**
+ * A container builder preventing using methods that wouldn't have any effect from extensions.
+ *
+ * @internal
+ */
+class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder
+{
+    private $extensionClass;
+
+    public function __construct(ExtensionInterface $extension, ParameterBagInterface $parameterBag = null)
+    {
+        parent::__construct($parameterBag);
+
+        $this->extensionClass = \get_class($extension);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
+    {
+        throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', \get_class($pass), $this->extensionClass));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function registerExtension(ExtensionInterface $extension)
+    {
+        throw new LogicException(sprintf('You cannot register extension "%s" from "%s". Extensions must be registered before the container is compiled.', \get_class($extension), $this->extensionClass));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function compile($resolveEnvPlaceholders = false)
+    {
+        throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null)
+    {
+        if (true !== $format || !\is_string($value)) {
+            return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
+        }
+
+        $bag = $this->getParameterBag();
+        $value = $bag->resolveValue($value);
+
+        if (!$bag instanceof EnvPlaceholderParameterBag) {
+            return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
+        }
+
+        foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
+            if (false === strpos($env, ':')) {
+                continue;
+            }
+            foreach ($placeholders as $placeholder) {
+                if (false !== stripos($value, $placeholder)) {
+                    throw new RuntimeException(sprintf('Using a cast in "env(%s)" is incompatible with resolution at compile time in "%s". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead.', $env, $this->extensionClass));
+                }
+            }
+        }
+
+        return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/PassConfig.php b/civicrm/vendor/symfony/dependency-injection/Compiler/PassConfig.php
index 8eabf3529d..e470cdec2d 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/PassConfig.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/PassConfig.php
@@ -29,9 +29,9 @@ class PassConfig
     const TYPE_REMOVE = 'removing';
 
     private $mergePass;
-    private $afterRemovingPasses = array();
-    private $beforeOptimizationPasses = array();
-    private $beforeRemovingPasses = array();
+    private $afterRemovingPasses = [];
+    private $beforeOptimizationPasses = [];
+    private $beforeRemovingPasses = [];
     private $optimizationPasses;
     private $removingPasses;
 
@@ -39,48 +39,74 @@ class PassConfig
     {
         $this->mergePass = new MergeExtensionConfigurationPass();
 
-        $this->optimizationPasses = array(
-            new ExtensionCompilerPass(),
-            new ResolveDefinitionTemplatesPass(),
+        $this->beforeOptimizationPasses = [
+            100 => [
+                $resolveClassPass = new ResolveClassPass(),
+                new ResolveInstanceofConditionalsPass(),
+                new RegisterEnvVarProcessorsPass(),
+            ],
+            -1000 => [new ExtensionCompilerPass()],
+        ];
+
+        $this->optimizationPasses = [[
+            new ResolveChildDefinitionsPass(),
+            new ServiceLocatorTagPass(),
+            new RegisterServiceSubscribersPass(),
             new DecoratorServicePass(),
-            new ResolveParameterPlaceHoldersPass(),
+            new ResolveParameterPlaceHoldersPass(false, false),
+            new ResolveFactoryClassPass(),
+            new FactoryReturnTypePass($resolveClassPass),
             new CheckDefinitionValidityPass(),
+            new ResolveNamedArgumentsPass(),
+            new AutowireRequiredMethodsPass(),
+            new ResolveBindingsPass(),
+            new AutowirePass(false),
+            new ResolveTaggedIteratorArgumentPass(),
+            new ResolveServiceSubscribersPass(),
             new ResolveReferencesToAliasesPass(),
             new ResolveInvalidReferencesPass(),
-            new AutowirePass(),
             new AnalyzeServiceReferencesPass(true),
             new CheckCircularReferencesPass(),
             new CheckReferenceValidityPass(),
-        );
+            new CheckArgumentsValidityPass(false),
+        ]];
+
+        $this->beforeRemovingPasses = [
+            -100 => [
+                new ResolvePrivatesPass(),
+            ],
+        ];
 
-        $this->removingPasses = array(
+        $this->removingPasses = [[
             new RemovePrivateAliasesPass(),
             new ReplaceAliasByActualDefinitionPass(),
             new RemoveAbstractDefinitionsPass(),
-            new RepeatedPass(array(
+            new RepeatedPass([
                 new AnalyzeServiceReferencesPass(),
                 new InlineServiceDefinitionsPass(),
                 new AnalyzeServiceReferencesPass(),
                 new RemoveUnusedDefinitionsPass(),
-            )),
+            ]),
+            new DefinitionErrorExceptionPass(),
             new CheckExceptionOnInvalidReferenceBehaviorPass(),
-        );
+            new ResolveHotPathPass(),
+        ]];
     }
 
     /**
      * Returns all passes in order to be processed.
      *
-     * @return array An array of all passes to process
+     * @return CompilerPassInterface[]
      */
     public function getPasses()
     {
         return array_merge(
-            array($this->mergePass),
-            $this->beforeOptimizationPasses,
-            $this->optimizationPasses,
-            $this->beforeRemovingPasses,
-            $this->removingPasses,
-            $this->afterRemovingPasses
+            [$this->mergePass],
+            $this->getBeforeOptimizationPasses(),
+            $this->getOptimizationPasses(),
+            $this->getBeforeRemovingPasses(),
+            $this->getRemovingPasses(),
+            $this->getAfterRemovingPasses()
         );
     }
 
@@ -92,70 +118,88 @@ class PassConfig
      *
      * @throws InvalidArgumentException when a pass type doesn't exist
      */
-    public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION)
+    public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
     {
+        if (\func_num_args() >= 3) {
+            $priority = func_get_arg(2);
+        } else {
+            if (__CLASS__ !== static::class) {
+                $r = new \ReflectionMethod($this, __FUNCTION__);
+                if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
+                    @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED);
+                }
+            }
+
+            $priority = 0;
+        }
+
         $property = $type.'Passes';
         if (!isset($this->$property)) {
             throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
         }
 
-        $this->{$property}[] = $pass;
+        $passes = &$this->$property;
+
+        if (!isset($passes[$priority])) {
+            $passes[$priority] = [];
+        }
+        $passes[$priority][] = $pass;
     }
 
     /**
      * Gets all passes for the AfterRemoving pass.
      *
-     * @return array An array of passes
+     * @return CompilerPassInterface[]
      */
     public function getAfterRemovingPasses()
     {
-        return $this->afterRemovingPasses;
+        return $this->sortPasses($this->afterRemovingPasses);
     }
 
     /**
      * Gets all passes for the BeforeOptimization pass.
      *
-     * @return array An array of passes
+     * @return CompilerPassInterface[]
      */
     public function getBeforeOptimizationPasses()
     {
-        return $this->beforeOptimizationPasses;
+        return $this->sortPasses($this->beforeOptimizationPasses);
     }
 
     /**
      * Gets all passes for the BeforeRemoving pass.
      *
-     * @return array An array of passes
+     * @return CompilerPassInterface[]
      */
     public function getBeforeRemovingPasses()
     {
-        return $this->beforeRemovingPasses;
+        return $this->sortPasses($this->beforeRemovingPasses);
     }
 
     /**
      * Gets all passes for the Optimization pass.
      *
-     * @return array An array of passes
+     * @return CompilerPassInterface[]
      */
     public function getOptimizationPasses()
     {
-        return $this->optimizationPasses;
+        return $this->sortPasses($this->optimizationPasses);
     }
 
     /**
      * Gets all passes for the Removing pass.
      *
-     * @return array An array of passes
+     * @return CompilerPassInterface[]
      */
     public function getRemovingPasses()
     {
-        return $this->removingPasses;
+        return $this->sortPasses($this->removingPasses);
     }
 
     /**
      * Gets the Merge pass.
      *
-     * @return CompilerPassInterface The merge pass
+     * @return CompilerPassInterface
      */
     public function getMergePass()
     {
@@ -170,50 +214,69 @@ class PassConfig
     /**
      * Sets the AfterRemoving passes.
      *
-     * @param array $passes An array of passes
+     * @param CompilerPassInterface[] $passes
      */
     public function setAfterRemovingPasses(array $passes)
     {
-        $this->afterRemovingPasses = $passes;
+        $this->afterRemovingPasses = [$passes];
     }
 
     /**
      * Sets the BeforeOptimization passes.
      *
-     * @param array $passes An array of passes
+     * @param CompilerPassInterface[] $passes
      */
     public function setBeforeOptimizationPasses(array $passes)
     {
-        $this->beforeOptimizationPasses = $passes;
+        $this->beforeOptimizationPasses = [$passes];
     }
 
     /**
      * Sets the BeforeRemoving passes.
      *
-     * @param array $passes An array of passes
+     * @param CompilerPassInterface[] $passes
      */
     public function setBeforeRemovingPasses(array $passes)
     {
-        $this->beforeRemovingPasses = $passes;
+        $this->beforeRemovingPasses = [$passes];
     }
 
     /**
      * Sets the Optimization passes.
      *
-     * @param array $passes An array of passes
+     * @param CompilerPassInterface[] $passes
      */
     public function setOptimizationPasses(array $passes)
     {
-        $this->optimizationPasses = $passes;
+        $this->optimizationPasses = [$passes];
     }
 
     /**
      * Sets the Removing passes.
      *
-     * @param array $passes An array of passes
+     * @param CompilerPassInterface[] $passes
      */
     public function setRemovingPasses(array $passes)
     {
-        $this->removingPasses = $passes;
+        $this->removingPasses = [$passes];
+    }
+
+    /**
+     * Sort passes by priority.
+     *
+     * @param array $passes CompilerPassInterface instances with their priority as key
+     *
+     * @return CompilerPassInterface[]
+     */
+    private function sortPasses(array $passes)
+    {
+        if (0 === \count($passes)) {
+            return [];
+        }
+
+        krsort($passes);
+
+        // Flatten the array
+        return \call_user_func_array('array_merge', $passes);
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php b/civicrm/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
new file mode 100644
index 0000000000..c7e12536ea
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Trait that allows a generic method to find and sort service by priority option in the tag.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+trait PriorityTaggedServiceTrait
+{
+    /**
+     * Finds all services with the given tag name and order them by their priority.
+     *
+     * The order of additions must be respected for services having the same priority,
+     * and knowing that the \SplPriorityQueue class does not respect the FIFO method,
+     * we should not use that class.
+     *
+     * @see https://bugs.php.net/53710
+     * @see https://bugs.php.net/60926
+     *
+     * @param string $tagName
+     *
+     * @return Reference[]
+     */
+    private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
+    {
+        $services = [];
+
+        foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
+            $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
+            $services[$priority][] = new Reference($serviceId);
+        }
+
+        if ($services) {
+            krsort($services);
+            $services = \call_user_func_array('array_merge', $services);
+        }
+
+        return $services;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
new file mode 100644
index 0000000000..b4d0d05506
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
@@ -0,0 +1,78 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\EnvVarProcessor;
+use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+
+/**
+ * Creates the container.env_var_processors_locator service.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class RegisterEnvVarProcessorsPass implements CompilerPassInterface
+{
+    private static $allowedTypes = ['array', 'bool', 'float', 'int', 'string'];
+
+    public function process(ContainerBuilder $container)
+    {
+        $bag = $container->getParameterBag();
+        $types = [];
+        $processors = [];
+        foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) {
+            if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) {
+                throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
+            } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) {
+                throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class));
+            }
+            foreach ($class::getProvidedTypes() as $prefix => $type) {
+                $processors[$prefix] = new ServiceClosureArgument(new Reference($id));
+                $types[$prefix] = self::validateProvidedTypes($type, $class);
+            }
+        }
+
+        if ($bag instanceof EnvPlaceholderParameterBag) {
+            foreach (EnvVarProcessor::getProvidedTypes() as $prefix => $type) {
+                if (!isset($types[$prefix])) {
+                    $types[$prefix] = self::validateProvidedTypes($type, EnvVarProcessor::class);
+                }
+            }
+            $bag->setProvidedTypes($types);
+        }
+
+        if ($processors) {
+            $container->register('container.env_var_processors_locator', ServiceLocator::class)
+                ->setPublic(true)
+                ->setArguments([$processors])
+            ;
+        }
+    }
+
+    private static function validateProvidedTypes($types, $class)
+    {
+        $types = explode('|', $types);
+
+        foreach ($types as $type) {
+            if (!\in_array($type, self::$allowedTypes)) {
+                throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::$allowedTypes)));
+            }
+        }
+
+        return $types;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
new file mode 100644
index 0000000000..bf1387c04e
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
@@ -0,0 +1,101 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
+use Symfony\Component\DependencyInjection\TypedReference;
+
+/**
+ * Compiler pass to register tagged services that require a service locator.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class RegisterServiceSubscribersPass extends AbstractRecursivePass
+{
+    protected function processValue($value, $isRoot = false)
+    {
+        if (!$value instanceof Definition || $value->isAbstract() || $value->isSynthetic() || !$value->hasTag('container.service_subscriber')) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        $serviceMap = [];
+        $autowire = $value->isAutowired();
+
+        foreach ($value->getTag('container.service_subscriber') as $attributes) {
+            if (!$attributes) {
+                $autowire = true;
+                continue;
+            }
+            ksort($attributes);
+            if ([] !== array_diff(array_keys($attributes), ['id', 'key'])) {
+                throw new InvalidArgumentException(sprintf('The "container.service_subscriber" tag accepts only the "key" and "id" attributes, "%s" given for service "%s".', implode('", "', array_keys($attributes)), $this->currentId));
+            }
+            if (!\array_key_exists('id', $attributes)) {
+                throw new InvalidArgumentException(sprintf('Missing "id" attribute on "container.service_subscriber" tag with key="%s" for service "%s".', $attributes['key'], $this->currentId));
+            }
+            if (!\array_key_exists('key', $attributes)) {
+                $attributes['key'] = $attributes['id'];
+            }
+            if (isset($serviceMap[$attributes['key']])) {
+                continue;
+            }
+            $serviceMap[$attributes['key']] = new Reference($attributes['id']);
+        }
+        $class = $value->getClass();
+
+        if (!$r = $this->container->getReflectionClass($class)) {
+            throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId));
+        }
+        if (!$r->isSubclassOf(ServiceSubscriberInterface::class)) {
+            throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class));
+        }
+        $class = $r->name;
+
+        $subscriberMap = [];
+        $declaringClass = (new \ReflectionMethod($class, 'getSubscribedServices'))->class;
+
+        foreach ($class::getSubscribedServices() as $key => $type) {
+            if (!\is_string($type) || !preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $type)) {
+                throw new InvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : \gettype($type)));
+            }
+            if ($optionalBehavior = '?' === $type[0]) {
+                $type = substr($type, 1);
+                $optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
+            }
+            if (\is_int($key)) {
+                $key = $type;
+            }
+            if (!isset($serviceMap[$key])) {
+                if (!$autowire) {
+                    throw new InvalidArgumentException(sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class));
+                }
+                $serviceMap[$key] = new Reference($type);
+            }
+
+            $subscriberMap[$key] = new TypedReference($this->container->normalizeId($serviceMap[$key]), $type, $declaringClass, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
+            unset($serviceMap[$key]);
+        }
+
+        if ($serviceMap = array_keys($serviceMap)) {
+            $message = sprintf(1 < \count($serviceMap) ? 'keys "%s" do' : 'key "%s" does', str_replace('%', '%%', implode('", "', $serviceMap)));
+            throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId));
+        }
+
+        $value->addTag('container.service_subscriber.locator', ['id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId)]);
+
+        return parent::processValue($value);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php
index 9999214c8b..04b6852fab 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php
@@ -23,13 +23,10 @@ class RemoveAbstractDefinitionsPass implements CompilerPassInterface
      */
     public function process(ContainerBuilder $container)
     {
-        $compiler = $container->getCompiler();
-        $formatter = $compiler->getLoggingFormatter();
-
         foreach ($container->getDefinitions() as $id => $definition) {
             if ($definition->isAbstract()) {
                 $container->removeDefinition($id);
-                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'abstract'));
+                $container->log($this, sprintf('Removed service "%s"; reason: abstract.', $id));
             }
         }
     }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
index 36abc6159e..03d9e1d8a5 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
@@ -27,16 +27,13 @@ class RemovePrivateAliasesPass implements CompilerPassInterface
      */
     public function process(ContainerBuilder $container)
     {
-        $compiler = $container->getCompiler();
-        $formatter = $compiler->getLoggingFormatter();
-
         foreach ($container->getAliases() as $id => $alias) {
-            if ($alias->isPublic()) {
+            if ($alias->isPublic() || $alias->isPrivate()) {
                 continue;
             }
 
             $container->removeAlias($id);
-            $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'private alias'));
+            $container->log($this, sprintf('Removed service "%s"; reason: private alias.', $id));
         }
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
index 911875cf51..a1013f66c0 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
@@ -35,21 +35,22 @@ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
      */
     public function process(ContainerBuilder $container)
     {
-        $compiler = $container->getCompiler();
-        $formatter = $compiler->getLoggingFormatter();
-        $graph = $compiler->getServiceReferenceGraph();
+        $graph = $container->getCompiler()->getServiceReferenceGraph();
 
         $hasChanged = false;
         foreach ($container->getDefinitions() as $id => $definition) {
-            if ($definition->isPublic()) {
+            if ($definition->isPublic() || $definition->isPrivate()) {
                 continue;
             }
 
             if ($graph->hasNode($id)) {
                 $edges = $graph->getNode($id)->getInEdges();
-                $referencingAliases = array();
-                $sourceIds = array();
+                $referencingAliases = [];
+                $sourceIds = [];
                 foreach ($edges as $edge) {
+                    if ($edge->isWeak()) {
+                        continue;
+                    }
                     $node = $edge->getSourceNode();
                     $sourceIds[] = $node->getId();
 
@@ -59,18 +60,20 @@ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
                 }
                 $isReferenced = (\count(array_unique($sourceIds)) - \count($referencingAliases)) > 0;
             } else {
-                $referencingAliases = array();
+                $referencingAliases = [];
                 $isReferenced = false;
             }
 
             if (1 === \count($referencingAliases) && false === $isReferenced) {
                 $container->setDefinition((string) reset($referencingAliases), $definition);
-                $definition->setPublic(true);
+                $definition->setPublic(!$definition->isPrivate());
+                $definition->setPrivate(reset($referencingAliases)->isPrivate());
                 $container->removeDefinition($id);
-                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'replaces alias '.reset($referencingAliases)));
+                $container->log($this, sprintf('Removed service "%s"; reason: replaces alias %s.', $id, reset($referencingAliases)));
             } elseif (0 === \count($referencingAliases) && false === $isReferenced) {
                 $container->removeDefinition($id);
-                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'unused'));
+                $container->resolveEnvPlaceholders(serialize($definition));
+                $container->log($this, sprintf('Removed service "%s"; reason: unused.', $id));
                 $hasChanged = true;
             }
         }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
index cf48c53da8..472bf9415a 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
@@ -21,10 +21,9 @@ use Symfony\Component\DependencyInjection\Reference;
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
+class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass
 {
-    private $compiler;
-    private $formatter;
+    private $replacements;
 
     /**
      * Process the Container to replace aliases with service definitions.
@@ -33,21 +32,18 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
      */
     public function process(ContainerBuilder $container)
     {
-        // Setup
-        $this->compiler = $container->getCompiler();
-        $this->formatter = $this->compiler->getLoggingFormatter();
         // First collect all alias targets that need to be replaced
-        $seenAliasTargets = array();
-        $replacements = array();
+        $seenAliasTargets = [];
+        $replacements = [];
         foreach ($container->getAliases() as $definitionId => $target) {
-            $targetId = (string) $target;
+            $targetId = $container->normalizeId($target);
             // Special case: leave this target alone
             if ('service_container' === $targetId) {
                 continue;
             }
             // Check if target needs to be replaces
             if (isset($replacements[$targetId])) {
-                $container->setAlias($definitionId, $replacements[$targetId]);
+                $container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic())->setPrivate($target->isPrivate());
             }
             // No need to process the same target twice
             if (isset($seenAliasTargets[$targetId])) {
@@ -60,83 +56,34 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
             } catch (InvalidArgumentException $e) {
                 throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e);
             }
-            if ($definition->isPublic()) {
+            if ($definition->isPublic() || $definition->isPrivate()) {
                 continue;
             }
             // Remove private definition and schedule for replacement
-            $definition->setPublic(true);
+            $definition->setPublic(!$target->isPrivate());
+            $definition->setPrivate($target->isPrivate());
             $container->setDefinition($definitionId, $definition);
             $container->removeDefinition($targetId);
             $replacements[$targetId] = $definitionId;
         }
+        $this->replacements = $replacements;
 
-        // Now replace target instances in all definitions
-        foreach ($container->getDefinitions() as $definitionId => $definition) {
-            $definition->setArguments($this->updateArgumentReferences($replacements, $definitionId, $definition->getArguments()));
-            $definition->setMethodCalls($this->updateArgumentReferences($replacements, $definitionId, $definition->getMethodCalls()));
-            $definition->setProperties($this->updateArgumentReferences($replacements, $definitionId, $definition->getProperties()));
-            $definition->setFactoryService($this->updateFactoryReferenceId($replacements, $definition->getFactoryService(false)), false);
-            $definition->setFactory($this->updateFactoryReference($replacements, $definition->getFactory()));
-        }
+        parent::process($container);
+        $this->replacements = [];
     }
 
     /**
-     * Recursively updates references in an array.
-     *
-     * @param array  $replacements Table of aliases to replace
-     * @param string $definitionId Identifier of this definition
-     * @param array  $arguments    Where to replace the aliases
-     *
-     * @return array
+     * {@inheritdoc}
      */
-    private function updateArgumentReferences(array $replacements, $definitionId, array $arguments)
+    protected function processValue($value, $isRoot = false)
     {
-        foreach ($arguments as $k => $argument) {
-            // Handle recursion step
-            if (\is_array($argument)) {
-                $arguments[$k] = $this->updateArgumentReferences($replacements, $definitionId, $argument);
-                continue;
-            }
-            // Skip arguments that don't need replacement
-            if (!$argument instanceof Reference) {
-                continue;
-            }
-            $referenceId = (string) $argument;
-            if (!isset($replacements[$referenceId])) {
-                continue;
-            }
+        if ($value instanceof Reference && isset($this->replacements[$referenceId = $this->container->normalizeId($value)])) {
             // Perform the replacement
-            $newId = $replacements[$referenceId];
-            $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
-            $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $definitionId, $referenceId, $newId));
-        }
-
-        return $arguments;
-    }
-
-    /**
-     * Returns the updated reference for the factory service.
-     *
-     * @param array       $replacements Table of aliases to replace
-     * @param string|null $referenceId  Factory service reference identifier
-     *
-     * @return string|null
-     */
-    private function updateFactoryReferenceId(array $replacements, $referenceId)
-    {
-        if (null === $referenceId) {
-            return;
-        }
-
-        return isset($replacements[$referenceId]) ? $replacements[$referenceId] : $referenceId;
-    }
-
-    private function updateFactoryReference(array $replacements, $factory)
-    {
-        if (\is_array($factory) && $factory[0] instanceof Reference && isset($replacements[$referenceId = (string) $factory[0]])) {
-            $factory[0] = new Reference($replacements[$referenceId], $factory[0]->getInvalidBehavior());
+            $newId = $this->replacements[$referenceId];
+            $value = new Reference($newId, $value->getInvalidBehavior());
+            $this->container->log($this, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $this->currentId, $referenceId, $newId));
         }
 
-        return $factory;
+        return parent::processValue($value, $isRoot);
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
new file mode 100644
index 0000000000..065dbb4b40
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
@@ -0,0 +1,180 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Argument\BoundArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\TypedReference;
+
+/**
+ * @author Guilhem Niot <guilhem.niot@gmail.com>
+ */
+class ResolveBindingsPass extends AbstractRecursivePass
+{
+    private $usedBindings = [];
+    private $unusedBindings = [];
+    private $errorMessages = [];
+
+    /**
+     * {@inheritdoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        $this->usedBindings = $container->getRemovedBindingIds();
+
+        try {
+            parent::process($container);
+
+            foreach ($this->unusedBindings as list($key, $serviceId)) {
+                $message = sprintf('Unused binding "%s" in service "%s".', $key, $serviceId);
+                if ($this->errorMessages) {
+                    $message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : '');
+                }
+                foreach ($this->errorMessages as $m) {
+                    $message .= "\n - ".$m;
+                }
+                throw new InvalidArgumentException($message);
+            }
+        } finally {
+            $this->usedBindings = [];
+            $this->unusedBindings = [];
+            $this->errorMessages = [];
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if ($value instanceof TypedReference && $value->getType() === $this->container->normalizeId($value)) {
+            // Already checked
+            $bindings = $this->container->getDefinition($this->currentId)->getBindings();
+
+            if (isset($bindings[$value->getType()])) {
+                return $this->getBindingValue($bindings[$value->getType()]);
+            }
+
+            return parent::processValue($value, $isRoot);
+        }
+
+        if (!$value instanceof Definition || !$bindings = $value->getBindings()) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        foreach ($bindings as $key => $binding) {
+            list($bindingValue, $bindingId, $used) = $binding->getValues();
+            if ($used) {
+                $this->usedBindings[$bindingId] = true;
+                unset($this->unusedBindings[$bindingId]);
+            } elseif (!isset($this->usedBindings[$bindingId])) {
+                $this->unusedBindings[$bindingId] = [$key, $this->currentId];
+            }
+
+            if (isset($key[0]) && '$' === $key[0]) {
+                continue;
+            }
+
+            if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition) {
+                throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected null, an instance of "%s" or an instance of "%s", "%s" given.', $key, $this->currentId, Reference::class, Definition::class, \gettype($bindingValue)));
+            }
+        }
+
+        if ($value->isAbstract()) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        $calls = $value->getMethodCalls();
+
+        try {
+            if ($constructor = $this->getConstructor($value, false)) {
+                $calls[] = [$constructor, $value->getArguments()];
+            }
+        } catch (RuntimeException $e) {
+            $this->errorMessages[] = $e->getMessage();
+            $this->container->getDefinition($this->currentId)->addError($e->getMessage());
+
+            return parent::processValue($value, $isRoot);
+        }
+
+        foreach ($calls as $i => $call) {
+            list($method, $arguments) = $call;
+
+            if ($method instanceof \ReflectionFunctionAbstract) {
+                $reflectionMethod = $method;
+            } else {
+                try {
+                    $reflectionMethod = $this->getReflectionMethod($value, $method);
+                } catch (RuntimeException $e) {
+                    if ($value->getFactory()) {
+                        continue;
+                    }
+                    throw $e;
+                }
+            }
+
+            foreach ($reflectionMethod->getParameters() as $key => $parameter) {
+                if (\array_key_exists($key, $arguments) && '' !== $arguments[$key]) {
+                    continue;
+                }
+
+                if (\array_key_exists('$'.$parameter->name, $bindings)) {
+                    $arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]);
+
+                    continue;
+                }
+
+                $typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
+
+                if (!isset($bindings[$typeHint])) {
+                    continue;
+                }
+
+                $arguments[$key] = $this->getBindingValue($bindings[$typeHint]);
+            }
+
+            if ($arguments !== $call[1]) {
+                ksort($arguments);
+                $calls[$i][1] = $arguments;
+            }
+        }
+
+        if ($constructor) {
+            list(, $arguments) = array_pop($calls);
+
+            if ($arguments !== $value->getArguments()) {
+                $value->setArguments($arguments);
+            }
+        }
+
+        if ($calls !== $value->getMethodCalls()) {
+            $value->setMethodCalls($calls);
+        }
+
+        return parent::processValue($value, $isRoot);
+    }
+
+    private function getBindingValue(BoundArgument $binding)
+    {
+        list($bindingValue, $bindingId) = $binding->getValues();
+
+        $this->usedBindings[$bindingId] = true;
+        unset($this->unusedBindings[$bindingId]);
+
+        return $bindingValue;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
new file mode 100644
index 0000000000..539395a437
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
@@ -0,0 +1,198 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\ExceptionInterface;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
+
+/**
+ * This replaces all ChildDefinition instances with their equivalent fully
+ * merged Definition instance.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ResolveChildDefinitionsPass extends AbstractRecursivePass
+{
+    private $currentPath;
+
+    protected function processValue($value, $isRoot = false)
+    {
+        if (!$value instanceof Definition) {
+            return parent::processValue($value, $isRoot);
+        }
+        if ($isRoot) {
+            // yes, we are specifically fetching the definition from the
+            // container to ensure we are not operating on stale data
+            $value = $this->container->getDefinition($this->currentId);
+        }
+        if ($value instanceof ChildDefinition) {
+            $this->currentPath = [];
+            $value = $this->resolveDefinition($value);
+            if ($isRoot) {
+                $this->container->setDefinition($this->currentId, $value);
+            }
+        }
+
+        return parent::processValue($value, $isRoot);
+    }
+
+    /**
+     * Resolves the definition.
+     *
+     * @return Definition
+     *
+     * @throws RuntimeException When the definition is invalid
+     */
+    private function resolveDefinition(ChildDefinition $definition)
+    {
+        try {
+            return $this->doResolveDefinition($definition);
+        } catch (ServiceCircularReferenceException $e) {
+            throw $e;
+        } catch (ExceptionInterface $e) {
+            $r = new \ReflectionProperty($e, 'message');
+            $r->setAccessible(true);
+            $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage()));
+
+            throw $e;
+        }
+    }
+
+    private function doResolveDefinition(ChildDefinition $definition)
+    {
+        if (!$this->container->has($parent = $definition->getParent())) {
+            throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent));
+        }
+
+        $searchKey = array_search($parent, $this->currentPath);
+        $this->currentPath[] = $parent;
+
+        if (false !== $searchKey) {
+            throw new ServiceCircularReferenceException($parent, \array_slice($this->currentPath, $searchKey));
+        }
+
+        $parentDef = $this->container->findDefinition($parent);
+        if ($parentDef instanceof ChildDefinition) {
+            $id = $this->currentId;
+            $this->currentId = $parent;
+            $parentDef = $this->resolveDefinition($parentDef);
+            $this->container->setDefinition($parent, $parentDef);
+            $this->currentId = $id;
+        }
+
+        $this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent));
+        $def = new Definition();
+
+        // merge in parent definition
+        // purposely ignored attributes: abstract, shared, tags, autoconfigured
+        $def->setClass($parentDef->getClass());
+        $def->setArguments($parentDef->getArguments());
+        $def->setMethodCalls($parentDef->getMethodCalls());
+        $def->setProperties($parentDef->getProperties());
+        if ($parentDef->getAutowiringTypes(false)) {
+            $def->setAutowiringTypes($parentDef->getAutowiringTypes(false));
+        }
+        if ($parentDef->isDeprecated()) {
+            $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
+        }
+        $def->setFactory($parentDef->getFactory());
+        $def->setConfigurator($parentDef->getConfigurator());
+        $def->setFile($parentDef->getFile());
+        $def->setPublic($parentDef->isPublic());
+        $def->setLazy($parentDef->isLazy());
+        $def->setAutowired($parentDef->isAutowired());
+        $def->setChanges($parentDef->getChanges());
+
+        $def->setBindings($definition->getBindings() + $parentDef->getBindings());
+
+        // overwrite with values specified in the decorator
+        $changes = $definition->getChanges();
+        if (isset($changes['class'])) {
+            $def->setClass($definition->getClass());
+        }
+        if (isset($changes['factory'])) {
+            $def->setFactory($definition->getFactory());
+        }
+        if (isset($changes['configurator'])) {
+            $def->setConfigurator($definition->getConfigurator());
+        }
+        if (isset($changes['file'])) {
+            $def->setFile($definition->getFile());
+        }
+        if (isset($changes['public'])) {
+            $def->setPublic($definition->isPublic());
+        } else {
+            $def->setPrivate($definition->isPrivate() || $parentDef->isPrivate());
+        }
+        if (isset($changes['lazy'])) {
+            $def->setLazy($definition->isLazy());
+        }
+        if (isset($changes['deprecated'])) {
+            $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
+        }
+        if (isset($changes['autowired'])) {
+            $def->setAutowired($definition->isAutowired());
+        }
+        if (isset($changes['shared'])) {
+            $def->setShared($definition->isShared());
+        }
+        if (isset($changes['decorated_service'])) {
+            $decoratedService = $definition->getDecoratedService();
+            if (null === $decoratedService) {
+                $def->setDecoratedService($decoratedService);
+            } else {
+                $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
+            }
+        }
+
+        // merge arguments
+        foreach ($definition->getArguments() as $k => $v) {
+            if (is_numeric($k)) {
+                $def->addArgument($v);
+            } elseif (0 === strpos($k, 'index_')) {
+                $def->replaceArgument((int) substr($k, \strlen('index_')), $v);
+            } else {
+                $def->setArgument($k, $v);
+            }
+        }
+
+        // merge properties
+        foreach ($definition->getProperties() as $k => $v) {
+            $def->setProperty($k, $v);
+        }
+
+        // append method calls
+        if ($calls = $definition->getMethodCalls()) {
+            $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
+        }
+
+        // merge autowiring types
+        foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
+            $def->addAutowiringType($autowiringType);
+        }
+
+        // these attributes are always taken from the child
+        $def->setAbstract($definition->isAbstract());
+        $def->setTags($definition->getTags());
+        // autoconfigure is never taken from parent (on purpose)
+        // and it's not legal on an instanceof
+        $def->setAutoconfigured($definition->isAutoconfigured());
+
+        return $def;
+    }
+}
+
+class_alias(ResolveChildDefinitionsPass::class, ResolveDefinitionTemplatesPass::class);
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
new file mode 100644
index 0000000000..b1c1b4f884
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ResolveClassPass implements CompilerPassInterface
+{
+    private $changes = [];
+
+    /**
+     * {@inheritdoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        foreach ($container->getDefinitions() as $id => $definition) {
+            if ($definition->isSynthetic() || null !== $definition->getClass()) {
+                continue;
+            }
+            if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) {
+                if ($definition instanceof ChildDefinition && !class_exists($id)) {
+                    throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id));
+                }
+                $this->changes[strtolower($id)] = $id;
+                $definition->setClass($id);
+            }
+        }
+    }
+
+    /**
+     * @internal
+     *
+     * @deprecated since 3.3, to be removed in 4.0.
+     */
+    public function getChanges()
+    {
+        $changes = $this->changes;
+        $this->changes = [];
+
+        return $changes;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php
index db1864ec01..d48eff2214 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php
@@ -11,211 +11,19 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
-use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+@trigger_error('The '.__NAMESPACE__.'\ResolveDefinitionTemplatesPass class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead.', E_USER_DEPRECATED);
 
-/**
- * This replaces all DefinitionDecorator instances with their equivalent fully
- * merged Definition instance.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- * @author Nicolas Grekas <p@tchwork.com>
- */
-class ResolveDefinitionTemplatesPass implements CompilerPassInterface
-{
-    private $compiler;
-    private $formatter;
-    private $currentId;
-
-    /**
-     * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances.
-     */
-    public function process(ContainerBuilder $container)
-    {
-        $this->compiler = $container->getCompiler();
-        $this->formatter = $this->compiler->getLoggingFormatter();
-
-        $container->setDefinitions($this->resolveArguments($container, $container->getDefinitions(), true));
-    }
+class_exists(ResolveChildDefinitionsPass::class);
 
+if (false) {
     /**
-     * Resolves definition decorator arguments.
+     * This definition decorates another definition.
      *
-     * @param ContainerBuilder $container The ContainerBuilder
-     * @param array            $arguments An array of arguments
-     * @param bool             $isRoot    If we are processing the root definitions or not
+     * @author Johannes M. Schmitt <schmittjoh@gmail.com>
      *
-     * @return array
+     * @deprecated The ResolveDefinitionTemplatesPass class is deprecated since version 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead.
      */
-    private function resolveArguments(ContainerBuilder $container, array $arguments, $isRoot = false)
+    class ResolveDefinitionTemplatesPass extends AbstractRecursivePass
     {
-        foreach ($arguments as $k => $argument) {
-            if ($isRoot) {
-                // yes, we are specifically fetching the definition from the
-                // container to ensure we are not operating on stale data
-                $arguments[$k] = $argument = $container->getDefinition($k);
-                $this->currentId = $k;
-            }
-            if (\is_array($argument)) {
-                $arguments[$k] = $this->resolveArguments($container, $argument);
-            } elseif ($argument instanceof Definition) {
-                if ($argument instanceof DefinitionDecorator) {
-                    $arguments[$k] = $argument = $this->resolveDefinition($container, $argument);
-                    if ($isRoot) {
-                        $container->setDefinition($k, $argument);
-                    }
-                }
-                $argument->setArguments($this->resolveArguments($container, $argument->getArguments()));
-                $argument->setMethodCalls($this->resolveArguments($container, $argument->getMethodCalls()));
-                $argument->setProperties($this->resolveArguments($container, $argument->getProperties()));
-
-                $configurator = $this->resolveArguments($container, array($argument->getConfigurator()));
-                $argument->setConfigurator($configurator[0]);
-
-                $factory = $this->resolveArguments($container, array($argument->getFactory()));
-                $argument->setFactory($factory[0]);
-            }
-        }
-
-        return $arguments;
-    }
-
-    /**
-     * Resolves the definition.
-     *
-     * @param ContainerBuilder    $container  The ContainerBuilder
-     * @param DefinitionDecorator $definition
-     *
-     * @return Definition
-     *
-     * @throws \RuntimeException When the definition is invalid
-     */
-    private function resolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition)
-    {
-        if (!$container->hasDefinition($parent = $definition->getParent())) {
-            throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $this->currentId));
-        }
-
-        $parentDef = $container->getDefinition($parent);
-        if ($parentDef instanceof DefinitionDecorator) {
-            $id = $this->currentId;
-            $this->currentId = $parent;
-            $parentDef = $this->resolveDefinition($container, $parentDef);
-            $container->setDefinition($parent, $parentDef);
-            $this->currentId = $id;
-        }
-
-        $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $this->currentId, $parent));
-        $def = new Definition();
-
-        // merge in parent definition
-        // purposely ignored attributes: scope, abstract, tags
-        $def->setClass($parentDef->getClass());
-        $def->setArguments($parentDef->getArguments());
-        $def->setMethodCalls($parentDef->getMethodCalls());
-        $def->setProperties($parentDef->getProperties());
-        $def->setAutowiringTypes($parentDef->getAutowiringTypes());
-        if ($parentDef->getFactoryClass(false)) {
-            $def->setFactoryClass($parentDef->getFactoryClass(false));
-        }
-        if ($parentDef->getFactoryMethod(false)) {
-            $def->setFactoryMethod($parentDef->getFactoryMethod(false));
-        }
-        if ($parentDef->getFactoryService(false)) {
-            $def->setFactoryService($parentDef->getFactoryService(false));
-        }
-        if ($parentDef->isDeprecated()) {
-            $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
-        }
-        $def->setFactory($parentDef->getFactory());
-        $def->setConfigurator($parentDef->getConfigurator());
-        $def->setFile($parentDef->getFile());
-        $def->setPublic($parentDef->isPublic());
-        $def->setLazy($parentDef->isLazy());
-        $def->setAutowired($parentDef->isAutowired());
-
-        // overwrite with values specified in the decorator
-        $changes = $definition->getChanges();
-        if (isset($changes['class'])) {
-            $def->setClass($definition->getClass());
-        }
-        if (isset($changes['factory_class'])) {
-            $def->setFactoryClass($definition->getFactoryClass(false));
-        }
-        if (isset($changes['factory_method'])) {
-            $def->setFactoryMethod($definition->getFactoryMethod(false));
-        }
-        if (isset($changes['factory_service'])) {
-            $def->setFactoryService($definition->getFactoryService(false));
-        }
-        if (isset($changes['factory'])) {
-            $def->setFactory($definition->getFactory());
-        }
-        if (isset($changes['configurator'])) {
-            $def->setConfigurator($definition->getConfigurator());
-        }
-        if (isset($changes['file'])) {
-            $def->setFile($definition->getFile());
-        }
-        if (isset($changes['public'])) {
-            $def->setPublic($definition->isPublic());
-        }
-        if (isset($changes['lazy'])) {
-            $def->setLazy($definition->isLazy());
-        }
-        if (isset($changes['deprecated'])) {
-            $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
-        }
-        if (isset($changes['autowire'])) {
-            $def->setAutowired($definition->isAutowired());
-        }
-        if (isset($changes['decorated_service'])) {
-            $decoratedService = $definition->getDecoratedService();
-            if (null === $decoratedService) {
-                $def->setDecoratedService($decoratedService);
-            } else {
-                $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
-            }
-        }
-
-        // merge arguments
-        foreach ($definition->getArguments() as $k => $v) {
-            if (is_numeric($k)) {
-                $def->addArgument($v);
-                continue;
-            }
-
-            if (0 !== strpos($k, 'index_')) {
-                throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
-            }
-
-            $index = (int) substr($k, \strlen('index_'));
-            $def->replaceArgument($index, $v);
-        }
-
-        // merge properties
-        foreach ($definition->getProperties() as $k => $v) {
-            $def->setProperty($k, $v);
-        }
-
-        // append method calls
-        if (\count($calls = $definition->getMethodCalls()) > 0) {
-            $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
-        }
-
-        // merge autowiring types
-        foreach ($definition->getAutowiringTypes() as $autowiringType) {
-            $def->addAutowiringType($autowiringType);
-        }
-
-        // these attributes are always taken from the child
-        $def->setAbstract($definition->isAbstract());
-        $def->setScope($definition->getScope(false), false);
-        $def->setShared($definition->isShared());
-        $def->setTags($definition->getTags());
-
-        return $def;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php
new file mode 100644
index 0000000000..9e1edd4d31
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Definition;
+
+/**
+ * Replaces env var placeholders by their current values.
+ */
+class ResolveEnvPlaceholdersPass extends AbstractRecursivePass
+{
+    protected function processValue($value, $isRoot = false)
+    {
+        if (\is_string($value)) {
+            return $this->container->resolveEnvPlaceholders($value, true);
+        }
+        if ($value instanceof Definition) {
+            $changes = $value->getChanges();
+            if (isset($changes['class'])) {
+                $value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), true));
+            }
+            if (isset($changes['file'])) {
+                $value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), true));
+            }
+        }
+
+        $value = parent::processValue($value, $isRoot);
+
+        if ($value && \is_array($value) && !$isRoot) {
+            $value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), true), $value);
+        }
+
+        return $value;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php
new file mode 100644
index 0000000000..848da7f2bd
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+class ResolveFactoryClassPass extends AbstractRecursivePass
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if ($value instanceof Definition && \is_array($factory = $value->getFactory()) && null === $factory[0]) {
+            if (null === $class = $value->getClass()) {
+                throw new RuntimeException(sprintf('The "%s" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?', $this->currentId));
+            }
+
+            $factory[0] = $class;
+            $value->setFactory($factory);
+        }
+
+        return parent::processValue($value, $isRoot);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
new file mode 100644
index 0000000000..4e025113ac
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Propagate "container.hot_path" tags to referenced services.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ResolveHotPathPass extends AbstractRecursivePass
+{
+    private $tagName;
+    private $resolvedIds = [];
+
+    public function __construct($tagName = 'container.hot_path')
+    {
+        $this->tagName = $tagName;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        try {
+            parent::process($container);
+            $container->getDefinition('service_container')->clearTag($this->tagName);
+        } finally {
+            $this->resolvedIds = [];
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if ($value instanceof ArgumentInterface) {
+            return $value;
+        }
+        if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) {
+            return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value;
+        }
+        if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = $this->container->normalizeId($value))) {
+            $definition = $this->container->findDefinition($id);
+            if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) {
+                $this->resolvedIds[$id] = true;
+                $definition->addTag($this->tagName);
+                parent::processValue($definition, false);
+            }
+
+            return $value;
+        }
+
+        return parent::processValue($value, $isRoot);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
new file mode 100644
index 0000000000..6268ed9ed0
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
@@ -0,0 +1,156 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * Applies instanceof conditionals to definitions.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ResolveInstanceofConditionalsPass implements CompilerPassInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) {
+            if ($definition->getArguments()) {
+                throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface));
+            }
+            if ($definition->getMethodCalls()) {
+                throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines method calls but these are not supported and should be removed.', $interface));
+            }
+        }
+
+        foreach ($container->getDefinitions() as $id => $definition) {
+            if ($definition instanceof ChildDefinition) {
+                // don't apply "instanceof" to children: it will be applied to their parent
+                continue;
+            }
+            $container->setDefinition($id, $this->processDefinition($container, $id, $definition));
+        }
+    }
+
+    private function processDefinition(ContainerBuilder $container, $id, Definition $definition)
+    {
+        $instanceofConditionals = $definition->getInstanceofConditionals();
+        $autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : [];
+        if (!$instanceofConditionals && !$autoconfiguredInstanceof) {
+            return $definition;
+        }
+
+        if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) {
+            return $definition;
+        }
+
+        $conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container);
+
+        $definition->setInstanceofConditionals([]);
+        $parent = $shared = null;
+        $instanceofTags = [];
+        $reflectionClass = null;
+
+        foreach ($conditionals as $interface => $instanceofDefs) {
+            if ($interface !== $class && !(null === $reflectionClass ? $reflectionClass = ($container->getReflectionClass($class, false) ?: false) : $reflectionClass)) {
+                continue;
+            }
+
+            if ($interface !== $class && !is_subclass_of($class, $interface)) {
+                continue;
+            }
+
+            foreach ($instanceofDefs as $key => $instanceofDef) {
+                /** @var ChildDefinition $instanceofDef */
+                $instanceofDef = clone $instanceofDef;
+                $instanceofDef->setAbstract(true)->setParent($parent ?: 'abstract.instanceof.'.$id);
+                $parent = 'instanceof.'.$interface.'.'.$key.'.'.$id;
+                $container->setDefinition($parent, $instanceofDef);
+                $instanceofTags[] = $instanceofDef->getTags();
+                $instanceofDef->setTags([]);
+
+                if (isset($instanceofDef->getChanges()['shared'])) {
+                    $shared = $instanceofDef->isShared();
+                }
+            }
+        }
+
+        if ($parent) {
+            $bindings = $definition->getBindings();
+            $abstract = $container->setDefinition('abstract.instanceof.'.$id, $definition);
+
+            // cast Definition to ChildDefinition
+            $definition->setBindings([]);
+            $definition = serialize($definition);
+            $definition = substr_replace($definition, '53', 2, 2);
+            $definition = substr_replace($definition, 'Child', 44, 0);
+            $definition = unserialize($definition);
+            $definition->setParent($parent);
+
+            if (null !== $shared && !isset($definition->getChanges()['shared'])) {
+                $definition->setShared($shared);
+            }
+
+            $i = \count($instanceofTags);
+            while (0 <= --$i) {
+                foreach ($instanceofTags[$i] as $k => $v) {
+                    foreach ($v as $v) {
+                        if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) {
+                            continue;
+                        }
+                        $definition->addTag($k, $v);
+                    }
+                }
+            }
+
+            $definition->setBindings($bindings);
+
+            // reset fields with "merge" behavior
+            $abstract
+                ->setBindings([])
+                ->setArguments([])
+                ->setMethodCalls([])
+                ->setDecoratedService(null)
+                ->setTags([])
+                ->setAbstract(true);
+        }
+
+        return $definition;
+    }
+
+    private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container)
+    {
+        // make each value an array of ChildDefinition
+        $conditionals = array_map(function ($childDef) { return [$childDef]; }, $autoconfiguredInstanceof);
+
+        foreach ($instanceofConditionals as $interface => $instanceofDef) {
+            // make sure the interface/class exists (but don't validate automaticInstanceofConditionals)
+            if (!$container->getReflectionClass($interface)) {
+                throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface));
+            }
+
+            if (!isset($autoconfiguredInstanceof[$interface])) {
+                $conditionals[$interface] = [];
+            }
+
+            $conditionals[$interface][] = $instanceofDef;
+        }
+
+        return $conditionals;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
index 181c85fa8f..f1a1475aeb 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
@@ -11,8 +11,11 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 use Symfony\Component\DependencyInjection\Reference;
 
@@ -25,6 +28,7 @@ use Symfony\Component\DependencyInjection\Reference;
 class ResolveInvalidReferencesPass implements CompilerPassInterface
 {
     private $container;
+    private $signalingException;
 
     /**
      * Process the ContainerBuilder to resolve invalid references.
@@ -32,72 +36,76 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface
     public function process(ContainerBuilder $container)
     {
         $this->container = $container;
-        foreach ($container->getDefinitions() as $definition) {
-            if ($definition->isSynthetic() || $definition->isAbstract()) {
-                continue;
-            }
-
-            $definition->setArguments(
-                $this->processArguments($definition->getArguments())
-            );
-
-            $calls = array();
-            foreach ($definition->getMethodCalls() as $call) {
-                try {
-                    $calls[] = array($call[0], $this->processArguments($call[1], true));
-                } catch (RuntimeException $e) {
-                    // this call is simply removed
-                }
-            }
-            $definition->setMethodCalls($calls);
+        $this->signalingException = new RuntimeException('Invalid reference.');
 
-            $properties = array();
-            foreach ($definition->getProperties() as $name => $value) {
-                try {
-                    $value = $this->processArguments(array($value), true);
-                    $properties[$name] = reset($value);
-                } catch (RuntimeException $e) {
-                    // ignore property
-                }
-            }
-            $definition->setProperties($properties);
+        try {
+            $this->processValue($container->getDefinitions(), 1);
+        } finally {
+            $this->container = $this->signalingException = null;
         }
     }
 
     /**
      * Processes arguments to determine invalid references.
      *
-     * @param array $arguments    An array of Reference objects
-     * @param bool  $inMethodCall
-     *
-     * @return array
-     *
-     * @throws RuntimeException When the config is invalid
+     * @throws RuntimeException When an invalid reference is found
      */
-    private function processArguments(array $arguments, $inMethodCall = false)
+    private function processValue($value, $rootLevel = 0, $level = 0)
     {
-        foreach ($arguments as $k => $argument) {
-            if (\is_array($argument)) {
-                $arguments[$k] = $this->processArguments($argument, $inMethodCall);
-            } elseif ($argument instanceof Reference) {
-                $id = (string) $argument;
-
-                $invalidBehavior = $argument->getInvalidBehavior();
-                $exists = $this->container->has($id);
+        if ($value instanceof ServiceClosureArgument) {
+            $value->setValues($this->processValue($value->getValues(), 1, 1));
+        } elseif ($value instanceof ArgumentInterface) {
+            $value->setValues($this->processValue($value->getValues(), $rootLevel, 1 + $level));
+        } elseif ($value instanceof Definition) {
+            if ($value->isSynthetic() || $value->isAbstract()) {
+                return $value;
+            }
+            $value->setArguments($this->processValue($value->getArguments(), 0));
+            $value->setProperties($this->processValue($value->getProperties(), 1));
+            $value->setMethodCalls($this->processValue($value->getMethodCalls(), 2));
+        } elseif (\is_array($value)) {
+            $i = 0;
 
-                // resolve invalid behavior
-                if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
-                    $arguments[$k] = null;
-                } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
-                    if ($inMethodCall) {
-                        throw new RuntimeException('Method shouldn\'t be called.');
+            foreach ($value as $k => $v) {
+                try {
+                    if (false !== $i && $k !== $i++) {
+                        $i = false;
+                    }
+                    if ($v !== $processedValue = $this->processValue($v, $rootLevel, 1 + $level)) {
+                        $value[$k] = $processedValue;
+                    }
+                } catch (RuntimeException $e) {
+                    if ($rootLevel < $level || ($rootLevel && !$level)) {
+                        unset($value[$k]);
+                    } elseif ($rootLevel) {
+                        throw $e;
+                    } else {
+                        $value[$k] = null;
                     }
+                }
+            }
+
+            // Ensure numerically indexed arguments have sequential numeric keys.
+            if (false !== $i) {
+                $value = array_values($value);
+            }
+        } elseif ($value instanceof Reference) {
+            if ($this->container->has($value)) {
+                return $value;
+            }
+            $invalidBehavior = $value->getInvalidBehavior();
 
-                    $arguments[$k] = null;
+            // resolve invalid behavior
+            if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
+                $value = null;
+            } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
+                if (0 < $level || $rootLevel) {
+                    throw $this->signalingException;
                 }
+                $value = null;
             }
         }
 
-        return $arguments;
+        return $value;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
new file mode 100644
index 0000000000..225014f1e4
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
@@ -0,0 +1,102 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Resolves named arguments to their corresponding numeric index.
+ *
+ * @author Kévin Dunglas <dunglas@gmail.com>
+ */
+class ResolveNamedArgumentsPass extends AbstractRecursivePass
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if (!$value instanceof Definition) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        $calls = $value->getMethodCalls();
+        $calls[] = ['__construct', $value->getArguments()];
+
+        foreach ($calls as $i => $call) {
+            list($method, $arguments) = $call;
+            $parameters = null;
+            $resolvedArguments = [];
+
+            foreach ($arguments as $key => $argument) {
+                if (\is_int($key)) {
+                    $resolvedArguments[$key] = $argument;
+                    continue;
+                }
+
+                if (null === $parameters) {
+                    $r = $this->getReflectionMethod($value, $method);
+                    $class = $r instanceof \ReflectionMethod ? $r->class : $this->currentId;
+                    $method = $r->getName();
+                    $parameters = $r->getParameters();
+                }
+
+                if (isset($key[0]) && '$' === $key[0]) {
+                    foreach ($parameters as $j => $p) {
+                        if ($key === '$'.$p->name) {
+                            $resolvedArguments[$j] = $argument;
+
+                            continue 2;
+                        }
+                    }
+
+                    throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key));
+                }
+
+                if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) {
+                    throw new InvalidArgumentException(sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of "%s" or an instance of "%s", "%s" given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, \gettype($argument)));
+                }
+
+                $typeFound = false;
+                foreach ($parameters as $j => $p) {
+                    if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) {
+                        $resolvedArguments[$j] = $argument;
+                        $typeFound = true;
+                    }
+                }
+
+                if (!$typeFound) {
+                    throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key));
+                }
+            }
+
+            if ($resolvedArguments !== $call[1]) {
+                ksort($resolvedArguments);
+                $calls[$i][1] = $resolvedArguments;
+            }
+        }
+
+        list(, $arguments) = array_pop($calls);
+
+        if ($arguments !== $value->getArguments()) {
+            $value->setArguments($arguments);
+        }
+        if ($calls !== $value->getMethodCalls()) {
+            $value->setMethodCalls($calls);
+        }
+
+        return parent::processValue($value, $isRoot);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
index 3a31dd55f6..32eb6a3a76 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
@@ -12,6 +12,7 @@
 namespace Symfony\Component\DependencyInjection\Compiler;
 
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
 
 /**
@@ -19,53 +20,79 @@ use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
+class ResolveParameterPlaceHoldersPass extends AbstractRecursivePass
 {
+    private $bag;
+    private $resolveArrays;
+    private $throwOnResolveException;
+
+    public function __construct($resolveArrays = true, $throwOnResolveException = true)
+    {
+        $this->resolveArrays = $resolveArrays;
+        $this->throwOnResolveException = $throwOnResolveException;
+    }
+
     /**
-     * Processes the ContainerBuilder to resolve parameter placeholders.
+     * {@inheritdoc}
      *
      * @throws ParameterNotFoundException
      */
     public function process(ContainerBuilder $container)
     {
-        $parameterBag = $container->getParameterBag();
+        $this->bag = $container->getParameterBag();
 
-        foreach ($container->getDefinitions() as $id => $definition) {
-            try {
-                $definition->setClass($parameterBag->resolveValue($definition->getClass()));
-                $definition->setFile($parameterBag->resolveValue($definition->getFile()));
-                $definition->setArguments($parameterBag->resolveValue($definition->getArguments()));
-                if ($definition->getFactoryClass(false)) {
-                    $definition->setFactoryClass($parameterBag->resolveValue($definition->getFactoryClass(false)));
-                }
+        try {
+            parent::process($container);
 
-                $factory = $definition->getFactory();
+            $aliases = [];
+            foreach ($container->getAliases() as $name => $target) {
+                $this->currentId = $name;
+                $aliases[$this->bag->resolveValue($name)] = $target;
+            }
+            $container->setAliases($aliases);
+        } catch (ParameterNotFoundException $e) {
+            $e->setSourceId($this->currentId);
 
-                if (\is_array($factory) && isset($factory[0])) {
-                    $factory[0] = $parameterBag->resolveValue($factory[0]);
-                    $definition->setFactory($factory);
-                }
+            throw $e;
+        }
 
-                $calls = array();
-                foreach ($definition->getMethodCalls() as $name => $arguments) {
-                    $calls[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($arguments);
-                }
-                $definition->setMethodCalls($calls);
+        $this->bag->resolve();
+        $this->bag = null;
+    }
 
-                $definition->setProperties($parameterBag->resolveValue($definition->getProperties()));
+    protected function processValue($value, $isRoot = false)
+    {
+        if (\is_string($value)) {
+            try {
+                $v = $this->bag->resolveValue($value);
             } catch (ParameterNotFoundException $e) {
-                $e->setSourceId($id);
+                if ($this->throwOnResolveException) {
+                    throw $e;
+                }
 
-                throw $e;
+                $v = null;
+                $this->container->getDefinition($this->currentId)->addError($e->getMessage());
             }
+
+            return $this->resolveArrays || !$v || !\is_array($v) ? $v : $value;
         }
+        if ($value instanceof Definition) {
+            $value->setBindings($this->processValue($value->getBindings()));
+            $changes = $value->getChanges();
+            if (isset($changes['class'])) {
+                $value->setClass($this->bag->resolveValue($value->getClass()));
+            }
+            if (isset($changes['file'])) {
+                $value->setFile($this->bag->resolveValue($value->getFile()));
+            }
+        }
+
+        $value = parent::processValue($value, $isRoot);
 
-        $aliases = array();
-        foreach ($container->getAliases() as $name => $target) {
-            $aliases[$parameterBag->resolveValue($name)] = $target;
+        if ($value && \is_array($value)) {
+            $value = array_combine($this->bag->resolveValue(array_keys($value)), $value);
         }
-        $container->setAliases($aliases);
 
-        $parameterBag->resolve();
+        return $value;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php
new file mode 100644
index 0000000000..1bd993458a
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ResolvePrivatesPass implements CompilerPassInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function process(ContainerBuilder $container)
+    {
+        foreach ($container->getDefinitions() as $id => $definition) {
+            if ($definition->isPrivate()) {
+                $definition->setPublic(false);
+                $definition->setPrivate(true);
+            }
+        }
+
+        foreach ($container->getAliases() as $id => $alias) {
+            if ($alias->isPrivate()) {
+                $alias->setPublic(false);
+                $alias->setPrivate(true);
+            }
+        }
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
index 8a11137517..2559dcf10c 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
@@ -11,7 +11,6 @@
 
 namespace Symfony\Component\DependencyInjection\Compiler;
 
-use Symfony\Component\DependencyInjection\Alias;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
 use Symfony\Component\DependencyInjection\Reference;
@@ -21,83 +20,37 @@ use Symfony\Component\DependencyInjection\Reference;
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class ResolveReferencesToAliasesPass implements CompilerPassInterface
+class ResolveReferencesToAliasesPass extends AbstractRecursivePass
 {
-    private $container;
-
     /**
-     * Processes the ContainerBuilder to replace references to aliases with actual service references.
+     * {@inheritdoc}
      */
     public function process(ContainerBuilder $container)
     {
-        $this->container = $container;
-
-        foreach ($container->getDefinitions() as $definition) {
-            if ($definition->isSynthetic() || $definition->isAbstract()) {
-                continue;
-            }
-
-            $definition->setArguments($this->processArguments($definition->getArguments()));
-            $definition->setMethodCalls($this->processArguments($definition->getMethodCalls()));
-            $definition->setProperties($this->processArguments($definition->getProperties()));
-            $definition->setFactory($this->processFactory($definition->getFactory()));
-            $definition->setFactoryService($this->processFactoryService($definition->getFactoryService(false)), false);
-        }
+        parent::process($container);
 
         foreach ($container->getAliases() as $id => $alias) {
-            $aliasId = (string) $alias;
-            if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) {
-                $container->setAlias($id, new Alias($defId, $alias->isPublic()));
+            $aliasId = $container->normalizeId($alias);
+            if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) {
+                $container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate());
             }
         }
     }
 
     /**
-     * Processes the arguments to replace aliases.
-     *
-     * @param array $arguments An array of References
-     *
-     * @return array An array of References
+     * {@inheritdoc}
      */
-    private function processArguments(array $arguments)
+    protected function processValue($value, $isRoot = false)
     {
-        foreach ($arguments as $k => $argument) {
-            if (\is_array($argument)) {
-                $arguments[$k] = $this->processArguments($argument);
-            } elseif ($argument instanceof Reference) {
-                $defId = $this->getDefinitionId($id = (string) $argument);
+        if ($value instanceof Reference) {
+            $defId = $this->getDefinitionId($id = $this->container->normalizeId($value), $this->container);
 
-                if ($defId !== $id) {
-                    $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior(), $argument->isStrict(false));
-                }
+            if ($defId !== $id) {
+                return new Reference($defId, $value->getInvalidBehavior());
             }
         }
 
-        return $arguments;
-    }
-
-    private function processFactoryService($factoryService)
-    {
-        if (null === $factoryService) {
-            return;
-        }
-
-        return $this->getDefinitionId($factoryService);
-    }
-
-    private function processFactory($factory)
-    {
-        if (null === $factory || !\is_array($factory) || !$factory[0] instanceof Reference) {
-            return $factory;
-        }
-
-        $defId = $this->getDefinitionId($id = (string) $factory[0]);
-
-        if ($defId !== $id) {
-            $factory[0] = new Reference($defId, $factory[0]->getInvalidBehavior(), $factory[0]->isStrict(false));
-        }
-
-        return $factory;
+        return parent::processValue($value);
     }
 
     /**
@@ -107,15 +60,15 @@ class ResolveReferencesToAliasesPass implements CompilerPassInterface
      *
      * @return string The definition id with aliases resolved
      */
-    private function getDefinitionId($id)
+    private function getDefinitionId($id, ContainerBuilder $container)
     {
-        $seen = array();
-        while ($this->container->hasAlias($id)) {
+        $seen = [];
+        while ($container->hasAlias($id)) {
             if (isset($seen[$id])) {
-                throw new ServiceCircularReferenceException($id, array_keys($seen));
+                throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), [$id]));
             }
             $seen[$id] = true;
-            $id = (string) $this->container->getAlias($id);
+            $id = $container->normalizeId($container->getAlias($id));
         }
 
         return $id;
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
new file mode 100644
index 0000000000..ccc80a443e
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Psr\Container\ContainerInterface;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Compiler pass to inject their service locator to service subscribers.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ResolveServiceSubscribersPass extends AbstractRecursivePass
+{
+    private $serviceLocator;
+
+    protected function processValue($value, $isRoot = false)
+    {
+        if ($value instanceof Reference && $this->serviceLocator && ContainerInterface::class === $this->container->normalizeId($value)) {
+            return new Reference($this->serviceLocator);
+        }
+
+        if (!$value instanceof Definition) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        $serviceLocator = $this->serviceLocator;
+        $this->serviceLocator = null;
+
+        if ($value->hasTag('container.service_subscriber.locator')) {
+            $this->serviceLocator = $value->getTag('container.service_subscriber.locator')[0]['id'];
+            $value->clearTag('container.service_subscriber.locator');
+        }
+
+        try {
+            return parent::processValue($value);
+        } finally {
+            $this->serviceLocator = $serviceLocator;
+        }
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
new file mode 100644
index 0000000000..009cee9bf5
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
+
+/**
+ * Resolves all TaggedIteratorArgument arguments.
+ *
+ * @author Roland Franssen <franssen.roland@gmail.com>
+ */
+class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass
+{
+    use PriorityTaggedServiceTrait;
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function processValue($value, $isRoot = false)
+    {
+        if (!$value instanceof TaggedIteratorArgument) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        $value->setValues($this->findAndSortTaggedServices($value->getTag(), $this->container));
+
+        return $value;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
new file mode 100644
index 0000000000..a7427c5a5b
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
@@ -0,0 +1,126 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+
+/**
+ * Applies the "container.service_locator" tag by wrapping references into ServiceClosureArgument instances.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+final class ServiceLocatorTagPass extends AbstractRecursivePass
+{
+    protected function processValue($value, $isRoot = false)
+    {
+        if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) {
+            return parent::processValue($value, $isRoot);
+        }
+
+        if (!$value->getClass()) {
+            $value->setClass(ServiceLocator::class);
+        }
+
+        $arguments = $value->getArguments();
+        if (!isset($arguments[0]) || !\is_array($arguments[0])) {
+            throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId));
+        }
+
+        $i = 0;
+
+        foreach ($arguments[0] as $k => $v) {
+            if ($v instanceof ServiceClosureArgument) {
+                continue;
+            }
+            if (!$v instanceof Reference) {
+                throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, \is_object($v) ? \get_class($v) : \gettype($v), $k));
+            }
+
+            if ($i === $k) {
+                unset($arguments[0][$k]);
+
+                $k = (string) $v;
+                ++$i;
+            } elseif (\is_int($k)) {
+                $i = null;
+            }
+            $arguments[0][$k] = new ServiceClosureArgument($v);
+        }
+        ksort($arguments[0]);
+
+        $value->setArguments($arguments);
+
+        $id = 'service_locator.'.ContainerBuilder::hash($value);
+
+        if ($isRoot) {
+            if ($id !== $this->currentId) {
+                $this->container->setAlias($id, new Alias($this->currentId, false));
+            }
+
+            return $value;
+        }
+
+        $this->container->setDefinition($id, $value->setPublic(false));
+
+        return new Reference($id);
+    }
+
+    /**
+     * @param Reference[] $refMap
+     * @param string|null $callerId
+     *
+     * @return Reference
+     */
+    public static function register(ContainerBuilder $container, array $refMap, $callerId = null)
+    {
+        foreach ($refMap as $id => $ref) {
+            if (!$ref instanceof Reference) {
+                throw new InvalidArgumentException(sprintf('Invalid service locator definition: only services can be referenced, "%s" found for key "%s". Inject parameter values using constructors instead.', \is_object($ref) ? \get_class($ref) : \gettype($ref), $id));
+            }
+            $refMap[$id] = new ServiceClosureArgument($ref);
+        }
+        ksort($refMap);
+
+        $locator = (new Definition(ServiceLocator::class))
+            ->addArgument($refMap)
+            ->setPublic(false)
+            ->addTag('container.service_locator');
+
+        if (null !== $callerId && $container->hasDefinition($callerId)) {
+            $locator->setBindings($container->getDefinition($callerId)->getBindings());
+        }
+
+        if (!$container->hasDefinition($id = 'service_locator.'.ContainerBuilder::hash($locator))) {
+            $container->setDefinition($id, $locator);
+        }
+
+        if (null !== $callerId) {
+            $locatorId = $id;
+            // Locators are shared when they hold the exact same list of factories;
+            // to have them specialized per consumer service, we use a cloning factory
+            // to derivate customized instances from the prototype one.
+            $container->register($id .= '.'.$callerId, ServiceLocator::class)
+                ->setPublic(false)
+                ->setFactory([new Reference($locatorId), 'withContext'])
+                ->addArgument($callerId)
+                ->addArgument(new Reference('service_container'));
+        }
+
+        return new Reference($id);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
index 43bac7120b..e419e297e8 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
@@ -20,13 +20,15 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  * it themselves which improves performance quite a lot.
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * @final since version 3.4
  */
 class ServiceReferenceGraph
 {
     /**
      * @var ServiceReferenceGraphNode[]
      */
-    private $nodes = array();
+    private $nodes = [];
 
     /**
      * Checks if the graph has a specific node.
@@ -73,7 +75,10 @@ class ServiceReferenceGraph
      */
     public function clear()
     {
-        $this->nodes = array();
+        foreach ($this->nodes as $node) {
+            $node->clear();
+        }
+        $this->nodes = [];
     }
 
     /**
@@ -85,14 +90,19 @@ class ServiceReferenceGraph
      * @param mixed  $destValue
      * @param string $reference
      */
-    public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null)
+    public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false, bool $weak = false, bool $byConstructor = false*/)
     {
+        $lazy = \func_num_args() >= 6 ? func_get_arg(5) : false;
+        $weak = \func_num_args() >= 7 ? func_get_arg(6) : false;
+        $byConstructor = \func_num_args() >= 8 ? func_get_arg(7) : false;
+
         if (null === $sourceId || null === $destId) {
             return;
         }
+
         $sourceNode = $this->createNode($sourceId, $sourceValue);
         $destNode = $this->createNode($destId, $destValue);
-        $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference);
+        $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak, $byConstructor);
 
         $sourceNode->addOutEdge($edge);
         $destNode->addInEdge($edge);
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
index 7e8cf812f7..911e7a5f5f 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
@@ -23,17 +23,24 @@ class ServiceReferenceGraphEdge
     private $sourceNode;
     private $destNode;
     private $value;
+    private $lazy;
+    private $weak;
+    private $byConstructor;
 
     /**
-     * @param ServiceReferenceGraphNode $sourceNode
-     * @param ServiceReferenceGraphNode $destNode
-     * @param mixed                     $value
+     * @param mixed $value
+     * @param bool  $lazy
+     * @param bool  $weak
+     * @param bool  $byConstructor
      */
-    public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null)
+    public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, $lazy = false, $weak = false, $byConstructor = false)
     {
         $this->sourceNode = $sourceNode;
         $this->destNode = $destNode;
         $this->value = $value;
+        $this->lazy = $lazy;
+        $this->weak = $weak;
+        $this->byConstructor = $byConstructor;
     }
 
     /**
@@ -65,4 +72,34 @@ class ServiceReferenceGraphEdge
     {
         return $this->destNode;
     }
+
+    /**
+     * Returns true if the edge is lazy, meaning it's a dependency not requiring direct instantiation.
+     *
+     * @return bool
+     */
+    public function isLazy()
+    {
+        return $this->lazy;
+    }
+
+    /**
+     * Returns true if the edge is weak, meaning it shouldn't prevent removing the target service.
+     *
+     * @return bool
+     */
+    public function isWeak()
+    {
+        return $this->weak;
+    }
+
+    /**
+     * Returns true if the edge links with a constructor argument.
+     *
+     * @return bool
+     */
+    public function isReferencedByConstructor()
+    {
+        return $this->byConstructor;
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
index 6a6d421390..50140b5fff 100644
--- a/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
+++ b/civicrm/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
@@ -24,8 +24,8 @@ use Symfony\Component\DependencyInjection\Definition;
 class ServiceReferenceGraphNode
 {
     private $id;
-    private $inEdges = array();
-    private $outEdges = array();
+    private $inEdges = [];
+    private $outEdges = [];
     private $value;
 
     /**
@@ -81,7 +81,7 @@ class ServiceReferenceGraphNode
     /**
      * Returns the in edges.
      *
-     * @return array The in ServiceReferenceGraphEdge array
+     * @return ServiceReferenceGraphEdge[]
      */
     public function getInEdges()
     {
@@ -91,7 +91,7 @@ class ServiceReferenceGraphNode
     /**
      * Returns the out edges.
      *
-     * @return array The out ServiceReferenceGraphEdge array
+     * @return ServiceReferenceGraphEdge[]
      */
     public function getOutEdges()
     {
@@ -107,4 +107,12 @@ class ServiceReferenceGraphNode
     {
         return $this->value;
     }
+
+    /**
+     * Clears all edges.
+     */
+    public function clear()
+    {
+        $this->inEdges = $this->outEdges = [];
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Config/AutowireServiceResource.php b/civicrm/vendor/symfony/dependency-injection/Config/AutowireServiceResource.php
new file mode 100644
index 0000000000..0c3d8f5758
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Config/AutowireServiceResource.php
@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Config;
+
+@trigger_error('The '.__NAMESPACE__.'\AutowireServiceResource class is deprecated since Symfony 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', E_USER_DEPRECATED);
+
+use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;
+use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
+
+/**
+ * @deprecated since version 3.3, to be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.
+ */
+class AutowireServiceResource implements SelfCheckingResourceInterface, \Serializable
+{
+    private $class;
+    private $filePath;
+    private $autowiringMetadata = [];
+
+    public function __construct($class, $path, array $autowiringMetadata)
+    {
+        $this->class = $class;
+        $this->filePath = $path;
+        $this->autowiringMetadata = $autowiringMetadata;
+    }
+
+    public function isFresh($timestamp)
+    {
+        if (!file_exists($this->filePath)) {
+            return false;
+        }
+
+        // has the file *not* been modified? Definitely fresh
+        if (@filemtime($this->filePath) <= $timestamp) {
+            return true;
+        }
+
+        try {
+            $reflectionClass = new \ReflectionClass($this->class);
+        } catch (\ReflectionException $e) {
+            // the class does not exist anymore!
+            return false;
+        }
+
+        return (array) $this === (array) AutowirePass::createResourceForClass($reflectionClass);
+    }
+
+    public function __toString()
+    {
+        return 'service.autowire.'.$this->class;
+    }
+
+    /**
+     * @internal
+     */
+    public function serialize()
+    {
+        return serialize([$this->class, $this->filePath, $this->autowiringMetadata]);
+    }
+
+    /**
+     * @internal
+     */
+    public function unserialize($serialized)
+    {
+        if (\PHP_VERSION_ID >= 70000) {
+            list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized, ['allowed_classes' => false]);
+        } else {
+            list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized);
+        }
+    }
+
+    /**
+     * @deprecated Implemented for compatibility with Symfony 2.8
+     */
+    public function getResource()
+    {
+        return $this->filePath;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php b/civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php
new file mode 100644
index 0000000000..7560c3356d
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Config;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+
+/**
+ * Tracks container parameters.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+class ContainerParametersResource implements ResourceInterface, \Serializable
+{
+    private $parameters;
+
+    /**
+     * @param array $parameters The container parameters to track
+     */
+    public function __construct(array $parameters)
+    {
+        $this->parameters = $parameters;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function __toString()
+    {
+        return 'container_parameters_'.md5(serialize($this->parameters));
+    }
+
+    /**
+     * @internal
+     */
+    public function serialize()
+    {
+        return serialize($this->parameters);
+    }
+
+    /**
+     * @internal
+     */
+    public function unserialize($serialized)
+    {
+        $this->parameters = unserialize($serialized);
+    }
+
+    /**
+     * @return array Tracked parameters
+     */
+    public function getParameters()
+    {
+        return $this->parameters;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php b/civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php
new file mode 100644
index 0000000000..6ed77e3fd2
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php
@@ -0,0 +1,52 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Config;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+use Symfony\Component\Config\ResourceCheckerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+class ContainerParametersResourceChecker implements ResourceCheckerInterface
+{
+    /** @var ContainerInterface */
+    private $container;
+
+    public function __construct(ContainerInterface $container)
+    {
+        $this->container = $container;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function supports(ResourceInterface $metadata)
+    {
+        return $metadata instanceof ContainerParametersResource;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isFresh(ResourceInterface $resource, $timestamp)
+    {
+        foreach ($resource->getParameters() as $key => $value) {
+            if (!$this->container->hasParameter($key) || $this->container->getParameter($key) !== $value) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Container.php b/civicrm/vendor/symfony/dependency-injection/Container.php
index 25532ead23..b9f44b0bf9 100644
--- a/civicrm/vendor/symfony/dependency-injection/Container.php
+++ b/civicrm/vendor/symfony/dependency-injection/Container.php
@@ -11,59 +11,61 @@
 
 namespace Symfony\Component\DependencyInjection;
 
-use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
+use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
-use Symfony\Component\DependencyInjection\Exception\LogicException;
-use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
 use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
-use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
 
 /**
  * Container is a dependency injection container.
  *
  * It gives access to object instances (services).
- *
  * Services and parameters are simple key/pair stores.
- *
- * Parameter and service keys are case insensitive.
- *
- * A service can also be defined by creating a method named
- * getXXXService(), where XXX is the camelized version of the id:
- *
- *  * request -> getRequestService()
- *  * mysql_session_storage -> getMysqlSessionStorageService()
- *  * symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()
- *
- * The container can have three possible behaviors when a service does not exist:
+ * The container can have four possible behaviors when a service
+ * does not exist (or is not initialized for the last case):
  *
  *  * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
  *  * NULL_ON_INVALID_REFERENCE:      Returns null
  *  * IGNORE_ON_INVALID_REFERENCE:    Ignores the wrapping command asking for the reference
  *                                    (for instance, ignore a setter if the service does not exist)
+ *  * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references
  *
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class Container implements IntrospectableContainerInterface, ResettableContainerInterface
+class Container implements ResettableContainerInterface
 {
     protected $parameterBag;
-    protected $services = array();
-    protected $methodMap = array();
-    protected $aliases = array();
-    protected $scopes = array();
-    protected $scopeChildren = array();
-    protected $scopedServices = array();
-    protected $scopeStacks = array();
-    protected $loading = array();
+    protected $services = [];
+    protected $fileMap = [];
+    protected $methodMap = [];
+    protected $aliases = [];
+    protected $loading = [];
+    protected $resolving = [];
+    protected $syntheticIds = [];
+
+    /**
+     * @internal
+     */
+    protected $privates = [];
+
+    /**
+     * @internal
+     */
+    protected $normalizedIds = [];
 
-    private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_');
+    private $underscoreMap = ['_' => '', '.' => '_', '\\' => '_'];
+    private $envCache = [];
+    private $compiled = false;
+    private $getEnv;
 
     public function __construct(ParameterBagInterface $parameterBag = null)
     {
-        $this->parameterBag = $parameterBag ?: new ParameterBag();
+        $this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag();
     }
 
     /**
@@ -79,15 +81,31 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
         $this->parameterBag->resolve();
 
         $this->parameterBag = new FrozenParameterBag($this->parameterBag->all());
+
+        $this->compiled = true;
+    }
+
+    /**
+     * Returns true if the container is compiled.
+     *
+     * @return bool
+     */
+    public function isCompiled()
+    {
+        return $this->compiled;
     }
 
     /**
      * Returns true if the container parameter bag are frozen.
      *
+     * @deprecated since version 3.3, to be removed in 4.0.
+     *
      * @return bool true if the container parameter bag are frozen, false otherwise
      */
     public function isFrozen()
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
+
         return $this->parameterBag instanceof FrozenParameterBag;
     }
 
@@ -141,61 +159,55 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
     /**
      * Sets a service.
      *
-     * Setting a service to null resets the service: has() returns false and get()
+     * Setting a synthetic service to null resets it: has() returns false and get()
      * behaves in the same way as if the service was never created.
      *
-     * Note: The $scope parameter is deprecated since version 2.8 and will be removed in 3.0.
-     *
-     * @param string $id      The service identifier
-     * @param object $service The service instance
-     * @param string $scope   The scope of the service
-     *
-     * @throws RuntimeException         When trying to set a service in an inactive scope
-     * @throws InvalidArgumentException When trying to set a service in the prototype scope
+     * @param string      $id      The service identifier
+     * @param object|null $service The service instance
      */
-    public function set($id, $service, $scope = self::SCOPE_CONTAINER)
+    public function set($id, $service)
     {
-        if (!\in_array($scope, array('container', 'request')) || ('request' === $scope && 'request' !== $id)) {
-            @trigger_error('The concept of container scopes is deprecated since Symfony 2.8 and will be removed in 3.0. Omit the third parameter.', E_USER_DEPRECATED);
-        }
-
-        if (self::SCOPE_PROTOTYPE === $scope) {
-            throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id));
+        // Runs the internal initializer; used by the dumped container to include always-needed files
+        if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) {
+            $initialize = $this->privates['service_container'];
+            unset($this->privates['service_container']);
+            $initialize();
         }
 
-        $id = strtolower($id);
+        $id = $this->normalizeId($id);
 
         if ('service_container' === $id) {
-            // BC: 'service_container' is no longer a self-reference but always
-            // $this, so ignore this call.
-            // @todo Throw InvalidArgumentException in next major release.
-            return;
+            throw new InvalidArgumentException('You cannot set service "service_container".');
         }
-        if (self::SCOPE_CONTAINER !== $scope) {
-            if (!isset($this->scopedServices[$scope])) {
-                throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id));
-            }
 
-            $this->scopedServices[$scope][$id] = $service;
+        if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
+            if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) {
+                // no-op
+            } elseif (null === $service) {
+                @trigger_error(sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED);
+                unset($this->privates[$id]);
+            } else {
+                @trigger_error(sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED);
+            }
+        } elseif (isset($this->services[$id])) {
+            if (null === $service) {
+                @trigger_error(sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED);
+            } else {
+                @trigger_error(sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED);
+            }
         }
 
         if (isset($this->aliases[$id])) {
             unset($this->aliases[$id]);
         }
 
-        $this->services[$id] = $service;
-
-        if (method_exists($this, $method = 'synchronize'.strtr($id, $this->underscoreMap).'Service')) {
-            $this->$method();
-        }
-
         if (null === $service) {
-            if (self::SCOPE_CONTAINER !== $scope) {
-                unset($this->scopedServices[$scope][$id]);
-            }
-
             unset($this->services[$id]);
+
+            return;
         }
+
+        $this->services[$id] = $service;
     }
 
     /**
@@ -208,18 +220,37 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
     public function has($id)
     {
         for ($i = 2;;) {
-            if ('service_container' === $id
-                || isset($this->aliases[$id])
-                || isset($this->services[$id])
-                || array_key_exists($id, $this->services)
-            ) {
+            if (isset($this->privates[$id])) {
+                @trigger_error(sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED);
+            }
+            if (isset($this->aliases[$id])) {
+                $id = $this->aliases[$id];
+            }
+            if (isset($this->services[$id])) {
                 return true;
             }
-            if (--$i && $id !== $lcId = strtolower($id)) {
-                $id = $lcId;
-            } else {
-                return method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service');
+            if ('service_container' === $id) {
+                return true;
             }
+
+            if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
+                return true;
+            }
+
+            if (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
+                $id = $normalizedId;
+                continue;
+            }
+
+            // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
+            // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
+            if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service')) {
+                @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED);
+
+                return true;
+            }
+
+            return false;
         }
     }
 
@@ -232,7 +263,7 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
      * @param string $id              The service identifier
      * @param int    $invalidBehavior The behavior when the service does not exist
      *
-     * @return object The associated service
+     * @return object|null The associated service
      *
      * @throws ServiceCircularReferenceException When a circular reference is detected
      * @throws ServiceNotFoundException          When the service is not defined
@@ -240,18 +271,22 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
      *
      * @see Reference
      */
-    public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
+    public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1)
     {
         // Attempt to retrieve the service by checking first aliases then
         // available services. Service IDs are case insensitive, however since
         // this method can be called thousands of times during a request, avoid
-        // calling strtolower() unless necessary.
+        // calling $this->normalizeId($id) unless necessary.
         for ($i = 2;;) {
+            if (isset($this->privates[$id])) {
+                @trigger_error(sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.', $id), E_USER_DEPRECATED);
+            }
             if (isset($this->aliases[$id])) {
                 $id = $this->aliases[$id];
             }
+
             // Re-use shared service instance if it exists.
-            if (isset($this->services[$id]) || array_key_exists($id, $this->services)) {
+            if (isset($this->services[$id])) {
                 return $this->services[$id];
             }
             if ('service_container' === $id) {
@@ -259,59 +294,58 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
             }
 
             if (isset($this->loading[$id])) {
-                throw new ServiceCircularReferenceException($id, array_keys($this->loading));
-            }
-
-            if (isset($this->methodMap[$id])) {
-                $method = $this->methodMap[$id];
-            } elseif (--$i && $id !== $lcId = strtolower($id)) {
-                $id = $lcId;
-                continue;
-            } elseif (method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) {
-                // $method is set to the right value, proceed
-            } else {
-                if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
-                    if (!$id) {
-                        throw new ServiceNotFoundException($id);
-                    }
-
-                    $alternatives = array();
-                    foreach ($this->getServiceIds() as $knownId) {
-                        $lev = levenshtein($id, $knownId);
-                        if ($lev <= \strlen($id) / 3 || false !== strpos($knownId, $id)) {
-                            $alternatives[] = $knownId;
-                        }
-                    }
-
-                    throw new ServiceNotFoundException($id, null, null, $alternatives);
-                }
-
-                return;
+                throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), [$id]));
             }
 
             $this->loading[$id] = true;
 
             try {
-                $service = $this->$method();
+                if (isset($this->fileMap[$id])) {
+                    return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]);
+                } elseif (isset($this->methodMap[$id])) {
+                    return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}();
+                } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
+                    unset($this->loading[$id]);
+                    $id = $normalizedId;
+                    continue;
+                } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) {
+                    // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
+                    // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
+                    @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED);
+
+                    return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$method}();
+                }
+
+                break;
             } catch (\Exception $e) {
-                unset($this->loading[$id]);
                 unset($this->services[$id]);
 
-                if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
-                    return;
-                }
-
                 throw $e;
-            } catch (\Throwable $e) {
+            } finally {
                 unset($this->loading[$id]);
-                unset($this->services[$id]);
+            }
+        }
 
-                throw $e;
+        if (/* self::EXCEPTION_ON_INVALID_REFERENCE */ 1 === $invalidBehavior) {
+            if (!$id) {
+                throw new ServiceNotFoundException($id);
+            }
+            if (isset($this->syntheticIds[$id])) {
+                throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id));
+            }
+            if (isset($this->getRemovedIds()[$id])) {
+                throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id));
             }
 
-            unset($this->loading[$id]);
+            $alternatives = [];
+            foreach ($this->getServiceIds() as $knownId) {
+                $lev = levenshtein($id, $knownId);
+                if ($lev <= \strlen($id) / 3 || false !== strpos($knownId, $id)) {
+                    $alternatives[] = $knownId;
+                }
+            }
 
-            return $service;
+            throw new ServiceNotFoundException($id, null, null, $alternatives);
         }
     }
 
@@ -324,19 +358,21 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
      */
     public function initialized($id)
     {
-        $id = strtolower($id);
+        $id = $this->normalizeId($id);
+
+        if (isset($this->privates[$id])) {
+            @trigger_error(sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
+        }
 
         if (isset($this->aliases[$id])) {
             $id = $this->aliases[$id];
         }
 
         if ('service_container' === $id) {
-            // BC: 'service_container' was a synthetic service previously.
-            // @todo Change to false in next major release.
-            return true;
+            return false;
         }
 
-        return isset($this->services[$id]) || array_key_exists($id, $this->services);
+        return isset($this->services[$id]);
     }
 
     /**
@@ -344,228 +380,144 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
      */
     public function reset()
     {
-        if (!empty($this->scopedServices)) {
-            throw new LogicException('Resetting the container is not allowed when a scope is active.');
-        }
-
-        $this->services = array();
+        $this->services = [];
     }
 
     /**
      * Gets all service ids.
      *
-     * @return array An array of all defined service ids
+     * @return string[] An array of all defined service ids
      */
     public function getServiceIds()
     {
-        $ids = array();
-        foreach (get_class_methods($this) as $method) {
-            if (preg_match('/^get(.+)Service$/', $method, $match)) {
-                $ids[] = self::underscore($match[1]);
+        $ids = [];
+
+        if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class) {
+            // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
+            // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
+            @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED);
+
+            foreach (get_class_methods($this) as $method) {
+                if (preg_match('/^get(.+)Service$/', $method, $match)) {
+                    $ids[] = self::underscore($match[1]);
+                }
             }
         }
         $ids[] = 'service_container';
 
-        return array_unique(array_merge($ids, array_keys($this->services)));
+        return array_map('strval', array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->aliases), array_keys($this->services))));
     }
 
     /**
-     * This is called when you enter a scope.
-     *
-     * @param string $name
-     *
-     * @throws RuntimeException         When the parent scope is inactive
-     * @throws InvalidArgumentException When the scope does not exist
+     * Gets service ids that existed at compile time.
      *
-     * @deprecated since version 2.8, to be removed in 3.0.
+     * @return array
      */
-    public function enterScope($name)
+    public function getRemovedIds()
     {
-        if ('request' !== $name) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        if (!isset($this->scopes[$name])) {
-            throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name));
-        }
-
-        if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) {
-            throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name]));
-        }
-
-        // check if a scope of this name is already active, if so we need to
-        // remove all services of this scope, and those of any of its child
-        // scopes from the global services map
-        if (isset($this->scopedServices[$name])) {
-            $services = array($this->services, $name => $this->scopedServices[$name]);
-            unset($this->scopedServices[$name]);
-
-            foreach ($this->scopeChildren[$name] as $child) {
-                if (isset($this->scopedServices[$child])) {
-                    $services[$child] = $this->scopedServices[$child];
-                    unset($this->scopedServices[$child]);
-                }
-            }
-
-            // update global map
-            $this->services = \call_user_func_array('array_diff_key', $services);
-            array_shift($services);
-
-            // add stack entry for this scope so we can restore the removed services later
-            if (!isset($this->scopeStacks[$name])) {
-                $this->scopeStacks[$name] = new \SplStack();
-            }
-            $this->scopeStacks[$name]->push($services);
-        }
-
-        $this->scopedServices[$name] = array();
+        return [];
     }
 
     /**
-     * This is called to leave the current scope, and move back to the parent
-     * scope.
-     *
-     * @param string $name The name of the scope to leave
+     * Camelizes a string.
      *
-     * @throws InvalidArgumentException if the scope is not active
+     * @param string $id A string to camelize
      *
-     * @deprecated since version 2.8, to be removed in 3.0.
+     * @return string The camelized string
      */
-    public function leaveScope($name)
+    public static function camelize($id)
     {
-        if ('request' !== $name) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        if (!isset($this->scopedServices[$name])) {
-            throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name));
-        }
-
-        // remove all services of this scope, or any of its child scopes from
-        // the global service map
-        $services = array($this->services, $this->scopedServices[$name]);
-        unset($this->scopedServices[$name]);
-
-        foreach ($this->scopeChildren[$name] as $child) {
-            if (isset($this->scopedServices[$child])) {
-                $services[] = $this->scopedServices[$child];
-                unset($this->scopedServices[$child]);
-            }
-        }
-
-        // update global map
-        $this->services = \call_user_func_array('array_diff_key', $services);
-
-        // check if we need to restore services of a previous scope of this type
-        if (isset($this->scopeStacks[$name]) && \count($this->scopeStacks[$name]) > 0) {
-            $services = $this->scopeStacks[$name]->pop();
-            $this->scopedServices += $services;
-
-            if ($this->scopeStacks[$name]->isEmpty()) {
-                unset($this->scopeStacks[$name]);
-            }
-
-            foreach ($services as $array) {
-                foreach ($array as $id => $service) {
-                    $this->set($id, $service, $name);
-                }
-            }
-        }
+        return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']);
     }
 
     /**
-     * Adds a scope to the container.
+     * A string to underscore.
      *
-     * @throws InvalidArgumentException
+     * @param string $id The string to underscore
      *
-     * @deprecated since version 2.8, to be removed in 3.0.
+     * @return string The underscored string
      */
-    public function addScope(ScopeInterface $scope)
+    public static function underscore($id)
     {
-        $name = $scope->getName();
-        $parentScope = $scope->getParentName();
-
-        if ('request' !== $name) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-        if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) {
-            throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name));
-        }
-        if (isset($this->scopes[$name])) {
-            throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name));
-        }
-        if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) {
-            throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope));
-        }
-
-        $this->scopes[$name] = $parentScope;
-        $this->scopeChildren[$name] = array();
-
-        // normalize the child relations
-        while (self::SCOPE_CONTAINER !== $parentScope) {
-            $this->scopeChildren[$parentScope][] = $name;
-            $parentScope = $this->scopes[$parentScope];
-        }
+        return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], str_replace('_', '.', $id)));
     }
 
     /**
-     * Returns whether this container has a certain scope.
-     *
-     * @param string $name The name of the scope
-     *
-     * @return bool
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
+     * Creates a service by requiring its factory file.
      */
-    public function hasScope($name)
+    protected function load($file)
     {
-        if ('request' !== $name) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return isset($this->scopes[$name]);
+        return require $file;
     }
 
     /**
-     * Returns whether this scope is currently active.
-     *
-     * This does not actually check if the passed scope actually exists.
+     * Fetches a variable from the environment.
      *
-     * @param string $name
+     * @param string $name The name of the environment variable
      *
-     * @return bool
+     * @return mixed The value to use for the provided environment variable name
      *
-     * @deprecated since version 2.8, to be removed in 3.0.
+     * @throws EnvNotFoundException When the environment variable is not found and has no default value
      */
-    public function isScopeActive($name)
+    protected function getEnv($name)
     {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
+        if (isset($this->resolving[$envName = "env($name)"])) {
+            throw new ParameterCircularReferenceException(array_keys($this->resolving));
+        }
+        if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) {
+            return $this->envCache[$name];
+        }
+        if (!$this->has($id = 'container.env_var_processors_locator')) {
+            $this->set($id, new ServiceLocator([]));
+        }
+        if (!$this->getEnv) {
+            $this->getEnv = new \ReflectionMethod($this, __FUNCTION__);
+            $this->getEnv->setAccessible(true);
+            $this->getEnv = $this->getEnv->getClosure($this);
+        }
+        $processors = $this->get($id);
+
+        if (false !== $i = strpos($name, ':')) {
+            $prefix = substr($name, 0, $i);
+            $localName = substr($name, 1 + $i);
+        } else {
+            $prefix = 'string';
+            $localName = $name;
+        }
+        $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this);
 
-        return isset($this->scopedServices[$name]);
+        $this->resolving[$envName] = true;
+        try {
+            return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv);
+        } finally {
+            unset($this->resolving[$envName]);
+        }
     }
 
     /**
-     * Camelizes a string.
-     *
-     * @param string $id A string to camelize
+     * Returns the case sensitive id used at registration time.
      *
-     * @return string The camelized string
-     */
-    public static function camelize($id)
-    {
-        return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => ''));
-    }
-
-    /**
-     * A string to underscore.
+     * @param string $id
      *
-     * @param string $id The string to underscore
+     * @return string
      *
-     * @return string The underscored string
+     * @internal
      */
-    public static function underscore($id)
+    public function normalizeId($id)
     {
-        return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id)));
+        if (!\is_string($id)) {
+            $id = (string) $id;
+        }
+        if (isset($this->normalizedIds[$normalizedId = strtolower($id)])) {
+            $normalizedId = $this->normalizedIds[$normalizedId];
+            if ($id !== $normalizedId) {
+                @trigger_error(sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.3.', $id, $normalizedId), E_USER_DEPRECATED);
+            }
+        } else {
+            $normalizedId = $this->normalizedIds[$normalizedId] = $id;
+        }
+
+        return $normalizedId;
     }
 
     private function __clone()
diff --git a/civicrm/vendor/symfony/dependency-injection/ContainerAware.php b/civicrm/vendor/symfony/dependency-injection/ContainerAware.php
deleted file mode 100644
index f3f2a5065c..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/ContainerAware.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection;
-
-/**
- * A simple implementation of ContainerAwareInterface.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- *
- * @deprecated since version 2.8, to be removed in 3.0. Use the ContainerAwareTrait instead.
- */
-abstract class ContainerAware implements ContainerAwareInterface
-{
-    /**
-     * @var ContainerInterface
-     */
-    protected $container;
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setContainer(ContainerInterface $container = null)
-    {
-        $this->container = $container;
-    }
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/ContainerBuilder.php b/civicrm/vendor/symfony/dependency-injection/ContainerBuilder.php
index 0e1391f9f8..7c9860b4dc 100644
--- a/civicrm/vendor/symfony/dependency-injection/ContainerBuilder.php
+++ b/civicrm/vendor/symfony/dependency-injection/ContainerBuilder.php
@@ -11,13 +11,23 @@
 
 namespace Symfony\Component\DependencyInjection;
 
+use Psr\Container\ContainerInterface as PsrContainerInterface;
+use Symfony\Component\Config\Resource\ClassExistenceResource;
+use Symfony\Component\Config\Resource\ComposerResource;
+use Symfony\Component\Config\Resource\DirectoryResource;
+use Symfony\Component\Config\Resource\FileExistenceResource;
 use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Resource\GlobResource;
+use Symfony\Component\Config\Resource\ReflectionClassResource;
 use Symfony\Component\Config\Resource\ResourceInterface;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
 use Symfony\Component\DependencyInjection\Compiler\Compiler;
 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
 use Symfony\Component\DependencyInjection\Compiler\PassConfig;
+use Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass;
 use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
-use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 use Symfony\Component\DependencyInjection\Exception\LogicException;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -26,7 +36,10 @@ use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
 use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
 use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
+use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
+use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
 use Symfony\Component\ExpressionLanguage\Expression;
 use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
 
@@ -40,34 +53,29 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
     /**
      * @var ExtensionInterface[]
      */
-    private $extensions = array();
+    private $extensions = [];
 
     /**
      * @var ExtensionInterface[]
      */
-    private $extensionsByNs = array();
+    private $extensionsByNs = [];
 
     /**
      * @var Definition[]
      */
-    private $definitions = array();
-
-    /**
-     * @var Definition[]
-     */
-    private $obsoleteDefinitions = array();
+    private $definitions = [];
 
     /**
      * @var Alias[]
      */
-    private $aliasDefinitions = array();
+    private $aliasDefinitions = [];
 
     /**
      * @var ResourceInterface[]
      */
-    private $resources = array();
+    private $resources = [];
 
-    private $extensionConfigs = array();
+    private $extensionConfigs = [];
 
     /**
      * @var Compiler
@@ -89,19 +97,62 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
     /**
      * @var ExpressionFunctionProviderInterface[]
      */
-    private $expressionLanguageProviders = array();
+    private $expressionLanguageProviders = [];
+
+    /**
+     * @var string[] with tag names used by findTaggedServiceIds
+     */
+    private $usedTags = [];
+
+    /**
+     * @var string[][] a map of env var names to their placeholders
+     */
+    private $envPlaceholders = [];
+
+    /**
+     * @var int[] a map of env vars to their resolution counter
+     */
+    private $envCounters = [];
+
+    /**
+     * @var string[] the list of vendor directories
+     */
+    private $vendors;
+
+    private $autoconfiguredInstanceof = [];
+
+    private $removedIds = [];
+
+    private $removedBindingIds = [];
+
+    private static $internalTypes = [
+        'int' => true,
+        'float' => true,
+        'string' => true,
+        'bool' => true,
+        'resource' => true,
+        'object' => true,
+        'array' => true,
+        'null' => true,
+        'callable' => true,
+        'iterable' => true,
+        'mixed' => true,
+    ];
 
     public function __construct(ParameterBagInterface $parameterBag = null)
     {
         parent::__construct($parameterBag);
 
         $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface');
+        $this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(true)->setPublic(true));
+        $this->setAlias(PsrContainerInterface::class, new Alias('service_container', false));
+        $this->setAlias(ContainerInterface::class, new Alias('service_container', false));
     }
 
     /**
-     * @var string[] with tag names used by findTaggedServiceIds
+     * @var \ReflectionClass[] a list of class reflectors
      */
-    private $usedTags = array();
+    private $classReflectors;
 
     /**
      * Sets the track resources flag.
@@ -162,7 +213,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
             return $this->extensionsByNs[$name];
         }
 
-        throw new LogicException(sprintf('Container extension "%s" is not registered', $name));
+        throw new LogicException(sprintf('Container extension "%s" is not registered.', $name));
     }
 
     /**
@@ -194,7 +245,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function getResources()
     {
-        return array_unique($this->resources);
+        return array_values($this->resources);
     }
 
     /**
@@ -206,7 +257,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
             return $this;
         }
 
-        $this->resources[] = $resource;
+        if ($resource instanceof GlobResource && $this->inVendors($resource->getPrefix())) {
+            return $this;
+        }
+
+        $this->resources[(string) $resource] = $resource;
 
         return $this;
     }
@@ -232,14 +287,39 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
     /**
      * Adds the object class hierarchy as resources.
      *
-     * @param object $object An object instance
+     * @param object|string $object An object instance or class name
      *
      * @return $this
      */
     public function addObjectResource($object)
     {
         if ($this->trackResources) {
-            $this->addClassResource(new \ReflectionClass($object));
+            if (\is_object($object)) {
+                $object = \get_class($object);
+            }
+            if (!isset($this->classReflectors[$object])) {
+                $this->classReflectors[$object] = new \ReflectionClass($object);
+            }
+            $class = $this->classReflectors[$object];
+
+            foreach ($class->getInterfaceNames() as $name) {
+                if (null === $interface = &$this->classReflectors[$name]) {
+                    $interface = new \ReflectionClass($name);
+                }
+                $file = $interface->getFileName();
+                if (false !== $file && file_exists($file)) {
+                    $this->fileExists($file);
+                }
+            }
+            do {
+                $file = $class->getFileName();
+                if (false !== $file && file_exists($file)) {
+                    $this->fileExists($file);
+                }
+                foreach ($class->getTraitNames() as $name) {
+                    $this->addObjectResource($name);
+                }
+            } while ($class = $class->getParentClass());
         }
 
         return $this;
@@ -249,20 +329,107 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      * Adds the given class hierarchy as resources.
      *
      * @return $this
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Use addObjectResource() or getReflectionClass() instead.
      */
     public function addClassResource(\ReflectionClass $class)
     {
-        if (!$this->trackResources) {
-            return $this;
+        @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the addObjectResource() or the getReflectionClass() method instead.', E_USER_DEPRECATED);
+
+        return $this->addObjectResource($class->name);
+    }
+
+    /**
+     * Retrieves the requested reflection class and registers it for resource tracking.
+     *
+     * @param string $class
+     * @param bool   $throw
+     *
+     * @return \ReflectionClass|null
+     *
+     * @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true
+     *
+     * @final
+     */
+    public function getReflectionClass($class, $throw = true)
+    {
+        if (!$class = $this->getParameterBag()->resolveValue($class)) {
+            return null;
+        }
+
+        if (isset(self::$internalTypes[$class])) {
+            return null;
         }
 
-        do {
-            if (is_file($class->getFileName())) {
-                $this->addResource(new FileResource($class->getFileName()));
+        $resource = $classReflector = null;
+
+        try {
+            if (isset($this->classReflectors[$class])) {
+                $classReflector = $this->classReflectors[$class];
+            } elseif (class_exists(ClassExistenceResource::class)) {
+                $resource = new ClassExistenceResource($class, false);
+                $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class);
+            } else {
+                $classReflector = class_exists($class) ? new \ReflectionClass($class) : false;
             }
-        } while ($class = $class->getParentClass());
+        } catch (\ReflectionException $e) {
+            if ($throw) {
+                throw $e;
+            }
+        }
 
-        return $this;
+        if ($this->trackResources) {
+            if (!$classReflector) {
+                $this->addResource($resource ?: new ClassExistenceResource($class, false));
+            } elseif (!$classReflector->isInternal()) {
+                $path = $classReflector->getFileName();
+
+                if (!$this->inVendors($path)) {
+                    $this->addResource(new ReflectionClassResource($classReflector, $this->vendors));
+                }
+            }
+            $this->classReflectors[$class] = $classReflector;
+        }
+
+        return $classReflector ?: null;
+    }
+
+    /**
+     * Checks whether the requested file or directory exists and registers the result for resource tracking.
+     *
+     * @param string      $path          The file or directory path for which to check the existence
+     * @param bool|string $trackContents Whether to track contents of the given resource. If a string is passed,
+     *                                   it will be used as pattern for tracking contents of the requested directory
+     *
+     * @return bool
+     *
+     * @final
+     */
+    public function fileExists($path, $trackContents = true)
+    {
+        $exists = file_exists($path);
+
+        if (!$this->trackResources || $this->inVendors($path)) {
+            return $exists;
+        }
+
+        if (!$exists) {
+            $this->addResource(new FileExistenceResource($path));
+
+            return $exists;
+        }
+
+        if (is_dir($path)) {
+            if ($trackContents) {
+                $this->addResource(new DirectoryResource($path, \is_string($trackContents) ? $trackContents : null));
+            } else {
+                $this->addResource(new GlobResource($path, '/*', false));
+            }
+        } elseif ($trackContents) {
+            $this->addResource(new FileResource($path));
+        }
+
+        return $exists;
     }
 
     /**
@@ -273,17 +440,17 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      *
      * @return $this
      *
-     * @throws BadMethodCallException When this ContainerBuilder is frozen
-     * @throws \LogicException        if the container is frozen
+     * @throws BadMethodCallException When this ContainerBuilder is compiled
+     * @throws \LogicException        if the extension is not registered
      */
     public function loadFromExtension($extension, array $values = null)
     {
-        if ($this->isFrozen()) {
-            throw new BadMethodCallException('Cannot load from an extension on a frozen container.');
+        if ($this->isCompiled()) {
+            throw new BadMethodCallException('Cannot load from an extension on a compiled container.');
         }
 
         if (\func_num_args() < 2) {
-            $values = array();
+            $values = [];
         }
 
         $namespace = $this->getExtension($extension)->getAlias();
@@ -296,14 +463,28 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
     /**
      * Adds a compiler pass.
      *
-     * @param CompilerPassInterface $pass A compiler pass
-     * @param string                $type The type of compiler pass
+     * @param CompilerPassInterface $pass     A compiler pass
+     * @param string                $type     The type of compiler pass
+     * @param int                   $priority Used to sort the passes
      *
      * @return $this
      */
-    public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
+    public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
     {
-        $this->getCompiler()->addPass($pass, $type);
+        if (\func_num_args() >= 3) {
+            $priority = func_get_arg(2);
+        } else {
+            if (__CLASS__ !== static::class) {
+                $r = new \ReflectionMethod($this, __FUNCTION__);
+                if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
+                    @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED);
+                }
+            }
+
+            $priority = 0;
+        }
+
+        $this->getCompiler()->addPass($pass, $type, $priority);
 
         $this->addObjectResource($pass);
 
@@ -334,70 +515,26 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
         return $this->compiler;
     }
 
-    /**
-     * Returns all Scopes.
-     *
-     * @return array An array of scopes
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function getScopes($triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return $this->scopes;
-    }
-
-    /**
-     * Returns all Scope children.
-     *
-     * @return array An array of scope children
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function getScopeChildren($triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return $this->scopeChildren;
-    }
-
     /**
      * Sets a service.
      *
-     * Note: The $scope parameter is deprecated since version 2.8 and will be removed in 3.0.
-     *
-     * @param string $id      The service identifier
-     * @param object $service The service instance
-     * @param string $scope   The scope
+     * @param string      $id      The service identifier
+     * @param object|null $service The service instance
      *
-     * @throws BadMethodCallException When this ContainerBuilder is frozen
+     * @throws BadMethodCallException When this ContainerBuilder is compiled
      */
-    public function set($id, $service, $scope = self::SCOPE_CONTAINER)
+    public function set($id, $service)
     {
-        $id = strtolower($id);
-        $set = isset($this->definitions[$id]);
-
-        if ($this->isFrozen() && ($set || isset($this->obsoleteDefinitions[$id])) && !$this->{$set ? 'definitions' : 'obsoleteDefinitions'}[$id]->isSynthetic()) {
-            // setting a synthetic service on a frozen container is alright
-            throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
-        }
+        $id = $this->normalizeId($id);
 
-        if ($set) {
-            $this->obsoleteDefinitions[$id] = $this->definitions[$id];
+        if ($this->isCompiled() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) {
+            // setting a synthetic service on a compiled container is alright
+            throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id));
         }
 
-        unset($this->definitions[$id], $this->aliasDefinitions[$id]);
+        unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->removedIds[$id]);
 
-        parent::set($id, $service, $scope);
-
-        if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized(false)) {
-            $this->synchronize($id);
-        }
+        parent::set($id, $service);
     }
 
     /**
@@ -407,7 +544,10 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function removeDefinition($id)
     {
-        unset($this->definitions[strtolower($id)]);
+        if (isset($this->definitions[$id = $this->normalizeId($id)])) {
+            unset($this->definitions[$id]);
+            $this->removedIds[$id] = true;
+        }
     }
 
     /**
@@ -419,7 +559,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function has($id)
     {
-        $id = strtolower($id);
+        $id = $this->normalizeId($id);
 
         return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
     }
@@ -430,7 +570,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      * @param string $id              The service identifier
      * @param int    $invalidBehavior The behavior when the service does not exist
      *
-     * @return object The associated service
+     * @return object|null The associated service
      *
      * @throws InvalidArgumentException          when no definitions are available
      * @throws ServiceCircularReferenceException When a circular reference is detected
@@ -441,47 +581,62 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
     {
-        $id = strtolower($id);
+        if ($this->isCompiled() && isset($this->removedIds[$id = $this->normalizeId($id)])) {
+            @trigger_error(sprintf('Fetching the "%s" private service or alias is deprecated since Symfony 3.4 and will fail in 4.0. Make it public instead.', $id), E_USER_DEPRECATED);
+        }
+
+        return $this->doGet($id, $invalidBehavior);
+    }
 
-        if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
-            return $service;
+    private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, $isConstructorArgument = false)
+    {
+        $id = $this->normalizeId($id);
+
+        if (isset($inlineServices[$id])) {
+            return $inlineServices[$id];
+        }
+        if (null === $inlineServices) {
+            $isConstructorArgument = true;
+            $inlineServices = [];
+        }
+        try {
+            if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) {
+                return parent::get($id, $invalidBehavior);
+            }
+            if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
+                return $service;
+            }
+        } catch (ServiceCircularReferenceException $e) {
+            if ($isConstructorArgument) {
+                throw $e;
+            }
         }
 
-        if (!array_key_exists($id, $this->definitions) && isset($this->aliasDefinitions[$id])) {
-            return $this->get((string) $this->aliasDefinitions[$id], $invalidBehavior);
+        if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
+            return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices, $isConstructorArgument);
         }
 
         try {
             $definition = $this->getDefinition($id);
         } catch (ServiceNotFoundException $e) {
             if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
-                return;
+                return null;
             }
 
             throw $e;
         }
 
-        $this->loading[$id] = true;
+        if ($isConstructorArgument) {
+            $this->loading[$id] = true;
+        }
 
         try {
-            $service = $this->createService($definition, new \SplObjectStorage(), $id);
-        } catch (\Exception $e) {
-            unset($this->loading[$id]);
-
-            if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
-                return;
+            return $this->createService($definition, $inlineServices, $isConstructorArgument, $id);
+        } finally {
+            if ($isConstructorArgument) {
+                unset($this->loading[$id]);
             }
-
-            throw $e;
-        } catch (\Throwable $e) {
-            unset($this->loading[$id]);
-
-            throw $e;
         }
-
-        unset($this->loading[$id]);
-
-        return $service;
     }
 
     /**
@@ -493,7 +648,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      * the parameters passed to the container constructor to have precedence
      * over the loaded ones.
      *
-     *     $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
+     *     $container = new ContainerBuilder(new ParameterBag(['foo' => 'bar']));
      *     $loader = new LoaderXXX($container);
      *     $loader->load('resource_name');
      *     $container->register('foo', 'stdClass');
@@ -502,12 +657,12 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      * parameter, the value will still be 'bar' as defined in the ContainerBuilder
      * constructor.
      *
-     * @throws BadMethodCallException When this ContainerBuilder is frozen
+     * @throws BadMethodCallException When this ContainerBuilder is compiled
      */
-    public function merge(ContainerBuilder $container)
+    public function merge(self $container)
     {
-        if ($this->isFrozen()) {
-            throw new BadMethodCallException('Cannot merge on a frozen container.');
+        if ($this->isCompiled()) {
+            throw new BadMethodCallException('Cannot merge on a compiled container.');
         }
 
         $this->addDefinitions($container->getDefinitions());
@@ -522,11 +677,37 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
 
         foreach ($this->extensions as $name => $extension) {
             if (!isset($this->extensionConfigs[$name])) {
-                $this->extensionConfigs[$name] = array();
+                $this->extensionConfigs[$name] = [];
             }
 
             $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
         }
+
+        if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) {
+            $envPlaceholders = $container->getParameterBag()->getEnvPlaceholders();
+            $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag());
+        } else {
+            $envPlaceholders = [];
+        }
+
+        foreach ($container->envCounters as $env => $count) {
+            if (!$count && !isset($envPlaceholders[$env])) {
+                continue;
+            }
+            if (!isset($this->envCounters[$env])) {
+                $this->envCounters[$env] = $count;
+            } else {
+                $this->envCounters[$env] += $count;
+            }
+        }
+
+        foreach ($container->getAutoconfiguredInstanceof() as $interface => $childDefinition) {
+            if (isset($this->autoconfiguredInstanceof[$interface])) {
+                throw new InvalidArgumentException(sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same class/interface.', $interface));
+            }
+
+            $this->autoconfiguredInstanceof[$interface] = $childDefinition;
+        }
     }
 
     /**
@@ -539,7 +720,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
     public function getExtensionConfig($name)
     {
         if (!isset($this->extensionConfigs[$name])) {
-            $this->extensionConfigs[$name] = array();
+            $this->extensionConfigs[$name] = [];
         }
 
         return $this->extensionConfigs[$name];
@@ -554,7 +735,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
     public function prependExtensionConfig($name, array $config)
     {
         if (!isset($this->extensionConfigs[$name])) {
-            $this->extensionConfigs[$name] = array();
+            $this->extensionConfigs[$name] = [];
         }
 
         array_unshift($this->extensionConfigs[$name], $config);
@@ -573,9 +754,25 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      *  * Parameter values are resolved;
      *  * The parameter bag is frozen;
      *  * Extension loading is disabled.
+     *
+     * @param bool $resolveEnvPlaceholders Whether %env()% parameters should be resolved using the current
+     *                                     env vars or be replaced by uniquely identifiable placeholders.
+     *                                     Set to "true" when you want to use the current ContainerBuilder
+     *                                     directly, keep to "false" when the container is dumped instead.
      */
-    public function compile()
+    public function compile(/*$resolveEnvPlaceholders = false*/)
     {
+        if (1 <= \func_num_args()) {
+            $resolveEnvPlaceholders = func_get_arg(0);
+        } else {
+            if (__CLASS__ !== static::class) {
+                $r = new \ReflectionMethod($this, __FUNCTION__);
+                if (__CLASS__ !== $r->getDeclaringClass()->getName() && (1 > $r->getNumberOfParameters() || 'resolveEnvPlaceholders' !== $r->getParameters()[0]->name)) {
+                    @trigger_error(sprintf('The %s::compile() method expects a first "$resolveEnvPlaceholders" argument since Symfony 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED);
+                }
+            }
+            $resolveEnvPlaceholders = false;
+        }
         $compiler = $this->getCompiler();
 
         if ($this->trackResources) {
@@ -583,30 +780,55 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
                 $this->addObjectResource($pass);
             }
         }
+        $bag = $this->getParameterBag();
+
+        if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) {
+            $compiler->addPass(new ResolveEnvPlaceholdersPass(), PassConfig::TYPE_AFTER_REMOVING, -1000);
+        }
 
         $compiler->compile($this);
 
-        if ($this->trackResources) {
-            foreach ($this->definitions as $definition) {
-                if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) {
-                    $this->addClassResource(new \ReflectionClass($class));
-                }
+        foreach ($this->definitions as $id => $definition) {
+            if ($this->trackResources && $definition->isLazy()) {
+                $this->getReflectionClass($definition->getClass());
             }
         }
 
-        $this->extensionConfigs = array();
+        $this->extensionConfigs = [];
+
+        if ($bag instanceof EnvPlaceholderParameterBag) {
+            if ($resolveEnvPlaceholders) {
+                $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true));
+            }
+
+            $this->envPlaceholders = $bag->getEnvPlaceholders();
+        }
 
         parent::compile();
+
+        foreach ($this->definitions + $this->aliasDefinitions as $id => $definition) {
+            if (!$definition->isPublic() || $definition->isPrivate()) {
+                $this->removedIds[$id] = true;
+            }
+        }
     }
 
     /**
-     * Gets all service ids.
-     *
-     * @return array An array of all defined service ids
+     * {@inheritdoc}
      */
     public function getServiceIds()
     {
-        return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()));
+        return array_map('strval', array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds())));
+    }
+
+    /**
+     * Gets removed service or alias ids.
+     *
+     * @return array
+     */
+    public function getRemovedIds()
+    {
+        return $this->removedIds;
     }
 
     /**
@@ -624,7 +846,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function setAliases(array $aliases)
     {
-        $this->aliasDefinitions = array();
+        $this->aliasDefinitions = [];
         $this->addAliases($aliases);
     }
 
@@ -634,19 +856,21 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      * @param string       $alias The alias to create
      * @param string|Alias $id    The service to alias
      *
+     * @return Alias
+     *
      * @throws InvalidArgumentException if the id is not a string or an Alias
      * @throws InvalidArgumentException if the alias is for itself
      */
     public function setAlias($alias, $id)
     {
-        $alias = strtolower($alias);
+        $alias = $this->normalizeId($alias);
 
         if ('' === $alias || '\\' === substr($alias, -1) || \strlen($alias) !== strcspn($alias, "\0\r\n'")) {
-            throw new InvalidArgumentException(sprintf('Invalid alias id: "%s"', $alias));
+            throw new InvalidArgumentException(sprintf('Invalid alias id: "%s".', $alias));
         }
 
         if (\is_string($id)) {
-            $id = new Alias($id);
+            $id = new Alias($this->normalizeId($id));
         } elseif (!$id instanceof Alias) {
             throw new InvalidArgumentException('$id must be a string, or an Alias object.');
         }
@@ -655,9 +879,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
             throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
         }
 
-        unset($this->definitions[$alias]);
+        unset($this->definitions[$alias], $this->removedIds[$alias]);
 
-        $this->aliasDefinitions[$alias] = $id;
+        return $this->aliasDefinitions[$alias] = $id;
     }
 
     /**
@@ -667,7 +891,10 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function removeAlias($alias)
     {
-        unset($this->aliasDefinitions[strtolower($alias)]);
+        if (isset($this->aliasDefinitions[$alias = $this->normalizeId($alias)])) {
+            unset($this->aliasDefinitions[$alias]);
+            $this->removedIds[$alias] = true;
+        }
     }
 
     /**
@@ -679,7 +906,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function hasAlias($id)
     {
-        return isset($this->aliasDefinitions[strtolower($id)]);
+        return isset($this->aliasDefinitions[$this->normalizeId($id)]);
     }
 
     /**
@@ -703,7 +930,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function getAlias($id)
     {
-        $id = strtolower($id);
+        $id = $this->normalizeId($id);
 
         if (!isset($this->aliasDefinitions[$id])) {
             throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id));
@@ -718,8 +945,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      * This methods allows for simple registration of service definition
      * with a fluid interface.
      *
-     * @param string $id         The service identifier
-     * @param string $class|null The service class
+     * @param string      $id    The service identifier
+     * @param string|null $class The service class
      *
      * @return Definition A Definition instance
      */
@@ -728,6 +955,22 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
         return $this->setDefinition($id, new Definition($class));
     }
 
+    /**
+     * Registers an autowired service definition.
+     *
+     * This method implements a shortcut for using setDefinition() with
+     * an autowired definition.
+     *
+     * @param string      $id    The service identifier
+     * @param string|null $class The service class
+     *
+     * @return Definition The created definition
+     */
+    public function autowire($id, $class = null)
+    {
+        return $this->setDefinition($id, (new Definition($class))->setAutowired(true));
+    }
+
     /**
      * Adds the service definitions.
      *
@@ -747,7 +990,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function setDefinitions(array $definitions)
     {
-        $this->definitions = array();
+        $this->definitions = [];
         $this->addDefinitions($definitions);
     }
 
@@ -769,21 +1012,21 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      *
      * @return Definition the service definition
      *
-     * @throws BadMethodCallException When this ContainerBuilder is frozen
+     * @throws BadMethodCallException When this ContainerBuilder is compiled
      */
     public function setDefinition($id, Definition $definition)
     {
-        if ($this->isFrozen()) {
-            throw new BadMethodCallException('Adding definition to a frozen container is not allowed');
+        if ($this->isCompiled()) {
+            throw new BadMethodCallException('Adding definition to a compiled container is not allowed.');
         }
 
-        $id = strtolower($id);
+        $id = $this->normalizeId($id);
 
         if ('' === $id || '\\' === substr($id, -1) || \strlen($id) !== strcspn($id, "\0\r\n'")) {
-            throw new InvalidArgumentException(sprintf('Invalid service id: "%s"', $id));
+            throw new InvalidArgumentException(sprintf('Invalid service id: "%s".', $id));
         }
 
-        unset($this->aliasDefinitions[$id]);
+        unset($this->aliasDefinitions[$id], $this->removedIds[$id]);
 
         return $this->definitions[$id] = $definition;
     }
@@ -797,7 +1040,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function hasDefinition($id)
     {
-        return array_key_exists(strtolower($id), $this->definitions);
+        return isset($this->definitions[$this->normalizeId($id)]);
     }
 
     /**
@@ -811,9 +1054,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function getDefinition($id)
     {
-        $id = strtolower($id);
+        $id = $this->normalizeId($id);
 
-        if (!array_key_exists($id, $this->definitions)) {
+        if (!isset($this->definitions[$id])) {
             throw new ServiceNotFoundException($id);
         }
 
@@ -833,10 +1076,21 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function findDefinition($id)
     {
-        $id = strtolower($id);
+        $id = $this->normalizeId($id);
 
+        $seen = [];
         while (isset($this->aliasDefinitions[$id])) {
             $id = (string) $this->aliasDefinitions[$id];
+
+            if (isset($seen[$id])) {
+                $seen = array_values($seen);
+                $seen = \array_slice($seen, array_search($id, $seen));
+                $seen[] = $id;
+
+                throw new ServiceCircularReferenceException($id, $seen);
+            }
+
+            $seen[$id] = $id;
         }
 
         return $this->getDefinition($id);
@@ -849,22 +1103,19 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      * @param string     $id         The service identifier
      * @param bool       $tryProxy   Whether to try proxying the service with a lazy proxy
      *
-     * @return object The service described by the service definition
+     * @return mixed The service described by the service definition
      *
-     * @throws RuntimeException         When the scope is inactive
      * @throws RuntimeException         When the factory definition is incomplete
      * @throws RuntimeException         When the service is a synthetic service
      * @throws InvalidArgumentException When configure callable is not callable
-     *
-     * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code
      */
-    public function createService(Definition $definition, \SplObjectStorage $inlinedDefinitions, $id = null, $tryProxy = true)
+    private function createService(Definition $definition, array &$inlineServices, $isConstructorArgument = false, $id = null, $tryProxy = true)
     {
-        if (null === $id && isset($inlinedDefinitions[$definition])) {
-            return $inlinedDefinitions[$definition];
+        if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) {
+            return $inlineServices[$h];
         }
 
-        if ($definition instanceof DefinitionDecorator) {
+        if ($definition instanceof ChildDefinition) {
             throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id));
         }
 
@@ -876,19 +1127,15 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
             @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED);
         }
 
-        if ($tryProxy && $definition->isLazy()) {
-            $container = $this;
-
-            $proxy = $this
-                ->getProxyInstantiator()
-                ->instantiateProxy(
-                    $container,
-                    $definition,
-                    $id, function () use ($definition, $inlinedDefinitions, $id, $container) {
-                        return $container->createService($definition, $inlinedDefinitions, $id, false);
-                    }
-                );
-            $this->shareService($definition, $proxy, $id, $inlinedDefinitions);
+        if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) {
+            $proxy = $proxy->instantiateProxy(
+                $this,
+                $definition,
+                $id, function () use ($definition, &$inlineServices, $id) {
+                    return $this->createService($definition, $inlineServices, true, $id, false);
+                }
+            );
+            $this->shareService($definition, $proxy, $id, $inlineServices);
 
             return $proxy;
         }
@@ -899,15 +1146,21 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
             require_once $parameterBag->resolveValue($definition->getFile());
         }
 
-        $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlinedDefinitions);
+        $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices, $isConstructorArgument);
 
         if (null !== $factory = $definition->getFactory()) {
             if (\is_array($factory)) {
-                $factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlinedDefinitions), $factory[1]);
+                $factory = [$this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument), $factory[1]];
             } elseif (!\is_string($factory)) {
-                throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
+                throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory.', $id));
             }
+        }
+
+        if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) {
+            return $this->services[$id];
+        }
 
+        if (null !== $factory) {
             $service = \call_user_func_array($factory, $arguments);
 
             if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) {
@@ -917,38 +1170,31 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
                     @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED);
                 }
             }
-        } elseif (null !== $definition->getFactoryMethod(false)) {
-            if (null !== $definition->getFactoryClass(false)) {
-                $factory = $parameterBag->resolveValue($definition->getFactoryClass(false));
-            } elseif (null !== $definition->getFactoryService(false)) {
-                $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService(false)));
-            } else {
-                throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id));
-            }
-
-            $service = \call_user_func_array(array($factory, $definition->getFactoryMethod(false)), $arguments);
         } else {
-            $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
+            $r = new \ReflectionClass($class = $parameterBag->resolveValue($definition->getClass()));
 
             $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
+            // don't trigger deprecations for internal uses
+            // @deprecated since version 3.3, to be removed in 4.0 along with the deprecated class
+            $deprecationWhitelist = ['event_dispatcher' => ContainerAwareEventDispatcher::class];
 
-            if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
+            if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ") && (!isset($deprecationWhitelist[$id]) || $deprecationWhitelist[$id] !== $class)) {
                 @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED);
             }
         }
 
         if ($tryProxy || !$definition->isLazy()) {
             // share only if proxying failed, or if not a proxy
-            $this->shareService($definition, $service, $id, $inlinedDefinitions);
+            $this->shareService($definition, $service, $id, $inlineServices);
         }
 
-        $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlinedDefinitions);
+        $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlineServices);
         foreach ($properties as $name => $value) {
             $service->$name = $value;
         }
 
         foreach ($definition->getMethodCalls() as $call) {
-            $this->callMethod($service, $call, $inlinedDefinitions);
+            $this->callMethod($service, $call, $inlineServices);
         }
 
         if ($callable = $definition->getConfigurator()) {
@@ -956,9 +1202,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
                 $callable[0] = $parameterBag->resolveValue($callable[0]);
 
                 if ($callable[0] instanceof Reference) {
-                    $callable[0] = $this->get((string) $callable[0], $callable[0]->getInvalidBehavior());
+                    $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices);
                 } elseif ($callable[0] instanceof Definition) {
-                    $callable[0] = $this->createService($callable[0], $inlinedDefinitions);
+                    $callable[0] = $this->createService($callable[0], $inlineServices);
                 }
             }
 
@@ -982,21 +1228,63 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function resolveServices($value)
     {
-        return $this->doResolveServices($value, new \SplObjectStorage());
+        return $this->doResolveServices($value);
     }
 
-    private function doResolveServices($value, \SplObjectStorage $inlinedDefinitions)
+    private function doResolveServices($value, array &$inlineServices = [], $isConstructorArgument = false)
     {
         if (\is_array($value)) {
             foreach ($value as $k => $v) {
-                $value[$k] = $this->doResolveServices($v, $inlinedDefinitions);
+                $value[$k] = $this->doResolveServices($v, $inlineServices, $isConstructorArgument);
             }
+        } elseif ($value instanceof ServiceClosureArgument) {
+            $reference = $value->getValues()[0];
+            $value = function () use ($reference) {
+                return $this->resolveServices($reference);
+            };
+        } elseif ($value instanceof IteratorArgument) {
+            $value = new RewindableGenerator(function () use ($value) {
+                foreach ($value->getValues() as $k => $v) {
+                    foreach (self::getServiceConditionals($v) as $s) {
+                        if (!$this->has($s)) {
+                            continue 2;
+                        }
+                    }
+                    foreach (self::getInitializedConditionals($v) as $s) {
+                        if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
+                            continue 2;
+                        }
+                    }
+
+                    yield $k => $this->resolveServices($v);
+                }
+            }, function () use ($value) {
+                $count = 0;
+                foreach ($value->getValues() as $v) {
+                    foreach (self::getServiceConditionals($v) as $s) {
+                        if (!$this->has($s)) {
+                            continue 2;
+                        }
+                    }
+                    foreach (self::getInitializedConditionals($v) as $s) {
+                        if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
+                            continue 2;
+                        }
+                    }
+
+                    ++$count;
+                }
+
+                return $count;
+            });
         } elseif ($value instanceof Reference) {
-            $value = $this->get((string) $value, $value->getInvalidBehavior());
+            $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument);
         } elseif ($value instanceof Definition) {
-            $value = $this->createService($value, $inlinedDefinitions);
+            $value = $this->createService($value, $inlineServices, $isConstructorArgument);
+        } elseif ($value instanceof Parameter) {
+            $value = $this->getParameter((string) $value);
         } elseif ($value instanceof Expression) {
-            $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
+            $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this]);
         }
 
         return $value;
@@ -1007,7 +1295,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      *
      * Example:
      *
-     *     $container->register('foo')->addTag('my.tag', array('hello' => 'world'));
+     *     $container->register('foo')->addTag('my.tag', ['hello' => 'world']);
      *
      *     $serviceIds = $container->findTaggedServiceIds('my.tag');
      *     foreach ($serviceIds as $serviceId => $tags) {
@@ -1016,16 +1304,20 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      *         }
      *     }
      *
-     * @param string $name The tag name
+     * @param string $name
+     * @param bool   $throwOnAbstract
      *
      * @return array An array of tags with the tagged service as key, holding a list of attribute arrays
      */
-    public function findTaggedServiceIds($name)
+    public function findTaggedServiceIds($name, $throwOnAbstract = false)
     {
         $this->usedTags[] = $name;
-        $tags = array();
+        $tags = [];
         foreach ($this->getDefinitions() as $id => $definition) {
             if ($definition->hasTag($name)) {
+                if ($throwOnAbstract && $definition->isAbstract()) {
+                    throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name));
+                }
                 $tags[$id] = $definition->getTag($name);
             }
         }
@@ -1040,7 +1332,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
      */
     public function findTags()
     {
-        $tags = array();
+        $tags = [];
         foreach ($this->getDefinitions() as $id => $definition) {
             $tags = array_merge(array_keys($definition->getTags()), $tags);
         }
@@ -1071,16 +1363,195 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
         return $this->expressionLanguageProviders;
     }
 
+    /**
+     * Returns a ChildDefinition that will be used for autoconfiguring the interface/class.
+     *
+     * @param string $interface The class or interface to match
+     *
+     * @return ChildDefinition
+     */
+    public function registerForAutoconfiguration($interface)
+    {
+        if (!isset($this->autoconfiguredInstanceof[$interface])) {
+            $this->autoconfiguredInstanceof[$interface] = new ChildDefinition('');
+        }
+
+        return $this->autoconfiguredInstanceof[$interface];
+    }
+
+    /**
+     * Returns an array of ChildDefinition[] keyed by interface.
+     *
+     * @return ChildDefinition[]
+     */
+    public function getAutoconfiguredInstanceof()
+    {
+        return $this->autoconfiguredInstanceof;
+    }
+
+    /**
+     * Resolves env parameter placeholders in a string or an array.
+     *
+     * @param mixed            $value     The value to resolve
+     * @param string|true|null $format    A sprintf() format returning the replacement for each env var name or
+     *                                    null to resolve back to the original "%env(VAR)%" format or
+     *                                    true to resolve to the actual values of the referenced env vars
+     * @param array            &$usedEnvs Env vars found while resolving are added to this array
+     *
+     * @return mixed The value with env parameters resolved if a string or an array is passed
+     */
+    public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null)
+    {
+        if (null === $format) {
+            $format = '%%env(%s)%%';
+        }
+
+        $bag = $this->getParameterBag();
+        if (true === $format) {
+            $value = $bag->resolveValue($value);
+        }
+
+        if (\is_array($value)) {
+            $result = [];
+            foreach ($value as $k => $v) {
+                $result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs);
+            }
+
+            return $result;
+        }
+
+        if (!\is_string($value) || 38 > \strlen($value)) {
+            return $value;
+        }
+        $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
+
+        $completed = false;
+        foreach ($envPlaceholders as $env => $placeholders) {
+            foreach ($placeholders as $placeholder) {
+                if (false !== stripos($value, $placeholder)) {
+                    if (true === $format) {
+                        $resolved = $bag->escapeValue($this->getEnv($env));
+                    } else {
+                        $resolved = sprintf($format, $env);
+                    }
+                    if ($placeholder === $value) {
+                        $value = $resolved;
+                        $completed = true;
+                    } else {
+                        if (!\is_string($resolved) && !is_numeric($resolved)) {
+                            throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type "%s" inside string value "%s".', $env, \gettype($resolved), $this->resolveEnvPlaceholders($value)));
+                        }
+                        $value = str_ireplace($placeholder, $resolved, $value);
+                    }
+                    $usedEnvs[$env] = $env;
+                    $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1;
+
+                    if ($completed) {
+                        break 2;
+                    }
+                }
+            }
+        }
+
+        return $value;
+    }
+
+    /**
+     * Get statistics about env usage.
+     *
+     * @return int[] The number of time each env vars has been resolved
+     */
+    public function getEnvCounters()
+    {
+        $bag = $this->getParameterBag();
+        $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
+
+        foreach ($envPlaceholders as $env => $placeholders) {
+            if (!isset($this->envCounters[$env])) {
+                $this->envCounters[$env] = 0;
+            }
+        }
+
+        return $this->envCounters;
+    }
+
+    /**
+     * @internal
+     */
+    public function getNormalizedIds()
+    {
+        $normalizedIds = [];
+
+        foreach ($this->normalizedIds as $k => $v) {
+            if ($v !== (string) $k) {
+                $normalizedIds[$k] = $v;
+            }
+        }
+
+        return $normalizedIds;
+    }
+
+    /**
+     * @final
+     */
+    public function log(CompilerPassInterface $pass, $message)
+    {
+        $this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function normalizeId($id)
+    {
+        if (!\is_string($id)) {
+            $id = (string) $id;
+        }
+
+        return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || isset($this->removedIds[$id]) ? $id : parent::normalizeId($id);
+    }
+
+    /**
+     * Gets removed binding ids.
+     *
+     * @return array
+     *
+     * @internal
+     */
+    public function getRemovedBindingIds()
+    {
+        return $this->removedBindingIds;
+    }
+
+    /**
+     * Removes bindings for a service.
+     *
+     * @param string $id The service identifier
+     *
+     * @internal
+     */
+    public function removeBindings($id)
+    {
+        if ($this->hasDefinition($id)) {
+            foreach ($this->getDefinition($id)->getBindings() as $key => $binding) {
+                list(, $bindingId) = $binding->getValues();
+                $this->removedBindingIds[(int) $bindingId] = true;
+            }
+        }
+    }
+
     /**
      * Returns the Service Conditionals.
      *
      * @param mixed $value An array of conditionals to return
      *
      * @return array An array of Service conditionals
+     *
+     * @internal since version 3.4
      */
     public static function getServiceConditionals($value)
     {
-        $services = array();
+        $services = [];
 
         if (\is_array($value)) {
             foreach ($value as $v) {
@@ -1094,90 +1565,100 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
     }
 
     /**
-     * Retrieves the currently set proxy instantiator or instantiates one.
+     * Returns the initialized conditionals.
+     *
+     * @param mixed $value An array of conditionals to return
+     *
+     * @return array An array of uninitialized conditionals
      *
-     * @return InstantiatorInterface
+     * @internal
      */
-    private function getProxyInstantiator()
+    public static function getInitializedConditionals($value)
     {
-        if (!$this->proxyInstantiator) {
-            $this->proxyInstantiator = new RealServiceInstantiator();
+        $services = [];
+
+        if (\is_array($value)) {
+            foreach ($value as $v) {
+                $services = array_unique(array_merge($services, self::getInitializedConditionals($v)));
+            }
+        } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) {
+            $services[] = (string) $value;
         }
 
-        return $this->proxyInstantiator;
+        return $services;
     }
 
     /**
-     * Synchronizes a service change.
-     *
-     * This method updates all services that depend on the given
-     * service by calling all methods referencing it.
+     * Computes a reasonably unique hash of a value.
      *
-     * @param string $id A service id
+     * @param mixed $value A serializable value
      *
-     * @deprecated since version 2.7, will be removed in 3.0.
+     * @return string
      */
-    private function synchronize($id)
+    public static function hash($value)
     {
-        if ('request' !== $id) {
-            @trigger_error('The '.__METHOD__.' method is deprecated in version 2.7 and will be removed in version 3.0.', E_USER_DEPRECATED);
+        $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7);
+
+        return str_replace(['/', '+'], ['.', '_'], strtolower($hash));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getEnv($name)
+    {
+        $value = parent::getEnv($name);
+        $bag = $this->getParameterBag();
+
+        if (!\is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) {
+            return $value;
         }
 
-        foreach ($this->definitions as $definitionId => $definition) {
-            // only check initialized services
-            if (!$this->initialized($definitionId)) {
-                continue;
-            }
+        foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
+            if (isset($placeholders[$value])) {
+                $bag = new ParameterBag($bag->all());
 
-            foreach ($definition->getMethodCalls() as $call) {
-                foreach ($call[1] as $argument) {
-                    if ($argument instanceof Reference && $id == (string) $argument) {
-                        $this->callMethod($this->get($definitionId), $call, new \SplObjectStorage());
-                    }
-                }
+                return $bag->unescapeValue($bag->get("env($name)"));
             }
         }
+
+        $this->resolving["env($name)"] = true;
+        try {
+            return $bag->unescapeValue($this->resolveEnvPlaceholders($bag->escapeValue($value), true));
+        } finally {
+            unset($this->resolving["env($name)"]);
+        }
     }
 
-    private function callMethod($service, $call, \SplObjectStorage $inlinedDefinitions)
+    private function callMethod($service, $call, array &$inlineServices)
     {
-        $services = self::getServiceConditionals($call[1]);
-
-        foreach ($services as $s) {
+        foreach (self::getServiceConditionals($call[1]) as $s) {
             if (!$this->has($s)) {
                 return;
             }
         }
+        foreach (self::getInitializedConditionals($call[1]) as $s) {
+            if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
+                return;
+            }
+        }
 
-        \call_user_func_array(array($service, $call[0]), $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlinedDefinitions));
+        \call_user_func_array([$service, $call[0]], $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices));
     }
 
     /**
      * Shares a given service in the container.
      *
-     * @param Definition  $definition
      * @param mixed       $service
      * @param string|null $id
-     *
-     * @throws InactiveScopeException
      */
-    private function shareService(Definition $definition, $service, $id, \SplObjectStorage $inlinedDefinitions)
+    private function shareService(Definition $definition, $service, $id, array &$inlineServices)
     {
-        if (!$definition->isShared() || self::SCOPE_PROTOTYPE === $scope = $definition->getScope(false)) {
-            return;
-        }
-        if (null === $id) {
-            $inlinedDefinitions[$definition] = $service;
-        } else {
-            if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) {
-                throw new InactiveScopeException($id, $scope);
-            }
-
-            $this->services[$lowerId = strtolower($id)] = $service;
+        $inlineServices[null !== $id ? $id : spl_object_hash($definition)] = $service;
 
-            if (self::SCOPE_CONTAINER !== $scope) {
-                $this->scopedServices[$scope][$lowerId] = $service;
-            }
+        if (null !== $id && $definition->isShared()) {
+            $this->services[$id] = $service;
+            unset($this->loading[$id]);
         }
     }
 
@@ -1192,4 +1673,22 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
 
         return $this->expressionLanguage;
     }
+
+    private function inVendors($path)
+    {
+        if (null === $this->vendors) {
+            $resource = new ComposerResource();
+            $this->vendors = $resource->getVendors();
+            $this->addResource($resource);
+        }
+        $path = realpath($path) ?: $path;
+
+        foreach ($this->vendors as $vendor) {
+            if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/ContainerInterface.php b/civicrm/vendor/symfony/dependency-injection/ContainerInterface.php
index d9076eb1f8..c5ab4c2eda 100644
--- a/civicrm/vendor/symfony/dependency-injection/ContainerInterface.php
+++ b/civicrm/vendor/symfony/dependency-injection/ContainerInterface.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\DependencyInjection;
 
+use Psr\Container\ContainerInterface as PsrContainerInterface;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
@@ -21,24 +22,20 @@ use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-interface ContainerInterface
+interface ContainerInterface extends PsrContainerInterface
 {
     const EXCEPTION_ON_INVALID_REFERENCE = 1;
     const NULL_ON_INVALID_REFERENCE = 2;
     const IGNORE_ON_INVALID_REFERENCE = 3;
-    const SCOPE_CONTAINER = 'container';
-    const SCOPE_PROTOTYPE = 'prototype';
+    const IGNORE_ON_UNINITIALIZED_REFERENCE = 4;
 
     /**
      * Sets a service.
      *
-     * Note: The $scope parameter is deprecated since version 2.8 and will be removed in 3.0.
-     *
-     * @param string $id      The service identifier
-     * @param object $service The service instance
-     * @param string $scope   The scope of the service
+     * @param string      $id      The service identifier
+     * @param object|null $service The service instance
      */
-    public function set($id, $service, $scope = self::SCOPE_CONTAINER);
+    public function set($id, $service);
 
     /**
      * Gets a service.
@@ -46,7 +43,7 @@ interface ContainerInterface
      * @param string $id              The service identifier
      * @param int    $invalidBehavior The behavior when the service does not exist
      *
-     * @return object The associated service
+     * @return object|null The associated service
      *
      * @throws ServiceCircularReferenceException When a circular reference is detected
      * @throws ServiceNotFoundException          When the service is not defined
@@ -64,6 +61,15 @@ interface ContainerInterface
      */
     public function has($id);
 
+    /**
+     * Check for whether or not a service has been initialized.
+     *
+     * @param string $id
+     *
+     * @return bool true if the service has been initialized, false otherwise
+     */
+    public function initialized($id);
+
     /**
      * Gets a parameter.
      *
@@ -91,55 +97,4 @@ interface ContainerInterface
      * @param mixed  $value The parameter value
      */
     public function setParameter($name, $value);
-
-    /**
-     * Enters the given scope.
-     *
-     * @param string $name
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function enterScope($name);
-
-    /**
-     * Leaves the current scope, and re-enters the parent scope.
-     *
-     * @param string $name
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function leaveScope($name);
-
-    /**
-     * Adds a scope to the container.
-     *
-     * @param ScopeInterface $scope
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function addScope(ScopeInterface $scope);
-
-    /**
-     * Whether this container has the given scope.
-     *
-     * @param string $name
-     *
-     * @return bool
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function hasScope($name);
-
-    /**
-     * Determines whether the given scope is currently active.
-     *
-     * It does however not check if the scope actually exists.
-     *
-     * @param string $name
-     *
-     * @return bool
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function isScopeActive($name);
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Definition.php b/civicrm/vendor/symfony/dependency-injection/Definition.php
index d9c37ea504..c7d2049484 100644
--- a/civicrm/vendor/symfony/dependency-injection/Definition.php
+++ b/civicrm/vendor/symfony/dependency-injection/Definition.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\DependencyInjection;
 
+use Symfony\Component\DependencyInjection\Argument\BoundArgument;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
 
@@ -24,119 +25,95 @@ class Definition
     private $class;
     private $file;
     private $factory;
-    private $factoryClass;
-    private $factoryMethod;
-    private $factoryService;
     private $shared = true;
     private $deprecated = false;
     private $deprecationTemplate;
-    private $scope = ContainerInterface::SCOPE_CONTAINER;
-    private $properties = array();
-    private $calls = array();
+    private $properties = [];
+    private $calls = [];
+    private $instanceof = [];
+    private $autoconfigured = false;
     private $configurator;
-    private $tags = array();
+    private $tags = [];
     private $public = true;
+    private $private = true;
     private $synthetic = false;
     private $abstract = false;
-    private $synchronized = false;
     private $lazy = false;
     private $decoratedService;
     private $autowired = false;
-    private $autowiringTypes = array();
+    private $autowiringTypes = [];
+    private $changes = [];
+    private $bindings = [];
+    private $errors = [];
 
-    private static $defaultDeprecationTemplate = 'The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed.';
+    protected $arguments = [];
 
-    protected $arguments;
+    private static $defaultDeprecationTemplate = 'The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed.';
 
     /**
      * @param string|null $class     The service class
      * @param array       $arguments An array of arguments to pass to the service constructor
      */
-    public function __construct($class = null, array $arguments = array())
+    public function __construct($class = null, array $arguments = [])
     {
-        $this->class = $class;
-        $this->arguments = $arguments;
-    }
-
-    /**
-     * Sets a factory.
-     *
-     * @param string|array $factory A PHP function or an array containing a class/Reference and a method to call
-     *
-     * @return $this
-     */
-    public function setFactory($factory)
-    {
-        if (\is_string($factory) && false !== strpos($factory, '::')) {
-            $factory = explode('::', $factory, 2);
+        if (null !== $class) {
+            $this->setClass($class);
         }
-
-        $this->factory = $factory;
-
-        return $this;
+        $this->arguments = $arguments;
     }
 
     /**
-     * Gets the factory.
+     * Returns all changes tracked for the Definition object.
      *
-     * @return string|array|null The PHP function or an array containing a class/Reference and a method to call
+     * @return array An array of changes for this Definition
      */
-    public function getFactory()
+    public function getChanges()
     {
-        return $this->factory;
+        return $this->changes;
     }
 
     /**
-     * Sets the name of the class that acts as a factory using the factory method,
-     * which will be invoked statically.
+     * Sets the tracked changes for the Definition object.
      *
-     * @param string $factoryClass The factory class name
+     * @param array $changes An array of changes for this Definition
      *
      * @return $this
-     *
-     * @deprecated since version 2.6, to be removed in 3.0.
      */
-    public function setFactoryClass($factoryClass)
+    public function setChanges(array $changes)
     {
-        @trigger_error(sprintf('%s(%s) is deprecated since Symfony 2.6 and will be removed in 3.0. Use Definition::setFactory() instead.', __METHOD__, $factoryClass), E_USER_DEPRECATED);
-
-        $this->factoryClass = $factoryClass;
+        $this->changes = $changes;
 
         return $this;
     }
 
     /**
-     * Gets the factory class.
+     * Sets a factory.
      *
-     * @return string|null The factory class name
+     * @param string|array $factory A PHP function or an array containing a class/Reference and a method to call
      *
-     * @deprecated since version 2.6, to be removed in 3.0.
+     * @return $this
      */
-    public function getFactoryClass($triggerDeprecationError = true)
+    public function setFactory($factory)
     {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0.', E_USER_DEPRECATED);
+        $this->changes['factory'] = true;
+
+        if (\is_string($factory) && false !== strpos($factory, '::')) {
+            $factory = explode('::', $factory, 2);
         }
 
-        return $this->factoryClass;
+        $this->factory = $factory;
+
+        return $this;
     }
 
     /**
-     * Sets the factory method able to create an instance of this class.
-     *
-     * @param string $factoryMethod The factory method name
-     *
-     * @return $this
+     * Gets the factory.
      *
-     * @deprecated since version 2.6, to be removed in 3.0.
+     * @return string|array|null The PHP function or an array containing a class/Reference and a method to call
      */
-    public function setFactoryMethod($factoryMethod)
+    public function getFactory()
     {
-        @trigger_error(sprintf('%s(%s) is deprecated since Symfony 2.6 and will be removed in 3.0. Use Definition::setFactory() instead.', __METHOD__, $factoryMethod), E_USER_DEPRECATED);
-
-        $this->factoryMethod = $factoryMethod;
-
-        return $this;
+        return $this->factory;
     }
 
     /**
@@ -153,13 +130,15 @@ class Definition
     public function setDecoratedService($id, $renamedId = null, $priority = 0)
     {
         if ($renamedId && $id === $renamedId) {
-            throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
+            throw new InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
         }
 
+        $this->changes['decorated_service'] = true;
+
         if (null === $id) {
             $this->decoratedService = null;
         } else {
-            $this->decoratedService = array($id, $renamedId, (int) $priority);
+            $this->decoratedService = [$id, $renamedId, (int) $priority];
         }
 
         return $this;
@@ -175,58 +154,6 @@ class Definition
         return $this->decoratedService;
     }
 
-    /**
-     * Gets the factory method.
-     *
-     * @return string|null The factory method name
-     *
-     * @deprecated since version 2.6, to be removed in 3.0.
-     */
-    public function getFactoryMethod($triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return $this->factoryMethod;
-    }
-
-    /**
-     * Sets the name of the service that acts as a factory using the factory method.
-     *
-     * @param string $factoryService The factory service id
-     *
-     * @return $this
-     *
-     * @deprecated since version 2.6, to be removed in 3.0.
-     */
-    public function setFactoryService($factoryService, $triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error(sprintf('%s(%s) is deprecated since Symfony 2.6 and will be removed in 3.0. Use Definition::setFactory() instead.', __METHOD__, $factoryService), E_USER_DEPRECATED);
-        }
-
-        $this->factoryService = $factoryService;
-
-        return $this;
-    }
-
-    /**
-     * Gets the factory service id.
-     *
-     * @return string|null The factory service id
-     *
-     * @deprecated since version 2.6, to be removed in 3.0.
-     */
-    public function getFactoryService($triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return $this->factoryService;
-    }
-
     /**
      * Sets the service class.
      *
@@ -236,6 +163,8 @@ class Definition
      */
     public function setClass($class)
     {
+        $this->changes['class'] = true;
+
         $this->class = $class;
 
         return $this;
@@ -317,8 +246,8 @@ class Definition
     /**
      * Replaces a specific argument.
      *
-     * @param int   $index
-     * @param mixed $argument
+     * @param int|string $index
+     * @param mixed      $argument
      *
      * @return $this
      *
@@ -330,15 +259,34 @@ class Definition
             throw new OutOfBoundsException('Cannot replace arguments if none have been configured yet.');
         }
 
-        if ($index < 0 || $index > \count($this->arguments) - 1) {
+        if (\is_int($index) && ($index < 0 || $index > \count($this->arguments) - 1)) {
             throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, \count($this->arguments) - 1));
         }
 
+        if (!\array_key_exists($index, $this->arguments)) {
+            throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index));
+        }
+
         $this->arguments[$index] = $argument;
 
         return $this;
     }
 
+    /**
+     * Sets a specific argument.
+     *
+     * @param int|string $key
+     * @param mixed      $value
+     *
+     * @return $this
+     */
+    public function setArgument($key, $value)
+    {
+        $this->arguments[$key] = $value;
+
+        return $this;
+    }
+
     /**
      * Gets the arguments to pass to the service constructor/factory method.
      *
@@ -352,7 +300,7 @@ class Definition
     /**
      * Gets an argument to pass to the service constructor/factory method.
      *
-     * @param int $index
+     * @param int|string $index
      *
      * @return mixed The argument value
      *
@@ -360,8 +308,8 @@ class Definition
      */
     public function getArgument($index)
     {
-        if ($index < 0 || $index > \count($this->arguments) - 1) {
-            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, \count($this->arguments) - 1));
+        if (!\array_key_exists($index, $this->arguments)) {
+            throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index));
         }
 
         return $this->arguments[$index];
@@ -372,9 +320,9 @@ class Definition
      *
      * @return $this
      */
-    public function setMethodCalls(array $calls = array())
+    public function setMethodCalls(array $calls = [])
     {
-        $this->calls = array();
+        $this->calls = [];
         foreach ($calls as $call) {
             $this->addMethodCall($call[0], $call[1]);
         }
@@ -392,12 +340,12 @@ class Definition
      *
      * @throws InvalidArgumentException on empty $method param
      */
-    public function addMethodCall($method, array $arguments = array())
+    public function addMethodCall($method, array $arguments = [])
     {
         if (empty($method)) {
             throw new InvalidArgumentException('Method name cannot be empty.');
         }
-        $this->calls[] = array($method, $arguments);
+        $this->calls[] = [$method, $arguments];
 
         return $this;
     }
@@ -449,6 +397,54 @@ class Definition
         return $this->calls;
     }
 
+    /**
+     * Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class.
+     *
+     * @param ChildDefinition[] $instanceof
+     *
+     * @return $this
+     */
+    public function setInstanceofConditionals(array $instanceof)
+    {
+        $this->instanceof = $instanceof;
+
+        return $this;
+    }
+
+    /**
+     * Gets the definition templates to conditionally apply on the current definition, keyed by parent interface/class.
+     *
+     * @return ChildDefinition[]
+     */
+    public function getInstanceofConditionals()
+    {
+        return $this->instanceof;
+    }
+
+    /**
+     * Sets whether or not instanceof conditionals should be prepended with a global set.
+     *
+     * @param bool $autoconfigured
+     *
+     * @return $this
+     */
+    public function setAutoconfigured($autoconfigured)
+    {
+        $this->changes['autoconfigured'] = true;
+
+        $this->autoconfigured = $autoconfigured;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isAutoconfigured()
+    {
+        return $this->autoconfigured;
+    }
+
     /**
      * Sets tags for this definition.
      *
@@ -480,7 +476,7 @@ class Definition
      */
     public function getTag($name)
     {
-        return isset($this->tags[$name]) ? $this->tags[$name] : array();
+        return isset($this->tags[$name]) ? $this->tags[$name] : [];
     }
 
     /**
@@ -491,7 +487,7 @@ class Definition
      *
      * @return $this
      */
-    public function addTag($name, array $attributes = array())
+    public function addTag($name, array $attributes = [])
     {
         $this->tags[$name][] = $attributes;
 
@@ -531,7 +527,7 @@ class Definition
      */
     public function clearTags()
     {
-        $this->tags = array();
+        $this->tags = [];
 
         return $this;
     }
@@ -545,6 +541,8 @@ class Definition
      */
     public function setFile($file)
     {
+        $this->changes['file'] = true;
+
         $this->file = $file;
 
         return $this;
@@ -569,6 +567,8 @@ class Definition
      */
     public function setShared($shared)
     {
+        $this->changes['shared'] = true;
+
         $this->shared = (bool) $shared;
 
         return $this;
@@ -584,46 +584,6 @@ class Definition
         return $this->shared;
     }
 
-    /**
-     * Sets the scope of the service.
-     *
-     * @param string $scope Whether the service must be shared or not
-     *
-     * @return $this
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function setScope($scope, $triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        if (ContainerInterface::SCOPE_PROTOTYPE === $scope) {
-            $this->setShared(false);
-        }
-
-        $this->scope = $scope;
-
-        return $this;
-    }
-
-    /**
-     * Returns the scope of the service.
-     *
-     * @return string
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function getScope($triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return $this->scope;
-    }
-
     /**
      * Sets the visibility of this service.
      *
@@ -633,7 +593,10 @@ class Definition
      */
     public function setPublic($boolean)
     {
+        $this->changes['public'] = true;
+
         $this->public = (bool) $boolean;
+        $this->private = false;
 
         return $this;
     }
@@ -649,39 +612,32 @@ class Definition
     }
 
     /**
-     * Sets the synchronized flag of this service.
+     * Sets if this service is private.
+     *
+     * When set, the "private" state has a higher precedence than "public".
+     * In version 3.4, a "private" service always remains publicly accessible,
+     * but triggers a deprecation notice when accessed from the container,
+     * so that the service can be made really private in 4.0.
      *
      * @param bool $boolean
      *
      * @return $this
-     *
-     * @deprecated since version 2.7, will be removed in 3.0.
      */
-    public function setSynchronized($boolean, $triggerDeprecationError = true)
+    public function setPrivate($boolean)
     {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        $this->synchronized = (bool) $boolean;
+        $this->private = (bool) $boolean;
 
         return $this;
     }
 
     /**
-     * Whether this service is synchronized.
+     * Whether this service is private.
      *
      * @return bool
-     *
-     * @deprecated since version 2.7, will be removed in 3.0.
      */
-    public function isSynchronized($triggerDeprecationError = true)
+    public function isPrivate()
     {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return $this->synchronized;
+        return $this->private;
     }
 
     /**
@@ -693,6 +649,8 @@ class Definition
      */
     public function setLazy($lazy)
     {
+        $this->changes['lazy'] = true;
+
         $this->lazy = (bool) $lazy;
 
         return $this;
@@ -785,6 +743,8 @@ class Definition
             $this->deprecationTemplate = $template;
         }
 
+        $this->changes['deprecated'] = true;
+
         $this->deprecated = (bool) $status;
 
         return $this;
@@ -816,13 +776,19 @@ class Definition
     /**
      * Sets a configurator to call after the service is fully initialized.
      *
-     * @param callable $callable A PHP callable
+     * @param string|array $configurator A PHP callable
      *
      * @return $this
      */
-    public function setConfigurator($callable)
+    public function setConfigurator($configurator)
     {
-        $this->configurator = $callable;
+        $this->changes['configurator'] = true;
+
+        if (\is_string($configurator) && false !== strpos($configurator, '::')) {
+            $configurator = explode('::', $configurator, 2);
+        }
+
+        $this->configurator = $configurator;
 
         return $this;
     }
@@ -830,7 +796,7 @@ class Definition
     /**
      * Gets the configurator to call after the service is fully initialized.
      *
-     * @return callable|null The PHP callable to call
+     * @return callable|array|null
      */
     public function getConfigurator()
     {
@@ -843,10 +809,14 @@ class Definition
      * @param string[] $types
      *
      * @return $this
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
     public function setAutowiringTypes(array $types)
     {
-        $this->autowiringTypes = array();
+        @trigger_error('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead.', E_USER_DEPRECATED);
+
+        $this->autowiringTypes = [];
 
         foreach ($types as $type) {
             $this->autowiringTypes[$type] = true;
@@ -874,7 +844,9 @@ class Definition
      */
     public function setAutowired($autowired)
     {
-        $this->autowired = $autowired;
+        $this->changes['autowired'] = true;
+
+        $this->autowired = (bool) $autowired;
 
         return $this;
     }
@@ -883,9 +855,15 @@ class Definition
      * Gets autowiring types that will default to this definition.
      *
      * @return string[]
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
-    public function getAutowiringTypes()
+    public function getAutowiringTypes(/*$triggerDeprecation = true*/)
     {
+        if (1 > \func_num_args() || func_get_arg(0)) {
+            @trigger_error('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead.', E_USER_DEPRECATED);
+        }
+
         return array_keys($this->autowiringTypes);
     }
 
@@ -895,9 +873,13 @@ class Definition
      * @param string $type
      *
      * @return $this
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
     public function addAutowiringType($type)
     {
+        @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), E_USER_DEPRECATED);
+
         $this->autowiringTypes[$type] = true;
 
         return $this;
@@ -909,9 +891,13 @@ class Definition
      * @param string $type
      *
      * @return $this
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
     public function removeAutowiringType($type)
     {
+        @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), E_USER_DEPRECATED);
+
         unset($this->autowiringTypes[$type]);
 
         return $this;
@@ -923,9 +909,65 @@ class Definition
      * @param string $type
      *
      * @return bool
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
     public function hasAutowiringType($type)
     {
+        @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), E_USER_DEPRECATED);
+
         return isset($this->autowiringTypes[$type]);
     }
+
+    /**
+     * Gets bindings.
+     *
+     * @return array
+     */
+    public function getBindings()
+    {
+        return $this->bindings;
+    }
+
+    /**
+     * Sets bindings.
+     *
+     * Bindings map $named or FQCN arguments to values that should be
+     * injected in the matching parameters (of the constructor, of methods
+     * called and of controller actions).
+     *
+     * @return $this
+     */
+    public function setBindings(array $bindings)
+    {
+        foreach ($bindings as $key => $binding) {
+            if (!$binding instanceof BoundArgument) {
+                $bindings[$key] = new BoundArgument($binding);
+            }
+        }
+
+        $this->bindings = $bindings;
+
+        return $this;
+    }
+
+    /**
+     * Add an error that occurred when building this Definition.
+     *
+     * @param string $error
+     */
+    public function addError($error)
+    {
+        $this->errors[] = $error;
+    }
+
+    /**
+     * Returns any errors that occurred while building this Definition.
+     *
+     * @return array
+     */
+    public function getErrors()
+    {
+        return $this->errors;
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/DefinitionDecorator.php b/civicrm/vendor/symfony/dependency-injection/DefinitionDecorator.php
index 44e9c0f7d4..99af39e89d 100644
--- a/civicrm/vendor/symfony/dependency-injection/DefinitionDecorator.php
+++ b/civicrm/vendor/symfony/dependency-injection/DefinitionDecorator.php
@@ -11,219 +11,19 @@
 
 namespace Symfony\Component\DependencyInjection;
 
-use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
-use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;
+@trigger_error('The '.__NAMESPACE__.'\DefinitionDecorator class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.', E_USER_DEPRECATED);
 
-/**
- * This definition decorates another definition.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
-class DefinitionDecorator extends Definition
-{
-    private $parent;
-    private $changes = array();
-
-    /**
-     * @param string $parent The id of Definition instance to decorate
-     */
-    public function __construct($parent)
-    {
-        parent::__construct();
-
-        $this->parent = $parent;
-    }
-
-    /**
-     * Returns the Definition being decorated.
-     *
-     * @return string
-     */
-    public function getParent()
-    {
-        return $this->parent;
-    }
-
-    /**
-     * Returns all changes tracked for the Definition object.
-     *
-     * @return array An array of changes for this Definition
-     */
-    public function getChanges()
-    {
-        return $this->changes;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setClass($class)
-    {
-        $this->changes['class'] = true;
-
-        return parent::setClass($class);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setFactory($callable)
-    {
-        $this->changes['factory'] = true;
-
-        return parent::setFactory($callable);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setFactoryClass($class)
-    {
-        $this->changes['factory_class'] = true;
-
-        return parent::setFactoryClass($class);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setFactoryMethod($method)
-    {
-        $this->changes['factory_method'] = true;
-
-        return parent::setFactoryMethod($method);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setFactoryService($service, $triggerDeprecationError = true)
-    {
-        $this->changes['factory_service'] = true;
-
-        return parent::setFactoryService($service, $triggerDeprecationError);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setConfigurator($callable)
-    {
-        $this->changes['configurator'] = true;
-
-        return parent::setConfigurator($callable);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setFile($file)
-    {
-        $this->changes['file'] = true;
-
-        return parent::setFile($file);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setPublic($boolean)
-    {
-        $this->changes['public'] = true;
-
-        return parent::setPublic($boolean);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setLazy($boolean)
-    {
-        $this->changes['lazy'] = true;
-
-        return parent::setLazy($boolean);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setDecoratedService($id, $renamedId = null, $priority = 0)
-    {
-        $this->changes['decorated_service'] = true;
-
-        return parent::setDecoratedService($id, $renamedId, $priority);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setDeprecated($boolean = true, $template = null)
-    {
-        $this->changes['deprecated'] = true;
-
-        return parent::setDeprecated($boolean, $template);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setAutowired($autowired)
-    {
-        $this->changes['autowire'] = true;
-
-        return parent::setAutowired($autowired);
-    }
+class_exists(ChildDefinition::class);
 
+if (false) {
     /**
-     * Gets an argument to pass to the service constructor/factory method.
+     * This definition decorates another definition.
      *
-     * If replaceArgument() has been used to replace an argument, this method
-     * will return the replacement value.
+     * @author Johannes M. Schmitt <schmittjoh@gmail.com>
      *
-     * @param int $index
-     *
-     * @return mixed The argument value
-     *
-     * @throws OutOfBoundsException When the argument does not exist
+     * @deprecated The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.
      */
-    public function getArgument($index)
+    class DefinitionDecorator extends Definition
     {
-        if (array_key_exists('index_'.$index, $this->arguments)) {
-            return $this->arguments['index_'.$index];
-        }
-
-        $lastIndex = \count(array_filter(array_keys($this->arguments), 'is_int')) - 1;
-
-        if ($index < 0 || $index > $lastIndex) {
-            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, $lastIndex));
-        }
-
-        return $this->arguments[$index];
-    }
-
-    /**
-     * You should always use this method when overwriting existing arguments
-     * of the parent definition.
-     *
-     * If you directly call setArguments() keep in mind that you must follow
-     * certain conventions when you want to overwrite the arguments of the
-     * parent definition, otherwise your arguments will only be appended.
-     *
-     * @param int   $index
-     * @param mixed $value
-     *
-     * @return $this
-     *
-     * @throws InvalidArgumentException when $index isn't an integer
-     */
-    public function replaceArgument($index, $value)
-    {
-        if (!\is_int($index)) {
-            throw new InvalidArgumentException('$index must be an integer.');
-        }
-
-        $this->arguments['index_'.$index] = $value;
-
-        return $this;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Dumper/DumperInterface.php b/civicrm/vendor/symfony/dependency-injection/Dumper/DumperInterface.php
index dd001e4ed0..8abc19250f 100644
--- a/civicrm/vendor/symfony/dependency-injection/Dumper/DumperInterface.php
+++ b/civicrm/vendor/symfony/dependency-injection/Dumper/DumperInterface.php
@@ -21,9 +21,7 @@ interface DumperInterface
     /**
      * Dumps the service container.
      *
-     * @param array $options An array of options
-     *
-     * @return string The representation of the service container
+     * @return string|array The representation of the service container
      */
-    public function dump(array $options = array());
+    public function dump(array $options = []);
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php b/civicrm/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php
index dfb0dee193..0591e024f5 100644
--- a/civicrm/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php
+++ b/civicrm/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php
@@ -11,14 +11,13 @@
 
 namespace Symfony\Component\DependencyInjection\Dumper;
 
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\Scope;
 
 /**
  * GraphvizDumper dumps a service container as a graphviz file.
@@ -33,14 +32,15 @@ class GraphvizDumper extends Dumper
 {
     private $nodes;
     private $edges;
-    private $options = array(
-            'graph' => array('ratio' => 'compress'),
-            'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'),
-            'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5),
-            'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'),
-            'node.definition' => array('fillcolor' => '#eeeeee'),
-            'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'),
-        );
+    // All values should be strings
+    private $options = [
+            'graph' => ['ratio' => 'compress'],
+            'node' => ['fontsize' => '11', 'fontname' => 'Arial', 'shape' => 'record'],
+            'edge' => ['fontsize' => '9', 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => '0.5'],
+            'node.instance' => ['fillcolor' => '#9999ff', 'style' => 'filled'],
+            'node.definition' => ['fillcolor' => '#eeeeee'],
+            'node.missing' => ['fillcolor' => '#ff9999', 'style' => 'filled'],
+        ];
 
     /**
      * Dumps the service container as a graphviz graph.
@@ -56,9 +56,9 @@ class GraphvizDumper extends Dumper
      *
      * @return string The dot representation of the service container
      */
-    public function dump(array $options = array())
+    public function dump(array $options = [])
     {
-        foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) {
+        foreach (['graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing'] as $key) {
             if (isset($options[$key])) {
                 $this->options[$key] = array_merge($this->options[$key], $options[$key]);
             }
@@ -66,7 +66,7 @@ class GraphvizDumper extends Dumper
 
         $this->nodes = $this->findNodes();
 
-        $this->edges = array();
+        $this->edges = [];
         foreach ($this->container->getDefinitions() as $id => $definition) {
             $this->edges[$id] = array_merge(
                 $this->findEdges($id, $definition->getArguments(), true, ''),
@@ -81,7 +81,7 @@ class GraphvizDumper extends Dumper
             }
         }
 
-        return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot();
+        return $this->container->resolveEnvPlaceholders($this->startDot().$this->addNodes().$this->addEdges().$this->endDot(), '__ENV_%s__');
     }
 
     /**
@@ -111,7 +111,7 @@ class GraphvizDumper extends Dumper
         $code = '';
         foreach ($this->edges as $id => $edges) {
             foreach ($edges as $edge) {
-                $code .= sprintf("  node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed');
+                $code .= sprintf("  node_%s -> node_%s [label=\"%s\" style=\"%s\"%s];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed', $edge['lazy'] ? ' color="#9999ff"' : '');
             }
         }
 
@@ -128,9 +128,9 @@ class GraphvizDumper extends Dumper
      *
      * @return array An array of edges
      */
-    private function findEdges($id, array $arguments, $required, $name)
+    private function findEdges($id, array $arguments, $required, $name, $lazy = false)
     {
-        $edges = array();
+        $edges = [];
         foreach ($arguments as $argument) {
             if ($argument instanceof Parameter) {
                 $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null;
@@ -139,13 +139,27 @@ class GraphvizDumper extends Dumper
             }
 
             if ($argument instanceof Reference) {
+                $lazyEdge = $lazy;
+
                 if (!$this->container->has((string) $argument)) {
-                    $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']);
+                    $this->nodes[(string) $argument] = ['name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']];
+                } elseif ('service_container' !== (string) $argument) {
+                    $lazyEdge = $lazy || $this->container->getDefinition((string) $argument)->isLazy();
                 }
 
-                $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument);
+                $edges[] = ['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge];
+            } elseif ($argument instanceof ArgumentInterface) {
+                $edges = array_merge($edges, $this->findEdges($id, $argument->getValues(), $required, $name, true));
+            } elseif ($argument instanceof Definition) {
+                $edges = array_merge($edges,
+                    $this->findEdges($id, $argument->getArguments(), $required, ''),
+                    $this->findEdges($id, $argument->getProperties(), false, '')
+                );
+                foreach ($argument->getMethodCalls() as $call) {
+                    $edges = array_merge($edges, $this->findEdges($id, $call[1], false, $call[0].'()'));
+                }
             } elseif (\is_array($argument)) {
-                $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name));
+                $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name, $lazy));
             }
         }
 
@@ -159,7 +173,7 @@ class GraphvizDumper extends Dumper
      */
     private function findNodes()
     {
-        $nodes = array();
+        $nodes = [];
 
         $container = $this->cloneContainer();
 
@@ -175,20 +189,17 @@ class GraphvizDumper extends Dumper
             } catch (ParameterNotFoundException $e) {
             }
 
-            $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], array('style' => $definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope(false) ? 'filled' : 'dotted')));
+            $nodes[$id] = ['class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], ['style' => $definition->isShared() ? 'filled' : 'dotted'])];
             $container->setDefinition($id, new Definition('stdClass'));
         }
 
         foreach ($container->getServiceIds() as $id) {
-            $service = $container->get($id);
-
-            if (array_key_exists($id, $container->getAliases())) {
+            if (\array_key_exists($id, $container->getAliases())) {
                 continue;
             }
 
             if (!$container->hasDefinition($id)) {
-                $class = ('service_container' === $id) ? \get_class($this->container) : \get_class($service);
-                $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']);
+                $nodes[$id] = ['class' => str_replace('\\', '\\\\', \get_class($container->get($id))), 'attributes' => $this->options['node.instance']];
             }
         }
 
@@ -203,9 +214,6 @@ class GraphvizDumper extends Dumper
         $container->setDefinitions($this->container->getDefinitions());
         $container->setAliases($this->container->getAliases());
         $container->setResources($this->container->getResources());
-        foreach ($this->container->getScopes(false) as $scope => $parentScope) {
-            $container->addScope(new Scope($scope, $parentScope));
-        }
         foreach ($this->container->getExtensions() as $extension) {
             $container->registerExtension($extension);
         }
@@ -246,7 +254,7 @@ class GraphvizDumper extends Dumper
      */
     private function addAttributes(array $attributes)
     {
-        $code = array();
+        $code = [];
         foreach ($attributes as $k => $v) {
             $code[] = sprintf('%s="%s"', $k, $v);
         }
@@ -263,7 +271,7 @@ class GraphvizDumper extends Dumper
      */
     private function addOptions(array $options)
     {
-        $code = array();
+        $code = [];
         foreach ($options as $k => $v) {
             $code[] = sprintf('%s="%s"', $k, $v);
         }
@@ -292,7 +300,7 @@ class GraphvizDumper extends Dumper
      */
     private function getAliases($id)
     {
-        $aliases = array();
+        $aliases = [];
         foreach ($this->container->getAliases() as $alias => $origin) {
             if ($id == $origin) {
                 $aliases[] = $alias;
diff --git a/civicrm/vendor/symfony/dependency-injection/Dumper/PhpDumper.php b/civicrm/vendor/symfony/dependency-injection/Dumper/PhpDumper.php
index 2f530e9e3e..3bfa0c3188 100644
--- a/civicrm/vendor/symfony/dependency-injection/Dumper/PhpDumper.php
+++ b/civicrm/vendor/symfony/dependency-injection/Dumper/PhpDumper.php
@@ -11,10 +11,16 @@
 
 namespace Symfony\Component\DependencyInjection\Dumper;
 
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
+use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;
 use Symfony\Component\DependencyInjection\Container;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
@@ -23,9 +29,9 @@ use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as
 use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
 use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\TypedReference;
 use Symfony\Component\DependencyInjection\Variable;
 use Symfony\Component\ExpressionLanguage\Expression;
-use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
 use Symfony\Component\HttpKernel\Kernel;
 
 /**
@@ -46,20 +52,24 @@ class PhpDumper extends Dumper
      */
     const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';
 
-    private $inlinedDefinitions;
     private $definitionVariables;
     private $referenceVariables;
     private $variableCount;
-    private $reservedVariables = array('instance', 'class');
+    private $inlinedDefinitions;
+    private $serviceCalls;
+    private $reservedVariables = ['instance', 'class', 'this'];
     private $expressionLanguage;
     private $targetDirRegex;
     private $targetDirMaxMatches;
     private $docStar;
-
-    /**
-     * @var ExpressionFunctionProviderInterface[]
-     */
-    private $expressionLanguageProviders = array();
+    private $serviceIdToMethodNameMap;
+    private $usedMethodNames;
+    private $namespace;
+    private $asFiles;
+    private $hotPathTag;
+    private $inlineRequires;
+    private $inlinedRequires = [];
+    private $circularReferences = [];
 
     /**
      * @var ProxyDumper
@@ -71,9 +81,11 @@ class PhpDumper extends Dumper
      */
     public function __construct(ContainerBuilder $container)
     {
-        parent::__construct($container);
+        if (!$container->isCompiled()) {
+            @trigger_error('Dumping an uncompiled ContainerBuilder is deprecated since Symfony 3.3 and will not be supported anymore in 4.0. Compile the container beforehand.', E_USER_DEPRECATED);
+        }
 
-        $this->inlinedDefinitions = new \SplObjectStorage();
+        parent::__construct($container);
     }
 
     /**
@@ -92,31 +104,83 @@ class PhpDumper extends Dumper
      *  * class:      The class name
      *  * base_class: The base class name
      *  * namespace:  The class namespace
+     *  * as_files:   To split the container in several files
+     *
+     * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set
      *
-     * @return string A PHP class representing of the service container
+     * @throws EnvParameterException When an env var exists but has not been dumped
      */
-    public function dump(array $options = array())
+    public function dump(array $options = [])
     {
         $this->targetDirRegex = null;
-        $options = array_merge(array(
+        $this->inlinedRequires = [];
+        $options = array_merge([
             'class' => 'ProjectServiceContainer',
             'base_class' => 'Container',
             'namespace' => '',
+            'as_files' => false,
             'debug' => true,
-        ), $options);
+            'hot_path_tag' => 'container.hot_path',
+            'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
+            'build_time' => time(),
+        ], $options);
+
+        $this->namespace = $options['namespace'];
+        $this->asFiles = $options['as_files'];
+        $this->hotPathTag = $options['hot_path_tag'];
+        $this->inlineRequires = $options['inline_class_loader_parameter'] && $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']);
+
+        if (0 !== strpos($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) {
+            $baseClass = sprintf('%s\%s', $options['namespace'] ? '\\'.$options['namespace'] : '', $baseClass);
+            $baseClassWithNamespace = $baseClass;
+        } elseif ('Container' === $baseClass) {
+            $baseClassWithNamespace = Container::class;
+        } else {
+            $baseClassWithNamespace = $baseClass;
+        }
+
+        $this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
+
+        if ($this->getProxyDumper() instanceof NullDumper) {
+            (new AnalyzeServiceReferencesPass(true, false))->process($this->container);
+            try {
+                (new CheckCircularReferencesPass())->process($this->container);
+            } catch (ServiceCircularReferenceException $e) {
+                $path = $e->getPath();
+                end($path);
+                $path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge';
+
+                throw new ServiceCircularReferenceException($e->getServiceId(), $path);
+            }
+        }
+
+        (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container);
+        $checkedNodes = [];
+        $this->circularReferences = [];
+        foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
+            if (!$node->getValue() instanceof Definition) {
+                continue;
+            }
+            if (!isset($checkedNodes[$id])) {
+                $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes);
+            }
+        }
+        $this->container->getCompiler()->getServiceReferenceGraph()->clear();
+        $checkedNodes = [];
+
         $this->docStar = $options['debug'] ? '*' : '';
 
         if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) {
             // Build a regexp where the first root dirs are mandatory,
             // but every other sub-dir is optional up to the full path in $dir
-            // Mandate at least 2 root dirs and not more that 5 optional dirs.
+            // Mandate at least 1 root dir and not more than 5 optional dirs.
 
             $dir = explode(\DIRECTORY_SEPARATOR, realpath($dir));
             $i = \count($dir);
 
-            if (3 <= $i) {
+            if (2 + (int) ('\\' === \DIRECTORY_SEPARATOR) <= $i) {
                 $regex = '';
-                $lastOptionalDir = $i > 8 ? $i - 5 : 3;
+                $lastOptionalDir = $i > 8 ? $i - 5 : (2 + (int) ('\\' === \DIRECTORY_SEPARATOR));
                 $this->targetDirMaxMatches = $i - $lastOptionalDir;
 
                 while (--$i >= $lastOptionalDir) {
@@ -131,23 +195,95 @@ class PhpDumper extends Dumper
             }
         }
 
-        $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']);
+        $code =
+            $this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
+            $this->addServices().
+            $this->addDefaultParametersMethod().
+            $this->endClass()
+        ;
+
+        if ($this->asFiles) {
+            $fileStart = <<<EOF
+<?php
+
+use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
+
+// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
+
+EOF;
+            $files = [];
+
+            if ($ids = array_keys($this->container->getRemovedIds())) {
+                sort($ids);
+                $c = "<?php\n\nreturn [\n";
+                foreach ($ids as $id) {
+                    $c .= '    '.$this->doExport($id)." => true,\n";
+                }
+                $files['removed-ids.php'] = $c."];\n";
+            }
+
+            foreach ($this->generateServiceFiles() as $file => $c) {
+                $files[$file] = $fileStart.$c;
+            }
+            foreach ($this->generateProxyClasses() as $file => $c) {
+                $files[$file] = "<?php\n".$c;
+            }
+            $files[$options['class'].'.php'] = $code;
+            $hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx'));
+            $code = [];
+
+            foreach ($files as $file => $c) {
+                $code["Container{$hash}/{$file}"] = $c;
+            }
+            array_pop($code);
+            $code["Container{$hash}/{$options['class']}.php"] = substr_replace($files[$options['class'].'.php'], "<?php\n\nnamespace Container{$hash};\n", 0, 6);
+            $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
+            $time = $options['build_time'];
+            $id = hash('crc32', $hash.$time);
 
-        if ($this->container->isFrozen()) {
-            $code .= $this->addFrozenConstructor();
-            $code .= $this->addFrozenCompile();
-            $code .= $this->addIsFrozenMethod();
+            $code[$options['class'].'.php'] = <<<EOF
+<?php
+{$namespaceLine}
+// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
+
+if (\\class_exists(\\Container{$hash}\\{$options['class']}::class, false)) {
+    // no-op
+} elseif (!include __DIR__.'/Container{$hash}/{$options['class']}.php') {
+    touch(__DIR__.'/Container{$hash}.legacy');
+
+    return;
+}
+
+if (!\\class_exists({$options['class']}::class, false)) {
+    \\class_alias(\\Container{$hash}\\{$options['class']}::class, {$options['class']}::class, false);
+}
+
+return new \\Container{$hash}\\{$options['class']}([
+    'container.build_hash' => '$hash',
+    'container.build_id' => '$id',
+    'container.build_time' => $time,
+], __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}');
+
+EOF;
         } else {
-            $code .= $this->addConstructor();
+            foreach ($this->generateProxyClasses() as $c) {
+                $code .= $c;
+            }
         }
 
-        $code .=
-            $this->addServices().
-            $this->addDefaultParametersMethod().
-            $this->endClass().
-            $this->addProxyClasses()
-        ;
         $this->targetDirRegex = null;
+        $this->inlinedRequires = [];
+        $this->circularReferences = [];
+
+        $unusedEnvs = [];
+        foreach ($this->container->getEnvCounters() as $env => $use) {
+            if (!$use) {
+                $unusedEnvs[] = $env;
+            }
+        }
+        if ($unusedEnvs) {
+            throw new EnvParameterException($unusedEnvs, null, 'Environment variables "%s" are never used. Please, check your container\'s configuration.');
+        }
 
         return $code;
     }
@@ -166,84 +302,123 @@ class PhpDumper extends Dumper
         return $this->proxyDumper;
     }
 
-    /**
-     * Generates Service local temp variables.
-     *
-     * @param string $cId
-     * @param string $definition
-     *
-     * @return string
-     */
-    private function addServiceLocalTempVariables($cId, $definition)
+    private function analyzeCircularReferences($sourceId, array $edges, &$checkedNodes, &$currentPath = [], $byConstructor = true)
     {
-        static $template = "        \$%s = %s;\n";
+        $checkedNodes[$sourceId] = true;
+        $currentPath[$sourceId] = $byConstructor;
+
+        foreach ($edges as $edge) {
+            $node = $edge->getDestNode();
+            $id = $node->getId();
+
+            if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) {
+                // no-op
+            } elseif (isset($currentPath[$id])) {
+                $this->addCircularReferences($id, $currentPath, $edge->isReferencedByConstructor());
+            } elseif (!isset($checkedNodes[$id])) {
+                $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes, $currentPath, $edge->isReferencedByConstructor());
+            } elseif (isset($this->circularReferences[$id])) {
+                $this->connectCircularReferences($id, $currentPath, $edge->isReferencedByConstructor());
+            }
+        }
+        unset($currentPath[$sourceId]);
+    }
 
-        $localDefinitions = array_merge(
-            array($definition),
-            $this->getInlinedDefinitions($definition)
-        );
+    private function connectCircularReferences($sourceId, &$currentPath, $byConstructor, &$subPath = [])
+    {
+        $currentPath[$sourceId] = $subPath[$sourceId] = $byConstructor;
 
-        $calls = $behavior = array();
-        foreach ($localDefinitions as $iDefinition) {
-            $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior);
-            $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
-            $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
-            $this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior);
-            $this->getServiceCallsFromArguments(array($iDefinition->getFactory()), $calls, $behavior);
+        foreach ($this->circularReferences[$sourceId] as $id => $byConstructor) {
+            if (isset($currentPath[$id])) {
+                $this->addCircularReferences($id, $currentPath, $byConstructor);
+            } elseif (!isset($subPath[$id]) && isset($this->circularReferences[$id])) {
+                $this->connectCircularReferences($id, $currentPath, $byConstructor, $subPath);
+            }
         }
+        unset($currentPath[$sourceId], $subPath[$sourceId]);
+    }
 
-        $code = '';
-        foreach ($calls as $id => $callCount) {
-            if ('service_container' === $id || $id === $cId) {
-                continue;
-            }
+    private function addCircularReferences($id, $currentPath, $byConstructor)
+    {
+        $currentPath[$id] = $byConstructor;
+        $circularRefs = [];
 
-            if ($callCount > 1) {
-                $name = $this->getNextVariableName();
-                $this->referenceVariables[$id] = new Variable($name);
+        foreach (array_reverse($currentPath) as $parentId => $v) {
+            $byConstructor = $byConstructor && $v;
+            $circularRefs[] = $parentId;
 
-                if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) {
-                    $code .= sprintf($template, $name, $this->getServiceCall($id));
-                } else {
-                    $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)));
-                }
+            if ($parentId === $id) {
+                break;
             }
         }
 
-        if ('' !== $code) {
-            $code .= "\n";
+        $currentId = $id;
+        foreach ($circularRefs as $parentId) {
+            if (empty($this->circularReferences[$parentId][$currentId])) {
+                $this->circularReferences[$parentId][$currentId] = $byConstructor;
+            }
+
+            $currentId = $parentId;
         }
+    }
 
-        return $code;
+    private function collectLineage($class, array &$lineage)
+    {
+        if (isset($lineage[$class])) {
+            return;
+        }
+        if (!$r = $this->container->getReflectionClass($class, false)) {
+            return;
+        }
+        if ($this->container instanceof $class) {
+            return;
+        }
+        $file = $r->getFileName();
+        if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) {
+            return;
+        }
+
+        if ($parent = $r->getParentClass()) {
+            $this->collectLineage($parent->name, $lineage);
+        }
+
+        foreach ($r->getInterfaces() as $parent) {
+            $this->collectLineage($parent->name, $lineage);
+        }
+
+        foreach ($r->getTraits() as $parent) {
+            $this->collectLineage($parent->name, $lineage);
+        }
+
+        $lineage[$class] = substr($exportedFile, 1, -1);
     }
 
-    /**
-     * Generates code for the proxies to be attached after the container class.
-     *
-     * @return string
-     */
-    private function addProxyClasses()
+    private function generateProxyClasses()
     {
-        /* @var $definitions Definition[] */
-        $definitions = array_filter(
-            $this->container->getDefinitions(),
-            array($this->getProxyDumper(), 'isProxyCandidate')
-        );
-        $code = '';
+        $alreadyGenerated = [];
+        $definitions = $this->container->getDefinitions();
         $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments');
-
+        $proxyDumper = $this->getProxyDumper();
+        ksort($definitions);
         foreach ($definitions as $definition) {
-            if ("\n" === $proxyCode = "\n".$this->getProxyDumper()->getProxyCode($definition)) {
+            if (!$proxyDumper->isProxyCandidate($definition)) {
+                continue;
+            }
+            if (isset($alreadyGenerated[$class = $definition->getClass()])) {
+                continue;
+            }
+            $alreadyGenerated[$class] = true;
+            // register class' reflector for resource tracking
+            $this->container->getReflectionClass($class);
+            if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) {
                 continue;
             }
             if ($strip) {
                 $proxyCode = "<?php\n".$proxyCode;
                 $proxyCode = substr(Kernel::stripComments($proxyCode), 5);
             }
-            $code .= $proxyCode;
+            yield sprintf('%s.php', explode(' ', $proxyCode, 3)[1]) => $proxyCode;
         }
-
-        return $code;
     }
 
     /**
@@ -251,173 +426,121 @@ class PhpDumper extends Dumper
      *
      * @return string
      */
-    private function addServiceInclude(Definition $definition)
+    private function addServiceInclude($cId, Definition $definition)
     {
-        $template = "        require_once %s;\n";
         $code = '';
 
-        if (null !== $file = $definition->getFile()) {
-            $code .= sprintf($template, $this->dumpValue($file));
-        }
-
-        foreach ($this->getInlinedDefinitions($definition) as $definition) {
-            if (null !== $file = $definition->getFile()) {
-                $code .= sprintf($template, $this->dumpValue($file));
+        if ($this->inlineRequires && !$this->isHotPath($definition)) {
+            $lineage = [];
+            foreach ($this->inlinedDefinitions as $def) {
+                if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
+                    $this->collectLineage($class, $lineage);
+                }
             }
-        }
-
-        if ('' !== $code) {
-            $code .= "\n";
-        }
 
-        return $code;
-    }
-
-    /**
-     * Generates the inline definition of a service.
-     *
-     * @param string     $id
-     * @param Definition $definition
-     *
-     * @return string
-     *
-     * @throws RuntimeException                  When the factory definition is incomplete
-     * @throws ServiceCircularReferenceException When a circular reference is detected
-     */
-    private function addServiceInlinedDefinitions($id, Definition $definition)
-    {
-        $code = '';
-        $variableMap = $this->definitionVariables;
-        $nbOccurrences = new \SplObjectStorage();
-        $processed = new \SplObjectStorage();
-        $inlinedDefinitions = $this->getInlinedDefinitions($definition);
-
-        foreach ($inlinedDefinitions as $definition) {
-            if (false === $nbOccurrences->contains($definition)) {
-                $nbOccurrences->offsetSet($definition, 1);
-            } else {
-                $i = $nbOccurrences->offsetGet($definition);
-                $nbOccurrences->offsetSet($definition, $i + 1);
+            foreach ($this->serviceCalls as $id => list($callCount, $behavior)) {
+                if ('service_container' !== $id && $id !== $cId
+                    && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior
+                    && $this->container->has($id)
+                    && $this->isTrivialInstance($def = $this->container->findDefinition($id))
+                    && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())
+                ) {
+                    $this->collectLineage($class, $lineage);
+                }
             }
-        }
 
-        foreach ($inlinedDefinitions as $sDefinition) {
-            if ($processed->contains($sDefinition)) {
-                continue;
+            foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
+                $code .= sprintf("        include_once %s;\n", $file);
             }
-            $processed->offsetSet($sDefinition);
-
-            $class = $this->dumpValue($sDefinition->getClass());
-            if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) {
-                $name = $this->getNextVariableName();
-                $variableMap->offsetSet($sDefinition, new Variable($name));
-
-                // a construct like:
-                // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a);
-                // this is an indication for a wrong implementation, you can circumvent this problem
-                // by setting up your service structure like this:
-                // $b = new ServiceB();
-                // $a = new ServiceA(ServiceB $b);
-                // $b->setServiceA(ServiceA $a);
-                if ($this->hasReference($id, $sDefinition->getArguments())) {
-                    throw new ServiceCircularReferenceException($id, array($id));
-                }
-
-                $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');
-
-                if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
-                    $code .= $this->addServiceProperties($sDefinition, $name);
-                    $code .= $this->addServiceMethodCalls($sDefinition, $name);
-                    $code .= $this->addServiceConfigurator($sDefinition, $name);
-                }
+        }
 
-                $code .= "\n";
+        foreach ($this->inlinedDefinitions as $def) {
+            if ($file = $def->getFile()) {
+                $code .= sprintf("        include_once %s;\n", $this->dumpValue($file));
             }
         }
 
-        return $code;
-    }
-
-    /**
-     * Adds the service return statement.
-     *
-     * @param string     $id         Service id
-     * @param Definition $definition
-     *
-     * @return string
-     */
-    private function addServiceReturn($id, Definition $definition)
-    {
-        if ($this->isSimpleInstance($id, $definition)) {
-            return "    }\n";
+        if ('' !== $code) {
+            $code .= "\n";
         }
 
-        return "\n        return \$instance;\n    }\n";
+        return $code;
     }
 
     /**
      * Generates the service instance.
      *
-     * @param string     $id
-     * @param Definition $definition
+     * @param string $id
+     * @param bool   $isSimpleInstance
      *
      * @return string
      *
      * @throws InvalidArgumentException
      * @throws RuntimeException
      */
-    private function addServiceInstance($id, Definition $definition)
+    private function addServiceInstance($id, Definition $definition, $isSimpleInstance)
     {
         $class = $this->dumpValue($definition->getClass());
 
-        if (0 === strpos($class, "'") && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
+        if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
             throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
         }
 
-        $simple = $this->isSimpleInstance($id, $definition);
         $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
         $instantiation = '';
 
-        if (!$isProxyCandidate && $definition->isShared() && ContainerInterface::SCOPE_CONTAINER === $definition->getScope(false)) {
-            $instantiation = sprintf('$this->services[%s] = %s', var_export($id, true), $simple ? '' : '$instance');
-        } elseif (!$isProxyCandidate && $definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope(false)) {
-            $instantiation = sprintf('$this->services[%s] = $this->scopedServices[%s][%1$s] = %s', var_export($id, true), var_export($scope, true), $simple ? '' : '$instance');
-        } elseif (!$simple) {
+        if (!$isProxyCandidate && $definition->isShared()) {
+            $instantiation = sprintf('$this->services[%s] = %s', $this->doExport($id), $isSimpleInstance ? '' : '$instance');
+        } elseif (!$isSimpleInstance) {
             $instantiation = '$instance';
         }
 
         $return = '';
-        if ($simple) {
+        if ($isSimpleInstance) {
             $return = 'return ';
         } else {
             $instantiation .= ' = ';
         }
 
-        $code = $this->addNewInstance($id, $definition, $return, $instantiation);
-
-        if (!$simple) {
-            $code .= "\n";
-        }
-
-        return $code;
+        return $this->addNewInstance($definition, $return, $instantiation, $id);
     }
 
     /**
-     * Checks if the definition is a simple instance.
-     *
-     * @param string     $id
-     * @param Definition $definition
+     * Checks if the definition is a trivial instance.
      *
      * @return bool
      */
-    private function isSimpleInstance($id, Definition $definition)
+    private function isTrivialInstance(Definition $definition)
     {
-        foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) {
-            if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) {
+        if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) {
+            return false;
+        }
+        if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < \count($definition->getArguments())) {
+            return false;
+        }
+
+        foreach ($definition->getArguments() as $arg) {
+            if (!$arg || $arg instanceof Parameter) {
                 continue;
             }
-
-            if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) {
+            if (\is_array($arg) && 3 >= \count($arg)) {
+                foreach ($arg as $k => $v) {
+                    if ($this->dumpValue($k) !== $this->dumpValue($k, false)) {
+                        return false;
+                    }
+                    if (!$v || $v instanceof Parameter) {
+                        continue;
+                    }
+                    if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) {
+                        continue;
+                    }
+                    if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) {
+                        return false;
+                    }
+                }
+            } elseif ($arg instanceof Reference && $this->container->has($id = (string) $arg) && $this->container->findDefinition($id)->isSynthetic()) {
+                continue;
+            } elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) {
                 return false;
             }
         }
@@ -428,8 +551,7 @@ class PhpDumper extends Dumper
     /**
      * Adds method calls to a service definition.
      *
-     * @param Definition $definition
-     * @param string     $variableName
+     * @param string $variableName
      *
      * @return string
      */
@@ -437,7 +559,7 @@ class PhpDumper extends Dumper
     {
         $calls = '';
         foreach ($definition->getMethodCalls() as $call) {
-            $arguments = array();
+            $arguments = [];
             foreach ($call[1] as $value) {
                 $arguments[] = $this->dumpValue($value);
             }
@@ -458,56 +580,10 @@ class PhpDumper extends Dumper
         return $code;
     }
 
-    /**
-     * Generates the inline definition setup.
-     *
-     * @param string     $id
-     * @param Definition $definition
-     *
-     * @return string
-     *
-     * @throws ServiceCircularReferenceException when the container contains a circular reference
-     */
-    private function addServiceInlinedDefinitionsSetup($id, Definition $definition)
-    {
-        $this->referenceVariables[$id] = new Variable('instance');
-
-        $code = '';
-        $processed = new \SplObjectStorage();
-        foreach ($this->getInlinedDefinitions($definition) as $iDefinition) {
-            if ($processed->contains($iDefinition)) {
-                continue;
-            }
-            $processed->offsetSet($iDefinition);
-
-            if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) {
-                continue;
-            }
-
-            // if the instance is simple, the return statement has already been generated
-            // so, the only possible way to get there is because of a circular reference
-            if ($this->isSimpleInstance($id, $definition)) {
-                throw new ServiceCircularReferenceException($id, array($id));
-            }
-
-            $name = (string) $this->definitionVariables->offsetGet($iDefinition);
-            $code .= $this->addServiceProperties($iDefinition, $name);
-            $code .= $this->addServiceMethodCalls($iDefinition, $name);
-            $code .= $this->addServiceConfigurator($iDefinition, $name);
-        }
-
-        if ('' !== $code) {
-            $code .= "\n";
-        }
-
-        return $code;
-    }
-
     /**
      * Adds configurator definition.
      *
-     * @param Definition $definition
-     * @param string     $variableName
+     * @param string $variableName
      *
      * @return string
      */
@@ -519,17 +595,22 @@ class PhpDumper extends Dumper
 
         if (\is_array($callable)) {
             if ($callable[0] instanceof Reference
-                || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
+                || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))
+            ) {
                 return sprintf("        %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
             }
 
             $class = $this->dumpValue($callable[0]);
             // If the class is a string we can optimize call_user_func away
-            if (0 === strpos($class, "'")) {
+            if (0 === strpos($class, "'") && false === strpos($class, '$')) {
                 return sprintf("        %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName);
             }
 
-            return sprintf("        call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
+            if (0 === strpos($class, 'new ')) {
+                return sprintf("        (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
+            }
+
+            return sprintf("        \\call_user_func([%s, '%s'], \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
         }
 
         return sprintf("        %s(\$%s);\n", $callable, $variableName);
@@ -538,46 +619,32 @@ class PhpDumper extends Dumper
     /**
      * Adds a service.
      *
-     * @param string     $id
-     * @param Definition $definition
+     * @param string $id
+     * @param string &$file
      *
      * @return string
      */
-    private function addService($id, Definition $definition)
+    private function addService($id, Definition $definition, &$file = null)
     {
         $this->definitionVariables = new \SplObjectStorage();
-        $this->referenceVariables = array();
+        $this->referenceVariables = [];
         $this->variableCount = 0;
+        $this->referenceVariables[$id] = new Variable('instance');
 
-        $return = array();
+        $return = [];
 
-        if ($definition->isSynthetic()) {
-            $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
-        } elseif ($class = $definition->getClass()) {
+        if ($class = $definition->getClass()) {
+            $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class);
             $return[] = sprintf(0 === strpos($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\'));
         } elseif ($definition->getFactory()) {
             $factory = $definition->getFactory();
             if (\is_string($factory)) {
                 $return[] = sprintf('@return object An instance returned by %s()', $factory);
             } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
-                if (\is_string($factory[0]) || $factory[0] instanceof Reference) {
-                    $return[] = sprintf('@return object An instance returned by %s::%s()', (string) $factory[0], $factory[1]);
-                } elseif ($factory[0] instanceof Definition) {
-                    $return[] = sprintf('@return object An instance returned by %s::%s()', $factory[0]->getClass(), $factory[1]);
-                }
+                $class = $factory[0] instanceof Definition ? $factory[0]->getClass() : (string) $factory[0];
+                $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class);
+                $return[] = sprintf('@return object An instance returned by %s::%s()', $class, $factory[1]);
             }
-        } elseif ($definition->getFactoryClass(false)) {
-            $return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryClass(false), $definition->getFactoryMethod(false));
-        } elseif ($definition->getFactoryService(false)) {
-            $return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryService(false), $definition->getFactoryMethod(false));
-        }
-
-        $scope = $definition->getScope(false);
-        if (!\in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
-            if ($return && 0 === strpos($return[\count($return) - 1], '@return')) {
-                $return[] = '';
-            }
-            $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope);
         }
 
         if ($definition->isDeprecated()) {
@@ -589,8 +656,9 @@ class PhpDumper extends Dumper
         }
 
         $return = str_replace("\n     * \n", "\n     *\n", implode("\n     * ", $return));
+        $return = $this->container->resolveEnvPlaceholders($return);
 
-        $shared = $definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope ? ' shared' : '';
+        $shared = $definition->isShared() ? ' shared' : '';
         $public = $definition->isPublic() ? 'public' : 'private';
         $autowired = $definition->isAutowired() ? ' autowired' : '';
 
@@ -600,10 +668,13 @@ class PhpDumper extends Dumper
             $lazyInitialization = '';
         }
 
-        // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
-        $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
-        $visibility = $isProxyCandidate ? 'public' : 'protected';
-        $code = <<<EOF
+        $asFile = $this->asFiles && $definition->isShared() && !$this->isHotPath($definition);
+        $methodName = $this->generateMethodName($id);
+        if ($asFile) {
+            $file = $methodName.'.php';
+            $code = "        // Returns the $public '$id'$shared$autowired service.\n\n";
+        } else {
+            $code = <<<EOF
 
     /*{$this->docStar}
      * Gets the $public '$id'$shared$autowired service.
@@ -613,137 +684,209 @@ EOF;
             $code = str_replace('*/', ' ', $code).<<<EOF
 
      */
-    {$visibility} function get{$this->camelize($id)}Service($lazyInitialization)
+    protected function {$methodName}($lazyInitialization)
     {
 
 EOF;
+        }
 
-        $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : '';
+        $this->serviceCalls = [];
+        $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);
 
-        if (!\in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
-            $code .= <<<EOF
-        if (!isset(\$this->scopedServices['$scope'])) {
-            throw new InactiveScopeException({$this->export($id)}, '$scope');
-        }
+        $code .= $this->addServiceInclude($id, $definition);
 
+        if ($this->getProxyDumper()->isProxyCandidate($definition)) {
+            $factoryCode = $asFile ? "\$this->load('%s.php', false)" : '$this->%s(false)';
+            $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id)));
+        }
 
-EOF;
+        if ($definition->isDeprecated()) {
+            $code .= sprintf("        @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
         }
 
-        if ($definition->isSynthetic()) {
-            $code .= sprintf("        throw new RuntimeException(%s);\n    }\n", var_export("You have requested a synthetic service (\"$id\"). The DIC does not know how to construct this service.", true));
-        } else {
-            if ($definition->isDeprecated()) {
-                $code .= sprintf("        @trigger_error(%s, E_USER_DEPRECATED);\n\n", var_export($definition->getDeprecationMessage($id), true));
-            }
+        $code .= $this->addInlineService($id, $definition);
 
-            $code .=
-                $this->addServiceInclude($definition).
-                $this->addServiceLocalTempVariables($id, $definition).
-                $this->addServiceInlinedDefinitions($id, $definition).
-                $this->addServiceInstance($id, $definition).
-                $this->addServiceInlinedDefinitionsSetup($id, $definition).
-                $this->addServiceProperties($definition).
-                $this->addServiceMethodCalls($definition).
-                $this->addServiceConfigurator($definition).
-                $this->addServiceReturn($id, $definition)
-            ;
+        if ($asFile) {
+            $code = implode("\n", array_map(function ($line) { return $line ? substr($line, 8) : $line; }, explode("\n", $code)));
+        } else {
+            $code .= "    }\n";
         }
 
-        $this->definitionVariables = null;
-        $this->referenceVariables = null;
+        $this->definitionVariables = $this->inlinedDefinitions = null;
+        $this->referenceVariables = $this->serviceCalls = null;
 
         return $code;
     }
 
-    /**
-     * Adds multiple services.
-     *
-     * @return string
-     */
-    private function addServices()
+    private function addInlineVariables($id, Definition $definition, array $arguments, $forConstructor)
     {
-        $publicServices = $privateServices = $synchronizers = '';
-        $definitions = $this->container->getDefinitions();
-        ksort($definitions);
-        foreach ($definitions as $id => $definition) {
-            if ($definition->isPublic()) {
-                $publicServices .= $this->addService($id, $definition);
-            } else {
-                $privateServices .= $this->addService($id, $definition);
-            }
+        $code = '';
 
-            $synchronizers .= $this->addServiceSynchronizer($id, $definition);
+        foreach ($arguments as $argument) {
+            if (\is_array($argument)) {
+                $code .= $this->addInlineVariables($id, $definition, $argument, $forConstructor);
+            } elseif ($argument instanceof Reference) {
+                $code .= $this->addInlineReference($id, $definition, $this->container->normalizeId($argument), $forConstructor);
+            } elseif ($argument instanceof Definition) {
+                $code .= $this->addInlineService($id, $definition, $argument, $forConstructor);
+            }
         }
 
-        return $publicServices.$synchronizers.$privateServices;
+        return $code;
     }
 
-    /**
-     * Adds synchronizer methods.
-     *
-     * @param string     $id         A service identifier
-     * @param Definition $definition A Definition instance
-     *
-     * @return string|null
-     *
-     * @deprecated since version 2.7, will be removed in 3.0.
-     */
-    private function addServiceSynchronizer($id, Definition $definition)
+    private function addInlineReference($id, Definition $definition, $targetId, $forConstructor)
     {
-        if (!$definition->isSynchronized(false)) {
-            return;
+        while ($this->container->hasAlias($targetId)) {
+            $targetId = (string) $this->container->getAlias($targetId);
         }
 
-        if ('request' !== $id) {
-            @trigger_error('Synchronized services were deprecated in version 2.7 and won\'t work anymore in 3.0.', E_USER_DEPRECATED);
+        list($callCount, $behavior) = $this->serviceCalls[$targetId];
+
+        if ($id === $targetId) {
+            return $this->addInlineService($id, $definition, $definition);
         }
 
-        $code = '';
-        foreach ($this->container->getDefinitions() as $definitionId => $definition) {
-            foreach ($definition->getMethodCalls() as $call) {
-                foreach ($call[1] as $argument) {
-                    if ($argument instanceof Reference && $id == (string) $argument) {
-                        $arguments = array();
-                        foreach ($call[1] as $value) {
-                            $arguments[] = $this->dumpValue($value);
-                        }
+        if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) {
+            return '';
+        }
 
-                        $definitionId = var_export($definitionId, true);
-                        $call = $this->wrapServiceConditionals($call[1], sprintf('$this->get(%s)->%s(%s);', $definitionId, $call[0], implode(', ', $arguments)));
+        $hasSelfRef = isset($this->circularReferences[$id][$targetId]) && !isset($this->definitionVariables[$definition]);
 
-                        $code .= <<<EOF
-        if (\$this->initialized($definitionId)) {
-            $call
+        if ($hasSelfRef && !$forConstructor && !$forConstructor = !$this->circularReferences[$id][$targetId]) {
+            $code = $this->addInlineService($id, $definition, $definition);
+        } else {
+            $code = '';
         }
 
-EOF;
-                    }
+        if (isset($this->referenceVariables[$targetId]) || (2 > $callCount && (!$hasSelfRef || !$forConstructor))) {
+            return $code;
+        }
+
+        $name = $this->getNextVariableName();
+        $this->referenceVariables[$targetId] = new Variable($name);
+
+        $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior ? new Reference($targetId, $behavior) : null;
+        $code .= sprintf("        \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference));
+
+        if (!$hasSelfRef || !$forConstructor) {
+            return $code;
+        }
+
+        $code .= sprintf(<<<'EOTXT'
+
+        if (isset($this->%s[%s])) {
+            return $this->%1$s[%2$s];
+        }
+
+EOTXT
+            ,
+            'services',
+            $this->doExport($id)
+        );
+
+        return $code;
+    }
+
+    private function addInlineService($id, Definition $definition, Definition $inlineDef = null, $forConstructor = true)
+    {
+        $code = '';
+
+        if ($isSimpleInstance = $isRootInstance = null === $inlineDef) {
+            foreach ($this->serviceCalls as $targetId => list($callCount, $behavior, $byConstructor)) {
+                if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId]) {
+                    $code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor);
                 }
             }
         }
 
-        if (!$code) {
-            return;
+        if (isset($this->definitionVariables[$inlineDef = $inlineDef ?: $definition])) {
+            return $code;
         }
 
-        return <<<EOF
+        $arguments = [$inlineDef->getArguments(), $inlineDef->getFactory()];
 
-    /*{$this->docStar}
-     * Updates the '$id' service.
+        $code .= $this->addInlineVariables($id, $definition, $arguments, $forConstructor);
+
+        if ($arguments = array_filter([$inlineDef->getProperties(), $inlineDef->getMethodCalls(), $inlineDef->getConfigurator()])) {
+            $isSimpleInstance = false;
+        } elseif ($definition !== $inlineDef && 2 > $this->inlinedDefinitions[$inlineDef]) {
+            return $code;
+        }
+
+        if (isset($this->definitionVariables[$inlineDef])) {
+            $isSimpleInstance = false;
+        } else {
+            $name = $definition === $inlineDef ? 'instance' : $this->getNextVariableName();
+            $this->definitionVariables[$inlineDef] = new Variable($name);
+            $code .= '' !== $code ? "\n" : '';
+
+            if ('instance' === $name) {
+                $code .= $this->addServiceInstance($id, $definition, $isSimpleInstance);
+            } else {
+                $code .= $this->addNewInstance($inlineDef, '$'.$name, ' = ', $id);
+            }
+
+            if ('' !== $inline = $this->addInlineVariables($id, $definition, $arguments, false)) {
+                $code .= "\n".$inline."\n";
+            } elseif ($arguments && 'instance' === $name) {
+                $code .= "\n";
+            }
+
+            $code .= $this->addServiceProperties($inlineDef, $name);
+            $code .= $this->addServiceMethodCalls($inlineDef, $name);
+            $code .= $this->addServiceConfigurator($inlineDef, $name);
+        }
+
+        if ($isRootInstance && !$isSimpleInstance) {
+            $code .= "\n        return \$instance;\n";
+        }
+
+        return $code;
+    }
+
+    /**
+     * Adds multiple services.
+     *
+     * @return string
      */
-    protected function synchronize{$this->camelize($id)}Service()
+    private function addServices()
     {
-$code    }
+        $publicServices = $privateServices = '';
+        $definitions = $this->container->getDefinitions();
+        ksort($definitions);
+        foreach ($definitions as $id => $definition) {
+            if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition))) {
+                continue;
+            }
+            if ($definition->isPublic()) {
+                $publicServices .= $this->addService($id, $definition);
+            } else {
+                $privateServices .= $this->addService($id, $definition);
+            }
+        }
 
-EOF;
+        return $publicServices.$privateServices;
+    }
+
+    private function generateServiceFiles()
+    {
+        $definitions = $this->container->getDefinitions();
+        ksort($definitions);
+        foreach ($definitions as $id => $definition) {
+            if (!$definition->isSynthetic() && $definition->isShared() && !$this->isHotPath($definition)) {
+                $code = $this->addService($id, $definition, $file);
+                yield $file => $code;
+            }
+        }
     }
 
-    private function addNewInstance($id, Definition $definition, $return, $instantiation)
+    private function addNewInstance(Definition $definition, $return, $instantiation, $id)
     {
         $class = $this->dumpValue($definition->getClass());
+        $return = '        '.$return.$instantiation;
 
-        $arguments = array();
+        $arguments = [];
         foreach ($definition->getArguments() as $value) {
             $arguments[] = $this->dumpValue($value);
         }
@@ -752,70 +895,61 @@ EOF;
             $callable = $definition->getFactory();
             if (\is_array($callable)) {
                 if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) {
-                    throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $callable[1] ?: 'n/a'));
+                    throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s).', $callable[1] ?: 'n/a'));
                 }
 
                 if ($callable[0] instanceof Reference
                     || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
-                    return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
+                    return $return.sprintf("%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
                 }
 
                 $class = $this->dumpValue($callable[0]);
                 // If the class is a string we can optimize call_user_func away
-                if (0 === strpos($class, "'")) {
-                    return sprintf("        $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '');
-                }
-
-                return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
-            }
-
-            return sprintf("        $return{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : '');
-        } elseif (null !== $definition->getFactoryMethod(false)) {
-            if (null !== $definition->getFactoryClass(false)) {
-                $class = $this->dumpValue($definition->getFactoryClass(false));
+                if (0 === strpos($class, "'") && false === strpos($class, '$')) {
+                    if ("''" === $class) {
+                        throw new RuntimeException(sprintf('Cannot dump definition: The "%s" service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id));
+                    }
 
-                // If the class is a string we can optimize call_user_func away
-                if (0 === strpos($class, "'")) {
-                    return sprintf("        $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $definition->getFactoryMethod(false), $arguments ? implode(', ', $arguments) : '');
+                    return $return.sprintf("%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '');
                 }
 
-                return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass(false)), $definition->getFactoryMethod(false), $arguments ? ', '.implode(', ', $arguments) : '');
-            }
+                if (0 === strpos($class, 'new ')) {
+                    return $return.sprintf("(%s)->%s(%s);\n", $class, $callable[1], $arguments ? implode(', ', $arguments) : '');
+                }
 
-            if (null !== $definition->getFactoryService(false)) {
-                return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService(false)), $definition->getFactoryMethod(false), implode(', ', $arguments));
+                return $return.sprintf("\\call_user_func([%s, '%s']%s);\n", $class, $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
             }
 
-            throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id));
+            return $return.sprintf("%s(%s);\n", $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : '');
         }
 
         if (false !== strpos($class, '$')) {
-            return sprintf("        \$class = %s;\n\n        $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments));
+            return sprintf("        \$class = %s;\n\n%snew \$class(%s);\n", $class, $return, implode(', ', $arguments));
         }
 
-        return sprintf("        $return{$instantiation}new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments));
+        return $return.sprintf("new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments));
     }
 
     /**
      * Adds the class headers.
      *
-     * @param string $class     Class name
-     * @param string $baseClass The name of the base class
-     * @param string $namespace The class namespace
+     * @param string $class                  Class name
+     * @param string $baseClass              The name of the base class
+     * @param string $baseClassWithNamespace Fully qualified base class name
      *
      * @return string
      */
-    private function startClass($class, $baseClass, $namespace)
+    private function startClass($class, $baseClass, $baseClassWithNamespace)
     {
-        $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
-        $namespaceLine = $namespace ? "\nnamespace $namespace;\n" : '';
+        $bagClass = $this->container->isCompiled() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
+        $namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
 
-        return <<<EOF
+        $code = <<<EOF
 <?php
 $namespaceLine
+use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
-use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 use Symfony\Component\DependencyInjection\Exception\LogicException;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -824,154 +958,280 @@ $bagClass
 /*{$this->docStar}
  * This class has been auto-generated
  * by the Symfony Dependency Injection Component.
+ *
+ * @final since Symfony 3.3
  */
 class $class extends $baseClass
 {
-    private \$parameters;
-    private \$targetDirs = array();
-
-EOF;
-    }
+    private \$parameters = [];
+    private \$targetDirs = [];
 
-    /**
-     * Adds the constructor.
-     *
-     * @return string
-     */
-    private function addConstructor()
+    public function __construct()
     {
-        $targetDirs = $this->exportTargetDirs();
-        $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;
 
-        $code = <<<EOF
-
-    public function __construct()
-    {{$targetDirs}
-        parent::__construct($arguments);
+EOF;
+        if (null !== $this->targetDirRegex) {
+            $dir = $this->asFiles ? '$this->targetDirs[0] = \\dirname($containerDir)' : '__DIR__';
+            $code .= <<<EOF
+        \$dir = {$dir};
+        for (\$i = 1; \$i <= {$this->targetDirMaxMatches}; ++\$i) {
+            \$this->targetDirs[\$i] = \$dir = \\dirname(\$dir);
+        }
 
 EOF;
+        }
+        if ($this->asFiles) {
+            $code = str_replace('$parameters', "\$buildParameters;\n    private \$containerDir;\n    private \$parameters", $code);
+            $code = str_replace('__construct()', '__construct(array $buildParameters = [], $containerDir = __DIR__)', $code);
+            $code .= "        \$this->buildParameters = \$buildParameters;\n";
+            $code .= "        \$this->containerDir = \$containerDir;\n";
+        }
+
+        if ($this->container->isCompiled()) {
+            if (Container::class !== $baseClassWithNamespace) {
+                $r = $this->container->getReflectionClass($baseClassWithNamespace, false);
+                if (null !== $r
+                    && (null !== $constructor = $r->getConstructor())
+                    && 0 === $constructor->getNumberOfRequiredParameters()
+                    && Container::class !== $constructor->getDeclaringClass()->name
+                ) {
+                    $code .= "        parent::__construct();\n";
+                    $code .= "        \$this->parameterBag = null;\n\n";
+                }
+            }
 
-        if (\count($scopes = $this->container->getScopes(false)) > 0) {
-            $code .= "\n";
-            $code .= '        $this->scopes = '.$this->dumpValue($scopes).";\n";
-            $code .= '        $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren(false)).";\n";
+            if ($this->container->getParameterBag()->all()) {
+                $code .= "        \$this->parameters = \$this->getDefaultParameters();\n\n";
+            }
+
+            $code .= "        \$this->services = [];\n";
+        } else {
+            $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;
+            $code .= "        parent::__construct($arguments);\n";
         }
 
+        $code .= $this->addNormalizedIds();
+        $code .= $this->addSyntheticIds();
         $code .= $this->addMethodMap();
+        $code .= $this->asFiles ? $this->addFileMap() : '';
+        $code .= $this->addPrivateServices();
         $code .= $this->addAliases();
-
+        $code .= $this->addInlineRequires();
         $code .= <<<'EOF'
     }
 
 EOF;
+        $code .= $this->addRemovedIds();
 
-        return $code;
+        if ($this->container->isCompiled()) {
+            $code .= <<<EOF
+
+    public function compile()
+    {
+        throw new LogicException('You cannot compile a dumped container that was already compiled.');
     }
 
-    /**
-     * Adds the constructor for a frozen container.
-     *
-     * @return string
-     */
-    private function addFrozenConstructor()
+    public function isCompiled()
     {
-        $targetDirs = $this->exportTargetDirs();
+        return true;
+    }
 
-        $code = <<<EOF
+    public function isFrozen()
+    {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
 
-    public function __construct()
-    {{$targetDirs}
-EOF;
+        return true;
+    }
 
-        if ($this->container->getParameterBag()->all()) {
-            $code .= "\n        \$this->parameters = \$this->getDefaultParameters();\n";
+EOF;
         }
 
-        $code .= <<<'EOF'
+        if ($this->asFiles) {
+            $code .= <<<EOF
 
-        $this->services =
-        $this->scopedServices =
-        $this->scopeStacks = array();
-EOF;
+    protected function load(\$file, \$lazyLoad = true)
+    {
+        return require \$this->containerDir.\\DIRECTORY_SEPARATOR.\$file;
+    }
 
-        $code .= "\n";
-        if (\count($scopes = $this->container->getScopes(false)) > 0) {
-            $code .= '        $this->scopes = '.$this->dumpValue($scopes).";\n";
-            $code .= '        $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren(false)).";\n";
-        } else {
-            $code .= "        \$this->scopes = array();\n";
-            $code .= "        \$this->scopeChildren = array();\n";
+EOF;
         }
 
-        $code .= $this->addMethodMap();
-        $code .= $this->addAliases();
+        $proxyDumper = $this->getProxyDumper();
+        foreach ($this->container->getDefinitions() as $definition) {
+            if (!$proxyDumper->isProxyCandidate($definition)) {
+                continue;
+            }
+            if ($this->asFiles) {
+                $proxyLoader = '$this->load("{$class}.php")';
+            } elseif ($this->namespace) {
+                $proxyLoader = 'class_alias("'.$this->namespace.'\\\\{$class}", $class, false)';
+            } else {
+                $proxyLoader = '';
+            }
+            if ($proxyLoader) {
+                $proxyLoader = "class_exists(\$class, false) || {$proxyLoader};\n\n        ";
+            }
+            $code .= <<<EOF
 
-        $code .= <<<'EOF'
+    protected function createProxy(\$class, \Closure \$factory)
+    {
+        {$proxyLoader}return \$factory();
     }
 
 EOF;
+            break;
+        }
+
+        return $code;
+    }
+
+    /**
+     * Adds the normalizedIds property definition.
+     *
+     * @return string
+     */
+    private function addNormalizedIds()
+    {
+        $code = '';
+        $normalizedIds = $this->container->getNormalizedIds();
+        ksort($normalizedIds);
+        foreach ($normalizedIds as $id => $normalizedId) {
+            if ($this->container->has($normalizedId)) {
+                $code .= '            '.$this->doExport($id).' => '.$this->doExport($normalizedId).",\n";
+            }
+        }
+
+        return $code ? "        \$this->normalizedIds = [\n".$code."        ];\n" : '';
+    }
+
+    /**
+     * Adds the syntheticIds definition.
+     *
+     * @return string
+     */
+    private function addSyntheticIds()
+    {
+        $code = '';
+        $definitions = $this->container->getDefinitions();
+        ksort($definitions);
+        foreach ($definitions as $id => $definition) {
+            if ($definition->isSynthetic() && 'service_container' !== $id) {
+                $code .= '            '.$this->doExport($id)." => true,\n";
+            }
+        }
 
-        return $code;
+        return $code ? "        \$this->syntheticIds = [\n{$code}        ];\n" : '';
     }
 
     /**
-     * Adds the constructor for a frozen container.
+     * Adds the removedIds definition.
      *
      * @return string
      */
-    private function addFrozenCompile()
+    private function addRemovedIds()
     {
+        if (!$ids = $this->container->getRemovedIds()) {
+            return '';
+        }
+        if ($this->asFiles) {
+            $code = "require \$this->containerDir.\\DIRECTORY_SEPARATOR.'removed-ids.php'";
+        } else {
+            $code = '';
+            $ids = array_keys($ids);
+            sort($ids);
+            foreach ($ids as $id) {
+                if (preg_match('/^\d+_[^~]++~[._a-zA-Z\d]{7}$/', $id)) {
+                    continue;
+                }
+                $code .= '            '.$this->doExport($id)." => true,\n";
+            }
+
+            $code = "[\n{$code}        ]";
+        }
+
         return <<<EOF
 
-    /*{$this->docStar}
-     * {@inheritdoc}
-     */
-    public function compile()
+    public function getRemovedIds()
     {
-        throw new LogicException('You cannot compile a dumped frozen container.');
+        return {$code};
     }
 
 EOF;
     }
 
     /**
-     * Adds the isFrozen method for a frozen container.
+     * Adds the methodMap property definition.
      *
      * @return string
      */
-    private function addIsFrozenMethod()
+    private function addMethodMap()
     {
-        return <<<EOF
+        $code = '';
+        $definitions = $this->container->getDefinitions();
+        ksort($definitions);
+        foreach ($definitions as $id => $definition) {
+            if (!$definition->isSynthetic() && (!$this->asFiles || !$definition->isShared() || $this->isHotPath($definition))) {
+                $code .= '            '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n";
+            }
+        }
 
-    /*{$this->docStar}
-     * {@inheritdoc}
+        return $code ? "        \$this->methodMap = [\n{$code}        ];\n" : '';
+    }
+
+    /**
+     * Adds the fileMap property definition.
+     *
+     * @return string
      */
-    public function isFrozen()
+    private function addFileMap()
     {
-        return true;
-    }
+        $code = '';
+        $definitions = $this->container->getDefinitions();
+        ksort($definitions);
+        foreach ($definitions as $id => $definition) {
+            if (!$definition->isSynthetic() && $definition->isShared() && !$this->isHotPath($definition)) {
+                $code .= sprintf("            %s => '%s.php',\n", $this->doExport($id), $this->generateMethodName($id));
+            }
+        }
 
-EOF;
+        return $code ? "        \$this->fileMap = [\n{$code}        ];\n" : '';
     }
 
     /**
-     * Adds the methodMap property definition.
+     * Adds the privates property definition.
      *
      * @return string
      */
-    private function addMethodMap()
+    private function addPrivateServices()
     {
-        if (!$definitions = $this->container->getDefinitions()) {
-            return '';
+        $code = '';
+
+        $aliases = $this->container->getAliases();
+        ksort($aliases);
+        foreach ($aliases as $id => $alias) {
+            if ($alias->isPrivate()) {
+                $code .= '            '.$this->doExport($id)." => true,\n";
+            }
         }
 
-        $code = "        \$this->methodMap = array(\n";
+        $definitions = $this->container->getDefinitions();
         ksort($definitions);
         foreach ($definitions as $id => $definition) {
-            $code .= '            '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n";
+            if (!$definition->isPublic()) {
+                $code .= '            '.$this->doExport($id)." => true,\n";
+            }
+        }
+
+        if (empty($code)) {
+            return '';
         }
 
-        return $code."        );\n";
+        $out = "        \$this->privates = [\n";
+        $out .= $code;
+        $out .= "        ];\n";
+
+        return $out;
     }
 
     /**
@@ -982,20 +1242,51 @@ EOF;
     private function addAliases()
     {
         if (!$aliases = $this->container->getAliases()) {
-            return $this->container->isFrozen() ? "\n        \$this->aliases = array();\n" : '';
+            return $this->container->isCompiled() ? "\n        \$this->aliases = [];\n" : '';
         }
 
-        $code = "        \$this->aliases = array(\n";
+        $code = "        \$this->aliases = [\n";
         ksort($aliases);
         foreach ($aliases as $alias => $id) {
-            $id = (string) $id;
+            $id = $this->container->normalizeId($id);
             while (isset($aliases[$id])) {
-                $id = (string) $aliases[$id];
+                $id = $this->container->normalizeId($aliases[$id]);
+            }
+            $code .= '            '.$this->doExport($alias).' => '.$this->doExport($id).",\n";
+        }
+
+        return $code."        ];\n";
+    }
+
+    private function addInlineRequires()
+    {
+        if (!$this->hotPathTag || !$this->inlineRequires) {
+            return '';
+        }
+
+        $lineage = [];
+
+        foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) {
+            $definition = $this->container->getDefinition($id);
+            $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
+
+            foreach ($inlinedDefinitions as $def) {
+                if (\is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
+                    $this->collectLineage($class, $lineage);
+                }
+            }
+        }
+
+        $code = '';
+
+        foreach ($lineage as $file) {
+            if (!isset($this->inlinedRequires[$file])) {
+                $this->inlinedRequires[$file] = true;
+                $code .= sprintf("\n            include_once %s;", $file);
             }
-            $code .= '            '.var_export($alias, true).' => '.var_export($id, true).",\n";
         }
 
-        return $code."        );\n";
+        return $code ? sprintf("\n        \$this->privates['service_container'] = function () {%s\n        };\n", $code) : '';
     }
 
     /**
@@ -1009,60 +1300,149 @@ EOF;
             return '';
         }
 
-        $parameters = $this->exportParameters($this->container->getParameterBag()->all());
+        $php = [];
+        $dynamicPhp = [];
+        $normalizedParams = [];
+
+        foreach ($this->container->getParameterBag()->all() as $key => $value) {
+            if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) {
+                throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: "%s".', $resolvedKey));
+            }
+            if ($key !== $lcKey = strtolower($key)) {
+                $normalizedParams[] = sprintf('        %s => %s,', $this->export($lcKey), $this->export($key));
+            }
+            $export = $this->exportParameters([$value]);
+            $export = explode('0 => ', substr(rtrim($export, " ]\n"), 2, -1), 2);
+
+            if (preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $export[1])) {
+                $dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]);
+            } else {
+                $php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
+            }
+        }
+
+        $parameters = sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', 8));
 
         $code = '';
-        if ($this->container->isFrozen()) {
+        if ($this->container->isCompiled()) {
             $code .= <<<'EOF'
 
-    /**
-     * {@inheritdoc}
-     */
     public function getParameter($name)
     {
-        $name = strtolower($name);
+        $name = (string) $name;
+        if (isset($this->buildParameters[$name])) {
+            return $this->buildParameters[$name];
+        }
+        if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
+            $name = $this->normalizeParameterName($name);
 
-        if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
-            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
+            if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
+                throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
+            }
+        }
+        if (isset($this->loadedDynamicParameters[$name])) {
+            return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
         }
 
         return $this->parameters[$name];
     }
 
-    /**
-     * {@inheritdoc}
-     */
     public function hasParameter($name)
     {
-        $name = strtolower($name);
+        $name = (string) $name;
+        if (isset($this->buildParameters[$name])) {
+            return true;
+        }
+        $name = $this->normalizeParameterName($name);
 
-        return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
+        return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
     }
 
-    /**
-     * {@inheritdoc}
-     */
     public function setParameter($name, $value)
     {
         throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
     }
 
-    /**
-     * {@inheritdoc}
-     */
     public function getParameterBag()
     {
         if (null === $this->parameterBag) {
-            $this->parameterBag = new FrozenParameterBag($this->parameters);
+            $parameters = $this->parameters;
+            foreach ($this->loadedDynamicParameters as $name => $loaded) {
+                $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
+            }
+            foreach ($this->buildParameters as $name => $value) {
+                $parameters[$name] = $value;
+            }
+            $this->parameterBag = new FrozenParameterBag($parameters);
         }
 
         return $this->parameterBag;
     }
 
 EOF;
-            if ('' === $this->docStar) {
-                $code = str_replace('/**', '/*', $code);
+            if (!$this->asFiles) {
+                $code = preg_replace('/^.*buildParameters.*\n.*\n.*\n/m', '', $code);
+            }
+
+            if ($dynamicPhp) {
+                $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, \count($dynamicPhp), false)), '', 8);
+                $getDynamicParameter = <<<'EOF'
+        switch ($name) {
+%s
+            default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%%s" must be defined.', $name));
+        }
+        $this->loadedDynamicParameters[$name] = true;
+
+        return $this->dynamicParameters[$name] = $value;
+EOF;
+                $getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp));
+            } else {
+                $loadedDynamicParameters = '[]';
+                $getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));';
+            }
+
+            $code .= <<<EOF
+
+    private \$loadedDynamicParameters = {$loadedDynamicParameters};
+    private \$dynamicParameters = [];
+
+    /*{$this->docStar}
+     * Computes a dynamic parameter.
+     *
+     * @param string \$name The name of the dynamic parameter to load
+     *
+     * @return mixed The value of the dynamic parameter
+     *
+     * @throws InvalidArgumentException When the dynamic parameter does not exist
+     */
+    private function getDynamicParameter(\$name)
+    {
+{$getDynamicParameter}
+    }
+
+
+EOF;
+
+            $code .= '    private $normalizedParameterNames = '.($normalizedParams ? sprintf("[\n%s\n    ];", implode("\n", $normalizedParams)) : '[];')."\n";
+            $code .= <<<'EOF'
+
+    private function normalizeParameterName($name)
+    {
+        if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) {
+            $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName;
+            if ((string) $name !== $normalizedName) {
+                @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
             }
+        } else {
+            $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name;
+        }
+
+        return $normalizedName;
+    }
+
+EOF;
+        } elseif ($dynamicPhp) {
+            throw new RuntimeException('You cannot dump a not-frozen container with dynamic parameters.');
         }
 
         $code .= <<<EOF
@@ -1085,7 +1465,6 @@ EOF;
     /**
      * Exports parameters.
      *
-     * @param array  $parameters
      * @param string $path
      * @param int    $indent
      *
@@ -1095,10 +1474,12 @@ EOF;
      */
     private function exportParameters(array $parameters, $path = '', $indent = 12)
     {
-        $php = array();
+        $php = [];
         foreach ($parameters as $key => $value) {
             if (\is_array($value)) {
                 $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4);
+            } elseif ($value instanceof ArgumentInterface) {
+                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain special arguments. "%s" found in "%s".', \get_class($value), $path.'/'.$key));
             } elseif ($value instanceof Variable) {
                 throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key));
             } elseif ($value instanceof Definition) {
@@ -1111,10 +1492,10 @@ EOF;
                 $value = $this->export($value);
             }
 
-            $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value);
+            $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), $this->export($key), $value);
         }
 
-        return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4));
+        return sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', $indent - 4));
     }
 
     /**
@@ -1140,137 +1521,84 @@ EOF;
      */
     private function wrapServiceConditionals($value, $code)
     {
-        if (!$services = ContainerBuilder::getServiceConditionals($value)) {
+        if (!$condition = $this->getServiceConditionals($value)) {
             return $code;
         }
 
-        $conditions = array();
-        foreach ($services as $service) {
-            $conditions[] = sprintf('$this->has(%s)', var_export($service, true));
-        }
-
         // re-indent the wrapped code
         $code = implode("\n", array_map(function ($line) { return $line ? '    '.$line : $line; }, explode("\n", $code)));
 
-        return sprintf("        if (%s) {\n%s        }\n", implode(' && ', $conditions), $code);
+        return sprintf("        if (%s) {\n%s        }\n", $condition, $code);
     }
 
     /**
-     * Builds service calls from arguments.
+     * Get the conditions to execute for conditional services.
+     *
+     * @param string $value
+     *
+     * @return string|null
      */
-    private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior)
+    private function getServiceConditionals($value)
     {
-        foreach ($arguments as $argument) {
-            if (\is_array($argument)) {
-                $this->getServiceCallsFromArguments($argument, $calls, $behavior);
-            } elseif ($argument instanceof Reference) {
-                $id = (string) $argument;
-
-                if (!isset($calls[$id])) {
-                    $calls[$id] = 0;
-                }
-                if (!isset($behavior[$id])) {
-                    $behavior[$id] = $argument->getInvalidBehavior();
-                } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) {
-                    $behavior[$id] = $argument->getInvalidBehavior();
-                }
-
-                ++$calls[$id];
+        $conditions = [];
+        foreach (ContainerBuilder::getInitializedConditionals($value) as $service) {
+            if (!$this->container->hasDefinition($service)) {
+                return 'false';
             }
+            $conditions[] = sprintf('isset($this->services[%s])', $this->doExport($service));
         }
-    }
-
-    /**
-     * Returns the inline definition.
-     *
-     * @return array
-     */
-    private function getInlinedDefinitions(Definition $definition)
-    {
-        if (false === $this->inlinedDefinitions->contains($definition)) {
-            $definitions = array_merge(
-                $this->getDefinitionsFromArguments($definition->getArguments()),
-                $this->getDefinitionsFromArguments($definition->getMethodCalls()),
-                $this->getDefinitionsFromArguments($definition->getProperties()),
-                $this->getDefinitionsFromArguments(array($definition->getConfigurator())),
-                $this->getDefinitionsFromArguments(array($definition->getFactory()))
-            );
+        foreach (ContainerBuilder::getServiceConditionals($value) as $service) {
+            if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) {
+                continue;
+            }
 
-            $this->inlinedDefinitions->offsetSet($definition, $definitions);
+            $conditions[] = sprintf('$this->has(%s)', $this->doExport($service));
+        }
 
-            return $definitions;
+        if (!$conditions) {
+            return '';
         }
 
-        return $this->inlinedDefinitions->offsetGet($definition);
+        return implode(' && ', $conditions);
     }
 
-    /**
-     * Gets the definition from arguments.
-     *
-     * @return array
-     */
-    private function getDefinitionsFromArguments(array $arguments)
+    private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage $definitions = null, array &$calls = [], $byConstructor = null)
     {
-        $definitions = array();
-        foreach ($arguments as $argument) {
-            if (\is_array($argument)) {
-                $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument));
-            } elseif ($argument instanceof Definition) {
-                $definitions = array_merge(
-                    $definitions,
-                    $this->getInlinedDefinitions($argument),
-                    array($argument)
-                );
-            }
+        if (null === $definitions) {
+            $definitions = new \SplObjectStorage();
         }
 
-        return $definitions;
-    }
-
-    /**
-     * Checks if a service id has a reference.
-     *
-     * @param string $id
-     * @param array  $arguments
-     * @param bool   $deep
-     * @param array  $visited
-     *
-     * @return bool
-     */
-    private function hasReference($id, array $arguments, $deep = false, array &$visited = array())
-    {
         foreach ($arguments as $argument) {
             if (\is_array($argument)) {
-                if ($this->hasReference($id, $argument, $deep, $visited)) {
-                    return true;
-                }
+                $this->getDefinitionsFromArguments($argument, $definitions, $calls, $byConstructor);
             } elseif ($argument instanceof Reference) {
-                $argumentId = (string) $argument;
-                if ($id === $argumentId) {
-                    return true;
-                }
-
-                if ($deep && !isset($visited[$argumentId]) && 'service_container' !== $argumentId) {
-                    $visited[$argumentId] = true;
-
-                    $service = $this->container->getDefinition($argumentId);
+                $id = $this->container->normalizeId($argument);
 
-                    // if the proxy manager is enabled, disable searching for references in lazy services,
-                    // as these services will be instantiated lazily and don't have direct related references.
-                    if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) {
-                        continue;
-                    }
-
-                    $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
+                while ($this->container->hasAlias($id)) {
+                    $id = (string) $this->container->getAlias($id);
+                }
 
-                    if ($this->hasReference($id, $arguments, $deep, $visited)) {
-                        return true;
-                    }
+                if (!isset($calls[$id])) {
+                    $calls[$id] = [0, $argument->getInvalidBehavior(), $byConstructor];
+                } else {
+                    $calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior());
                 }
+
+                ++$calls[$id][0];
+            } elseif (!$argument instanceof Definition) {
+                // no-op
+            } elseif (isset($definitions[$argument])) {
+                $definitions[$argument] = 1 + $definitions[$argument];
+            } else {
+                $definitions[$argument] = 1;
+                $arguments = [$argument->getArguments(), $argument->getFactory()];
+                $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null === $byConstructor || $byConstructor);
+                $arguments = [$argument->getProperties(), $argument->getMethodCalls(), $argument->getConfigurator()];
+                $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null !== $byConstructor && $byConstructor);
             }
         }
 
-        return false;
+        return $definitions;
     }
 
     /**
@@ -1286,15 +1614,68 @@ EOF;
     private function dumpValue($value, $interpolate = true)
     {
         if (\is_array($value)) {
-            $code = array();
+            if ($value && $interpolate && false !== $param = array_search($value, $this->container->getParameterBag()->all(), true)) {
+                return $this->dumpValue("%$param%");
+            }
+            $code = [];
             foreach ($value as $k => $v) {
                 $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate));
             }
 
-            return sprintf('array(%s)', implode(', ', $code));
+            return sprintf('[%s]', implode(', ', $code));
+        } elseif ($value instanceof ArgumentInterface) {
+            $scope = [$this->definitionVariables, $this->referenceVariables];
+            $this->definitionVariables = $this->referenceVariables = null;
+
+            try {
+                if ($value instanceof ServiceClosureArgument) {
+                    $value = $value->getValues()[0];
+                    $code = $this->dumpValue($value, $interpolate);
+
+                    if ($value instanceof TypedReference) {
+                        $code = sprintf('$f = function (\\%s $v%s) { return $v; }; return $f(%s);', $value->getType(), ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $value->getInvalidBehavior() ? ' = null' : '', $code);
+                    } else {
+                        $code = sprintf('return %s;', $code);
+                    }
+
+                    return sprintf("function () {\n            %s\n        }", $code);
+                }
+
+                if ($value instanceof IteratorArgument) {
+                    $operands = [0];
+                    $code = [];
+                    $code[] = 'new RewindableGenerator(function () {';
+
+                    if (!$values = $value->getValues()) {
+                        $code[] = '            return new \EmptyIterator();';
+                    } else {
+                        $countCode = [];
+                        $countCode[] = 'function () {';
+
+                        foreach ($values as $k => $v) {
+                            ($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0];
+                            $v = $this->wrapServiceConditionals($v, sprintf("        yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)));
+                            foreach (explode("\n", $v) as $v) {
+                                if ($v) {
+                                    $code[] = '    '.$v;
+                                }
+                            }
+                        }
+
+                        $countCode[] = sprintf('            return %s;', implode(' + ', $operands));
+                        $countCode[] = '        }';
+                    }
+
+                    $code[] = sprintf('        }, %s)', \count($operands) > 1 ? implode("\n", $countCode) : $operands[0]);
+
+                    return implode("\n", $code);
+                }
+            } finally {
+                list($this->definitionVariables, $this->referenceVariables) = $scope;
+            }
         } elseif ($value instanceof Definition) {
             if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
-                return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate);
+                return $this->dumpValue($this->definitionVariables[$value], $interpolate);
             }
             if ($value->getMethodCalls()) {
                 throw new RuntimeException('Cannot dump definitions which have method calls.');
@@ -1306,7 +1687,7 @@ EOF;
                 throw new RuntimeException('Cannot dump definitions which have a configurator.');
             }
 
-            $arguments = array();
+            $arguments = [];
             foreach ($value->getArguments() as $argument) {
                 $arguments[] = $this->dumpValue($argument);
             }
@@ -1315,40 +1696,33 @@ EOF;
                 $factory = $value->getFactory();
 
                 if (\is_string($factory)) {
-                    return sprintf('\\%s(%s)', $factory, implode(', ', $arguments));
+                    return sprintf('%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory)), implode(', ', $arguments));
                 }
 
                 if (\is_array($factory)) {
                     if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $factory[1])) {
-                        throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $factory[1] ?: 'n/a'));
+                        throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s).', $factory[1] ?: 'n/a'));
                     }
 
+                    $class = $this->dumpValue($factory[0]);
                     if (\is_string($factory[0])) {
-                        return sprintf('%s::%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory[0])), $factory[1], implode(', ', $arguments));
+                        return sprintf('%s::%s(%s)', $this->dumpLiteralClass($class), $factory[1], implode(', ', $arguments));
                     }
 
                     if ($factory[0] instanceof Definition) {
-                        return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($factory[0]), $factory[1], \count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
+                        if (0 === strpos($class, 'new ')) {
+                            return sprintf('(%s)->%s(%s)', $class, $factory[1], implode(', ', $arguments));
+                        }
+
+                        return sprintf("\\call_user_func([%s, '%s']%s)", $class, $factory[1], \count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
                     }
 
                     if ($factory[0] instanceof Reference) {
-                        return sprintf('%s->%s(%s)', $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments));
+                        return sprintf('%s->%s(%s)', $class, $factory[1], implode(', ', $arguments));
                     }
                 }
 
-                throw new RuntimeException('Cannot dump definition because of invalid factory');
-            }
-
-            if (null !== $value->getFactoryMethod(false)) {
-                if (null !== $value->getFactoryClass(false)) {
-                    return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass(false)), $value->getFactoryMethod(false), \count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
-                } elseif (null !== $value->getFactoryService(false)) {
-                    $service = $this->dumpValue($value->getFactoryService(false));
-
-                    return sprintf('%s->%s(%s)', 0 === strpos($service, '$') ? sprintf('$this->get(%s)', $service) : $this->getServiceCall($value->getFactoryService(false)), $value->getFactoryMethod(false), implode(', ', $arguments));
-                }
-
-                throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.');
+                throw new RuntimeException('Cannot dump definition because of invalid factory.');
             }
 
             $class = $value->getClass();
@@ -1360,24 +1734,29 @@ EOF;
         } elseif ($value instanceof Variable) {
             return '$'.$value;
         } elseif ($value instanceof Reference) {
-            if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) {
+            $id = $this->container->normalizeId($value);
+
+            while ($this->container->hasAlias($id)) {
+                $id = (string) $this->container->getAlias($id);
+            }
+
+            if (null !== $this->referenceVariables && isset($this->referenceVariables[$id])) {
                 return $this->dumpValue($this->referenceVariables[$id], $interpolate);
             }
 
-            return $this->getServiceCall((string) $value, $value);
+            return $this->getServiceCall($id, $value);
         } elseif ($value instanceof Expression) {
-            return $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
+            return $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']);
         } elseif ($value instanceof Parameter) {
             return $this->dumpParameter($value);
         } elseif (true === $interpolate && \is_string($value)) {
             if (preg_match('/^%([^%]+)%$/', $value, $match)) {
                 // we do this to deal with non string values (Boolean, integer, ...)
                 // the preg_replace_callback converts them to strings
-                return $this->dumpParameter(strtolower($match[1]));
+                return $this->dumpParameter($match[1]);
             } else {
-                $that = $this;
-                $replaceParameters = function ($match) use ($that) {
-                    return "'.".$that->dumpParameter(strtolower($match[2])).".'";
+                $replaceParameters = function ($match) {
+                    return "'.".$this->dumpParameter($match[2]).".'";
                 };
 
                 $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, $this->export($value)));
@@ -1403,10 +1782,10 @@ EOF;
     private function dumpLiteralClass($class)
     {
         if (false !== strpos($class, '$')) {
-            throw new RuntimeException('Cannot dump definitions which have a variable class name.');
+            return sprintf('${($_ = %s) && false ?: "_"}', $class);
         }
         if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
-            throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
+            throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s).', $class ?: 'n/a'));
         }
 
         $class = substr(str_replace('\\\\', '\\', $class), 1, -1);
@@ -1421,28 +1800,24 @@ EOF;
      *
      * @return string
      */
-    public function dumpParameter($name)
+    private function dumpParameter($name)
     {
         $name = (string) $name;
 
-        if ($this->container->isFrozen() && $this->container->hasParameter($name)) {
-            return $this->dumpValue($this->container->getParameter($name), false);
-        }
+        if ($this->container->isCompiled() && $this->container->hasParameter($name)) {
+            $value = $this->container->getParameter($name);
+            $dumpedValue = $this->dumpValue($value, false);
 
-        return sprintf('$this->getParameter(%s)', var_export($name, true));
-    }
+            if (!$value || !\is_array($value)) {
+                return $dumpedValue;
+            }
 
-    /**
-     * @deprecated since version 2.6.2, to be removed in 3.0.
-     *             Use \Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider instead.
-     *
-     * @param ExpressionFunctionProviderInterface $provider
-     */
-    public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6.2 and will be removed in 3.0. Use the Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider method instead.', E_USER_DEPRECATED);
+            if (!preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) {
+                return sprintf('$this->parameters[%s]', $this->doExport($name));
+            }
+        }
 
-        $this->expressionLanguageProviders[] = $provider;
+        return sprintf('$this->getParameter(%s)', $this->doExport($name));
     }
 
     /**
@@ -1458,16 +1833,59 @@ EOF;
         while ($this->container->hasAlias($id)) {
             $id = (string) $this->container->getAlias($id);
         }
+        $id = $this->container->normalizeId($id);
 
         if ('service_container' === $id) {
             return '$this';
         }
 
-        if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
-            return sprintf('$this->get(%s, ContainerInterface::NULL_ON_INVALID_REFERENCE)', var_export($id, true));
+        if ($this->container->hasDefinition($id) && $definition = $this->container->getDefinition($id)) {
+            if ($definition->isSynthetic()) {
+                $code = sprintf('$this->get(%s%s)', $this->doExport($id), null !== $reference ? ', '.$reference->getInvalidBehavior() : '');
+            } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
+                $code = 'null';
+                if (!$definition->isShared()) {
+                    return $code;
+                }
+            } elseif ($this->isTrivialInstance($definition)) {
+                $code = substr($this->addNewInstance($definition, '', '', $id), 8, -2);
+                if ($definition->isShared()) {
+                    $code = sprintf('$this->services[%s] = %s', $this->doExport($id), $code);
+                }
+                $code = "($code)";
+            } elseif ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition)) {
+                $code = sprintf("\$this->load('%s.php')", $this->generateMethodName($id));
+            } else {
+                $code = sprintf('$this->%s()', $this->generateMethodName($id));
+            }
+        } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
+            return 'null';
+        } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
+            $code = sprintf('$this->get(%s, /* ContainerInterface::NULL_ON_INVALID_REFERENCE */ %d)', $this->doExport($id), ContainerInterface::NULL_ON_INVALID_REFERENCE);
+        } else {
+            $code = sprintf('$this->get(%s)', $this->doExport($id));
         }
 
-        return sprintf('$this->get(%s)', var_export($id, true));
+        // The following is PHP 5.5 syntax for what could be written as "(\$this->services['$id'] ?? $code)" on PHP>=7.0
+
+        return sprintf("\${(\$_ = isset(\$this->services[%s]) ? \$this->services[%1\$s] : %s) && false ?: '_'}", $this->doExport($id), $code);
+    }
+
+    /**
+     * Initializes the method names map to avoid conflicts with the Container methods.
+     *
+     * @param string $class the container base class
+     */
+    private function initializeMethodNamesMap($class)
+    {
+        $this->serviceIdToMethodNameMap = [];
+        $this->usedMethodNames = [];
+
+        if ($reflectionClass = $this->container->getReflectionClass($class)) {
+            foreach ($reflectionClass->getMethods() as $method) {
+                $this->usedMethodNames[strtolower($method->getName())] = true;
+            }
+        }
     }
 
     /**
@@ -1479,15 +1897,27 @@ EOF;
      *
      * @throws InvalidArgumentException
      */
-    private function camelize($id)
+    private function generateMethodName($id)
     {
-        $name = Container::camelize($id);
+        if (isset($this->serviceIdToMethodNameMap[$id])) {
+            return $this->serviceIdToMethodNameMap[$id];
+        }
+
+        $i = strrpos($id, '\\');
+        $name = Container::camelize(false !== $i && isset($id[1 + $i]) ? substr($id, 1 + $i) : $id);
+        $name = preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', $name);
+        $methodName = 'get'.$name.'Service';
+        $suffix = 1;
 
-        if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) {
-            throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id));
+        while (isset($this->usedMethodNames[strtolower($methodName)])) {
+            ++$suffix;
+            $methodName = 'get'.$name.$suffix.'Service';
         }
 
-        return $name;
+        $this->serviceIdToMethodNameMap[$id] = $methodName;
+        $this->usedMethodNames[strtolower($methodName)] = true;
+
+        return $methodName;
     }
 
     /**
@@ -1534,8 +1964,16 @@ EOF;
             if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                 throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
             }
-            $providers = array_merge($this->container->getExpressionLanguageProviders(), $this->expressionLanguageProviders);
-            $this->expressionLanguage = new ExpressionLanguage(null, $providers);
+            $providers = $this->container->getExpressionLanguageProviders();
+            $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
+                $id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null;
+
+                if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) {
+                    return $this->getServiceCall($id);
+                }
+
+                return sprintf('$this->get(%s)', $arg);
+            });
 
             if ($this->container->isTrackingResources()) {
                 foreach ($providers as $provider) {
@@ -1547,26 +1985,21 @@ EOF;
         return $this->expressionLanguage;
     }
 
-    private function exportTargetDirs()
+    private function isHotPath(Definition $definition)
     {
-        return null === $this->targetDirRegex ? '' : <<<EOF
-
-        \$dir = __DIR__;
-        for (\$i = 1; \$i <= {$this->targetDirMaxMatches}; ++\$i) {
-            \$this->targetDirs[\$i] = \$dir = dirname(\$dir);
-        }
-EOF;
+        return $this->hotPathTag && $definition->hasTag($this->hotPathTag) && !$definition->isDeprecated();
     }
 
     private function export($value)
     {
         if (null !== $this->targetDirRegex && \is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) {
-            $prefix = $matches[0][1] ? var_export(substr($value, 0, $matches[0][1]), true).'.' : '';
+            $prefix = $matches[0][1] ? $this->doExport(substr($value, 0, $matches[0][1]), true).'.' : '';
             $suffix = $matches[0][1] + \strlen($matches[0][0]);
-            $suffix = isset($value[$suffix]) ? '.'.var_export(substr($value, $suffix), true) : '';
-            $dirname = '__DIR__';
+            $suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix), true) : '';
+            $dirname = $this->asFiles ? '$this->containerDir' : '__DIR__';
+            $offset = 1 + $this->targetDirMaxMatches - \count($matches);
 
-            if (0 < $offset = 1 + $this->targetDirMaxMatches - \count($matches)) {
+            if ($this->asFiles || 0 < $offset) {
                 $dirname = sprintf('$this->targetDirs[%d]', $offset);
             }
 
@@ -1577,13 +2010,32 @@ EOF;
             return $dirname;
         }
 
+        return $this->doExport($value, true);
+    }
+
+    private function doExport($value, $resolveEnv = false)
+    {
         if (\is_string($value) && false !== strpos($value, "\n")) {
             $cleanParts = explode("\n", $value);
             $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts);
+            $export = implode('."\n".', $cleanParts);
+        } else {
+            $export = var_export($value, true);
+        }
 
-            return implode('."\n".', $cleanParts);
+        if ($resolveEnv && "'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) {
+            $export = $resolvedExport;
+            if (".''" === substr($export, -3)) {
+                $export = substr($export, 0, -3);
+                if ("'" === $export[1]) {
+                    $export = substr_replace($export, '', 18, 7);
+                }
+            }
+            if ("'" === $export[1]) {
+                $export = substr($export, 3);
+            }
         }
 
-        return var_export($value, true);
+        return $export;
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Dumper/XmlDumper.php b/civicrm/vendor/symfony/dependency-injection/Dumper/XmlDumper.php
index 5a85d67ddc..eff421ec4e 100644
--- a/civicrm/vendor/symfony/dependency-injection/Dumper/XmlDumper.php
+++ b/civicrm/vendor/symfony/dependency-injection/Dumper/XmlDumper.php
@@ -12,6 +12,9 @@
 namespace Symfony\Component\DependencyInjection\Dumper;
 
 use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -37,14 +40,14 @@ class XmlDumper extends Dumper
      *
      * @return string An xml string representing of the service container
      */
-    public function dump(array $options = array())
+    public function dump(array $options = [])
     {
         $this->document = new \DOMDocument('1.0', 'utf-8');
         $this->document->formatOutput = true;
 
         $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container');
         $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
-        $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd');
+        $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd');
 
         $this->addParameters($container);
         $this->addServices($container);
@@ -53,7 +56,7 @@ class XmlDumper extends Dumper
         $xml = $this->document->saveXML();
         $this->document = null;
 
-        return $xml;
+        return $this->container->resolveEnvPlaceholders($xml);
     }
 
     private function addParameters(\DOMElement $parent)
@@ -63,7 +66,7 @@ class XmlDumper extends Dumper
             return;
         }
 
-        if ($this->container->isFrozen()) {
+        if ($this->container->isCompiled()) {
             $data = $this->escape($data);
         }
 
@@ -87,9 +90,8 @@ class XmlDumper extends Dumper
     /**
      * Adds a service.
      *
-     * @param Definition  $definition
-     * @param string      $id
-     * @param \DOMElement $parent
+     * @param Definition $definition
+     * @param string     $id
      */
     private function addService($definition, $id, \DOMElement $parent)
     {
@@ -104,30 +106,15 @@ class XmlDumper extends Dumper
 
             $service->setAttribute('class', $class);
         }
-        if ($definition->getFactoryMethod(false)) {
-            $service->setAttribute('factory-method', $definition->getFactoryMethod(false));
-        }
-        if ($definition->getFactoryClass(false)) {
-            $service->setAttribute('factory-class', $definition->getFactoryClass(false));
-        }
-        if ($definition->getFactoryService(false)) {
-            $service->setAttribute('factory-service', $definition->getFactoryService(false));
-        }
         if (!$definition->isShared()) {
             $service->setAttribute('shared', 'false');
         }
-        if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope(false)) {
-            $service->setAttribute('scope', $scope);
-        }
-        if (!$definition->isPublic()) {
-            $service->setAttribute('public', 'false');
+        if (!$definition->isPrivate()) {
+            $service->setAttribute('public', $definition->isPublic() ? 'true' : 'false');
         }
         if ($definition->isSynthetic()) {
             $service->setAttribute('synthetic', 'true');
         }
-        if ($definition->isSynchronized(false)) {
-            $service->setAttribute('synchronized', 'true');
-        }
         if ($definition->isLazy()) {
             $service->setAttribute('lazy', 'true');
         }
@@ -176,7 +163,9 @@ class XmlDumper extends Dumper
                 $this->addService($callable[0], null, $factory);
                 $factory->setAttribute('method', $callable[1]);
             } elseif (\is_array($callable)) {
-                $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
+                if (null !== $callable[0]) {
+                    $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
+                }
                 $factory->setAttribute('method', $callable[1]);
             } else {
                 $factory->setAttribute('function', $callable);
@@ -195,13 +184,17 @@ class XmlDumper extends Dumper
             $service->setAttribute('autowire', 'true');
         }
 
-        foreach ($definition->getAutowiringTypes() as $autowiringTypeValue) {
+        foreach ($definition->getAutowiringTypes(false) as $autowiringTypeValue) {
             $autowiringType = $this->document->createElement('autowiring-type');
             $autowiringType->appendChild($this->document->createTextNode($autowiringTypeValue));
 
             $service->appendChild($autowiringType);
         }
 
+        if ($definition->isAutoconfigured()) {
+            $service->setAttribute('autoconfigure', 'true');
+        }
+
         if ($definition->isAbstract()) {
             $service->setAttribute('abstract', 'true');
         }
@@ -227,17 +220,15 @@ class XmlDumper extends Dumper
     /**
      * Adds a service alias.
      *
-     * @param string      $alias
-     * @param Alias       $id
-     * @param \DOMElement $parent
+     * @param string $alias
      */
     private function addServiceAlias($alias, Alias $id, \DOMElement $parent)
     {
         $service = $this->document->createElement('service');
         $service->setAttribute('id', $alias);
         $service->setAttribute('alias', $id);
-        if (!$id->isPublic()) {
-            $service->setAttribute('public', 'false');
+        if (!$id->isPrivate()) {
+            $service->setAttribute('public', $id->isPublic() ? 'true' : 'false');
         }
         $parent->appendChild($service);
     }
@@ -267,10 +258,8 @@ class XmlDumper extends Dumper
     /**
      * Converts parameters.
      *
-     * @param array       $parameters
-     * @param string      $type
-     * @param \DOMElement $parent
-     * @param string      $keyAttribute
+     * @param string $type
+     * @param string $keyAttribute
      */
     private function convertParameters(array $parameters, $type, \DOMElement $parent, $keyAttribute = 'key')
     {
@@ -281,20 +270,28 @@ class XmlDumper extends Dumper
                 $element->setAttribute($keyAttribute, $key);
             }
 
+            if ($value instanceof ServiceClosureArgument) {
+                $value = $value->getValues()[0];
+            }
             if (\is_array($value)) {
                 $element->setAttribute('type', 'collection');
                 $this->convertParameters($value, $type, $element, 'key');
+            } elseif ($value instanceof TaggedIteratorArgument) {
+                $element->setAttribute('type', 'tagged');
+                $element->setAttribute('tag', $value->getTag());
+            } elseif ($value instanceof IteratorArgument) {
+                $element->setAttribute('type', 'iterator');
+                $this->convertParameters($value->getValues(), $type, $element, 'key');
             } elseif ($value instanceof Reference) {
                 $element->setAttribute('type', 'service');
                 $element->setAttribute('id', (string) $value);
-                $behaviour = $value->getInvalidBehavior();
-                if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behaviour) {
+                $behavior = $value->getInvalidBehavior();
+                if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behavior) {
                     $element->setAttribute('on-invalid', 'null');
-                } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behaviour) {
+                } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behavior) {
                     $element->setAttribute('on-invalid', 'ignore');
-                }
-                if (!$value->isStrict(false)) {
-                    $element->setAttribute('strict', 'false');
+                } elseif (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE == $behavior) {
+                    $element->setAttribute('on-invalid', 'ignore_uninitialized');
                 }
             } elseif ($value instanceof Definition) {
                 $element->setAttribute('type', 'service');
@@ -304,9 +301,14 @@ class XmlDumper extends Dumper
                 $text = $this->document->createTextNode(self::phpToXml((string) $value));
                 $element->appendChild($text);
             } else {
-                if (\in_array($value, array('null', 'true', 'false'), true)) {
+                if (\in_array($value, ['null', 'true', 'false'], true)) {
                     $element->setAttribute('type', 'string');
                 }
+
+                if (\is_string($value) && (is_numeric($value) || preg_match('/^0b[01]*$/', $value) || preg_match('/^0x[0-9a-f]++$/i', $value))) {
+                    $element->setAttribute('type', 'string');
+                }
+
                 $text = $this->document->createTextNode(self::phpToXml($value));
                 $element->appendChild($text);
             }
@@ -321,7 +323,7 @@ class XmlDumper extends Dumper
      */
     private function escape(array $arguments)
     {
-        $args = array();
+        $args = [];
         foreach ($arguments as $k => $v) {
             if (\is_array($v)) {
                 $args[$k] = $this->escape($v);
diff --git a/civicrm/vendor/symfony/dependency-injection/Dumper/YamlDumper.php b/civicrm/vendor/symfony/dependency-injection/Dumper/YamlDumper.php
index 35d1218e25..1e795c7daf 100644
--- a/civicrm/vendor/symfony/dependency-injection/Dumper/YamlDumper.php
+++ b/civicrm/vendor/symfony/dependency-injection/Dumper/YamlDumper.php
@@ -12,6 +12,10 @@
 namespace Symfony\Component\DependencyInjection\Dumper;
 
 use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -19,6 +23,9 @@ use Symfony\Component\DependencyInjection\Parameter;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\ExpressionLanguage\Expression;
 use Symfony\Component\Yaml\Dumper as YmlDumper;
+use Symfony\Component\Yaml\Parser;
+use Symfony\Component\Yaml\Tag\TaggedValue;
+use Symfony\Component\Yaml\Yaml;
 
 /**
  * YamlDumper dumps a service container as a YAML string.
@@ -34,7 +41,7 @@ class YamlDumper extends Dumper
      *
      * @return string A YAML string representing of the service container
      */
-    public function dump(array $options = array())
+    public function dump(array $options = [])
     {
         if (!class_exists('Symfony\Component\Yaml\Dumper')) {
             throw new RuntimeException('Unable to dump the container as the Symfony Yaml Component is not installed.');
@@ -44,14 +51,13 @@ class YamlDumper extends Dumper
             $this->dumper = new YmlDumper();
         }
 
-        return $this->addParameters()."\n".$this->addServices();
+        return $this->container->resolveEnvPlaceholders($this->addParameters()."\n".$this->addServices());
     }
 
     /**
      * Adds a service.
      *
-     * @param string     $id
-     * @param Definition $definition
+     * @param string $id
      *
      * @return string
      */
@@ -66,14 +72,14 @@ class YamlDumper extends Dumper
             $code .= sprintf("        class: %s\n", $this->dumper->dump($class));
         }
 
-        if (!$definition->isPublic()) {
-            $code .= "        public: false\n";
+        if (!$definition->isPrivate()) {
+            $code .= sprintf("        public: %s\n", $definition->isPublic() ? 'true' : 'false');
         }
 
         $tagsCode = '';
         foreach ($definition->getTags() as $name => $tags) {
             foreach ($tags as $attributes) {
-                $att = array();
+                $att = [];
                 foreach ($attributes as $key => $value) {
                     $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value));
                 }
@@ -94,10 +100,6 @@ class YamlDumper extends Dumper
             $code .= "        synthetic: true\n";
         }
 
-        if ($definition->isSynchronized(false)) {
-            $code .= "        synchronized: true\n";
-        }
-
         if ($definition->isDeprecated()) {
             $code .= sprintf("        deprecated: %s\n", $this->dumper->dump($definition->getDeprecationMessage('%service_id%')));
         }
@@ -107,15 +109,15 @@ class YamlDumper extends Dumper
         }
 
         $autowiringTypesCode = '';
-        foreach ($definition->getAutowiringTypes() as $autowiringType) {
+        foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
             $autowiringTypesCode .= sprintf("            - %s\n", $this->dumper->dump($autowiringType));
         }
         if ($autowiringTypesCode) {
             $code .= sprintf("        autowiring_types:\n%s", $autowiringTypesCode);
         }
 
-        if ($definition->getFactoryClass(false)) {
-            $code .= sprintf("        factory_class: %s\n", $this->dumper->dump($definition->getFactoryClass(false)));
+        if ($definition->isAutoconfigured()) {
+            $code .= "        autoconfigure: true\n";
         }
 
         if ($definition->isAbstract()) {
@@ -126,14 +128,6 @@ class YamlDumper extends Dumper
             $code .= "        lazy: true\n";
         }
 
-        if ($definition->getFactoryMethod(false)) {
-            $code .= sprintf("        factory_method: %s\n", $this->dumper->dump($definition->getFactoryMethod(false)));
-        }
-
-        if ($definition->getFactoryService(false)) {
-            $code .= sprintf("        factory_service: %s\n", $this->dumper->dump($definition->getFactoryService(false)));
-        }
-
         if ($definition->getArguments()) {
             $code .= sprintf("        arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0));
         }
@@ -150,10 +144,6 @@ class YamlDumper extends Dumper
             $code .= "        shared: false\n";
         }
 
-        if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope(false)) {
-            $code .= sprintf("        scope: %s\n", $this->dumper->dump($scope));
-        }
-
         if (null !== $decorated = $definition->getDecoratedService()) {
             list($decorated, $renamedId, $priority) = $decorated;
             $code .= sprintf("        decorates: %s\n", $decorated);
@@ -180,17 +170,16 @@ class YamlDumper extends Dumper
      * Adds a service alias.
      *
      * @param string $alias
-     * @param Alias  $id
      *
      * @return string
      */
     private function addServiceAlias($alias, Alias $id)
     {
-        if ($id->isPublic()) {
+        if ($id->isPrivate()) {
             return sprintf("    %s: '@%s'\n", $alias, $id);
         }
 
-        return sprintf("    %s:\n        alias: %s\n        public: false\n", $alias, $id);
+        return sprintf("    %s:\n        alias: %s\n        public: %s\n", $alias, $id, $id->isPublic() ? 'true' : 'false');
     }
 
     /**
@@ -231,25 +220,23 @@ class YamlDumper extends Dumper
             return '';
         }
 
-        $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isFrozen());
+        $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isCompiled());
 
-        return $this->dumper->dump(array('parameters' => $parameters), 2);
+        return $this->dumper->dump(['parameters' => $parameters], 2);
     }
 
     /**
      * Dumps callable to YAML format.
      *
-     * @param callable $callable
-     *
-     * @return callable
+     * @param mixed $callable
      */
     private function dumpCallable($callable)
     {
         if (\is_array($callable)) {
             if ($callable[0] instanceof Reference) {
-                $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]);
+                $callable = [$this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]];
             } else {
-                $callable = array($callable[0], $callable[1]);
+                $callable = [$callable[0], $callable[1]];
             }
         }
 
@@ -267,8 +254,24 @@ class YamlDumper extends Dumper
      */
     private function dumpValue($value)
     {
+        if ($value instanceof ServiceClosureArgument) {
+            $value = $value->getValues()[0];
+        }
+        if ($value instanceof ArgumentInterface) {
+            if ($value instanceof TaggedIteratorArgument) {
+                return new TaggedValue('tagged', $value->getTag());
+            }
+            if ($value instanceof IteratorArgument) {
+                $tag = 'iterator';
+            } else {
+                throw new RuntimeException(sprintf('Unspecified Yaml tag for type "%s".', \get_class($value)));
+            }
+
+            return new TaggedValue($tag, $this->dumpValue($value->getValues()));
+        }
+
         if (\is_array($value)) {
-            $code = array();
+            $code = [];
             foreach ($value as $k => $v) {
                 $code[$k] = $this->dumpValue($v);
             }
@@ -280,6 +283,8 @@ class YamlDumper extends Dumper
             return $this->getParameterCall((string) $value);
         } elseif ($value instanceof Expression) {
             return $this->getExpressionCall((string) $value);
+        } elseif ($value instanceof Definition) {
+            return new TaggedValue('service', (new Parser())->parse("_:\n".$this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']);
         } elseif (\is_object($value) || \is_resource($value)) {
             throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
         }
@@ -297,8 +302,12 @@ class YamlDumper extends Dumper
      */
     private function getServiceCall($id, Reference $reference = null)
     {
-        if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
-            return sprintf('@?%s', $id);
+        if (null !== $reference) {
+            switch ($reference->getInvalidBehavior()) {
+                case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break;
+                case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id);
+                default: return sprintf('@?%s', $id);
+            }
         }
 
         return sprintf('@%s', $id);
@@ -324,14 +333,13 @@ class YamlDumper extends Dumper
     /**
      * Prepares parameters.
      *
-     * @param array $parameters
-     * @param bool  $escape
+     * @param bool $escape
      *
      * @return array
      */
     private function prepareParameters(array $parameters, $escape = true)
     {
-        $filtered = array();
+        $filtered = [];
         foreach ($parameters as $key => $value) {
             if (\is_array($value)) {
                 $value = $this->prepareParameters($value, $escape);
@@ -352,7 +360,7 @@ class YamlDumper extends Dumper
      */
     private function escape(array $arguments)
     {
-        $args = array();
+        $args = [];
         foreach ($arguments as $k => $v) {
             if (\is_array($v)) {
                 $args[$k] = $this->escape($v);
diff --git a/civicrm/vendor/symfony/dependency-injection/EnvVarProcessor.php b/civicrm/vendor/symfony/dependency-injection/EnvVarProcessor.php
new file mode 100644
index 0000000000..3410103764
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/EnvVarProcessor.php
@@ -0,0 +1,163 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection;
+
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class EnvVarProcessor implements EnvVarProcessorInterface
+{
+    private $container;
+
+    public function __construct(ContainerInterface $container)
+    {
+        $this->container = $container;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public static function getProvidedTypes()
+    {
+        return [
+            'base64' => 'string',
+            'bool' => 'bool',
+            'const' => 'bool|int|float|string|array',
+            'file' => 'string',
+            'float' => 'float',
+            'int' => 'int',
+            'json' => 'array',
+            'resolve' => 'string',
+            'string' => 'string',
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getEnv($prefix, $name, \Closure $getEnv)
+    {
+        $i = strpos($name, ':');
+
+        if ('file' === $prefix) {
+            if (!is_scalar($file = $getEnv($name))) {
+                throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name));
+            }
+            if (!file_exists($file)) {
+                throw new RuntimeException(sprintf('Env "file:%s" not found: "%s" does not exist.', $name, $file));
+            }
+
+            return file_get_contents($file);
+        }
+
+        if (false !== $i || 'string' !== $prefix) {
+            if (null === $env = $getEnv($name)) {
+                return null;
+            }
+        } elseif (isset($_ENV[$name])) {
+            $env = $_ENV[$name];
+        } elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
+            $env = $_SERVER[$name];
+        } elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues
+            if (!$this->container->hasParameter("env($name)")) {
+                throw new EnvNotFoundException($name);
+            }
+
+            if (null === $env = $this->container->getParameter("env($name)")) {
+                return null;
+            }
+        }
+
+        if (!is_scalar($env)) {
+            throw new RuntimeException(sprintf('Non-scalar env var "%s" cannot be cast to "%s".', $name, $prefix));
+        }
+
+        if ('string' === $prefix) {
+            return (string) $env;
+        }
+
+        if ('bool' === $prefix) {
+            return (bool) self::phpize($env);
+        }
+
+        if ('int' === $prefix) {
+            if (!is_numeric($env = self::phpize($env))) {
+                throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to int.', $name));
+            }
+
+            return (int) $env;
+        }
+
+        if ('float' === $prefix) {
+            if (!is_numeric($env = self::phpize($env))) {
+                throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to float.', $name));
+            }
+
+            return (float) $env;
+        }
+
+        if ('const' === $prefix) {
+            if (!\defined($env)) {
+                throw new RuntimeException(sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env));
+            }
+
+            return \constant($env);
+        }
+
+        if ('base64' === $prefix) {
+            return base64_decode($env);
+        }
+
+        if ('json' === $prefix) {
+            $env = json_decode($env, true);
+
+            if (JSON_ERROR_NONE !== json_last_error()) {
+                throw new RuntimeException(sprintf('Invalid JSON in env var "%s": '.json_last_error_msg(), $name));
+            }
+
+            if (!\is_array($env)) {
+                throw new RuntimeException(sprintf('Invalid JSON env var "%s": array expected, "%s" given.', $name, \gettype($env)));
+            }
+
+            return $env;
+        }
+
+        if ('resolve' === $prefix) {
+            return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) {
+                if (!isset($match[1])) {
+                    return '%';
+                }
+                $value = $this->container->getParameter($match[1]);
+                if (!is_scalar($value)) {
+                    throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, \gettype($value)));
+                }
+
+                return $value;
+            }, $env);
+        }
+
+        throw new RuntimeException(sprintf('Unsupported env var prefix "%s".', $prefix));
+    }
+
+    private static function phpize($value)
+    {
+        if (!class_exists(XmlUtils::class)) {
+            throw new RuntimeException('The Symfony Config component is required to cast env vars to "bool", "int" or "float".');
+        }
+
+        return XmlUtils::phpize($value);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php b/civicrm/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php
new file mode 100644
index 0000000000..654fe55e98
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * The EnvVarProcessorInterface is implemented by objects that manage environment-like variables.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface EnvVarProcessorInterface
+{
+    /**
+     * Returns the value of the given variable as managed by the current instance.
+     *
+     * @param string   $prefix The namespace of the variable
+     * @param string   $name   The name of the variable within the namespace
+     * @param \Closure $getEnv A closure that allows fetching more env vars
+     *
+     * @return mixed
+     *
+     * @throws RuntimeException on error
+     */
+    public function getEnv($prefix, $name, \Closure $getEnv);
+
+    /**
+     * @return string[] The PHP-types managed by getEnv(), keyed by prefixes
+     */
+    public static function getProvidedTypes();
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php b/civicrm/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php
new file mode 100644
index 0000000000..145cd8cbdc
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Exception;
+
+/**
+ * Thrown when a definition cannot be autowired.
+ */
+class AutowiringFailedException extends RuntimeException
+{
+    private $serviceId;
+
+    public function __construct($serviceId, $message = '', $code = 0, \Exception $previous = null)
+    {
+        $this->serviceId = $serviceId;
+
+        parent::__construct($message, $code, $previous);
+    }
+
+    public function getServiceId()
+    {
+        return $this->serviceId;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php b/civicrm/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php
new file mode 100644
index 0000000000..577095e88b
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Exception;
+
+/**
+ * This exception is thrown when an environment variable is not found.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class EnvNotFoundException extends InvalidArgumentException
+{
+    public function __construct($name)
+    {
+        parent::__construct(sprintf('Environment variable not found: "%s".', $name));
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/EnvParameterException.php b/civicrm/vendor/symfony/dependency-injection/Exception/EnvParameterException.php
new file mode 100644
index 0000000000..3839a4633b
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Exception/EnvParameterException.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Exception;
+
+/**
+ * This exception wraps exceptions whose messages contain a reference to an env parameter.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class EnvParameterException extends InvalidArgumentException
+{
+    public function __construct(array $envs, \Exception $previous = null, $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.')
+    {
+        parent::__construct(sprintf($message, implode('", "', $envs)), 0, $previous);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php b/civicrm/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php
index f5e9099f11..5bec478695 100644
--- a/civicrm/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php
+++ b/civicrm/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php
@@ -11,12 +11,14 @@
 
 namespace Symfony\Component\DependencyInjection\Exception;
 
+use Psr\Container\ContainerExceptionInterface;
+
 /**
  * Base ExceptionInterface for Dependency Injection component.
  *
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
  */
-interface ExceptionInterface
+interface ExceptionInterface extends ContainerExceptionInterface
 {
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/InactiveScopeException.php b/civicrm/vendor/symfony/dependency-injection/Exception/InactiveScopeException.php
deleted file mode 100644
index 6b3dd3ebb1..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/Exception/InactiveScopeException.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Exception;
-
-/**
- * This exception is thrown when you try to create a service of an inactive scope.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
-class InactiveScopeException extends RuntimeException
-{
-    private $serviceId;
-    private $scope;
-
-    public function __construct($serviceId, $scope, \Exception $previous = null)
-    {
-        parent::__construct(sprintf('You cannot create a service ("%s") of an inactive scope ("%s").', $serviceId, $scope), 0, $previous);
-
-        $this->serviceId = $serviceId;
-        $this->scope = $scope;
-    }
-
-    public function getServiceId()
-    {
-        return $this->serviceId;
-    }
-
-    public function getScope()
-    {
-        return $this->scope;
-    }
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php b/civicrm/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php
index 1d97830f4a..b08f2e8559 100644
--- a/civicrm/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php
+++ b/civicrm/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php
@@ -22,20 +22,23 @@ class ParameterNotFoundException extends InvalidArgumentException
     private $sourceId;
     private $sourceKey;
     private $alternatives;
+    private $nonNestedAlternative;
 
     /**
-     * @param string     $key          The requested parameter key
-     * @param string     $sourceId     The service id that references the non-existent parameter
-     * @param string     $sourceKey    The parameter key that references the non-existent parameter
-     * @param \Exception $previous     The previous exception
-     * @param string[]   $alternatives Some parameter name alternatives
+     * @param string      $key                  The requested parameter key
+     * @param string      $sourceId             The service id that references the non-existent parameter
+     * @param string      $sourceKey            The parameter key that references the non-existent parameter
+     * @param \Exception  $previous             The previous exception
+     * @param string[]    $alternatives         Some parameter name alternatives
+     * @param string|null $nonNestedAlternative The alternative parameter name when the user expected dot notation for nested parameters
      */
-    public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array())
+    public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = [], $nonNestedAlternative = null)
     {
         $this->key = $key;
         $this->sourceId = $sourceId;
         $this->sourceKey = $sourceKey;
         $this->alternatives = $alternatives;
+        $this->nonNestedAlternative = $nonNestedAlternative;
 
         parent::__construct('', 0, $previous);
 
@@ -59,6 +62,8 @@ class ParameterNotFoundException extends InvalidArgumentException
                 $this->message .= ' Did you mean one of these: "';
             }
             $this->message .= implode('", "', $this->alternatives).'"?';
+        } elseif (null !== $this->nonNestedAlternative) {
+            $this->message .= ' You cannot access nested array items, do you want to inject "'.$this->nonNestedAlternative.'" instead?';
         }
     }
 
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/ScopeCrossingInjectionException.php b/civicrm/vendor/symfony/dependency-injection/Exception/ScopeCrossingInjectionException.php
deleted file mode 100644
index 661fbab369..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/Exception/ScopeCrossingInjectionException.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Exception;
-
-/**
- * This exception is thrown when the a scope crossing injection is detected.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
-class ScopeCrossingInjectionException extends RuntimeException
-{
-    private $sourceServiceId;
-    private $sourceScope;
-    private $destServiceId;
-    private $destScope;
-
-    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null)
-    {
-        parent::__construct(sprintf(
-            'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. '
-           .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or '
-           .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.',
-           $sourceServiceId,
-           $destServiceId,
-           $sourceServiceId,
-           $destScope,
-           $sourceScope,
-           $destScope
-        ), 0, $previous);
-
-        $this->sourceServiceId = $sourceServiceId;
-        $this->sourceScope = $sourceScope;
-        $this->destServiceId = $destServiceId;
-        $this->destScope = $destScope;
-    }
-
-    public function getSourceServiceId()
-    {
-        return $this->sourceServiceId;
-    }
-
-    public function getSourceScope()
-    {
-        return $this->sourceScope;
-    }
-
-    public function getDestServiceId()
-    {
-        return $this->destServiceId;
-    }
-
-    public function getDestScope()
-    {
-        return $this->destScope;
-    }
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/ScopeWideningInjectionException.php b/civicrm/vendor/symfony/dependency-injection/Exception/ScopeWideningInjectionException.php
deleted file mode 100644
index 86a6684195..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/Exception/ScopeWideningInjectionException.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Exception;
-
-/**
- * Thrown when a scope widening injection is detected.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- */
-class ScopeWideningInjectionException extends RuntimeException
-{
-    private $sourceServiceId;
-    private $sourceScope;
-    private $destServiceId;
-    private $destScope;
-
-    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null)
-    {
-        parent::__construct(sprintf(
-            'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. '
-           .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. '
-           .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.',
-           $sourceServiceId,
-           $destServiceId,
-           $sourceServiceId,
-           $destScope,
-           $destServiceId
-        ), 0, $previous);
-
-        $this->sourceServiceId = $sourceServiceId;
-        $this->sourceScope = $sourceScope;
-        $this->destServiceId = $destServiceId;
-        $this->destScope = $destScope;
-    }
-
-    public function getSourceServiceId()
-    {
-        return $this->sourceServiceId;
-    }
-
-    public function getSourceScope()
-    {
-        return $this->sourceScope;
-    }
-
-    public function getDestServiceId()
-    {
-        return $this->destServiceId;
-    }
-
-    public function getDestScope()
-    {
-        return $this->destScope;
-    }
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php b/civicrm/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php
index 620ed98e68..280dabf33f 100644
--- a/civicrm/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php
+++ b/civicrm/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php
@@ -11,19 +11,24 @@
 
 namespace Symfony\Component\DependencyInjection\Exception;
 
+use Psr\Container\NotFoundExceptionInterface;
+
 /**
  * This exception is thrown when a non-existent service is requested.
  *
  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
-class ServiceNotFoundException extends InvalidArgumentException
+class ServiceNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface
 {
     private $id;
     private $sourceId;
+    private $alternatives;
 
-    public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = array())
+    public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = [], $msg = null)
     {
-        if (null === $sourceId) {
+        if (null !== $msg) {
+            // no-op
+        } elseif (null === $sourceId) {
             $msg = sprintf('You have requested a non-existent service "%s".', $id);
         } else {
             $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id);
@@ -42,6 +47,7 @@ class ServiceNotFoundException extends InvalidArgumentException
 
         $this->id = $id;
         $this->sourceId = $sourceId;
+        $this->alternatives = $alternatives;
     }
 
     public function getId()
@@ -53,4 +59,9 @@ class ServiceNotFoundException extends InvalidArgumentException
     {
         return $this->sourceId;
     }
+
+    public function getAlternatives()
+    {
+        return $this->alternatives;
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/ExpressionLanguage.php b/civicrm/vendor/symfony/dependency-injection/ExpressionLanguage.php
index acc97bcf49..0c1780b8b1 100644
--- a/civicrm/vendor/symfony/dependency-injection/ExpressionLanguage.php
+++ b/civicrm/vendor/symfony/dependency-injection/ExpressionLanguage.php
@@ -12,7 +12,6 @@
 namespace Symfony\Component\DependencyInjection;
 
 use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
-use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
 
 /**
  * Adds some function to the default ExpressionLanguage.
@@ -23,10 +22,13 @@ use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
  */
 class ExpressionLanguage extends BaseExpressionLanguage
 {
-    public function __construct(ParserCacheInterface $cache = null, array $providers = array())
+    /**
+     * {@inheritdoc}
+     */
+    public function __construct($cache = null, array $providers = [], callable $serviceCompiler = null)
     {
         // prepend the default provider to let users override it easily
-        array_unshift($providers, new ExpressionLanguageProvider());
+        array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler));
 
         parent::__construct($cache, $providers);
     }
diff --git a/civicrm/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php b/civicrm/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php
index ce6d69522e..9198ca0a40 100644
--- a/civicrm/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php
+++ b/civicrm/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php
@@ -24,10 +24,17 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
  */
 class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
 {
+    private $serviceCompiler;
+
+    public function __construct(callable $serviceCompiler = null)
+    {
+        $this->serviceCompiler = $serviceCompiler;
+    }
+
     public function getFunctions()
     {
-        return array(
-            new ExpressionFunction('service', function ($arg) {
+        return [
+            new ExpressionFunction('service', $this->serviceCompiler ?: function ($arg) {
                 return sprintf('$this->get(%s)', $arg);
             }, function (array $variables, $value) {
                 return $variables['container']->get($value);
@@ -38,6 +45,6 @@ class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
             }, function (array $variables, $value) {
                 return $variables['container']->getParameter($value);
             }),
-        );
+        ];
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Extension/Extension.php b/civicrm/vendor/symfony/dependency-injection/Extension/Extension.php
index b56a2ccff0..00fa9dc8da 100644
--- a/civicrm/vendor/symfony/dependency-injection/Extension/Extension.php
+++ b/civicrm/vendor/symfony/dependency-injection/Extension/Extension.php
@@ -13,7 +13,6 @@ namespace Symfony\Component\DependencyInjection\Extension;
 
 use Symfony\Component\Config\Definition\ConfigurationInterface;
 use Symfony\Component\Config\Definition\Processor;
-use Symfony\Component\Config\Resource\FileResource;
 use Symfony\Component\DependencyInjection\Container;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
@@ -26,6 +25,8 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  */
 abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface
 {
+    private $processedConfigs = [];
+
     /**
      * {@inheritdoc}
      */
@@ -64,7 +65,7 @@ abstract class Extension implements ExtensionInterface, ConfigurationExtensionIn
      */
     public function getAlias()
     {
-        $className = \get_class($this);
+        $className = static::class;
         if ('Extension' != substr($className, -9)) {
             throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.');
         }
@@ -78,25 +79,39 @@ abstract class Extension implements ExtensionInterface, ConfigurationExtensionIn
      */
     public function getConfiguration(array $config, ContainerBuilder $container)
     {
-        $reflected = new \ReflectionClass($this);
-        $namespace = $reflected->getNamespaceName();
-
-        $class = $namespace.'\\Configuration';
-        if (class_exists($class)) {
-            $r = new \ReflectionClass($class);
-            $container->addResource(new FileResource($r->getFileName()));
+        $class = static::class;
 
-            if (!method_exists($class, '__construct')) {
-                return new $class();
-            }
+        if (false !== strpos($class, "\0")) {
+            return null; // ignore anonymous classes
         }
+
+        $class = substr_replace($class, '\Configuration', strrpos($class, '\\'));
+        $class = $container->getReflectionClass($class);
+        $constructor = $class ? $class->getConstructor() : null;
+
+        return $class && (!$constructor || !$constructor->getNumberOfRequiredParameters()) ? $class->newInstance() : null;
     }
 
+    /**
+     * @return array
+     */
     final protected function processConfiguration(ConfigurationInterface $configuration, array $configs)
     {
         $processor = new Processor();
 
-        return $processor->processConfiguration($configuration, $configs);
+        return $this->processedConfigs[] = $processor->processConfiguration($configuration, $configs);
+    }
+
+    /**
+     * @internal
+     */
+    final public function getProcessedConfigs()
+    {
+        try {
+            return $this->processedConfigs;
+        } finally {
+            $this->processedConfigs = [];
+        }
     }
 
     /**
@@ -106,7 +121,7 @@ abstract class Extension implements ExtensionInterface, ConfigurationExtensionIn
      */
     protected function isConfigEnabled(ContainerBuilder $container, array $config)
     {
-        if (!array_key_exists('enabled', $config)) {
+        if (!\array_key_exists('enabled', $config)) {
             throw new InvalidArgumentException("The config array has no 'enabled' key.");
         }
 
diff --git a/civicrm/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php b/civicrm/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php
index 18de31272f..6a7a2cf023 100644
--- a/civicrm/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php
+++ b/civicrm/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php
@@ -37,7 +37,7 @@ interface ExtensionInterface
     /**
      * Returns the base path for the XSD files.
      *
-     * @return string The XSD base path
+     * @return string|false
      */
     public function getXsdValidationBasePath();
 
diff --git a/civicrm/vendor/symfony/dependency-injection/IntrospectableContainerInterface.php b/civicrm/vendor/symfony/dependency-injection/IntrospectableContainerInterface.php
deleted file mode 100644
index 4aa0059992..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/IntrospectableContainerInterface.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection;
-
-/**
- * IntrospectableContainerInterface defines additional introspection functionality
- * for containers, allowing logic to be implemented based on a Container's state.
- *
- * @author Evan Villemez <evillemez@gmail.com>
- *
- * @deprecated since version 2.8, to be merged with ContainerInterface in 3.0.
- */
-interface IntrospectableContainerInterface extends ContainerInterface
-{
-    /**
-     * Check for whether or not a service has been initialized.
-     *
-     * @param string $id
-     *
-     * @return bool true if the service has been initialized, false otherwise
-     */
-    public function initialized($id);
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/LICENSE b/civicrm/vendor/symfony/dependency-injection/LICENSE
index 21d7fb9e2f..9e936ec044 100644
--- a/civicrm/vendor/symfony/dependency-injection/LICENSE
+++ b/civicrm/vendor/symfony/dependency-injection/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2018 Fabien Potencier
+Copyright (c) 2004-2020 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/civicrm/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php b/civicrm/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php
index 3b0b57ef0f..532e768684 100644
--- a/civicrm/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php
+++ b/civicrm/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php
@@ -17,7 +17,7 @@ use Symfony\Component\DependencyInjection\Definition;
 /**
  * {@inheritdoc}
  *
- * Noop proxy instantiator - simply produces the real service instead of a proxy instance.
+ * Noop proxy instantiator - produces the real service instead of a proxy instance.
  *
  * @author Marco Pivetta <ocramius@gmail.com>
  */
diff --git a/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php b/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php
index 502c72abaf..3946eafafd 100644
--- a/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php
+++ b/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php
@@ -30,12 +30,11 @@ interface DumperInterface
     /**
      * Generates the code to be used to instantiate a proxy in the dumped factory code.
      *
-     * @param Definition $definition
-     * @param string     $id         Service identifier
+     * @param string $id Service identifier
      *
      * @return string
      */
-    public function getProxyFactoryCode(Definition $definition, $id);
+    public function getProxyFactoryCode(Definition $definition, $id/**, $factoryCode = null */);
 
     /**
      * Generates the code for the lazy proxy.
diff --git a/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php b/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php
index 30911d3a5e..67f9fae94d 100644
--- a/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php
+++ b/civicrm/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php
@@ -17,6 +17,8 @@ use Symfony\Component\DependencyInjection\Definition;
  * Null dumper, negates any proxy code generation for any given service definition.
  *
  * @author Marco Pivetta <ocramius@gmail.com>
+ *
+ * @final since version 3.3
  */
 class NullDumper implements DumperInterface
 {
@@ -31,7 +33,7 @@ class NullDumper implements DumperInterface
     /**
      * {@inheritdoc}
      */
-    public function getProxyFactoryCode(Definition $definition, $id)
+    public function getProxyFactoryCode(Definition $definition, $id, $factoryCode = null)
     {
         return '';
     }
diff --git a/civicrm/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php b/civicrm/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php
new file mode 100644
index 0000000000..cb19c729c1
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\LazyProxy;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @internal
+ */
+class ProxyHelper
+{
+    /**
+     * @return string|null The FQCN or builtin name of the type hint, or null when the type hint references an invalid self|parent context
+     */
+    public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionParameter $p = null, $noBuiltin = false)
+    {
+        if ($p instanceof \ReflectionParameter) {
+            if (method_exists($p, 'getType')) {
+                $type = $p->getType();
+            } elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $p, $type)) {
+                $name = $type = $type[1];
+
+                if ('callable' === $name || 'array' === $name) {
+                    return $noBuiltin ? null : $name;
+                }
+            }
+        } else {
+            $type = method_exists($r, 'getReturnType') ? $r->getReturnType() : null;
+        }
+        if (!$type) {
+            return null;
+        }
+        if (!\is_string($type)) {
+            $name = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString();
+
+            if ($type->isBuiltin()) {
+                return $noBuiltin ? null : $name;
+            }
+        }
+        $lcName = strtolower($name);
+        $prefix = $noBuiltin ? '' : '\\';
+
+        if ('self' !== $lcName && 'parent' !== $lcName) {
+            return $prefix.$name;
+        }
+        if (!$r instanceof \ReflectionMethod) {
+            return null;
+        }
+        if ('self' === $lcName) {
+            return $prefix.$r->getDeclaringClass()->name;
+        }
+
+        return ($parent = $r->getDeclaringClass()->getParentClass()) ? $prefix.$parent->name : null;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php
new file mode 100644
index 0000000000..428683ef4c
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php
@@ -0,0 +1,87 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Parameter;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\ExpressionLanguage\Expression;
+
+abstract class AbstractConfigurator
+{
+    const FACTORY = 'unknown';
+
+    /** @internal */
+    protected $definition;
+
+    public function __call($method, $args)
+    {
+        if (method_exists($this, 'set'.$method)) {
+            return \call_user_func_array([$this, 'set'.$method], $args);
+        }
+
+        throw new \BadMethodCallException(sprintf('Call to undefined method "%s::%s()".', static::class, $method));
+    }
+
+    /**
+     * Checks that a value is valid, optionally replacing Definition and Reference configurators by their configure value.
+     *
+     * @param mixed $value
+     * @param bool  $allowServices whether Definition and Reference are allowed; by default, only scalars and arrays are
+     *
+     * @return mixed the value, optionally cast to a Definition/Reference
+     */
+    public static function processValue($value, $allowServices = false)
+    {
+        if (\is_array($value)) {
+            foreach ($value as $k => $v) {
+                $value[$k] = static::processValue($v, $allowServices);
+            }
+
+            return $value;
+        }
+
+        if ($value instanceof ReferenceConfigurator) {
+            return new Reference($value->id, $value->invalidBehavior);
+        }
+
+        if ($value instanceof InlineServiceConfigurator) {
+            $def = $value->definition;
+            $value->definition = null;
+
+            return $def;
+        }
+
+        if ($value instanceof self) {
+            throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY));
+        }
+
+        switch (true) {
+            case null === $value:
+            case is_scalar($value):
+                return $value;
+
+            case $value instanceof ArgumentInterface:
+            case $value instanceof Definition:
+            case $value instanceof Expression:
+            case $value instanceof Parameter:
+            case $value instanceof Reference:
+                if ($allowServices) {
+                    return $value;
+                }
+        }
+
+        throw new InvalidArgumentException(sprintf('Cannot use values of type "%s" in service configuration files.', \is_object($value) ? \get_class($value) : \gettype($value)));
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php
new file mode 100644
index 0000000000..0a565787fd
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php
@@ -0,0 +1,117 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+
+abstract class AbstractServiceConfigurator extends AbstractConfigurator
+{
+    protected $parent;
+    protected $id;
+    private $defaultTags = [];
+
+    public function __construct(ServicesConfigurator $parent, Definition $definition, $id = null, array $defaultTags = [])
+    {
+        $this->parent = $parent;
+        $this->definition = $definition;
+        $this->id = $id;
+        $this->defaultTags = $defaultTags;
+    }
+
+    public function __destruct()
+    {
+        // default tags should be added last
+        foreach ($this->defaultTags as $name => $attributes) {
+            foreach ($attributes as $attributes) {
+                $this->definition->addTag($name, $attributes);
+            }
+        }
+        $this->defaultTags = [];
+    }
+
+    /**
+     * Registers a service.
+     *
+     * @param string      $id
+     * @param string|null $class
+     *
+     * @return ServiceConfigurator
+     */
+    final public function set($id, $class = null)
+    {
+        $this->__destruct();
+
+        return $this->parent->set($id, $class);
+    }
+
+    /**
+     * Creates an alias.
+     *
+     * @param string $id
+     * @param string $referencedId
+     *
+     * @return AliasConfigurator
+     */
+    final public function alias($id, $referencedId)
+    {
+        $this->__destruct();
+
+        return $this->parent->alias($id, $referencedId);
+    }
+
+    /**
+     * Registers a PSR-4 namespace using a glob pattern.
+     *
+     * @param string $namespace
+     * @param string $resource
+     *
+     * @return PrototypeConfigurator
+     */
+    final public function load($namespace, $resource)
+    {
+        $this->__destruct();
+
+        return $this->parent->load($namespace, $resource);
+    }
+
+    /**
+     * Gets an already defined service definition.
+     *
+     * @param string $id
+     *
+     * @return ServiceConfigurator
+     *
+     * @throws ServiceNotFoundException if the service definition does not exist
+     */
+    final public function get($id)
+    {
+        $this->__destruct();
+
+        return $this->parent->get($id);
+    }
+
+    /**
+     * Registers a service.
+     *
+     * @param string      $id
+     * @param string|null $class
+     *
+     * @return ServiceConfigurator
+     */
+    final public function __invoke($id, $class = null)
+    {
+        $this->__destruct();
+
+        return $this->parent->set($id, $class);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php
new file mode 100644
index 0000000000..cb00f58c04
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Alias;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class AliasConfigurator extends AbstractServiceConfigurator
+{
+    const FACTORY = 'alias';
+
+    use Traits\PublicTrait;
+
+    public function __construct(ServicesConfigurator $parent, Alias $alias)
+    {
+        $this->parent = $parent;
+        $this->definition = $alias;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php
new file mode 100644
index 0000000000..f2e5ccf8b0
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php
@@ -0,0 +1,135 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
+use Symfony\Component\ExpressionLanguage\Expression;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ContainerConfigurator extends AbstractConfigurator
+{
+    const FACTORY = 'container';
+
+    private $container;
+    private $loader;
+    private $instanceof;
+    private $path;
+    private $file;
+
+    public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, $path, $file)
+    {
+        $this->container = $container;
+        $this->loader = $loader;
+        $this->instanceof = &$instanceof;
+        $this->path = $path;
+        $this->file = $file;
+    }
+
+    final public function extension($namespace, array $config)
+    {
+        if (!$this->container->hasExtension($namespace)) {
+            $extensions = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions()));
+            throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $namespace, $this->file, $namespace, $extensions ? implode('", "', $extensions) : 'none'));
+        }
+
+        $this->container->loadFromExtension($namespace, static::processValue($config));
+    }
+
+    final public function import($resource, $type = null, $ignoreErrors = false)
+    {
+        $this->loader->setCurrentDir(\dirname($this->path));
+        $this->loader->import($resource, $type, $ignoreErrors, $this->file);
+    }
+
+    /**
+     * @return ParametersConfigurator
+     */
+    final public function parameters()
+    {
+        return new ParametersConfigurator($this->container);
+    }
+
+    /**
+     * @return ServicesConfigurator
+     */
+    final public function services()
+    {
+        return new ServicesConfigurator($this->container, $this->loader, $this->instanceof);
+    }
+}
+
+/**
+ * Creates a service reference.
+ *
+ * @param string $id
+ *
+ * @return ReferenceConfigurator
+ */
+function ref($id)
+{
+    return new ReferenceConfigurator($id);
+}
+
+/**
+ * Creates an inline service.
+ *
+ * @param string|null $class
+ *
+ * @return InlineServiceConfigurator
+ */
+function inline($class = null)
+{
+    return new InlineServiceConfigurator(new Definition($class));
+}
+
+/**
+ * Creates a lazy iterator.
+ *
+ * @param ReferenceConfigurator[] $values
+ *
+ * @return IteratorArgument
+ */
+function iterator(array $values)
+{
+    return new IteratorArgument(AbstractConfigurator::processValue($values, true));
+}
+
+/**
+ * Creates a lazy iterator by tag name.
+ *
+ * @param string $tag
+ *
+ * @return TaggedIteratorArgument
+ */
+function tagged($tag)
+{
+    return new TaggedIteratorArgument($tag);
+}
+
+/**
+ * Creates an expression.
+ *
+ * @param string $expression an expression
+ *
+ * @return Expression
+ */
+function expr($expression)
+{
+    return new Expression($expression);
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php
new file mode 100644
index 0000000000..662ba95d1b
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @method InstanceofConfigurator instanceof(string $fqcn)
+ */
+class DefaultsConfigurator extends AbstractServiceConfigurator
+{
+    const FACTORY = 'defaults';
+
+    use Traits\AutoconfigureTrait;
+    use Traits\AutowireTrait;
+    use Traits\BindTrait;
+    use Traits\PublicTrait;
+
+    /**
+     * Adds a tag for this definition.
+     *
+     * @param string $name       The tag name
+     * @param array  $attributes An array of attributes
+     *
+     * @return $this
+     *
+     * @throws InvalidArgumentException when an invalid tag name or attribute is provided
+     */
+    final public function tag($name, array $attributes = [])
+    {
+        if (!\is_string($name) || '' === $name) {
+            throw new InvalidArgumentException('The tag name in "_defaults" must be a non-empty string.');
+        }
+
+        foreach ($attributes as $attribute => $value) {
+            if (!is_scalar($value) && null !== $value) {
+                throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type.', $name, $attribute));
+            }
+        }
+
+        $this->definition->addTag($name, $attributes);
+
+        return $this;
+    }
+
+    /**
+     * Defines an instanceof-conditional to be applied to following service definitions.
+     *
+     * @param string $fqcn
+     *
+     * @return InstanceofConfigurator
+     */
+    final protected function setInstanceof($fqcn)
+    {
+        return $this->parent->instanceof($fqcn);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php
new file mode 100644
index 0000000000..362b374e55
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Definition;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class InlineServiceConfigurator extends AbstractConfigurator
+{
+    const FACTORY = 'inline';
+
+    use Traits\ArgumentTrait;
+    use Traits\AutowireTrait;
+    use Traits\BindTrait;
+    use Traits\FactoryTrait;
+    use Traits\FileTrait;
+    use Traits\LazyTrait;
+    use Traits\ParentTrait;
+    use Traits\TagTrait;
+
+    public function __construct(Definition $definition)
+    {
+        $this->definition = $definition;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php
new file mode 100644
index 0000000000..629874d19c
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @method InstanceofConfigurator instanceof(string $fqcn)
+ */
+class InstanceofConfigurator extends AbstractServiceConfigurator
+{
+    const FACTORY = 'instanceof';
+
+    use Traits\AutowireTrait;
+    use Traits\CallTrait;
+    use Traits\ConfiguratorTrait;
+    use Traits\LazyTrait;
+    use Traits\PropertyTrait;
+    use Traits\PublicTrait;
+    use Traits\ShareTrait;
+    use Traits\TagTrait;
+
+    /**
+     * Defines an instanceof-conditional to be applied to following service definitions.
+     *
+     * @param string $fqcn
+     *
+     * @return self
+     */
+    final protected function setInstanceof($fqcn)
+    {
+        return $this->parent->instanceof($fqcn);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php
new file mode 100644
index 0000000000..9585b1a4b5
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ParametersConfigurator extends AbstractConfigurator
+{
+    const FACTORY = 'parameters';
+
+    private $container;
+
+    public function __construct(ContainerBuilder $container)
+    {
+        $this->container = $container;
+    }
+
+    /**
+     * Creates a parameter.
+     *
+     * @param string $name
+     * @param mixed  $value
+     *
+     * @return $this
+     */
+    final public function set($name, $value)
+    {
+        $this->container->setParameter($name, static::processValue($value, true));
+
+        return $this;
+    }
+
+    /**
+     * Creates a parameter.
+     *
+     * @param string $name
+     * @param mixed  $value
+     *
+     * @return $this
+     */
+    final public function __invoke($name, $value)
+    {
+        return $this->set($name, $value);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php
new file mode 100644
index 0000000000..3d844798d4
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php
@@ -0,0 +1,87 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class PrototypeConfigurator extends AbstractServiceConfigurator
+{
+    const FACTORY = 'load';
+
+    use Traits\AbstractTrait;
+    use Traits\ArgumentTrait;
+    use Traits\AutoconfigureTrait;
+    use Traits\AutowireTrait;
+    use Traits\BindTrait;
+    use Traits\CallTrait;
+    use Traits\ConfiguratorTrait;
+    use Traits\DeprecateTrait;
+    use Traits\FactoryTrait;
+    use Traits\LazyTrait;
+    use Traits\ParentTrait;
+    use Traits\PropertyTrait;
+    use Traits\PublicTrait;
+    use Traits\ShareTrait;
+    use Traits\TagTrait;
+
+    private $loader;
+    private $resource;
+    private $exclude;
+    private $allowParent;
+
+    public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, $namespace, $resource, $allowParent)
+    {
+        $definition = new Definition();
+        if (!$defaults->isPublic() || !$defaults->isPrivate()) {
+            $definition->setPublic($defaults->isPublic());
+        }
+        $definition->setAutowired($defaults->isAutowired());
+        $definition->setAutoconfigured($defaults->isAutoconfigured());
+        // deep clone, to avoid multiple process of the same instance in the passes
+        $definition->setBindings(unserialize(serialize($defaults->getBindings())));
+        $definition->setChanges([]);
+
+        $this->loader = $loader;
+        $this->resource = $resource;
+        $this->allowParent = $allowParent;
+
+        parent::__construct($parent, $definition, $namespace, $defaults->getTags());
+    }
+
+    public function __destruct()
+    {
+        parent::__destruct();
+
+        if ($this->loader) {
+            $this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->exclude);
+        }
+        $this->loader = null;
+    }
+
+    /**
+     * Excludes files from registration using a glob pattern.
+     *
+     * @param string $exclude
+     *
+     * @return $this
+     */
+    final public function exclude($exclude)
+    {
+        $this->exclude = $exclude;
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php
new file mode 100644
index 0000000000..1585c0872a
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ReferenceConfigurator extends AbstractConfigurator
+{
+    /** @internal */
+    protected $id;
+
+    /** @internal */
+    protected $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
+
+    public function __construct($id)
+    {
+        $this->id = $id;
+    }
+
+    /**
+     * @return $this
+     */
+    final public function ignoreOnInvalid()
+    {
+        $this->invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    final public function nullOnInvalid()
+    {
+        $this->invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    final public function ignoreOnUninitialized()
+    {
+        $this->invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
+
+        return $this;
+    }
+
+    public function __toString()
+    {
+        return $this->id;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php
new file mode 100644
index 0000000000..897dedaac5
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ServiceConfigurator extends AbstractServiceConfigurator
+{
+    const FACTORY = 'services';
+
+    use Traits\AbstractTrait;
+    use Traits\ArgumentTrait;
+    use Traits\AutoconfigureTrait;
+    use Traits\AutowireTrait;
+    use Traits\BindTrait;
+    use Traits\CallTrait;
+    use Traits\ClassTrait;
+    use Traits\ConfiguratorTrait;
+    use Traits\DecorateTrait;
+    use Traits\DeprecateTrait;
+    use Traits\FactoryTrait;
+    use Traits\FileTrait;
+    use Traits\LazyTrait;
+    use Traits\ParentTrait;
+    use Traits\PropertyTrait;
+    use Traits\PublicTrait;
+    use Traits\ShareTrait;
+    use Traits\SyntheticTrait;
+    use Traits\TagTrait;
+
+    private $container;
+    private $instanceof;
+    private $allowParent;
+
+    public function __construct(ContainerBuilder $container, array $instanceof, $allowParent, ServicesConfigurator $parent, Definition $definition, $id, array $defaultTags)
+    {
+        $this->container = $container;
+        $this->instanceof = $instanceof;
+        $this->allowParent = $allowParent;
+
+        parent::__construct($parent, $definition, $id, $defaultTags);
+    }
+
+    public function __destruct()
+    {
+        parent::__destruct();
+
+        $this->container->removeBindings($this->id);
+
+        if (!$this->definition instanceof ChildDefinition) {
+            $this->container->setDefinition($this->id, $this->definition->setInstanceofConditionals($this->instanceof));
+        } else {
+            $this->container->setDefinition($this->id, $this->definition);
+        }
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php
new file mode 100644
index 0000000000..b6ccbc63b4
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php
@@ -0,0 +1,160 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @method InstanceofConfigurator instanceof($fqcn)
+ */
+class ServicesConfigurator extends AbstractConfigurator
+{
+    const FACTORY = 'services';
+
+    private $defaults;
+    private $container;
+    private $loader;
+    private $instanceof;
+
+    public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof)
+    {
+        $this->defaults = new Definition();
+        $this->container = $container;
+        $this->loader = $loader;
+        $this->instanceof = &$instanceof;
+        $instanceof = [];
+    }
+
+    /**
+     * Defines a set of defaults for following service definitions.
+     *
+     * @return DefaultsConfigurator
+     */
+    final public function defaults()
+    {
+        return new DefaultsConfigurator($this, $this->defaults = new Definition());
+    }
+
+    /**
+     * Defines an instanceof-conditional to be applied to following service definitions.
+     *
+     * @param string $fqcn
+     *
+     * @return InstanceofConfigurator
+     */
+    final protected function setInstanceof($fqcn)
+    {
+        $this->instanceof[$fqcn] = $definition = new ChildDefinition('');
+
+        return new InstanceofConfigurator($this, $definition, $fqcn);
+    }
+
+    /**
+     * Registers a service.
+     *
+     * @param string      $id
+     * @param string|null $class
+     *
+     * @return ServiceConfigurator
+     */
+    final public function set($id, $class = null)
+    {
+        $defaults = $this->defaults;
+        $allowParent = !$defaults->getChanges() && empty($this->instanceof);
+
+        $definition = new Definition();
+        if (!$defaults->isPublic() || !$defaults->isPrivate()) {
+            $definition->setPublic($defaults->isPublic() && !$defaults->isPrivate());
+        }
+        $definition->setAutowired($defaults->isAutowired());
+        $definition->setAutoconfigured($defaults->isAutoconfigured());
+        // deep clone, to avoid multiple process of the same instance in the passes
+        $definition->setBindings(unserialize(serialize($defaults->getBindings())));
+        $definition->setChanges([]);
+
+        $configurator = new ServiceConfigurator($this->container, $this->instanceof, $allowParent, $this, $definition, $id, $defaults->getTags());
+
+        return null !== $class ? $configurator->class($class) : $configurator;
+    }
+
+    /**
+     * Creates an alias.
+     *
+     * @param string $id
+     * @param string $referencedId
+     *
+     * @return AliasConfigurator
+     */
+    final public function alias($id, $referencedId)
+    {
+        $ref = static::processValue($referencedId, true);
+        $alias = new Alias((string) $ref);
+        if (!$this->defaults->isPublic() || !$this->defaults->isPrivate()) {
+            $alias->setPublic($this->defaults->isPublic());
+        }
+        $this->container->setAlias($id, $alias);
+
+        return new AliasConfigurator($this, $alias);
+    }
+
+    /**
+     * Registers a PSR-4 namespace using a glob pattern.
+     *
+     * @param string $namespace
+     * @param string $resource
+     *
+     * @return PrototypeConfigurator
+     */
+    final public function load($namespace, $resource)
+    {
+        $allowParent = !$this->defaults->getChanges() && empty($this->instanceof);
+
+        return new PrototypeConfigurator($this, $this->loader, $this->defaults, $namespace, $resource, $allowParent);
+    }
+
+    /**
+     * Gets an already defined service definition.
+     *
+     * @param string $id
+     *
+     * @return ServiceConfigurator
+     *
+     * @throws ServiceNotFoundException if the service definition does not exist
+     */
+    final public function get($id)
+    {
+        $allowParent = !$this->defaults->getChanges() && empty($this->instanceof);
+        $definition = $this->container->getDefinition($id);
+
+        return new ServiceConfigurator($this->container, $definition->getInstanceofConditionals(), $allowParent, $this, $definition, $id, []);
+    }
+
+    /**
+     * Registers a service.
+     *
+     * @param string      $id
+     * @param string|null $class
+     *
+     * @return ServiceConfigurator
+     */
+    final public function __invoke($id, $class = null)
+    {
+        return $this->set($id, $class);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php
new file mode 100644
index 0000000000..f69a7a5be1
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+/**
+ * @method $this abstract(bool $abstract = true)
+ */
+trait AbstractTrait
+{
+    /**
+     * Whether this definition is abstract, that means it merely serves as a
+     * template for other definitions.
+     *
+     * @param bool $abstract
+     *
+     * @return $this
+     */
+    final protected function setAbstract($abstract = true)
+    {
+        $this->definition->setAbstract($abstract);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php
new file mode 100644
index 0000000000..7ec8c51d47
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait ArgumentTrait
+{
+    /**
+     * Sets the arguments to pass to the service constructor/factory method.
+     *
+     * @param array $arguments An array of arguments
+     *
+     * @return $this
+     */
+    final public function args(array $arguments)
+    {
+        $this->definition->setArguments(static::processValue($arguments, true));
+
+        return $this;
+    }
+
+    /**
+     * Sets one argument to pass to the service constructor/factory method.
+     *
+     * @param string|int $key
+     * @param mixed      $value
+     *
+     * @return $this
+     */
+    final public function arg($key, $value)
+    {
+        $this->definition->setArgument($key, static::processValue($value, true));
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php
new file mode 100644
index 0000000000..42a692353e
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+trait AutoconfigureTrait
+{
+    /**
+     * Sets whether or not instanceof conditionals should be prepended with a global set.
+     *
+     * @param bool $autoconfigured
+     *
+     * @return $this
+     *
+     * @throws InvalidArgumentException when a parent is already set
+     */
+    final public function autoconfigure($autoconfigured = true)
+    {
+        if ($autoconfigured && $this->definition instanceof ChildDefinition) {
+            throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id));
+        }
+        $this->definition->setAutoconfigured($autoconfigured);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php
new file mode 100644
index 0000000000..3d4b2e854b
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait AutowireTrait
+{
+    /**
+     * Enables/disables autowiring.
+     *
+     * @param bool $autowired
+     *
+     * @return $this
+     */
+    final public function autowire($autowired = true)
+    {
+        $this->definition->setAutowired($autowired);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php
new file mode 100644
index 0000000000..4511ed659d
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+
+trait BindTrait
+{
+    /**
+     * Sets bindings.
+     *
+     * Bindings map $named or FQCN arguments to values that should be
+     * injected in the matching parameters (of the constructor, of methods
+     * called and of controller actions).
+     *
+     * @param string $nameOrFqcn A parameter name with its "$" prefix, or a FQCN
+     * @param mixed  $valueOrRef The value or reference to bind
+     *
+     * @return $this
+     */
+    final public function bind($nameOrFqcn, $valueOrRef)
+    {
+        $valueOrRef = static::processValue($valueOrRef, true);
+        if (isset($nameOrFqcn[0]) && '$' !== $nameOrFqcn[0] && !$valueOrRef instanceof Reference) {
+            throw new InvalidArgumentException(sprintf('Invalid binding for service "%s": named arguments must start with a "$", and FQCN must map to references. Neither applies to binding "%s".', $this->id, $nameOrFqcn));
+        }
+        $bindings = $this->definition->getBindings();
+        $bindings[$nameOrFqcn] = $valueOrRef;
+        $this->definition->setBindings($bindings);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php
new file mode 100644
index 0000000000..8e6b17a19d
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php
@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+trait CallTrait
+{
+    /**
+     * Adds a method to call after service initialization.
+     *
+     * @param string $method    The method name to call
+     * @param array  $arguments An array of arguments to pass to the method call
+     *
+     * @return $this
+     *
+     * @throws InvalidArgumentException on empty $method param
+     */
+    final public function call($method, array $arguments = [])
+    {
+        $this->definition->addMethodCall($method, static::processValue($arguments, true));
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php
new file mode 100644
index 0000000000..ae5b1c0a3d
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+/**
+ * @method $this class(string $class)
+ */
+trait ClassTrait
+{
+    /**
+     * Sets the service class.
+     *
+     * @param string $class The service class
+     *
+     * @return $this
+     */
+    final protected function setClass($class)
+    {
+        $this->definition->setClass($class);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php
new file mode 100644
index 0000000000..a38283b0e7
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait ConfiguratorTrait
+{
+    /**
+     * Sets a configurator to call after the service is fully initialized.
+     *
+     * @param string|array $configurator A PHP callable reference
+     *
+     * @return $this
+     */
+    final public function configurator($configurator)
+    {
+        $this->definition->setConfigurator(static::processValue($configurator, true));
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php
new file mode 100644
index 0000000000..173ad15f06
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+trait DecorateTrait
+{
+    /**
+     * Sets the service that this service is decorating.
+     *
+     * @param string|null $id        The decorated service id, use null to remove decoration
+     * @param string|null $renamedId The new decorated service id
+     * @param int         $priority  The priority of decoration
+     *
+     * @return $this
+     *
+     * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals
+     */
+    final public function decorate($id, $renamedId = null, $priority = 0)
+    {
+        $this->definition->setDecoratedService($id, $renamedId, $priority);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php
new file mode 100644
index 0000000000..b14a6557ee
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+trait DeprecateTrait
+{
+    /**
+     * Whether this definition is deprecated, that means it should not be called anymore.
+     *
+     * @param string $template Template message to use if the definition is deprecated
+     *
+     * @return $this
+     *
+     * @throws InvalidArgumentException when the message template is invalid
+     */
+    final public function deprecate($template = null)
+    {
+        $this->definition->setDeprecated(true, $template);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php
new file mode 100644
index 0000000000..0d50fb747f
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+trait FactoryTrait
+{
+    /**
+     * Sets a factory.
+     *
+     * @param string|array $factory A PHP callable reference
+     *
+     * @return $this
+     */
+    final public function factory($factory)
+    {
+        if (\is_string($factory) && 1 === substr_count($factory, ':')) {
+            $factoryParts = explode(':', $factory);
+
+            throw new InvalidArgumentException(sprintf('Invalid factory "%s": the `service:method` notation is not available when using PHP-based DI configuration. Use "[ref(\'%s\'), \'%s\']" instead.', $factory, $factoryParts[0], $factoryParts[1]));
+        }
+
+        $this->definition->setFactory(static::processValue($factory, true));
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php
new file mode 100644
index 0000000000..895f5304c3
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait FileTrait
+{
+    /**
+     * Sets a file to require before creating the service.
+     *
+     * @param string $file A full pathname to include
+     *
+     * @return $this
+     */
+    final public function file($file)
+    {
+        $this->definition->setFile($file);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php
new file mode 100644
index 0000000000..d7ea8b27f5
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait LazyTrait
+{
+    /**
+     * Sets the lazy flag of this service.
+     *
+     * @param bool $lazy
+     *
+     * @return $this
+     */
+    final public function lazy($lazy = true)
+    {
+        $this->definition->setLazy($lazy);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php
new file mode 100644
index 0000000000..43f1223e32
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+/**
+ * @method $this parent(string $parent)
+ */
+trait ParentTrait
+{
+    /**
+     * Sets the Definition to inherit from.
+     *
+     * @param string $parent
+     *
+     * @return $this
+     *
+     * @throws InvalidArgumentException when parent cannot be set
+     */
+    final protected function setParent($parent)
+    {
+        if (!$this->allowParent) {
+            throw new InvalidArgumentException(sprintf('A parent cannot be defined when either "_instanceof" or "_defaults" are also defined for service prototype "%s".', $this->id));
+        }
+
+        if ($this->definition instanceof ChildDefinition) {
+            $this->definition->setParent($parent);
+        } elseif ($this->definition->isAutoconfigured()) {
+            throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id));
+        } elseif ($this->definition->getBindings()) {
+            throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also "bind" arguments.', $this->id));
+        } else {
+            // cast Definition to ChildDefinition
+            $definition = serialize($this->definition);
+            $definition = substr_replace($definition, '53', 2, 2);
+            $definition = substr_replace($definition, 'Child', 44, 0);
+            $definition = unserialize($definition);
+
+            $this->definition = $definition->setParent($parent);
+        }
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php
new file mode 100644
index 0000000000..d5d938708e
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait PropertyTrait
+{
+    /**
+     * Sets a specific property.
+     *
+     * @param string $name
+     * @param mixed  $value
+     *
+     * @return $this
+     */
+    final public function property($name, $value)
+    {
+        $this->definition->setProperty($name, static::processValue($value, true));
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php
new file mode 100644
index 0000000000..8f7f79f1cc
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+/**
+ * @method $this public()
+ * @method $this private()
+ */
+trait PublicTrait
+{
+    /**
+     * @return $this
+     */
+    final protected function setPublic()
+    {
+        $this->definition->setPublic(true);
+
+        return $this;
+    }
+
+    /**
+     * @return $this
+     */
+    final protected function setPrivate()
+    {
+        $this->definition->setPublic(false);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php
new file mode 100644
index 0000000000..1c2f97b597
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait ShareTrait
+{
+    /**
+     * Sets if the service must be shared or not.
+     *
+     * @param bool $shared Whether the service must be shared or not
+     *
+     * @return $this
+     */
+    final public function share($shared = true)
+    {
+        $this->definition->setShared($shared);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php
new file mode 100644
index 0000000000..81eceff43d
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+trait SyntheticTrait
+{
+    /**
+     * Sets whether this definition is synthetic, that is not constructed by the
+     * container, but dynamically injected.
+     *
+     * @param bool $synthetic
+     *
+     * @return $this
+     */
+    final public function synthetic($synthetic = true)
+    {
+        $this->definition->setSynthetic($synthetic);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php
new file mode 100644
index 0000000000..d17339f88b
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+trait TagTrait
+{
+    /**
+     * Adds a tag for this definition.
+     *
+     * @param string $name       The tag name
+     * @param array  $attributes An array of attributes
+     *
+     * @return $this
+     */
+    final public function tag($name, array $attributes = [])
+    {
+        if (!\is_string($name) || '' === $name) {
+            throw new InvalidArgumentException(sprintf('The tag name for service "%s" must be a non-empty string.', $this->id));
+        }
+
+        foreach ($attributes as $attribute => $value) {
+            if (!is_scalar($value) && null !== $value) {
+                throw new InvalidArgumentException(sprintf('A tag attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $this->id, $name, $attribute));
+            }
+        }
+
+        $this->definition->addTag($name, $attributes);
+
+        return $this;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php b/civicrm/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php
index 05a3ba2b5c..a57cac3b5e 100644
--- a/civicrm/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php
@@ -11,8 +11,6 @@
 
 namespace Symfony\Component\DependencyInjection\Loader;
 
-use Symfony\Component\Config\Resource\DirectoryResource;
-
 /**
  * DirectoryLoader is a recursive loader to go through directories.
  *
@@ -27,7 +25,7 @@ class DirectoryLoader extends FileLoader
     {
         $file = rtrim($file, '/');
         $path = $this->locator->locate($file);
-        $this->container->addResource(new DirectoryResource($path));
+        $this->container->fileExists($path, false);
 
         foreach (scandir($path) as $dir) {
             if ('.' !== $dir[0]) {
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/FileLoader.php b/civicrm/vendor/symfony/dependency-injection/Loader/FileLoader.php
index 9fc297bab4..749dd4d06b 100644
--- a/civicrm/vendor/symfony/dependency-injection/Loader/FileLoader.php
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/FileLoader.php
@@ -13,7 +13,11 @@ namespace Symfony\Component\DependencyInjection\Loader;
 
 use Symfony\Component\Config\FileLocatorInterface;
 use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
+use Symfony\Component\Config\Resource\GlobResource;
+use Symfony\Component\DependencyInjection\ChildDefinition;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 
 /**
  * FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -23,6 +27,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
 abstract class FileLoader extends BaseFileLoader
 {
     protected $container;
+    protected $isLoadingInstanceof = false;
+    protected $instanceof = [];
 
     public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
     {
@@ -30,4 +36,141 @@ abstract class FileLoader extends BaseFileLoader
 
         parent::__construct($locator);
     }
+
+    /**
+     * Registers a set of classes as services using PSR-4 for discovery.
+     *
+     * @param Definition $prototype A definition to use as template
+     * @param string     $namespace The namespace prefix of classes in the scanned directory
+     * @param string     $resource  The directory to look for classes, glob-patterns allowed
+     * @param string     $exclude   A globed path of files to exclude
+     */
+    public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null)
+    {
+        if ('\\' !== substr($namespace, -1)) {
+            throw new InvalidArgumentException(sprintf('Namespace prefix must end with a "\\": "%s".', $namespace));
+        }
+        if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++$/', $namespace)) {
+            throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: "%s".', $namespace));
+        }
+
+        $classes = $this->findClasses($namespace, $resource, $exclude);
+        // prepare for deep cloning
+        $serializedPrototype = serialize($prototype);
+        $interfaces = [];
+        $singlyImplemented = [];
+
+        foreach ($classes as $class => $errorMessage) {
+            if (interface_exists($class, false)) {
+                $interfaces[] = $class;
+            } else {
+                $this->setDefinition($class, $definition = unserialize($serializedPrototype));
+                if (null !== $errorMessage) {
+                    $definition->addError($errorMessage);
+
+                    continue;
+                }
+                foreach (class_implements($class, false) as $interface) {
+                    $singlyImplemented[$interface] = isset($singlyImplemented[$interface]) ? false : $class;
+                }
+            }
+        }
+        foreach ($interfaces as $interface) {
+            if (!empty($singlyImplemented[$interface])) {
+                $this->container->setAlias($interface, $singlyImplemented[$interface])
+                    ->setPublic(false);
+            }
+        }
+    }
+
+    /**
+     * Registers a definition in the container with its instanceof-conditionals.
+     *
+     * @param string $id
+     */
+    protected function setDefinition($id, Definition $definition)
+    {
+        $this->container->removeBindings($id);
+
+        if ($this->isLoadingInstanceof) {
+            if (!$definition instanceof ChildDefinition) {
+                throw new InvalidArgumentException(sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, \get_class($definition)));
+            }
+            $this->instanceof[$id] = $definition;
+        } else {
+            $this->container->setDefinition($id, $definition instanceof ChildDefinition ? $definition : $definition->setInstanceofConditionals($this->instanceof));
+        }
+    }
+
+    private function findClasses($namespace, $pattern, $excludePattern)
+    {
+        $parameterBag = $this->container->getParameterBag();
+
+        $excludePaths = [];
+        $excludePrefix = null;
+        if ($excludePattern) {
+            $excludePattern = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePattern));
+            foreach ($this->glob($excludePattern, true, $resource, true) as $path => $info) {
+                if (null === $excludePrefix) {
+                    $excludePrefix = $resource->getPrefix();
+                }
+
+                // normalize Windows slashes
+                $excludePaths[str_replace('\\', '/', $path)] = true;
+            }
+        }
+
+        $pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern));
+        $classes = [];
+        $extRegexp = \defined('HHVM_VERSION') ? '/\\.(?:php|hh)$/' : '/\\.php$/';
+        $prefixLen = null;
+        foreach ($this->glob($pattern, true, $resource) as $path => $info) {
+            if (null === $prefixLen) {
+                $prefixLen = \strlen($resource->getPrefix());
+
+                if ($excludePrefix && 0 !== strpos($excludePrefix, $resource->getPrefix())) {
+                    throw new InvalidArgumentException(sprintf('Invalid "exclude" pattern when importing classes for "%s": make sure your "exclude" pattern (%s) is a subset of the "resource" pattern (%s).', $namespace, $excludePattern, $pattern));
+                }
+            }
+
+            if (isset($excludePaths[str_replace('\\', '/', $path)])) {
+                continue;
+            }
+
+            if (!preg_match($extRegexp, $path, $m) || !$info->isReadable()) {
+                continue;
+            }
+            $class = $namespace.ltrim(str_replace('/', '\\', substr($path, $prefixLen, -\strlen($m[0]))), '\\');
+
+            if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) {
+                continue;
+            }
+
+            try {
+                $r = $this->container->getReflectionClass($class);
+            } catch (\ReflectionException $e) {
+                $classes[$class] = $e->getMessage();
+                continue;
+            }
+            // check to make sure the expected class exists
+            if (!$r) {
+                throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern));
+            }
+
+            if ($r->isInstantiable() || $r->isInterface()) {
+                $classes[$class] = null;
+            }
+        }
+
+        // track only for new & removed files
+        if ($resource instanceof GlobResource) {
+            $this->container->addResource($resource);
+        } else {
+            foreach ($resource as $path) {
+                $this->container->fileExists($path, false);
+            }
+        }
+
+        return $classes;
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php b/civicrm/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php
new file mode 100644
index 0000000000..4b25610efe
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Loader;
+
+/**
+ * GlobFileLoader loads files from a glob pattern.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class GlobFileLoader extends FileLoader
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function load($resource, $type = null)
+    {
+        foreach ($this->glob($resource, false, $globResource) as $path => $info) {
+            $this->import($path);
+        }
+
+        $this->container->addResource($globResource);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function supports($resource, $type = null)
+    {
+        return 'glob' === $type;
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/IniFileLoader.php b/civicrm/vendor/symfony/dependency-injection/Loader/IniFileLoader.php
index fa8cbbf287..307a3eefbb 100644
--- a/civicrm/vendor/symfony/dependency-injection/Loader/IniFileLoader.php
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/IniFileLoader.php
@@ -11,7 +11,7 @@
 
 namespace Symfony\Component\DependencyInjection\Loader;
 
-use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Util\XmlUtils;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 
 /**
@@ -28,16 +28,20 @@ class IniFileLoader extends FileLoader
     {
         $path = $this->locator->locate($resource);
 
-        $this->container->addResource(new FileResource($path));
+        $this->container->fileExists($path);
 
+        // first pass to catch parsing errors
         $result = parse_ini_file($path, true);
-        if (false === $result || array() === $result) {
+        if (false === $result || [] === $result) {
             throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $resource));
         }
 
+        // real raw parsing
+        $result = parse_ini_file($path, true, INI_SCANNER_RAW);
+
         if (isset($result['parameters']) && \is_array($result['parameters'])) {
             foreach ($result['parameters'] as $key => $value) {
-                $this->container->setParameter($key, $value);
+                $this->container->setParameter($key, $this->phpize($value));
             }
         }
     }
@@ -47,6 +51,45 @@ class IniFileLoader extends FileLoader
      */
     public function supports($resource, $type = null)
     {
-        return \is_string($resource) && 'ini' === pathinfo($resource, PATHINFO_EXTENSION);
+        if (!\is_string($resource)) {
+            return false;
+        }
+
+        if (null === $type && 'ini' === pathinfo($resource, PATHINFO_EXTENSION)) {
+            return true;
+        }
+
+        return 'ini' === $type;
+    }
+
+    /**
+     * Note that the following features are not supported:
+     *  * strings with escaped quotes are not supported "foo\"bar";
+     *  * string concatenation ("foo" "bar").
+     */
+    private function phpize($value)
+    {
+        // trim on the right as comments removal keep whitespaces
+        if ($value !== $v = rtrim($value)) {
+            $value = '""' === substr_replace($v, '', 1, -1) ? substr($v, 1, -1) : $v;
+        }
+        $lowercaseValue = strtolower($value);
+
+        switch (true) {
+            case \defined($value):
+                return \constant($value);
+            case 'yes' === $lowercaseValue || 'on' === $lowercaseValue:
+                return true;
+            case 'no' === $lowercaseValue || 'off' === $lowercaseValue || 'none' === $lowercaseValue:
+                return false;
+            case isset($value[1]) && (
+                ("'" === $value[0] && "'" === $value[\strlen($value) - 1]) ||
+                ('"' === $value[0] && '"' === $value[\strlen($value) - 1])
+            ):
+                // quoted string
+                return substr($value, 1, -1);
+            default:
+                return XmlUtils::phpize($value);
+        }
     }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php b/civicrm/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php
index c52bd8c98c..ff8df43f84 100644
--- a/civicrm/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php
@@ -11,7 +11,7 @@
 
 namespace Symfony\Component\DependencyInjection\Loader;
 
-use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
 
 /**
  * PhpFileLoader loads service definitions from a PHP file.
@@ -34,9 +34,18 @@ class PhpFileLoader extends FileLoader
 
         $path = $this->locator->locate($resource);
         $this->setCurrentDir(\dirname($path));
-        $this->container->addResource(new FileResource($path));
+        $this->container->fileExists($path);
 
-        include $path;
+        // the closure forbids access to the private scope in the included file
+        $load = \Closure::bind(function ($path) use ($container, $loader, $resource, $type) {
+            return include $path;
+        }, $this, ProtectedPhpFileLoader::class);
+
+        $callback = $load($path);
+
+        if ($callback instanceof \Closure) {
+            $callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this);
+        }
     }
 
     /**
@@ -44,6 +53,21 @@ class PhpFileLoader extends FileLoader
      */
     public function supports($resource, $type = null)
     {
-        return \is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION);
+        if (!\is_string($resource)) {
+            return false;
+        }
+
+        if (null === $type && 'php' === pathinfo($resource, PATHINFO_EXTENSION)) {
+            return true;
+        }
+
+        return 'php' === $type;
     }
 }
+
+/**
+ * @internal
+ */
+final class ProtectedPhpFileLoader extends PhpFileLoader
+{
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php b/civicrm/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php
index ecebe0125e..6ccb66a421 100644
--- a/civicrm/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php
@@ -11,12 +11,15 @@
 
 namespace Symfony\Component\DependencyInjection\Loader;
 
-use Symfony\Component\Config\Resource\FileResource;
 use Symfony\Component\Config\Util\XmlUtils;
 use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\BoundArgument;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 use Symfony\Component\DependencyInjection\Reference;
@@ -40,22 +43,28 @@ class XmlFileLoader extends FileLoader
 
         $xml = $this->parseFileToDOM($path);
 
-        $this->container->addResource(new FileResource($path));
+        $this->container->fileExists($path);
+
+        $defaults = $this->getServiceDefaults($xml, $path);
 
         // anonymous services
-        $this->processAnonymousServices($xml, $path);
+        $this->processAnonymousServices($xml, $path, $defaults);
 
         // imports
         $this->parseImports($xml, $path);
 
         // parameters
-        $this->parseParameters($xml);
+        $this->parseParameters($xml, $path);
 
         // extensions
         $this->loadFromExtensions($xml);
 
         // services
-        $this->parseDefinitions($xml, $path);
+        try {
+            $this->parseDefinitions($xml, $path, $defaults);
+        } finally {
+            $this->instanceof = [];
+        }
     }
 
     /**
@@ -63,26 +72,33 @@ class XmlFileLoader extends FileLoader
      */
     public function supports($resource, $type = null)
     {
-        return \is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION);
+        if (!\is_string($resource)) {
+            return false;
+        }
+
+        if (null === $type && 'xml' === pathinfo($resource, PATHINFO_EXTENSION)) {
+            return true;
+        }
+
+        return 'xml' === $type;
     }
 
     /**
      * Parses parameters.
      *
-     * @param \DOMDocument $xml
+     * @param string $file
      */
-    private function parseParameters(\DOMDocument $xml)
+    private function parseParameters(\DOMDocument $xml, $file)
     {
         if ($parameters = $this->getChildren($xml->documentElement, 'parameters')) {
-            $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter'));
+            $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file));
         }
     }
 
     /**
      * Parses imports.
      *
-     * @param \DOMDocument $xml
-     * @param string       $file
+     * @param string $file
      */
     private function parseImports(\DOMDocument $xml, $file)
     {
@@ -96,64 +112,148 @@ class XmlFileLoader extends FileLoader
         $defaultDirectory = \dirname($file);
         foreach ($imports as $import) {
             $this->setCurrentDir($defaultDirectory);
-            $this->import($import->getAttribute('resource'), null, (bool) XmlUtils::phpize($import->getAttribute('ignore-errors')), $file);
+            $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, (bool) XmlUtils::phpize($import->getAttribute('ignore-errors')), $file);
         }
     }
 
     /**
      * Parses multiple definitions.
      *
-     * @param \DOMDocument $xml
-     * @param string       $file
+     * @param string $file
      */
-    private function parseDefinitions(\DOMDocument $xml, $file)
+    private function parseDefinitions(\DOMDocument $xml, $file, $defaults)
     {
         $xpath = new \DOMXPath($xml);
         $xpath->registerNamespace('container', self::NS);
 
-        if (false === $services = $xpath->query('//container:services/container:service')) {
+        if (false === $services = $xpath->query('//container:services/container:service|//container:services/container:prototype')) {
             return;
         }
+        $this->setCurrentDir(\dirname($file));
 
+        $this->instanceof = [];
+        $this->isLoadingInstanceof = true;
+        $instanceof = $xpath->query('//container:services/container:instanceof');
+        foreach ($instanceof as $service) {
+            $this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, []));
+        }
+
+        $this->isLoadingInstanceof = false;
         foreach ($services as $service) {
-            if (null !== $definition = $this->parseDefinition($service, $file)) {
-                $this->container->setDefinition((string) $service->getAttribute('id'), $definition);
+            if (null !== $definition = $this->parseDefinition($service, $file, $defaults)) {
+                if ('prototype' === $service->tagName) {
+                    $this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), (string) $service->getAttribute('exclude'));
+                } else {
+                    $this->setDefinition((string) $service->getAttribute('id'), $definition);
+                }
             }
         }
     }
 
+    /**
+     * Get service defaults.
+     *
+     * @return array
+     */
+    private function getServiceDefaults(\DOMDocument $xml, $file)
+    {
+        $xpath = new \DOMXPath($xml);
+        $xpath->registerNamespace('container', self::NS);
+
+        if (null === $defaultsNode = $xpath->query('//container:services/container:defaults')->item(0)) {
+            return [];
+        }
+        $defaults = [
+            'tags' => $this->getChildren($defaultsNode, 'tag'),
+            'bind' => array_map(function ($v) { return new BoundArgument($v); }, $this->getArgumentsAsPhp($defaultsNode, 'bind', $file)),
+        ];
+
+        foreach ($defaults['tags'] as $tag) {
+            if ('' === $tag->getAttribute('name')) {
+                throw new InvalidArgumentException(sprintf('The tag name for tag "<defaults>" in "%s" must be a non-empty string.', $file));
+            }
+        }
+
+        if ($defaultsNode->hasAttribute('autowire')) {
+            $defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire'));
+        }
+        if ($defaultsNode->hasAttribute('public')) {
+            $defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public'));
+        }
+        if ($defaultsNode->hasAttribute('autoconfigure')) {
+            $defaults['autoconfigure'] = XmlUtils::phpize($defaultsNode->getAttribute('autoconfigure'));
+        }
+
+        return $defaults;
+    }
+
     /**
      * Parses an individual Definition.
      *
-     * @param \DOMElement $service
-     * @param string      $file
+     * @param string $file
      *
      * @return Definition|null
      */
-    private function parseDefinition(\DOMElement $service, $file)
+    private function parseDefinition(\DOMElement $service, $file, array $defaults)
     {
         if ($alias = $service->getAttribute('alias')) {
-            $public = true;
+            $this->validateAlias($service, $file);
+
+            $this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias));
             if ($publicAttr = $service->getAttribute('public')) {
-                $public = XmlUtils::phpize($publicAttr);
+                $alias->setPublic(XmlUtils::phpize($publicAttr));
+            } elseif (isset($defaults['public'])) {
+                $alias->setPublic($defaults['public']);
             }
-            $this->container->setAlias((string) $service->getAttribute('id'), new Alias($alias, $public));
 
-            return;
+            return null;
         }
 
-        if ($parent = $service->getAttribute('parent')) {
-            $definition = new DefinitionDecorator($parent);
+        if ($this->isLoadingInstanceof) {
+            $definition = new ChildDefinition('');
+        } elseif ($parent = $service->getAttribute('parent')) {
+            if (!empty($this->instanceof)) {
+                throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.', $service->getAttribute('id')));
+            }
+
+            foreach ($defaults as $k => $v) {
+                if ('tags' === $k) {
+                    // since tags are never inherited from parents, there is no confusion
+                    // thus we can safely add them as defaults to ChildDefinition
+                    continue;
+                }
+                if ('bind' === $k) {
+                    if ($defaults['bind']) {
+                        throw new InvalidArgumentException(sprintf('Bound values on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file.', $service->getAttribute('id')));
+                    }
+
+                    continue;
+                }
+                if (!$service->hasAttribute($k)) {
+                    throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $service->getAttribute('id')));
+                }
+            }
+
+            $definition = new ChildDefinition($parent);
         } else {
             $definition = new Definition();
+
+            if (isset($defaults['public'])) {
+                $definition->setPublic($defaults['public']);
+            }
+            if (isset($defaults['autowire'])) {
+                $definition->setAutowired($defaults['autowire']);
+            }
+            if (isset($defaults['autoconfigure'])) {
+                $definition->setAutoconfigured($defaults['autoconfigure']);
+            }
+
+            $definition->setChanges([]);
         }
 
-        foreach (array('class', 'shared', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'lazy', 'abstract') as $key) {
+        foreach (['class', 'public', 'shared', 'synthetic', 'lazy', 'abstract'] as $key) {
             if ($value = $service->getAttribute($key)) {
-                if (\in_array($key, array('factory-class', 'factory-method', 'factory-service'))) {
-                    @trigger_error(sprintf('The "%s" attribute of service "%s" in file "%s" is deprecated since Symfony 2.6 and will be removed in 3.0. Use the "factory" element instead.', $key, (string) $service->getAttribute('id'), $file), E_USER_DEPRECATED);
-                }
-                $method = 'set'.str_replace('-', '', $key);
+                $method = 'set'.$key;
                 $definition->$method(XmlUtils::phpize($value));
             }
         }
@@ -162,24 +262,12 @@ class XmlFileLoader extends FileLoader
             $definition->setAutowired(XmlUtils::phpize($value));
         }
 
-        if ($value = $service->getAttribute('scope')) {
-            $triggerDeprecation = 'request' !== (string) $service->getAttribute('id');
-
-            if ($triggerDeprecation) {
-                @trigger_error(sprintf('The "scope" attribute of service "%s" in file "%s" is deprecated since Symfony 2.8 and will be removed in 3.0.', (string) $service->getAttribute('id'), $file), E_USER_DEPRECATED);
-            }
-
-            $definition->setScope(XmlUtils::phpize($value), false);
-        }
-
-        if ($value = $service->getAttribute('synchronized')) {
-            $triggerDeprecation = 'request' !== (string) $service->getAttribute('id');
-
-            if ($triggerDeprecation) {
-                @trigger_error(sprintf('The "synchronized" attribute of service "%s" in file "%s" is deprecated since Symfony 2.7 and will be removed in 3.0.', (string) $service->getAttribute('id'), $file), E_USER_DEPRECATED);
+        if ($value = $service->getAttribute('autoconfigure')) {
+            if (!$definition instanceof ChildDefinition) {
+                $definition->setAutoconfigured(XmlUtils::phpize($value));
+            } elseif ($value = XmlUtils::phpize($value)) {
+                throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting autoconfigure="false" for the service.', $service->getAttribute('id')));
             }
-
-            $definition->setSynchronized(XmlUtils::phpize($value), $triggerDeprecation);
         }
 
         if ($files = $this->getChildren($service, 'file')) {
@@ -190,25 +278,21 @@ class XmlFileLoader extends FileLoader
             $definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
         }
 
-        $definition->setArguments($this->getArgumentsAsPhp($service, 'argument'));
-        $definition->setProperties($this->getArgumentsAsPhp($service, 'property'));
+        $definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition));
+        $definition->setProperties($this->getArgumentsAsPhp($service, 'property', $file));
 
         if ($factories = $this->getChildren($service, 'factory')) {
             $factory = $factories[0];
             if ($function = $factory->getAttribute('function')) {
                 $definition->setFactory($function);
             } else {
-                $factoryService = $this->getChildren($factory, 'service');
-
-                if (isset($factoryService[0])) {
-                    $class = $this->parseDefinition($factoryService[0], $file);
-                } elseif ($childService = $factory->getAttribute('service')) {
-                    $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
+                if ($childService = $factory->getAttribute('service')) {
+                    $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
                 } else {
-                    $class = $factory->getAttribute('class');
+                    $class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null;
                 }
 
-                $definition->setFactory(array($class, $factory->getAttribute('method')));
+                $definition->setFactory([$class, $factory->getAttribute('method')]);
             }
         }
 
@@ -217,40 +301,42 @@ class XmlFileLoader extends FileLoader
             if ($function = $configurator->getAttribute('function')) {
                 $definition->setConfigurator($function);
             } else {
-                $configuratorService = $this->getChildren($configurator, 'service');
-
-                if (isset($configuratorService[0])) {
-                    $class = $this->parseDefinition($configuratorService[0], $file);
-                } elseif ($childService = $configurator->getAttribute('service')) {
-                    $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
+                if ($childService = $configurator->getAttribute('service')) {
+                    $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
                 } else {
                     $class = $configurator->getAttribute('class');
                 }
 
-                $definition->setConfigurator(array($class, $configurator->getAttribute('method')));
+                $definition->setConfigurator([$class, $configurator->getAttribute('method')]);
             }
         }
 
         foreach ($this->getChildren($service, 'call') as $call) {
-            $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument'));
+            $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file));
+        }
+
+        $tags = $this->getChildren($service, 'tag');
+
+        if (!empty($defaults['tags'])) {
+            $tags = array_merge($tags, $defaults['tags']);
         }
 
-        foreach ($this->getChildren($service, 'tag') as $tag) {
-            $parameters = array();
+        foreach ($tags as $tag) {
+            $parameters = [];
             foreach ($tag->attributes as $name => $node) {
                 if ('name' === $name) {
                     continue;
                 }
 
-                if (false !== strpos($name, '-') && false === strpos($name, '_') && !array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
+                if (false !== strpos($name, '-') && false === strpos($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
                     $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue);
                 }
-                // keep not normalized key for BC too
+                // keep not normalized key
                 $parameters[$name] = XmlUtils::phpize($node->nodeValue);
             }
 
             if ('' === $tag->getAttribute('name')) {
-                throw new InvalidArgumentException(sprintf('The tag name for service "%s" in %s must be a non-empty string.', (string) $service->getAttribute('id'), $file));
+                throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', (string) $service->getAttribute('id'), $file));
             }
 
             $definition->addTag($tag->getAttribute('name'), $parameters);
@@ -260,6 +346,15 @@ class XmlFileLoader extends FileLoader
             $definition->addAutowiringType($type->textContent);
         }
 
+        $bindings = $this->getArgumentsAsPhp($service, 'bind', $file);
+        if (isset($defaults['bind'])) {
+            // deep clone, to avoid multiple process of the same instance in the passes
+            $bindings = array_merge(unserialize(serialize($defaults['bind'])), $bindings);
+        }
+        if ($bindings) {
+            $definition->setBindings($bindings);
+        }
+
         if ($value = $service->getAttribute('decorates')) {
             $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
             $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0;
@@ -281,9 +376,9 @@ class XmlFileLoader extends FileLoader
     private function parseFileToDOM($file)
     {
         try {
-            $dom = XmlUtils::loadFile($file, array($this, 'validateSchema'));
+            $dom = XmlUtils::loadFile($file, [$this, 'validateSchema']);
         } catch (\InvalidArgumentException $e) {
-            throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e);
+            throw new InvalidArgumentException(sprintf('Unable to parse file "%s": "%s".', $file, $e->getMessage()), $e->getCode(), $e);
         }
 
         $this->validateExtensions($dom, $file);
@@ -294,26 +389,28 @@ class XmlFileLoader extends FileLoader
     /**
      * Processes anonymous services.
      *
-     * @param \DOMDocument $xml
-     * @param string       $file
+     * @param string $file
+     * @param array  $defaults
      */
-    private function processAnonymousServices(\DOMDocument $xml, $file)
+    private function processAnonymousServices(\DOMDocument $xml, $file, $defaults)
     {
-        $definitions = array();
+        $definitions = [];
         $count = 0;
+        $suffix = '~'.ContainerBuilder::hash($file);
 
         $xpath = new \DOMXPath($xml);
         $xpath->registerNamespace('container', self::NS);
 
         // anonymous services as arguments/properties
-        if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]')) {
+        if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]|//container:bind[not(@id)]|//container:factory[not(@service)]|//container:configurator[not(@service)]')) {
             foreach ($nodes as $node) {
-                // give it a unique name
-                $id = sprintf('%s_%d', hash('sha256', $file), ++$count);
-                $node->setAttribute('id', $id);
-
                 if ($services = $this->getChildren($node, 'service')) {
-                    $definitions[$id] = array($services[0], $file, false);
+                    // give it a unique name
+                    $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $services[0]->getAttribute('class')).$suffix);
+                    $node->setAttribute('id', $id);
+                    $node->setAttribute('service', $id);
+
+                    $definitions[$id] = [$services[0], $file, false];
                     $services[0]->setAttribute('id', $id);
 
                     // anonymous services are always private
@@ -326,30 +423,26 @@ class XmlFileLoader extends FileLoader
         // anonymous services "in the wild"
         if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) {
             foreach ($nodes as $node) {
+                @trigger_error(sprintf('Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %s at line %d.', $file, $node->getLineNo()), E_USER_DEPRECATED);
+
                 // give it a unique name
-                $id = sprintf('%s_%d', hash('sha256', $file), ++$count);
+                $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $node->getAttribute('class')).$suffix);
                 $node->setAttribute('id', $id);
-                $definitions[$id] = array($node, $file, true);
+                $definitions[$id] = [$node, $file, true];
             }
         }
 
         // resolve definitions
-        krsort($definitions);
-        foreach ($definitions as $id => $def) {
-            list($domElement, $file, $wild) = $def;
-
-            if (null !== $definition = $this->parseDefinition($domElement, $file)) {
-                $this->container->setDefinition($id, $definition);
+        uksort($definitions, 'strnatcmp');
+        foreach (array_reverse($definitions) as $id => list($domElement, $file, $wild)) {
+            if (null !== $definition = $this->parseDefinition($domElement, $file, $wild ? $defaults : [])) {
+                $this->setDefinition($id, $definition);
             }
 
             if (true === $wild) {
                 $tmpDomElement = new \DOMElement('_services', null, self::NS);
                 $domElement->parentNode->replaceChild($tmpDomElement, $domElement);
                 $tmpDomElement->setAttribute('id', $id);
-            } else {
-                if (null !== $domElement->parentNode) {
-                    $domElement->parentNode->removeChild($domElement);
-                }
             }
         }
     }
@@ -357,24 +450,23 @@ class XmlFileLoader extends FileLoader
     /**
      * Returns arguments as valid php types.
      *
-     * @param \DOMElement $node
-     * @param string      $name
-     * @param bool        $lowercase
+     * @param string $name
+     * @param string $file
      *
      * @return mixed
      */
-    private function getArgumentsAsPhp(\DOMElement $node, $name, $lowercase = true)
+    private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $isChildDefinition = false)
     {
-        $arguments = array();
+        $arguments = [];
         foreach ($this->getChildren($node, $name) as $arg) {
             if ($arg->hasAttribute('name')) {
                 $arg->setAttribute('key', $arg->getAttribute('name'));
             }
 
-            // this is used by DefinitionDecorator to overwrite a specific
+            // this is used by ChildDefinition to overwrite a specific
             // argument of the parent definition
             if ($arg->hasAttribute('index')) {
-                $key = 'index_'.$arg->getAttribute('index');
+                $key = ($isChildDefinition ? 'index_' : '').$arg->getAttribute('index');
             } elseif (!$arg->hasAttribute('key')) {
                 // Append an empty argument, then fetch its key to overwrite it later
                 $arguments[] = null;
@@ -382,36 +474,52 @@ class XmlFileLoader extends FileLoader
                 $key = array_pop($keys);
             } else {
                 $key = $arg->getAttribute('key');
+            }
 
-                // parameter keys are case insensitive
-                if ('parameter' == $name && $lowercase) {
-                    $key = strtolower($key);
-                }
+            $onInvalid = $arg->getAttribute('on-invalid');
+            $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
+            if ('ignore' == $onInvalid) {
+                $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
+            } elseif ('ignore_uninitialized' == $onInvalid) {
+                $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
+            } elseif ('null' == $onInvalid) {
+                $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
             }
 
             switch ($arg->getAttribute('type')) {
                 case 'service':
-                    $onInvalid = $arg->getAttribute('on-invalid');
-                    $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
-                    if ('ignore' == $onInvalid) {
-                        $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
-                    } elseif ('null' == $onInvalid) {
-                        $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
+                    if ('' === $arg->getAttribute('id')) {
+                        throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file));
                     }
-
-                    if ($strict = $arg->getAttribute('strict')) {
-                        $strict = XmlUtils::phpize($strict);
-                    } else {
-                        $strict = true;
+                    if ($arg->hasAttribute('strict')) {
+                        @trigger_error(sprintf('The "strict" attribute used when referencing the "%s" service is deprecated since Symfony 3.3 and will be removed in 4.0.', $arg->getAttribute('id')), E_USER_DEPRECATED);
                     }
 
-                    $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior, $strict);
+                    $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior);
                     break;
                 case 'expression':
+                    if (!class_exists(Expression::class)) {
+                        throw new \LogicException(sprintf('The type="expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".'));
+                    }
+
                     $arguments[$key] = new Expression($arg->nodeValue);
                     break;
                 case 'collection':
-                    $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, false);
+                    $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, $file);
+                    break;
+                case 'iterator':
+                    $arg = $this->getArgumentsAsPhp($arg, $name, $file);
+                    try {
+                        $arguments[$key] = new IteratorArgument($arg);
+                    } catch (InvalidArgumentException $e) {
+                        throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file));
+                    }
+                    break;
+                case 'tagged':
+                    if (!$arg->getAttribute('tag')) {
+                        throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="tagged" has no or empty "tag" attribute in "%s".', $name, $file));
+                    }
+                    $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'));
                     break;
                 case 'string':
                     $arguments[$key] = $arg->nodeValue;
@@ -430,14 +538,13 @@ class XmlFileLoader extends FileLoader
     /**
      * Get child elements by name.
      *
-     * @param \DOMNode $node
-     * @param mixed    $name
+     * @param mixed $name
      *
-     * @return array
+     * @return \DOMElement[]
      */
     private function getChildren(\DOMNode $node, $name)
     {
-        $children = array();
+        $children = [];
         foreach ($node->childNodes as $child) {
             if ($child instanceof \DOMElement && $child->localName === $name && self::NS === $child->namespaceURI) {
                 $children[] = $child;
@@ -450,15 +557,13 @@ class XmlFileLoader extends FileLoader
     /**
      * Validates a documents XML schema.
      *
-     * @param \DOMDocument $dom
-     *
      * @return bool
      *
      * @throws RuntimeException When extension references a non-existent XSD file
      */
     public function validateSchema(\DOMDocument $dom)
     {
-        $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd'));
+        $schemaLocations = ['http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')];
 
         if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) {
             $items = preg_split('/\s+/', $element);
@@ -468,10 +573,11 @@ class XmlFileLoader extends FileLoader
                 }
 
                 if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) {
-                    $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]);
+                    $ns = $extension->getNamespace();
+                    $path = str_replace([$ns, str_replace('http://', 'https://', $ns)], str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]);
 
                     if (!is_file($path)) {
-                        throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', \get_class($extension), $path));
+                        throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s".', \get_class($extension), $path));
                     }
 
                     $schemaLocations[$items[$i]] = $path;
@@ -479,13 +585,13 @@ class XmlFileLoader extends FileLoader
             }
         }
 
-        $tmpfiles = array();
+        $tmpfiles = [];
         $imports = '';
         foreach ($schemaLocations as $namespace => $location) {
             $parts = explode('/', $location);
             $locationstart = 'file:///';
             if (0 === stripos($location, 'phar://')) {
-                $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
+                $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
                 if ($tmpfile) {
                     copy($location, $tmpfile);
                     $tmpfiles[] = $tmpfile;
@@ -525,11 +631,30 @@ EOF
         return $valid;
     }
 
+    /**
+     * Validates an alias.
+     *
+     * @param string $file
+     */
+    private function validateAlias(\DOMElement $alias, $file)
+    {
+        foreach ($alias->attributes as $name => $node) {
+            if (!\in_array($name, ['alias', 'id', 'public'])) {
+                @trigger_error(sprintf('Using the attribute "%s" is deprecated for the service "%s" which is defined as an alias in "%s". Allowed attributes for service aliases are "alias", "id" and "public". The XmlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported attributes.', $name, $alias->getAttribute('id'), $file), E_USER_DEPRECATED);
+            }
+        }
+
+        foreach ($alias->childNodes as $child) {
+            if ($child instanceof \DOMElement && self::NS === $child->namespaceURI) {
+                @trigger_error(sprintf('Using the element "%s" is deprecated for the service "%s" which is defined as an alias in "%s". The XmlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported elements.', $child->localName, $alias->getAttribute('id'), $file), E_USER_DEPRECATED);
+            }
+        }
+    }
+
     /**
      * Validates an extension.
      *
-     * @param \DOMDocument $dom
-     * @param string       $file
+     * @param string $file
      *
      * @throws InvalidArgumentException When no extension is found corresponding to a tag
      */
@@ -543,15 +668,13 @@ EOF
             // can it be handled by an extension?
             if (!$this->container->hasExtension($node->namespaceURI)) {
                 $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions()));
-                throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'));
+                throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'));
             }
         }
     }
 
     /**
      * Loads from an extension.
-     *
-     * @param \DOMDocument $xml
      */
     private function loadFromExtensions(\DOMDocument $xml)
     {
@@ -562,7 +685,7 @@ EOF
 
             $values = static::convertDomElementToArray($node);
             if (!\is_array($values)) {
-                $values = array();
+                $values = [];
             }
 
             $this->container->loadFromExtension($node->namespaceURI, $values);
@@ -586,7 +709,7 @@ EOF
      *
      * @param \DOMElement $element A \DOMElement instance
      *
-     * @return array A PHP array
+     * @return mixed
      */
     public static function convertDomElementToArray(\DOMElement $element)
     {
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php b/civicrm/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php
index d25f654709..bc0c55e94d 100644
--- a/civicrm/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php
@@ -11,29 +11,102 @@
 
 namespace Symfony\Component\DependencyInjection\Loader;
 
-use Symfony\Component\Config\Resource\FileResource;
 use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\Argument\BoundArgument;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\DefinitionDecorator;
 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\ExpressionLanguage\Expression;
 use Symfony\Component\Yaml\Exception\ParseException;
 use Symfony\Component\Yaml\Parser as YamlParser;
+use Symfony\Component\Yaml\Tag\TaggedValue;
+use Symfony\Component\Yaml\Yaml;
 
 /**
  * YamlFileLoader loads YAML files service definitions.
  *
- * The YAML format does not support anonymous services (cf. the XML loader).
- *
  * @author Fabien Potencier <fabien@symfony.com>
  */
 class YamlFileLoader extends FileLoader
 {
+    private static $serviceKeywords = [
+        'alias' => 'alias',
+        'parent' => 'parent',
+        'class' => 'class',
+        'shared' => 'shared',
+        'synthetic' => 'synthetic',
+        'lazy' => 'lazy',
+        'public' => 'public',
+        'abstract' => 'abstract',
+        'deprecated' => 'deprecated',
+        'factory' => 'factory',
+        'file' => 'file',
+        'arguments' => 'arguments',
+        'properties' => 'properties',
+        'configurator' => 'configurator',
+        'calls' => 'calls',
+        'tags' => 'tags',
+        'decorates' => 'decorates',
+        'decoration_inner_name' => 'decoration_inner_name',
+        'decoration_priority' => 'decoration_priority',
+        'autowire' => 'autowire',
+        'autowiring_types' => 'autowiring_types',
+        'autoconfigure' => 'autoconfigure',
+        'bind' => 'bind',
+    ];
+
+    private static $prototypeKeywords = [
+        'resource' => 'resource',
+        'namespace' => 'namespace',
+        'exclude' => 'exclude',
+        'parent' => 'parent',
+        'shared' => 'shared',
+        'lazy' => 'lazy',
+        'public' => 'public',
+        'abstract' => 'abstract',
+        'deprecated' => 'deprecated',
+        'factory' => 'factory',
+        'arguments' => 'arguments',
+        'properties' => 'properties',
+        'configurator' => 'configurator',
+        'calls' => 'calls',
+        'tags' => 'tags',
+        'autowire' => 'autowire',
+        'autoconfigure' => 'autoconfigure',
+        'bind' => 'bind',
+    ];
+
+    private static $instanceofKeywords = [
+        'shared' => 'shared',
+        'lazy' => 'lazy',
+        'public' => 'public',
+        'properties' => 'properties',
+        'configurator' => 'configurator',
+        'calls' => 'calls',
+        'tags' => 'tags',
+        'autowire' => 'autowire',
+    ];
+
+    private static $defaultsKeywords = [
+        'public' => 'public',
+        'tags' => 'tags',
+        'autowire' => 'autowire',
+        'autoconfigure' => 'autoconfigure',
+        'bind' => 'bind',
+    ];
+
     private $yamlParser;
 
+    private $anonymousServicesCount;
+    private $anonymousServicesSuffix;
+
     /**
      * {@inheritdoc}
      */
@@ -43,7 +116,7 @@ class YamlFileLoader extends FileLoader
 
         $content = $this->loadFile($path);
 
-        $this->container->addResource(new FileResource($path));
+        $this->container->fileExists($path);
 
         // empty file
         if (null === $content) {
@@ -56,11 +129,11 @@ class YamlFileLoader extends FileLoader
         // parameters
         if (isset($content['parameters'])) {
             if (!\is_array($content['parameters'])) {
-                throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $resource));
+                throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in "%s". Check your YAML syntax.', $path));
             }
 
             foreach ($content['parameters'] as $key => $value) {
-                $this->container->setParameter($key, $this->resolveServices($value));
+                $this->container->setParameter($key, $this->resolveServices($value, $path, true));
             }
         }
 
@@ -68,7 +141,14 @@ class YamlFileLoader extends FileLoader
         $this->loadFromExtensions($content);
 
         // services
-        $this->parseDefinitions($content, $resource);
+        $this->anonymousServicesCount = 0;
+        $this->anonymousServicesSuffix = '~'.ContainerBuilder::hash($path);
+        $this->setCurrentDir(\dirname($path));
+        try {
+            $this->parseDefinitions($content, $path);
+        } finally {
+            $this->instanceof = [];
+        }
     }
 
     /**
@@ -76,13 +156,20 @@ class YamlFileLoader extends FileLoader
      */
     public function supports($resource, $type = null)
     {
-        return \is_string($resource) && \in_array(pathinfo($resource, PATHINFO_EXTENSION), array('yml', 'yaml'), true);
+        if (!\is_string($resource)) {
+            return false;
+        }
+
+        if (null === $type && \in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yaml', 'yml'], true)) {
+            return true;
+        }
+
+        return \in_array($type, ['yaml', 'yml'], true);
     }
 
     /**
      * Parses all imports.
      *
-     * @param array  $content
      * @param string $file
      */
     private function parseImports(array $content, $file)
@@ -92,24 +179,26 @@ class YamlFileLoader extends FileLoader
         }
 
         if (!\is_array($content['imports'])) {
-            throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in %s. Check your YAML syntax.', $file));
+            throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in "%s". Check your YAML syntax.', $file));
         }
 
         $defaultDirectory = \dirname($file);
         foreach ($content['imports'] as $import) {
             if (!\is_array($import)) {
-                throw new InvalidArgumentException(sprintf('The values in the "imports" key should be arrays in %s. Check your YAML syntax.', $file));
+                $import = ['resource' => $import];
+            }
+            if (!isset($import['resource'])) {
+                throw new InvalidArgumentException(sprintf('An import should provide a resource in "%s". Check your YAML syntax.', $file));
             }
 
             $this->setCurrentDir($defaultDirectory);
-            $this->import($import['resource'], null, isset($import['ignore_errors']) ? (bool) $import['ignore_errors'] : false, $file);
+            $this->import($import['resource'], isset($import['type']) ? $import['type'] : null, isset($import['ignore_errors']) ? (bool) $import['ignore_errors'] : false, $file);
         }
     }
 
     /**
      * Parses definitions.
      *
-     * @param array  $content
      * @param string $file
      */
     private function parseDefinitions(array $content, $file)
@@ -119,14 +208,114 @@ class YamlFileLoader extends FileLoader
         }
 
         if (!\is_array($content['services'])) {
-            throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file));
+            throw new InvalidArgumentException(sprintf('The "services" key should contain an array in "%s". Check your YAML syntax.', $file));
         }
 
+        if (\array_key_exists('_instanceof', $content['services'])) {
+            $instanceof = $content['services']['_instanceof'];
+            unset($content['services']['_instanceof']);
+
+            if (!\is_array($instanceof)) {
+                throw new InvalidArgumentException(sprintf('Service "_instanceof" key must be an array, "%s" given in "%s".', \gettype($instanceof), $file));
+            }
+            $this->instanceof = [];
+            $this->isLoadingInstanceof = true;
+            foreach ($instanceof as $id => $service) {
+                if (!$service || !\is_array($service)) {
+                    throw new InvalidArgumentException(sprintf('Type definition "%s" must be a non-empty array within "_instanceof" in "%s". Check your YAML syntax.', $id, $file));
+                }
+                if (\is_string($service) && 0 === strpos($service, '@')) {
+                    throw new InvalidArgumentException(sprintf('Type definition "%s" cannot be an alias within "_instanceof" in "%s". Check your YAML syntax.', $id, $file));
+                }
+                $this->parseDefinition($id, $service, $file, []);
+            }
+        }
+
+        $this->isLoadingInstanceof = false;
+        $defaults = $this->parseDefaults($content, $file);
         foreach ($content['services'] as $id => $service) {
-            $this->parseDefinition($id, $service, $file);
+            $this->parseDefinition($id, $service, $file, $defaults);
         }
     }
 
+    /**
+     * @param string $file
+     *
+     * @return array
+     *
+     * @throws InvalidArgumentException
+     */
+    private function parseDefaults(array &$content, $file)
+    {
+        if (!\array_key_exists('_defaults', $content['services'])) {
+            return [];
+        }
+        $defaults = $content['services']['_defaults'];
+        unset($content['services']['_defaults']);
+
+        if (!\is_array($defaults)) {
+            throw new InvalidArgumentException(sprintf('Service "_defaults" key must be an array, "%s" given in "%s".', \gettype($defaults), $file));
+        }
+
+        foreach ($defaults as $key => $default) {
+            if (!isset(self::$defaultsKeywords[$key])) {
+                throw new InvalidArgumentException(sprintf('The configuration key "%s" cannot be used to define a default value in "%s". Allowed keys are "%s".', $key, $file, implode('", "', self::$defaultsKeywords)));
+            }
+        }
+
+        if (isset($defaults['tags'])) {
+            if (!\is_array($tags = $defaults['tags'])) {
+                throw new InvalidArgumentException(sprintf('Parameter "tags" in "_defaults" must be an array in "%s". Check your YAML syntax.', $file));
+            }
+
+            foreach ($tags as $tag) {
+                if (!\is_array($tag)) {
+                    $tag = ['name' => $tag];
+                }
+
+                if (!isset($tag['name'])) {
+                    throw new InvalidArgumentException(sprintf('A "tags" entry in "_defaults" is missing a "name" key in "%s".', $file));
+                }
+                $name = $tag['name'];
+                unset($tag['name']);
+
+                if (!\is_string($name) || '' === $name) {
+                    throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string in "%s".', $file));
+                }
+
+                foreach ($tag as $attribute => $value) {
+                    if (!is_scalar($value) && null !== $value) {
+                        throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in "%s". Check your YAML syntax.', $name, $attribute, $file));
+                    }
+                }
+            }
+        }
+
+        if (isset($defaults['bind'])) {
+            if (!\is_array($defaults['bind'])) {
+                throw new InvalidArgumentException(sprintf('Parameter "bind" in "_defaults" must be an array in "%s". Check your YAML syntax.', $file));
+            }
+
+            $defaults['bind'] = array_map(function ($v) { return new BoundArgument($v); }, $this->resolveServices($defaults['bind'], $file));
+        }
+
+        return $defaults;
+    }
+
+    /**
+     * @return bool
+     */
+    private function isUsingShortSyntax(array $service)
+    {
+        foreach ($service as $key => $value) {
+            if (\is_string($key) && ('' === $key || '$' !== $key[0])) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     /**
      * Parses a definition.
      *
@@ -136,29 +325,87 @@ class YamlFileLoader extends FileLoader
      *
      * @throws InvalidArgumentException When tags are invalid
      */
-    private function parseDefinition($id, $service, $file)
+    private function parseDefinition($id, $service, $file, array $defaults)
     {
+        if (preg_match('/^_[a-zA-Z0-9_]*$/', $id)) {
+            @trigger_error(sprintf('Service names that start with an underscore are deprecated since Symfony 3.3 and will be reserved in 4.0. Rename the "%s" service or define it in XML instead.', $id), E_USER_DEPRECATED);
+        }
         if (\is_string($service) && 0 === strpos($service, '@')) {
-            $this->container->setAlias($id, substr($service, 1));
+            $this->container->setAlias($id, $alias = new Alias(substr($service, 1)));
+            if (isset($defaults['public'])) {
+                $alias->setPublic($defaults['public']);
+            }
 
             return;
         }
 
+        if (\is_array($service) && $this->isUsingShortSyntax($service)) {
+            $service = ['arguments' => $service];
+        }
+
+        if (null === $service) {
+            $service = [];
+        }
+
         if (!\is_array($service)) {
-            throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', \gettype($service), $id, $file));
+            throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but "%s" found for service "%s" in "%s". Check your YAML syntax.', \gettype($service), $id, $file));
         }
 
+        $this->checkDefinition($id, $service, $file);
+
         if (isset($service['alias'])) {
-            $public = !array_key_exists('public', $service) || (bool) $service['public'];
-            $this->container->setAlias($id, new Alias($service['alias'], $public));
+            $this->container->setAlias($id, $alias = new Alias($service['alias']));
+            if (isset($service['public'])) {
+                $alias->setPublic($service['public']);
+            } elseif (isset($defaults['public'])) {
+                $alias->setPublic($defaults['public']);
+            }
+
+            foreach ($service as $key => $value) {
+                if (!\in_array($key, ['alias', 'public'])) {
+                    @trigger_error(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias" and "public". The YamlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported attributes.', $key, $id, $file), E_USER_DEPRECATED);
+                }
+            }
 
             return;
         }
 
-        if (isset($service['parent'])) {
-            $definition = new DefinitionDecorator($service['parent']);
+        if ($this->isLoadingInstanceof) {
+            $definition = new ChildDefinition('');
+        } elseif (isset($service['parent'])) {
+            if (!empty($this->instanceof)) {
+                throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "_instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.', $id));
+            }
+
+            foreach ($defaults as $k => $v) {
+                if ('tags' === $k) {
+                    // since tags are never inherited from parents, there is no confusion
+                    // thus we can safely add them as defaults to ChildDefinition
+                    continue;
+                }
+                if ('bind' === $k) {
+                    throw new InvalidArgumentException(sprintf('Attribute "bind" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file.', $id));
+                }
+                if (!isset($service[$k])) {
+                    throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $id));
+                }
+            }
+
+            $definition = new ChildDefinition($service['parent']);
         } else {
             $definition = new Definition();
+
+            if (isset($defaults['public'])) {
+                $definition->setPublic($defaults['public']);
+            }
+            if (isset($defaults['autowire'])) {
+                $definition->setAutowired($defaults['autowire']);
+            }
+            if (isset($defaults['autoconfigure'])) {
+                $definition->setAutoconfigured($defaults['autoconfigure']);
+            }
+
+            $definition->setChanges([]);
         }
 
         if (isset($service['class'])) {
@@ -169,22 +416,10 @@ class YamlFileLoader extends FileLoader
             $definition->setShared($service['shared']);
         }
 
-        if (isset($service['scope'])) {
-            if ('request' !== $id) {
-                @trigger_error(sprintf('The "scope" key of service "%s" in file "%s" is deprecated since Symfony 2.8 and will be removed in 3.0.', $id, $file), E_USER_DEPRECATED);
-            }
-            $definition->setScope($service['scope'], false);
-        }
-
         if (isset($service['synthetic'])) {
             $definition->setSynthetic($service['synthetic']);
         }
 
-        if (isset($service['synchronized'])) {
-            @trigger_error(sprintf('The "synchronized" key of service "%s" in file "%s" is deprecated since Symfony 2.7 and will be removed in 3.0.', $id, $file), E_USER_DEPRECATED);
-            $definition->setSynchronized($service['synchronized'], 'request' !== $id);
-        }
-
         if (isset($service['lazy'])) {
             $definition->setLazy($service['lazy']);
         }
@@ -197,36 +432,12 @@ class YamlFileLoader extends FileLoader
             $definition->setAbstract($service['abstract']);
         }
 
-        if (array_key_exists('deprecated', $service)) {
+        if (\array_key_exists('deprecated', $service)) {
             $definition->setDeprecated(true, $service['deprecated']);
         }
 
         if (isset($service['factory'])) {
-            if (\is_string($service['factory'])) {
-                if (false !== strpos($service['factory'], ':') && false === strpos($service['factory'], '::')) {
-                    $parts = explode(':', $service['factory']);
-                    $definition->setFactory(array($this->resolveServices('@'.$parts[0]), $parts[1]));
-                } else {
-                    $definition->setFactory($service['factory']);
-                }
-            } else {
-                $definition->setFactory(array($this->resolveServices($service['factory'][0]), $service['factory'][1]));
-            }
-        }
-
-        if (isset($service['factory_class'])) {
-            @trigger_error(sprintf('The "factory_class" key of service "%s" in file "%s" is deprecated since Symfony 2.6 and will be removed in 3.0. Use "factory" instead.', $id, $file), E_USER_DEPRECATED);
-            $definition->setFactoryClass($service['factory_class']);
-        }
-
-        if (isset($service['factory_method'])) {
-            @trigger_error(sprintf('The "factory_method" key of service "%s" in file "%s" is deprecated since Symfony 2.6 and will be removed in 3.0. Use "factory" instead.', $id, $file), E_USER_DEPRECATED);
-            $definition->setFactoryMethod($service['factory_method']);
-        }
-
-        if (isset($service['factory_service'])) {
-            @trigger_error(sprintf('The "factory_service" key of service "%s" in file "%s" is deprecated since Symfony 2.6 and will be removed in 3.0. Use "factory" instead.', $id, $file), E_USER_DEPRECATED);
-            $definition->setFactoryService($service['factory_service']);
+            $definition->setFactory($this->parseCallable($service['factory'], 'factory', $id, $file));
         }
 
         if (isset($service['file'])) {
@@ -234,68 +445,69 @@ class YamlFileLoader extends FileLoader
         }
 
         if (isset($service['arguments'])) {
-            $definition->setArguments($this->resolveServices($service['arguments']));
+            $definition->setArguments($this->resolveServices($service['arguments'], $file));
         }
 
         if (isset($service['properties'])) {
-            $definition->setProperties($this->resolveServices($service['properties']));
+            $definition->setProperties($this->resolveServices($service['properties'], $file));
         }
 
         if (isset($service['configurator'])) {
-            if (\is_string($service['configurator'])) {
-                $definition->setConfigurator($service['configurator']);
-            } else {
-                $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1]));
-            }
+            $definition->setConfigurator($this->parseCallable($service['configurator'], 'configurator', $id, $file));
         }
 
         if (isset($service['calls'])) {
             if (!\is_array($service['calls'])) {
-                throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
+                throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file));
             }
 
             foreach ($service['calls'] as $call) {
                 if (isset($call['method'])) {
                     $method = $call['method'];
-                    $args = isset($call['arguments']) ? $this->resolveServices($call['arguments']) : array();
+                    $args = isset($call['arguments']) ? $this->resolveServices($call['arguments'], $file) : [];
                 } else {
                     $method = $call[0];
-                    $args = isset($call[1]) ? $this->resolveServices($call[1]) : array();
+                    $args = isset($call[1]) ? $this->resolveServices($call[1], $file) : [];
                 }
 
+                if (!\is_array($args)) {
+                    throw new InvalidArgumentException(sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in "%s". Check your YAML syntax.', $method, $id, $file));
+                }
                 $definition->addMethodCall($method, $args);
             }
         }
 
-        if (isset($service['tags'])) {
-            if (!\is_array($service['tags'])) {
-                throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
-            }
+        $tags = isset($service['tags']) ? $service['tags'] : [];
+        if (!\is_array($tags)) {
+            throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file));
+        }
 
-            foreach ($service['tags'] as $tag) {
-                if (!\is_array($tag)) {
-                    throw new InvalidArgumentException(sprintf('A "tags" entry must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
-                }
+        if (isset($defaults['tags'])) {
+            $tags = array_merge($tags, $defaults['tags']);
+        }
 
-                if (!isset($tag['name'])) {
-                    throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file));
-                }
+        foreach ($tags as $tag) {
+            if (!\is_array($tag)) {
+                $tag = ['name' => $tag];
+            }
 
-                if (!\is_string($tag['name']) || '' === $tag['name']) {
-                    throw new InvalidArgumentException(sprintf('The tag name for service "%s" in %s must be a non-empty string.', $id, $file));
-                }
+            if (!isset($tag['name'])) {
+                throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in "%s".', $id, $file));
+            }
+            $name = $tag['name'];
+            unset($tag['name']);
 
-                $name = $tag['name'];
-                unset($tag['name']);
+            if (!\is_string($name) || '' === $name) {
+                throw new InvalidArgumentException(sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $id, $file));
+            }
 
-                foreach ($tag as $attribute => $value) {
-                    if (!is_scalar($value) && null !== $value) {
-                        throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s. Check your YAML syntax.', $id, $name, $attribute, $file));
-                    }
+            foreach ($tag as $attribute => $value) {
+                if (!is_scalar($value) && null !== $value) {
+                    throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in "%s". Check your YAML syntax.', $id, $name, $attribute, $file));
                 }
-
-                $definition->addTag($name, $tag);
             }
+
+            $definition->addTag($name, $tag);
         }
 
         if (isset($service['decorates'])) {
@@ -317,12 +529,12 @@ class YamlFileLoader extends FileLoader
                 $definition->addAutowiringType($service['autowiring_types']);
             } else {
                 if (!\is_array($service['autowiring_types'])) {
-                    throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be a string or an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
+                    throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be a string or an array for service "%s" in "%s". Check your YAML syntax.', $id, $file));
                 }
 
                 foreach ($service['autowiring_types'] as $autowiringType) {
                     if (!\is_string($autowiringType)) {
-                        throw new InvalidArgumentException(sprintf('A "autowiring_types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file));
+                        throw new InvalidArgumentException(sprintf('A "autowiring_types" attribute must be of type string for service "%s" in "%s". Check your YAML syntax.', $id, $file));
                     }
 
                     $definition->addAutowiringType($autowiringType);
@@ -330,7 +542,86 @@ class YamlFileLoader extends FileLoader
             }
         }
 
-        $this->container->setDefinition($id, $definition);
+        if (isset($defaults['bind']) || isset($service['bind'])) {
+            // deep clone, to avoid multiple process of the same instance in the passes
+            $bindings = isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : [];
+
+            if (isset($service['bind'])) {
+                if (!\is_array($service['bind'])) {
+                    throw new InvalidArgumentException(sprintf('Parameter "bind" must be an array for service "%s" in "%s". Check your YAML syntax.', $id, $file));
+                }
+
+                $bindings = array_merge($bindings, $this->resolveServices($service['bind'], $file));
+            }
+
+            $definition->setBindings($bindings);
+        }
+
+        if (isset($service['autoconfigure'])) {
+            if (!$definition instanceof ChildDefinition) {
+                $definition->setAutoconfigured($service['autoconfigure']);
+            } elseif ($service['autoconfigure']) {
+                throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting "autoconfigure: false" for the service.', $id));
+            }
+        }
+
+        if (\array_key_exists('namespace', $service) && !\array_key_exists('resource', $service)) {
+            throw new InvalidArgumentException(sprintf('A "resource" attribute must be set when the "namespace" attribute is set for service "%s" in "%s". Check your YAML syntax.', $id, $file));
+        }
+
+        if (\array_key_exists('resource', $service)) {
+            if (!\is_string($service['resource'])) {
+                throw new InvalidArgumentException(sprintf('A "resource" attribute must be of type string for service "%s" in "%s". Check your YAML syntax.', $id, $file));
+            }
+            $exclude = isset($service['exclude']) ? $service['exclude'] : null;
+            $namespace = isset($service['namespace']) ? $service['namespace'] : $id;
+            $this->registerClasses($definition, $namespace, $service['resource'], $exclude);
+        } else {
+            $this->setDefinition($id, $definition);
+        }
+    }
+
+    /**
+     * Parses a callable.
+     *
+     * @param string|array $callable  A callable
+     * @param string       $parameter A parameter (e.g. 'factory' or 'configurator')
+     * @param string       $id        A service identifier
+     * @param string       $file      A parsed file
+     *
+     * @throws InvalidArgumentException When errors occur
+     *
+     * @return string|array A parsed callable
+     */
+    private function parseCallable($callable, $parameter, $id, $file)
+    {
+        if (\is_string($callable)) {
+            if ('' !== $callable && '@' === $callable[0]) {
+                throw new InvalidArgumentException(sprintf('The value of the "%s" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $parameter, $id, $callable, substr($callable, 1)));
+            }
+
+            if (false !== strpos($callable, ':') && false === strpos($callable, '::')) {
+                $parts = explode(':', $callable);
+
+                return [$this->resolveServices('@'.$parts[0], $file), $parts[1]];
+            }
+
+            return $callable;
+        }
+
+        if (\is_array($callable)) {
+            if (isset($callable[0]) && isset($callable[1])) {
+                return [$this->resolveServices($callable[0], $file), $callable[1]];
+            }
+
+            if ('factory' === $parameter && isset($callable[1]) && null === $callable[0]) {
+                return $callable;
+            }
+
+            throw new InvalidArgumentException(sprintf('Parameter "%s" must contain an array with two elements for service "%s" in "%s". Check your YAML syntax.', $parameter, $id, $file));
+        }
+
+        throw new InvalidArgumentException(sprintf('Parameter "%s" must be a string or an array for service "%s" in "%s". Check your YAML syntax.', $parameter, $id, $file));
     }
 
     /**
@@ -360,10 +651,18 @@ class YamlFileLoader extends FileLoader
             $this->yamlParser = new YamlParser();
         }
 
+        $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) {
+            $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message;
+
+            return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false;
+        });
+
         try {
-            $configuration = $this->yamlParser->parse(file_get_contents($file));
+            $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS);
         } catch (ParseException $e) {
-            throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e);
+            throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: '.$e->getMessage(), $file), 0, $e);
+        } finally {
+            restore_error_handler();
         }
 
         return $this->validate($configuration, $file);
@@ -390,13 +689,13 @@ class YamlFileLoader extends FileLoader
         }
 
         foreach ($content as $namespace => $data) {
-            if (\in_array($namespace, array('imports', 'parameters', 'services'))) {
+            if (\in_array($namespace, ['imports', 'parameters', 'services'])) {
                 continue;
             }
 
             if (!$this->container->hasExtension($namespace)) {
                 $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions()));
-                throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'));
+                throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in "%s"). Looked for namespace "%s", found "%s".', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'));
             }
         }
 
@@ -406,20 +705,79 @@ class YamlFileLoader extends FileLoader
     /**
      * Resolves services.
      *
-     * @param string|array $value
+     * @param mixed  $value
+     * @param string $file
+     * @param bool   $isParameter
      *
-     * @return array|string|Reference
+     * @return array|string|Reference|ArgumentInterface
      */
-    private function resolveServices($value)
+    private function resolveServices($value, $file, $isParameter = false)
     {
+        if ($value instanceof TaggedValue) {
+            $argument = $value->getValue();
+            if ('iterator' === $value->getTag()) {
+                if (!\is_array($argument)) {
+                    throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts sequences in "%s".', $file));
+                }
+                $argument = $this->resolveServices($argument, $file, $isParameter);
+                try {
+                    return new IteratorArgument($argument);
+                } catch (InvalidArgumentException $e) {
+                    throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file));
+                }
+            }
+            if ('tagged' === $value->getTag()) {
+                if (!\is_string($argument) || !$argument) {
+                    throw new InvalidArgumentException(sprintf('"!tagged" tag only accepts non empty string in "%s".', $file));
+                }
+
+                return new TaggedIteratorArgument($argument);
+            }
+            if ('service' === $value->getTag()) {
+                if ($isParameter) {
+                    throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file));
+                }
+
+                $isLoadingInstanceof = $this->isLoadingInstanceof;
+                $this->isLoadingInstanceof = false;
+                $instanceof = $this->instanceof;
+                $this->instanceof = [];
+
+                $id = sprintf('%d_%s', ++$this->anonymousServicesCount, preg_replace('/^.*\\\\/', '', isset($argument['class']) ? $argument['class'] : '').$this->anonymousServicesSuffix);
+                $this->parseDefinition($id, $argument, $file, []);
+
+                if (!$this->container->hasDefinition($id)) {
+                    throw new InvalidArgumentException(sprintf('Creating an alias using the tag "!service" is not allowed in "%s".', $file));
+                }
+
+                $this->container->getDefinition($id)->setPublic(false);
+
+                $this->isLoadingInstanceof = $isLoadingInstanceof;
+                $this->instanceof = $instanceof;
+
+                return new Reference($id);
+            }
+
+            throw new InvalidArgumentException(sprintf('Unsupported tag "!%s".', $value->getTag()));
+        }
+
         if (\is_array($value)) {
-            $value = array_map(array($this, 'resolveServices'), $value);
+            foreach ($value as $k => $v) {
+                $value[$k] = $this->resolveServices($v, $file, $isParameter);
+            }
         } elseif (\is_string($value) && 0 === strpos($value, '@=')) {
+            if (!class_exists(Expression::class)) {
+                throw new \LogicException(sprintf('The "@=" expression syntax cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".'));
+            }
+
             return new Expression(substr($value, 2));
         } elseif (\is_string($value) && 0 === strpos($value, '@')) {
             if (0 === strpos($value, '@@')) {
                 $value = substr($value, 1);
                 $invalidBehavior = null;
+            } elseif (0 === strpos($value, '@!')) {
+                $value = substr($value, 2);
+                $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE;
             } elseif (0 === strpos($value, '@?')) {
                 $value = substr($value, 2);
                 $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
@@ -429,14 +787,12 @@ class YamlFileLoader extends FileLoader
             }
 
             if ('=' === substr($value, -1)) {
+                @trigger_error(sprintf('The "=" suffix that used to disable strict references in Symfony 2.x is deprecated since Symfony 3.3 and will be unsupported in 4.0. Remove it in "%s".', $value), E_USER_DEPRECATED);
                 $value = substr($value, 0, -1);
-                $strict = false;
-            } else {
-                $strict = true;
             }
 
             if (null !== $invalidBehavior) {
-                $value = new Reference($value, $invalidBehavior, $strict);
+                $value = new Reference($value, $invalidBehavior);
             }
         }
 
@@ -449,15 +805,43 @@ class YamlFileLoader extends FileLoader
     private function loadFromExtensions(array $content)
     {
         foreach ($content as $namespace => $values) {
-            if (\in_array($namespace, array('imports', 'parameters', 'services'))) {
+            if (\in_array($namespace, ['imports', 'parameters', 'services'])) {
                 continue;
             }
 
             if (!\is_array($values) && null !== $values) {
-                $values = array();
+                $values = [];
             }
 
             $this->container->loadFromExtension($namespace, $values);
         }
     }
+
+    /**
+     * Checks the keywords used to define a service.
+     *
+     * @param string $id         The service name
+     * @param array  $definition The service definition to check
+     * @param string $file       The loaded YAML file
+     */
+    private function checkDefinition($id, array $definition, $file)
+    {
+        if ($throw = $this->isLoadingInstanceof) {
+            $keywords = self::$instanceofKeywords;
+        } elseif ($throw = (isset($definition['resource']) || isset($definition['namespace']))) {
+            $keywords = self::$prototypeKeywords;
+        } else {
+            $keywords = self::$serviceKeywords;
+        }
+
+        foreach ($definition as $key => $value) {
+            if (!isset($keywords[$key])) {
+                if ($throw) {
+                    throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for definition "%s" in "%s". Allowed configuration keys are "%s".', $key, $id, $file, implode('", "', $keywords)));
+                }
+
+                @trigger_error(sprintf('The configuration key "%s" is unsupported for service definition "%s" in "%s". Allowed configuration keys are "%s". The YamlFileLoader object will raise an exception instead in Symfony 4.0 when detecting an unsupported service configuration key.', $key, $id, $file, implode('", "', $keywords)), E_USER_DEPRECATED);
+            }
+        }
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd b/civicrm/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd
index a8d7cf88df..3a55a7df67 100644
--- a/civicrm/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd
+++ b/civicrm/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd
@@ -52,8 +52,11 @@
         Enclosing element for the definition of all services
       ]]></xsd:documentation>
     </xsd:annotation>
-    <xsd:choice minOccurs="1" maxOccurs="unbounded">
-      <xsd:element name="service" type="service" />
+    <xsd:choice maxOccurs="unbounded">
+      <xsd:element name="service" type="service" minOccurs="1" />
+      <xsd:element name="prototype" type="prototype" minOccurs="0" />
+      <xsd:element name="defaults" type="defaults" minOccurs="0" maxOccurs="1" />
+      <xsd:element name="instanceof" type="instanceof" minOccurs="0" />
     </xsd:choice>
   </xsd:complexType>
 
@@ -76,19 +79,34 @@
     </xsd:annotation>
     <xsd:attribute name="resource" type="xsd:string" use="required" />
     <xsd:attribute name="ignore-errors" type="boolean" />
+    <xsd:attribute name="type" type="xsd:string" />
   </xsd:complexType>
 
   <xsd:complexType name="callable">
     <xsd:choice minOccurs="0" maxOccurs="1">
       <xsd:element name="service" type="service" minOccurs="0" maxOccurs="1" />
     </xsd:choice>
-    <xsd:attribute name="id" type="xsd:string" />
     <xsd:attribute name="service" type="xsd:string" />
     <xsd:attribute name="class" type="xsd:string" />
     <xsd:attribute name="method" type="xsd:string" />
     <xsd:attribute name="function" type="xsd:string" />
   </xsd:complexType>
 
+  <xsd:complexType name="defaults">
+    <xsd:annotation>
+      <xsd:documentation><![CDATA[
+        Enclosing element for the service definitions' defaults for the current file
+      ]]></xsd:documentation>
+    </xsd:annotation>
+    <xsd:choice maxOccurs="unbounded">
+      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:choice>
+    <xsd:attribute name="public" type="boolean" />
+    <xsd:attribute name="autowire" type="boolean" />
+    <xsd:attribute name="autoconfigure" type="boolean" />
+  </xsd:complexType>
+
   <xsd:complexType name="service">
     <xsd:choice maxOccurs="unbounded">
       <xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" />
@@ -100,25 +118,60 @@
       <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
       <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
       <xsd:element name="autowiring-type" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
     </xsd:choice>
     <xsd:attribute name="id" type="xsd:string" />
     <xsd:attribute name="class" type="xsd:string" />
     <xsd:attribute name="shared" type="boolean" />
-    <xsd:attribute name="scope" type="xsd:string" />
     <xsd:attribute name="public" type="boolean" />
     <xsd:attribute name="synthetic" type="boolean" />
-    <xsd:attribute name="synchronized" type="boolean" />
     <xsd:attribute name="lazy" type="boolean" />
     <xsd:attribute name="abstract" type="boolean" />
-    <xsd:attribute name="factory-class" type="xsd:string" />
-    <xsd:attribute name="factory-method" type="xsd:string" />
-    <xsd:attribute name="factory-service" type="xsd:string" />
     <xsd:attribute name="alias" type="xsd:string" />
     <xsd:attribute name="parent" type="xsd:string" />
     <xsd:attribute name="decorates" type="xsd:string" />
     <xsd:attribute name="decoration-inner-name" type="xsd:string" />
     <xsd:attribute name="decoration-priority" type="xsd:integer" />
     <xsd:attribute name="autowire" type="boolean" />
+    <xsd:attribute name="autoconfigure" type="boolean" />
+  </xsd:complexType>
+
+  <xsd:complexType name="instanceof">
+    <xsd:choice maxOccurs="unbounded">
+      <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
+      <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:choice>
+    <xsd:attribute name="id" type="xsd:string" use="required" />
+    <xsd:attribute name="shared" type="boolean" />
+    <xsd:attribute name="public" type="boolean" />
+    <xsd:attribute name="lazy" type="boolean" />
+    <xsd:attribute name="autowire" type="boolean" />
+    <xsd:attribute name="autoconfigure" type="boolean" />
+  </xsd:complexType>
+
+  <xsd:complexType name="prototype">
+    <xsd:choice maxOccurs="unbounded">
+      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
+      <xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" />
+      <xsd:element name="deprecated" type="xsd:string" minOccurs="0" maxOccurs="1" />
+      <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="bind" type="bind" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:choice>
+    <xsd:attribute name="namespace" type="xsd:string" use="required" />
+    <xsd:attribute name="resource" type="xsd:string" use="required" />
+    <xsd:attribute name="exclude" type="xsd:string" />
+    <xsd:attribute name="shared" type="boolean" />
+    <xsd:attribute name="public" type="boolean" />
+    <xsd:attribute name="lazy" type="boolean" />
+    <xsd:attribute name="abstract" type="boolean" />
+    <xsd:attribute name="parent" type="xsd:string" />
+    <xsd:attribute name="autowire" type="boolean" />
+    <xsd:attribute name="autoconfigure" type="boolean" />
   </xsd:complexType>
 
   <xsd:complexType name="tag">
@@ -155,6 +208,19 @@
     <xsd:attribute name="name" type="xsd:string" />
     <xsd:attribute name="on-invalid" type="invalid_sequence" />
     <xsd:attribute name="strict" type="boolean" />
+    <xsd:attribute name="tag" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="bind" mixed="true">
+    <xsd:choice maxOccurs="unbounded">
+      <xsd:element name="bind" type="argument" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="service" type="service" />
+    </xsd:choice>
+    <xsd:attribute name="type" type="argument_type" />
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="key" type="xsd:string" use="required" />
+    <xsd:attribute name="on-invalid" type="invalid_sequence" />
+    <xsd:attribute name="method" type="xsd:string" />
   </xsd:complexType>
 
   <xsd:complexType name="argument" mixed="true">
@@ -168,6 +234,7 @@
     <xsd:attribute name="index" type="xsd:integer" />
     <xsd:attribute name="on-invalid" type="invalid_sequence" />
     <xsd:attribute name="strict" type="boolean" />
+    <xsd:attribute name="tag" type="xsd:string" />
   </xsd:complexType>
 
   <xsd:complexType name="call">
@@ -192,6 +259,8 @@
       <xsd:enumeration value="expression" />
       <xsd:enumeration value="string" />
       <xsd:enumeration value="constant" />
+      <xsd:enumeration value="iterator" />
+      <xsd:enumeration value="tagged" />
     </xsd:restriction>
   </xsd:simpleType>
 
@@ -200,6 +269,7 @@
       <xsd:enumeration value="null" />
       <xsd:enumeration value="ignore" />
       <xsd:enumeration value="exception" />
+      <xsd:enumeration value="ignore_uninitialized" />
     </xsd:restriction>
   </xsd:simpleType>
 
diff --git a/civicrm/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php b/civicrm/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php
new file mode 100644
index 0000000000..c4e369b010
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\ParameterBag;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class EnvPlaceholderParameterBag extends ParameterBag
+{
+    private $envPlaceholders = [];
+    private $providedTypes = [];
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($name)
+    {
+        if (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) {
+            $env = substr($name, 4, -1);
+
+            if (isset($this->envPlaceholders[$env])) {
+                foreach ($this->envPlaceholders[$env] as $placeholder) {
+                    return $placeholder; // return first result
+                }
+            }
+            if (!preg_match('/^(?:\w++:)*+\w++$/', $env)) {
+                throw new InvalidArgumentException(sprintf('Invalid "%s" name: only "word" characters are allowed.', $name));
+            }
+
+            if ($this->has($name)) {
+                $defaultValue = parent::get($name);
+
+                if (null !== $defaultValue && !is_scalar($defaultValue)) {
+                    throw new RuntimeException(sprintf('The default value of an env() parameter must be scalar or null, but "%s" given to "%s".', \gettype($defaultValue), $name));
+                }
+            }
+
+            $uniqueName = md5($name.uniqid(mt_rand(), true));
+            $placeholder = sprintf('env_%s_%s', str_replace(':', '_', $env), $uniqueName);
+            $this->envPlaceholders[$env][$placeholder] = $placeholder;
+
+            return $placeholder;
+        }
+
+        return parent::get($name);
+    }
+
+    /**
+     * Returns the map of env vars used in the resolved parameter values to their placeholders.
+     *
+     * @return string[][] A map of env var names to their placeholders
+     */
+    public function getEnvPlaceholders()
+    {
+        return $this->envPlaceholders;
+    }
+
+    /**
+     * Merges the env placeholders of another EnvPlaceholderParameterBag.
+     */
+    public function mergeEnvPlaceholders(self $bag)
+    {
+        if ($newPlaceholders = $bag->getEnvPlaceholders()) {
+            $this->envPlaceholders += $newPlaceholders;
+
+            foreach ($newPlaceholders as $env => $placeholders) {
+                $this->envPlaceholders[$env] += $placeholders;
+            }
+        }
+    }
+
+    /**
+     * Maps env prefixes to their corresponding PHP types.
+     */
+    public function setProvidedTypes(array $providedTypes)
+    {
+        $this->providedTypes = $providedTypes;
+    }
+
+    /**
+     * Gets the PHP types corresponding to env() parameter prefixes.
+     *
+     * @return string[][]
+     */
+    public function getProvidedTypes()
+    {
+        return $this->providedTypes;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function resolve()
+    {
+        if ($this->resolved) {
+            return;
+        }
+        parent::resolve();
+
+        foreach ($this->envPlaceholders as $env => $placeholders) {
+            if (!$this->has($name = "env($env)")) {
+                continue;
+            }
+            if (is_numeric($default = $this->parameters[$name])) {
+                $this->parameters[$name] = (string) $default;
+            } elseif (null !== $default && !is_scalar($default)) {
+                throw new RuntimeException(sprintf('The default value of env parameter "%s" must be scalar or null, "%s" given.', $env, \gettype($default)));
+            }
+        }
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php b/civicrm/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php
index ad65ad960f..a5199937e2 100644
--- a/civicrm/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php
+++ b/civicrm/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php
@@ -28,7 +28,7 @@ class FrozenParameterBag extends ParameterBag
      *
      * @param array $parameters An array of parameters
      */
-    public function __construct(array $parameters = array())
+    public function __construct(array $parameters = [])
     {
         $this->parameters = $parameters;
         $this->resolved = true;
diff --git a/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php b/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php
index c17029b3ef..539d56616d 100644
--- a/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php
+++ b/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php
@@ -22,13 +22,15 @@ use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  */
 class ParameterBag implements ParameterBagInterface
 {
-    protected $parameters = array();
+    protected $parameters = [];
     protected $resolved = false;
 
+    private $normalizedNames = [];
+
     /**
      * @param array $parameters An array of parameters
      */
-    public function __construct(array $parameters = array())
+    public function __construct(array $parameters = [])
     {
         $this->add($parameters);
     }
@@ -38,7 +40,7 @@ class ParameterBag implements ParameterBagInterface
      */
     public function clear()
     {
-        $this->parameters = array();
+        $this->parameters = [];
     }
 
     /**
@@ -49,7 +51,7 @@ class ParameterBag implements ParameterBagInterface
     public function add(array $parameters)
     {
         foreach ($parameters as $key => $value) {
-            $this->parameters[strtolower($key)] = $value;
+            $this->set($key, $value);
         }
     }
 
@@ -66,14 +68,14 @@ class ParameterBag implements ParameterBagInterface
      */
     public function get($name)
     {
-        $name = strtolower($name);
+        $name = $this->normalizeName($name);
 
-        if (!array_key_exists($name, $this->parameters)) {
+        if (!\array_key_exists($name, $this->parameters)) {
             if (!$name) {
                 throw new ParameterNotFoundException($name);
             }
 
-            $alternatives = array();
+            $alternatives = [];
             foreach ($this->parameters as $key => $parameterValue) {
                 $lev = levenshtein($name, $key);
                 if ($lev <= \strlen($name) / 3 || false !== strpos($key, $name)) {
@@ -81,7 +83,23 @@ class ParameterBag implements ParameterBagInterface
                 }
             }
 
-            throw new ParameterNotFoundException($name, null, null, null, $alternatives);
+            $nonNestedAlternative = null;
+            if (!\count($alternatives) && false !== strpos($name, '.')) {
+                $namePartsLength = array_map('strlen', explode('.', $name));
+                $key = substr($name, 0, -1 * (1 + array_pop($namePartsLength)));
+                while (\count($namePartsLength)) {
+                    if ($this->has($key)) {
+                        if (\is_array($this->get($key))) {
+                            $nonNestedAlternative = $key;
+                        }
+                        break;
+                    }
+
+                    $key = substr($key, 0, -1 * (1 + array_pop($namePartsLength)));
+                }
+            }
+
+            throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative);
         }
 
         return $this->parameters[$name];
@@ -95,7 +113,7 @@ class ParameterBag implements ParameterBagInterface
      */
     public function set($name, $value)
     {
-        $this->parameters[strtolower($name)] = $value;
+        $this->parameters[$this->normalizeName($name)] = $value;
     }
 
     /**
@@ -103,7 +121,7 @@ class ParameterBag implements ParameterBagInterface
      */
     public function has($name)
     {
-        return array_key_exists(strtolower($name), $this->parameters);
+        return \array_key_exists($this->normalizeName($name), $this->parameters);
     }
 
     /**
@@ -113,7 +131,7 @@ class ParameterBag implements ParameterBagInterface
      */
     public function remove($name)
     {
-        unset($this->parameters[strtolower($name)]);
+        unset($this->parameters[$this->normalizeName($name)]);
     }
 
     /**
@@ -125,7 +143,7 @@ class ParameterBag implements ParameterBagInterface
             return;
         }
 
-        $parameters = array();
+        $parameters = [];
         foreach ($this->parameters as $key => $value) {
             try {
                 $value = $this->resolveValue($value);
@@ -153,18 +171,18 @@ class ParameterBag implements ParameterBagInterface
      * @throws ParameterCircularReferenceException if a circular reference if detected
      * @throws RuntimeException                    when a given parameter has a type problem
      */
-    public function resolveValue($value, array $resolving = array())
+    public function resolveValue($value, array $resolving = [])
     {
         if (\is_array($value)) {
-            $args = array();
+            $args = [];
             foreach ($value as $k => $v) {
-                $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving);
+                $args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving);
             }
 
             return $args;
         }
 
-        if (!\is_string($value)) {
+        if (!\is_string($value) || 2 > \strlen($value)) {
             return $value;
         }
 
@@ -177,52 +195,52 @@ class ParameterBag implements ParameterBagInterface
      * @param string $value     The string to resolve
      * @param array  $resolving An array of keys that are being resolved (used internally to detect circular references)
      *
-     * @return string The resolved string
+     * @return mixed The resolved string
      *
      * @throws ParameterNotFoundException          if a placeholder references a parameter that does not exist
      * @throws ParameterCircularReferenceException if a circular reference if detected
      * @throws RuntimeException                    when a given parameter has a type problem
      */
-    public function resolveString($value, array $resolving = array())
+    public function resolveString($value, array $resolving = [])
     {
         // we do this to deal with non string values (Boolean, integer, ...)
         // as the preg_replace_callback throw an exception when trying
         // a non-string in a parameter value
         if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
-            $key = strtolower($match[1]);
+            $key = $match[1];
+            $lcKey = strtolower($key); // strtolower() to be removed in 4.0
 
-            if (isset($resolving[$key])) {
+            if (isset($resolving[$lcKey])) {
                 throw new ParameterCircularReferenceException(array_keys($resolving));
             }
 
-            $resolving[$key] = true;
+            $resolving[$lcKey] = true;
 
             return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
         }
 
-        $self = $this;
-
-        return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value) {
+        return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($resolving, $value) {
             // skip %%
             if (!isset($match[1])) {
                 return '%%';
             }
 
-            $key = strtolower($match[1]);
-            if (isset($resolving[$key])) {
+            $key = $match[1];
+            $lcKey = strtolower($key); // strtolower() to be removed in 4.0
+            if (isset($resolving[$lcKey])) {
                 throw new ParameterCircularReferenceException(array_keys($resolving));
             }
 
-            $resolved = $self->get($key);
+            $resolved = $this->get($key);
 
             if (!\is_string($resolved) && !is_numeric($resolved)) {
-                throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, \gettype($resolved), $value));
+                throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type "%s" inside string value "%s".', $key, \gettype($resolved), $value));
             }
 
             $resolved = (string) $resolved;
-            $resolving[$key] = true;
+            $resolving[$lcKey] = true;
 
-            return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving);
+            return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving);
         }, $value);
     }
 
@@ -241,7 +259,7 @@ class ParameterBag implements ParameterBagInterface
         }
 
         if (\is_array($value)) {
-            $result = array();
+            $result = [];
             foreach ($value as $k => $v) {
                 $result[$k] = $this->escapeValue($v);
             }
@@ -262,7 +280,7 @@ class ParameterBag implements ParameterBagInterface
         }
 
         if (\is_array($value)) {
-            $result = array();
+            $result = [];
             foreach ($value as $k => $v) {
                 $result[$k] = $this->unescapeValue($v);
             }
@@ -272,4 +290,18 @@ class ParameterBag implements ParameterBagInterface
 
         return $value;
     }
+
+    private function normalizeName($name)
+    {
+        if (isset($this->normalizedNames[$normalizedName = strtolower($name)])) {
+            $normalizedName = $this->normalizedNames[$normalizedName];
+            if ((string) $name !== $normalizedName) {
+                @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
+            }
+        } else {
+            $normalizedName = $this->normalizedNames[$normalizedName] = (string) $name;
+        }
+
+        return $normalizedName;
+    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php b/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php
index 3291b373de..7386df0648 100644
--- a/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php
+++ b/civicrm/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php
@@ -55,6 +55,13 @@ interface ParameterBagInterface
      */
     public function get($name);
 
+    /**
+     * Removes a parameter.
+     *
+     * @param string $name The parameter name
+     */
+    public function remove($name);
+
     /**
      * Sets a service container parameter.
      *
diff --git a/civicrm/vendor/symfony/dependency-injection/README.md b/civicrm/vendor/symfony/dependency-injection/README.md
index 932647f94a..cb2d4a11c5 100644
--- a/civicrm/vendor/symfony/dependency-injection/README.md
+++ b/civicrm/vendor/symfony/dependency-injection/README.md
@@ -7,7 +7,7 @@ way objects are constructed in your application.
 Resources
 ---------
 
-  * [Documentation](https://symfony.com/doc/current/components/dependency_injection/index.html)
+  * [Documentation](https://symfony.com/doc/current/components/dependency_injection.html)
   * [Contributing](https://symfony.com/doc/current/contributing/index.html)
   * [Report issues](https://github.com/symfony/symfony/issues) and
     [send Pull Requests](https://github.com/symfony/symfony/pulls)
diff --git a/civicrm/vendor/symfony/dependency-injection/Reference.php b/civicrm/vendor/symfony/dependency-injection/Reference.php
index 869dfae1bc..82906d2b75 100644
--- a/civicrm/vendor/symfony/dependency-injection/Reference.php
+++ b/civicrm/vendor/symfony/dependency-injection/Reference.php
@@ -20,22 +20,17 @@ class Reference
 {
     private $id;
     private $invalidBehavior;
-    private $strict;
 
     /**
-     * Note: The $strict parameter is deprecated since version 2.8 and will be removed in 3.0.
-     *
      * @param string $id              The service identifier
      * @param int    $invalidBehavior The behavior when the service does not exist
-     * @param bool   $strict          Sets how this reference is validated
      *
      * @see Container
      */
-    public function __construct($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $strict = true)
+    public function __construct($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
     {
-        $this->id = strtolower($id);
+        $this->id = (string) $id;
         $this->invalidBehavior = $invalidBehavior;
-        $this->strict = $strict;
     }
 
     /**
@@ -55,20 +50,4 @@ class Reference
     {
         return $this->invalidBehavior;
     }
-
-    /**
-     * Returns true when this Reference is strict.
-     *
-     * @return bool
-     *
-     * @deprecated since version 2.8, to be removed in 3.0.
-     */
-    public function isStrict($triggerDeprecationError = true)
-    {
-        if ($triggerDeprecationError) {
-            @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-        }
-
-        return $this->strict;
-    }
 }
diff --git a/civicrm/vendor/symfony/dependency-injection/Scope.php b/civicrm/vendor/symfony/dependency-injection/Scope.php
deleted file mode 100644
index b0b8ed6c2e..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/Scope.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection;
-
-/**
- * Scope class.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- *
- * @deprecated since version 2.8, to be removed in 3.0.
- */
-class Scope implements ScopeInterface
-{
-    private $name;
-    private $parentName;
-
-    public function __construct($name, $parentName = ContainerInterface::SCOPE_CONTAINER)
-    {
-        $this->name = $name;
-        $this->parentName = $parentName;
-    }
-
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    public function getParentName()
-    {
-        return $this->parentName;
-    }
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/ScopeInterface.php b/civicrm/vendor/symfony/dependency-injection/ScopeInterface.php
deleted file mode 100644
index 11b1097399..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/ScopeInterface.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection;
-
-/**
- * Scope Interface.
- *
- * @author Johannes M. Schmitt <schmittjoh@gmail.com>
- *
- * @deprecated since version 2.8, to be removed in 3.0.
- */
-interface ScopeInterface
-{
-    public function getName();
-
-    public function getParentName();
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/ServiceLocator.php b/civicrm/vendor/symfony/dependency-injection/ServiceLocator.php
new file mode 100644
index 0000000000..a4f5bf9945
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/ServiceLocator.php
@@ -0,0 +1,146 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection;
+
+use Psr\Container\ContainerInterface as PsrContainerInterface;
+use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+
+/**
+ * @author Robin Chalas <robin.chalas@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class ServiceLocator implements PsrContainerInterface
+{
+    private $factories;
+    private $loading = [];
+    private $externalId;
+    private $container;
+
+    /**
+     * @param callable[] $factories
+     */
+    public function __construct(array $factories)
+    {
+        $this->factories = $factories;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($id)
+    {
+        return isset($this->factories[$id]);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($id)
+    {
+        if (!isset($this->factories[$id])) {
+            throw new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], $this->createServiceNotFoundMessage($id));
+        }
+
+        if (isset($this->loading[$id])) {
+            $ids = array_values($this->loading);
+            $ids = \array_slice($this->loading, array_search($id, $ids));
+            $ids[] = $id;
+
+            throw new ServiceCircularReferenceException($id, $ids);
+        }
+
+        $this->loading[$id] = $id;
+        try {
+            return $this->factories[$id]();
+        } finally {
+            unset($this->loading[$id]);
+        }
+    }
+
+    public function __invoke($id)
+    {
+        return isset($this->factories[$id]) ? $this->get($id) : null;
+    }
+
+    /**
+     * @internal
+     */
+    public function withContext($externalId, Container $container)
+    {
+        $locator = clone $this;
+        $locator->externalId = $externalId;
+        $locator->container = $container;
+
+        return $locator;
+    }
+
+    private function createServiceNotFoundMessage($id)
+    {
+        if ($this->loading) {
+            return sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives());
+        }
+
+        $class = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 3);
+        $class = isset($class[2]['object']) ? \get_class($class[2]['object']) : null;
+        $externalId = $this->externalId ?: $class;
+
+        $msg = [];
+        $msg[] = sprintf('Service "%s" not found:', $id);
+
+        if (!$this->container) {
+            $class = null;
+        } elseif ($this->container->has($id) || isset($this->container->getRemovedIds()[$id])) {
+            $msg[] = 'even though it exists in the app\'s container,';
+        } else {
+            try {
+                $this->container->get($id);
+                $class = null;
+            } catch (ServiceNotFoundException $e) {
+                if ($e->getAlternatives()) {
+                    $msg[] = sprintf('did you mean %s? Anyway,', $this->formatAlternatives($e->getAlternatives(), 'or'));
+                } else {
+                    $class = null;
+                }
+            }
+        }
+        if ($externalId) {
+            $msg[] = sprintf('the container inside "%s" is a smaller service locator that %s', $externalId, $this->formatAlternatives());
+        } else {
+            $msg[] = sprintf('the current service locator %s', $this->formatAlternatives());
+        }
+
+        if (!$class) {
+            // no-op
+        } elseif (is_subclass_of($class, ServiceSubscriberInterface::class)) {
+            $msg[] = sprintf('Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "%s::getSubscribedServices()".', preg_replace('/([^\\\\]++\\\\)++/', '', $class));
+        } else {
+            $msg[] = 'Try using dependency injection instead.';
+        }
+
+        return implode(' ', $msg);
+    }
+
+    private function formatAlternatives(array $alternatives = null, $separator = 'and')
+    {
+        $format = '"%s"%s';
+        if (null === $alternatives) {
+            if (!$alternatives = array_keys($this->factories)) {
+                return 'is empty...';
+            }
+            $format = sprintf('only knows about the %s service%s.', $format, 1 < \count($alternatives) ? 's' : '');
+        }
+        $last = array_pop($alternatives);
+
+        return sprintf($format, $alternatives ? implode('", "', $alternatives) : $last, $alternatives ? sprintf(' %s "%s"', $separator, $last) : '');
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/ServiceSubscriberInterface.php b/civicrm/vendor/symfony/dependency-injection/ServiceSubscriberInterface.php
new file mode 100644
index 0000000000..10c2387544
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/ServiceSubscriberInterface.php
@@ -0,0 +1,50 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection;
+
+/**
+ * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
+ *
+ * The getSubscribedServices method returns an array of service types required by such instances,
+ * optionally keyed by the service names used internally. Service types that start with an interrogation
+ * mark "?" are optional, while the other ones are mandatory service dependencies.
+ *
+ * The injected service locators SHOULD NOT allow access to any other services not specified by the method.
+ *
+ * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
+ * This interface does not dictate any injection method for these service locators, although constructor
+ * injection is recommended.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface ServiceSubscriberInterface
+{
+    /**
+     * Returns an array of service types required by such instances, optionally keyed by the service names used internally.
+     *
+     * For mandatory dependencies:
+     *
+     *  * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name
+     *    internally to fetch a service which must implement Psr\Log\LoggerInterface.
+     *  * ['Psr\Log\LoggerInterface'] is a shortcut for
+     *  * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface']
+     *
+     * otherwise:
+     *
+     *  * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency
+     *  * ['?Psr\Log\LoggerInterface'] is a shortcut for
+     *  * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface']
+     *
+     * @return array The required service types, optionally keyed by service names
+     */
+    public static function getSubscribedServices();
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/SimpleXMLElement.php b/civicrm/vendor/symfony/dependency-injection/SimpleXMLElement.php
deleted file mode 100644
index bb985ace4f..0000000000
--- a/civicrm/vendor/symfony/dependency-injection/SimpleXMLElement.php
+++ /dev/null
@@ -1,116 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection;
-
-@trigger_error('The '.__NAMESPACE__.'\SimpleXMLElement class is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-use Symfony\Component\Config\Util\XmlUtils;
-use Symfony\Component\ExpressionLanguage\Expression;
-
-/**
- * SimpleXMLElement class.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- *
- * @deprecated since version 2.5, to be removed in 3.0.
- */
-class SimpleXMLElement extends \SimpleXMLElement
-{
-    /**
-     * Converts an attribute as a PHP type.
-     *
-     * @param string $name
-     *
-     * @return mixed
-     */
-    public function getAttributeAsPhp($name)
-    {
-        return self::phpize($this[$name]);
-    }
-
-    /**
-     * Returns arguments as valid PHP types.
-     *
-     * @param string $name
-     * @param bool   $lowercase
-     *
-     * @return mixed
-     */
-    public function getArgumentsAsPhp($name, $lowercase = true)
-    {
-        $arguments = array();
-        foreach ($this->$name as $arg) {
-            if (isset($arg['name'])) {
-                $arg['key'] = (string) $arg['name'];
-            }
-            $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1);
-
-            // parameter keys are case insensitive
-            if ('parameter' == $name && $lowercase) {
-                $key = strtolower($key);
-            }
-
-            // this is used by DefinitionDecorator to overwrite a specific
-            // argument of the parent definition
-            if (isset($arg['index'])) {
-                $key = 'index_'.$arg['index'];
-            }
-
-            switch ($arg['type']) {
-                case 'service':
-                    $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
-                    if (isset($arg['on-invalid']) && 'ignore' == $arg['on-invalid']) {
-                        $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
-                    } elseif (isset($arg['on-invalid']) && 'null' == $arg['on-invalid']) {
-                        $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
-                    }
-
-                    if (isset($arg['strict'])) {
-                        $strict = self::phpize($arg['strict']);
-                    } else {
-                        $strict = true;
-                    }
-
-                    $arguments[$key] = new Reference((string) $arg['id'], $invalidBehavior, $strict);
-                    break;
-                case 'expression':
-                    $arguments[$key] = new Expression((string) $arg);
-                    break;
-                case 'collection':
-                    $arguments[$key] = $arg->getArgumentsAsPhp($name, false);
-                    break;
-                case 'string':
-                    $arguments[$key] = (string) $arg;
-                    break;
-                case 'constant':
-                    $arguments[$key] = \constant((string) $arg);
-                    break;
-                default:
-                    $arguments[$key] = self::phpize($arg);
-            }
-        }
-
-        return $arguments;
-    }
-
-    /**
-     * Converts an xml value to a PHP type.
-     *
-     * @param mixed $value
-     *
-     * @return mixed
-     */
-    public static function phpize($value)
-    {
-        return XmlUtils::phpize($value);
-    }
-}
diff --git a/civicrm/vendor/symfony/dependency-injection/TypedReference.php b/civicrm/vendor/symfony/dependency-injection/TypedReference.php
new file mode 100644
index 0000000000..aad78e806b
--- /dev/null
+++ b/civicrm/vendor/symfony/dependency-injection/TypedReference.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection;
+
+/**
+ * Represents a PHP type-hinted service reference.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class TypedReference extends Reference
+{
+    private $type;
+    private $requiringClass;
+
+    /**
+     * @param string $id              The service identifier
+     * @param string $type            The PHP type of the identified service
+     * @param string $requiringClass  The class of the service that requires the referenced type
+     * @param int    $invalidBehavior The behavior when the service does not exist
+     */
+    public function __construct($id, $type, $requiringClass = '', $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
+    {
+        parent::__construct($id, $invalidBehavior);
+        $this->type = $type;
+        $this->requiringClass = $requiringClass;
+    }
+
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    public function getRequiringClass()
+    {
+        return $this->requiringClass;
+    }
+
+    public function canBeAutoregistered()
+    {
+        return $this->requiringClass && (false !== $i = strpos($this->type, '\\')) && 0 === strncasecmp($this->type, $this->requiringClass, 1 + $i);
+    }
+}
diff --git a/civicrm/vendor/symfony/dependency-injection/composer.json b/civicrm/vendor/symfony/dependency-injection/composer.json
index 2506690ca6..6eaa3fd089 100644
--- a/civicrm/vendor/symfony/dependency-injection/composer.json
+++ b/civicrm/vendor/symfony/dependency-injection/composer.json
@@ -16,22 +16,30 @@
         }
     ],
     "require": {
-        "php": ">=5.3.9"
+        "php": "^5.5.9|>=7.0.8",
+        "psr/container": "^1.0"
     },
     "require-dev": {
-        "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7",
-        "symfony/config": "~2.2|~3.0.0",
-        "symfony/expression-language": "~2.6|~3.0.0"
-    },
-    "conflict": {
-        "symfony/expression-language": "<2.6"
+        "symfony/yaml": "~3.4|~4.0",
+        "symfony/config": "~3.3|~4.0",
+        "symfony/expression-language": "~2.8|~3.0|~4.0"
     },
     "suggest": {
         "symfony/yaml": "",
         "symfony/config": "",
+        "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required",
         "symfony/expression-language": "For using expressions in service container configuration",
         "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them"
     },
+    "conflict": {
+        "symfony/config": "<3.3.7",
+        "symfony/finder": "<3.3",
+        "symfony/proxy-manager-bridge": "<3.4",
+        "symfony/yaml": "<3.4"
+    },
+    "provide": {
+        "psr/container-implementation": "1.0"
+    },
     "autoload": {
         "psr-4": { "Symfony\\Component\\DependencyInjection\\": "" },
         "exclude-from-classmap": [
@@ -41,7 +49,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "2.8-dev"
+            "dev-master": "3.4-dev"
         }
     }
 }
diff --git a/civicrm/vendor/symfony/event-dispatcher/CHANGELOG.md b/civicrm/vendor/symfony/event-dispatcher/CHANGELOG.md
index bb42ee19c0..c6aa5389ac 100644
--- a/civicrm/vendor/symfony/event-dispatcher/CHANGELOG.md
+++ b/civicrm/vendor/symfony/event-dispatcher/CHANGELOG.md
@@ -1,6 +1,25 @@
 CHANGELOG
 =========
 
+3.4.0
+-----
+
+  * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated.
+
+3.3.0
+-----
+
+  * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead.
+
+3.0.0
+-----
+
+  * The method `getListenerPriority($eventName, $listener)` has been added to the
+    `EventDispatcherInterface`.
+  * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()`
+    and `Event::getName()` have been removed.
+    The event dispatcher and the event name are passed to the listener call.
+
 2.5.0
 -----
 
diff --git a/civicrm/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php b/civicrm/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php
index 4dcede7e73..8f53a9d06a 100644
--- a/civicrm/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php
+++ b/civicrm/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php
@@ -11,6 +11,7 @@
 
 namespace Symfony\Component\EventDispatcher;
 
+use PHPUnit\Framework\MockObject\MockObject;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -20,6 +21,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Bernhard Schussek <bschussek@gmail.com>
  * @author Jordan Alliot <jordan.alliot@gmail.com>
+ *
+ * @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure factories instead.
  */
 class ContainerAwareEventDispatcher extends EventDispatcher
 {
@@ -28,16 +31,24 @@ class ContainerAwareEventDispatcher extends EventDispatcher
     /**
      * The service IDs of the event listeners and subscribers.
      */
-    private $listenerIds = array();
+    private $listenerIds = [];
 
     /**
      * The services registered as listeners.
      */
-    private $listeners = array();
+    private $listeners = [];
 
     public function __construct(ContainerInterface $container)
     {
         $this->container = $container;
+
+        $class = static::class;
+        if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) {
+            $class = get_parent_class($class);
+        }
+        if (__CLASS__ !== $class) {
+            @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED);
+        }
     }
 
     /**
@@ -54,11 +65,13 @@ class ContainerAwareEventDispatcher extends EventDispatcher
      */
     public function addListenerService($eventName, $callback, $priority = 0)
     {
+        @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED);
+
         if (!\is_array($callback) || 2 !== \count($callback)) {
-            throw new \InvalidArgumentException('Expected an array("service", "method") argument');
+            throw new \InvalidArgumentException('Expected an ["service", "method"] argument.');
         }
 
-        $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
+        $this->listenerIds[$eventName][] = [$callback[0], $callback[1], $priority];
     }
 
     public function removeListener($eventName, $listener)
@@ -66,10 +79,9 @@ class ContainerAwareEventDispatcher extends EventDispatcher
         $this->lazyLoad($eventName);
 
         if (isset($this->listenerIds[$eventName])) {
-            foreach ($this->listenerIds[$eventName] as $i => $args) {
-                list($serviceId, $method) = $args;
+            foreach ($this->listenerIds[$eventName] as $i => list($serviceId, $method)) {
                 $key = $serviceId.'.'.$method;
-                if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) {
+                if (isset($this->listeners[$eventName][$key]) && $listener === [$this->listeners[$eventName][$key], $method]) {
                     unset($this->listeners[$eventName][$key]);
                     if (empty($this->listeners[$eventName])) {
                         unset($this->listeners[$eventName]);
@@ -135,14 +147,16 @@ class ContainerAwareEventDispatcher extends EventDispatcher
      */
     public function addSubscriberService($serviceId, $class)
     {
+        @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED);
+
         foreach ($class::getSubscribedEvents() as $eventName => $params) {
             if (\is_string($params)) {
-                $this->listenerIds[$eventName][] = array($serviceId, $params, 0);
+                $this->listenerIds[$eventName][] = [$serviceId, $params, 0];
             } elseif (\is_string($params[0])) {
-                $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0);
+                $this->listenerIds[$eventName][] = [$serviceId, $params[0], isset($params[1]) ? $params[1] : 0];
             } else {
                 foreach ($params as $listener) {
-                    $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0);
+                    $this->listenerIds[$eventName][] = [$serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0];
                 }
             }
         }
@@ -150,6 +164,8 @@ class ContainerAwareEventDispatcher extends EventDispatcher
 
     public function getContainer()
     {
+        @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 as its class will be removed in 4.0. Inject the container or the services you need in your listeners/subscribers instead.', E_USER_DEPRECATED);
+
         return $this->container;
     }
 
@@ -164,16 +180,15 @@ class ContainerAwareEventDispatcher extends EventDispatcher
     protected function lazyLoad($eventName)
     {
         if (isset($this->listenerIds[$eventName])) {
-            foreach ($this->listenerIds[$eventName] as $args) {
-                list($serviceId, $method, $priority) = $args;
+            foreach ($this->listenerIds[$eventName] as list($serviceId, $method, $priority)) {
                 $listener = $this->container->get($serviceId);
 
                 $key = $serviceId.'.'.$method;
                 if (!isset($this->listeners[$eventName][$key])) {
-                    $this->addListener($eventName, array($listener, $method), $priority);
+                    $this->addListener($eventName, [$listener, $method], $priority);
                 } elseif ($this->listeners[$eventName][$key] !== $listener) {
-                    parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
-                    $this->addListener($eventName, array($listener, $method), $priority);
+                    parent::removeListener($eventName, [$this->listeners[$eventName][$key], $method]);
+                    $this->addListener($eventName, [$listener, $method], $priority);
                 }
 
                 $this->listeners[$eventName][$key] = $listener;
diff --git a/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
index 53d7c5d51a..017459723d 100644
--- a/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
+++ b/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
@@ -29,7 +29,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
     protected $logger;
     protected $stopwatch;
 
-    private $called;
+    private $callStack;
     private $dispatcher;
     private $wrappedListeners;
 
@@ -38,8 +38,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
         $this->dispatcher = $dispatcher;
         $this->stopwatch = $stopwatch;
         $this->logger = $logger;
-        $this->called = array();
-        $this->wrappedListeners = array();
+        $this->wrappedListeners = [];
     }
 
     /**
@@ -97,8 +96,14 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
      */
     public function getListenerPriority($eventName, $listener)
     {
-        if (!method_exists($this->dispatcher, 'getListenerPriority')) {
-            return 0;
+        // we might have wrapped listeners for the event (if called while dispatching)
+        // in that case get the priority by wrapper
+        if (isset($this->wrappedListeners[$eventName])) {
+            foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
+                if ($wrappedListener->getWrappedListener() === $listener) {
+                    return $this->dispatcher->getListenerPriority($eventName, $wrappedListener);
+                }
+            }
         }
 
         return $this->dispatcher->getListenerPriority($eventName, $listener);
@@ -117,6 +122,10 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
      */
     public function dispatch($eventName, Event $event = null)
     {
+        if (null === $this->callStack) {
+            $this->callStack = new \SplObjectStorage();
+        }
+
         if (null === $event) {
             $event = new Event();
         }
@@ -126,19 +135,24 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
         }
 
         $this->preProcess($eventName);
-        $this->preDispatch($eventName, $event);
-
-        $e = $this->stopwatch->start($eventName, 'section');
-
-        $this->dispatcher->dispatch($eventName, $event);
-
-        if ($e->isStarted()) {
-            $e->stop();
+        try {
+            $this->preDispatch($eventName, $event);
+            try {
+                $e = $this->stopwatch->start($eventName, 'section');
+                try {
+                    $this->dispatcher->dispatch($eventName, $event);
+                } finally {
+                    if ($e->isStarted()) {
+                        $e->stop();
+                    }
+                }
+            } finally {
+                $this->postDispatch($eventName, $event);
+            }
+        } finally {
+            $this->postProcess($eventName);
         }
 
-        $this->postDispatch($eventName, $event);
-        $this->postProcess($eventName);
-
         return $event;
     }
 
@@ -147,12 +161,15 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
      */
     public function getCalledListeners()
     {
-        $called = array();
-        foreach ($this->called as $eventName => $listeners) {
-            foreach ($listeners as $listener) {
-                $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
-                $called[$eventName.'.'.$info['pretty']] = $info;
-            }
+        if (null === $this->callStack) {
+            return [];
+        }
+
+        $called = [];
+        foreach ($this->callStack as $listener) {
+            list($eventName) = $this->callStack->getInfo();
+
+            $called[] = $listener->getInfo($eventName);
         }
 
         return $called;
@@ -167,39 +184,43 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
             $allListeners = $this->getListeners();
         } catch (\Exception $e) {
             if (null !== $this->logger) {
-                $this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e));
+                $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]);
             }
 
             // unable to retrieve the uncalled listeners
-            return array();
+            return [];
+        }
+
+        $calledListeners = [];
+
+        if (null !== $this->callStack) {
+            foreach ($this->callStack as $calledListener) {
+                $calledListeners[] = $calledListener->getWrappedListener();
+            }
         }
 
-        $notCalled = array();
+        $notCalled = [];
         foreach ($allListeners as $eventName => $listeners) {
             foreach ($listeners as $listener) {
-                $called = false;
-                if (isset($this->called[$eventName])) {
-                    foreach ($this->called[$eventName] as $l) {
-                        if ($l->getWrappedListener() === $listener) {
-                            $called = true;
-
-                            break;
-                        }
+                if (!\in_array($listener, $calledListeners, true)) {
+                    if (!$listener instanceof WrappedListener) {
+                        $listener = new WrappedListener($listener, null, $this->stopwatch, $this);
                     }
-                }
-
-                if (!$called) {
-                    $info = $this->getListenerInfo($listener, $eventName);
-                    $notCalled[$eventName.'.'.$info['pretty']] = $info;
+                    $notCalled[] = $listener->getInfo($eventName);
                 }
             }
         }
 
-        uasort($notCalled, array($this, 'sortListenersByPriority'));
+        uasort($notCalled, [$this, 'sortNotCalledListeners']);
 
         return $notCalled;
     }
 
+    public function reset()
+    {
+        $this->callStack = null;
+    }
+
     /**
      * Proxies all method calls to the original event dispatcher.
      *
@@ -210,7 +231,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
      */
     public function __call($method, $arguments)
     {
-        return \call_user_func_array(array($this->dispatcher, $method), $arguments);
+        return \call_user_func_array([$this->dispatcher, $method], $arguments);
     }
 
     /**
@@ -236,12 +257,12 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
     private function preProcess($eventName)
     {
         foreach ($this->dispatcher->getListeners($eventName) as $listener) {
-            $info = $this->getListenerInfo($listener, $eventName);
-            $name = isset($info['class']) ? $info['class'] : $info['type'];
-            $wrappedListener = new WrappedListener($listener, $name, $this->stopwatch, $this);
+            $priority = $this->getListenerPriority($eventName, $listener);
+            $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this);
             $this->wrappedListeners[$eventName][] = $wrappedListener;
             $this->dispatcher->removeListener($eventName, $listener);
-            $this->dispatcher->addListener($eventName, $wrappedListener, $info['priority']);
+            $this->dispatcher->addListener($eventName, $wrappedListener, $priority);
+            $this->callStack->attach($wrappedListener, [$eventName]);
         }
     }
 
@@ -258,26 +279,25 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
             $this->dispatcher->removeListener($eventName, $listener);
             $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
 
-            $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
+            if (null !== $this->logger) {
+                $context = ['event' => $eventName, 'listener' => $listener->getPretty()];
+            }
+
             if ($listener->wasCalled()) {
                 if (null !== $this->logger) {
-                    $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty']));
-                }
-
-                if (!isset($this->called[$eventName])) {
-                    $this->called[$eventName] = new \SplObjectStorage();
+                    $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context);
                 }
-
-                $this->called[$eventName]->attach($listener);
+            } else {
+                $this->callStack->detach($listener);
             }
 
             if (null !== $this->logger && $skipped) {
-                $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName));
+                $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context);
             }
 
             if ($listener->stoppedPropagation()) {
                 if (null !== $this->logger) {
-                    $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName));
+                    $this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context);
                 }
 
                 $skipped = true;
@@ -285,75 +305,12 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
         }
     }
 
-    /**
-     * Returns information about the listener.
-     *
-     * @param object $listener  The listener
-     * @param string $eventName The event name
-     *
-     * @return array Information about the listener
-     */
-    private function getListenerInfo($listener, $eventName)
+    private function sortNotCalledListeners(array $a, array $b)
     {
-        $info = array(
-            'event' => $eventName,
-            'priority' => $this->getListenerPriority($eventName, $listener),
-        );
-
-        // unwrap for correct listener info
-        if ($listener instanceof WrappedListener) {
-            $listener = $listener->getWrappedListener();
+        if (0 !== $cmp = strcmp($a['event'], $b['event'])) {
+            return $cmp;
         }
 
-        if ($listener instanceof \Closure) {
-            $info += array(
-                'type' => 'Closure',
-                'pretty' => 'closure',
-            );
-        } elseif (\is_string($listener)) {
-            try {
-                $r = new \ReflectionFunction($listener);
-                $file = $r->getFileName();
-                $line = $r->getStartLine();
-            } catch (\ReflectionException $e) {
-                $file = null;
-                $line = null;
-            }
-            $info += array(
-                'type' => 'Function',
-                'function' => $listener,
-                'file' => $file,
-                'line' => $line,
-                'pretty' => $listener,
-            );
-        } elseif (\is_array($listener) || (\is_object($listener) && \is_callable($listener))) {
-            if (!\is_array($listener)) {
-                $listener = array($listener, '__invoke');
-            }
-            $class = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0];
-            try {
-                $r = new \ReflectionMethod($class, $listener[1]);
-                $file = $r->getFileName();
-                $line = $r->getStartLine();
-            } catch (\ReflectionException $e) {
-                $file = null;
-                $line = null;
-            }
-            $info += array(
-                'type' => 'Method',
-                'class' => $class,
-                'method' => $listener[1],
-                'file' => $file,
-                'line' => $line,
-                'pretty' => $class.'::'.$listener[1],
-            );
-        }
-
-        return $info;
-    }
-
-    private function sortListenersByPriority($a, $b)
-    {
         if (\is_int($a['priority']) && !\is_int($b['priority'])) {
             return 1;
         }
diff --git a/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php b/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
index 5483e81506..f0212753be 100644
--- a/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
+++ b/civicrm/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
@@ -15,6 +15,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 /**
  * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @method reset() Resets the trace.
  */
 interface TraceableEventDispatcherInterface extends EventDispatcherInterface
 {
diff --git a/civicrm/vendor/symfony/event-dispatcher/Debug/WrappedListener.php b/civicrm/vendor/symfony/event-dispatcher/Debug/WrappedListener.php
index 1552af02d8..de2b850953 100644
--- a/civicrm/vendor/symfony/event-dispatcher/Debug/WrappedListener.php
+++ b/civicrm/vendor/symfony/event-dispatcher/Debug/WrappedListener.php
@@ -14,6 +14,7 @@ namespace Symfony\Component\EventDispatcher\Debug;
 use Symfony\Component\EventDispatcher\Event;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\Stopwatch\Stopwatch;
+use Symfony\Component\VarDumper\Caster\ClassStub;
 
 /**
  * @author Fabien Potencier <fabien@symfony.com>
@@ -26,15 +27,46 @@ class WrappedListener
     private $stoppedPropagation;
     private $stopwatch;
     private $dispatcher;
+    private $pretty;
+    private $stub;
+    private $priority;
+    private static $hasClassStub;
 
     public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
     {
         $this->listener = $listener;
-        $this->name = $name;
         $this->stopwatch = $stopwatch;
         $this->dispatcher = $dispatcher;
         $this->called = false;
         $this->stoppedPropagation = false;
+
+        if (\is_array($listener)) {
+            $this->name = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0];
+            $this->pretty = $this->name.'::'.$listener[1];
+        } elseif ($listener instanceof \Closure) {
+            $r = new \ReflectionFunction($listener);
+            if (false !== strpos($r->name, '{closure}')) {
+                $this->pretty = $this->name = 'closure';
+            } elseif ($class = $r->getClosureScopeClass()) {
+                $this->name = $class->name;
+                $this->pretty = $this->name.'::'.$r->name;
+            } else {
+                $this->pretty = $this->name = $r->name;
+            }
+        } elseif (\is_string($listener)) {
+            $this->pretty = $this->name = $listener;
+        } else {
+            $this->name = \get_class($listener);
+            $this->pretty = $this->name.'::__invoke';
+        }
+
+        if (null !== $name) {
+            $this->name = $name;
+        }
+
+        if (null === self::$hasClassStub) {
+            self::$hasClassStub = class_exists(ClassStub::class);
+        }
     }
 
     public function getWrappedListener()
@@ -52,13 +84,35 @@ class WrappedListener
         return $this->stoppedPropagation;
     }
 
+    public function getPretty()
+    {
+        return $this->pretty;
+    }
+
+    public function getInfo($eventName)
+    {
+        if (null === $this->stub) {
+            $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()';
+        }
+
+        return [
+            'event' => $eventName,
+            'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null),
+            'pretty' => $this->pretty,
+            'stub' => $this->stub,
+        ];
+    }
+
     public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher)
     {
+        $dispatcher = $this->dispatcher ?: $dispatcher;
+
         $this->called = true;
+        $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener);
 
         $e = $this->stopwatch->start($this->name, 'event_listener');
 
-        \call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher);
+        \call_user_func($this->listener, $event, $eventName, $dispatcher);
 
         if ($e->isStarted()) {
             $e->stop();
diff --git a/civicrm/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/civicrm/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php
index 5a94ae82b3..2951c1ee45 100644
--- a/civicrm/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php
+++ b/civicrm/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php
@@ -11,8 +11,13 @@
 
 namespace Symfony\Component\EventDispatcher\DependencyInjection;
 
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Compiler pass to register tagged services for an event dispatcher.
@@ -23,6 +28,9 @@ class RegisterListenersPass implements CompilerPassInterface
     protected $listenerTag;
     protected $subscriberTag;
 
+    private $hotPathEvents = [];
+    private $hotPathTagName;
+
     /**
      * @param string $dispatcherService Service name of the event dispatcher in processed container
      * @param string $listenerTag       Tag name used for listener
@@ -35,6 +43,14 @@ class RegisterListenersPass implements CompilerPassInterface
         $this->subscriberTag = $subscriberTag;
     }
 
+    public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path')
+    {
+        $this->hotPathEvents = array_flip($hotPathEvents);
+        $this->hotPathTagName = $tagName;
+
+        return $this;
+    }
+
     public function process(ContainerBuilder $container)
     {
         if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) {
@@ -43,58 +59,79 @@ class RegisterListenersPass implements CompilerPassInterface
 
         $definition = $container->findDefinition($this->dispatcherService);
 
-        foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) {
-            $def = $container->getDefinition($id);
-            if (!$def->isPublic()) {
-                throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id));
-            }
-
-            if ($def->isAbstract()) {
-                throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id));
-            }
-
+        foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) {
             foreach ($events as $event) {
                 $priority = isset($event['priority']) ? $event['priority'] : 0;
 
                 if (!isset($event['event'])) {
-                    throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag));
+                    throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag));
                 }
 
                 if (!isset($event['method'])) {
-                    $event['method'] = 'on'.preg_replace_callback(array(
+                    $event['method'] = 'on'.preg_replace_callback([
                         '/(?<=\b)[a-z]/i',
                         '/[^a-z0-9]/i',
-                    ), function ($matches) { return strtoupper($matches[0]); }, $event['event']);
+                    ], function ($matches) { return strtoupper($matches[0]); }, $event['event']);
                     $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
                 }
 
-                $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority));
+                $definition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]);
+
+                if (isset($this->hotPathEvents[$event['event']])) {
+                    $container->getDefinition($id)->addTag($this->hotPathTagName);
+                }
             }
         }
 
-        foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) {
+        $extractingDispatcher = new ExtractingEventDispatcher();
+
+        foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $attributes) {
             $def = $container->getDefinition($id);
-            if (!$def->isPublic()) {
-                throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id));
-            }
 
-            if ($def->isAbstract()) {
-                throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event subscribers are lazy-loaded.', $id));
+            // We must assume that the class value has been correctly filled, even if the service is created by a factory
+            $class = $def->getClass();
+
+            if (!$r = $container->getReflectionClass($class)) {
+                throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
+            }
+            if (!$r->isSubclassOf(EventSubscriberInterface::class)) {
+                throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class));
             }
+            $class = $r->name;
 
-            // We must assume that the class value has been correctly filled, even if the service is created by a factory
-            $class = $container->getParameterBag()->resolveValue($def->getClass());
-            $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
+            ExtractingEventDispatcher::$subscriber = $class;
+            $extractingDispatcher->addSubscriber($extractingDispatcher);
+            foreach ($extractingDispatcher->listeners as $args) {
+                $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]];
+                $definition->addMethodCall('addListener', $args);
 
-            if (!is_subclass_of($class, $interface)) {
-                if (!class_exists($class, false)) {
-                    throw new \InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
+                if (isset($this->hotPathEvents[$args[0]])) {
+                    $container->getDefinition($id)->addTag($this->hotPathTagName);
                 }
-
-                throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
             }
-
-            $definition->addMethodCall('addSubscriberService', array($id, $class));
+            $extractingDispatcher->listeners = [];
         }
     }
 }
+
+/**
+ * @internal
+ */
+class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface
+{
+    public $listeners = [];
+
+    public static $subscriber;
+
+    public function addListener($eventName, $listener, $priority = 0)
+    {
+        $this->listeners[] = [$eventName, $listener[1], $priority];
+    }
+
+    public static function getSubscribedEvents()
+    {
+        $callback = [self::$subscriber, 'getSubscribedEvents'];
+
+        return $callback();
+    }
+}
diff --git a/civicrm/vendor/symfony/event-dispatcher/Event.php b/civicrm/vendor/symfony/event-dispatcher/Event.php
index 320919ae2f..9c56b2f55b 100644
--- a/civicrm/vendor/symfony/event-dispatcher/Event.php
+++ b/civicrm/vendor/symfony/event-dispatcher/Event.php
@@ -32,16 +32,6 @@ class Event
      */
     private $propagationStopped = false;
 
-    /**
-     * @var EventDispatcherInterface Dispatcher that dispatched this event
-     */
-    private $dispatcher;
-
-    /**
-     * @var string This event's name
-     */
-    private $name;
-
     /**
      * Returns whether further event listeners should be triggered.
      *
@@ -65,56 +55,4 @@ class Event
     {
         $this->propagationStopped = true;
     }
-
-    /**
-     * Stores the EventDispatcher that dispatches this Event.
-     *
-     * @param EventDispatcherInterface $dispatcher
-     *
-     * @deprecated since version 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
-     */
-    public function setDispatcher(EventDispatcherInterface $dispatcher)
-    {
-        $this->dispatcher = $dispatcher;
-    }
-
-    /**
-     * Returns the EventDispatcher that dispatches this Event.
-     *
-     * @return EventDispatcherInterface
-     *
-     * @deprecated since version 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
-     */
-    public function getDispatcher()
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.4 and will be removed in 3.0. The event dispatcher instance can be received in the listener call instead.', E_USER_DEPRECATED);
-
-        return $this->dispatcher;
-    }
-
-    /**
-     * Gets the event's name.
-     *
-     * @return string
-     *
-     * @deprecated since version 2.4, to be removed in 3.0. The event name is passed to the listener call.
-     */
-    public function getName()
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.4 and will be removed in 3.0. The event name can be received in the listener call instead.', E_USER_DEPRECATED);
-
-        return $this->name;
-    }
-
-    /**
-     * Sets the event's name property.
-     *
-     * @param string $name The event name
-     *
-     * @deprecated since version 2.4, to be removed in 3.0. The event name is passed to the listener call.
-     */
-    public function setName($name)
-    {
-        $this->name = $name;
-    }
 }
diff --git a/civicrm/vendor/symfony/event-dispatcher/EventDispatcher.php b/civicrm/vendor/symfony/event-dispatcher/EventDispatcher.php
index b41b98e554..207790f06b 100644
--- a/civicrm/vendor/symfony/event-dispatcher/EventDispatcher.php
+++ b/civicrm/vendor/symfony/event-dispatcher/EventDispatcher.php
@@ -24,11 +24,12 @@ namespace Symfony\Component\EventDispatcher;
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Jordi Boggiano <j.boggiano@seld.be>
  * @author Jordan Alliot <jordan.alliot@gmail.com>
+ * @author Nicolas Grekas <p@tchwork.com>
  */
 class EventDispatcher implements EventDispatcherInterface
 {
-    private $listeners = array();
-    private $sorted = array();
+    private $listeners = [];
+    private $sorted = [];
 
     /**
      * {@inheritdoc}
@@ -39,9 +40,6 @@ class EventDispatcher implements EventDispatcherInterface
             $event = new Event();
         }
 
-        $event->setDispatcher($this);
-        $event->setName($eventName);
-
         if ($listeners = $this->getListeners($eventName)) {
             $this->doDispatch($listeners, $eventName, $event);
         }
@@ -55,8 +53,8 @@ class EventDispatcher implements EventDispatcherInterface
     public function getListeners($eventName = null)
     {
         if (null !== $eventName) {
-            if (!isset($this->listeners[$eventName])) {
-                return array();
+            if (empty($this->listeners[$eventName])) {
+                return [];
             }
 
             if (!isset($this->sorted[$eventName])) {
@@ -76,26 +74,31 @@ class EventDispatcher implements EventDispatcherInterface
     }
 
     /**
-     * Gets the listener priority for a specific event.
-     *
-     * Returns null if the event or the listener does not exist.
-     *
-     * @param string   $eventName The name of the event
-     * @param callable $listener  The listener
-     *
-     * @return int|null The event listener priority
+     * {@inheritdoc}
      */
     public function getListenerPriority($eventName, $listener)
     {
-        if (!isset($this->listeners[$eventName])) {
-            return;
+        if (empty($this->listeners[$eventName])) {
+            return null;
+        }
+
+        if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
+            $listener[0] = $listener[0]();
         }
 
         foreach ($this->listeners[$eventName] as $priority => $listeners) {
-            if (false !== \in_array($listener, $listeners, true)) {
-                return $priority;
+            foreach ($listeners as $k => $v) {
+                if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
+                    $v[0] = $v[0]();
+                    $this->listeners[$eventName][$priority][$k] = $v;
+                }
+                if ($v === $listener) {
+                    return $priority;
+                }
             }
         }
+
+        return null;
     }
 
     /**
@@ -103,7 +106,17 @@ class EventDispatcher implements EventDispatcherInterface
      */
     public function hasListeners($eventName = null)
     {
-        return (bool) $this->getListeners($eventName);
+        if (null !== $eventName) {
+            return !empty($this->listeners[$eventName]);
+        }
+
+        foreach ($this->listeners as $eventListeners) {
+            if ($eventListeners) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     /**
@@ -120,13 +133,30 @@ class EventDispatcher implements EventDispatcherInterface
      */
     public function removeListener($eventName, $listener)
     {
-        if (!isset($this->listeners[$eventName])) {
+        if (empty($this->listeners[$eventName])) {
             return;
         }
 
+        if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
+            $listener[0] = $listener[0]();
+        }
+
         foreach ($this->listeners[$eventName] as $priority => $listeners) {
-            if (false !== ($key = array_search($listener, $listeners, true))) {
-                unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
+            foreach ($listeners as $k => $v) {
+                if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
+                    $v[0] = $v[0]();
+                }
+                if ($v === $listener) {
+                    unset($listeners[$k], $this->sorted[$eventName]);
+                } else {
+                    $listeners[$k] = $v;
+                }
+            }
+
+            if ($listeners) {
+                $this->listeners[$eventName][$priority] = $listeners;
+            } else {
+                unset($this->listeners[$eventName][$priority]);
             }
         }
     }
@@ -138,12 +168,12 @@ class EventDispatcher implements EventDispatcherInterface
     {
         foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
             if (\is_string($params)) {
-                $this->addListener($eventName, array($subscriber, $params));
+                $this->addListener($eventName, [$subscriber, $params]);
             } elseif (\is_string($params[0])) {
-                $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
+                $this->addListener($eventName, [$subscriber, $params[0]], isset($params[1]) ? $params[1] : 0);
             } else {
                 foreach ($params as $listener) {
-                    $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
+                    $this->addListener($eventName, [$subscriber, $listener[0]], isset($listener[1]) ? $listener[1] : 0);
                 }
             }
         }
@@ -157,10 +187,10 @@ class EventDispatcher implements EventDispatcherInterface
         foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
             if (\is_array($params) && \is_array($params[0])) {
                 foreach ($params as $listener) {
-                    $this->removeListener($eventName, array($subscriber, $listener[0]));
+                    $this->removeListener($eventName, [$subscriber, $listener[0]]);
                 }
             } else {
-                $this->removeListener($eventName, array($subscriber, \is_string($params) ? $params : $params[0]));
+                $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]);
             }
         }
     }
@@ -193,6 +223,16 @@ class EventDispatcher implements EventDispatcherInterface
     private function sortListeners($eventName)
     {
         krsort($this->listeners[$eventName]);
-        $this->sorted[$eventName] = \call_user_func_array('array_merge', $this->listeners[$eventName]);
+        $this->sorted[$eventName] = [];
+
+        foreach ($this->listeners[$eventName] as $priority => $listeners) {
+            foreach ($listeners as $k => $listener) {
+                if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
+                    $listener[0] = $listener[0]();
+                    $this->listeners[$eventName][$priority][$k] = $listener;
+                }
+                $this->sorted[$eventName][] = $listener;
+            }
+        }
     }
 }
diff --git a/civicrm/vendor/symfony/event-dispatcher/EventDispatcherInterface.php b/civicrm/vendor/symfony/event-dispatcher/EventDispatcherInterface.php
index 60160a90e0..bde753a12f 100644
--- a/civicrm/vendor/symfony/event-dispatcher/EventDispatcherInterface.php
+++ b/civicrm/vendor/symfony/event-dispatcher/EventDispatcherInterface.php
@@ -23,11 +23,11 @@ interface EventDispatcherInterface
     /**
      * Dispatches an event to all registered listeners.
      *
-     * @param string $eventName The name of the event to dispatch. The name of
-     *                          the event is the name of the method that is
-     *                          invoked on listeners.
-     * @param Event  $event     The event to pass to the event handlers/listeners
-     *                          If not supplied, an empty Event instance is created
+     * @param string     $eventName The name of the event to dispatch. The name of
+     *                              the event is the name of the method that is
+     *                              invoked on listeners.
+     * @param Event|null $event     The event to pass to the event handlers/listeners
+     *                              If not supplied, an empty Event instance is created
      *
      * @return Event
      */
@@ -46,7 +46,7 @@ interface EventDispatcherInterface
     /**
      * Adds an event subscriber.
      *
-     * The subscriber is asked for all the events he is
+     * The subscriber is asked for all the events it is
      * interested in and added as a listener for these events.
      */
     public function addSubscriber(EventSubscriberInterface $subscriber);
@@ -64,16 +64,28 @@ interface EventDispatcherInterface
     /**
      * Gets the listeners of a specific event or all listeners sorted by descending priority.
      *
-     * @param string $eventName The name of the event
+     * @param string|null $eventName The name of the event
      *
      * @return array The event listeners for the specified event, or all event listeners by event name
      */
     public function getListeners($eventName = null);
 
+    /**
+     * Gets the listener priority for a specific event.
+     *
+     * Returns null if the event or the listener does not exist.
+     *
+     * @param string   $eventName The name of the event
+     * @param callable $listener  The listener
+     *
+     * @return int|null The event listener priority
+     */
+    public function getListenerPriority($eventName, $listener);
+
     /**
      * Checks whether an event has any registered listeners.
      *
-     * @param string $eventName The name of the event
+     * @param string|null $eventName The name of the event
      *
      * @return bool true if the specified event has any listeners, false otherwise
      */
diff --git a/civicrm/vendor/symfony/event-dispatcher/EventSubscriberInterface.php b/civicrm/vendor/symfony/event-dispatcher/EventSubscriberInterface.php
index 8af778919b..824f21599c 100644
--- a/civicrm/vendor/symfony/event-dispatcher/EventSubscriberInterface.php
+++ b/civicrm/vendor/symfony/event-dispatcher/EventSubscriberInterface.php
@@ -12,7 +12,7 @@
 namespace Symfony\Component\EventDispatcher;
 
 /**
- * An EventSubscriber knows himself what events he is interested in.
+ * An EventSubscriber knows itself what events it is interested in.
  * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes
  * {@link getSubscribedEvents} and registers the subscriber as a listener for all
  * returned events.
@@ -36,9 +36,9 @@ interface EventSubscriberInterface
      *
      * For instance:
      *
-     *  * array('eventName' => 'methodName')
-     *  * array('eventName' => array('methodName', $priority))
-     *  * array('eventName' => array(array('methodName1', $priority), array('methodName2')))
+     *  * ['eventName' => 'methodName']
+     *  * ['eventName' => ['methodName', $priority]]
+     *  * ['eventName' => [['methodName1', $priority], ['methodName2']]]
      *
      * @return array The event names to listen to
      */
diff --git a/civicrm/vendor/symfony/event-dispatcher/GenericEvent.php b/civicrm/vendor/symfony/event-dispatcher/GenericEvent.php
index f0be7e18ff..f005e3a3db 100644
--- a/civicrm/vendor/symfony/event-dispatcher/GenericEvent.php
+++ b/civicrm/vendor/symfony/event-dispatcher/GenericEvent.php
@@ -29,7 +29,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
      * @param mixed $subject   The subject of the event, usually an object or a callable
      * @param array $arguments Arguments to store in the event
      */
-    public function __construct($subject = null, array $arguments = array())
+    public function __construct($subject = null, array $arguments = [])
     {
         $this->subject = $subject;
         $this->arguments = $arguments;
@@ -95,7 +95,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
      *
      * @return $this
      */
-    public function setArguments(array $args = array())
+    public function setArguments(array $args = [])
     {
         $this->arguments = $args;
 
@@ -111,7 +111,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
      */
     public function hasArgument($key)
     {
-        return array_key_exists($key, $this->arguments);
+        return \array_key_exists($key, $this->arguments);
     }
 
     /**
diff --git a/civicrm/vendor/symfony/event-dispatcher/LICENSE b/civicrm/vendor/symfony/event-dispatcher/LICENSE
index 21d7fb9e2f..9e936ec044 100644
--- a/civicrm/vendor/symfony/event-dispatcher/LICENSE
+++ b/civicrm/vendor/symfony/event-dispatcher/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2018 Fabien Potencier
+Copyright (c) 2004-2020 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/civicrm/vendor/symfony/event-dispatcher/README.md b/civicrm/vendor/symfony/event-dispatcher/README.md
index 185c3fecf8..e0d38eed01 100644
--- a/civicrm/vendor/symfony/event-dispatcher/README.md
+++ b/civicrm/vendor/symfony/event-dispatcher/README.md
@@ -8,7 +8,7 @@ them.
 Resources
 ---------
 
-  * [Documentation](https://symfony.com/doc/current/components/event_dispatcher/index.html)
+  * [Documentation](https://symfony.com/doc/current/components/event_dispatcher.html)
   * [Contributing](https://symfony.com/doc/current/contributing/index.html)
   * [Report issues](https://github.com/symfony/symfony/issues) and
     [send Pull Requests](https://github.com/symfony/symfony/pulls)
diff --git a/civicrm/vendor/symfony/event-dispatcher/composer.json b/civicrm/vendor/symfony/event-dispatcher/composer.json
index 14fc24ba22..75b881b917 100644
--- a/civicrm/vendor/symfony/event-dispatcher/composer.json
+++ b/civicrm/vendor/symfony/event-dispatcher/composer.json
@@ -16,15 +16,18 @@
         }
     ],
     "require": {
-        "php": ">=5.3.9"
+        "php": "^5.5.9|>=7.0.8"
     },
     "require-dev": {
-        "symfony/dependency-injection": "~2.6|~3.0.0",
-        "symfony/expression-language": "~2.6|~3.0.0",
-        "symfony/config": "^2.0.5|~3.0.0",
-        "symfony/stopwatch": "~2.3|~3.0.0",
+        "symfony/dependency-injection": "~3.3|~4.0",
+        "symfony/expression-language": "~2.8|~3.0|~4.0",
+        "symfony/config": "~2.8|~3.0|~4.0",
+        "symfony/stopwatch": "~2.8|~3.0|~4.0",
         "psr/log": "~1.0"
     },
+    "conflict": {
+        "symfony/dependency-injection": "<3.3"
+    },
     "suggest": {
         "symfony/dependency-injection": "",
         "symfony/http-kernel": ""
@@ -38,7 +41,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "2.8-dev"
+            "dev-master": "3.4-dev"
         }
     }
 }
diff --git a/civicrm/vendor/symfony/filesystem/CHANGELOG.md b/civicrm/vendor/symfony/filesystem/CHANGELOG.md
index aee6e804b0..d01f5f45e1 100644
--- a/civicrm/vendor/symfony/filesystem/CHANGELOG.md
+++ b/civicrm/vendor/symfony/filesystem/CHANGELOG.md
@@ -1,6 +1,26 @@
 CHANGELOG
 =========
 
+3.4.0
+-----
+
+ * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0
+
+3.3.0
+-----
+
+ * added `appendToFile()` to append contents to existing files
+
+3.2.0
+-----
+
+ * added `readlink()` as a platform independent method to read links
+
+3.0.0
+-----
+
+ * removed `$mode` argument from `Filesystem::dumpFile()`
+
 2.8.0
 -----
 
diff --git a/civicrm/vendor/symfony/filesystem/Exception/IOExceptionInterface.php b/civicrm/vendor/symfony/filesystem/Exception/IOExceptionInterface.php
index c11965a424..f9d4644a87 100644
--- a/civicrm/vendor/symfony/filesystem/Exception/IOExceptionInterface.php
+++ b/civicrm/vendor/symfony/filesystem/Exception/IOExceptionInterface.php
@@ -21,7 +21,7 @@ interface IOExceptionInterface extends ExceptionInterface
     /**
      * Returns the associated path for the exception.
      *
-     * @return string The path
+     * @return string|null The path
      */
     public function getPath();
 }
diff --git a/civicrm/vendor/symfony/filesystem/Filesystem.php b/civicrm/vendor/symfony/filesystem/Filesystem.php
index df31620561..a8701533cb 100644
--- a/civicrm/vendor/symfony/filesystem/Filesystem.php
+++ b/civicrm/vendor/symfony/filesystem/Filesystem.php
@@ -52,13 +52,13 @@ class Filesystem
         }
 
         if ($doCopy) {
-            // https://bugs.php.net/bug.php?id=64634
+            // https://bugs.php.net/64634
             if (false === $source = @fopen($originFile, 'r')) {
                 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
             }
 
             // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default
-            if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
+            if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(['ftp' => ['overwrite' => true]]))) {
                 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
             }
 
@@ -92,7 +92,7 @@ class Filesystem
      */
     public function mkdir($dirs, $mode = 0777)
     {
-        foreach ($this->toIterator($dirs) as $dir) {
+        foreach ($this->toIterable($dirs) as $dir) {
             if (is_dir($dir)) {
                 continue;
             }
@@ -101,9 +101,9 @@ class Filesystem
                 if (!is_dir($dir)) {
                     // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
                     if (self::$lastError) {
-                        throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
+                        throw new IOException(sprintf('Failed to create "%s": '.self::$lastError, $dir), 0, null, $dir);
                     }
-                    throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
+                    throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir);
                 }
             }
         }
@@ -120,7 +120,7 @@ class Filesystem
     {
         $maxPathLength = PHP_MAXPATHLEN - 2;
 
-        foreach ($this->toIterator($files) as $file) {
+        foreach ($this->toIterable($files) as $file) {
             if (\strlen($file) > $maxPathLength) {
                 throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file);
             }
@@ -137,14 +137,14 @@ class Filesystem
      * Sets access and modification time of file.
      *
      * @param string|iterable $files A filename, an array of files, or a \Traversable instance to create
-     * @param int             $time  The touch time as a Unix timestamp
-     * @param int             $atime The access time as a Unix timestamp
+     * @param int|null        $time  The touch time as a Unix timestamp, if not supplied the current system time is used
+     * @param int|null        $atime The access time as a Unix timestamp, if not supplied the current system time is used
      *
      * @throws IOException When touch fails
      */
     public function touch($files, $time = null, $atime = null)
     {
-        foreach ($this->toIterator($files) as $file) {
+        foreach ($this->toIterable($files) as $file) {
             $touch = $time ? @touch($file, $time, $atime) : @touch($file);
             if (true !== $touch) {
                 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
@@ -164,23 +164,23 @@ class Filesystem
         if ($files instanceof \Traversable) {
             $files = iterator_to_array($files, false);
         } elseif (!\is_array($files)) {
-            $files = array($files);
+            $files = [$files];
         }
         $files = array_reverse($files);
         foreach ($files as $file) {
             if (is_link($file)) {
                 // See https://bugs.php.net/52176
                 if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
-                    throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
+                    throw new IOException(sprintf('Failed to remove symlink "%s": '.self::$lastError, $file));
                 }
             } elseif (is_dir($file)) {
                 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
 
                 if (!self::box('rmdir', $file) && file_exists($file)) {
-                    throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
+                    throw new IOException(sprintf('Failed to remove directory "%s": '.self::$lastError, $file));
                 }
             } elseif (!self::box('unlink', $file) && file_exists($file)) {
-                throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
+                throw new IOException(sprintf('Failed to remove file "%s": '.self::$lastError, $file));
             }
         }
     }
@@ -193,11 +193,11 @@ class Filesystem
      * @param int             $umask     The mode mask (octal)
      * @param bool            $recursive Whether change the mod recursively or not
      *
-     * @throws IOException When the change fail
+     * @throws IOException When the change fails
      */
     public function chmod($files, $mode, $umask = 0000, $recursive = false)
     {
-        foreach ($this->toIterator($files) as $file) {
+        foreach ($this->toIterable($files) as $file) {
             if (true !== @chmod($file, $mode & ~$umask)) {
                 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
             }
@@ -211,14 +211,14 @@ class Filesystem
      * Change the owner of an array of files or directories.
      *
      * @param string|iterable $files     A filename, an array of files, or a \Traversable instance to change owner
-     * @param string          $user      The new owner user name
+     * @param string|int      $user      A user name or number
      * @param bool            $recursive Whether change the owner recursively or not
      *
-     * @throws IOException When the change fail
+     * @throws IOException When the change fails
      */
     public function chown($files, $user, $recursive = false)
     {
-        foreach ($this->toIterator($files) as $file) {
+        foreach ($this->toIterable($files) as $file) {
             if ($recursive && is_dir($file) && !is_link($file)) {
                 $this->chown(new \FilesystemIterator($file), $user, true);
             }
@@ -238,14 +238,14 @@ class Filesystem
      * Change the group of an array of files or directories.
      *
      * @param string|iterable $files     A filename, an array of files, or a \Traversable instance to change group
-     * @param string          $group     The group name
+     * @param string|int      $group     A group name or number
      * @param bool            $recursive Whether change the group recursively or not
      *
-     * @throws IOException When the change fail
+     * @throws IOException When the change fails
      */
     public function chgrp($files, $group, $recursive = false)
     {
-        foreach ($this->toIterator($files) as $file) {
+        foreach ($this->toIterable($files) as $file) {
             if ($recursive && is_dir($file) && !is_link($file)) {
                 $this->chgrp(new \FilesystemIterator($file), $group, true);
             }
@@ -280,8 +280,8 @@ class Filesystem
 
         if (true !== @rename($origin, $target)) {
             if (is_dir($origin)) {
-                // See https://bugs.php.net/bug.php?id=54097 & http://php.net/manual/en/function.rename.php#113943
-                $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
+                // See https://bugs.php.net/54097 & https://php.net/rename#113943
+                $this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]);
                 $this->remove($origin);
 
                 return;
@@ -342,13 +342,97 @@ class Filesystem
         }
 
         if (!self::box('symlink', $originDir, $targetDir)) {
-            if (null !== self::$lastError) {
-                if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
-                    throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', 0, null, $targetDir);
+            $this->linkException($originDir, $targetDir, 'symbolic');
+        }
+    }
+
+    /**
+     * Creates a hard link, or several hard links to a file.
+     *
+     * @param string          $originFile  The original file
+     * @param string|string[] $targetFiles The target file(s)
+     *
+     * @throws FileNotFoundException When original file is missing or not a file
+     * @throws IOException           When link fails, including if link already exists
+     */
+    public function hardlink($originFile, $targetFiles)
+    {
+        if (!$this->exists($originFile)) {
+            throw new FileNotFoundException(null, 0, null, $originFile);
+        }
+
+        if (!is_file($originFile)) {
+            throw new FileNotFoundException(sprintf('Origin file "%s" is not a file.', $originFile));
+        }
+
+        foreach ($this->toIterable($targetFiles) as $targetFile) {
+            if (is_file($targetFile)) {
+                if (fileinode($originFile) === fileinode($targetFile)) {
+                    continue;
                 }
+                $this->remove($targetFile);
+            }
+
+            if (!self::box('link', $originFile, $targetFile)) {
+                $this->linkException($originFile, $targetFile, 'hard');
+            }
+        }
+    }
+
+    /**
+     * @param string $origin
+     * @param string $target
+     * @param string $linkType Name of the link type, typically 'symbolic' or 'hard'
+     */
+    private function linkException($origin, $target, $linkType)
+    {
+        if (self::$lastError) {
+            if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
+                throw new IOException(sprintf('Unable to create "%s" link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target);
+            }
+        }
+        throw new IOException(sprintf('Failed to create "%s" link from "%s" to "%s".', $linkType, $origin, $target), 0, null, $target);
+    }
+
+    /**
+     * Resolves links in paths.
+     *
+     * With $canonicalize = false (default)
+     *      - if $path does not exist or is not a link, returns null
+     *      - if $path is a link, returns the next direct target of the link without considering the existence of the target
+     *
+     * With $canonicalize = true
+     *      - if $path does not exist, returns null
+     *      - if $path exists, returns its absolute fully resolved final version
+     *
+     * @param string $path         A filesystem path
+     * @param bool   $canonicalize Whether or not to return a canonicalized path
+     *
+     * @return string|null
+     */
+    public function readlink($path, $canonicalize = false)
+    {
+        if (!$canonicalize && !is_link($path)) {
+            return null;
+        }
+
+        if ($canonicalize) {
+            if (!$this->exists($path)) {
+                return null;
             }
-            throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
+
+            if ('\\' === \DIRECTORY_SEPARATOR) {
+                $path = readlink($path);
+            }
+
+            return realpath($path);
         }
+
+        if ('\\' === \DIRECTORY_SEPARATOR) {
+            return realpath($path);
+        }
+
+        return readlink($path);
     }
 
     /**
@@ -361,6 +445,10 @@ class Filesystem
      */
     public function makePathRelative($endPath, $startPath)
     {
+        if (!$this->isAbsolutePath($endPath) || !$this->isAbsolutePath($startPath)) {
+            @trigger_error(sprintf('Support for passing relative paths to %s() is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
+        }
+
         // Normalize separators on Windows
         if ('\\' === \DIRECTORY_SEPARATOR) {
             $endPath = str_replace('\\', '/', $endPath);
@@ -383,7 +471,7 @@ class Filesystem
         $endPathArr = explode('/', trim($endPath, '/'));
 
         $normalizePathArray = function ($pathSegments, $absolute) {
-            $result = array();
+            $result = [];
 
             foreach ($pathSegments as $segment) {
                 if ('..' === $segment && ($absolute || \count($result))) {
@@ -431,18 +519,18 @@ class Filesystem
      *  - existing files in the target directory will be overwritten, except if they are newer (see the `override` option)
      *  - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option)
      *
-     * @param string       $originDir The origin directory
-     * @param string       $targetDir The target directory
-     * @param \Traversable $iterator  Iterator that filters which files and directories to copy
-     * @param array        $options   An array of boolean options
-     *                                Valid options are:
-     *                                - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false)
-     *                                - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false)
-     *                                - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
+     * @param string            $originDir The origin directory
+     * @param string            $targetDir The target directory
+     * @param \Traversable|null $iterator  Iterator that filters which files and directories to copy, if null a recursive iterator is created
+     * @param array             $options   An array of boolean options
+     *                                     Valid options are:
+     *                                     - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false)
+     *                                     - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false)
+     *                                     - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
      *
      * @throws IOException When file type is unknown
      */
-    public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
+    public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = [])
     {
         $targetDir = rtrim($targetDir, '/\\');
         $originDir = rtrim($originDir, '/\\');
@@ -514,7 +602,7 @@ class Filesystem
     {
         return strspn($file, '/\\', 0, 1)
             || (\strlen($file) > 3 && ctype_alpha($file[0])
-                && ':' === substr($file, 1, 1)
+                && ':' === $file[1]
                 && strspn($file, '/\\', 2, 1)
             )
             || null !== parse_url($file, PHP_URL_SCHEME)
@@ -576,14 +664,12 @@ class Filesystem
     /**
      * Atomically dumps content into a file.
      *
-     * @param string   $filename The file to be written to
-     * @param string   $content  The data to write into the file
-     * @param int|null $mode     The file mode (octal). If null, file permissions are not modified
-     *                           Deprecated since version 2.3.12, to be removed in 3.0.
+     * @param string $filename The file to be written to
+     * @param string $content  The data to write into the file
      *
      * @throws IOException if the file cannot be written to
      */
-    public function dumpFile($filename, $content, $mode = 0666)
+    public function dumpFile($filename, $content)
     {
         $dir = \dirname($filename);
 
@@ -595,41 +681,56 @@ class Filesystem
             throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
         }
 
+        // Will create a temp file with 0600 access rights
+        // when the filesystem supports chmod.
         $tmpFile = $this->tempnam($dir, basename($filename));
 
         if (false === @file_put_contents($tmpFile, $content)) {
             throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
         }
 
-        if (null !== $mode) {
-            if (\func_num_args() > 2) {
-                @trigger_error('Support for modifying file permissions is deprecated since Symfony 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
-            }
-
-            $this->chmod($tmpFile, $mode);
-        } elseif (file_exists($filename)) {
-            @chmod($tmpFile, fileperms($filename));
-        }
+        @chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask());
 
         $this->rename($tmpFile, $filename, true);
     }
 
     /**
-     * @param mixed $files
+     * Appends content to an existing file.
      *
-     * @return \Traversable
+     * @param string $filename The file to which to append content
+     * @param string $content  The content to append
+     *
+     * @throws IOException If the file is not writable
      */
-    private function toIterator($files)
+    public function appendToFile($filename, $content)
     {
-        if (!$files instanceof \Traversable) {
-            $files = new \ArrayObject(\is_array($files) ? $files : array($files));
+        $dir = \dirname($filename);
+
+        if (!is_dir($dir)) {
+            $this->mkdir($dir);
+        }
+
+        if (!is_writable($dir)) {
+            throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
         }
 
-        return $files;
+        if (false === @file_put_contents($filename, $content, FILE_APPEND)) {
+            throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
+        }
     }
 
     /**
-     * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> array(file, tmp)).
+     * @param mixed $files
+     *
+     * @return array|\Traversable
+     */
+    private function toIterable($files)
+    {
+        return \is_array($files) || $files instanceof \Traversable ? $files : [$files];
+    }
+
+    /**
+     * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> [file, tmp]).
      *
      * @param string $filename The filename to be parsed
      *
@@ -639,22 +740,27 @@ class Filesystem
     {
         $components = explode('://', $filename, 2);
 
-        return 2 === \count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
+        return 2 === \count($components) ? [$components[0], $components[1]] : [null, $components[0]];
     }
 
+    /**
+     * @param callable $func
+     *
+     * @return mixed
+     */
     private static function box($func)
     {
         self::$lastError = null;
-        \set_error_handler(__CLASS__.'::handleError');
+        set_error_handler(__CLASS__.'::handleError');
         try {
             $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
-            \restore_error_handler();
+            restore_error_handler();
 
             return $result;
         } catch (\Throwable $e) {
         } catch (\Exception $e) {
         }
-        \restore_error_handler();
+        restore_error_handler();
 
         throw $e;
     }
diff --git a/civicrm/vendor/symfony/filesystem/LICENSE b/civicrm/vendor/symfony/filesystem/LICENSE
index 21d7fb9e2f..9e936ec044 100644
--- a/civicrm/vendor/symfony/filesystem/LICENSE
+++ b/civicrm/vendor/symfony/filesystem/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2018 Fabien Potencier
+Copyright (c) 2004-2020 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/civicrm/vendor/symfony/filesystem/LockHandler.php b/civicrm/vendor/symfony/filesystem/LockHandler.php
index 6d85c51b8c..8e0eb74121 100644
--- a/civicrm/vendor/symfony/filesystem/LockHandler.php
+++ b/civicrm/vendor/symfony/filesystem/LockHandler.php
@@ -12,6 +12,10 @@
 namespace Symfony\Component\Filesystem;
 
 use Symfony\Component\Filesystem\Exception\IOException;
+use Symfony\Component\Lock\Store\FlockStore;
+use Symfony\Component\Lock\Store\SemaphoreStore;
+
+@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Use %s or %s instead.', LockHandler::class, SemaphoreStore::class, FlockStore::class), E_USER_DEPRECATED);
 
 /**
  * LockHandler class provides a simple abstraction to lock anything by means of
@@ -25,6 +29,8 @@ use Symfony\Component\Filesystem\Exception\IOException;
  * @author Grégoire Pineau <lyrixx@lyrixx.info>
  * @author Romain Neutron <imprec@gmail.com>
  * @author Nicolas Grekas <p@tchwork.com>
+ *
+ * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\Lock\Store\SemaphoreStore or Symfony\Component\Lock\Store\FlockStore instead.
  */
 class LockHandler
 {
diff --git a/civicrm/vendor/symfony/filesystem/README.md b/civicrm/vendor/symfony/filesystem/README.md
index 877ab3543f..cb03d43c15 100644
--- a/civicrm/vendor/symfony/filesystem/README.md
+++ b/civicrm/vendor/symfony/filesystem/README.md
@@ -6,7 +6,7 @@ The Filesystem component provides basic utilities for the filesystem.
 Resources
 ---------
 
-  * [Documentation](https://symfony.com/doc/current/components/filesystem/index.html)
+  * [Documentation](https://symfony.com/doc/current/components/filesystem.html)
   * [Contributing](https://symfony.com/doc/current/contributing/index.html)
   * [Report issues](https://github.com/symfony/symfony/issues) and
     [send Pull Requests](https://github.com/symfony/symfony/pulls)
diff --git a/civicrm/vendor/symfony/filesystem/composer.json b/civicrm/vendor/symfony/filesystem/composer.json
index 3a2db520b6..0fc8043cc0 100644
--- a/civicrm/vendor/symfony/filesystem/composer.json
+++ b/civicrm/vendor/symfony/filesystem/composer.json
@@ -16,7 +16,7 @@
         }
     ],
     "require": {
-        "php": ">=5.3.9",
+        "php": "^5.5.9|>=7.0.8",
         "symfony/polyfill-ctype": "~1.8"
     },
     "autoload": {
@@ -28,7 +28,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "2.8-dev"
+            "dev-master": "3.4-dev"
         }
     }
 }
diff --git a/civicrm/vendor/symfony/finder/Adapter/AbstractAdapter.php b/civicrm/vendor/symfony/finder/Adapter/AbstractAdapter.php
deleted file mode 100644
index 1a1647c317..0000000000
--- a/civicrm/vendor/symfony/finder/Adapter/AbstractAdapter.php
+++ /dev/null
@@ -1,240 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Adapter;
-
-@trigger_error('The '.__NAMESPACE__.'\AbstractAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
-
-/**
- * Interface for finder engine implementations.
- *
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0. Use Finder instead.
- */
-abstract class AbstractAdapter implements AdapterInterface
-{
-    protected $followLinks = false;
-    protected $mode = 0;
-    protected $minDepth = 0;
-    protected $maxDepth = PHP_INT_MAX;
-    protected $exclude = array();
-    protected $names = array();
-    protected $notNames = array();
-    protected $contains = array();
-    protected $notContains = array();
-    protected $sizes = array();
-    protected $dates = array();
-    protected $filters = array();
-    protected $sort = false;
-    protected $paths = array();
-    protected $notPaths = array();
-    protected $ignoreUnreadableDirs = false;
-
-    private static $areSupported = array();
-
-    /**
-     * {@inheritdoc}
-     */
-    public function isSupported()
-    {
-        $name = $this->getName();
-
-        if (!array_key_exists($name, self::$areSupported)) {
-            self::$areSupported[$name] = $this->canBeUsed();
-        }
-
-        return self::$areSupported[$name];
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setFollowLinks($followLinks)
-    {
-        $this->followLinks = $followLinks;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setMode($mode)
-    {
-        $this->mode = $mode;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setDepths(array $depths)
-    {
-        $this->minDepth = 0;
-        $this->maxDepth = PHP_INT_MAX;
-
-        foreach ($depths as $comparator) {
-            switch ($comparator->getOperator()) {
-                case '>':
-                    $this->minDepth = $comparator->getTarget() + 1;
-                    break;
-                case '>=':
-                    $this->minDepth = $comparator->getTarget();
-                    break;
-                case '<':
-                    $this->maxDepth = $comparator->getTarget() - 1;
-                    break;
-                case '<=':
-                    $this->maxDepth = $comparator->getTarget();
-                    break;
-                default:
-                    $this->minDepth = $this->maxDepth = $comparator->getTarget();
-            }
-        }
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setExclude(array $exclude)
-    {
-        $this->exclude = $exclude;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setNames(array $names)
-    {
-        $this->names = $names;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setNotNames(array $notNames)
-    {
-        $this->notNames = $notNames;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setContains(array $contains)
-    {
-        $this->contains = $contains;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setNotContains(array $notContains)
-    {
-        $this->notContains = $notContains;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setSizes(array $sizes)
-    {
-        $this->sizes = $sizes;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setDates(array $dates)
-    {
-        $this->dates = $dates;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setFilters(array $filters)
-    {
-        $this->filters = $filters;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setSort($sort)
-    {
-        $this->sort = $sort;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setPath(array $paths)
-    {
-        $this->paths = $paths;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setNotPath(array $notPaths)
-    {
-        $this->notPaths = $notPaths;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function ignoreUnreadableDirs($ignore = true)
-    {
-        $this->ignoreUnreadableDirs = (bool) $ignore;
-
-        return $this;
-    }
-
-    /**
-     * Returns whether the adapter is supported in the current environment.
-     *
-     * This method should be implemented in all adapters. Do not implement
-     * isSupported in the adapters as the generic implementation provides a cache
-     * layer.
-     *
-     * @see isSupported()
-     *
-     * @return bool Whether the adapter is supported
-     */
-    abstract protected function canBeUsed();
-}
diff --git a/civicrm/vendor/symfony/finder/Adapter/AbstractFindAdapter.php b/civicrm/vendor/symfony/finder/Adapter/AbstractFindAdapter.php
deleted file mode 100644
index ef458695b5..0000000000
--- a/civicrm/vendor/symfony/finder/Adapter/AbstractFindAdapter.php
+++ /dev/null
@@ -1,325 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Adapter;
-
-@trigger_error('The '.__NAMESPACE__.'\AbstractFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\Comparator\DateComparator;
-use Symfony\Component\Finder\Comparator\NumberComparator;
-use Symfony\Component\Finder\Exception\AccessDeniedException;
-use Symfony\Component\Finder\Expression\Expression;
-use Symfony\Component\Finder\Iterator;
-use Symfony\Component\Finder\Shell\Command;
-use Symfony\Component\Finder\Shell\Shell;
-
-/**
- * Shell engine implementation using GNU find command.
- *
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0. Use Finder instead.
- */
-abstract class AbstractFindAdapter extends AbstractAdapter
-{
-    protected $shell;
-
-    public function __construct()
-    {
-        $this->shell = new Shell();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function searchInDirectory($dir)
-    {
-        // having "/../" in path make find fail
-        $dir = realpath($dir);
-
-        // searching directories containing or not containing strings leads to no result
-        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
-            return new Iterator\FilePathsIterator(array(), $dir);
-        }
-
-        $command = Command::create();
-        $find = $this->buildFindCommand($command, $dir);
-
-        if ($this->followLinks) {
-            $find->add('-follow');
-        }
-
-        $find->add('-mindepth')->add($this->minDepth + 1);
-
-        if (PHP_INT_MAX !== $this->maxDepth) {
-            $find->add('-maxdepth')->add($this->maxDepth + 1);
-        }
-
-        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
-            $find->add('-type d');
-        } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
-            $find->add('-type f');
-        }
-
-        $this->buildNamesFiltering($find, $this->names);
-        $this->buildNamesFiltering($find, $this->notNames, true);
-        $this->buildPathsFiltering($find, $dir, $this->paths);
-        $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
-        $this->buildSizesFiltering($find, $this->sizes);
-        $this->buildDatesFiltering($find, $this->dates);
-
-        $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
-        $useSort = \is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
-
-        if ($useGrep && ($this->contains || $this->notContains)) {
-            $grep = $command->ins('grep');
-            $this->buildContentFiltering($grep, $this->contains);
-            $this->buildContentFiltering($grep, $this->notContains, true);
-        }
-
-        if ($useSort) {
-            $this->buildSorting($command, $this->sort);
-        }
-
-        $command->setErrorHandler(
-            $this->ignoreUnreadableDirs
-                // If directory is unreadable and finder is set to ignore it, `stderr` is ignored.
-                ? function ($stderr) { }
-                : function ($stderr) { throw new AccessDeniedException($stderr); }
-        );
-
-        $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
-        $iterator = new Iterator\FilePathsIterator($paths, $dir);
-
-        if ($this->exclude) {
-            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
-        }
-
-        if (!$useGrep && ($this->contains || $this->notContains)) {
-            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
-        }
-
-        if ($this->filters) {
-            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
-        }
-
-        if (!$useSort && $this->sort) {
-            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
-            $iterator = $iteratorAggregate->getIterator();
-        }
-
-        return $iterator;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function canBeUsed()
-    {
-        return $this->shell->testCommand('find');
-    }
-
-    /**
-     * @param Command $command
-     * @param string  $dir
-     *
-     * @return Command
-     */
-    protected function buildFindCommand(Command $command, $dir)
-    {
-        return $command
-            ->ins('find')
-            ->add('find ')
-            ->arg($dir)
-            ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions
-    }
-
-    /**
-     * @param Command  $command
-     * @param string[] $names
-     * @param bool     $not
-     */
-    private function buildNamesFiltering(Command $command, array $names, $not = false)
-    {
-        if (0 === \count($names)) {
-            return;
-        }
-
-        $command->add($not ? '-not' : null)->cmd('(');
-
-        foreach ($names as $i => $name) {
-            $expr = Expression::create($name);
-
-            // Find does not support expandable globs ("*.{a,b}" syntax).
-            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
-                $expr = Expression::create($expr->getGlob()->toRegex(false));
-            }
-
-            // Fixes 'not search' and 'full path matching' regex problems.
-            // - Jokers '.' are replaced by [^/].
-            // - We add '[^/]*' before and after regex (if no ^|$ flags are present).
-            if ($expr->isRegex()) {
-                $regex = $expr->getRegex();
-                $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
-                    ->setStartFlag(false)
-                    ->setStartJoker(true)
-                    ->replaceJokers('[^/]');
-                if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
-                    $regex->setEndJoker(false)->append('[^/]*');
-                }
-            }
-
-            $command
-                ->add($i > 0 ? '-or' : null)
-                ->add($expr->isRegex()
-                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
-                    : ($expr->isCaseSensitive() ? '-name' : '-iname')
-                )
-                ->arg($expr->renderPattern());
-        }
-
-        $command->cmd(')');
-    }
-
-    /**
-     * @param Command  $command
-     * @param string   $dir
-     * @param string[] $paths
-     * @param bool     $not
-     */
-    private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
-    {
-        if (0 === \count($paths)) {
-            return;
-        }
-
-        $command->add($not ? '-not' : null)->cmd('(');
-
-        foreach ($paths as $i => $path) {
-            $expr = Expression::create($path);
-
-            // Find does not support expandable globs ("*.{a,b}" syntax).
-            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
-                $expr = Expression::create($expr->getGlob()->toRegex(false));
-            }
-
-            // Fixes 'not search' regex problems.
-            if ($expr->isRegex()) {
-                $regex = $expr->getRegex();
-                $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).\DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
-            } else {
-                $expr->prepend('*')->append('*');
-            }
-
-            $command
-                ->add($i > 0 ? '-or' : null)
-                ->add($expr->isRegex()
-                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
-                    : ($expr->isCaseSensitive() ? '-path' : '-ipath')
-                )
-                ->arg($expr->renderPattern());
-        }
-
-        $command->cmd(')');
-    }
-
-    /**
-     * @param Command            $command
-     * @param NumberComparator[] $sizes
-     */
-    private function buildSizesFiltering(Command $command, array $sizes)
-    {
-        foreach ($sizes as $i => $size) {
-            $command->add($i > 0 ? '-and' : null);
-
-            switch ($size->getOperator()) {
-                case '<=':
-                    $command->add('-size -'.($size->getTarget() + 1).'c');
-                    break;
-                case '>=':
-                    $command->add('-size +'.($size->getTarget() - 1).'c');
-                    break;
-                case '>':
-                    $command->add('-size +'.$size->getTarget().'c');
-                    break;
-                case '!=':
-                    $command->add('-size -'.$size->getTarget().'c');
-                    $command->add('-size +'.$size->getTarget().'c');
-                    break;
-                case '<':
-                default:
-                    $command->add('-size -'.$size->getTarget().'c');
-            }
-        }
-    }
-
-    /**
-     * @param Command          $command
-     * @param DateComparator[] $dates
-     */
-    private function buildDatesFiltering(Command $command, array $dates)
-    {
-        foreach ($dates as $i => $date) {
-            $command->add($i > 0 ? '-and' : null);
-
-            $mins = (int) round((time() - $date->getTarget()) / 60);
-
-            if (0 > $mins) {
-                // mtime is in the future
-                $command->add(' -mmin -0');
-                // we will have no result so we don't need to continue
-                return;
-            }
-
-            switch ($date->getOperator()) {
-                case '<=':
-                    $command->add('-mmin +'.($mins - 1));
-                    break;
-                case '>=':
-                    $command->add('-mmin -'.($mins + 1));
-                    break;
-                case '>':
-                    $command->add('-mmin -'.$mins);
-                    break;
-                case '!=':
-                    $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
-                    break;
-                case '<':
-                default:
-                    $command->add('-mmin +'.$mins);
-            }
-        }
-    }
-
-    /**
-     * @param Command $command
-     * @param string  $sort
-     *
-     * @throws \InvalidArgumentException
-     */
-    private function buildSorting(Command $command, $sort)
-    {
-        $this->buildFormatSorting($command, $sort);
-    }
-
-    /**
-     * @param Command $command
-     * @param string  $sort
-     */
-    abstract protected function buildFormatSorting(Command $command, $sort);
-
-    /**
-     * @param Command $command
-     * @param array   $contains
-     * @param bool    $not
-     */
-    abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
-}
diff --git a/civicrm/vendor/symfony/finder/Adapter/AdapterInterface.php b/civicrm/vendor/symfony/finder/Adapter/AdapterInterface.php
deleted file mode 100644
index 8d8fb0749a..0000000000
--- a/civicrm/vendor/symfony/finder/Adapter/AdapterInterface.php
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Adapter;
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-interface AdapterInterface
-{
-    /**
-     * @param bool $followLinks
-     *
-     * @return $this
-     */
-    public function setFollowLinks($followLinks);
-
-    /**
-     * @param int $mode
-     *
-     * @return $this
-     */
-    public function setMode($mode);
-
-    /**
-     * @return $this
-     */
-    public function setExclude(array $exclude);
-
-    /**
-     * @return $this
-     */
-    public function setDepths(array $depths);
-
-    /**
-     * @return $this
-     */
-    public function setNames(array $names);
-
-    /**
-     * @return $this
-     */
-    public function setNotNames(array $notNames);
-
-    /**
-     * @return $this
-     */
-    public function setContains(array $contains);
-
-    /**
-     * @return $this
-     */
-    public function setNotContains(array $notContains);
-
-    /**
-     * @return $this
-     */
-    public function setSizes(array $sizes);
-
-    /**
-     * @return $this
-     */
-    public function setDates(array $dates);
-
-    /**
-     * @return $this
-     */
-    public function setFilters(array $filters);
-
-    /**
-     * @param \Closure|int $sort
-     *
-     * @return $this
-     */
-    public function setSort($sort);
-
-    /**
-     * @return $this
-     */
-    public function setPath(array $paths);
-
-    /**
-     * @return $this
-     */
-    public function setNotPath(array $notPaths);
-
-    /**
-     * @param bool $ignore
-     *
-     * @return $this
-     */
-    public function ignoreUnreadableDirs($ignore = true);
-
-    /**
-     * @param string $dir
-     *
-     * @return \Iterator Result iterator
-     */
-    public function searchInDirectory($dir);
-
-    /**
-     * Tests adapter support for current platform.
-     *
-     * @return bool
-     */
-    public function isSupported();
-
-    /**
-     * Returns adapter name.
-     *
-     * @return string
-     */
-    public function getName();
-}
diff --git a/civicrm/vendor/symfony/finder/Adapter/BsdFindAdapter.php b/civicrm/vendor/symfony/finder/Adapter/BsdFindAdapter.php
deleted file mode 100644
index f6e4303d00..0000000000
--- a/civicrm/vendor/symfony/finder/Adapter/BsdFindAdapter.php
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Adapter;
-
-@trigger_error('The '.__NAMESPACE__.'\BsdFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\Expression\Expression;
-use Symfony\Component\Finder\Iterator\SortableIterator;
-use Symfony\Component\Finder\Shell\Command;
-use Symfony\Component\Finder\Shell\Shell;
-
-/**
- * Shell engine implementation using BSD find command.
- *
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0. Use Finder instead.
- */
-class BsdFindAdapter extends AbstractFindAdapter
-{
-    /**
-     * {@inheritdoc}
-     */
-    public function getName()
-    {
-        return 'bsd_find';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function canBeUsed()
-    {
-        return \in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function buildFormatSorting(Command $command, $sort)
-    {
-        switch ($sort) {
-            case SortableIterator::SORT_BY_NAME:
-                $command->ins('sort')->add('| sort');
-
-                return;
-            case SortableIterator::SORT_BY_TYPE:
-                $format = '%HT';
-                break;
-            case SortableIterator::SORT_BY_ACCESSED_TIME:
-                $format = '%a';
-                break;
-            case SortableIterator::SORT_BY_CHANGED_TIME:
-                $format = '%c';
-                break;
-            case SortableIterator::SORT_BY_MODIFIED_TIME:
-                $format = '%m';
-                break;
-            default:
-                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
-        }
-
-        $command
-            ->add('-print0 | xargs -0 stat -f')
-            ->arg($format.'%t%N')
-            ->add('| sort | cut -f 2');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function buildFindCommand(Command $command, $dir)
-    {
-        parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
-
-        return $command;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function buildContentFiltering(Command $command, array $contains, $not = false)
-    {
-        foreach ($contains as $contain) {
-            $expr = Expression::create($contain);
-
-            // todo: avoid forking process for each $pattern by using multiple -e options
-            $command
-                ->add('| grep -v \'^$\'')
-                ->add('| xargs -I{} grep -I')
-                ->add($expr->isCaseSensitive() ? null : '-i')
-                ->add($not ? '-L' : '-l')
-                ->add('-Ee')->arg($expr->renderPattern())
-                ->add('{}')
-            ;
-        }
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Adapter/GnuFindAdapter.php b/civicrm/vendor/symfony/finder/Adapter/GnuFindAdapter.php
deleted file mode 100644
index 140c5665c9..0000000000
--- a/civicrm/vendor/symfony/finder/Adapter/GnuFindAdapter.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Adapter;
-
-@trigger_error('The '.__NAMESPACE__.'\GnuFindAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\Expression\Expression;
-use Symfony\Component\Finder\Iterator\SortableIterator;
-use Symfony\Component\Finder\Shell\Command;
-use Symfony\Component\Finder\Shell\Shell;
-
-/**
- * Shell engine implementation using GNU find command.
- *
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0. Use Finder instead.
- */
-class GnuFindAdapter extends AbstractFindAdapter
-{
-    /**
-     * {@inheritdoc}
-     */
-    public function getName()
-    {
-        return 'gnu_find';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function buildFormatSorting(Command $command, $sort)
-    {
-        switch ($sort) {
-            case SortableIterator::SORT_BY_NAME:
-                $command->ins('sort')->add('| sort');
-
-                return;
-            case SortableIterator::SORT_BY_TYPE:
-                $format = '%y';
-                break;
-            case SortableIterator::SORT_BY_ACCESSED_TIME:
-                $format = '%A@';
-                break;
-            case SortableIterator::SORT_BY_CHANGED_TIME:
-                $format = '%C@';
-                break;
-            case SortableIterator::SORT_BY_MODIFIED_TIME:
-                $format = '%T@';
-                break;
-            default:
-                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
-        }
-
-        $command
-            ->get('find')
-            ->add('-printf')
-            ->arg($format.' %h/%f\\n')
-            ->add('| sort | cut')
-            ->arg('-d ')
-            ->arg('-f2-')
-        ;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function canBeUsed()
-    {
-        return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function buildFindCommand(Command $command, $dir)
-    {
-        return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function buildContentFiltering(Command $command, array $contains, $not = false)
-    {
-        foreach ($contains as $contain) {
-            $expr = Expression::create($contain);
-
-            // todo: avoid forking process for each $pattern by using multiple -e options
-            $command
-                ->add('| xargs -I{} -r grep -I')
-                ->add($expr->isCaseSensitive() ? null : '-i')
-                ->add($not ? '-L' : '-l')
-                ->add('-Ee')->arg($expr->renderPattern())
-                ->add('{}')
-            ;
-        }
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Adapter/PhpAdapter.php b/civicrm/vendor/symfony/finder/Adapter/PhpAdapter.php
deleted file mode 100644
index c2fb66cf5e..0000000000
--- a/civicrm/vendor/symfony/finder/Adapter/PhpAdapter.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Adapter;
-
-@trigger_error('The '.__NAMESPACE__.'\PhpAdapter class is deprecated since Symfony 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\Iterator;
-
-/**
- * PHP finder engine implementation.
- *
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0. Use Finder instead.
- */
-class PhpAdapter extends AbstractAdapter
-{
-    /**
-     * {@inheritdoc}
-     */
-    public function searchInDirectory($dir)
-    {
-        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
-
-        if ($this->followLinks) {
-            $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
-        }
-
-        $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
-
-        if ($this->exclude) {
-            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
-        }
-
-        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
-
-        if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
-            $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
-        }
-
-        if ($this->mode) {
-            $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
-        }
-
-        if ($this->names || $this->notNames) {
-            $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
-        }
-
-        if ($this->contains || $this->notContains) {
-            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
-        }
-
-        if ($this->sizes) {
-            $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
-        }
-
-        if ($this->dates) {
-            $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
-        }
-
-        if ($this->filters) {
-            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
-        }
-
-        if ($this->paths || $this->notPaths) {
-            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
-        }
-
-        if ($this->sort) {
-            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
-            $iterator = $iteratorAggregate->getIterator();
-        }
-
-        return $iterator;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getName()
-    {
-        return 'php';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    protected function canBeUsed()
-    {
-        return true;
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/CHANGELOG.md b/civicrm/vendor/symfony/finder/CHANGELOG.md
index a45c20825f..53c34be860 100644
--- a/civicrm/vendor/symfony/finder/CHANGELOG.md
+++ b/civicrm/vendor/symfony/finder/CHANGELOG.md
@@ -1,6 +1,22 @@
 CHANGELOG
 =========
 
+3.4.0
+-----
+
+ * deprecated `Symfony\Component\Finder\Iterator\FilterIterator`
+ * added Finder::hasResults() method to check if any results were found
+
+3.3.0
+-----
+
+ * added double-star matching to Glob::toRegex()
+
+3.0.0
+-----
+
+ * removed deprecated classes
+
 2.8.0
 -----
 
diff --git a/civicrm/vendor/symfony/finder/Comparator/Comparator.php b/civicrm/vendor/symfony/finder/Comparator/Comparator.php
index ea37566df8..6aee21cf09 100644
--- a/civicrm/vendor/symfony/finder/Comparator/Comparator.php
+++ b/civicrm/vendor/symfony/finder/Comparator/Comparator.php
@@ -64,7 +64,7 @@ class Comparator
             $operator = '==';
         }
 
-        if (!\in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
+        if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
             throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
         }
 
diff --git a/civicrm/vendor/symfony/finder/Exception/AdapterFailureException.php b/civicrm/vendor/symfony/finder/Exception/AdapterFailureException.php
deleted file mode 100644
index 594940a47e..0000000000
--- a/civicrm/vendor/symfony/finder/Exception/AdapterFailureException.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Exception;
-
-@trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\Adapter\AdapterInterface;
-
-/**
- * Base exception for all adapter failures.
- *
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-class AdapterFailureException extends \RuntimeException implements ExceptionInterface
-{
-    private $adapter;
-
-    /**
-     * @param AdapterInterface $adapter
-     * @param string|null      $message
-     * @param \Exception|null  $previous
-     */
-    public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
-    {
-        $this->adapter = $adapter;
-        parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getAdapter()
-    {
-        return $this->adapter;
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Exception/ExceptionInterface.php b/civicrm/vendor/symfony/finder/Exception/ExceptionInterface.php
index bff02142df..161e9686d2 100644
--- a/civicrm/vendor/symfony/finder/Exception/ExceptionInterface.php
+++ b/civicrm/vendor/symfony/finder/Exception/ExceptionInterface.php
@@ -13,6 +13,8 @@ namespace Symfony\Component\Finder\Exception;
 
 /**
  * @author Jean-François Simon <contact@jfsimon.fr>
+ *
+ * @deprecated since 3.3, to be removed in 4.0.
  */
 interface ExceptionInterface
 {
diff --git a/civicrm/vendor/symfony/finder/Exception/OperationNotPermitedException.php b/civicrm/vendor/symfony/finder/Exception/OperationNotPermitedException.php
deleted file mode 100644
index 4c668582cb..0000000000
--- a/civicrm/vendor/symfony/finder/Exception/OperationNotPermitedException.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Exception;
-
-@trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-class OperationNotPermitedException extends AdapterFailureException
-{
-}
diff --git a/civicrm/vendor/symfony/finder/Exception/ShellCommandFailureException.php b/civicrm/vendor/symfony/finder/Exception/ShellCommandFailureException.php
deleted file mode 100644
index db85e682d9..0000000000
--- a/civicrm/vendor/symfony/finder/Exception/ShellCommandFailureException.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Exception;
-
-@trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\Adapter\AdapterInterface;
-use Symfony\Component\Finder\Shell\Command;
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-class ShellCommandFailureException extends AdapterFailureException
-{
-    private $command;
-
-    public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
-    {
-        $this->command = $command;
-        parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
-    }
-
-    /**
-     * @return Command
-     */
-    public function getCommand()
-    {
-        return $this->command;
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Expression/Expression.php b/civicrm/vendor/symfony/finder/Expression/Expression.php
deleted file mode 100644
index e83c771609..0000000000
--- a/civicrm/vendor/symfony/finder/Expression/Expression.php
+++ /dev/null
@@ -1,148 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Expression;
-
-@trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- */
-class Expression implements ValueInterface
-{
-    const TYPE_REGEX = 1;
-    const TYPE_GLOB = 2;
-
-    /**
-     * @var ValueInterface
-     */
-    private $value;
-
-    /**
-     * @param string $expr
-     *
-     * @return self
-     */
-    public static function create($expr)
-    {
-        return new self($expr);
-    }
-
-    /**
-     * @param string $expr
-     */
-    public function __construct($expr)
-    {
-        try {
-            $this->value = Regex::create($expr);
-        } catch (\InvalidArgumentException $e) {
-            $this->value = new Glob($expr);
-        }
-    }
-
-    /**
-     * @return string
-     */
-    public function __toString()
-    {
-        return $this->render();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function render()
-    {
-        return $this->value->render();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function renderPattern()
-    {
-        return $this->value->renderPattern();
-    }
-
-    /**
-     * @return bool
-     */
-    public function isCaseSensitive()
-    {
-        return $this->value->isCaseSensitive();
-    }
-
-    /**
-     * @return int
-     */
-    public function getType()
-    {
-        return $this->value->getType();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function prepend($expr)
-    {
-        $this->value->prepend($expr);
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function append($expr)
-    {
-        $this->value->append($expr);
-
-        return $this;
-    }
-
-    /**
-     * @return bool
-     */
-    public function isRegex()
-    {
-        return self::TYPE_REGEX === $this->value->getType();
-    }
-
-    /**
-     * @return bool
-     */
-    public function isGlob()
-    {
-        return self::TYPE_GLOB === $this->value->getType();
-    }
-
-    /**
-     * @return Glob
-     *
-     * @throws \LogicException
-     */
-    public function getGlob()
-    {
-        if (self::TYPE_GLOB !== $this->value->getType()) {
-            throw new \LogicException('Regex can\'t be transformed to glob.');
-        }
-
-        return $this->value;
-    }
-
-    /**
-     * @return Regex
-     */
-    public function getRegex()
-    {
-        return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Expression/Glob.php b/civicrm/vendor/symfony/finder/Expression/Glob.php
deleted file mode 100644
index e80578ecef..0000000000
--- a/civicrm/vendor/symfony/finder/Expression/Glob.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Expression;
-
-@trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\Glob as FinderGlob;
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- */
-class Glob implements ValueInterface
-{
-    private $pattern;
-
-    /**
-     * @param string $pattern
-     */
-    public function __construct($pattern)
-    {
-        $this->pattern = $pattern;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function render()
-    {
-        return $this->pattern;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function renderPattern()
-    {
-        return $this->pattern;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return Expression::TYPE_GLOB;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function isCaseSensitive()
-    {
-        return true;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function prepend($expr)
-    {
-        $this->pattern = $expr.$this->pattern;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function append($expr)
-    {
-        $this->pattern .= $expr;
-
-        return $this;
-    }
-
-    /**
-     * Tests if glob is expandable ("*.{a,b}" syntax).
-     *
-     * @return bool
-     */
-    public function isExpandable()
-    {
-        return false !== strpos($this->pattern, '{')
-            && false !== strpos($this->pattern, '}');
-    }
-
-    /**
-     * @param bool $strictLeadingDot
-     * @param bool $strictWildcardSlash
-     *
-     * @return Regex
-     */
-    public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
-    {
-        $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
-
-        return new Regex($regex);
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Expression/Regex.php b/civicrm/vendor/symfony/finder/Expression/Regex.php
deleted file mode 100644
index 2f1ab3db03..0000000000
--- a/civicrm/vendor/symfony/finder/Expression/Regex.php
+++ /dev/null
@@ -1,321 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Expression;
-
-@trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- */
-class Regex implements ValueInterface
-{
-    const START_FLAG = '^';
-    const END_FLAG = '$';
-    const BOUNDARY = '~';
-    const JOKER = '.*';
-    const ESCAPING = '\\';
-
-    /**
-     * @var string
-     */
-    private $pattern;
-
-    /**
-     * @var string
-     */
-    private $options;
-
-    /**
-     * @var bool
-     */
-    private $startFlag;
-
-    /**
-     * @var bool
-     */
-    private $endFlag;
-
-    /**
-     * @var bool
-     */
-    private $startJoker;
-
-    /**
-     * @var bool
-     */
-    private $endJoker;
-
-    /**
-     * @param string $expr
-     *
-     * @return self
-     *
-     * @throws \InvalidArgumentException
-     */
-    public static function create($expr)
-    {
-        if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
-            $start = substr($m[1], 0, 1);
-            $end = substr($m[1], -1);
-
-            if (
-                ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
-                || ('{' === $start && '}' === $end)
-                || ('(' === $start && ')' === $end)
-            ) {
-                return new self(substr($m[1], 1, -1), $m[2], $end);
-            }
-        }
-
-        throw new \InvalidArgumentException('Given expression is not a regex.');
-    }
-
-    /**
-     * @param string $pattern
-     * @param string $options
-     * @param string $delimiter
-     */
-    public function __construct($pattern, $options = '', $delimiter = null)
-    {
-        if (null !== $delimiter) {
-            // removes delimiter escaping
-            $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
-        }
-
-        $this->parsePattern($pattern);
-        $this->options = $options;
-    }
-
-    /**
-     * @return string
-     */
-    public function __toString()
-    {
-        return $this->render();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function render()
-    {
-        return self::BOUNDARY
-            .$this->renderPattern()
-            .self::BOUNDARY
-            .$this->options;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function renderPattern()
-    {
-        return ($this->startFlag ? self::START_FLAG : '')
-            .($this->startJoker ? self::JOKER : '')
-            .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
-            .($this->endJoker ? self::JOKER : '')
-            .($this->endFlag ? self::END_FLAG : '');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function isCaseSensitive()
-    {
-        return !$this->hasOption('i');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return Expression::TYPE_REGEX;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function prepend($expr)
-    {
-        $this->pattern = $expr.$this->pattern;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function append($expr)
-    {
-        $this->pattern .= $expr;
-
-        return $this;
-    }
-
-    /**
-     * @param string $option
-     *
-     * @return bool
-     */
-    public function hasOption($option)
-    {
-        return false !== strpos($this->options, $option);
-    }
-
-    /**
-     * @param string $option
-     *
-     * @return $this
-     */
-    public function addOption($option)
-    {
-        if (!$this->hasOption($option)) {
-            $this->options .= $option;
-        }
-
-        return $this;
-    }
-
-    /**
-     * @param string $option
-     *
-     * @return $this
-     */
-    public function removeOption($option)
-    {
-        $this->options = str_replace($option, '', $this->options);
-
-        return $this;
-    }
-
-    /**
-     * @param bool $startFlag
-     *
-     * @return $this
-     */
-    public function setStartFlag($startFlag)
-    {
-        $this->startFlag = $startFlag;
-
-        return $this;
-    }
-
-    /**
-     * @return bool
-     */
-    public function hasStartFlag()
-    {
-        return $this->startFlag;
-    }
-
-    /**
-     * @param bool $endFlag
-     *
-     * @return $this
-     */
-    public function setEndFlag($endFlag)
-    {
-        $this->endFlag = (bool) $endFlag;
-
-        return $this;
-    }
-
-    /**
-     * @return bool
-     */
-    public function hasEndFlag()
-    {
-        return $this->endFlag;
-    }
-
-    /**
-     * @param bool $startJoker
-     *
-     * @return $this
-     */
-    public function setStartJoker($startJoker)
-    {
-        $this->startJoker = $startJoker;
-
-        return $this;
-    }
-
-    /**
-     * @return bool
-     */
-    public function hasStartJoker()
-    {
-        return $this->startJoker;
-    }
-
-    /**
-     * @param bool $endJoker
-     *
-     * @return $this
-     */
-    public function setEndJoker($endJoker)
-    {
-        $this->endJoker = (bool) $endJoker;
-
-        return $this;
-    }
-
-    /**
-     * @return bool
-     */
-    public function hasEndJoker()
-    {
-        return $this->endJoker;
-    }
-
-    /**
-     * @return $this
-     */
-    public function replaceJokers($replacement)
-    {
-        $replace = function ($subject) use ($replacement) {
-            $subject = $subject[0];
-            $replace = 0 === substr_count($subject, '\\') % 2;
-
-            return $replace ? str_replace('.', $replacement, $subject) : $subject;
-        };
-
-        $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
-
-        return $this;
-    }
-
-    /**
-     * @param string $pattern
-     */
-    private function parsePattern($pattern)
-    {
-        if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
-            $pattern = substr($pattern, 1);
-        }
-
-        if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
-            $pattern = substr($pattern, 2);
-        }
-
-        if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
-            $pattern = substr($pattern, 0, -1);
-        }
-
-        if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
-            $pattern = substr($pattern, 0, -2);
-        }
-
-        $this->pattern = $pattern;
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Expression/ValueInterface.php b/civicrm/vendor/symfony/finder/Expression/ValueInterface.php
deleted file mode 100644
index 08ede1422e..0000000000
--- a/civicrm/vendor/symfony/finder/Expression/ValueInterface.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Expression;
-
-@trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- */
-interface ValueInterface
-{
-    /**
-     * Renders string representation of expression.
-     *
-     * @return string
-     */
-    public function render();
-
-    /**
-     * Renders string representation of pattern.
-     *
-     * @return string
-     */
-    public function renderPattern();
-
-    /**
-     * Returns value case sensitivity.
-     *
-     * @return bool
-     */
-    public function isCaseSensitive();
-
-    /**
-     * Returns expression type.
-     *
-     * @return int
-     */
-    public function getType();
-
-    /**
-     * @param string $expr
-     *
-     * @return $this
-     */
-    public function prepend($expr);
-
-    /**
-     * @param string $expr
-     *
-     * @return $this
-     */
-    public function append($expr);
-}
diff --git a/civicrm/vendor/symfony/finder/Finder.php b/civicrm/vendor/symfony/finder/Finder.php
index 1ee9017356..33a76cc976 100644
--- a/civicrm/vendor/symfony/finder/Finder.php
+++ b/civicrm/vendor/symfony/finder/Finder.php
@@ -11,13 +11,8 @@
 
 namespace Symfony\Component\Finder;
 
-use Symfony\Component\Finder\Adapter\AdapterInterface;
-use Symfony\Component\Finder\Adapter\BsdFindAdapter;
-use Symfony\Component\Finder\Adapter\GnuFindAdapter;
-use Symfony\Component\Finder\Adapter\PhpAdapter;
 use Symfony\Component\Finder\Comparator\DateComparator;
 use Symfony\Component\Finder\Comparator\NumberComparator;
-use Symfony\Component\Finder\Exception\ExceptionInterface;
 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
@@ -34,7 +29,7 @@ use Symfony\Component\Finder\Iterator\SortableIterator;
  *
  * All rules may be invoked several times.
  *
- * All methods return the current Finder object to allow easy chaining:
+ * All methods return the current Finder object to allow chaining:
  *
  *     $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
  *
@@ -46,26 +41,25 @@ class Finder implements \IteratorAggregate, \Countable
     const IGNORE_DOT_FILES = 2;
 
     private $mode = 0;
-    private $names = array();
-    private $notNames = array();
-    private $exclude = array();
-    private $filters = array();
-    private $depths = array();
-    private $sizes = array();
+    private $names = [];
+    private $notNames = [];
+    private $exclude = [];
+    private $filters = [];
+    private $depths = [];
+    private $sizes = [];
     private $followLinks = false;
     private $sort = false;
     private $ignore = 0;
-    private $dirs = array();
-    private $dates = array();
-    private $iterators = array();
-    private $contains = array();
-    private $notContains = array();
-    private $adapters = null;
-    private $paths = array();
-    private $notPaths = array();
+    private $dirs = [];
+    private $dates = [];
+    private $iterators = [];
+    private $contains = [];
+    private $notContains = [];
+    private $paths = [];
+    private $notPaths = [];
     private $ignoreUnreadableDirs = false;
 
-    private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
+    private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'];
 
     public function __construct()
     {
@@ -82,110 +76,6 @@ class Finder implements \IteratorAggregate, \Countable
         return new static();
     }
 
-    /**
-     * Registers a finder engine implementation.
-     *
-     * @param AdapterInterface $adapter  An adapter instance
-     * @param int              $priority Highest is selected first
-     *
-     * @return $this
-     *
-     * @deprecated since 2.8, to be removed in 3.0.
-     */
-    public function addAdapter(AdapterInterface $adapter, $priority = 0)
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-        $this->initDefaultAdapters();
-
-        $this->adapters[$adapter->getName()] = array(
-            'adapter' => $adapter,
-            'priority' => $priority,
-            'selected' => false,
-        );
-
-        return $this->sortAdapters();
-    }
-
-    /**
-     * Sets the selected adapter to the best one according to the current platform the code is run on.
-     *
-     * @return $this
-     *
-     * @deprecated since 2.8, to be removed in 3.0.
-     */
-    public function useBestAdapter()
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-        $this->initDefaultAdapters();
-
-        $this->resetAdapterSelection();
-
-        return $this->sortAdapters();
-    }
-
-    /**
-     * Selects the adapter to use.
-     *
-     * @param string $name
-     *
-     * @return $this
-     *
-     * @throws \InvalidArgumentException
-     *
-     * @deprecated since 2.8, to be removed in 3.0.
-     */
-    public function setAdapter($name)
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-        $this->initDefaultAdapters();
-
-        if (!isset($this->adapters[$name])) {
-            throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
-        }
-
-        $this->resetAdapterSelection();
-        $this->adapters[$name]['selected'] = true;
-
-        return $this->sortAdapters();
-    }
-
-    /**
-     * Removes all adapters registered in the finder.
-     *
-     * @return $this
-     *
-     * @deprecated since 2.8, to be removed in 3.0.
-     */
-    public function removeAdapters()
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-        $this->adapters = array();
-
-        return $this;
-    }
-
-    /**
-     * Returns registered adapters ordered by priority without extra information.
-     *
-     * @return AdapterInterface[]
-     *
-     * @deprecated since 2.8, to be removed in 3.0.
-     */
-    public function getAdapters()
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-        $this->initDefaultAdapters();
-
-        return array_values(array_map(function (array $adapter) {
-            return $adapter['adapter'];
-        }, $this->adapters));
-    }
-
     /**
      * Restricts the matching to directories only.
      *
@@ -638,7 +528,7 @@ class Finder implements \IteratorAggregate, \Countable
     /**
      * Searches files and directories which match defined rules.
      *
-     * @param string|array $dirs A directory path or an array of directories
+     * @param string|string[] $dirs A directory path or an array of directories
      *
      * @return $this
      *
@@ -646,13 +536,14 @@ class Finder implements \IteratorAggregate, \Countable
      */
     public function in($dirs)
     {
-        $resolvedDirs = array();
+        $resolvedDirs = [];
 
         foreach ((array) $dirs as $dir) {
             if (is_dir($dir)) {
                 $resolvedDirs[] = $this->normalizeDir($dir);
-            } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
-                $resolvedDirs = array_merge($resolvedDirs, array_map(array($this, 'normalizeDir'), $glob));
+            } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR | GLOB_NOSORT)) {
+                sort($glob);
+                $resolvedDirs = array_merge($resolvedDirs, array_map([$this, 'normalizeDir'], $glob));
             } else {
                 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
             }
@@ -725,29 +616,27 @@ class Finder implements \IteratorAggregate, \Countable
     }
 
     /**
-     * Counts all the results collected by the iterators.
+     * Check if the any results were found.
      *
-     * @return int
+     * @return bool
      */
-    public function count()
+    public function hasResults()
     {
-        return iterator_count($this->getIterator());
+        foreach ($this->getIterator() as $_) {
+            return true;
+        }
+
+        return false;
     }
 
     /**
-     * @return $this
+     * Counts all the results collected by the iterators.
+     *
+     * @return int
      */
-    private function sortAdapters()
+    public function count()
     {
-        uasort($this->adapters, function (array $a, array $b) {
-            if ($a['selected'] || $b['selected']) {
-                return $a['selected'] ? -1 : 1;
-            }
-
-            return $a['priority'] > $b['priority'] ? -1 : 1;
-        });
-
-        return $this;
+        return iterator_count($this->getIterator());
     }
 
     /**
@@ -757,25 +646,15 @@ class Finder implements \IteratorAggregate, \Countable
      */
     private function searchInDirectory($dir)
     {
+        $exclude = $this->exclude;
+        $notPaths = $this->notPaths;
+
         if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
-            $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
+            $exclude = array_merge($exclude, self::$vcsPatterns);
         }
 
         if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
-            $this->notPaths[] = '#(^|/)\..+(/|$)#';
-        }
-
-        if ($this->adapters) {
-            foreach ($this->adapters as $adapter) {
-                if ($adapter['adapter']->isSupported()) {
-                    try {
-                        return $this
-                            ->buildAdapter($adapter['adapter'])
-                            ->searchInDirectory($dir);
-                    } catch (ExceptionInterface $e) {
-                    }
-                }
-            }
+            $notPaths[] = '#(^|/)\..+(/|$)#';
         }
 
         $minDepth = 0;
@@ -808,8 +687,8 @@ class Finder implements \IteratorAggregate, \Countable
 
         $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
 
-        if ($this->exclude) {
-            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
+        if ($exclude) {
+            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude);
         }
 
         $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
@@ -842,8 +721,8 @@ class Finder implements \IteratorAggregate, \Countable
             $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
         }
 
-        if ($this->paths || $this->notPaths) {
-            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
+        if ($this->paths || $notPaths) {
+            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths);
         }
 
         if ($this->sort) {
@@ -854,63 +733,27 @@ class Finder implements \IteratorAggregate, \Countable
         return $iterator;
     }
 
-    /**
-     * @return AdapterInterface
-     */
-    private function buildAdapter(AdapterInterface $adapter)
-    {
-        return $adapter
-            ->setFollowLinks($this->followLinks)
-            ->setDepths($this->depths)
-            ->setMode($this->mode)
-            ->setExclude($this->exclude)
-            ->setNames($this->names)
-            ->setNotNames($this->notNames)
-            ->setContains($this->contains)
-            ->setNotContains($this->notContains)
-            ->setSizes($this->sizes)
-            ->setDates($this->dates)
-            ->setFilters($this->filters)
-            ->setSort($this->sort)
-            ->setPath($this->paths)
-            ->setNotPath($this->notPaths)
-            ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
-    }
-
-    /**
-     * Unselects all adapters.
-     */
-    private function resetAdapterSelection()
-    {
-        $this->adapters = array_map(function (array $properties) {
-            $properties['selected'] = false;
-
-            return $properties;
-        }, $this->adapters);
-    }
-
-    private function initDefaultAdapters()
-    {
-        if (null === $this->adapters) {
-            $this->adapters = array();
-            $this
-                ->addAdapter(new GnuFindAdapter())
-                ->addAdapter(new BsdFindAdapter())
-                ->addAdapter(new PhpAdapter(), -50)
-                ->setAdapter('php')
-            ;
-        }
-    }
-
     /**
      * Normalizes given directory names by removing trailing slashes.
      *
+     * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper
+     *
      * @param string $dir
      *
      * @return string
      */
     private function normalizeDir($dir)
     {
-        return rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
+        if ('/' === $dir) {
+            return $dir;
+        }
+
+        $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR);
+
+        if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) {
+            $dir .= '/';
+        }
+
+        return $dir;
     }
 }
diff --git a/civicrm/vendor/symfony/finder/Glob.php b/civicrm/vendor/symfony/finder/Glob.php
index e2988f2576..ea76d51ae0 100644
--- a/civicrm/vendor/symfony/finder/Glob.php
+++ b/civicrm/vendor/symfony/finder/Glob.php
@@ -18,7 +18,7 @@ namespace Symfony\Component\Finder;
  *
  *     // prints foo.bar and foo.baz
  *     $regex = glob_to_regex("foo.*");
- *     for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t)
+ *     for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t)
  *     {
  *         if (/$regex/) echo "matched: $car\n";
  *     }
@@ -54,16 +54,28 @@ class Glob
         $sizeGlob = \strlen($glob);
         for ($i = 0; $i < $sizeGlob; ++$i) {
             $car = $glob[$i];
-            if ($firstByte) {
-                if ($strictLeadingDot && '.' !== $car) {
-                    $regex .= '(?=[^\.])';
+            if ($firstByte && $strictLeadingDot && '.' !== $car) {
+                $regex .= '(?=[^\.])';
+            }
+
+            $firstByte = '/' === $car;
+
+            if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) {
+                $car = '[^/]++/';
+                if (!isset($glob[$i + 3])) {
+                    $car .= '?';
                 }
 
-                $firstByte = false;
-            }
+                if ($strictLeadingDot) {
+                    $car = '(?=[^\.])'.$car;
+                }
+
+                $car = '/(?:'.$car.')*';
+                $i += 2 + isset($glob[$i + 3]);
 
-            if ('/' === $car) {
-                $firstByte = true;
+                if ('/' === $delimiter) {
+                    $car = str_replace('/', '\\/', $car);
+                }
             }
 
             if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
diff --git a/civicrm/vendor/symfony/finder/Iterator/CustomFilterIterator.php b/civicrm/vendor/symfony/finder/Iterator/CustomFilterIterator.php
index 6666e07ec5..896f7e912f 100644
--- a/civicrm/vendor/symfony/finder/Iterator/CustomFilterIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/CustomFilterIterator.php
@@ -21,7 +21,7 @@ namespace Symfony\Component\Finder\Iterator;
  */
 class CustomFilterIterator extends FilterIterator
 {
-    private $filters = array();
+    private $filters = [];
 
     /**
      * @param \Iterator  $iterator The Iterator to filter
diff --git a/civicrm/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php b/civicrm/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php
index b01e5e3f5d..8a47321a3c 100644
--- a/civicrm/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php
@@ -20,7 +20,7 @@ use Symfony\Component\Finder\Comparator\DateComparator;
  */
 class DateRangeFilterIterator extends FilterIterator
 {
-    private $comparators = array();
+    private $comparators = [];
 
     /**
      * @param \Iterator        $iterator    The Iterator to filter
diff --git a/civicrm/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php b/civicrm/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php
index c57128c278..60bc4e814c 100644
--- a/civicrm/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php
@@ -20,18 +20,18 @@ class ExcludeDirectoryFilterIterator extends FilterIterator implements \Recursiv
 {
     private $iterator;
     private $isRecursive;
-    private $excludedDirs = array();
+    private $excludedDirs = [];
     private $excludedPattern;
 
     /**
      * @param \Iterator $iterator    The Iterator to filter
-     * @param array     $directories An array of directories to exclude
+     * @param string[]  $directories An array of directories to exclude
      */
     public function __construct(\Iterator $iterator, array $directories)
     {
         $this->iterator = $iterator;
         $this->isRecursive = $iterator instanceof \RecursiveIterator;
-        $patterns = array();
+        $patterns = [];
         foreach ($directories as $directory) {
             $directory = rtrim($directory, '/');
             if (!$this->isRecursive || false !== strpos($directory, '/')) {
@@ -75,7 +75,7 @@ class ExcludeDirectoryFilterIterator extends FilterIterator implements \Recursiv
 
     public function getChildren()
     {
-        $children = new self($this->iterator->getChildren(), array());
+        $children = new self($this->iterator->getChildren(), []);
         $children->excludedDirs = $this->excludedDirs;
         $children->excludedPattern = $this->excludedPattern;
 
diff --git a/civicrm/vendor/symfony/finder/Iterator/FilePathsIterator.php b/civicrm/vendor/symfony/finder/Iterator/FilePathsIterator.php
deleted file mode 100644
index 9c4e5c4aab..0000000000
--- a/civicrm/vendor/symfony/finder/Iterator/FilePathsIterator.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Iterator;
-
-@trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-use Symfony\Component\Finder\SplFileInfo;
-
-/**
- * Iterate over shell command result.
- *
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-class FilePathsIterator extends \ArrayIterator
-{
-    /**
-     * @var string
-     */
-    private $baseDir;
-
-    /**
-     * @var int
-     */
-    private $baseDirLength;
-
-    /**
-     * @var string
-     */
-    private $subPath;
-
-    /**
-     * @var string
-     */
-    private $subPathname;
-
-    /**
-     * @var SplFileInfo
-     */
-    private $current;
-
-    /**
-     * @param array  $paths   List of paths returned by shell command
-     * @param string $baseDir Base dir for relative path building
-     */
-    public function __construct(array $paths, $baseDir)
-    {
-        $this->baseDir = $baseDir;
-        $this->baseDirLength = \strlen($baseDir);
-
-        parent::__construct($paths);
-    }
-
-    /**
-     * @param string $name
-     * @param array  $arguments
-     *
-     * @return mixed
-     */
-    public function __call($name, array $arguments)
-    {
-        return \call_user_func_array(array($this->current(), $name), $arguments);
-    }
-
-    /**
-     * Return an instance of SplFileInfo with support for relative paths.
-     *
-     * @return SplFileInfo File information
-     */
-    public function current()
-    {
-        return $this->current;
-    }
-
-    /**
-     * @return string
-     */
-    public function key()
-    {
-        return $this->current->getPathname();
-    }
-
-    public function next()
-    {
-        parent::next();
-        $this->buildProperties();
-    }
-
-    public function rewind()
-    {
-        parent::rewind();
-        $this->buildProperties();
-    }
-
-    /**
-     * @return string
-     */
-    public function getSubPath()
-    {
-        return $this->subPath;
-    }
-
-    /**
-     * @return string
-     */
-    public function getSubPathname()
-    {
-        return $this->subPathname;
-    }
-
-    private function buildProperties()
-    {
-        $absolutePath = parent::current();
-
-        if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
-            $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
-            $dir = \dirname($this->subPathname);
-            $this->subPath = '.' === $dir ? '' : $dir;
-        } else {
-            $this->subPath = $this->subPathname = '';
-        }
-
-        $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Iterator/FilterIterator.php b/civicrm/vendor/symfony/finder/Iterator/FilterIterator.php
index acb98361c9..c16dd8fa9e 100644
--- a/civicrm/vendor/symfony/finder/Iterator/FilterIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/FilterIterator.php
@@ -18,6 +18,8 @@ namespace Symfony\Component\Finder\Iterator;
  * @see https://bugs.php.net/68557
  *
  * @author Alex Bogomazov
+ *
+ * @deprecated since 3.4, to be removed in 4.0.
  */
 abstract class FilterIterator extends \FilterIterator
 {
diff --git a/civicrm/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php b/civicrm/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php
index fc8854047e..ee365a58b0 100644
--- a/civicrm/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php
@@ -18,8 +18,8 @@ namespace Symfony\Component\Finder\Iterator;
  */
 abstract class MultiplePcreFilterIterator extends FilterIterator
 {
-    protected $matchRegexps = array();
-    protected $noMatchRegexps = array();
+    protected $matchRegexps = [];
+    protected $noMatchRegexps = [];
 
     /**
      * @param \Iterator $iterator        The Iterator to filter
@@ -91,7 +91,7 @@ abstract class MultiplePcreFilterIterator extends FilterIterator
                 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
             }
 
-            foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
+            foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) {
                 if ($start === $delimiters[0] && $end === $delimiters[1]) {
                     return true;
                 }
diff --git a/civicrm/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/civicrm/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php
index cb2964f8f2..63764d407d 100644
--- a/civicrm/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php
@@ -51,7 +51,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
 
         parent::__construct($path, $flags);
         $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
-        $this->rootPath = (string) $path;
+        $this->rootPath = $path;
         if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
             $this->directorySeparator = \DIRECTORY_SEPARATOR;
         }
@@ -74,7 +74,11 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
         }
         $subPathname .= $this->getFilename();
 
-        return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
+        if ('/' !== $basePath = $this->rootPath) {
+            $basePath .= $this->directorySeparator;
+        }
+
+        return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname);
     }
 
     /**
@@ -100,7 +104,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
         } catch (\UnexpectedValueException $e) {
             if ($this->ignoreUnreadableDirs) {
                 // If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
-                return new \RecursiveArrayIterator(array());
+                return new \RecursiveArrayIterator([]);
             } else {
                 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
             }
diff --git a/civicrm/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php b/civicrm/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php
index bd1a7fb700..4e521c8c90 100644
--- a/civicrm/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php
@@ -20,7 +20,7 @@ use Symfony\Component\Finder\Comparator\NumberComparator;
  */
 class SizeRangeFilterIterator extends FilterIterator
 {
-    private $comparators = array();
+    private $comparators = [];
 
     /**
      * @param \Iterator          $iterator    The Iterator to filter
diff --git a/civicrm/vendor/symfony/finder/Iterator/SortableIterator.php b/civicrm/vendor/symfony/finder/Iterator/SortableIterator.php
index 53f8e31c6c..e67997d117 100644
--- a/civicrm/vendor/symfony/finder/Iterator/SortableIterator.php
+++ b/civicrm/vendor/symfony/finder/Iterator/SortableIterator.php
@@ -38,29 +38,29 @@ class SortableIterator implements \IteratorAggregate
         $this->iterator = $iterator;
 
         if (self::SORT_BY_NAME === $sort) {
-            $this->sort = function ($a, $b) {
-                return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
+            $this->sort = static function ($a, $b) {
+                return strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
             };
         } elseif (self::SORT_BY_TYPE === $sort) {
-            $this->sort = function ($a, $b) {
+            $this->sort = static function ($a, $b) {
                 if ($a->isDir() && $b->isFile()) {
                     return -1;
                 } elseif ($a->isFile() && $b->isDir()) {
                     return 1;
                 }
 
-                return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
+                return strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname());
             };
         } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
-            $this->sort = function ($a, $b) {
+            $this->sort = static function ($a, $b) {
                 return $a->getATime() - $b->getATime();
             };
         } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
-            $this->sort = function ($a, $b) {
+            $this->sort = static function ($a, $b) {
                 return $a->getCTime() - $b->getCTime();
             };
         } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
-            $this->sort = function ($a, $b) {
+            $this->sort = static function ($a, $b) {
                 return $a->getMTime() - $b->getMTime();
             };
         } elseif (\is_callable($sort)) {
diff --git a/civicrm/vendor/symfony/finder/LICENSE b/civicrm/vendor/symfony/finder/LICENSE
index 21d7fb9e2f..9e936ec044 100644
--- a/civicrm/vendor/symfony/finder/LICENSE
+++ b/civicrm/vendor/symfony/finder/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2018 Fabien Potencier
+Copyright (c) 2004-2020 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/civicrm/vendor/symfony/finder/Shell/Command.php b/civicrm/vendor/symfony/finder/Shell/Command.php
deleted file mode 100644
index 8219078723..0000000000
--- a/civicrm/vendor/symfony/finder/Shell/Command.php
+++ /dev/null
@@ -1,278 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Shell;
-
-@trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-class Command
-{
-    private $parent;
-    private $bits = array();
-    private $labels = array();
-
-    /**
-     * @var \Closure|null
-     */
-    private $errorHandler;
-
-    public function __construct(Command $parent = null)
-    {
-        $this->parent = $parent;
-    }
-
-    /**
-     * Returns command as string.
-     *
-     * @return string
-     */
-    public function __toString()
-    {
-        return $this->join();
-    }
-
-    /**
-     * Creates a new Command instance.
-     *
-     * @return self
-     */
-    public static function create(Command $parent = null)
-    {
-        return new self($parent);
-    }
-
-    /**
-     * Escapes special chars from input.
-     *
-     * @param string $input A string to escape
-     *
-     * @return string The escaped string
-     */
-    public static function escape($input)
-    {
-        return escapeshellcmd($input);
-    }
-
-    /**
-     * Quotes input.
-     *
-     * @param string $input An argument string
-     *
-     * @return string The quoted string
-     */
-    public static function quote($input)
-    {
-        return escapeshellarg($input);
-    }
-
-    /**
-     * Appends a string or a Command instance.
-     *
-     * @param string|Command $bit
-     *
-     * @return $this
-     */
-    public function add($bit)
-    {
-        $this->bits[] = $bit;
-
-        return $this;
-    }
-
-    /**
-     * Prepends a string or a command instance.
-     *
-     * @param string|Command $bit
-     *
-     * @return $this
-     */
-    public function top($bit)
-    {
-        array_unshift($this->bits, $bit);
-
-        foreach ($this->labels as $label => $index) {
-            ++$this->labels[$label];
-        }
-
-        return $this;
-    }
-
-    /**
-     * Appends an argument, will be quoted.
-     *
-     * @param string $arg
-     *
-     * @return $this
-     */
-    public function arg($arg)
-    {
-        $this->bits[] = self::quote($arg);
-
-        return $this;
-    }
-
-    /**
-     * Appends escaped special command chars.
-     *
-     * @param string $esc
-     *
-     * @return $this
-     */
-    public function cmd($esc)
-    {
-        $this->bits[] = self::escape($esc);
-
-        return $this;
-    }
-
-    /**
-     * Inserts a labeled command to feed later.
-     *
-     * @param string $label The unique label
-     *
-     * @return self|string
-     *
-     * @throws \RuntimeException If label already exists
-     */
-    public function ins($label)
-    {
-        if (isset($this->labels[$label])) {
-            throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
-        }
-
-        $this->bits[] = self::create($this);
-        $this->labels[$label] = \count($this->bits) - 1;
-
-        return $this->bits[$this->labels[$label]];
-    }
-
-    /**
-     * Retrieves a previously labeled command.
-     *
-     * @param string $label
-     *
-     * @return self|string
-     *
-     * @throws \RuntimeException
-     */
-    public function get($label)
-    {
-        if (!isset($this->labels[$label])) {
-            throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
-        }
-
-        return $this->bits[$this->labels[$label]];
-    }
-
-    /**
-     * Returns parent command (if any).
-     *
-     * @return self
-     *
-     * @throws \RuntimeException If command has no parent
-     */
-    public function end()
-    {
-        if (null === $this->parent) {
-            throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
-        }
-
-        return $this->parent;
-    }
-
-    /**
-     * Counts bits stored in command.
-     *
-     * @return int The bits count
-     */
-    public function length()
-    {
-        return \count($this->bits);
-    }
-
-    /**
-     * @return $this
-     */
-    public function setErrorHandler(\Closure $errorHandler)
-    {
-        $this->errorHandler = $errorHandler;
-
-        return $this;
-    }
-
-    /**
-     * @return \Closure|null
-     */
-    public function getErrorHandler()
-    {
-        return $this->errorHandler;
-    }
-
-    /**
-     * Executes current command.
-     *
-     * @return array The command result
-     *
-     * @throws \RuntimeException
-     */
-    public function execute()
-    {
-        if (null === $errorHandler = $this->errorHandler) {
-            exec($this->join(), $output);
-        } else {
-            $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
-            $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
-
-            if ($error = stream_get_contents($pipes[2])) {
-                $errorHandler($error);
-            }
-
-            proc_close($process);
-        }
-
-        return $output ?: array();
-    }
-
-    /**
-     * Joins bits.
-     *
-     * @return string
-     */
-    public function join()
-    {
-        return implode(' ', array_filter(
-            array_map(function ($bit) {
-                return $bit instanceof Command ? $bit->join() : ($bit ?: null);
-            }, $this->bits),
-            function ($bit) { return null !== $bit; }
-        ));
-    }
-
-    /**
-     * Insert a string or a Command instance before the bit at given position $index (index starts from 0).
-     *
-     * @param string|Command $bit
-     * @param int            $index
-     *
-     * @return $this
-     */
-    public function addAtIndex($bit, $index)
-    {
-        array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
-
-        return $this;
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/Shell/Shell.php b/civicrm/vendor/symfony/finder/Shell/Shell.php
deleted file mode 100644
index fa6ca4b940..0000000000
--- a/civicrm/vendor/symfony/finder/Shell/Shell.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Finder\Shell;
-
-@trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-/**
- * @author Jean-François Simon <contact@jfsimon.fr>
- *
- * @deprecated since 2.8, to be removed in 3.0.
- */
-class Shell
-{
-    const TYPE_UNIX = 1;
-    const TYPE_DARWIN = 2;
-    const TYPE_CYGWIN = 3;
-    const TYPE_WINDOWS = 4;
-    const TYPE_BSD = 5;
-
-    /**
-     * @var string|null
-     */
-    private $type;
-
-    /**
-     * Returns guessed OS type.
-     *
-     * @return int
-     */
-    public function getType()
-    {
-        if (null === $this->type) {
-            $this->type = $this->guessType();
-        }
-
-        return $this->type;
-    }
-
-    /**
-     * Tests if a command is available.
-     *
-     * @param string $command
-     *
-     * @return bool
-     */
-    public function testCommand($command)
-    {
-        if (!\function_exists('exec')) {
-            return false;
-        }
-
-        // todo: find a better way (command could not be available)
-        $testCommand = 'which ';
-        if (self::TYPE_WINDOWS === $this->type) {
-            $testCommand = 'where ';
-        }
-
-        $command = escapeshellcmd($command);
-
-        exec($testCommand.$command, $output, $code);
-
-        return 0 === $code && \count($output) > 0;
-    }
-
-    /**
-     * Guesses OS type.
-     *
-     * @return int
-     */
-    private function guessType()
-    {
-        $os = strtolower(PHP_OS);
-
-        if (false !== strpos($os, 'cygwin')) {
-            return self::TYPE_CYGWIN;
-        }
-
-        if (false !== strpos($os, 'darwin')) {
-            return self::TYPE_DARWIN;
-        }
-
-        if (false !== strpos($os, 'bsd')) {
-            return self::TYPE_BSD;
-        }
-
-        if (0 === strpos($os, 'win')) {
-            return self::TYPE_WINDOWS;
-        }
-
-        return self::TYPE_UNIX;
-    }
-}
diff --git a/civicrm/vendor/symfony/finder/composer.json b/civicrm/vendor/symfony/finder/composer.json
index 53dc98a9b2..de19826f73 100644
--- a/civicrm/vendor/symfony/finder/composer.json
+++ b/civicrm/vendor/symfony/finder/composer.json
@@ -16,7 +16,7 @@
         }
     ],
     "require": {
-        "php": ">=5.3.9"
+        "php": "^5.5.9|>=7.0.8"
     },
     "autoload": {
         "psr-4": { "Symfony\\Component\\Finder\\": "" },
@@ -27,7 +27,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "2.8-dev"
+            "dev-master": "3.4-dev"
         }
     }
 }
diff --git a/civicrm/vendor/symfony/polyfill-ctype/bootstrap.php b/civicrm/vendor/symfony/polyfill-ctype/bootstrap.php
index 14d1d0faa3..8d6fc4becc 100644
--- a/civicrm/vendor/symfony/polyfill-ctype/bootstrap.php
+++ b/civicrm/vendor/symfony/polyfill-ctype/bootstrap.php
@@ -13,14 +13,34 @@ use Symfony\Polyfill\Ctype as p;
 
 if (!function_exists('ctype_alnum')) {
     function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
+}
+if (!function_exists('ctype_alpha')) {
     function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
+}
+if (!function_exists('ctype_cntrl')) {
     function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
+}
+if (!function_exists('ctype_digit')) {
     function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
+}
+if (!function_exists('ctype_graph')) {
     function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
+}
+if (!function_exists('ctype_lower')) {
     function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
+}
+if (!function_exists('ctype_print')) {
     function ctype_print($text) { return p\Ctype::ctype_print($text); }
+}
+if (!function_exists('ctype_punct')) {
     function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
+}
+if (!function_exists('ctype_space')) {
     function ctype_space($text) { return p\Ctype::ctype_space($text); }
+}
+if (!function_exists('ctype_upper')) {
     function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
+}
+if (!function_exists('ctype_xdigit')) {
     function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
 }
diff --git a/civicrm/vendor/symfony/polyfill-ctype/composer.json b/civicrm/vendor/symfony/polyfill-ctype/composer.json
index 090f923ef1..afb2a443e9 100644
--- a/civicrm/vendor/symfony/polyfill-ctype/composer.json
+++ b/civicrm/vendor/symfony/polyfill-ctype/composer.json
@@ -28,7 +28,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "1.12-dev"
+            "dev-master": "1.17-dev"
         }
     }
 }
diff --git a/civicrm/vendor/symfony/polyfill-iconv/README.md b/civicrm/vendor/symfony/polyfill-iconv/README.md
index 2421831c6b..b0c8984cd6 100644
--- a/civicrm/vendor/symfony/polyfill-iconv/README.md
+++ b/civicrm/vendor/symfony/polyfill-iconv/README.md
@@ -2,8 +2,8 @@ Symfony Polyfill / Iconv
 ========================
 
 This component provides a native PHP implementation of the
-[php.net/iconv](http://php.net/iconv) functions
-(short of [`ob_iconv_handler`](http://php.net/manual/en/function.ob-iconv-handler.php)).
+[php.net/iconv](https://php.net/iconv) functions
+(short of [`ob_iconv_handler`](https://php.net/ob-iconv-handler)).
 
 More information can be found in the
 [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
diff --git a/civicrm/vendor/symfony/polyfill-iconv/Resources/charset/translit.php b/civicrm/vendor/symfony/polyfill-iconv/Resources/charset/translit.php
index 829ea12759..ed59858dc4 100644
--- a/civicrm/vendor/symfony/polyfill-iconv/Resources/charset/translit.php
+++ b/civicrm/vendor/symfony/polyfill-iconv/Resources/charset/translit.php
@@ -866,6 +866,7 @@ static $data = array (
   '㋼' => '(ヰ)',
   '㋽' => '(ヱ)',
   '㋾' => '(ヲ)',
+  '㋿' => '令和',
   '㌀' => 'アパート',
   '㌁' => 'アルファ',
   '㌂' => 'アンペア',
@@ -3133,6 +3134,7 @@ static $data = array (
   '🈸' => '申',
   '🈹' => '割',
   '🈺' => '営',
+  '🈻' => '配',
   '🉀' => '〔本〕',
   '🉁' => '〔三〕',
   '🉂' => '〔二〕',
@@ -3878,6 +3880,104 @@ static $data = array (
   'ỽ' => 'v',
   'Ỿ' => 'Y',
   'ỿ' => 'y',
+  'â± ' => 'L',
+  'ⱡ' => 'l',
+  'â±¢' => 'L',
+  'â±£' => 'P',
+  'Ɽ' => 'R',
+  'â±¥' => 'a',
+  'ⱦ' => 't',
+  'Ⱨ' => 'H',
+  'ⱨ' => 'h',
+  'Ⱪ' => 'K',
+  'ⱪ' => 'k',
+  'Ⱬ' => 'Z',
+  'ⱬ' => 'z',
+  'â±®' => 'M',
+  'â±±' => 'v',
+  'â±²' => 'W',
+  'â±³' => 'w',
+  'â±´' => 'v',
+  'ⱸ' => 'e',
+  'ⱺ' => 'o',
+  'â±¾' => 'S',
+  'Ɀ' => 'Z',
+  'ꜰ' => 'F',
+  'ꜱ' => 'S',
+  'Ꜳ' => 'AA',
+  'ꜳ' => 'aa',
+  'Ꜵ' => 'AO',
+  'ꜵ' => 'ao',
+  'Ꜷ' => 'AU',
+  'ꜷ' => 'au',
+  'Ꜹ' => 'AV',
+  'ꜹ' => 'av',
+  'Ꜻ' => 'AV',
+  'ꜻ' => 'av',
+  'Ꜽ' => 'AY',
+  'ꜽ' => 'ay',
+  'Ꝁ' => 'K',
+  'ꝁ' => 'k',
+  'Ꝃ' => 'K',
+  'ꝃ' => 'k',
+  'Ꝅ' => 'K',
+  'ꝅ' => 'k',
+  'Ꝇ' => 'L',
+  'ꝇ' => 'l',
+  'Ꝉ' => 'L',
+  'ꝉ' => 'l',
+  'Ꝋ' => 'O',
+  'ꝋ' => 'o',
+  'Ꝍ' => 'O',
+  'ꝍ' => 'o',
+  'Ꝏ' => 'OO',
+  'ꝏ' => 'oo',
+  'Ꝑ' => 'P',
+  'ꝑ' => 'p',
+  'Ꝓ' => 'P',
+  'ꝓ' => 'p',
+  'Ꝕ' => 'P',
+  'ꝕ' => 'p',
+  'Ꝗ' => 'Q',
+  'ꝗ' => 'q',
+  'Ꝙ' => 'Q',
+  'ꝙ' => 'q',
+  'Ꝟ' => 'V',
+  'ꝟ' => 'v',
+  'Ꝡ' => 'VY',
+  'ꝡ' => 'vy',
+  'Ꝥ' => 'TH',
+  'ꝥ' => 'th',
+  'Ꝧ' => 'TH',
+  'ꝧ' => 'th',
+  'ꝱ' => 'd',
+  'ꝲ' => 'l',
+  'ꝳ' => 'm',
+  'ꝴ' => 'n',
+  'ꝵ' => 'r',
+  'ꝶ' => 'R',
+  'ꝷ' => 't',
+  'Ꝺ' => 'D',
+  'ꝺ' => 'd',
+  'Ꝼ' => 'F',
+  'ꝼ' => 'f',
+  'Ꞇ' => 'T',
+  'ꞇ' => 't',
+  'Ꞑ' => 'N',
+  'êž‘' => 'n',
+  'êž’' => 'C',
+  'êž“' => 'c',
+  'êž ' => 'G',
+  'êž¡' => 'g',
+  'Ꞣ' => 'K',
+  'ꞣ' => 'k',
+  'Ꞥ' => 'N',
+  'ꞥ' => 'n',
+  'Ꞧ' => 'R',
+  'ꞧ' => 'r',
+  'Ꞩ' => 'S',
+  'êž©' => 's',
+  'Ɦ' => 'H',
   '©' => '(C)',
   '®' => '(R)',
   'â‚ ' => 'CE',
@@ -3887,8 +3987,28 @@ static $data = array (
   '₧' => 'Pts',
   '₺' => 'TL',
   '₹' => 'Rs',
+  'â„—' => '(P)',
+  '℘' => 'P',
   'â„ž' => 'Rx',
   '〇' => '0',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  ' ' => ' ',
+  'ʹ' => '\'',
+  'ʺ' => '"',
+  'Ê»' => '\'',
+  'ʼ' => '\'',
+  'ʽ' => '\'',
+  'ˈ' => '\'',
+  'Ë‹' => '`',
   '‘' => '\'',
   '’' => '\'',
   '‚' => ',',
@@ -3904,6 +4024,7 @@ static $data = array (
   '»' => '>>',
   '‹' => '<',
   '›' => '>',
+  '­' => '-',
   '‐' => '-',
   '‑' => '-',
   '‒' => '-',
@@ -3912,6 +4033,12 @@ static $data = array (
   '―' => '-',
   '︱' => '-',
   '︲' => '-',
+  'Ë‚' => '<',
+  '˃' => '>',
+  'Ë„' => '^',
+  'ˆ' => '^',
+  'ː' => ':',
+  '˜' => '~',
   '‖' => '||',
   '⁄' => '/',
   '⁅' => '[',
@@ -3952,6 +4079,8 @@ static $data = array (
   '﹈' => ']',
   '×' => '*',
   '÷' => '/',
+  'Ë–' => '+',
+  'Ë—' => '-',
   '−' => '-',
   '∕' => '/',
   '∖' => '\\',
diff --git a/civicrm/vendor/symfony/polyfill-iconv/bootstrap.php b/civicrm/vendor/symfony/polyfill-iconv/bootstrap.php
index 52747329d1..14b5003a8b 100644
--- a/civicrm/vendor/symfony/polyfill-iconv/bootstrap.php
+++ b/civicrm/vendor/symfony/polyfill-iconv/bootstrap.php
@@ -11,34 +11,74 @@
 
 use Symfony\Polyfill\Iconv as p;
 
-if (!function_exists('iconv')) {
+if (extension_loaded('iconv')) {
+    return;
+}
+
+if (!defined('ICONV_IMPL')) {
     define('ICONV_IMPL', 'Symfony');
+}
+if (!defined('ICONV_VERSION')) {
     define('ICONV_VERSION', '1.0');
+}
+if (!defined('ICONV_MIME_DECODE_STRICT')) {
     define('ICONV_MIME_DECODE_STRICT', 1);
+}
+if (!defined('ICONV_MIME_DECODE_CONTINUE_ON_ERROR')) {
     define('ICONV_MIME_DECODE_CONTINUE_ON_ERROR', 2);
+}
 
+if (!function_exists('iconv')) {
     function iconv($from, $to, $s) { return p\Iconv::iconv($from, $to, $s); }
+}
+if (!function_exists('iconv_get_encoding')) {
     function iconv_get_encoding($type = 'all') { return p\Iconv::iconv_get_encoding($type); }
+}
+if (!function_exists('iconv_set_encoding')) {
     function iconv_set_encoding($type, $charset) { return p\Iconv::iconv_set_encoding($type, $charset); }
+}
+if (!function_exists('iconv_mime_encode')) {
     function iconv_mime_encode($name, $value, $pref = null) { return p\Iconv::iconv_mime_encode($name, $value, $pref); }
+}
+if (!function_exists('iconv_mime_decode_headers')) {
     function iconv_mime_decode_headers($encodedHeaders, $mode = 0, $enc = null) { return p\Iconv::iconv_mime_decode_headers($encodedHeaders, $mode, $enc); }
+}
 
-    if (extension_loaded('mbstring')) {
+if (extension_loaded('mbstring')) {
+    if (!function_exists('iconv_strlen')) {
         function iconv_strlen($s, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_strlen($s, $enc); }
+    }
+    if (!function_exists('iconv_strpos')) {
         function iconv_strpos($s, $needle, $offset = 0, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_strpos($s, $needle, $offset, $enc); }
+    }
+    if (!function_exists('iconv_strrpos')) {
         function iconv_strrpos($s, $needle, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_strrpos($s, $needle, 0, $enc); }
+    }
+    if (!function_exists('iconv_substr')) {
         function iconv_substr($s, $start, $length = 2147483647, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_substr($s, $start, $length, $enc); }
+    }
+    if (!function_exists('iconv_mime_decode')) {
         function iconv_mime_decode($encodedHeaders, $mode = 0, $enc = null) { null === $enc and $enc = p\Iconv::$internalEncoding; return mb_decode_mimeheader($encodedHeaders, $mode, $enc); }
-    } else {
+    }
+} else {
+    if (!function_exists('iconv_strlen')) {
         if (extension_loaded('xml')) {
             function iconv_strlen($s, $enc = null) { return p\Iconv::strlen1($s, $enc); }
         } else {
             function iconv_strlen($s, $enc = null) { return p\Iconv::strlen2($s, $enc); }
         }
+    }
 
+    if (!function_exists('iconv_strpos')) {
         function iconv_strpos($s, $needle, $offset = 0, $enc = null) { return p\Iconv::iconv_strpos($s, $needle, $offset, $enc); }
+    }
+    if (!function_exists('iconv_strrpos')) {
         function iconv_strrpos($s, $needle, $enc = null) { return p\Iconv::iconv_strrpos($s, $needle, $enc); }
+    }
+    if (!function_exists('iconv_substr')) {
         function iconv_substr($s, $start, $length = 2147483647, $enc = null) { return p\Iconv::iconv_substr($s, $start, $length, $enc); }
+    }
+    if (!function_exists('iconv_mime_decode')) {
         function iconv_mime_decode($encodedHeaders, $mode = 0, $enc = null) { return p\Iconv::iconv_mime_decode($encodedHeaders, $mode, $enc); }
     }
 }
diff --git a/civicrm/vendor/symfony/polyfill-iconv/composer.json b/civicrm/vendor/symfony/polyfill-iconv/composer.json
index 0c23267cbe..3df179e351 100644
--- a/civicrm/vendor/symfony/polyfill-iconv/composer.json
+++ b/civicrm/vendor/symfony/polyfill-iconv/composer.json
@@ -28,7 +28,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "1.12-dev"
+            "dev-master": "1.17-dev"
         }
     }
 }
diff --git a/civicrm/vendor/symfony/process/CHANGELOG.md b/civicrm/vendor/symfony/process/CHANGELOG.md
index 2f3c1beb74..c5cdb99441 100644
--- a/civicrm/vendor/symfony/process/CHANGELOG.md
+++ b/civicrm/vendor/symfony/process/CHANGELOG.md
@@ -1,6 +1,23 @@
 CHANGELOG
 =========
 
+3.4.0
+-----
+
+ * deprecated the ProcessBuilder class
+ * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor)
+
+3.3.0
+-----
+
+ * added command line arrays in the `Process` class
+ * added `$env` argument to `Process::start()`, `run()`, `mustRun()` and `restart()` methods
+ * deprecated the `ProcessUtils::escapeArgument()` method
+ * deprecated not inheriting environment variables
+ * deprecated configuring `proc_open()` options
+ * deprecated configuring enhanced Windows compatibility
+ * deprecated configuring enhanced sigchild compatibility
+
 2.5.0
 -----
 
diff --git a/civicrm/vendor/symfony/process/ExecutableFinder.php b/civicrm/vendor/symfony/process/ExecutableFinder.php
index ccfa4c09b0..cb4345e7bb 100644
--- a/civicrm/vendor/symfony/process/ExecutableFinder.php
+++ b/civicrm/vendor/symfony/process/ExecutableFinder.php
@@ -19,7 +19,7 @@ namespace Symfony\Component\Process;
  */
 class ExecutableFinder
 {
-    private $suffixes = array('.exe', '.bat', '.cmd', '.com');
+    private $suffixes = ['.exe', '.bat', '.cmd', '.com'];
 
     /**
      * Replaces default suffixes of executable.
@@ -42,17 +42,17 @@ class ExecutableFinder
     /**
      * Finds an executable by name.
      *
-     * @param string $name      The executable name (without the extension)
-     * @param string $default   The default to return if no executable is found
-     * @param array  $extraDirs Additional dirs to check into
+     * @param string      $name      The executable name (without the extension)
+     * @param string|null $default   The default to return if no executable is found
+     * @param array       $extraDirs Additional dirs to check into
      *
-     * @return string The executable path or default value
+     * @return string|null The executable path or default value
      */
-    public function find($name, $default = null, array $extraDirs = array())
+    public function find($name, $default = null, array $extraDirs = [])
     {
         if (ini_get('open_basedir')) {
-            $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
-            $dirs = array();
+            $searchPath = array_merge(explode(PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs);
+            $dirs = [];
             foreach ($searchPath as $path) {
                 // Silencing against https://bugs.php.net/69240
                 if (@is_dir($path)) {
@@ -70,7 +70,7 @@ class ExecutableFinder
             );
         }
 
-        $suffixes = array('');
+        $suffixes = [''];
         if ('\\' === \DIRECTORY_SEPARATOR) {
             $pathExt = getenv('PATHEXT');
             $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
diff --git a/civicrm/vendor/symfony/process/InputStream.php b/civicrm/vendor/symfony/process/InputStream.php
new file mode 100644
index 0000000000..ef38dd7bfd
--- /dev/null
+++ b/civicrm/vendor/symfony/process/InputStream.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Process;
+
+use Symfony\Component\Process\Exception\RuntimeException;
+
+/**
+ * Provides a way to continuously write to the input of a Process until the InputStream is closed.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class InputStream implements \IteratorAggregate
+{
+    /** @var callable|null */
+    private $onEmpty = null;
+    private $input = [];
+    private $open = true;
+
+    /**
+     * Sets a callback that is called when the write buffer becomes empty.
+     */
+    public function onEmpty(callable $onEmpty = null)
+    {
+        $this->onEmpty = $onEmpty;
+    }
+
+    /**
+     * Appends an input to the write buffer.
+     *
+     * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar,
+     *                                                                stream resource or \Traversable
+     */
+    public function write($input)
+    {
+        if (null === $input) {
+            return;
+        }
+        if ($this->isClosed()) {
+            throw new RuntimeException(sprintf('"%s" is closed.', static::class));
+        }
+        $this->input[] = ProcessUtils::validateInput(__METHOD__, $input);
+    }
+
+    /**
+     * Closes the write buffer.
+     */
+    public function close()
+    {
+        $this->open = false;
+    }
+
+    /**
+     * Tells whether the write buffer is closed or not.
+     */
+    public function isClosed()
+    {
+        return !$this->open;
+    }
+
+    public function getIterator()
+    {
+        $this->open = true;
+
+        while ($this->open || $this->input) {
+            if (!$this->input) {
+                yield '';
+                continue;
+            }
+            $current = array_shift($this->input);
+
+            if ($current instanceof \Iterator) {
+                foreach ($current as $cur) {
+                    yield $cur;
+                }
+            } else {
+                yield $current;
+            }
+            if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) {
+                $this->write($onEmpty($this));
+            }
+        }
+    }
+}
diff --git a/civicrm/vendor/symfony/process/LICENSE b/civicrm/vendor/symfony/process/LICENSE
index 21d7fb9e2f..9e936ec044 100644
--- a/civicrm/vendor/symfony/process/LICENSE
+++ b/civicrm/vendor/symfony/process/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2018 Fabien Potencier
+Copyright (c) 2004-2020 Fabien Potencier
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/civicrm/vendor/symfony/process/PhpExecutableFinder.php b/civicrm/vendor/symfony/process/PhpExecutableFinder.php
index 933c02b3ec..a97aa12cbf 100644
--- a/civicrm/vendor/symfony/process/PhpExecutableFinder.php
+++ b/civicrm/vendor/symfony/process/PhpExecutableFinder.php
@@ -44,7 +44,7 @@ class PhpExecutableFinder
         }
 
         // PHP_BINARY return the current sapi executable
-        if (\defined('PHP_BINARY') && PHP_BINARY && \in_array(\PHP_SAPI, array('cli', 'cli-server', 'phpdbg'), true)) {
+        if (PHP_BINARY && \in_array(\PHP_SAPI, ['cli', 'cli-server', 'phpdbg'], true)) {
             return PHP_BINARY.$args;
         }
 
@@ -66,7 +66,7 @@ class PhpExecutableFinder
             return $php;
         }
 
-        $dirs = array(PHP_BINDIR);
+        $dirs = [PHP_BINDIR];
         if ('\\' === \DIRECTORY_SEPARATOR) {
             $dirs[] = 'C:\xampp\php\\';
         }
@@ -81,7 +81,7 @@ class PhpExecutableFinder
      */
     public function findArguments()
     {
-        $arguments = array();
+        $arguments = [];
 
         if (\defined('HHVM_VERSION')) {
             $arguments[] = '--php';
diff --git a/civicrm/vendor/symfony/process/PhpProcess.php b/civicrm/vendor/symfony/process/PhpProcess.php
index 31a855d943..f0c47b285a 100644
--- a/civicrm/vendor/symfony/process/PhpProcess.php
+++ b/civicrm/vendor/symfony/process/PhpProcess.php
@@ -31,24 +31,23 @@ class PhpProcess extends Process
      * @param int         $timeout The timeout in seconds
      * @param array       $options An array of options for proc_open
      */
-    public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
+    public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = null)
     {
         $executableFinder = new PhpExecutableFinder();
-        if (false === $php = $executableFinder->find()) {
+        if (false === $php = $executableFinder->find(false)) {
             $php = null;
+        } else {
+            $php = array_merge([$php], $executableFinder->findArguments());
         }
         if ('phpdbg' === \PHP_SAPI) {
             $file = tempnam(sys_get_temp_dir(), 'dbg');
             file_put_contents($file, $script);
             register_shutdown_function('unlink', $file);
-            $php .= ' '.ProcessUtils::escapeArgument($file);
+            $php[] = $file;
             $script = null;
         }
-        if ('\\' !== \DIRECTORY_SEPARATOR && null !== $php) {
-            // exec is mandatory to deal with sending a signal to the process
-            // see https://github.com/symfony/symfony/issues/5030 about prepending
-            // command with exec
-            $php = 'exec '.$php;
+        if (null !== $options) {
+            @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
         }
 
         parent::__construct($php, $cwd, $env, $script, $timeout, $options);
@@ -65,12 +64,13 @@ class PhpProcess extends Process
     /**
      * {@inheritdoc}
      */
-    public function start($callback = null)
+    public function start(callable $callback = null/*, array $env = []*/)
     {
         if (null === $this->getCommandLine()) {
             throw new RuntimeException('Unable to find the PHP executable.');
         }
+        $env = 1 < \func_num_args() ? func_get_arg(1) : null;
 
-        parent::start($callback);
+        parent::start($callback, $env);
     }
 }
diff --git a/civicrm/vendor/symfony/process/Pipes/AbstractPipes.php b/civicrm/vendor/symfony/process/Pipes/AbstractPipes.php
index bd4a459c4a..cdffaaffe4 100644
--- a/civicrm/vendor/symfony/process/Pipes/AbstractPipes.php
+++ b/civicrm/vendor/symfony/process/Pipes/AbstractPipes.php
@@ -11,6 +11,8 @@
 
 namespace Symfony\Component\Process\Pipes;
 
+use Symfony\Component\Process\Exception\InvalidArgumentException;
+
 /**
  * @author Romain Neutron <imprec@gmail.com>
  *
@@ -18,7 +20,7 @@ namespace Symfony\Component\Process\Pipes;
  */
 abstract class AbstractPipes implements PipesInterface
 {
-    public $pipes = array();
+    public $pipes = [];
 
     private $inputBuffer = '';
     private $input;
@@ -26,11 +28,11 @@ abstract class AbstractPipes implements PipesInterface
     private $lastError;
 
     /**
-     * @param resource|null $input
+     * @param resource|string|int|float|bool|\Iterator|null $input
      */
     public function __construct($input)
     {
-        if (\is_resource($input)) {
+        if (\is_resource($input) || $input instanceof \Iterator) {
             $this->input = $input;
         } elseif (\is_string($input)) {
             $this->inputBuffer = $input;
@@ -47,7 +49,7 @@ abstract class AbstractPipes implements PipesInterface
         foreach ($this->pipes as $pipe) {
             fclose($pipe);
         }
-        $this->pipes = array();
+        $this->pipes = [];
     }
 
     /**
@@ -76,7 +78,7 @@ abstract class AbstractPipes implements PipesInterface
         foreach ($this->pipes as $pipe) {
             stream_set_blocking($pipe, 0);
         }
-        if (null !== $this->input) {
+        if (\is_resource($this->input)) {
             stream_set_blocking($this->input, 0);
         }
 
@@ -85,19 +87,44 @@ abstract class AbstractPipes implements PipesInterface
 
     /**
      * Writes input to stdin.
+     *
+     * @return array|null
+     *
+     * @throws InvalidArgumentException When an input iterator yields a non supported value
      */
     protected function write()
     {
         if (!isset($this->pipes[0])) {
-            return;
+            return null;
         }
         $input = $this->input;
-        $r = $e = array();
-        $w = array($this->pipes[0]);
+
+        if ($input instanceof \Iterator) {
+            if (!$input->valid()) {
+                $input = null;
+            } elseif (\is_resource($input = $input->current())) {
+                stream_set_blocking($input, 0);
+            } elseif (!isset($this->inputBuffer[0])) {
+                if (!\is_string($input)) {
+                    if (!is_scalar($input)) {
+                        throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', \get_class($this->input), \gettype($input)));
+                    }
+                    $input = (string) $input;
+                }
+                $this->inputBuffer = $input;
+                $this->input->next();
+                $input = null;
+            } else {
+                $input = null;
+            }
+        }
+
+        $r = $e = [];
+        $w = [$this->pipes[0]];
 
         // let's have a look if something changed in streams
         if (false === @stream_select($r, $w, $e, 0, 0)) {
-            return;
+            return null;
         }
 
         foreach ($w as $stdin) {
@@ -105,7 +132,7 @@ abstract class AbstractPipes implements PipesInterface
                 $written = fwrite($stdin, $this->inputBuffer);
                 $this->inputBuffer = substr($this->inputBuffer, $written);
                 if (isset($this->inputBuffer[0])) {
-                    return array($this->pipes[0]);
+                    return [$this->pipes[0]];
                 }
             }
 
@@ -120,24 +147,29 @@ abstract class AbstractPipes implements PipesInterface
                     if (isset($data[0])) {
                         $this->inputBuffer = $data;
 
-                        return array($this->pipes[0]);
+                        return [$this->pipes[0]];
                     }
                 }
                 if (feof($input)) {
-                    // no more data to read on input resource
-                    // use an empty buffer in the next reads
-                    $this->input = null;
+                    if ($this->input instanceof \Iterator) {
+                        $this->input->next();
+                    } else {
+                        $this->input = null;
+                    }
                 }
             }
         }
 
         // no input to read on resource, buffer is empty
-        if (null === $this->input && !isset($this->inputBuffer[0])) {
+        if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
+            $this->input = null;
             fclose($this->pipes[0]);
             unset($this->pipes[0]);
         } elseif (!$w) {
-            return array($this->pipes[0]);
+            return [$this->pipes[0]];
         }
+
+        return null;
     }
 
     /**
diff --git a/civicrm/vendor/symfony/process/Pipes/PipesInterface.php b/civicrm/vendor/symfony/process/Pipes/PipesInterface.php
index b91c393d87..52bbe76b8f 100644
--- a/civicrm/vendor/symfony/process/Pipes/PipesInterface.php
+++ b/civicrm/vendor/symfony/process/Pipes/PipesInterface.php
@@ -53,6 +53,13 @@ interface PipesInterface
      */
     public function areOpen();
 
+    /**
+     * Returns if pipes are able to read output.
+     *
+     * @return bool
+     */
+    public function haveReadSupport();
+
     /**
      * Closes file handles and pipes.
      */
diff --git a/civicrm/vendor/symfony/process/Pipes/UnixPipes.php b/civicrm/vendor/symfony/process/Pipes/UnixPipes.php
index 935c43209d..1ebf2138a5 100644
--- a/civicrm/vendor/symfony/process/Pipes/UnixPipes.php
+++ b/civicrm/vendor/symfony/process/Pipes/UnixPipes.php
@@ -24,13 +24,13 @@ class UnixPipes extends AbstractPipes
 {
     private $ttyMode;
     private $ptyMode;
-    private $disableOutput;
+    private $haveReadSupport;
 
-    public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
+    public function __construct($ttyMode, $ptyMode, $input, $haveReadSupport)
     {
         $this->ttyMode = (bool) $ttyMode;
         $this->ptyMode = (bool) $ptyMode;
-        $this->disableOutput = (bool) $disableOutput;
+        $this->haveReadSupport = (bool) $haveReadSupport;
 
         parent::__construct($input);
     }
@@ -45,37 +45,37 @@ class UnixPipes extends AbstractPipes
      */
     public function getDescriptors()
     {
-        if ($this->disableOutput) {
+        if (!$this->haveReadSupport) {
             $nullstream = fopen('/dev/null', 'c');
 
-            return array(
-                array('pipe', 'r'),
+            return [
+                ['pipe', 'r'],
                 $nullstream,
                 $nullstream,
-            );
+            ];
         }
 
         if ($this->ttyMode) {
-            return array(
-                array('file', '/dev/tty', 'r'),
-                array('file', '/dev/tty', 'w'),
-                array('file', '/dev/tty', 'w'),
-            );
+            return [
+                ['file', '/dev/tty', 'r'],
+                ['file', '/dev/tty', 'w'],
+                ['file', '/dev/tty', 'w'],
+            ];
         }
 
         if ($this->ptyMode && Process::isPtySupported()) {
-            return array(
-                array('pty'),
-                array('pty'),
-                array('pty'),
-            );
+            return [
+                ['pty'],
+                ['pty'],
+                ['pty'],
+            ];
         }
 
-        return array(
-            array('pipe', 'r'),
-            array('pipe', 'w'), // stdout
-            array('pipe', 'w'), // stderr
-        );
+        return [
+            ['pipe', 'r'],
+            ['pipe', 'w'], // stdout
+            ['pipe', 'w'], // stderr
+        ];
     }
 
     /**
@@ -83,7 +83,7 @@ class UnixPipes extends AbstractPipes
      */
     public function getFiles()
     {
-        return array();
+        return [];
     }
 
     /**
@@ -94,18 +94,18 @@ class UnixPipes extends AbstractPipes
         $this->unblock();
         $w = $this->write();
 
-        $read = $e = array();
+        $read = $e = [];
         $r = $this->pipes;
         unset($r[0]);
 
         // let's have a look if something changed in streams
-        set_error_handler(array($this, 'handleError'));
+        set_error_handler([$this, 'handleError']);
         if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
             restore_error_handler();
             // if a system call has been interrupted, forget about it, let's try again
             // otherwise, an error occurred, let's reset pipes
             if (!$this->hasSystemCallBeenInterrupted()) {
-                $this->pipes = array();
+                $this->pipes = [];
             }
 
             return $read;
@@ -138,21 +138,16 @@ class UnixPipes extends AbstractPipes
     /**
      * {@inheritdoc}
      */
-    public function areOpen()
+    public function haveReadSupport()
     {
-        return (bool) $this->pipes;
+        return $this->haveReadSupport;
     }
 
     /**
-     * Creates a new UnixPipes instance.
-     *
-     * @param Process         $process
-     * @param string|resource $input
-     *
-     * @return static
+     * {@inheritdoc}
      */
-    public static function create(Process $process, $input)
+    public function areOpen()
     {
-        return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
+        return (bool) $this->pipes;
     }
 }
diff --git a/civicrm/vendor/symfony/process/Pipes/WindowsPipes.php b/civicrm/vendor/symfony/process/Pipes/WindowsPipes.php
index 0b2a76387f..302b0509a8 100644
--- a/civicrm/vendor/symfony/process/Pipes/WindowsPipes.php
+++ b/civicrm/vendor/symfony/process/Pipes/WindowsPipes.php
@@ -17,8 +17,8 @@ use Symfony\Component\Process\Process;
 /**
  * WindowsPipes implementation uses temporary files as handles.
  *
- * @see https://bugs.php.net/bug.php?id=51800
- * @see https://bugs.php.net/bug.php?id=65650
+ * @see https://bugs.php.net/51800
+ * @see https://bugs.php.net/65650
  *
  * @author Romain Neutron <imprec@gmail.com>
  *
@@ -26,28 +26,28 @@ use Symfony\Component\Process\Process;
  */
 class WindowsPipes extends AbstractPipes
 {
-    private $files = array();
-    private $fileHandles = array();
-    private $lockHandles = array();
-    private $readBytes = array(
+    private $files = [];
+    private $fileHandles = [];
+    private $lockHandles = [];
+    private $readBytes = [
         Process::STDOUT => 0,
         Process::STDERR => 0,
-    );
-    private $disableOutput;
+    ];
+    private $haveReadSupport;
 
-    public function __construct($disableOutput, $input)
+    public function __construct($input, $haveReadSupport)
     {
-        $this->disableOutput = (bool) $disableOutput;
+        $this->haveReadSupport = (bool) $haveReadSupport;
 
-        if (!$this->disableOutput) {
+        if ($this->haveReadSupport) {
             // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
             // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
             //
-            // @see https://bugs.php.net/bug.php?id=51800
-            $pipes = array(
+            // @see https://bugs.php.net/51800
+            $pipes = [
                 Process::STDOUT => Process::OUT,
                 Process::STDERR => Process::ERR,
-            );
+            ];
             $tmpDir = sys_get_temp_dir();
             $lastError = 'unknown reason';
             set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
@@ -57,7 +57,7 @@ class WindowsPipes extends AbstractPipes
 
                     if (!$h = fopen($file.'.lock', 'w')) {
                         restore_error_handler();
-                        throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $lastError));
+                        throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError);
                     }
                     if (!flock($h, LOCK_EX | LOCK_NB)) {
                         continue 2;
@@ -95,24 +95,24 @@ class WindowsPipes extends AbstractPipes
      */
     public function getDescriptors()
     {
-        if ($this->disableOutput) {
+        if (!$this->haveReadSupport) {
             $nullstream = fopen('NUL', 'c');
 
-            return array(
-                array('pipe', 'r'),
+            return [
+                ['pipe', 'r'],
                 $nullstream,
                 $nullstream,
-            );
+            ];
         }
 
-        // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800)
-        // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650
+        // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
+        // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
         // So we redirect output within the commandline and pass the nul device to the process
-        return array(
-            array('pipe', 'r'),
-            array('file', 'NUL', 'w'),
-            array('file', 'NUL', 'w'),
-        );
+        return [
+            ['pipe', 'r'],
+            ['file', 'NUL', 'w'],
+            ['file', 'NUL', 'w'],
+        ];
     }
 
     /**
@@ -130,7 +130,7 @@ class WindowsPipes extends AbstractPipes
     {
         $this->unblock();
         $w = $this->write();
-        $read = $r = $e = array();
+        $read = $r = $e = [];
 
         if ($blocking) {
             if ($w) {
@@ -158,6 +158,14 @@ class WindowsPipes extends AbstractPipes
         return $read;
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function haveReadSupport()
+    {
+        return $this->haveReadSupport;
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -178,19 +186,6 @@ class WindowsPipes extends AbstractPipes
             flock($this->lockHandles[$type], LOCK_UN);
             fclose($this->lockHandles[$type]);
         }
-        $this->fileHandles = $this->lockHandles = array();
-    }
-
-    /**
-     * Creates a new WindowsPipes instance.
-     *
-     * @param Process $process The process
-     * @param $input
-     *
-     * @return static
-     */
-    public static function create(Process $process, $input)
-    {
-        return new static($process->isOutputDisabled(), $input);
+        $this->fileHandles = $this->lockHandles = [];
     }
 }
diff --git a/civicrm/vendor/symfony/process/Process.php b/civicrm/vendor/symfony/process/Process.php
index a261ea5340..68d52512ed 100644
--- a/civicrm/vendor/symfony/process/Process.php
+++ b/civicrm/vendor/symfony/process/Process.php
@@ -27,7 +27,7 @@ use Symfony\Component\Process\Pipes\WindowsPipes;
  * @author Fabien Potencier <fabien@symfony.com>
  * @author Romain Neutron <imprec@gmail.com>
  */
-class Process
+class Process implements \IteratorAggregate
 {
     const ERR = 'err';
     const OUT = 'out';
@@ -43,7 +43,13 @@ class Process
     // Timeout Precision in seconds.
     const TIMEOUT_PRECISION = 0.2;
 
+    const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking
+    const ITER_KEEP_OUTPUT = 2;  // By default, outputs are cleared while iterating, use this flag to keep them in memory
+    const ITER_SKIP_OUT = 4;     // Use this flag to skip STDOUT while iterating
+    const ITER_SKIP_ERR = 8;     // Use this flag to skip STDERR while iterating
+
     private $callback;
+    private $hasCallback = false;
     private $commandline;
     private $cwd;
     private $env;
@@ -52,9 +58,9 @@ class Process
     private $lastOutputTime;
     private $timeout;
     private $idleTimeout;
-    private $options;
+    private $options = ['suppress_errors' => true];
     private $exitcode;
-    private $fallbackStatus = array();
+    private $fallbackStatus = [];
     private $processInformation;
     private $outputDisabled = false;
     private $stdout;
@@ -65,8 +71,9 @@ class Process
     private $status = self::STATUS_READY;
     private $incrementalOutputOffset = 0;
     private $incrementalErrorOutputOffset = 0;
-    private $tty;
+    private $tty = false;
     private $pty;
+    private $inheritEnv = false;
 
     private $useFileHandles = false;
     /** @var PipesInterface */
@@ -81,7 +88,7 @@ class Process
      *
      * User-defined errors must use exit codes in the 64-113 range.
      */
-    public static $exitCodes = array(
+    public static $exitCodes = [
         0 => 'OK',
         1 => 'General error',
         2 => 'Misuse of shell builtins',
@@ -122,19 +129,19 @@ class Process
         157 => 'Pollable event',
         // 158 - not defined
         159 => 'Bad syscall',
-    );
+    ];
 
     /**
-     * @param string         $commandline The command line to run
+     * @param string|array   $commandline The command line to run
      * @param string|null    $cwd         The working directory or null to use the working dir of the current PHP process
      * @param array|null     $env         The environment variables or null to use the same environment as the current PHP process
-     * @param string|null    $input       The input
+     * @param mixed|null     $input       The input as stream resource, scalar or \Traversable, or null for no input
      * @param int|float|null $timeout     The timeout in seconds or null to disable
      * @param array          $options     An array of options for proc_open
      *
      * @throws RuntimeException When proc_open is not installed
      */
-    public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
+    public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = null)
     {
         if (!\function_exists('proc_open')) {
             throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
@@ -145,8 +152,8 @@ class Process
 
         // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started
         // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected
-        // @see : https://bugs.php.net/bug.php?id=51800
-        // @see : https://bugs.php.net/bug.php?id=50524
+        // @see : https://bugs.php.net/51800
+        // @see : https://bugs.php.net/50524
         if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
             $this->cwd = getcwd();
         }
@@ -159,7 +166,10 @@ class Process
         $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR;
         $this->pty = false;
         $this->enhanceSigchildCompatibility = '\\' !== \DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
-        $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
+        if (null !== $options) {
+            @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
+            $this->options = array_replace($this->options, $options);
+        }
     }
 
     public function __destruct()
@@ -190,10 +200,13 @@ class Process
      * @throws RuntimeException When process can't be launched
      * @throws RuntimeException When process stopped after receiving signal
      * @throws LogicException   In case a callback is provided and output has been disabled
+     *
+     * @final since version 3.3
      */
-    public function run($callback = null)
+    public function run($callback = null/*, array $env = []*/)
     {
-        $this->start($callback);
+        $env = 1 < \func_num_args() ? func_get_arg(1) : null;
+        $this->start($callback, $env);
 
         return $this->wait();
     }
@@ -204,20 +217,21 @@ class Process
      * This is identical to run() except that an exception is thrown if the process
      * exits with a non-zero exit code.
      *
-     * @param callable|null $callback
-     *
-     * @return self
+     * @return $this
      *
      * @throws RuntimeException       if PHP was compiled with --enable-sigchild and the enhanced sigchild compatibility mode is not enabled
      * @throws ProcessFailedException if the process didn't terminate successfully
+     *
+     * @final since version 3.3
      */
-    public function mustRun($callback = null)
+    public function mustRun(callable $callback = null/*, array $env = []*/)
     {
         if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
             throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
         }
+        $env = 1 < \func_num_args() ? func_get_arg(1) : null;
 
-        if (0 !== $this->run($callback)) {
+        if (0 !== $this->run($callback, $env)) {
             throw new ProcessFailedException($this);
         }
 
@@ -243,46 +257,86 @@ class Process
      * @throws RuntimeException When process is already running
      * @throws LogicException   In case a callback is provided and output has been disabled
      */
-    public function start($callback = null)
+    public function start(callable $callback = null/*, array $env = [*/)
     {
         if ($this->isRunning()) {
-            throw new RuntimeException('Process is already running');
+            throw new RuntimeException('Process is already running.');
         }
-        if ($this->outputDisabled && null !== $callback) {
-            throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
+        if (2 <= \func_num_args()) {
+            $env = func_get_arg(1);
+        } else {
+            if (__CLASS__ !== static::class) {
+                $r = new \ReflectionMethod($this, __FUNCTION__);
+                if (__CLASS__ !== $r->getDeclaringClass()->getName() && (2 > $r->getNumberOfParameters() || 'env' !== $r->getParameters()[1]->name)) {
+                    @trigger_error(sprintf('The %s::start() method expects a second "$env" argument since Symfony 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED);
+                }
+            }
+            $env = null;
         }
 
         $this->resetProcessData();
         $this->starttime = $this->lastOutputTime = microtime(true);
         $this->callback = $this->buildCallback($callback);
+        $this->hasCallback = null !== $callback;
         $descriptors = $this->getDescriptors();
+        $inheritEnv = $this->inheritEnv;
 
-        $commandline = $this->commandline;
+        if (\is_array($commandline = $this->commandline)) {
+            $commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline));
 
-        if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
-            $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
-            foreach ($this->processPipes->getFiles() as $offset => $filename) {
-                $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
+            if ('\\' !== \DIRECTORY_SEPARATOR) {
+                // exec is mandatory to deal with sending a signal to the process
+                $commandline = 'exec '.$commandline;
             }
-            $commandline .= '"';
+        }
 
-            if (!isset($this->options['bypass_shell'])) {
-                $this->options['bypass_shell'] = true;
+        if (null === $env) {
+            $env = $this->env;
+        } else {
+            if ($this->env) {
+                $env += $this->env;
             }
+            $inheritEnv = true;
+        }
+
+        if (null !== $env && $inheritEnv) {
+            $env += $this->getDefaultEnv();
+        } elseif (null !== $env) {
+            @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED);
+        } else {
+            $env = $this->getDefaultEnv();
+        }
+        if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
+            $this->options['bypass_shell'] = true;
+            $commandline = $this->prepareWindowsCommandLine($commandline, $env);
         } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
             // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
-            $descriptors[3] = array('pipe', 'w');
+            $descriptors[3] = ['pipe', 'w'];
 
             // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input
-            $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
+            $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
             $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
 
             // Workaround for the bug, when PTS functionality is enabled.
             // @see : https://bugs.php.net/69442
             $ptsWorkaround = fopen(__FILE__, 'r');
         }
+        if (\defined('HHVM_VERSION')) {
+            $envPairs = $env;
+        } else {
+            $envPairs = [];
+            foreach ($env as $k => $v) {
+                if (false !== $v) {
+                    $envPairs[] = $k.'='.$v;
+                }
+            }
+        }
 
-        $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
+        if (!is_dir($this->cwd)) {
+            @trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
+        }
+
+        $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
 
         if (!\is_resource($this->process)) {
             throw new RuntimeException('Unable to launch a new process.');
@@ -309,21 +363,24 @@ class Process
      * @param callable|null $callback A PHP callback to run whenever there is some
      *                                output available on STDOUT or STDERR
      *
-     * @return $this
+     * @return static
      *
      * @throws RuntimeException When process can't be launched
      * @throws RuntimeException When process is already running
      *
      * @see start()
+     *
+     * @final since version 3.3
      */
-    public function restart($callback = null)
+    public function restart(callable $callback = null/*, array $env = []*/)
     {
         if ($this->isRunning()) {
-            throw new RuntimeException('Process is already running');
+            throw new RuntimeException('Process is already running.');
         }
+        $env = 1 < \func_num_args() ? func_get_arg(1) : null;
 
         $process = clone $this;
-        $process->start($callback);
+        $process->start($callback, $env);
 
         return $process;
     }
@@ -343,12 +400,17 @@ class Process
      * @throws RuntimeException When process stopped after receiving signal
      * @throws LogicException   When process is not yet started
      */
-    public function wait($callback = null)
+    public function wait(callable $callback = null)
     {
         $this->requireProcessIsStarted(__FUNCTION__);
 
         $this->updateStatus(false);
+
         if (null !== $callback) {
+            if (!$this->processPipes->haveReadSupport()) {
+                $this->stop(0);
+                throw new \LogicException('Pass the callback to the Process::start method or enableOutput to use a callback with Process::wait.');
+            }
             $this->callback = $this->buildCallback($callback);
         }
 
@@ -359,6 +421,7 @@ class Process
         } while ($running);
 
         while ($this->isRunning()) {
+            $this->checkTimeout();
             usleep(1000);
         }
 
@@ -382,7 +445,7 @@ class Process
     /**
      * Sends a POSIX signal to the process.
      *
-     * @param int $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php)
+     * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants)
      *
      * @return $this
      *
@@ -491,6 +554,63 @@ class Process
         return $latest;
     }
 
+    /**
+     * Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR).
+     *
+     * @param int $flags A bit field of Process::ITER_* flags
+     *
+     * @throws LogicException in case the output has been disabled
+     * @throws LogicException In case the process is not started
+     *
+     * @return \Generator
+     */
+    public function getIterator($flags = 0)
+    {
+        $this->readPipesForOutput(__FUNCTION__, false);
+
+        $clearOutput = !(self::ITER_KEEP_OUTPUT & $flags);
+        $blocking = !(self::ITER_NON_BLOCKING & $flags);
+        $yieldOut = !(self::ITER_SKIP_OUT & $flags);
+        $yieldErr = !(self::ITER_SKIP_ERR & $flags);
+
+        while (null !== $this->callback || ($yieldOut && !feof($this->stdout)) || ($yieldErr && !feof($this->stderr))) {
+            if ($yieldOut) {
+                $out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
+
+                if (isset($out[0])) {
+                    if ($clearOutput) {
+                        $this->clearOutput();
+                    } else {
+                        $this->incrementalOutputOffset = ftell($this->stdout);
+                    }
+
+                    yield self::OUT => $out;
+                }
+            }
+
+            if ($yieldErr) {
+                $err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
+
+                if (isset($err[0])) {
+                    if ($clearOutput) {
+                        $this->clearErrorOutput();
+                    } else {
+                        $this->incrementalErrorOutputOffset = ftell($this->stderr);
+                    }
+
+                    yield self::ERR => $err;
+                }
+            }
+
+            if (!$blocking && !isset($out[0]) && !isset($err[0])) {
+                yield self::OUT => '';
+            }
+
+            $this->checkTimeout();
+            $this->readPipesForOutput(__FUNCTION__, $blocking);
+        }
+    }
+
     /**
      * Clears the process output.
      *
@@ -596,7 +716,7 @@ class Process
     public function getExitCodeText()
     {
         if (null === $exitcode = $this->getExitCode()) {
-            return;
+            return null;
         }
 
         return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
@@ -744,7 +864,7 @@ class Process
      * @param int|float $timeout The timeout in seconds
      * @param int       $signal  A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9)
      *
-     * @return int The exit-code of the process
+     * @return int|null The exit-code of the process or null if it's not running
      */
     public function stop($timeout = 10, $signal = null)
     {
@@ -814,15 +934,15 @@ class Process
      */
     public function getCommandLine()
     {
-        return $this->commandline;
+        return \is_array($this->commandline) ? implode(' ', array_map([$this, 'escapeArgument'], $this->commandline)) : $this->commandline;
     }
 
     /**
      * Sets the command line to be executed.
      *
-     * @param string $commandline The command to execute
+     * @param string|array $commandline The command to execute
      *
-     * @return self The current Process instance
+     * @return $this
      */
     public function setCommandLine($commandline)
     {
@@ -852,13 +972,13 @@ class Process
     }
 
     /**
-     * Sets the process timeout (max. runtime).
+     * Sets the process timeout (max. runtime) in seconds.
      *
      * To disable the timeout, set this value to null.
      *
      * @param int|float|null $timeout The timeout in seconds
      *
-     * @return self The current Process instance
+     * @return $this
      *
      * @throws InvalidArgumentException if the timeout is negative
      */
@@ -876,7 +996,7 @@ class Process
      *
      * @param int|float|null $timeout The timeout in seconds
      *
-     * @return self The current Process instance
+     * @return $this
      *
      * @throws LogicException           if the output is disabled
      * @throws InvalidArgumentException if the timeout is negative
@@ -897,7 +1017,7 @@ class Process
      *
      * @param bool $tty True to enabled and false to disable
      *
-     * @return self The current Process instance
+     * @return $this
      *
      * @throws RuntimeException In case the TTY mode is not supported
      */
@@ -910,7 +1030,7 @@ class Process
             static $isTtySupported;
 
             if (null === $isTtySupported) {
-                $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', array(array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w')), $pipes);
+                $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes);
             }
 
             if (!$isTtySupported) {
@@ -938,7 +1058,7 @@ class Process
      *
      * @param bool $bool
      *
-     * @return self
+     * @return $this
      */
     public function setPty($bool)
     {
@@ -978,7 +1098,7 @@ class Process
      *
      * @param string $cwd The new working directory
      *
-     * @return self The current Process instance
+     * @return $this
      */
     public function setWorkingDirectory($cwd)
     {
@@ -1002,13 +1122,15 @@ class Process
      *
      * Each environment variable value should be a string.
      * If it is an array, the variable is ignored.
+     * If it is false or null, it will be removed when
+     * env vars are otherwise inherited.
      *
      * That happens in PHP when 'argv' is registered into
      * the $_ENV array for instance.
      *
      * @param array $env The new environment variables
      *
-     * @return self The current Process instance
+     * @return $this
      */
     public function setEnv(array $env)
     {
@@ -1017,72 +1139,31 @@ class Process
             return !\is_array($value);
         });
 
-        $this->env = array();
-        foreach ($env as $key => $value) {
-            $this->env[$key] = (string) $value;
-        }
+        $this->env = $env;
 
         return $this;
     }
 
-    /**
-     * Gets the contents of STDIN.
-     *
-     * @return string|null The current contents
-     *
-     * @deprecated since version 2.5, to be removed in 3.0.
-     *             Use setInput() instead.
-     *             This method is deprecated in favor of getInput.
-     */
-    public function getStdin()
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the getInput() method instead.', E_USER_DEPRECATED);
-
-        return $this->getInput();
-    }
-
     /**
      * Gets the Process input.
      *
-     * @return string|null The Process input
+     * @return resource|string|\Iterator|null The Process input
      */
     public function getInput()
     {
         return $this->input;
     }
 
-    /**
-     * Sets the contents of STDIN.
-     *
-     * @param string|null $stdin The new contents
-     *
-     * @return self The current Process instance
-     *
-     * @deprecated since version 2.5, to be removed in 3.0.
-     *             Use setInput() instead.
-     *
-     * @throws LogicException           In case the process is running
-     * @throws InvalidArgumentException In case the argument is invalid
-     */
-    public function setStdin($stdin)
-    {
-        @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.5 and will be removed in 3.0. Use the setInput() method instead.', E_USER_DEPRECATED);
-
-        return $this->setInput($stdin);
-    }
-
     /**
      * Sets the input.
      *
      * This content will be passed to the underlying process standard input.
      *
-     * @param mixed $input The content
+     * @param string|int|float|bool|resource|\Traversable|null $input The content
      *
-     * @return self The current Process instance
+     * @return $this
      *
      * @throws LogicException In case the process is running
-     *
-     * Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.
      */
     public function setInput($input)
     {
@@ -1099,9 +1180,13 @@ class Process
      * Gets the options for proc_open.
      *
      * @return array The current options
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
     public function getOptions()
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
+
         return $this->options;
     }
 
@@ -1110,10 +1195,14 @@ class Process
      *
      * @param array $options The new options
      *
-     * @return self The current Process instance
+     * @return $this
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
     public function setOptions(array $options)
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
+
         $this->options = $options;
 
         return $this;
@@ -1125,9 +1214,13 @@ class Process
      * This is true by default.
      *
      * @return bool
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled.
      */
     public function getEnhanceWindowsCompatibility()
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+
         return $this->enhanceWindowsCompatibility;
     }
 
@@ -1136,10 +1229,14 @@ class Process
      *
      * @param bool $enhance
      *
-     * @return self The current Process instance
+     * @return $this
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled.
      */
     public function setEnhanceWindowsCompatibility($enhance)
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+
         $this->enhanceWindowsCompatibility = (bool) $enhance;
 
         return $this;
@@ -1149,9 +1246,13 @@ class Process
      * Returns whether sigchild compatibility mode is activated or not.
      *
      * @return bool
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Sigchild compatibility will always be enabled.
      */
     public function getEnhanceSigchildCompatibility()
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+
         return $this->enhanceSigchildCompatibility;
     }
 
@@ -1164,15 +1265,51 @@ class Process
      *
      * @param bool $enhance
      *
-     * @return self The current Process instance
+     * @return $this
+     *
+     * @deprecated since version 3.3, to be removed in 4.0.
      */
     public function setEnhanceSigchildCompatibility($enhance)
     {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED);
+
         $this->enhanceSigchildCompatibility = (bool) $enhance;
 
         return $this;
     }
 
+    /**
+     * Sets whether environment variables will be inherited or not.
+     *
+     * @param bool $inheritEnv
+     *
+     * @return $this
+     */
+    public function inheritEnvironmentVariables($inheritEnv = true)
+    {
+        if (!$inheritEnv) {
+            @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED);
+        }
+
+        $this->inheritEnv = (bool) $inheritEnv;
+
+        return $this;
+    }
+
+    /**
+     * Returns whether environment variables will be inherited or not.
+     *
+     * @return bool
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Environment variables will always be inherited.
+     */
+    public function areEnvironmentVariablesInherited()
+    {
+        @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Environment variables will always be inherited.', __METHOD__), E_USER_DEPRECATED);
+
+        return $this->inheritEnv;
+    }
+
     /**
      * Performs a check between the timeout definition and the time the process started.
      *
@@ -1217,7 +1354,7 @@ class Process
             return $result = false;
         }
 
-        return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
+        return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes);
     }
 
     /**
@@ -1227,10 +1364,13 @@ class Process
      */
     private function getDescriptors()
     {
+        if ($this->input instanceof \Iterator) {
+            $this->input->rewind();
+        }
         if ('\\' === \DIRECTORY_SEPARATOR) {
-            $this->processPipes = WindowsPipes::create($this, $this->input);
+            $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback);
         } else {
-            $this->processPipes = UnixPipes::create($this, $this->input);
+            $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback);
         }
 
         return $this->processPipes->getDescriptors();
@@ -1246,23 +1386,29 @@ class Process
      *
      * @return \Closure A PHP closure
      */
-    protected function buildCallback($callback)
+    protected function buildCallback(callable $callback = null)
     {
-        $that = $this;
+        if ($this->outputDisabled) {
+            return function ($type, $data) use ($callback) {
+                if (null !== $callback) {
+                    \call_user_func($callback, $type, $data);
+                }
+            };
+        }
+
         $out = self::OUT;
-        $callback = function ($type, $data) use ($that, $callback, $out) {
+
+        return function ($type, $data) use ($callback, $out) {
             if ($out == $type) {
-                $that->addOutput($data);
+                $this->addOutput($data);
             } else {
-                $that->addErrorOutput($data);
+                $this->addErrorOutput($data);
             }
 
             if (null !== $callback) {
                 \call_user_func($callback, $type, $data);
             }
         };
-
-        return $callback;
     }
 
     /**
@@ -1314,11 +1460,12 @@ class Process
     /**
      * Reads pipes for the freshest output.
      *
-     * @param string $caller The name of the method that needs fresh outputs
+     * @param string $caller   The name of the method that needs fresh outputs
+     * @param bool   $blocking Whether to use blocking calls or not
      *
      * @throws LogicException in case output has been disabled or process is not started
      */
-    private function readPipesForOutput($caller)
+    private function readPipesForOutput($caller, $blocking = false)
     {
         if ($this->outputDisabled) {
             throw new LogicException('Output has been disabled.');
@@ -1326,7 +1473,7 @@ class Process
 
         $this->requireProcessIsStarted($caller);
 
-        $this->updateStatus(false);
+        $this->updateStatus($blocking);
     }
 
     /**
@@ -1411,7 +1558,7 @@ class Process
         $this->starttime = null;
         $this->callback = null;
         $this->exitcode = null;
-        $this->fallbackStatus = array();
+        $this->fallbackStatus = [];
         $this->processInformation = null;
         $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
         $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
@@ -1425,7 +1572,7 @@ class Process
     /**
      * Sends a POSIX signal to the process.
      *
-     * @param int  $signal         A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php)
+     * @param int  $signal         A valid POSIX signal (see https://php.net/pcntl.constants)
      * @param bool $throwException Whether to throw exception in case signal failed
      *
      * @return bool True if the signal was sent successfully, false otherwise
@@ -1458,7 +1605,7 @@ class Process
                 $ok = @proc_terminate($this->process, $signal);
             } elseif (\function_exists('posix_kill')) {
                 $ok = @posix_kill($pid, $signal);
-            } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
+            } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {
                 $ok = false === fgets($pipes[2]);
             }
             if (!$ok) {
@@ -1478,6 +1625,52 @@ class Process
         return true;
     }
 
+    private function prepareWindowsCommandLine($cmd, array &$env)
+    {
+        $uid = uniqid('', true);
+        $varCount = 0;
+        $varCache = [];
+        $cmd = preg_replace_callback(
+            '/"(?:(
+                [^"%!^]*+
+                (?:
+                    (?: !LF! | "(?:\^[%!^])?+" )
+                    [^"%!^]*+
+                )++
+            ) | [^"]*+ )"/x',
+            function ($m) use (&$env, &$varCache, &$varCount, $uid) {
+                if (!isset($m[1])) {
+                    return $m[0];
+                }
+                if (isset($varCache[$m[0]])) {
+                    return $varCache[$m[0]];
+                }
+                if (false !== strpos($value = $m[1], "\0")) {
+                    $value = str_replace("\0", '?', $value);
+                }
+                if (false === strpbrk($value, "\"%!\n")) {
+                    return '"'.$value.'"';
+                }
+
+                $value = str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value);
+                $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"';
+                $var = $uid.++$varCount;
+
+                $env[$var] = $value;
+
+                return $varCache[$m[0]] = '!'.$var.'!';
+            },
+            $cmd
+        );
+
+        $cmd = 'cmd /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')';
+        foreach ($this->processPipes->getFiles() as $offset => $filename) {
+            $cmd .= ' '.$offset.'>"'.$filename.'"';
+        }
+
+        return $cmd;
+    }
+
     /**
      * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
      *
@@ -1488,7 +1681,7 @@ class Process
     private function requireProcessIsStarted($functionName)
     {
         if (!$this->isStarted()) {
-            throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
+            throw new LogicException(sprintf('Process must be started before calling "%s()".', $functionName));
         }
     }
 
@@ -1502,7 +1695,52 @@ class Process
     private function requireProcessIsTerminated($functionName)
     {
         if (!$this->isTerminated()) {
-            throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
+            throw new LogicException(sprintf('Process must be terminated before calling "%s()".', $functionName));
+        }
+    }
+
+    /**
+     * Escapes a string to be used as a shell argument.
+     *
+     * @param string $argument The argument that will be escaped
+     *
+     * @return string The escaped argument
+     */
+    private function escapeArgument($argument)
+    {
+        if ('\\' !== \DIRECTORY_SEPARATOR) {
+            return "'".str_replace("'", "'\\''", $argument)."'";
+        }
+        if ('' === $argument = (string) $argument) {
+            return '""';
+        }
+        if (false !== strpos($argument, "\0")) {
+            $argument = str_replace("\0", '?', $argument);
+        }
+        if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) {
+            return $argument;
+        }
+        $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument);
+
+        return '"'.str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument).'"';
+    }
+
+    private function getDefaultEnv()
+    {
+        $env = [];
+
+        foreach ($_SERVER as $k => $v) {
+            if (\is_string($v) && false !== $v = getenv($k)) {
+                $env[$k] = $v;
+            }
         }
+
+        foreach ($_ENV as $k => $v) {
+            if (\is_string($v)) {
+                $env[$k] = $v;
+            }
+        }
+
+        return $env;
     }
 }
diff --git a/civicrm/vendor/symfony/process/ProcessBuilder.php b/civicrm/vendor/symfony/process/ProcessBuilder.php
index 1bac780d63..69d13c3f1b 100644
--- a/civicrm/vendor/symfony/process/ProcessBuilder.php
+++ b/civicrm/vendor/symfony/process/ProcessBuilder.php
@@ -11,28 +11,32 @@
 
 namespace Symfony\Component\Process;
 
+@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the Process class instead.', ProcessBuilder::class), E_USER_DEPRECATED);
+
 use Symfony\Component\Process\Exception\InvalidArgumentException;
 use Symfony\Component\Process\Exception\LogicException;
 
 /**
  * @author Kris Wallsmith <kris@symfony.com>
+ *
+ * @deprecated since version 3.4, to be removed in 4.0. Use the Process class instead.
  */
 class ProcessBuilder
 {
     private $arguments;
     private $cwd;
-    private $env = array();
+    private $env = [];
     private $input;
     private $timeout = 60;
-    private $options = array();
+    private $options;
     private $inheritEnv = true;
-    private $prefix = array();
+    private $prefix = [];
     private $outputDisabled = false;
 
     /**
      * @param string[] $arguments An array of arguments
      */
-    public function __construct(array $arguments = array())
+    public function __construct(array $arguments = [])
     {
         $this->arguments = $arguments;
     }
@@ -44,7 +48,7 @@ class ProcessBuilder
      *
      * @return static
      */
-    public static function create(array $arguments = array())
+    public static function create(array $arguments = [])
     {
         return new static($arguments);
     }
@@ -74,7 +78,7 @@ class ProcessBuilder
      */
     public function setPrefix($prefix)
     {
-        $this->prefix = \is_array($prefix) ? $prefix : array($prefix);
+        $this->prefix = \is_array($prefix) ? $prefix : [$prefix];
 
         return $this;
     }
@@ -163,13 +167,11 @@ class ProcessBuilder
     /**
      * Sets the input of the process.
      *
-     * @param mixed $input The input as a string
+     * @param resource|string|int|float|bool|\Traversable|null $input The input content
      *
      * @return $this
      *
      * @throws InvalidArgumentException In case the argument is invalid
-     *
-     * Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.
      */
     public function setInput($input)
     {
@@ -260,20 +262,15 @@ class ProcessBuilder
             throw new LogicException('You must add() command arguments before calling getProcess().');
         }
 
-        $options = $this->options;
-
         $arguments = array_merge($this->prefix, $this->arguments);
-        $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
+        $process = new Process($arguments, $this->cwd, $this->env, $this->input, $this->timeout, $this->options);
+        // to preserve the BC with symfony <3.3, we convert the array structure
+        // to a string structure to avoid the prefixing with the exec command
+        $process->setCommandLine($process->getCommandLine());
 
         if ($this->inheritEnv) {
-            // include $_ENV for BC purposes
-            $env = array_replace($_ENV, $_SERVER, $this->env);
-        } else {
-            $env = $this->env;
+            $process->inheritEnvironmentVariables();
         }
-
-        $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
-
         if ($this->outputDisabled) {
             $process->disableOutput();
         }
diff --git a/civicrm/vendor/symfony/process/ProcessUtils.php b/civicrm/vendor/symfony/process/ProcessUtils.php
index 21e6471c06..74f2d8654a 100644
--- a/civicrm/vendor/symfony/process/ProcessUtils.php
+++ b/civicrm/vendor/symfony/process/ProcessUtils.php
@@ -35,13 +35,17 @@ class ProcessUtils
      * @param string $argument The argument that will be escaped
      *
      * @return string The escaped argument
+     *
+     * @deprecated since version 3.3, to be removed in 4.0. Use a command line array or give env vars to the `Process::start/run()` method instead.
      */
     public static function escapeArgument($argument)
     {
+        @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use a command line array or give env vars to the Process::start/run() method instead.', E_USER_DEPRECATED);
+
         //Fix for PHP bug #43784 escapeshellarg removes % from given string
         //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
-        //@see https://bugs.php.net/bug.php?id=43784
-        //@see https://bugs.php.net/bug.php?id=49446
+        //@see https://bugs.php.net/43784
+        //@see https://bugs.php.net/49446
         if ('\\' === \DIRECTORY_SEPARATOR) {
             if ('' === $argument) {
                 return escapeshellarg($argument);
@@ -83,8 +87,6 @@ class ProcessUtils
      * @return mixed The validated input
      *
      * @throws InvalidArgumentException In case the input is not valid
-     *
-     * Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.
      */
     public static function validateInput($caller, $input)
     {
@@ -98,14 +100,17 @@ class ProcessUtils
             if (is_scalar($input)) {
                 return (string) $input;
             }
-            // deprecated as of Symfony 2.5, to be removed in 3.0
-            if (\is_object($input) && method_exists($input, '__toString')) {
-                @trigger_error('Passing an object as an input is deprecated since Symfony 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
-
-                return (string) $input;
+            if ($input instanceof Process) {
+                return $input->getIterator($input::ITER_SKIP_ERR);
+            }
+            if ($input instanceof \Iterator) {
+                return $input;
+            }
+            if ($input instanceof \Traversable) {
+                return new \IteratorIterator($input);
             }
 
-            throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
+            throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
         }
 
         return $input;
diff --git a/civicrm/vendor/symfony/process/composer.json b/civicrm/vendor/symfony/process/composer.json
index b3cb5186fc..b8867db368 100644
--- a/civicrm/vendor/symfony/process/composer.json
+++ b/civicrm/vendor/symfony/process/composer.json
@@ -16,7 +16,7 @@
         }
     ],
     "require": {
-        "php": ">=5.3.9"
+        "php": "^5.5.9|>=7.0.8"
     },
     "autoload": {
         "psr-4": { "Symfony\\Component\\Process\\": "" },
@@ -27,7 +27,7 @@
     "minimum-stability": "dev",
     "extra": {
         "branch-alias": {
-            "dev-master": "2.8-dev"
+            "dev-master": "3.4-dev"
         }
     }
 }
diff --git a/civicrm/xml/schema/Contribute/Contribution.xml b/civicrm/xml/schema/Contribute/Contribution.xml
index d2f5593b3d..ad1656a1be 100644
--- a/civicrm/xml/schema/Contribute/Contribution.xml
+++ b/civicrm/xml/schema/Contribute/Contribution.xml
@@ -14,6 +14,9 @@
     <import>true</import>
     <title>Contribution ID</title>
     <comment>Contribution ID</comment>
+    <html>
+      <type>Text</type>
+    </html>
     <add>1.3</add>
   </field>
   <primaryKey>
diff --git a/civicrm/xml/schema/Contribute/ContributionRecur.xml b/civicrm/xml/schema/Contribute/ContributionRecur.xml
index 3ac72066ca..d5295ff455 100644
--- a/civicrm/xml/schema/Contribute/ContributionRecur.xml
+++ b/civicrm/xml/schema/Contribute/ContributionRecur.xml
@@ -41,7 +41,7 @@
     <title>Amount</title>
     <type>decimal</type>
     <required>true</required>
-    <comment>Amount to be contributed or charged each recurrence.</comment>
+    <comment>Amount to be collected (including any sales tax) by payment processor each recurrence.</comment>
     <add>1.6</add>
     <html>
       <type>Text</type>
diff --git a/civicrm/xml/schema/Core/CustomField.xml b/civicrm/xml/schema/Core/CustomField.xml
index 0db6507227..2bfd28999a 100644
--- a/civicrm/xml/schema/Core/CustomField.xml
+++ b/civicrm/xml/schema/Core/CustomField.xml
@@ -281,6 +281,17 @@
     <add>5.6</add>
     <onDelete>SET NULL</onDelete>
   </foreignKey>
+  <field>
+    <name>serialize</name>
+    <type>int unsigned</type>
+    <title>Serialize</title>
+    <length>255</length>
+    <comment>Serialization method - a non-null value indicates a multi-valued field.</comment>
+    <pseudoconstant>
+      <callback>CRM_Core_SelectValues::fieldSerialization</callback>
+    </pseudoconstant>
+    <add>5.27</add>
+  </field>
   <field>
     <name>filter</name>
     <type>varchar</type>
diff --git a/civicrm/xml/schema/Core/OptionValue.xml b/civicrm/xml/schema/Core/OptionValue.xml
index f3a767d064..ce81cc6822 100644
--- a/civicrm/xml/schema/Core/OptionValue.xml
+++ b/civicrm/xml/schema/Core/OptionValue.xml
@@ -82,7 +82,7 @@
   <field>
     <name>filter</name>
     <type>int unsigned</type>
-    <default>NULL</default>
+    <default>0</default>
     <comment>Bitwise logic can be used to create subsets of options within an option_group for different uses.</comment>
     <add>1.5</add>
   </field>
diff --git a/civicrm/xml/schema/Mailing/MailingAB.xml b/civicrm/xml/schema/Mailing/MailingAB.xml
index 8bacee1aa7..14d224f98c 100644
--- a/civicrm/xml/schema/Mailing/MailingAB.xml
+++ b/civicrm/xml/schema/Mailing/MailingAB.xml
@@ -62,6 +62,7 @@
     <title>Domain ID</title>
     <comment>Which site is this mailing for</comment>
     <add>4.6</add>
+    <required>true</required>
   </field>
   <field>
     <name>testing_criteria</name>
diff --git a/civicrm/xml/schema/Member/MembershipType.xml b/civicrm/xml/schema/Member/MembershipType.xml
index 47a6230548..0007eefaf2 100644
--- a/civicrm/xml/schema/Member/MembershipType.xml
+++ b/civicrm/xml/schema/Member/MembershipType.xml
@@ -43,6 +43,7 @@
     <uniqueName>membership_type</uniqueName>
     <title>Membership Type</title>
     <type>varchar</type>
+    <required>true</required>
     <import>true</import>
     <length>128</length>
     <localizable>true</localizable>
diff --git a/civicrm/xml/schema/Price/PriceField.xml b/civicrm/xml/schema/Price/PriceField.xml
index c3ac6dd662..0c2c1af3c1 100644
--- a/civicrm/xml/schema/Price/PriceField.xml
+++ b/civicrm/xml/schema/Price/PriceField.xml
@@ -27,6 +27,7 @@
     <pseudoconstant>
       <table>civicrm_price_set</table>
       <keyColumn>id</keyColumn>
+      <nameColumn>name</nameColumn>
       <labelColumn>title</labelColumn>
     </pseudoconstant>
     <add>1.8</add>
diff --git a/civicrm/xml/schema/Price/PriceFieldValue.xml b/civicrm/xml/schema/Price/PriceFieldValue.xml
index 2740ab2e64..74c649b916 100644
--- a/civicrm/xml/schema/Price/PriceFieldValue.xml
+++ b/civicrm/xml/schema/Price/PriceFieldValue.xml
@@ -37,6 +37,7 @@
     <title>Name</title>
     <length>255</length>
     <comment>Price field option name</comment>
+    <required>true</required>
     <html>
       <type>Text</type>
     </html>
@@ -49,6 +50,7 @@
     <length>255</length>
     <localizable>true</localizable>
     <comment>Price field option label</comment>
+    <required>true</required>
     <html>
       <type>Text</type>
     </html>
diff --git a/civicrm/xml/templates/civicrm_state_province.tpl b/civicrm/xml/templates/civicrm_state_province.tpl
index f2a7496abe..a51b0e0be8 100644
--- a/civicrm/xml/templates/civicrm_state_province.tpl
+++ b/civicrm/xml/templates/civicrm_state_province.tpl
@@ -119,6 +119,7 @@ INSERT INTO civicrm_state_province (id, country_id, abbreviation, name) VALUES
 (1231, 1101, "DL", "Delhi"),
 (1232, 1101, "LD", "Lakshadweep"),
 (1233, 1101, "PY", "Pondicherry"),
+-- Note we believe all lower-case is correct for Poland. See https://github.com/civicrm/civicrm-core/pull/17107
 (1300, 1172, "MZ", "mazowieckie"),
 (1301, 1172, "PM", "pomorskie"),
 (1302, 1172, "DS", "dolnośląskie"),
diff --git a/civicrm/xml/version.xml b/civicrm/xml/version.xml
index 9a71db3eb8..16b756763f 100644
--- a/civicrm/xml/version.xml
+++ b/civicrm/xml/version.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="iso-8859-1" ?>
 <version>
-  <version_no>5.26.2</version_no>
+  <version_no>5.27.0</version_no>
 </version>
diff --git a/readme.txt b/readme.txt
index 0cfdc42e91..926e9dddb3 100755
--- a/readme.txt
+++ b/readme.txt
@@ -1,9 +1,9 @@
 === CiviCRM ===
 Contributors: needle
 Tags: civicrm, crm
-Requires at least: 3.4
-Tested up to: 4.0
-Stable tag: 4.7
+Requires at least: 4.9
+Tested up to: 5.5
+Stable tag: 5.26.1
 License: AGPL3
 License URI: http://www.gnu.org/licenses/agpl-3.0.html
 
@@ -27,7 +27,7 @@ CiviCRM is localized in over 20 languages including: Chinese (Taiwan, China), Du
 == Installation ==
 
 1. Download CiviCRM for WordPress from the [CiviCRM website](https://civicrm.org/download)
-1. Extract the plugin archive 
+1. Extract the plugin archive
 1. Upload plugin files to your plugins directory, normally `/wp-content/plugins/`
 1. Follow the instructions on the [CiviCRM website](http://wiki.civicrm.org/confluence/display/CRMDOC/WordPress+Installation+Guide+for+CiviCRM+4.5)
 
@@ -35,12 +35,4 @@ CiviCRM is localized in over 20 languages including: Chinese (Taiwan, China), Du
 
 == Changelog ==
 
-= 4.5 =
-Support for CiviCRM version 4.5.x
-
-= 4.4 =
-Support for CiviCRM version 4.4.x
-
-= 4.3 =
-Support for CiviCRM version 4.3.x
-
+[Full Release Notes](https://github.com/civicrm/civicrm-core/blob/master/release-notes.md)
diff --git a/wp-rest/Civi/Mailing-Hooks.php b/wp-rest/Civi/Mailing-Hooks.php
index 339ab5ecca..e7c2bd3817 100644
--- a/wp-rest/Civi/Mailing-Hooks.php
+++ b/wp-rest/Civi/Mailing-Hooks.php
@@ -80,12 +80,14 @@ class Mailing_Hooks {
 		if ( $path == 'extern/url' ) {
 			$url = $url
 				->withHost( $this->parsed_rest_url['host'] )
+				->withQuery( $query )
 				->withPath( "{$this->parsed_rest_url['path']}civicrm/v3/url" );
 		}
 
 		if ( $path == 'extern/open' ) {
 			$url = $url
 				->withHost( $this->parsed_rest_url['host'] )
+				->withQuery( $query )
 				->withPath( "{$this->parsed_rest_url['path']}civicrm/v3/open" );
 		}
 
-- 
GitLab