diff --git a/.travis.yml b/.travis.yml
index a99b22b1ebd4f..e078e89011dc6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,6 @@
+sudo: required
+dist: trusty
+
language: php
php:
- 5.5
@@ -44,12 +47,10 @@ before_script:
# Install MySQL 5.6, create DB for integration tests
- >
sh -c "if [ '$TEST_SUITE' = 'integration_part_1' ] || [ '$TEST_SUITE' = 'integration_part_2' ] || [ '$TEST_SUITE' = 'integration_integrity' ]; then
- sudo apt-get remove --purge mysql-common mysql-server-5.5 mysql-server-core-5.5 mysql-client-5.5 mysql-client-core-5.5;
- sudo apt-get autoremove;
- sudo apt-get autoclean;
- sudo apt-add-repository ppa:ondrej/mysql-5.6 -y;
- sudo apt-get update;
- sudo apt-get install mysql-server-5.6 mysql-client-5.6;
+ sudo apt-get remove -y -qq --purge mysql-common mysql-server-5.5 mysql-server-core-5.5 mysql-client-5.5 mysql-client-core-5.5;
+ sudo apt-get -y -qq autoremove;
+ sudo apt-get -y -qq autoclean;
+ sudo apt-get install -y -qq mysql-server-5.6 mysql-client-5.6;
mysql -uroot -e 'SET @@global.sql_mode = NO_ENGINE_SUBSTITUTION; CREATE DATABASE magento_integration_tests;';
mv dev/tests/integration/etc/install-config-mysql.travis.php.dist dev/tests/integration/etc/install-config-mysql.php;
fi"
diff --git a/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Cctypes.php b/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Cctypes.php
index a4f1da1a7ba6c..87a7870abf79e 100644
--- a/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Cctypes.php
+++ b/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Cctypes.php
@@ -11,7 +11,6 @@
/**
* Class Cctypes
- * @package Magento\BraintreeTwo\Block\Adminhtml\Form\Field
*/
class Cctypes extends Select
{
diff --git a/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Countries.php b/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Countries.php
index 10aea6da09efe..ae3ac5809d4ed 100644
--- a/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Countries.php
+++ b/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/Countries.php
@@ -11,7 +11,6 @@
/**
* Class Countries
- * @package Magento\BraintreeTwo\Block\Adminhtml\Form\Field
*/
class Countries extends Select
{
diff --git a/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/CountryCreditCard.php b/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/CountryCreditCard.php
index 332e0d90efaf1..1b2b46d015169 100644
--- a/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/CountryCreditCard.php
+++ b/app/code/Magento/BraintreeTwo/Block/Adminhtml/Form/Field/CountryCreditCard.php
@@ -10,7 +10,6 @@
/**
* Class CountryCreditCard
- * @package Magento\BraintreeTwo\Block\Adminhtml\Form\Field
*/
class CountryCreditCard extends AbstractFieldArray
{
diff --git a/app/code/Magento/BraintreeTwo/Block/Form.php b/app/code/Magento/BraintreeTwo/Block/Form.php
index 278b7490b863d..88f7ef3672b8e 100644
--- a/app/code/Magento/BraintreeTwo/Block/Form.php
+++ b/app/code/Magento/BraintreeTwo/Block/Form.php
@@ -14,7 +14,6 @@
/**
* Class Form
- * @package Magento\BraintreeTwo\Block
*/
class Form extends Cc
{
diff --git a/app/code/Magento/BraintreeTwo/Block/Info.php b/app/code/Magento/BraintreeTwo/Block/Info.php
index b18032b805a3d..60127f446b822 100644
--- a/app/code/Magento/BraintreeTwo/Block/Info.php
+++ b/app/code/Magento/BraintreeTwo/Block/Info.php
@@ -10,7 +10,6 @@
/**
* Class Info
- * @package Magento\BraintreeTwo\Block
*/
class Info extends ConfigurableInfo
{
diff --git a/app/code/Magento/BraintreeTwo/Controller/Payment/GetNonce.php b/app/code/Magento/BraintreeTwo/Controller/Payment/GetNonce.php
new file mode 100644
index 0000000000000..b7647971cb6a3
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Controller/Payment/GetNonce.php
@@ -0,0 +1,89 @@
+logger = $logger;
+ $this->session = $session;
+ $this->command = $command;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute()
+ {
+ $response = $this->resultFactory->create(ResultFactory::TYPE_JSON);
+
+ try {
+ $publicHash = $this->getRequest()->getParam('public_hash');
+ $customerId = $this->session->getCustomerId();
+ $result = $this->command->execute(['publicHash' => $publicHash, 'customerId' => $customerId])
+ ->get();
+ $response->setData(['paymentMethodNonce' => $result['paymentMethodNonce']]);
+
+ } catch (\Exception $e) {
+ $this->logger->critical($e);
+ return $this->processBadRequest($response);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Return response for bad request
+ * @param ResultInterface $response
+ * @return ResultInterface
+ */
+ private function processBadRequest(ResultInterface $response)
+ {
+ $response->setHttpResponseCode(Exception::HTTP_BAD_REQUEST);
+ $response->setData(['message' => __('Sorry, but something went wrong')]);
+
+ return $response;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Controller/Token/GetClientToken.php b/app/code/Magento/BraintreeTwo/Controller/Token/GetClientToken.php
deleted file mode 100644
index d5291178887e3..0000000000000
--- a/app/code/Magento/BraintreeTwo/Controller/Token/GetClientToken.php
+++ /dev/null
@@ -1,75 +0,0 @@
-logger = $logger;
- $this->config = $config;
- }
-
- /**
- * @inheritdoc
- */
- public function execute()
- {
- $controllerResult = $this->resultFactory->create(ResultFactory::TYPE_JSON);
-
- try {
- $controllerResult->setData(['client_token' => $this->config->getClientToken()]);
- } catch (\Exception $e) {
- $this->logger->critical($e);
- return $this->getErrorResponse($controllerResult);
- }
-
- return $controllerResult;
- }
-
- /**
- * @param ResultInterface $controllerResult
- * @return ResultInterface
- */
- private function getErrorResponse(ResultInterface $controllerResult)
- {
- $controllerResult->setHttpResponseCode(Exception::HTTP_BAD_REQUEST);
- $controllerResult->setData(['message' => __('Sorry, but something went wrong')]);
-
- return $controllerResult;
- }
-}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Command/CaptureStrategyCommand.php b/app/code/Magento/BraintreeTwo/Gateway/Command/CaptureStrategyCommand.php
new file mode 100644
index 0000000000000..1743916bf5847
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Command/CaptureStrategyCommand.php
@@ -0,0 +1,144 @@
+commandPool = $commandPool;
+ $this->transactionRepository = $repository;
+ $this->filterBuilder = $filterBuilder;
+ $this->searchCriteriaBuilder = $searchCriteriaBuilder;
+ $this->subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(array $commandSubject)
+ {
+ /** @var \Magento\Payment\Gateway\Data\PaymentDataObjectInterface $paymentDO */
+ $paymentDO = $this->subjectReader->readPayment($commandSubject);
+
+ /** @var \Magento\Sales\Api\Data\OrderPaymentInterface $paymentInfo */
+ $paymentInfo = $paymentDO->getPayment();
+ ContextHelper::assertOrderPayment($paymentInfo);
+
+ $command = $this->getCommand($paymentInfo);
+ return $this->commandPool->get($command)->execute($commandSubject);
+ }
+
+ /**
+ * Get execution command name
+ * @param OrderPaymentInterface $payment
+ * @return string
+ */
+ private function getCommand(OrderPaymentInterface $payment)
+ {
+ // if auth transaction is not exists execute authorize&capture command
+ if (!$payment->getAuthorizationTransaction()) {
+ return self::SALE;
+ }
+
+ if (!$this->isExistsCaptureTransaction($payment)) {
+ return self::CAPTURE;
+ }
+
+ return self::CLONE_TRANSACTION;
+ }
+
+ /**
+ * Check if capture transaction already exists
+ *
+ * @param OrderPaymentInterface $payment
+ * @return bool
+ */
+ private function isExistsCaptureTransaction(OrderPaymentInterface $payment)
+ {
+ $filters[] = $this->filterBuilder->setField('payment_id')
+ ->setValue($payment->getId())
+ ->create();
+
+ $filters[] = $this->filterBuilder->setField('txn_type')
+ ->setValue(TransactionInterface::TYPE_CAPTURE)
+ ->create();
+
+ $searchCriteria = $this->searchCriteriaBuilder->addFilters($filters)
+ ->create();
+
+ $count = $this->transactionRepository->getList($searchCriteria)->getTotalCount();
+ return (boolean) $count;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Command/GetPaymentNonceCommand.php b/app/code/Magento/BraintreeTwo/Gateway/Command/GetPaymentNonceCommand.php
new file mode 100644
index 0000000000000..dea64cafb6f6d
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Command/GetPaymentNonceCommand.php
@@ -0,0 +1,92 @@
+tokenManagement = $tokenManagement;
+ $this->adapter = $adapter;
+ $this->resultFactory = $resultFactory;
+ $this->subjectReader = $subjectReader;
+ $this->responseValidator = $responseValidator;
+ }
+
+ /**
+ * @inheritdoc
+ * @throws \Exception
+ */
+ public function execute(array $commandSubject)
+ {
+ $publicHash = $this->subjectReader->readPublicHash($commandSubject);
+ $customerId = $this->subjectReader->readCustomerId($commandSubject);
+ $paymentToken = $this->tokenManagement->getByPublicHash($publicHash, $customerId);
+ if (!$paymentToken) {
+ throw new Exception('No available payment tokens');
+ }
+
+ $data = $this->adapter->createNonce($paymentToken->getGatewayToken());
+ $result = $this->responseValidator->validate(['response' => ['object' => $data]]);
+
+ if (!$result->isValid()) {
+ throw new Exception(__(implode("\n", $result->getFailsDescription())));
+ }
+
+ return $this->resultFactory->create(['array' => ['paymentMethodNonce' => $data->paymentMethodNonce->nonce]]);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Config/Config.php b/app/code/Magento/BraintreeTwo/Gateway/Config/Config.php
index 651eef51162b4..ca32693b0bf52 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Config/Config.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Config/Config.php
@@ -5,14 +5,8 @@
*/
namespace Magento\BraintreeTwo\Gateway\Config;
-use Magento\Framework\App\Config\ScopeConfigInterface;
-use Magento\BraintreeTwo\Model\Adapter\BraintreeConfiguration;
-use Magento\BraintreeTwo\Model\Adapter\BraintreeClientToken;
-use Magento\BraintreeTwo\Model\Adminhtml\Source\Environment;
-
/**
* Class Config
- * @package Magento\BraintreeTwo\Gateway\Config
*/
class Config extends \Magento\Payment\Gateway\Config\Config
{
@@ -27,80 +21,14 @@ class Config extends \Magento\Payment\Gateway\Config\Config
const KEY_CC_TYPES_BRAINTREE_MAPPER = 'cctypes_braintree_mapper';
const KEY_SDK_URL = 'sdk_url';
const KEY_USE_CVV = 'useccv';
-
- /**
- * @var string
- */
- private $clientToken = '';
-
- /**
- * @var BraintreeConfiguration
- */
- private $braintreeConfiguration;
-
- /**
- * @var BraintreeClientToken
- */
- private $braintreeClientToken;
-
- /**
- * @param ScopeConfigInterface $scopeConfig
- * @param BraintreeConfiguration $braintreeConfiguration
- * @param BraintreeClientToken $braintreeClientToken
- * @param string $methodCode
- * @param string $pathPattern
- */
- public function __construct(
- ScopeConfigInterface $scopeConfig,
- BraintreeConfiguration $braintreeConfiguration,
- BraintreeClientToken $braintreeClientToken,
- $methodCode = '',
- $pathPattern = self::DEFAULT_PATH_PATTERN
- ) {
- parent::__construct(
- $scopeConfig,
- $methodCode,
- $pathPattern
- );
-
- $this->braintreeConfiguration = $braintreeConfiguration;
- $this->braintreeClientToken = $braintreeClientToken;
-
- if ($this->getValue(self::KEY_ACTIVE)) {
- $this->initCredentials();
- }
- }
-
- /**
- * Initializes credentials.
- *
- * @return void
- */
- public function initCredentials()
- {
- if ($this->getValue(self::KEY_ENVIRONMENT) == Environment::ENVIRONMENT_PRODUCTION) {
- $this->braintreeConfiguration->environment(Environment::ENVIRONMENT_PRODUCTION);
- } else {
- $this->braintreeConfiguration->environment(Environment::ENVIRONMENT_SANDBOX);
- }
- $this->braintreeConfiguration->merchantId($this->getValue(self::KEY_MERCHANT_ID));
- $this->braintreeConfiguration->publicKey($this->getValue(self::KEY_PUBLIC_KEY));
- $this->braintreeConfiguration->privateKey($this->getValue(self::KEY_PRIVATE_KEY));
- }
-
- /**
- * Generate a new client token if necessary
- * @TODO method should be moved to adapter
- * @return string
- */
- public function getClientToken()
- {
- if (empty($this->clientToken)) {
- $this->clientToken = $this->braintreeClientToken->generate();
- }
-
- return $this->clientToken;
- }
+ const KEY_VERIFY_3DSECURE = 'verify_3dsecure';
+ const KEY_THRESHOLD_AMOUNT = 'threshold_amount';
+ const KEY_VERIFY_ALLOW_SPECIFIC = 'verify_all_countries';
+ const KEY_VERIFY_SPECIFIC = 'verify_specific_countries';
+ const VALUE_3DSECURE_ALL = 0;
+ const CODE_3DSECURE = 'three_d_secure';
+ const KEY_KOUNT_MERCHANT_ID = 'kount_merchant_id';
+ const FRAUD_PROTECTION = 'fraud_protection';
/**
* Return the country specific card type config
@@ -149,6 +77,7 @@ public function getCcTypesMapper()
public function getCountryAvailableCardTypes($country)
{
$types = $this->getCountrySpecificCardTypeConfig();
+
return (!empty($types[$country])) ? $types[$country] : [];
}
@@ -160,4 +89,75 @@ public function isCvvEnabled()
{
return (bool) $this->getValue(self::KEY_USE_CVV);
}
+
+ /**
+ * Check if 3d secure verification enabled
+ * @return bool
+ */
+ public function isVerify3DSecure()
+ {
+ return (bool) $this->getValue(self::KEY_VERIFY_3DSECURE);
+ }
+
+ /**
+ * Get threshold amount for 3d secure
+ * @return float
+ */
+ public function getThresholdAmount()
+ {
+ return (double) $this->getValue(self::KEY_THRESHOLD_AMOUNT);
+ }
+
+ /**
+ * Get list of specific countries for 3d secure
+ * @return array
+ */
+ public function get3DSecureSpecificCountries()
+ {
+ if ((int) $this->getValue(self::KEY_VERIFY_ALLOW_SPECIFIC) == self::VALUE_3DSECURE_ALL) {
+ return [];
+ }
+
+ return explode(',', $this->getValue(self::KEY_VERIFY_SPECIFIC));
+ }
+
+ /**
+ * @return string
+ */
+ public function getEnvironment()
+ {
+ return $this->getValue(Config::KEY_ENVIRONMENT);
+ }
+
+ /**
+ * @return string
+ */
+ public function getKountMerchantId()
+ {
+ return $this->getValue(Config::KEY_KOUNT_MERCHANT_ID);
+ }
+
+ /**
+ * @return string
+ */
+ public function getMerchantId()
+ {
+ return $this->getValue(Config::KEY_MERCHANT_ID);
+ }
+
+ /**
+ * @return string
+ */
+ public function getSdkUrl()
+ {
+ return $this->getValue(Config::KEY_SDK_URL);
+ }
+
+ /**
+ * @return bool
+ */
+ public function hasFraudProtection()
+ {
+ return (bool) $this->getValue(Config::FRAUD_PROTECTION);
+ }
}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Helper/SubjectReader.php b/app/code/Magento/BraintreeTwo/Gateway/Helper/SubjectReader.php
index 77304c6cabbe4..aa8a503fa8cde 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Helper/SubjectReader.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Helper/SubjectReader.php
@@ -5,10 +5,13 @@
*/
namespace Magento\BraintreeTwo\Gateway\Helper;
+use Magento\Payment\Gateway\Helper;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
+
/**
* Class SubjectReader
*/
-class SubjectReader extends \Magento\Payment\Gateway\Helper\SubjectReader
+class SubjectReader
{
/**
* Reads response object from subject
@@ -16,13 +19,85 @@ class SubjectReader extends \Magento\Payment\Gateway\Helper\SubjectReader
* @param array $subject
* @return object
*/
- public static function readResponseObject(array $subject)
+ public function readResponseObject(array $subject)
{
- $response = self::readResponse($subject);
+ $response = Helper\SubjectReader::readResponse($subject);
if (!isset($response['object']) || !is_object($response['object'])) {
throw new \InvalidArgumentException('Response object does not exist');
}
return $response['object'];
}
+
+ /**
+ * Reads payment from subject
+ *
+ * @param array $subject
+ * @return PaymentDataObjectInterface
+ */
+ public function readPayment(array $subject)
+ {
+ return Helper\SubjectReader::readPayment($subject);
+ }
+
+ /**
+ * Reads transaction from subject
+ *
+ * @param array $subject
+ * @return \Braintree\Transaction
+ */
+ public function readTransaction(array $subject)
+ {
+ if (!isset($subject['object']) || !is_object($subject['object'])) {
+ throw new \InvalidArgumentException('Response object does not exist');
+ }
+
+ if (!isset($subject['object']->transaction)
+ && !$subject['object']->transaction instanceof \Braintree\Transaction
+ ) {
+ throw new \InvalidArgumentException('The object is not a class \Braintree\Transaction.');
+ }
+
+ return $subject['object']->transaction;
+ }
+
+ /**
+ * Reads amount from subject
+ *
+ * @param array $subject
+ * @return mixed
+ */
+ public function readAmount(array $subject)
+ {
+ return Helper\SubjectReader::readAmount($subject);
+ }
+
+ /**
+ * Reads customer id from subject
+ * @param array $subject
+ * @return int
+ */
+ public function readCustomerId(array $subject)
+ {
+ if (empty($subject['customerId'])) {
+ throw new \InvalidArgumentException('The "customerId" field does not exists');
+ }
+
+ return (int)$subject['customerId'];
+ }
+
+ /**
+ * Reads public hash from subject
+ *
+ * @param array $subject
+ * @return string
+ */
+ public function readPublicHash(array $subject)
+ {
+ if (empty($subject['publicHash'])) {
+ throw new \InvalidArgumentException('The "publicHash" field does not exists');
+ }
+
+ return $subject['publicHash'];
+ }
}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Http/Client/AbstractTransaction.php b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/AbstractTransaction.php
new file mode 100644
index 0000000000000..3e2fb25881286
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/AbstractTransaction.php
@@ -0,0 +1,82 @@
+logger = $logger;
+ $this->customLogger = $customLogger;
+ $this->adapter = $adapter;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function placeRequest(TransferInterface $transferObject)
+ {
+ $data = $transferObject->getBody();
+ $log = [
+ 'request' => $data,
+ 'client' => static::class
+ ];
+ $response['object'] = [];
+
+ try {
+ $response['object'] = $this->process($data);
+ } catch (\Exception $e) {
+ $message = __($e->getMessage() ?: 'Sorry, but something went wrong');
+ $this->logger->critical($message);
+ throw new ClientException($message);
+ } finally {
+ $log['response'] = (array) $response['object'];
+ $this->customLogger->debug($log);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Process http request
+ * @param array $data
+ * @return \Braintree\Result\Error|\Braintree\Result\Successful
+ */
+ abstract protected function process(array $data);
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionClone.php b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionClone.php
new file mode 100644
index 0000000000000..ed094aeb184d7
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionClone.php
@@ -0,0 +1,25 @@
+adapter->cloneTransaction($transactionId, $data);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionSale.php b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionSale.php
index 4896e81d70600..f906e22fa9629 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionSale.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionSale.php
@@ -5,64 +5,16 @@
*/
namespace Magento\BraintreeTwo\Gateway\Http\Client;
-use Magento\Payment\Model\Method\Logger;
-use Magento\Payment\Gateway\Http\ClientException;
-use Magento\Payment\Gateway\Http\ClientInterface;
-use Magento\Payment\Gateway\Http\TransferInterface;
-use Magento\BraintreeTwo\Model\Adapter\BraintreeTransaction;
-
/**
* Class TransactionSale
*/
-class TransactionSale implements ClientInterface
+class TransactionSale extends AbstractTransaction
{
- /**
- * @var Logger
- */
- private $logger;
-
- /**
- * @var BraintreeTransaction
- */
- private $braintreeTransaction;
-
- /**
- * Constructor
- *
- * @param Logger $logger
- * @param BraintreeTransaction $braintreeTransaction
- */
- public function __construct(
- Logger $logger,
- BraintreeTransaction $braintreeTransaction
- ) {
- $this->logger = $logger;
- $this->braintreeTransaction = $braintreeTransaction;
- }
-
/**
* @inheritdoc
*/
- public function placeRequest(TransferInterface $transferObject)
+ protected function process(array $data)
{
- $data = $transferObject->getBody();
- $log = [
- 'request' => $data,
- 'client' => self::class
- ];
- $response['object'] = [];
-
- try {
- $response['object'] = $this->braintreeTransaction->sale($data);
- } catch (\Exception $e) {
- throw new ClientException(__(
- $e->getMessage() ?: 'Sorry, but something went wrong'
- ));
- } finally {
- $log['response'] = (array) $response['object'];
- $this->logger->debug($log);
- }
-
- return $response;
+ return $this->adapter->sale($data);
}
}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionSubmitForSettlement.php b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionSubmitForSettlement.php
new file mode 100644
index 0000000000000..36615c32780e0
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Http/Client/TransactionSubmitForSettlement.php
@@ -0,0 +1,26 @@
+adapter->submitForSettlement(
+ $data[CaptureDataBuilder::TRANSACTION_ID],
+ $data[PaymentDataBuilder::AMOUNT]
+ );
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Request/AddressDataBuilder.php b/app/code/Magento/BraintreeTwo/Gateway/Request/AddressDataBuilder.php
index feff663bb658d..fc9d854da6cc7 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Request/AddressDataBuilder.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Request/AddressDataBuilder.php
@@ -5,8 +5,8 @@
*/
namespace Magento\BraintreeTwo\Gateway\Request;
-use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
/**
* Class AddressDataBuilder
@@ -75,14 +75,36 @@ class AddressDataBuilder implements BuilderInterface
*/
const COUNTRY_CODE = 'countryCodeAlpha2';
+ /**
+ * Order ID
+ */
+ const ORDER_ID = 'orderId';
+
+ /**
+ * @var SubjectReader
+ */
+ private $subjectReader;
+
+ /**
+ * Constructor
+ *
+ * @param SubjectReader $subjectReader
+ */
+ public function __construct(SubjectReader $subjectReader)
+ {
+ $this->subjectReader = $subjectReader;
+ }
+
/**
* @inheritdoc
*/
public function build(array $buildSubject)
{
- $paymentDO = SubjectReader::readPayment($buildSubject);
+ $paymentDO = $this->subjectReader->readPayment($buildSubject);
$order = $paymentDO->getOrder();
- $result = [];
+ $result = [
+ self::ORDER_ID => $order->getOrderIncrementId()
+ ];
$billingAddress = $order->getBillingAddress();
if ($billingAddress) {
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Request/CaptureDataBuilder.php b/app/code/Magento/BraintreeTwo/Gateway/Request/CaptureDataBuilder.php
new file mode 100644
index 0000000000000..11bfdf8142968
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Request/CaptureDataBuilder.php
@@ -0,0 +1,56 @@
+subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function build(array $buildSubject)
+ {
+ $paymentDO = $this->subjectReader->readPayment($buildSubject);
+
+ $payment = $paymentDO->getPayment();
+
+ $transactionId = $payment->getCcTransId();
+ if (!$transactionId) {
+ throw new LocalizedException(__('No authorization transaction to proceed capture.'));
+ }
+
+ return [
+ self::TRANSACTION_ID => $transactionId,
+ PaymentDataBuilder::AMOUNT => $this->formatPrice($this->subjectReader->readAmount($buildSubject))
+ ];
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Request/CustomerDataBuilder.php b/app/code/Magento/BraintreeTwo/Gateway/Request/CustomerDataBuilder.php
index 2fff378d67c17..ee3c188070f35 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Request/CustomerDataBuilder.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Request/CustomerDataBuilder.php
@@ -5,8 +5,8 @@
*/
namespace Magento\BraintreeTwo\Gateway\Request;
-use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
/**
* Class CustomerDataBuilder
@@ -44,12 +44,27 @@ class CustomerDataBuilder implements BuilderInterface
*/
const PHONE = 'phone';
+ /**
+ * @var SubjectReader
+ */
+ private $subjectReader;
+
+ /**
+ * Constructor
+ *
+ * @param SubjectReader $subjectReader
+ */
+ public function __construct(SubjectReader $subjectReader)
+ {
+ $this->subjectReader = $subjectReader;
+ }
+
/**
* @inheritdoc
*/
public function build(array $buildSubject)
{
- $paymentDO = SubjectReader::readPayment($buildSubject);
+ $paymentDO = $this->subjectReader->readPayment($buildSubject);
$order = $paymentDO->getOrder();
$billingAddress = $order->getBillingAddress();
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Request/KountPaymentDataBuilder.php b/app/code/Magento/BraintreeTwo/Gateway/Request/KountPaymentDataBuilder.php
new file mode 100644
index 0000000000000..4a121b9a2cadb
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Request/KountPaymentDataBuilder.php
@@ -0,0 +1,65 @@
+config = $config;
+ $this->subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function build(array $buildSubject)
+ {
+ $result = [];
+ if (!$this->config->hasFraudProtection()) {
+ return $result;
+ }
+ $paymentDO = $this->subjectReader->readPayment($buildSubject);
+
+ $payment = $paymentDO->getPayment();
+ $data = $payment->getAdditionalInformation();
+
+ if (isset($data[DataAssignObserver::DEVICE_DATA])) {
+ $result[self::DEVICE_DATA] = $data[DataAssignObserver::DEVICE_DATA];
+ }
+
+ return $result;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Request/PaymentDataBuilder.php b/app/code/Magento/BraintreeTwo/Gateway/Request/PaymentDataBuilder.php
index c9d1a743b2e93..807de2c50ab11 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Request/PaymentDataBuilder.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Request/PaymentDataBuilder.php
@@ -5,16 +5,19 @@
*/
namespace Magento\BraintreeTwo\Gateway\Request;
-use Magento\Payment\Gateway\Helper\SubjectReader;
-use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\BraintreeTwo\Gateway\Config\Config;
use Magento\BraintreeTwo\Observer\DataAssignObserver;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
+use Magento\Payment\Gateway\Request\BuilderInterface;
+use Magento\Payment\Helper\Formatter;
/**
- * Class PaymentDataBuilder
+ * Payment Data Builder
*/
class PaymentDataBuilder implements BuilderInterface
{
+ use Formatter;
+
/**
* The billing amount of the request. This value must be greater than 0,
* and must match the currency format of the merchant account.
@@ -45,12 +48,20 @@ class PaymentDataBuilder implements BuilderInterface
private $config;
/**
+ * @var SubjectReader
+ */
+ private $subjectReader;
+
+ /**
+ * Constructor
+ *
* @param Config $config
+ * @param SubjectReader $subjectReader
*/
- public function __construct(
- Config $config
- ) {
+ public function __construct(Config $config, SubjectReader $subjectReader)
+ {
$this->config = $config;
+ $this->subjectReader = $subjectReader;
}
/**
@@ -58,16 +69,15 @@ public function __construct(
*/
public function build(array $buildSubject)
{
- $paymentDO = SubjectReader::readPayment($buildSubject);
+ $paymentDO = $this->subjectReader->readPayment($buildSubject);
- /** @var \Magento\Sales\Model\Order\Payment $payment */
$payment = $paymentDO->getPayment();
$result = [
- self::AMOUNT => sprintf('%.2F', SubjectReader::readAmount($buildSubject)),
+ self::AMOUNT => $this->formatPrice($this->subjectReader->readAmount($buildSubject)),
self::PAYMENT_METHOD_NONCE => $payment->getAdditionalInformation(
DataAssignObserver::PAYMENT_METHOD_NONCE
- )
+ ),
];
$merchantAccountId = $this->config->getValue(Config::KEY_MERCHANT_ACCOUNT_ID);
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Request/ThreeDSecureDataBuilder.php b/app/code/Magento/BraintreeTwo/Gateway/Request/ThreeDSecureDataBuilder.php
new file mode 100644
index 0000000000000..12206605a618a
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Request/ThreeDSecureDataBuilder.php
@@ -0,0 +1,79 @@
+config = $config;
+ $this->subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function build(array $buildSubject)
+ {
+ $result = [];
+
+ $paymentDO = $this->subjectReader->readPayment($buildSubject);
+ $amount = $this->formatPrice($this->subjectReader->readAmount($buildSubject));
+
+ if ($this->is3DSecureEnabled($paymentDO->getOrder(), $amount)) {
+ $result['options'][Config::CODE_3DSECURE] = ['required' => true];
+ }
+ return $result;
+ }
+
+ /**
+ * Check if 3d secure is enabled
+ * @param OrderAdapterInterface $order
+ * @param float $amount
+ * @return bool
+ */
+ private function is3DSecureEnabled(OrderAdapterInterface $order, $amount)
+ {
+ if (!$this->config->isVerify3DSecure() || $amount < $this->config->getThresholdAmount()) {
+ return false;
+ }
+
+ $billingAddress = $order->getBillingAddress();
+ $specificCounties = $this->config->get3DSecureSpecificCountries();
+ if (!empty($specificCounties) && !in_array($billingAddress->getCountryId(), $specificCounties)) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Request/VaultDataBuilder.php b/app/code/Magento/BraintreeTwo/Gateway/Request/VaultDataBuilder.php
new file mode 100644
index 0000000000000..9e494ffc590a7
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Request/VaultDataBuilder.php
@@ -0,0 +1,69 @@
+vaultPayment = $vaultPayment;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function build(array $buildSubject)
+ {
+ $result = [];
+
+ $isActiveVaultModule = $this->vaultPayment->isActiveForPayment(ConfigProvider::CODE);
+ if ($isActiveVaultModule) {
+ $result[self::OPTIONS][self::STORE_IN_VAULT_ON_SUCCESS] = true;
+ }
+
+ return $result;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Response/CaptureDetailsHandler.php b/app/code/Magento/BraintreeTwo/Gateway/Response/CaptureDetailsHandler.php
new file mode 100644
index 0000000000000..a13c0d0e74ced
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Response/CaptureDetailsHandler.php
@@ -0,0 +1,47 @@
+subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function handle(array $handlingSubject, array $response)
+ {
+ $paymentDO = $this->subjectReader->readPayment($handlingSubject);
+ /**
+ * @TODO after changes in sales module should be refactored for new interfaces
+ */
+ $payment = $paymentDO->getPayment();
+ ContextHelper::assertOrderPayment($payment);
+
+ $payment->setIsTransactionClosed(false);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Response/CardDetailsHandler.php b/app/code/Magento/BraintreeTwo/Gateway/Response/CardDetailsHandler.php
index 975f17b0a1ada..a8bd79cf88329 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Response/CardDetailsHandler.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Response/CardDetailsHandler.php
@@ -5,17 +5,15 @@
*/
namespace Magento\BraintreeTwo\Gateway\Response;
-use Braintree_Transaction;
+use \Braintree\Transaction;
use Magento\BraintreeTwo\Gateway\Config\Config;
use Magento\Payment\Gateway\Helper\ContextHelper;
-use Magento\Payment\Gateway\Helper\SubjectReader;
-use Magento\Payment\Gateway\Response\HandlerInterface;
use Magento\Sales\Api\Data\OrderPaymentInterface;
-use Magento\Sales\Model\Order\Payment;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
+use Magento\Payment\Gateway\Response\HandlerInterface;
/**
* Class CardDetailsHandler
- * @package Magento\BraintreeTwo\Gateway\Response
*/
class CardDetailsHandler implements HandlerInterface
{
@@ -30,16 +28,27 @@ class CardDetailsHandler implements HandlerInterface
const CARD_NUMBER = 'cc_number';
/**
- * @var \Magento\BraintreeTwo\Gateway\Config\Config
+ * @var Config
*/
private $config;
/**
- * @param \Magento\BraintreeTwo\Gateway\Config\Config $config
+ * @var SubjectReader
*/
- public function __construct(Config $config)
- {
+ private $subjectReader;
+
+ /**
+ * Constructor
+ *
+ * @param Config $config
+ * @param SubjectReader $subjectReader
+ */
+ public function __construct(
+ Config $config,
+ SubjectReader $subjectReader
+ ) {
$this->config = $config;
+ $this->subjectReader = $subjectReader;
}
/**
@@ -47,13 +56,12 @@ public function __construct(Config $config)
*/
public function handle(array $handlingSubject, array $response)
{
- $paymentDO = SubjectReader::readPayment($handlingSubject);
- /** @var \Braintree_Transaction $transaction */
- $transaction = $response['object']->transaction;
+ $paymentDO = $this->subjectReader->readPayment($handlingSubject);
+ $transaction = $this->subjectReader->readTransaction($response);
+
/**
* @TODO after changes in sales module should be refactored for new interfaces
*/
- /** @var \Magento\Sales\Model\Order\Payment $payment */
$payment = $paymentDO->getPayment();
ContextHelper::assertOrderPayment($payment);
@@ -72,6 +80,7 @@ public function handle(array $handlingSubject, array $response)
/**
* Get type of credit card mapped from Braintree
+ *
* @param string $type
* @return array
*/
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Response/CloneDetailsHandler.php b/app/code/Magento/BraintreeTwo/Gateway/Response/CloneDetailsHandler.php
new file mode 100644
index 0000000000000..e153214b2e76c
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Response/CloneDetailsHandler.php
@@ -0,0 +1,49 @@
+subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function handle(array $handlingSubject, array $response)
+ {
+ $paymentDO = $this->subjectReader->readPayment($handlingSubject);
+ /**
+ * @TODO after changes in sales module should be refactored for new interfaces
+ */
+ $payment = $paymentDO->getPayment();
+ ContextHelper::assertOrderPayment($payment);
+
+ $transaction = $this->subjectReader->readTransaction($response);
+
+ $payment->setTransactionId($transaction->id);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Response/PaymentDetailsHandler.php b/app/code/Magento/BraintreeTwo/Gateway/Response/PaymentDetailsHandler.php
index 80d68bf263477..04f9c644387bf 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Response/PaymentDetailsHandler.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Response/PaymentDetailsHandler.php
@@ -5,16 +5,15 @@
*/
namespace Magento\BraintreeTwo\Gateway\Response;
-use Braintree_Transaction;
+use Braintree\Transaction;
use Magento\BraintreeTwo\Observer\DataAssignObserver;
use Magento\Payment\Gateway\Helper\ContextHelper;
-use Magento\Payment\Gateway\Helper\SubjectReader;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Response\HandlerInterface;
-use Magento\Sales\Model\Order\Payment;
+use Magento\Sales\Api\Data\OrderPaymentInterface;
/**
- * Class PaymentDetailsHandler
- * @package Magento\BraintreeTwo\Gateway\Response
+ * Payment Details Handler
*/
class PaymentDetailsHandler implements HandlerInterface
{
@@ -43,18 +42,33 @@ class PaymentDetailsHandler implements HandlerInterface
self::PROCESSOR_RESPONSE_TEXT,
];
+ /**
+ * @var SubjectReader
+ */
+ private $subjectReader;
+
+ /**
+ * Constructor
+ *
+ * @param SubjectReader $subjectReader
+ */
+ public function __construct(SubjectReader $subjectReader)
+ {
+ $this->subjectReader = $subjectReader;
+ }
+
/**
* @inheritdoc
*/
public function handle(array $handlingSubject, array $response)
{
- $paymentDO = SubjectReader::readPayment($handlingSubject);
- /** @var \Braintree_Transaction $transaction */
- $transaction = $response['object']->transaction;
+ $paymentDO = $this->subjectReader->readPayment($handlingSubject);
+ /** @var \Braintree\Transaction $transaction */
+ $transaction = $this->subjectReader->readTransaction($response);
/**
* @TODO after changes in sales module should be refactored for new interfaces
*/
- /** @var \Magento\Sales\Model\Order\Payment $payment */
+ /** @var OrderPaymentInterface $payment */
$payment = $paymentDO->getPayment();
ContextHelper::assertOrderPayment($payment);
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Response/RiskDataHandler.php b/app/code/Magento/BraintreeTwo/Gateway/Response/RiskDataHandler.php
new file mode 100644
index 0000000000000..36678eb371817
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Response/RiskDataHandler.php
@@ -0,0 +1,66 @@
+subjectReader = $subjectReader;
+ }
+
+ /**
+ * Handles response
+ *
+ * @param array $handlingSubject
+ * @param array $response
+ * @return void
+ */
+ public function handle(array $handlingSubject, array $response)
+ {
+ $paymentDO = $this->subjectReader->readPayment($handlingSubject);
+
+ /** @var \Braintree\Transaction $transaction */
+ $transaction = $this->subjectReader->readTransaction($response);
+
+ if (!isset($transaction->riskData)) {
+ return;
+ }
+
+ $payment = $paymentDO->getPayment();
+ ContextHelper::assertOrderPayment($payment);
+
+ $payment->setAdditionalInformation(self::RISK_DATA_ID, $transaction->riskData->id);
+ $payment->setAdditionalInformation(self::RISK_DATA_DECISION, $transaction->riskData->decision);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Response/ThreeDSecureDetailsHandler.php b/app/code/Magento/BraintreeTwo/Gateway/Response/ThreeDSecureDetailsHandler.php
new file mode 100644
index 0000000000000..14005691da7eb
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Response/ThreeDSecureDetailsHandler.php
@@ -0,0 +1,70 @@
+subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function handle(array $handlingSubject, array $response)
+ {
+ $paymentDO = $this->subjectReader->readPayment($handlingSubject);
+ /**
+ * @TODO after changes in sales module should be refactored for new interfaces
+ */
+ /** @var OrderPaymentInterface $payment */
+ $payment = $paymentDO->getPayment();
+ ContextHelper::assertOrderPayment($payment);
+
+ /** @var Transaction $transaction */
+ $transaction = $this->subjectReader->readTransaction($response);
+
+ if ($payment->hasAdditionalInformation(self::LIABILITY_SHIFTED)) {
+ // remove 3d secure details for reorder
+ $payment->unsAdditionalInformation(self::LIABILITY_SHIFTED);
+ $payment->unsAdditionalInformation(self::LIABILITY_SHIFT_POSSIBLE);
+ }
+
+ if (empty($transaction->threeDSecureInfo)) {
+ return;
+ }
+
+ /** @var \Braintree\ThreeDSecureInfo $info */
+ $info = $transaction->threeDSecureInfo;
+ $payment->setAdditionalInformation(self::LIABILITY_SHIFTED, $info->liabilityShifted ? 'Yes' : 'No');
+ $shiftPossible = $info->liabilityShiftPossible ? 'Yes' : 'No';
+ $payment->setAdditionalInformation(self::LIABILITY_SHIFT_POSSIBLE, $shiftPossible);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Response/VaultDetailsHandler.php b/app/code/Magento/BraintreeTwo/Gateway/Response/VaultDetailsHandler.php
new file mode 100644
index 0000000000000..0debd234909d8
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Response/VaultDetailsHandler.php
@@ -0,0 +1,155 @@
+vaultPayment = $vaultPayment;
+ $this->paymentTokenFactory = $paymentTokenFactory;
+ $this->paymentExtensionFactory = $paymentExtensionFactory;
+ $this->config = $config;
+ $this->subjectReader = $subjectReader;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function handle(array $handlingSubject, array $response)
+ {
+ $isActiveVaultModule = $this->vaultPayment->isActiveForPayment(ConfigProvider::CODE);
+ if (!$isActiveVaultModule) {
+ return;
+ }
+
+ $paymentDO = $this->subjectReader->readPayment($handlingSubject);
+ $transaction = $this->subjectReader->readTransaction($response);
+ $payment = $paymentDO->getPayment();
+
+ // add vault payment token entity to extension attributes
+ $paymentToken = $this->getVaultPaymentToken($transaction, $payment);
+ if (null !== $paymentToken) {
+ $extensionAttributes = $payment->getExtensionAttributes();
+ if (null === $extensionAttributes) {
+ $extensionAttributes = $this->paymentExtensionFactory->create();
+ $payment->setExtensionAttributes($extensionAttributes);
+ }
+ $extensionAttributes->setVaultPaymentToken($paymentToken);
+ }
+ }
+
+ /**
+ * Get vault payment token entity
+ *
+ * @param \Braintree\Transaction $transaction
+ * @param OrderPaymentInterface $payment
+ * @return PaymentTokenInterface|null
+ */
+ protected function getVaultPaymentToken(Transaction $transaction, OrderPaymentInterface $payment)
+ {
+ // Check token existing in gateway response
+ $token = $transaction->creditCardDetails->token;
+ if (empty($token)) {
+ return null;
+ }
+
+ $order = $payment->getOrder();
+
+ /** @var PaymentTokenInterface $paymentToken */
+ $paymentToken = $this->paymentTokenFactory->create();
+ $paymentToken->setGatewayToken($token);
+ $paymentToken->setCustomerId($order->getCustomerId());
+ $paymentToken->setPaymentMethodCode($payment->getMethod());
+ $paymentToken->setCreatedAt($order->getCreatedAt());
+
+ $paymentToken->setTokenDetails($this->convertDetailsToJSON([
+ 'type' => $this->getCreditCardType($transaction->creditCardDetails->cardType),
+ 'maskedCC' => $transaction->creditCardDetails->last4,
+ 'expirationDate' => $transaction->creditCardDetails->expirationDate
+ ]));
+
+ return $paymentToken;
+ }
+
+ /**
+ * Convert payment token details to JSON
+ * @param array $details
+ * @return string
+ */
+ private function convertDetailsToJSON($details)
+ {
+ $json = \Zend_Json::encode($details);
+ return $json ? $json : '{}';
+ }
+
+ /**
+ * Get type of credit card mapped from Braintree
+ *
+ * @param string $type
+ * @return array
+ */
+ private function getCreditCardType($type)
+ {
+ $replaced = str_replace(' ', '-', strtolower($type));
+ $mapper = $this->config->getCctypesMapper();
+
+ return $mapper[$replaced];
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Validator/PaymentNonceResponseValidator.php b/app/code/Magento/BraintreeTwo/Gateway/Validator/PaymentNonceResponseValidator.php
new file mode 100644
index 0000000000000..51c804aeb49eb
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Gateway/Validator/PaymentNonceResponseValidator.php
@@ -0,0 +1,39 @@
+subjectReader->readResponseObject($validationSubject);
+ $result = $this->createResult(
+ $this->validateSuccess($response) &&
+ $this->validateErrors($response) &&
+ $this->validatePaymentMethodNonce($response),
+ [__('Payment method nonce can\'t be retrieved.')]
+ );
+
+ return $result;
+ }
+
+ /**
+ * Validate payment method nonce of response
+ *
+ * @param object $response
+ * @return bool
+ */
+ private function validatePaymentMethodNonce($response)
+ {
+ return !empty($response->paymentMethodNonce) && !empty($response->paymentMethodNonce->nonce);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Gateway/Validator/ResponseValidator.php b/app/code/Magento/BraintreeTwo/Gateway/Validator/ResponseValidator.php
index 48787ed97c899..0ed3b74d25466 100644
--- a/app/code/Magento/BraintreeTwo/Gateway/Validator/ResponseValidator.php
+++ b/app/code/Magento/BraintreeTwo/Gateway/Validator/ResponseValidator.php
@@ -5,21 +5,39 @@
*/
namespace Magento\BraintreeTwo\Gateway\Validator;
+use Braintree\Transaction;
use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Validator\AbstractValidator;
+use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
/**
* Class ResponseValidator
- * @package Magento\BraintreeTwo\Gateway\Validator
*/
class ResponseValidator extends AbstractValidator
{
+ /**
+ * @var SubjectReader
+ */
+ protected $subjectReader;
+
+ /**
+ * Constructor
+ *
+ * @param ResultInterfaceFactory $resultFactory
+ * @param SubjectReader $subjectReader
+ */
+ public function __construct(ResultInterfaceFactory $resultFactory, SubjectReader $subjectReader)
+ {
+ parent::__construct($resultFactory);
+ $this->subjectReader = $subjectReader;
+ }
+
/**
* @inheritdoc
*/
public function validate(array $validationSubject)
{
- $response = SubjectReader::readResponseObject($validationSubject);
+ $response = $this->subjectReader->readResponseObject($validationSubject);
$result = $this->createResult(
$this->validateSuccess($response)
@@ -35,7 +53,7 @@ public function validate(array $validationSubject)
* @param object $response
* @return bool
*/
- private function validateSuccess($response)
+ protected function validateSuccess($response)
{
return property_exists($response, 'success') && $response->success === true;
}
@@ -44,7 +62,7 @@ private function validateSuccess($response)
* @param object $response
* @return bool
*/
- private function validateErrors($response)
+ protected function validateErrors($response)
{
return !(property_exists($response, 'errors') && $response->errors->deepSize() > 0);
}
@@ -57,7 +75,7 @@ private function validateTransactionStatus($response)
{
return in_array(
$response->transaction->status,
- [\Braintree_Transaction::AUTHORIZED, \Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT]
+ [Transaction::AUTHORIZED, Transaction::SUBMITTED_FOR_SETTLEMENT]
);
}
}
diff --git a/app/code/Magento/BraintreeTwo/Helper/CcType.php b/app/code/Magento/BraintreeTwo/Helper/CcType.php
index 4f553c4430dd5..427c773a8766b 100644
--- a/app/code/Magento/BraintreeTwo/Helper/CcType.php
+++ b/app/code/Magento/BraintreeTwo/Helper/CcType.php
@@ -9,7 +9,6 @@
/**
* Class CcType
- * @package Magento\BraintreeTwo\Helper
*/
class CcType
{
diff --git a/app/code/Magento/BraintreeTwo/Helper/Country.php b/app/code/Magento/BraintreeTwo/Helper/Country.php
index 8065a3ca4c61d..1780e63358699 100644
--- a/app/code/Magento/BraintreeTwo/Helper/Country.php
+++ b/app/code/Magento/BraintreeTwo/Helper/Country.php
@@ -9,7 +9,6 @@
/**
* Class Country
- * @package Magento\BraintreeTwo\Helper
*/
class Country
{
diff --git a/app/code/Magento/BraintreeTwo/Model/Adapter/BraintreeAdapter.php b/app/code/Magento/BraintreeTwo/Model/Adapter/BraintreeAdapter.php
new file mode 100644
index 0000000000000..75ddf82a0d931
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Model/Adapter/BraintreeAdapter.php
@@ -0,0 +1,173 @@
+config = $config;
+ $this->initCredentials();
+ }
+
+ /**
+ * Initializes credentials.
+ *
+ * @return void
+ */
+ protected function initCredentials()
+ {
+ if ($this->config->getValue(Config::KEY_ENVIRONMENT) == Environment::ENVIRONMENT_PRODUCTION) {
+ $this->environment(Environment::ENVIRONMENT_PRODUCTION);
+ } else {
+ $this->environment(Environment::ENVIRONMENT_SANDBOX);
+ }
+ $this->merchantId($this->config->getValue(Config::KEY_MERCHANT_ID));
+ $this->publicKey($this->config->getValue(Config::KEY_PUBLIC_KEY));
+ $this->privateKey($this->config->getValue(Config::KEY_PRIVATE_KEY));
+ }
+
+ /**
+ * @param string|null $value
+ * @return mixed
+ */
+ public function environment($value = null)
+ {
+ return Configuration::environment($value);
+ }
+
+ /**
+ * @param string|null $value
+ * @return mixed
+ */
+ public function merchantId($value = null)
+ {
+ return Configuration::merchantId($value);
+ }
+
+ /**
+ * @param string|null $value
+ * @return mixed
+ */
+ public function publicKey($value = null)
+ {
+ return Configuration::publicKey($value);
+ }
+
+ /**
+ * @param string|null $value
+ * @return mixed
+ */
+ public function privateKey($value = null)
+ {
+ return Configuration::privateKey($value);
+ }
+
+ /**
+ * @param array $params
+ * @return \Braintree\Result\Successful|\Braintree\Result\Error|null
+ */
+ public function generate(array $params = [])
+ {
+ try {
+ return ClientToken::generate($params);
+ } catch (\Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * @param string $id
+ * @return \Braintree\CreditCard|null
+ */
+ public function find($token)
+ {
+ try {
+ return CreditCard::find($token);
+ } catch (\Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * @param string $token
+ * @return \Braintree\Result\Successful|\Braintree\Result\Error
+ */
+ public function createNonce($token)
+ {
+ return PaymentMethodNonce::create($token);
+ }
+
+ /**
+ * @param array $attributes
+ * @return \Braintree\Result\Successful|\Braintree\Result\Error
+ */
+ public function sale(array $attributes)
+ {
+ return Transaction::sale($attributes);
+ }
+
+ /**
+ * @param string $transactionId
+ * @param null|float $amount
+ * @return \Braintree\Result\Successful|\Braintree\Result\Error
+ */
+ public function submitForSettlement($transactionId, $amount = null)
+ {
+ return Transaction::submitForSettlement($transactionId, $amount);
+ }
+
+ /**
+ * @param string $transactionId
+ * @return \Braintree\Result\Successful|\Braintree\Result\Error
+ */
+ public function void($transactionId)
+ {
+ return Transaction::void($transactionId);
+ }
+
+ /**
+ * @param string $transactionId
+ * @param null|float $amount
+ * @return \Braintree\Result\Successful|\Braintree\Result\Error
+ */
+ public function refund($transactionId, $amount = null)
+ {
+ return Transaction::refund($transactionId, $amount);
+ }
+
+ /**
+ * Clone original transaction
+ * @param string $transactionId
+ * @param array $attributes
+ * @return mixed
+ */
+ public function cloneTransaction($transactionId, array $attributes)
+ {
+ return Transaction::cloneTransaction($transactionId, $attributes);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Model/Adapter/BraintreeClientToken.php b/app/code/Magento/BraintreeTwo/Model/Adapter/BraintreeClientToken.php
deleted file mode 100644
index 02c79825e634d..0000000000000
--- a/app/code/Magento/BraintreeTwo/Model/Adapter/BraintreeClientToken.php
+++ /dev/null
@@ -1,31 +0,0 @@
-config = $config;
+ $this->adapter = $adapter;
}
/**
@@ -40,14 +53,36 @@ public function getConfig()
return [
'payment' => [
self::CODE => [
- 'clientToken' => $this->config->getClientToken(),
+ 'clientToken' => $this->getClientToken(),
'ccTypesMapper' => $this->config->getCctypesMapper(),
- 'sdkUrl' => $this->config->getValue(Config::KEY_SDK_URL),
+ 'sdkUrl' => $this->config->getSdkUrl(),
'countrySpecificCardTypes' => $this->config->getCountrySpecificCardTypeConfig(),
'availableCardTypes' => $this->config->getAvailableCardTypes(),
- 'useCvv' => $this->config->isCvvEnabled()
+ 'useCvv' => $this->config->isCvvEnabled(),
+ 'environment' => $this->config->getEnvironment(),
+ 'kountMerchantId' => $this->config->getKountMerchantId(),
+ 'hasFraudProtection' => $this->config->hasFraudProtection(),
+ 'merchantId' => $this->config->getMerchantId(),
],
+ Config::CODE_3DSECURE => [
+ 'enabled' => $this->config->isVerify3DSecure(),
+ 'thresholdAmount' => $this->config->getThresholdAmount(),
+ 'specificCountries' => $this->config->get3DSecureSpecificCountries()
+ ]
]
];
}
+
+ /**
+ * Generate a new client token if necessary
+ * @return string
+ */
+ public function getClientToken()
+ {
+ if (empty($this->clientToken)) {
+ $this->clientToken = $this->adapter->generate();
+ }
+
+ return $this->clientToken;
+ }
}
diff --git a/app/code/Magento/BraintreeTwo/Model/Ui/TokenUiComponentProvider.php b/app/code/Magento/BraintreeTwo/Model/Ui/TokenUiComponentProvider.php
new file mode 100644
index 0000000000000..26ee2a1087569
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Model/Ui/TokenUiComponentProvider.php
@@ -0,0 +1,71 @@
+componentFactory = $componentFactory;
+ $this->urlBuilder = $urlBuilder;
+ }
+
+ /**
+ * Get UI component for token
+ * @param PaymentTokenInterface $paymentToken
+ * @return TokenUiComponentInterface
+ */
+ public function getComponentForToken(PaymentTokenInterface $paymentToken)
+ {
+ $jsonDetails = json_decode($paymentToken->getTokenDetails() ?: '{}', true);
+ $component = $this->componentFactory->create(
+ [
+ 'config' => [
+ TokenUiComponentProviderInterface::COMPONENT_NONCE_URL => $this->getNonceRetrieveUrl(),
+ TokenUiComponentProviderInterface::COMPONENT_DETAILS => $jsonDetails,
+ TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash()
+ ],
+ 'name' => 'Magento_BraintreeTwo/js/view/payment/method-renderer/vault'
+ ]
+ );
+
+ return $component;
+ }
+
+ /**
+ * Get url to retrieve payment method nonce
+ * @return string
+ */
+ private function getNonceRetrieveUrl()
+ {
+ return $this->urlBuilder->getUrl(ConfigProvider::CODE . '/payment/getnonce', ['_secure' => true]);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Observer/DataAssignObserver.php b/app/code/Magento/BraintreeTwo/Observer/DataAssignObserver.php
index 8da4f09767cbd..e38425e2fac25 100644
--- a/app/code/Magento/BraintreeTwo/Observer/DataAssignObserver.php
+++ b/app/code/Magento/BraintreeTwo/Observer/DataAssignObserver.php
@@ -14,6 +14,15 @@
class DataAssignObserver extends AbstractDataAssignObserver
{
const PAYMENT_METHOD_NONCE = 'payment_method_nonce';
+ const DEVICE_DATA = 'device_data';
+
+ /**
+ * @var array
+ */
+ protected $additionalInformationList = [
+ self::PAYMENT_METHOD_NONCE,
+ self::DEVICE_DATA
+ ];
/**
* @param Observer $observer
@@ -21,17 +30,16 @@ class DataAssignObserver extends AbstractDataAssignObserver
*/
public function execute(Observer $observer)
{
- $method = $this->readMethodArgument($observer);
$data = $this->readDataArgument($observer);
- /**
- * @TODO should be refactored after interface changes in payment and quote
- */
- $paymentInfo = $method->getInfoInstance();
- if ($data->getDataByKey(self::PAYMENT_METHOD_NONCE) !== null) {
- $paymentInfo->setAdditionalInformation(
- self::PAYMENT_METHOD_NONCE,
- $data->getDataByKey(self::PAYMENT_METHOD_NONCE)
- );
+ $paymentInfo = $this->readPaymentModelArgument($observer);
+
+ foreach ($this->additionalInformationList as $additionalInformationKey) {
+ if ($data->getDataByKey($additionalInformationKey) !== null) {
+ $paymentInfo->setAdditionalInformation(
+ $additionalInformationKey,
+ $data->getDataByKey($additionalInformationKey)
+ );
+ }
}
}
}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Block/FormTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Block/FormTest.php
index 100a8d44f2b84..4c95ff76508f7 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Block/FormTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Block/FormTest.php
@@ -14,7 +14,6 @@
/**
* Class FormTest
- * @package Magento\BraintreeTwo\Test\Unit\Block
*/
class FormTest extends \PHPUnit_Framework_TestCase
{
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Controller/Payment/GetNonceTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Controller/Payment/GetNonceTest.php
new file mode 100644
index 0000000000000..b7550e7c60a5f
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Controller/Payment/GetNonceTest.php
@@ -0,0 +1,203 @@
+initResultFactoryMock();
+
+ $this->request = $this->getMockBuilder(RequestInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getParam'])
+ ->getMock();
+
+ $this->command = $this->getMockBuilder(GetPaymentNonceCommand::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['execute', '__wakeup'])
+ ->getMock();
+
+ $this->commandResult = $this->getMockBuilder(CommandResultInterface::class)
+ ->setMethods(['get'])
+ ->getMock();
+
+ $this->session = $this->getMockBuilder(Session::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getCustomerId'])
+ ->getMock();
+
+ $this->logger = $this->getMock(LoggerInterface::class);
+
+ $context = $this->getMockBuilder(Context::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $context->expects(static::any())
+ ->method('getRequest')
+ ->willReturn($this->request);
+ $context->expects(static::any())
+ ->method('getResultFactory')
+ ->willReturn($this->resultFactory);
+
+ $managerHelper = new ObjectManager($this);
+ $this->action = $managerHelper->getObject(GetNonce::class, [
+ 'context' => $context,
+ 'logger' => $this->logger,
+ 'session' => $this->session,
+ 'command' => $this->command
+ ]);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Controller\Payment\GetNonce::execute
+ */
+ public function testExecuteWithException()
+ {
+ $this->request->expects(static::once())
+ ->method('getParam')
+ ->with('public_hash')
+ ->willReturn(null);
+
+ $this->session->expects(static::once())
+ ->method('getCustomerId')
+ ->willReturn(null);
+
+ $exception = new \Exception('The "publicHash" field does not exists');
+ $this->command->expects(static::once())
+ ->method('execute')
+ ->willThrowException($exception);
+
+ $this->logger->expects(static::once())
+ ->method('critical')
+ ->with($exception);
+
+ $this->result->expects(static::once())
+ ->method('setHttpResponseCode')
+ ->with(Exception::HTTP_BAD_REQUEST);
+ $this->result->expects(static::once())
+ ->method('setData')
+ ->with(['message' => 'Sorry, but something went wrong']);
+
+ $this->action->execute();
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Controller\Payment\GetNonce::execute
+ */
+ public function testExecute()
+ {
+ $customerId = 1;
+ $publicHash = '65b7bae0dcb690d93';
+ $nonce = 'f1hc45';
+
+ $this->request->expects(static::once())
+ ->method('getParam')
+ ->with('public_hash')
+ ->willReturn($publicHash);
+
+ $this->session->expects(static::once())
+ ->method('getCustomerId')
+ ->willReturn($customerId);
+
+ $this->commandResult->expects(static::once())
+ ->method('get')
+ ->willReturn([
+ 'paymentMethodNonce' => $nonce
+ ]);
+ $this->command->expects(static::once())
+ ->method('execute')
+ ->willReturn($this->commandResult);
+
+ $this->result->expects(static::once())
+ ->method('setData')
+ ->with(['paymentMethodNonce' => $nonce]);
+
+ $this->logger->expects(static::never())
+ ->method('critical');
+
+ $this->result->expects(static::never())
+ ->method('setHttpResponseCode');
+
+ $this->action->execute();
+ }
+
+ /**
+ * Create mock for result factory object
+ */
+ private function initResultFactoryMock()
+ {
+ $this->result = $this->getMockBuilder(ResultInterface::class)
+ ->setMethods(['setHttpResponseCode', 'renderResult', 'setHeader', 'setData'])
+ ->getMock();
+
+ $this->resultFactory = $this->getMockBuilder(ResultFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+
+ $this->resultFactory->expects(static::once())
+ ->method('create')
+ ->willReturn($this->result);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php
new file mode 100644
index 0000000000000..53bce5cd4f904
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Command/CaptureStrategyCommandTest.php
@@ -0,0 +1,257 @@
+commandPool = $this->getMockBuilder(CommandPoolInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['get', '__wakeup'])
+ ->getMock();
+
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->initCommandMock();
+ $this->initTransactionRepositoryMock();
+ $this->initFilterBuilderMock();
+ $this->initSearchCriteriaBuilderMock();
+
+ $this->strategyCommand = new CaptureStrategyCommand(
+ $this->commandPool,
+ $this->transactionRepository,
+ $this->filterBuilder,
+ $this->searchCriteriaBuilder,
+ $this->subjectReaderMock
+ );
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Command\CaptureStrategyCommand::execute
+ */
+ public function testSaleExecute()
+ {
+ $paymentData = $this->getPaymentDataObjectMock();
+ $subject['payment'] = $paymentData;
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+
+ $this->payment->expects(static::once())
+ ->method('getAuthorizationTransaction')
+ ->willReturn(false);
+
+ $this->payment->expects(static::never())
+ ->method('getId');
+
+ $this->commandPool->expects(static::once())
+ ->method('get')
+ ->with(CaptureStrategyCommand::SALE)
+ ->willReturn($this->command);
+
+ $this->strategyCommand->execute($subject);
+ }
+
+ /**
+ * @param int $size
+ * @param string $command
+ * @covers \Magento\BraintreeTwo\Gateway\Command\CaptureStrategyCommand::execute
+ * @dataProvider captureDataProvider
+ */
+ public function testCaptureExecute($size, $command)
+ {
+ $paymentData = $this->getPaymentDataObjectMock();
+ $subject['payment'] = $paymentData;
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+
+ $this->payment->expects(static::once())
+ ->method('getAuthorizationTransaction')
+ ->willReturn(true);
+
+ $this->payment->expects(static::once())
+ ->method('getId')
+ ->willReturn(1);
+
+ $this->filterBuilder->expects(static::exactly(2))
+ ->method('setField')
+ ->willReturnSelf();
+ $this->filterBuilder->expects(static::exactly(2))
+ ->method('setValue')
+ ->willReturnSelf();
+
+ $searchCriteria = new SearchCriteria();
+ $this->searchCriteriaBuilder->expects(static::once())
+ ->method('addFilters')
+ ->willReturnSelf();
+ $this->searchCriteriaBuilder->expects(static::once())
+ ->method('create')
+ ->willReturn($searchCriteria);
+
+ $this->transactionRepository->expects(static::once())
+ ->method('getList')
+ ->with($searchCriteria)
+ ->willReturnSelf();
+
+ $this->transactionRepository->expects(static::once())
+ ->method('getTotalCount')
+ ->willReturn($size);
+
+ $this->commandPool->expects(static::once())
+ ->method('get')
+ ->with($command)
+ ->willReturn($this->command);
+
+ $this->strategyCommand->execute($subject);
+ }
+
+ /**
+ * Return variations for command testing
+ */
+ public function captureDataProvider()
+ {
+ return [
+ ['collectionSize' => 0, 'command' => CaptureStrategyCommand::CAPTURE],
+ ['collectionSize' => 1, 'command' => CaptureStrategyCommand::CLONE_TRANSACTION]
+ ];
+ }
+
+ /**
+ * Create mock for payment data object and order payment
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getPaymentDataObjectMock()
+ {
+ $this->payment = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getAuthorizationTransaction', 'getId'])
+ ->getMock();
+
+ $mock = $this->getMockBuilder(PaymentDataObject::class)
+ ->setMethods(['getPayment'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mock->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ return $mock;
+ }
+
+ /**
+ * Create mock for gateway command object
+ */
+ private function initCommandMock()
+ {
+ $this->command = $this->getMockBuilder(GatewayCommand::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['execute'])
+ ->getMock();
+
+ $this->command->expects(static::once())
+ ->method('execute')
+ ->willReturn([]);
+ }
+
+ /**
+ * Create mock for filter object
+ */
+ private function initFilterBuilderMock()
+ {
+ $this->filterBuilder = $this->getMockBuilder(FilterBuilder::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setField', 'setValue', 'create', '__wakeup'])
+ ->getMock();
+ }
+
+ /**
+ * Create mock for search criteria object
+ */
+ private function initSearchCriteriaBuilderMock()
+ {
+ $this->searchCriteriaBuilder = $this->getMockBuilder(SearchCriteriaBuilder::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['addFilters', 'create', '__wakeup'])
+ ->getMock();
+ }
+
+ /**
+ * Create mock for transaction repository
+ */
+ private function initTransactionRepositoryMock()
+ {
+ $this->transactionRepository = $this->getMockBuilder(TransactionRepositoryInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getList', 'getTotalCount', 'delete', 'get', 'save', 'create', '__wakeup'])
+ ->getMock();
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php
new file mode 100644
index 0000000000000..7e75dee359b78
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Command/GetPaymentNonceCommandTest.php
@@ -0,0 +1,300 @@
+paymentToken = $this->getMockBuilder(PaymentToken::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGatewayToken'])
+ ->getMock();
+
+ $this->tokenManagement = $this->getMockBuilder(PaymentTokenManagement::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getByPublicHash'])
+ ->getMock();
+
+ $this->adapter = $this->getMockBuilder(BraintreeAdapter::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['createNonce'])
+ ->getMock();
+
+ $this->resultFactory = $this->getMockBuilder(ArrayResultFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+
+ $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['readPublicHash', 'readCustomerId'])
+ ->getMock();
+
+ $this->validationResult = $this->getMockBuilder(ResultInterface::class)
+ ->setMethods(['isValid', 'getFailsDescription'])
+ ->getMock();
+
+ $this->responseValidator = $this->getMockBuilder(PaymentNonceResponseValidator::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['validate', 'isValid', 'getFailsDescription'])
+ ->getMock();
+
+ $this->command = new GetPaymentNonceCommand(
+ $this->tokenManagement,
+ $this->adapter,
+ $this->resultFactory,
+ $this->subjectReader,
+ $this->responseValidator
+ );
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Command\GetPaymentNonceCommand::execute
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage The "publicHash" field does not exists
+ */
+ public function testExecuteWithExceptionForPublicHash()
+ {
+ $exception = new \InvalidArgumentException('The "publicHash" field does not exists');
+
+ $this->subjectReader->expects(static::once())
+ ->method('readPublicHash')
+ ->willThrowException($exception);
+
+ $this->subjectReader->expects(static::never())
+ ->method('readCustomerId');
+
+ $this->command->execute([]);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Command\GetPaymentNonceCommand::execute
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage The "customerId" field does not exists
+ */
+ public function testExecuteWithExceptionForCustomerId()
+ {
+ $publicHash = '3wv2m24d2er3';
+
+ $this->subjectReader->expects(static::once())
+ ->method('readPublicHash')
+ ->willReturn($publicHash);
+
+ $exception = new \InvalidArgumentException('The "customerId" field does not exists');
+ $this->subjectReader->expects(static::once())
+ ->method('readCustomerId')
+ ->willThrowException($exception);
+
+ $this->tokenManagement->expects(static::never())
+ ->method('getByPublicHash');
+
+ $this->command->execute(['publicHash' => $publicHash]);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Command\GetPaymentNonceCommand::execute
+ * @expectedException \Exception
+ * @expectedExceptionMessage No available payment tokens
+ */
+ public function testExecuteWithExceptionForTokenManagement()
+ {
+ $publicHash = '3wv2m24d2er3';
+ $customerId = 1;
+
+ $this->subjectReader->expects(static::once())
+ ->method('readPublicHash')
+ ->willReturn($publicHash);
+
+ $this->subjectReader->expects(static::once())
+ ->method('readCustomerId')
+ ->willReturn($customerId);
+
+ $exception = new \Exception('No available payment tokens');
+ $this->tokenManagement->expects(static::once())
+ ->method('getByPublicHash')
+ ->willThrowException($exception);
+
+ $this->paymentToken->expects(static::never())
+ ->method('getGatewayToken');
+
+ $this->command->execute(['publicHash' => $publicHash, 'customerId' => $customerId]);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Command\GetPaymentNonceCommand::execute
+ * @expectedException \Exception
+ * @expectedExceptionMessage Payment method nonce can't be retrieved.
+ */
+ public function testExecuteWithFailedValidation()
+ {
+ $publicHash = '3wv2m24d2er3';
+ $customerId = 1;
+ $token = 'jd2vnq';
+
+ $this->subjectReader->expects(static::once())
+ ->method('readPublicHash')
+ ->willReturn($publicHash);
+
+ $this->subjectReader->expects(static::once())
+ ->method('readCustomerId')
+ ->willReturn($customerId);
+
+ $this->tokenManagement->expects(static::once())
+ ->method('getByPublicHash')
+ ->with($publicHash, $customerId)
+ ->willReturn($this->paymentToken);
+
+ $this->paymentToken->expects(static::once())
+ ->method('getGatewayToken')
+ ->willReturn($token);
+
+ $obj = new \stdClass();
+ $obj->success = false;
+ $this->adapter->expects(static::once())
+ ->method('createNonce')
+ ->with($token)
+ ->willReturn($obj);
+
+ $this->responseValidator->expects(static::once())
+ ->method('validate')
+ ->with(['response' => ['object' => $obj]])
+ ->willReturn($this->validationResult);
+
+ $this->validationResult->expects(static::once())
+ ->method('isValid')
+ ->willReturn(false);
+
+ $this->validationResult->expects(static::once())
+ ->method('getFailsDescription')
+ ->willReturn(['Payment method nonce can\'t be retrieved.']);
+
+ $this->resultFactory->expects(static::never())
+ ->method('create');
+
+ $this->command->execute(['publicHash' => $publicHash, 'customerId' => $customerId]);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Command\GetPaymentNonceCommand::execute
+ */
+ public function testExecute()
+ {
+ $publicHash = '3wv2m24d2er3';
+ $customerId = 1;
+ $token = 'jd2vnq';
+ $nonce = 's1dj23';
+
+ $this->subjectReader->expects(static::once())
+ ->method('readPublicHash')
+ ->willReturn($publicHash);
+
+ $this->subjectReader->expects(static::once())
+ ->method('readCustomerId')
+ ->willReturn($customerId);
+
+ $this->tokenManagement->expects(static::once())
+ ->method('getByPublicHash')
+ ->with($publicHash, $customerId)
+ ->willReturn($this->paymentToken);
+
+ $this->paymentToken->expects(static::once())
+ ->method('getGatewayToken')
+ ->willReturn($token);
+
+ $obj = new \stdClass();
+ $obj->success = true;
+ $obj->paymentMethodNonce = new \stdClass();
+ $obj->paymentMethodNonce->nonce = $nonce;
+ $this->adapter->expects(static::once())
+ ->method('createNonce')
+ ->with($token)
+ ->willReturn($obj);
+
+ $this->responseValidator->expects(static::once())
+ ->method('validate')
+ ->with(['response' => ['object' => $obj]])
+ ->willReturn($this->validationResult);
+
+ $this->validationResult->expects(static::once())
+ ->method('isValid')
+ ->willReturn(true);
+
+ $this->validationResult->expects(static::never())
+ ->method('getFailsDescription');
+
+ $expected = $this->getMockBuilder(ArrayResult::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['get'])
+ ->getMock();
+ $expected->expects(static::once())
+ ->method('get')
+ ->willReturn(['paymentMethodNonce' => $nonce]);
+ $this->resultFactory->expects(static::once())
+ ->method('create')
+ ->willReturn($expected);
+
+ $actual = $this->command->execute(['publicHash' => $publicHash, 'customerId' => $customerId]);
+ static::assertEquals($expected, $actual);
+ static::assertEquals($nonce, $actual->get()['paymentMethodNonce']);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Config/ConfigTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Config/ConfigTest.php
index c275b3a8aa2de..ec998eb136e03 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Config/ConfigTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Config/ConfigTest.php
@@ -7,35 +7,21 @@
namespace Magento\BraintreeTwo\Test\Unit\Gateway\Config;
use Magento\BraintreeTwo\Gateway\Config\Config;
-use Magento\BraintreeTwo\Model\Adapter\BraintreeClientToken;
-use Magento\BraintreeTwo\Model\Adapter\BraintreeConfiguration;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
/**
* Class ConfigTest
- *
*/
class ConfigTest extends \PHPUnit_Framework_TestCase
{
const METHOD_CODE = 'braintree';
- const CLIENT_TOKEN = 'token';
/**
* @var Config
*/
private $model;
- /**
- * @var BraintreeConfiguration|\PHPUnit_Framework_MockObject_MockObject
- */
- private $braintreeConfigurationMock;
-
- /**
- * @var BraintreeClientToken|\PHPUnit_Framework_MockObject_MockObject
- */
- private $braintreeClientTokenMock;
-
/**
* @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
*/
@@ -44,96 +30,9 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->scopeConfigMock = $this->getMock(ScopeConfigInterface::class);
- $this->braintreeConfigurationMock = $this->getMock(BraintreeConfiguration::class);
- $this->braintreeClientTokenMock = $this->getMock(BraintreeClientToken::class);
-
- $this->model = new Config(
- $this->scopeConfigMock,
- $this->braintreeConfigurationMock,
- $this->braintreeClientTokenMock,
- self::METHOD_CODE
- );
- }
-
- /**
- * Test initCredentials call in constructor when payment is active
- *
- * @covers \Magento\BraintreeTwo\Gateway\Config\Config::initCredentials
- */
- public function testConstructorActive()
- {
- $environment = \Magento\BraintreeTwo\Model\Adminhtml\Source\Environment::ENVIRONMENT_PRODUCTION;
- $merchantId = 'merchantId';
- $publicKey = 'public_key';
- $privateKey = 'private_key';
-
- $this->scopeConfigMock->expects(static::exactly(5))
- ->method('getValue')
- ->willReturnMap(
- [
- [$this->getPath(Config::KEY_ACTIVE), ScopeInterface::SCOPE_STORE, null, 1],
- [$this->getPath(Config::KEY_ENVIRONMENT), ScopeInterface::SCOPE_STORE, null, $environment],
- [$this->getPath(Config::KEY_MERCHANT_ID), ScopeInterface::SCOPE_STORE, null, $merchantId],
- [$this->getPath(Config::KEY_PUBLIC_KEY), ScopeInterface::SCOPE_STORE, null, $publicKey],
- [$this->getPath(Config::KEY_PRIVATE_KEY), ScopeInterface::SCOPE_STORE, null, $privateKey]
- ]
- );
-
- $this->braintreeConfigurationMock->expects(static::once())
- ->method('environment')
- ->with($environment);
- $this->braintreeConfigurationMock->expects(static::once())
- ->method('merchantId')
- ->with($merchantId);
- $this->braintreeConfigurationMock->expects(static::once())
- ->method('publicKey')
- ->with($publicKey);
- $this->braintreeConfigurationMock->expects(static::once())
- ->method('privateKey')
- ->with($privateKey);
-
- $this->model = new Config(
- $this->scopeConfigMock,
- $this->braintreeConfigurationMock,
- $this->braintreeClientTokenMock,
- self::METHOD_CODE
- );
- }
-
- /**
- * Test constructor when payment is inactive
- */
- public function testConstructorInActive()
- {
- $this->scopeConfigMock->expects(static::once())
- ->method('getValue')
- ->with($this->getPath(Config::KEY_ACTIVE), ScopeInterface::SCOPE_STORE, null)
- ->willReturn(0);
- $this->braintreeConfigurationMock->expects(static::never())
- ->method('environment');
- $this->braintreeConfigurationMock->expects(static::never())
- ->method('merchantId');
- $this->braintreeConfigurationMock->expects(static::never())
- ->method('publicKey');
- $this->braintreeConfigurationMock->expects(static::never())
- ->method('privateKey');
- $this->model = new Config(
- $this->scopeConfigMock,
- $this->braintreeConfigurationMock,
- $this->braintreeClientTokenMock,
- self::METHOD_CODE
- );
- }
-
- public function testGetClientToken()
- {
- $this->braintreeClientTokenMock->expects(static::once())
- ->method('generate')
- ->willReturn(self::CLIENT_TOKEN);
-
- static::assertEquals(self::CLIENT_TOKEN, $this->model->getClientToken());
+ $this->model = new Config($this->scopeConfigMock, self::METHOD_CODE);
}
/**
@@ -246,7 +145,7 @@ public function getCcTypesMapperDataProvider()
}
/**
- * @covers \Magento\BraintreeTwo\Gateway\Config\Config::getCountryAvailableCardTypes
+ * @covers \Magento\BraintreeTwo\Gateway\Config\Config::getCountryAvailableCardTypes
* @dataProvider getCountrySpecificCardTypeConfigDataProvider
*/
public function testCountryAvailableCardTypes($data, $countryData)
@@ -262,6 +161,9 @@ public function testCountryAvailableCardTypes($data, $countryData)
}
}
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Config\Config::isCvvEnabled
+ */
public function testUseCvv()
{
$this->scopeConfigMock->expects(static::any())
@@ -272,6 +174,104 @@ public function testUseCvv()
static::assertEquals(true, $this->model->isCvvEnabled());
}
+ /**
+ * @param mixed $data
+ * @param boolean $expected
+ * @dataProvider verify3DSecureDataProvider
+ * @covers \Magento\BraintreeTwo\Gateway\Config\Config::isVerify3DSecure
+ */
+ public function testIsVerify3DSecure($data, $expected)
+ {
+ $this->scopeConfigMock->expects(static::any())
+ ->method('getValue')
+ ->with($this->getPath(Config::KEY_VERIFY_3DSECURE), ScopeInterface::SCOPE_STORE, null)
+ ->willReturn($data);
+ static::assertEquals($expected, $this->model->isVerify3DSecure());
+ }
+
+ /**
+ * Get items to verify 3d secure testing
+ * @return array
+ */
+ public function verify3DSecureDataProvider()
+ {
+ return [
+ ['data' => 1, 'expected' => true],
+ ['data' => true, 'expected' => true],
+ ['data' => '1', 'expected' => true],
+ ['data' => 0, 'expected' => false],
+ ['data' => '0', 'expected' => false],
+ ['data' => false, 'expected' => false],
+ ];
+ }
+
+ /**
+ * @param mixed $data
+ * @param double $expected
+ * @covers \Magento\BraintreeTwo\Gateway\Config\Config::getThresholdAmount
+ * @dataProvider thresholdAmountDataProvider
+ */
+ public function testGetThresholdAmount($data, $expected)
+ {
+ $this->scopeConfigMock->expects(static::any())
+ ->method('getValue')
+ ->with($this->getPath(Config::KEY_THRESHOLD_AMOUNT), ScopeInterface::SCOPE_STORE, null)
+ ->willReturn($data);
+ static::assertEquals($expected, $this->model->getThresholdAmount());
+ }
+
+ /**
+ * Get items for testing threshold amount
+ * @return array
+ */
+ public function thresholdAmountDataProvider()
+ {
+ return [
+ ['data' => '23.01', 'expected' => 23.01],
+ ['data' => -1.02, 'expected' => -1.02],
+ ['data' => true, 'expected' => 1],
+ ['data' => 'true', 'expected' => 0],
+ ['data' => 'abc', 'expected' => 0],
+ ['data' => false, 'expected' => 0],
+ ['data' => 'false', 'expected' => 0],
+ ['data' => 1, 'expected' => 1],
+ ];
+ }
+
+ /**
+ * @param int $value
+ * @param array $expected
+ * @covers \Magento\BraintreeTwo\Gateway\Config\Config::get3DSecureSpecificCountries
+ * @dataProvider threeDSecureSpecificCountriesDataProvider
+ */
+ public function testGet3DSecureSpecificCountries($value, array $expected)
+ {
+ $this->scopeConfigMock->expects(static::at(0))
+ ->method('getValue')
+ ->with($this->getPath(Config::KEY_VERIFY_ALLOW_SPECIFIC), ScopeInterface::SCOPE_STORE, null)
+ ->willReturn($value);
+
+ if ($value !== Config::VALUE_3DSECURE_ALL) {
+ $this->scopeConfigMock->expects(static::at(1))
+ ->method('getValue')
+ ->with($this->getPath(Config::KEY_VERIFY_SPECIFIC), ScopeInterface::SCOPE_STORE, null)
+ ->willReturn('GB,US');
+ }
+ static::assertEquals($expected, $this->model->get3DSecureSpecificCountries());
+ }
+
+ /**
+ * Get variations to test specific countries for 3d secure
+ * @return array
+ */
+ public function threeDSecureSpecificCountriesDataProvider()
+ {
+ return [
+ ['configValue' => 0, 'expected' => []],
+ ['configValue' => 1, 'expected' => ['GB', 'US']],
+ ];
+ }
+
/**
* Return config path
*
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Helper/SubjectReaderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Helper/SubjectReaderTest.php
new file mode 100644
index 0000000000000..169a2a8ecaa6f
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Helper/SubjectReaderTest.php
@@ -0,0 +1,63 @@
+subjectReader = new SubjectReader();
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Helper\SubjectReader::readCustomerId
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage The "customerId" field does not exists
+ */
+ public function testReadCustomerIdWithException()
+ {
+ $this->subjectReader->readCustomerId([]);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Helper\SubjectReader::readCustomerId
+ */
+ public function testReadCustomerId()
+ {
+ $customerId = 1;
+ static::assertEquals($customerId, $this->subjectReader->readCustomerId(['customerId' => $customerId]));
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Helper\SubjectReader::readPublicHash
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage The "publicHash" field does not exists
+ */
+ public function testReadPublicHashWithException()
+ {
+ $this->subjectReader->readPublicHash([]);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Helper\SubjectReader::readPublicHash
+ */
+ public function testReadPublicHash()
+ {
+ $hash = 'fj23djf2o1fd';
+ static::assertEquals($hash, $this->subjectReader->readPublicHash(['publicHash' => $hash]));
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionCloneTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionCloneTest.php
new file mode 100644
index 0000000000000..2dba828a3f586
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionCloneTest.php
@@ -0,0 +1,81 @@
+getMockForAbstractClass(LoggerInterface::class);
+ $this->loggerMock = $this->getMockBuilder(Logger::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->adapter = $this->getMockBuilder(BraintreeAdapter::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->client = new TransactionClone($criticalLogger, $this->loggerMock, $this->adapter);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Http\Client\TransactionSubmitForSettlement::placeRequest
+ */
+ public function testPlaceRequest()
+ {
+ $data = new Successful(['success'], [true]);
+ $this->adapter->expects(static::once())
+ ->method('cloneTransaction')
+ ->willReturn($data);
+
+ /** @var TransferInterface|\PHPUnit_Framework_MockObject_MockObject $transferObjectMock */
+ $transferObjectMock = $this->getTransferObjectMock();
+ $response = $this->client->placeRequest($transferObjectMock);
+ static::assertTrue(is_object($response['object']));
+ static::assertEquals(['object' => $data], $response);
+ }
+
+ /**
+ * @return TransferInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getTransferObjectMock()
+ {
+ $mock = $this->getMock(TransferInterface::class);
+ $mock->expects(static::once())
+ ->method('getBody')
+ ->willReturn([
+ 'transaction_id' => 'vb4b7c6b',
+ 'amount' => 45.00
+ ]);
+
+ return $mock;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php
index af1ad2a8f74f5..d2c26fc00c9d9 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionSaleTest.php
@@ -5,10 +5,11 @@
*/
namespace Magento\BraintreeTwo\Test\Unit\Gateway\Http\Client;
-use Magento\BraintreeTwo\Model\Adapter\BraintreeTransaction;
-use Magento\Payment\Model\Method\Logger;
use Magento\BraintreeTwo\Gateway\Http\Client\TransactionSale;
+use Magento\BraintreeTwo\Model\Adapter\BraintreeAdapter;
use Magento\Payment\Gateway\Http\TransferInterface;
+use Magento\Payment\Model\Method\Logger;
+use Psr\Log\LoggerInterface;
/**
* Class TransactionSaleTest
@@ -26,9 +27,9 @@ class TransactionSaleTest extends \PHPUnit_Framework_TestCase
private $loggerMock;
/**
- * @var BraintreeTransaction|\PHPUnit_Framework_MockObject_MockObject
+ * @var BraintreeAdapter|\PHPUnit_Framework_MockObject_MockObject
*/
- private $braintreeTransactionMock;
+ private $adapter;
/**
* Set up
@@ -37,13 +38,15 @@ class TransactionSaleTest extends \PHPUnit_Framework_TestCase
*/
protected function setUp()
{
+ $criticalLoggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
$this->loggerMock = $this->getMockBuilder(Logger::class)
->disableOriginalConstructor()
->getMock();
- $this->braintreeTransactionMock = $this->getMockBuilder(BraintreeTransaction::class)
+ $this->adapter = $this->getMockBuilder(BraintreeAdapter::class)
+ ->disableOriginalConstructor()
->getMock();
- $this->model = new TransactionSale($this->loggerMock, $this->braintreeTransactionMock);
+ $this->model = new TransactionSale($criticalLoggerMock, $this->loggerMock, $this->adapter);
}
/**
@@ -66,7 +69,7 @@ public function testPlaceRequestException()
]
);
- $this->braintreeTransactionMock->expects($this->once())
+ $this->adapter->expects($this->once())
->method('sale')
->willThrowException(new \Exception('Test messages'));
@@ -84,7 +87,7 @@ public function testPlaceRequestException()
public function testPlaceRequestSuccess()
{
$response = $this->getResponseObject();
- $this->braintreeTransactionMock->expects($this->once())
+ $this->adapter->expects($this->once())
->method('sale')
->with($this->getTransferData())
->willReturn($response)
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php
new file mode 100644
index 0000000000000..d5a3f4bc6a24b
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php
@@ -0,0 +1,103 @@
+getMockForAbstractClass(LoggerInterface::class);
+ $this->logger = $this->getMockBuilder(Logger::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['debug'])
+ ->getMock();
+ $this->adapter = $this->getMockBuilder(BraintreeAdapter::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['submitForSettlement'])
+ ->getMock();
+
+ $this->client = new TransactionSubmitForSettlement(
+ $criticalLoggerMock,
+ $this->logger,
+ $this->adapter
+ );
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Http\Client\TransactionSubmitForSettlement::placeRequest
+ * @expectedException \Magento\Payment\Gateway\Http\ClientException
+ * @expectedExceptionMessage Transaction has been declined
+ */
+ public function testPlaceRequestWithException()
+ {
+ $exception = new \Exception('Transaction has been declined');
+ $this->adapter->expects(static::once())
+ ->method('submitForSettlement')
+ ->willThrowException($exception);
+
+ /** @var TransferInterface|\PHPUnit_Framework_MockObject_MockObject $transferObjectMock */
+ $transferObjectMock = $this->getTransferObjectMock();
+ $this->client->placeRequest($transferObjectMock);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Http\Client\TransactionSubmitForSettlement::placeRequest
+ */
+ public function testPlaceRequest()
+ {
+ $data = new Successful(['success'], [true]);
+ $this->adapter->expects(static::once())
+ ->method('submitForSettlement')
+ ->willReturn($data);
+
+ /** @var TransferInterface|\PHPUnit_Framework_MockObject_MockObject $transferObjectMock */
+ $transferObjectMock = $this->getTransferObjectMock();
+ $response = $this->client->placeRequest($transferObjectMock);
+ static::assertTrue(is_object($response['object']));
+ static::assertEquals(['object' => $data], $response);
+ }
+
+ /**
+ * @return TransferInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getTransferObjectMock()
+ {
+ $mock = $this->getMock(TransferInterface::class);
+ $mock->expects($this->once())
+ ->method('getBody')
+ ->willReturn([
+ 'transaction_id' => 'vb4c6b',
+ 'amount' => 124.00
+ ]);
+
+ return $mock;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/AddressDataBuilderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/AddressDataBuilderTest.php
index e2a432e9fa36c..a37c0a1241639 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/AddressDataBuilderTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/AddressDataBuilderTest.php
@@ -9,7 +9,11 @@
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Payment\Gateway\Data\OrderAdapterInterface;
use Magento\Payment\Gateway\Data\AddressAdapterInterface;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
+/**
+ * Class AddressDataBuilderTest
+ */
class AddressDataBuilderTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -27,17 +31,24 @@ class AddressDataBuilderTest extends \PHPUnit_Framework_TestCase
*/
private $builder;
+ /**
+ * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $subjectReaderMock;
+
public function setUp()
{
$this->paymentDOMock = $this->getMock(PaymentDataObjectInterface::class);
$this->orderMock = $this->getMock(OrderAdapterInterface::class);
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
- $this->builder = new AddressDataBuilder();
+ $this->builder = new AddressDataBuilder($this->subjectReaderMock);
}
/**
* @expectedException \InvalidArgumentException
- * @expectedExceptionMessage Payment data object should be provided
*/
public function testBuildReadPaymentException()
{
@@ -45,18 +56,27 @@ public function testBuildReadPaymentException()
'payment' => null,
];
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willThrowException(new \InvalidArgumentException());
+
$this->builder->build($buildSubject);
}
public function testBuildNoAddresses()
{
- $this->paymentDOMock->expects($this->once())
+ $this->paymentDOMock->expects(static::once())
->method('getOrder')
->willReturn($this->orderMock);
- $this->orderMock->expects($this->once())
+
+ $this->orderMock->expects(static::once())
+ ->method('getOrderIncrementId')
+ ->willReturn('000000100');
+ $this->orderMock->expects(static::once())
->method('getShippingAddress')
->willReturn(null);
- $this->orderMock->expects($this->once())
+ $this->orderMock->expects(static::once())
->method('getBillingAddress')
->willReturn(null);
@@ -64,7 +84,12 @@ public function testBuildNoAddresses()
'payment' => $this->paymentDOMock,
];
- static::assertEmpty($this->builder->build($buildSubject));
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDOMock);
+
+ static::assertEquals(['orderId' => '000000100'], $this->builder->build($buildSubject));
}
/**
@@ -77,13 +102,17 @@ public function testBuild($addressData, $expectedResult)
{
$addressMock = $this->getAddressMock($addressData);
- $this->paymentDOMock->expects($this->once())
+ $this->paymentDOMock->expects(static::once())
->method('getOrder')
->willReturn($this->orderMock);
- $this->orderMock->expects($this->once())
+
+ $this->orderMock->expects(static::once())
+ ->method('getOrderIncrementId')
+ ->willReturn('000000101');
+ $this->orderMock->expects(static::once())
->method('getShippingAddress')
->willReturn($addressMock);
- $this->orderMock->expects($this->once())
+ $this->orderMock->expects(static::once())
->method('getBillingAddress')
->willReturn($addressMock);
@@ -91,7 +120,12 @@ public function testBuild($addressData, $expectedResult)
'payment' => $this->paymentDOMock,
];
- $this->assertEquals($expectedResult, $this->builder->build($buildSubject));
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDOMock);
+
+ self::assertEquals($expectedResult, $this->builder->build($buildSubject));
}
/**
@@ -113,6 +147,7 @@ public function dataProviderBuild()
'post_code' => '00000'
],
[
+ AddressDataBuilder::ORDER_ID => '000000101',
AddressDataBuilder::SHIPPING_ADDRESS => [
AddressDataBuilder::FIRST_NAME => 'John',
AddressDataBuilder::LAST_NAME => 'Smith',
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/CaptureDataBuilderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/CaptureDataBuilderTest.php
new file mode 100644
index 0000000000000..1a5e6d7cd0863
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/CaptureDataBuilderTest.php
@@ -0,0 +1,117 @@
+paymentDO = $this->getMock(PaymentDataObjectInterface::class);
+ $this->payment = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->builder = new CaptureDataBuilder($this->subjectReaderMock);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Request\CaptureDataBuilder::build
+ * @expectedException \Magento\Framework\Exception\LocalizedException
+ * @expectedExceptionMessage No authorization transaction to proceed capture.
+ */
+ public function testBuildWithException()
+ {
+ $amount = 10.00;
+ $buildSubject = [
+ 'payment' => $this->paymentDO,
+ 'amount' => $amount
+ ];
+
+ $this->payment->expects(static::once())
+ ->method('getCcTransId')
+ ->willReturn('');
+
+ $this->paymentDO->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDO);
+
+ $this->builder->build($buildSubject);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Request\CaptureDataBuilder::build
+ */
+ public function testBuild()
+ {
+ $transactionId = 'b3b99d';
+ $amount = 10.00;
+
+ $expected = [
+ 'transaction_id' => $transactionId,
+ 'amount' => $amount
+ ];
+
+ $buildSubject = [
+ 'payment' => $this->paymentDO,
+ 'amount' => $amount
+ ];
+
+ $this->payment->expects(static::once())
+ ->method('getCcTransId')
+ ->willReturn($transactionId);
+
+ $this->paymentDO->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDO);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readAmount')
+ ->with($buildSubject)
+ ->willReturn($amount);
+
+ static::assertEquals($expected, $this->builder->build($buildSubject));
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php
index 79148e1f25b01..e2cca39949797 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/CustomerDataBuilderTest.php
@@ -9,7 +9,11 @@
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Payment\Gateway\Data\OrderAdapterInterface;
use Magento\Payment\Gateway\Data\AddressAdapterInterface;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
+/**
+ * Class CustomerDataBuilderTest
+ */
class CustomerDataBuilderTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -27,17 +31,24 @@ class CustomerDataBuilderTest extends \PHPUnit_Framework_TestCase
*/
private $builder;
+ /**
+ * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $subjectReaderMock;
+
public function setUp()
{
$this->paymentDOMock = $this->getMock(PaymentDataObjectInterface::class);
$this->orderMock = $this->getMock(OrderAdapterInterface::class);
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
- $this->builder = new CustomerDataBuilder();
+ $this->builder = new CustomerDataBuilder($this->subjectReaderMock);
}
/**
* @expectedException \InvalidArgumentException
- * @expectedExceptionMessage Payment data object should be provided
*/
public function testBuildReadPaymentException()
{
@@ -45,6 +56,11 @@ public function testBuildReadPaymentException()
'payment' => null,
];
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willThrowException(new \InvalidArgumentException());
+
$this->builder->build($buildSubject);
}
@@ -58,10 +74,10 @@ public function testBuild($billingData, $expectedResult)
{
$billingMock = $this->getBillingMock($billingData);
- $this->paymentDOMock->expects($this->once())
+ $this->paymentDOMock->expects(static::once())
->method('getOrder')
->willReturn($this->orderMock);
- $this->orderMock->expects($this->once())
+ $this->orderMock->expects(static::once())
->method('getBillingAddress')
->willReturn($billingMock);
@@ -69,7 +85,12 @@ public function testBuild($billingData, $expectedResult)
'payment' => $this->paymentDOMock,
];
- $this->assertEquals($expectedResult, $this->builder->build($buildSubject));
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDOMock);
+
+ self::assertEquals($expectedResult, $this->builder->build($buildSubject));
}
/**
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php
new file mode 100644
index 0000000000000..9c455d2bcb8b9
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/KountPaymentDataBuilderTest.php
@@ -0,0 +1,118 @@
+paymentDO = $this->getMock(PaymentDataObjectInterface::class);
+ $this->configMock = $this->getMockBuilder(Config::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->paymentMock = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->builder = new KountPaymentDataBuilder($this->configMock, $this->subjectReaderMock);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testBuildReadPaymentException()
+ {
+ $buildSubject = [];
+
+ $this->configMock->expects(static::once())
+ ->method('hasFraudProtection')
+ ->willReturn(true);
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willThrowException(new \InvalidArgumentException());
+
+ $this->builder->build($buildSubject);
+ }
+
+ public function testBuild()
+ {
+ $additionalData = [
+ DataAssignObserver::DEVICE_DATA => self::DEVICE_DATA
+ ];
+
+ $expectedResult = [
+ KountPaymentDataBuilder::DEVICE_DATA => self::DEVICE_DATA,
+ ];
+
+ $buildSubject = ['payment' => $this->paymentDO];
+
+ $this->paymentMock->expects(static::exactly(count($additionalData)))
+ ->method('getAdditionalInformation')
+ ->willReturn($additionalData);
+
+ $this->configMock->expects(static::once())
+ ->method('hasFraudProtection')
+ ->willReturn(true);
+
+ $this->paymentDO->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->paymentMock);
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDO);
+
+ static::assertEquals(
+ $expectedResult,
+ $this->builder->build($buildSubject)
+ );
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php
index 903f64da383d6..1a95153293932 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/PaymentDataBuilderTest.php
@@ -5,12 +5,16 @@
*/
namespace Magento\BraintreeTwo\Test\Unit\Gateway\Request;
-use Magento\BraintreeTwo\Gateway\Request\PaymentDataBuilder;
-use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\BraintreeTwo\Gateway\Config\Config;
+use Magento\BraintreeTwo\Gateway\Request\PaymentDataBuilder;
use Magento\BraintreeTwo\Observer\DataAssignObserver;
+use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Sales\Model\Order\Payment;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
+/**
+ * Class PaymentDataBuilderTest
+ */
class PaymentDataBuilderTest extends \PHPUnit_Framework_TestCase
{
const PAYMENT_METHOD_NONCE = 'nonce';
@@ -36,6 +40,11 @@ class PaymentDataBuilderTest extends \PHPUnit_Framework_TestCase
*/
private $paymentDO;
+ /**
+ * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $subjectReaderMock;
+
public function setUp()
{
$this->paymentDO = $this->getMock(PaymentDataObjectInterface::class);
@@ -45,24 +54,30 @@ public function setUp()
$this->paymentMock = $this->getMockBuilder(Payment::class)
->disableOriginalConstructor()
->getMock();
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
- $this->builder = new PaymentDataBuilder($this->configMock);
+ $this->builder = new PaymentDataBuilder($this->configMock, $this->subjectReaderMock);
}
/**
* @expectedException \InvalidArgumentException
- * @expectedExceptionMessage Payment data object should be provided
*/
public function testBuildReadPaymentException()
{
$buildSubject = [];
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willThrowException(new \InvalidArgumentException());
+
$this->builder->build($buildSubject);
}
/**
* @expectedException \InvalidArgumentException
- * @expectedExceptionMessage Amount should be provided
*/
public function testBuildReadAmountException()
{
@@ -71,15 +86,31 @@ public function testBuildReadAmountException()
'amount' => null
];
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDO);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readAmount')
+ ->with($buildSubject)
+ ->willThrowException(new \InvalidArgumentException());
+
$this->builder->build($buildSubject);
}
public function testBuild()
{
+ $additionalData = [
+ [
+ DataAssignObserver::PAYMENT_METHOD_NONCE,
+ self::PAYMENT_METHOD_NONCE
+ ]
+ ];
+
$expectedResult = [
PaymentDataBuilder::AMOUNT => 10.00,
PaymentDataBuilder::PAYMENT_METHOD_NONCE => self::PAYMENT_METHOD_NONCE,
- PaymentDataBuilder::MERCHANT_ACCOUNT_ID => self::MERCHANT_ACCOUNT_ID
+ PaymentDataBuilder::MERCHANT_ACCOUNT_ID => self::MERCHANT_ACCOUNT_ID,
];
$buildSubject = [
@@ -87,10 +118,9 @@ public function testBuild()
'amount' => 10.00
];
- $this->paymentMock->expects(static::once())
+ $this->paymentMock->expects(static::exactly(count($additionalData)))
->method('getAdditionalInformation')
- ->with(DataAssignObserver::PAYMENT_METHOD_NONCE)
- ->willReturn(self::PAYMENT_METHOD_NONCE);
+ ->willReturnMap($additionalData);
$this->configMock->expects(static::once())
->method('getValue')
@@ -101,6 +131,15 @@ public function testBuild()
->method('getPayment')
->willReturn($this->paymentMock);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDO);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readAmount')
+ ->with($buildSubject)
+ ->willReturn(10.00);
+
static::assertEquals(
$expectedResult,
$this->builder->build($buildSubject)
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/ThreeDSecureDataBuilderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/ThreeDSecureDataBuilderTest.php
new file mode 100644
index 0000000000000..de7ee0e9f2872
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/ThreeDSecureDataBuilderTest.php
@@ -0,0 +1,165 @@
+initOrderMock();
+
+ $this->paymentDO = $this->getMockBuilder(PaymentDataObjectInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getOrder', 'getPayment'])
+ ->getMock();
+ $this->paymentDO->expects(static::once())
+ ->method('getOrder')
+ ->willReturn($this->order);
+
+ $this->configMock = $this->getMockBuilder(Config::class)
+ ->setMethods(['isVerify3DSecure', 'getThresholdAmount', 'get3DSecureSpecificCountries'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->builder = new ThreeDSecureDataBuilder($this->configMock, $this->subjectReaderMock);
+ }
+
+ /**
+ * @param bool $verify
+ * @param float $thresholdAmount
+ * @param string $countryId
+ * @param array $countries
+ * @param array $expected
+ * @covers \Magento\BraintreeTwo\Gateway\Request\ThreeDSecureDataBuilder::build
+ * @dataProvider buildDataProvider
+ */
+ public function testBuild($verify, $thresholdAmount, $countryId, array $countries, array $expected)
+ {
+ $buildSubject = [
+ 'payment' => $this->paymentDO,
+ 'amount' => 25
+ ];
+
+ $this->configMock->expects(static::once())
+ ->method('isVerify3DSecure')
+ ->willReturn($verify);
+
+ $this->configMock->expects(static::any())
+ ->method('getThresholdAmount')
+ ->willReturn($thresholdAmount);
+
+ $this->configMock->expects(static::any())
+ ->method('get3DSecureSpecificCountries')
+ ->willReturn($countries);
+
+ $this->billingAddress->expects(static::any())
+ ->method('getCountryId')
+ ->willReturn($countryId);
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($buildSubject)
+ ->willReturn($this->paymentDO);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readAmount')
+ ->with($buildSubject)
+ ->willReturn(25);
+
+ $result = $this->builder->build($buildSubject);
+ static::assertEquals($expected, $result);
+ }
+
+ /**
+ * Get list of variations for build test
+ * @return array
+ */
+ public function buildDataProvider()
+ {
+ return [
+ ['verify' => true, 'amount' => 20, 'countryId' => 'US', 'countries' => [], 'result' => [
+ 'options' => [
+ 'three_d_secure' => [
+ 'required' => true
+ ]
+ ]
+ ]],
+ ['verify' => true, 'amount' => 0, 'countryId' => 'US', 'countries' => ['US', 'GB'], 'result' => [
+ 'options' => [
+ 'three_d_secure' => [
+ 'required' => true
+ ]
+ ]
+ ]],
+ ['verify' => true, 'amount' => 40, 'countryId' => 'US', 'countries' => [], 'result' => []],
+ ['verify' => false, 'amount' => 40, 'countryId' => 'US', 'countries' => [], 'result' => []],
+ ['verify' => false, 'amount' => 20, 'countryId' => 'US', 'countries' => [], 'result' => []],
+ ['verify' => true, 'amount' => 20, 'countryId' => 'CA', 'countries' => ['US', 'GB'], 'result' => []],
+ ];
+ }
+
+ /**
+ * Create mock object for order adapter
+ */
+ private function initOrderMock()
+ {
+ $this->billingAddress = $this->getMockBuilder(AddressAdapter::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getCountryId'])
+ ->getMock();
+
+ $this->order = $this->getMockBuilder(OrderAdapter::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getBillingAddress'])
+ ->getMock();
+
+ $this->order->expects(static::any())
+ ->method('getBillingAddress')
+ ->willReturn($this->billingAddress);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/VaultDataBuilderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/VaultDataBuilderTest.php
new file mode 100644
index 0000000000000..ab11cb2bf82c6
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Request/VaultDataBuilderTest.php
@@ -0,0 +1,64 @@
+vaultPaymentMock = $this->getMock(VaultPaymentInterface::class);
+
+ $this->builder = new VaultDataBuilder($this->vaultPaymentMock);
+ }
+
+ public function testBuild()
+ {
+ $expectedResult = [
+ VaultDataBuilder::OPTIONS => [VaultDataBuilder::STORE_IN_VAULT_ON_SUCCESS => true]
+ ];
+
+ $buildSubject = [];
+
+ $this->vaultPaymentMock->expects(self::once())
+ ->method('isActiveForPayment')
+ ->willReturn(true);
+
+ static::assertEquals(
+ $expectedResult,
+ $this->builder->build($buildSubject)
+ );
+ }
+
+ public function testBuildWithSwitchedOffVault()
+ {
+ $expectedResult = [];
+
+ $buildSubject = [];
+
+ $this->vaultPaymentMock->expects(self::once())
+ ->method('isActiveForPayment')
+ ->willReturn(false);
+
+ static::assertEquals(
+ $expectedResult,
+ $this->builder->build($buildSubject)
+ );
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CaptureDetailsHandlerTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CaptureDetailsHandlerTest.php
new file mode 100644
index 0000000000000..8cbab55ad4652
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CaptureDetailsHandlerTest.php
@@ -0,0 +1,91 @@
+payment = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setIsTransactionClosed'])
+ ->getMock();
+ $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->captureHandler = new CaptureDetailsHandler($this->subjectReader);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Response\CaptureDetailsHandler::handle
+ */
+ public function testHandle()
+ {
+ $paymentData = $this->getPaymentDataObjectMock();
+ $subject['payment'] = $paymentData;
+
+ $this->payment->expects(static::once())
+ ->method('setIsTransactionClosed')
+ ->with(false);
+
+ $response = [
+ 'object' => [
+ 'success' => true
+ ]
+ ];
+
+ $this->subjectReader->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+
+ $this->captureHandler->handle($subject, $response);
+ }
+
+ /**
+ * Create mock for payment data object and order payment
+ * @return MockObject
+ */
+ private function getPaymentDataObjectMock()
+ {
+ $mock = $this->getMockBuilder(PaymentDataObject::class)
+ ->setMethods(['getPayment'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mock->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ return $mock;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php
index 1bdce17368595..5b65be7de10ae 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CardDetailsHandlerTest.php
@@ -5,21 +5,19 @@
*/
namespace Magento\BraintreeTwo\Test\Unit\Gateway\Response;
-use Braintree_Result_Successful;
-use Braintree_Transaction;
+use Braintree\Result\Successful;
+use Braintree\Transaction;
use Magento\BraintreeTwo\Gateway\Response\CardDetailsHandler;
-use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Payment\Gateway\Data\PaymentDataObject;
use Magento\Sales\Model\Order\Payment;
use Magento\BraintreeTwo\Gateway\Config\Config;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
/**
* Class CardDetailsHandlerTest
- * @package Magento\BraintreeTwo\Test\Unit\Gateway\Response
*/
class CardDetailsHandlerTest extends \PHPUnit_Framework_TestCase
{
-
/**
* @var \Magento\BraintreeTwo\Gateway\Response\CardDetailsHandler
*/
@@ -35,12 +33,19 @@ class CardDetailsHandlerTest extends \PHPUnit_Framework_TestCase
*/
private $config;
+ /**
+ * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $subjectReaderMock;
+
protected function setUp()
{
$this->initConfigMock();
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
- $helper = new ObjectManager($this);
- $this->cardHandler = $helper->getObject(CardDetailsHandler::class, ['config' => $this->config]);
+ $this->cardHandler = new CardDetailsHandler($this->config, $this->subjectReaderMock);
}
/**
@@ -49,11 +54,19 @@ protected function setUp()
public function testHandle()
{
$paymentData = $this->getPaymentDataObjectMock();
- $subject['payment'] = $paymentData;
-
- $response = [
- 'object' => $this->getBraintreeTransaction()
- ];
+ $transaction = $this->getBraintreeTransaction();
+
+ $subject = ['payment' => $paymentData];
+ $response = ['object' => $transaction];
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readTransaction')
+ ->with($response)
+ ->willReturn($transaction);
$this->payment->expects(static::once())
->method('setCcLast4');
@@ -122,7 +135,7 @@ private function getPaymentDataObjectMock()
/**
* Create Braintree transaction
- * @return \PHPUnit_Framework_MockObject_MockObject
+ * @return \Braintree\Transaction
*/
private function getBraintreeTransaction()
{
@@ -135,18 +148,8 @@ private function getBraintreeTransaction()
'last4' => 1231
]
];
- $transaction = Braintree_Transaction::factory($attributes);
-
- $mock = $this->getMockBuilder(Braintree_Result_Successful::class)
- ->disableOriginalConstructor()
- ->setMethods(['__get'])
- ->getMock();
+ $transaction = Transaction::factory($attributes);
- $mock->expects(static::once())
- ->method('__get')
- ->with('transaction')
- ->willReturn($transaction);
-
- return $mock;
+ return $transaction;
}
}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CloneDetailsHandlerTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CloneDetailsHandlerTest.php
new file mode 100644
index 0000000000000..4c613476ff016
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/CloneDetailsHandlerTest.php
@@ -0,0 +1,111 @@
+payment = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'setIsTransactionClosed', 'setTransactionId'
+ ])
+ ->getMock();
+ $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cloneHandler = new CloneDetailsHandler($this->subjectReader);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Response\CloneDetailsHandler::handle
+ */
+ public function testHandle()
+ {
+ $paymentData = $this->getPaymentDataObjectMock();
+ $transaction = $this->getBraintreeTransaction();
+ $subject['payment'] = $paymentData;
+
+ $this->payment->expects(static::once())
+ ->method('setTransactionId')
+ ->with(self::TRANSACTION_ID);
+
+ $response = ['object' => $transaction];
+
+ $this->subjectReader->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+ $this->subjectReader->expects(self::once())
+ ->method('readTransaction')
+ ->with($response)
+ ->willReturn($transaction);
+
+ $this->cloneHandler->handle($subject, $response);
+ }
+
+ /**
+ * Create mock for payment data object and order payment
+ * @return MockObject
+ */
+ private function getPaymentDataObjectMock()
+ {
+ $mock = $this->getMockBuilder(PaymentDataObject::class)
+ ->setMethods(['getPayment'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mock->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ return $mock;
+ }
+
+ /**
+ * Create Braintree transaction
+ * @return MockObject
+ */
+ private function getBraintreeTransaction()
+ {
+ $attributes = [
+ 'id' => self::TRANSACTION_ID,
+ ];
+
+ $transaction = Transaction::factory($attributes);
+
+ return $transaction;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php
index 7dfd216703d60..138d772141420 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/PaymentDetailsHandlerTest.php
@@ -5,16 +5,16 @@
*/
namespace Magento\BraintreeTwo\Test\Unit\Gateway\Response;
-use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Braintree\Transaction;
use Magento\BraintreeTwo\Gateway\Response\PaymentDetailsHandler;
-use Magento\Sales\Model\Order\Payment;
use Magento\Payment\Gateway\Data\PaymentDataObject;
-use Braintree_Transaction;
-use Braintree_Result_Successful;
+use Magento\Sales\Model\Order;
+use Magento\Sales\Model\Order\Payment;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
/**
* Class PaymentDetailsHandlerTest
- * @package Magento\BraintreeTwo\Test\Unit\Gateway\Response
*/
class PaymentDetailsHandlerTest extends \PHPUnit_Framework_TestCase
{
@@ -26,23 +26,30 @@ class PaymentDetailsHandlerTest extends \PHPUnit_Framework_TestCase
private $paymentHandler;
/**
- * @var \Magento\Sales\Model\Order\Payment|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Sales\Model\Order\Payment|MockObject
*/
private $payment;
- protected function setUp()
- {
- $helper = new ObjectManager($this);
- $this->paymentHandler = $helper->getObject(PaymentDetailsHandler::class);
- }
-
/**
- * @covers \Magento\BraintreeTwo\Gateway\Response\PaymentDetailsHandler::handle
+ * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
*/
- public function testHandle()
+ private $subjectReaderMock;
+
+ protected function setUp()
{
- $paymentData = $this->getPaymentDataObjectMock();
- $subject['payment'] = $paymentData;
+ $this->payment = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'setTransactionId',
+ 'setCcTransId',
+ 'setLastTransId',
+ 'setAdditionalInformation',
+ 'setIsTransactionClosed'
+ ])
+ ->getMock();
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
$this->payment->expects(static::once())
->method('setTransactionId');
@@ -52,33 +59,41 @@ public function testHandle()
->method('setLastTransId');
$this->payment->expects(static::once())
->method('setIsTransactionClosed');
- $this->payment->expects(static::exactly(6))
+ $this->payment->expects(static::any())
->method('setAdditionalInformation');
- $response = [
- 'object' => $this->getBraintreeTransaction()
- ];
+ $this->paymentHandler = new PaymentDetailsHandler($this->subjectReaderMock);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Response\PaymentDetailsHandler::handle
+ */
+ public function testHandle()
+ {
+ $paymentData = $this->getPaymentDataObjectMock();
+ $transaction = $this->getBraintreeTransaction();
+
+ $subject = ['payment' => $paymentData];
+ $response = ['object' => $transaction];
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readTransaction')
+ ->with($response)
+ ->willReturn($transaction);
$this->paymentHandler->handle($subject, $response);
}
/**
* Create mock for payment data object and order payment
- * @return \PHPUnit_Framework_MockObject_MockObject
+ * @return MockObject
*/
private function getPaymentDataObjectMock()
{
- $this->payment = $this->getMockBuilder(Payment::class)
- ->disableOriginalConstructor()
- ->setMethods([
- 'setTransactionId',
- 'setCcTransId',
- 'setLastTransId',
- 'setAdditionalInformation',
- 'setIsTransactionClosed',
- ])
- ->getMock();
-
$mock = $this->getMockBuilder(PaymentDataObject::class)
->setMethods(['getPayment'])
->disableOriginalConstructor()
@@ -93,7 +108,7 @@ private function getPaymentDataObjectMock()
/**
* Create Braintree transaction
- * @return \PHPUnit_Framework_MockObject_MockObject
+ * @return MockObject
*/
private function getBraintreeTransaction()
{
@@ -104,21 +119,11 @@ private function getBraintreeTransaction()
'cvvResponseCode' => 'M',
'processorAuthorizationCode' => 'W1V8XK',
'processorResponseCode' => '1000',
- 'processorResponseText' => 'Approved',
+ 'processorResponseText' => 'Approved'
];
- $transaction = Braintree_Transaction::factory($attributes);
-
- $mock = $this->getMockBuilder(Braintree_Result_Successful::class)
- ->disableOriginalConstructor()
- ->setMethods(['__get'])
- ->getMock();
-
- $mock->expects(static::once())
- ->method('__get')
- ->with('transaction')
- ->willReturn($transaction);
+ $transaction = \Braintree\Transaction::factory($attributes);
- return $mock;
+ return $transaction;
}
}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/RiskDataHandlerTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/RiskDataHandlerTest.php
new file mode 100644
index 0000000000000..c4aa2e4e251bb
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/RiskDataHandlerTest.php
@@ -0,0 +1,123 @@
+subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->riskDataHandler = new RiskDataHandler($this->subjectReaderMock);
+ }
+
+ /**
+ * Run test for handle method
+ */
+ public function testHandle()
+ {
+ $paymentData = $this->getPaymentDataObjectMock();
+ $transaction = $this->getBraintreeTransactionMock();
+
+ $response = [
+ 'object' => $transaction
+ ];
+ $handlingSubject = [
+ 'payment' =>$paymentData,
+ ];
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($handlingSubject)
+ ->willReturn($paymentData);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readTransaction')
+ ->with($response)
+ ->willReturn($transaction);
+
+ $this->riskDataHandler->handle($handlingSubject, $response);
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getBraintreeTransactionMock()
+ {
+ $transaction = \Braintree\Transaction::factory([]);
+ $transaction->_set(
+ 'riskData',
+ RiskData::factory(
+ [
+ 'id' => 'test-id',
+ 'decision' => 'test-decision',
+ ]
+ )
+ );
+
+ return $transaction;
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getPaymentDataObjectMock()
+ {
+ $mock = $this->getMockBuilder(PaymentDataObjectInterface::class)
+ ->getMockForAbstractClass();
+
+ $mock->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->getPaymentMock());
+
+ return $mock;
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getPaymentMock()
+ {
+ $paymentMock = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $paymentMock->expects(self::at(0))
+ ->method('setAdditionalInformation')
+ ->with(RiskDataHandler::RISK_DATA_ID, 'test-id');
+ $paymentMock->expects(self::at(1))
+ ->method('setAdditionalInformation')
+ ->with(RiskDataHandler::RISK_DATA_DECISION, 'test-decision');
+
+ return $paymentMock;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php
new file mode 100644
index 0000000000000..38b1849761ac6
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/ThreeDSecureDetailsHandlerTest.php
@@ -0,0 +1,134 @@
+payment = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'unsAdditionalInformation',
+ 'hasAdditionalInformation',
+ 'setAdditionalInformation',
+ ])
+ ->getMock();
+
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->handler = new ThreeDSecureDetailsHandler($this->subjectReaderMock);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Response\ThreeDSecureDetailsHandler::handle
+ */
+ public function testHandle()
+ {
+ $paymentData = $this->getPaymentDataObjectMock();
+ $transaction = $this->getBraintreeTransaction();
+
+ $subject = ['payment' => $paymentData];
+ $response = ['object' => $transaction];
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readTransaction')
+ ->with($response)
+ ->willReturn($transaction);
+
+ $this->payment->expects(static::at(1))
+ ->method('setAdditionalInformation')
+ ->with('liabilityShifted', 'Yes');
+ $this->payment->expects(static::at(2))
+ ->method('setAdditionalInformation')
+ ->with('liabilityShiftPossible', 'Yes');
+
+ $this->handler->handle($subject, $response);
+ }
+
+ /**
+ * Create mock for payment data object and order payment
+ * @return MockObject
+ */
+ private function getPaymentDataObjectMock()
+ {
+ $mock = $this->getMockBuilder(PaymentDataObject::class)
+ ->setMethods(['getPayment'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mock->expects(static::once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ return $mock;
+ }
+
+ /**
+ * Create Braintree transaction
+ * @return MockObject
+ */
+ private function getBraintreeTransaction()
+ {
+ $attributes = [
+ 'id' => self::TRANSACTION_ID,
+ 'threeDSecureInfo' => $this->getThreeDSecureInfo()
+ ];
+
+ $transaction = Transaction::factory($attributes);
+
+ return $transaction;
+ }
+
+ /**
+ * Get 3d secure details
+ * @return array
+ */
+ private function getThreeDSecureInfo()
+ {
+ $attributes = [
+ 'liabilityShifted' => 'Yes',
+ 'liabilityShiftPossible' => 'Yes'
+ ];
+
+ return $attributes;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/VaultDetailsHandlerTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/VaultDetailsHandlerTest.php
new file mode 100644
index 0000000000000..423900bdbcc96
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Response/VaultDetailsHandlerTest.php
@@ -0,0 +1,255 @@
+paymentTokenMock = $this->getMockBuilder(PaymentToken::class)
+ ->setMethods(null)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->paymentTokenFactoryMock = $this->getMockBuilder(PaymentTokenFactory::class)
+ ->setMethods(['create'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->paymentTokenFactoryMock->expects(self::once())
+ ->method('create')
+ ->willReturn($this->paymentTokenMock);
+
+ $this->paymentExtension = $this->getMockBuilder(OrderPaymentExtensionInterface::class)
+ ->setMethods(['setVaultPaymentToken', 'getVaultPaymentToken', '__wakeup'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->paymentExtensionFactoryMock = $this->getMockBuilder(OrderPaymentExtensionFactory::class)
+ ->setMethods(['create'])
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->paymentExtensionFactoryMock->expects(self::once())
+ ->method('create')
+ ->willReturn($this->paymentExtension);
+
+ // Sales Order Model
+ $this->salesOrderMock = $this->getMockBuilder(Order::class)
+ ->setMethods(null)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->payment = $this->getMockBuilder(Payment::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'getMethod',
+ 'getOrder'
+ ])
+ ->getMock();
+
+ $this->payment->expects(self::once())
+ ->method('getOrder')
+ ->willReturn($this->salesOrderMock);
+
+ $this->vaultPaymentMock = $this->getMock(VaultPaymentInterface::class);
+
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mapperArray = [
+ "american-express" => "AE",
+ "discover" => "DI",
+ "jcb" => "JCB",
+ "mastercard" => "MC",
+ "master-card" => "MC",
+ "visa" => "VI",
+ "maestro" => "MI",
+ "diners-club" => "DN",
+ "unionpay" => "CUP"
+ ];
+
+ $this->configMock = $this->getMockBuilder(Config::class)
+ ->setMethods(['getCctypesMapper'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->configMock->expects(self::once())
+ ->method('getCctypesMapper')
+ ->willReturn($mapperArray);
+
+ $this->paymentHandler = new VaultDetailsHandler(
+ $this->vaultPaymentMock,
+ $this->paymentTokenFactoryMock,
+ $this->paymentExtensionFactoryMock,
+ $this->configMock,
+ $this->subjectReaderMock
+ );
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Response\VaultDetailsHandler::handle
+ */
+ public function testHandle()
+ {
+ $this->vaultPaymentMock->expects(self::once())
+ ->method('isActiveForPayment')
+ ->willReturn(true);
+
+ $this->paymentExtension->expects(self::once())
+ ->method('setVaultPaymentToken')
+ ->with($this->paymentTokenMock);
+ $this->paymentExtension->expects(self::once())
+ ->method('getVaultPaymentToken')
+ ->willReturn($this->paymentTokenMock);
+
+ $paymentData = $this->getPaymentDataObjectMock();
+ $transaction = $this->getBraintreeTransaction();
+
+ $subject = ['payment' => $paymentData];
+ $response = ['object' => $transaction];
+
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readPayment')
+ ->with($subject)
+ ->willReturn($paymentData);
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readTransaction')
+ ->with($response)
+ ->willReturn($transaction);
+
+ $this->salesOrderMock->setCustomerId(10);
+
+ $this->paymentHandler->handle($subject, $response);
+
+ $this->assertEquals('rh3gd4', $this->paymentTokenMock->getGatewayToken());
+ $this->assertEquals('10', $this->paymentTokenMock->getCustomerId());
+ $this->assertSame($this->paymentTokenMock, $this->payment->getExtensionAttributes()->getVaultPaymentToken());
+ }
+
+ /**
+ * Create mock for payment data object and order payment
+ * @return MockObject
+ */
+ private function getPaymentDataObjectMock()
+ {
+ $mock = $this->getMockBuilder(PaymentDataObject::class)
+ ->setMethods(['getPayment'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $mock->expects($this->once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ return $mock;
+ }
+
+ /**
+ * Create Braintree transaction
+ * @return MockObject
+ */
+ private function getBraintreeTransaction()
+ {
+ $attributes = [
+ 'id' => self::TRANSACTION_ID,
+ 'creditCardDetails' => $this->getCreditCardDetails()
+ ];
+
+ $transaction = Transaction::factory($attributes);
+
+ return $transaction;
+ }
+
+ /**
+ * Create Braintree transaction
+ * @return \Braintree\Transaction\CreditCardDetails
+ */
+ private function getCreditCardDetails()
+ {
+ $attributes = [
+ 'token' => 'rh3gd4',
+ 'bin' => '5421',
+ 'cardType' => 'American Express',
+ 'expirationMonth' => 12,
+ 'expirationYear' => 21,
+ 'last4' => 1231
+ ];
+
+ $creditCardDetails = new CreditCardDetails($attributes);
+
+ return $creditCardDetails;
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php
new file mode 100644
index 0000000000000..b230908cf03b7
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Validator/PaymentNonceResponseValidatorTest.php
@@ -0,0 +1,114 @@
+resultInterfaceFactory = $this->getMockBuilder(ResultInterfaceFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+ $this->subjectReader = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['readResponseObject'])
+ ->getMock();
+
+ $this->validator = new PaymentNonceResponseValidator(
+ $this->resultInterfaceFactory,
+ $this->subjectReader
+ );
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Validator\PaymentNonceResponseValidator::validate
+ */
+ public function testFailedValidate()
+ {
+ $obj = new \stdClass();
+ $obj->success = true;
+ $subject = [
+ 'response' => [
+ 'object' => $obj
+ ]
+ ];
+
+ $this->subjectReader->expects(static::once())
+ ->method('readResponseObject')
+ ->willReturn($obj);
+
+ $result = $this->getMock(ResultInterface::class);
+ $this->resultInterfaceFactory->expects(self::once())
+ ->method('create')
+ ->with([
+ 'isValid' => false,
+ 'failsDescription' => ['Payment method nonce can\'t be retrieved.']
+ ])
+ ->willReturn($result);
+
+ $actual = $this->validator->validate($subject);
+ static::assertEquals($result, $actual);
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Gateway\Validator\PaymentNonceResponseValidator::validatePaymentMethodNonce
+ */
+ public function testValidatePaymentMethodNonce()
+ {
+ $obj = new \stdClass();
+ $obj->success = true;
+ $obj->paymentMethodNonce = new \stdClass();
+ $obj->paymentMethodNonce->nonce = 'fj2hd9239kd1kq9';
+
+ $subject = [
+ 'response' => [
+ 'object' => $obj
+ ]
+ ];
+
+ $this->subjectReader->expects(static::once())
+ ->method('readResponseObject')
+ ->willReturn($obj);
+
+ $result = $this->getMock(ResultInterface::class);
+ $this->resultInterfaceFactory->expects(self::once())
+ ->method('create')
+ ->with([
+ 'isValid' => true,
+ 'failsDescription' => ['Payment method nonce can\'t be retrieved.']
+ ])
+ ->willReturn($result);
+
+ $actual = $this->validator->validate($subject);
+ static::assertEquals($result, $actual);
+ }
+}
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Validator/ResponseValidatorTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Validator/ResponseValidatorTest.php
index cfcb03c3d1b35..01e17651063f6 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Validator/ResponseValidatorTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Gateway/Validator/ResponseValidatorTest.php
@@ -5,9 +5,11 @@
*/
namespace Magento\BraintreeTwo\Test\Unit\Gateway\Validator;
+use Braintree\Transaction;
use Magento\Payment\Gateway\Validator\ResultInterface;
use Magento\Payment\Gateway\Validator\ResultInterfaceFactory;
use Magento\BraintreeTwo\Gateway\Validator\ResponseValidator;
+use Magento\BraintreeTwo\Gateway\Helper\SubjectReader;
/**
* Class ResponseValidatorTest
@@ -24,6 +26,11 @@ class ResponseValidatorTest extends \PHPUnit_Framework_TestCase
*/
private $resultInterfaceFactoryMock;
+ /**
+ * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $subjectReaderMock;
+
/**
* Set up
*
@@ -36,13 +43,18 @@ protected function setUp()
)->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
+ $this->subjectReaderMock = $this->getMockBuilder(SubjectReader::class)
+ ->disableOriginalConstructor()
+ ->getMock();
- $this->responseValidator = new ResponseValidator($this->resultInterfaceFactoryMock);
+ $this->responseValidator = new ResponseValidator(
+ $this->resultInterfaceFactoryMock,
+ $this->subjectReaderMock
+ );
}
/**
* @expectedException \InvalidArgumentException
- * @expectedExceptionMessage Response does not exist
*/
public function testValidateReadResponseException()
{
@@ -50,12 +62,16 @@ public function testValidateReadResponseException()
'response' => null
];
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readResponseObject')
+ ->with($validationSubject)
+ ->willThrowException(new \InvalidArgumentException());
+
$this->responseValidator->validate($validationSubject);
}
/**
* @expectedException \InvalidArgumentException
- * @expectedExceptionMessage Response object does not exist
*/
public function testValidateReadResponseObjectException()
{
@@ -63,10 +79,14 @@ public function testValidateReadResponseObjectException()
'response' => ['object' => null]
];
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readResponseObject')
+ ->with($validationSubject)
+ ->willThrowException(new \InvalidArgumentException());
+
$this->responseValidator->validate($validationSubject);
}
-
/**
* Run test for validate method
*
@@ -81,7 +101,12 @@ public function testValidate(array $validationSubject, $isValid)
/** @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject $resultMock */
$resultMock = $this->getMock(ResultInterface::class);
- $this->resultInterfaceFactoryMock->expects($this->once())
+ $this->subjectReaderMock->expects(self::once())
+ ->method('readResponseObject')
+ ->with($validationSubject)
+ ->willReturn($validationSubject['response']['object']);
+
+ $this->resultInterfaceFactoryMock->expects(self::once())
->method('create')
->with([
'isValid' => $isValid,
@@ -91,7 +116,7 @@ public function testValidate(array $validationSubject, $isValid)
$actualMock = $this->responseValidator->validate($validationSubject);
- $this->assertEquals($resultMock, $actualMock);
+ self::assertEquals($resultMock, $actualMock);
}
/**
@@ -102,7 +127,7 @@ public function dataProviderTestValidate()
$successTrue = new \stdClass();
$successTrue->success = true;
$successTrue->transaction = new \stdClass();
- $successTrue->transaction->status = \Braintree_Transaction::AUTHORIZED;
+ $successTrue->transaction->status = Transaction::AUTHORIZED;
$successFalse = new \stdClass();
$successFalse->success = false;
@@ -110,7 +135,7 @@ public function dataProviderTestValidate()
$transactionDeclined = new \stdClass();
$transactionDeclined->success = true;
$transactionDeclined->transaction = new \stdClass();
- $transactionDeclined->transaction->status = \Braintree_Transaction::SETTLEMENT_DECLINED;
+ $transactionDeclined->transaction->status = Transaction::SETTLEMENT_DECLINED;
return [
[
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CcTypeTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CcTypeTest.php
index 39b65d1d74c52..3e4335499bee8 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CcTypeTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CcTypeTest.php
@@ -11,7 +11,6 @@
/**
* Class CcTypeTest
- * @package Magento\BraintreeTwo\Test\Unit\Helper
*/
class CcTypeTest extends \PHPUnit_Framework_TestCase
{
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CountryTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CountryTest.php
index 01390f9d238d3..a2dcaba980762 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CountryTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Helper/CountryTest.php
@@ -12,7 +12,6 @@
/**
* Class CountryTest
- * @package Magento\BraintreeTwo\Test\Unit\Helper
*/
class CountryTest extends \PHPUnit_Framework_TestCase
{
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Model/Ui/ConfigProviderTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Model/Ui/ConfigProviderTest.php
index 3fbbc73939233..69c3650430dc8 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Model/Ui/ConfigProviderTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Model/Ui/ConfigProviderTest.php
@@ -6,6 +6,7 @@
namespace Magento\BraintreeTwo\Test\Unit\Model\Ui;
use Magento\BraintreeTwo\Gateway\Config\Config;
+use Magento\BraintreeTwo\Model\Adapter\BraintreeAdapter;
use Magento\BraintreeTwo\Model\Ui\ConfigProvider;
/**
@@ -17,16 +18,33 @@ class ConfigProviderTest extends \PHPUnit_Framework_TestCase
{
const SDK_URL = 'https://js.braintreegateway.com/v2/braintree.js';
+ const CLIENT_TOKEN = 'token';
+
/**
* @var Config|\PHPUnit_Framework_MockObject_MockObject
*/
- private $configMock;
+ private $config;
+
+ /**
+ * @var BraintreeAdapter|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $braintreeAdapter;
+
+ /**
+ * @var ConfigProvider
+ */
+ private $configProvider;
protected function setUp()
{
- $this->configMock = $this->getMockBuilder(Config::class)
+ $this->config = $this->getMockBuilder(Config::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->braintreeAdapter = $this->getMockBuilder(BraintreeAdapter::class)
->disableOriginalConstructor()
->getMock();
+
+ $this->configProvider = new ConfigProvider($this->config, $this->braintreeAdapter);
}
/**
@@ -38,17 +56,29 @@ protected function setUp()
*/
public function testGetConfig($config, $expected)
{
- $configProvider = new ConfigProvider($this->configMock);
+ $this->braintreeAdapter->expects(static::once())
+ ->method('generate')
+ ->willReturn(self::CLIENT_TOKEN);
+
foreach ($config as $method => $value) {
- $this->configMock->expects(static::once())
+ $this->config->expects(static::once())
->method($method)
->willReturn($value);
}
- $this->configMock->expects(static::once())
- ->method('getValue')
- ->with(Config::KEY_SDK_URL)
- ->willReturn(self::SDK_URL);
- static::assertEquals($expected, $configProvider->getConfig());
+
+ static::assertEquals($expected, $this->configProvider->getConfig());
+ }
+
+ /**
+ * @covers \Magento\BraintreeTwo\Model\Ui\ConfigProvider::getClientToken
+ */
+ public function testGetClientToken()
+ {
+ $this->braintreeAdapter->expects(static::once())
+ ->method('generate')
+ ->willReturn(self::CLIENT_TOKEN);
+
+ static::assertEquals(self::CLIENT_TOKEN, $this->configProvider->getClientToken());
}
/**
@@ -59,19 +89,26 @@ public function getConfigDataProvider()
return [
[
'config' => [
- 'getClientToken' => 'token',
'getCcTypesMapper' => ['visa' => 'VI', 'american-express'=> 'AE'],
+ 'getSdkUrl' => self::SDK_URL,
'getCountrySpecificCardTypeConfig' => [
'GB' => ['VI', 'AE'],
'US' => ['DI', 'JCB']
],
'getAvailableCardTypes' => ['AE', 'VI', 'MC', 'DI', 'JCB'],
- 'isCvvEnabled' => true
+ 'isCvvEnabled' => true,
+ 'isVerify3DSecure' => true,
+ 'getThresholdAmount' => 20,
+ 'get3DSecureSpecificCountries' => ['GB', 'US', 'CA'],
+ 'getEnvironment' => 'test-environment',
+ 'getKountMerchantId' => 'test-kount-merchant-id',
+ 'getMerchantId' => 'test-merchant-id',
+ 'hasFraudProtection' => true
],
'expected' => [
'payment' => [
ConfigProvider::CODE => [
- 'clientToken' => 'token',
+ 'clientToken' => self::CLIENT_TOKEN,
'ccTypesMapper' => ['visa' => 'VI', 'american-express' => 'AE'],
'sdkUrl' => self::SDK_URL,
'countrySpecificCardTypes' =>[
@@ -79,7 +116,16 @@ public function getConfigDataProvider()
'US' => ['DI', 'JCB']
],
'availableCardTypes' => ['AE', 'VI', 'MC', 'DI', 'JCB'],
- 'useCvv' => true
+ 'useCvv' => true,
+ 'environment' => 'test-environment',
+ 'kountMerchantId' => 'test-kount-merchant-id',
+ 'merchantId' => 'test-merchant-id',
+ 'hasFraudProtection' => true
+ ],
+ Config::CODE_3DSECURE => [
+ 'enabled' => true,
+ 'thresholdAmount' => 20,
+ 'specificCountries' => ['GB', 'US', 'CA']
]
]
]
diff --git a/app/code/Magento/BraintreeTwo/Test/Unit/Observer/DataAssignObserverTest.php b/app/code/Magento/BraintreeTwo/Test/Unit/Observer/DataAssignObserverTest.php
index 870b8f1755a49..e11aa39f26abb 100644
--- a/app/code/Magento/BraintreeTwo/Test/Unit/Observer/DataAssignObserverTest.php
+++ b/app/code/Magento/BraintreeTwo/Test/Unit/Observer/DataAssignObserverTest.php
@@ -8,7 +8,6 @@
use Magento\Framework\DataObject;
use Magento\Framework\Event;
use Magento\Payment\Model\InfoInterface;
-use Magento\Payment\Model\MethodInterface;
use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\BraintreeTwo\Observer\DataAssignObserver;
@@ -18,6 +17,7 @@
class DataAssignObserverTest extends \PHPUnit_Framework_TestCase
{
const PAYMENT_METHOD_NONCE = 'nonce';
+ const DEVICE_DATA = '{"test": "test"}';
public function testExecute()
{
@@ -27,11 +27,11 @@ public function testExecute()
$event = $this->getMockBuilder(Event::class)
->disableOriginalConstructor()
->getMock();
- $paymentMethodFacade = $this->getMock(MethodInterface::class);
$paymentInfoModel = $this->getMock(InfoInterface::class);
$dataObject = new DataObject(
[
- 'payment_method_nonce' => self::PAYMENT_METHOD_NONCE
+ 'payment_method_nonce' => self::PAYMENT_METHOD_NONCE,
+ 'device_data' => self::DEVICE_DATA,
]
);
$observerContainer->expects(static::atLeastOnce())
@@ -41,19 +41,17 @@ public function testExecute()
->method('getDataByKey')
->willReturnMap(
[
- [AbstractDataAssignObserver::METHOD_CODE, $paymentMethodFacade],
+ [AbstractDataAssignObserver::MODEL_CODE, $paymentInfoModel],
[AbstractDataAssignObserver::DATA_CODE, $dataObject]
]
);
- $paymentMethodFacade->expects(static::once())
- ->method('getInfoInstance')
- ->willReturn($paymentInfoModel);
- $paymentInfoModel->expects(static::once())
+ $paymentInfoModel->expects(static::at(0))
->method('setAdditionalInformation')
- ->with(
- 'payment_method_nonce',
- self::PAYMENT_METHOD_NONCE
- );
+ ->with('payment_method_nonce', self::PAYMENT_METHOD_NONCE);
+ $paymentInfoModel->expects(static::at(1))
+ ->method('setAdditionalInformation')
+ ->with('device_data', self::DEVICE_DATA);
+
$observer = new DataAssignObserver();
$observer->execute($observerContainer);
}
diff --git a/app/code/Magento/BraintreeTwo/composer.json b/app/code/Magento/BraintreeTwo/composer.json
index 9e0c1ab77c89a..4ecded4b14c1a 100644
--- a/app/code/Magento/BraintreeTwo/composer.json
+++ b/app/code/Magento/BraintreeTwo/composer.json
@@ -5,12 +5,14 @@
"php": "~5.5.0|~5.6.0|~7.0.0",
"magento/framework": "*",
"magento/magento-composer-installer": "*",
+ "magento/module-customer": "*",
"magento/module-config": "*",
"magento/module-directory": "*",
"magento/module-payment": "*",
"magento/module-checkout": "*",
"magento/module-sales": "*",
"magento/module-backend": "*",
+ "magento/module-vault": "*",
"braintree/braintree_php": "3.7.0"
},
"type": "magento2-module",
@@ -26,4 +28,4 @@
"Magento\\BraintreeTwo\\": ""
}
}
-}
\ No newline at end of file
+}
diff --git a/app/code/Magento/BraintreeTwo/etc/adminhtml/di.xml b/app/code/Magento/BraintreeTwo/etc/adminhtml/di.xml
index 6b455b63ff8b4..7c39bbbb0af31 100644
--- a/app/code/Magento/BraintreeTwo/etc/adminhtml/di.xml
+++ b/app/code/Magento/BraintreeTwo/etc/adminhtml/di.xml
@@ -18,4 +18,21 @@
-
\ No newline at end of file
+
+
+
+
+ - BraintreeTwoFacade
+
+
+
+
+
+
+ - Magento\BraintreeTwo\Gateway\Request\CustomerDataBuilder
+ - Magento\BraintreeTwo\Gateway\Request\PaymentDataBuilder
+ - Magento\BraintreeTwo\Gateway\Request\AddressDataBuilder
+
+
+
+
diff --git a/app/code/Magento/BraintreeTwo/etc/adminhtml/system.xml b/app/code/Magento/BraintreeTwo/etc/adminhtml/system.xml
index 60cecb2c61422..ab1f8d64d75e1 100644
--- a/app/code/Magento/BraintreeTwo/etc/adminhtml/system.xml
+++ b/app/code/Magento/BraintreeTwo/etc/adminhtml/system.xml
@@ -68,6 +68,20 @@
If you don't specify the merchant account to use to process a transaction, Braintree will process it using your default merchant account.
payment/braintreetwo/merchant_account_id
+
+
+ Magento\Config\Model\Config\Source\Yesno
+ Be sure to Enable Advanced Fraud Protection in Your Braintree Account in Settings/Processing Section
+ payment/braintreetwo/fraud_protection
+
+
+
+ accounts@braintreepayments.com to setup your Kount account.]]>
+
+ 1
+
+ payment/braintreetwo/kount_merchant_id
+
Magento\Config\Model\Config\Source\Yesno
@@ -111,6 +125,30 @@
payment/braintreetwo/countrycreditcard
+
+
+ Magento\Config\Block\System\Config\Form\Fieldset
+
+
+ Magento\Config\Model\Config\Source\Yesno
+ payment/braintreetwo/verify_3dsecure
+
+
+
+ payment/braintreetwo/threshold_amount
+
+
+
+ Magento\Payment\Model\Config\Source\Allspecificcountries
+ payment/braintreetwo/verify_all_countries
+
+
+
+ Magento\BraintreeTwo\Model\Adminhtml\System\Config\Country
+ 1
+ payment/braintreetwo/verify_specific_countries
+
+
diff --git a/app/code/Magento/BraintreeTwo/etc/config.xml b/app/code/Magento/BraintreeTwo/etc/config.xml
index a0556c40df792..0162d0f79c655 100644
--- a/app/code/Magento/BraintreeTwo/etc/config.xml
+++ b/app/code/Magento/BraintreeTwo/etc/config.xml
@@ -17,6 +17,7 @@
1
1
1
+ 1
AE,VI,MC,DI,JCB,CUP,DN,MI
1
@@ -24,14 +25,14 @@
processing
sandbox
0
-
+
cvv,number
- avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText
- cc_type,cc_number,avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText
+ avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText,liabilityShifted,liabilityShiftPossible,riskDataId,riskDataDecision
+ cc_type,cc_number,avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText,liabilityShifted,liabilityShiftPossible,riskDataId,riskDataDecision
1
-
\ No newline at end of file
+
diff --git a/app/code/Magento/BraintreeTwo/etc/di.xml b/app/code/Magento/BraintreeTwo/etc/di.xml
index 8b886b6cc5714..3e94c7ccb93b3 100644
--- a/app/code/Magento/BraintreeTwo/etc/di.xml
+++ b/app/code/Magento/BraintreeTwo/etc/di.xml
@@ -5,7 +5,6 @@
* See COPYING.txt for license details.
*/
-->
-
@@ -38,11 +37,20 @@
- BraintreeTwoAuthorizeGatewayCommand
- - BraintreeTwoSaleGatewayCommand
+ - BraintreeTwoSaleGatewayCommand
+ - BraintreeTwoCaptureStrategyGatewayCommand
+ - BraintreeTwoCaptureGatewayCommand
+ - BraintreeTwoCloneGatewayCommand
+
+
+ BraintreeTwoCommandPool
+
+
+
@@ -59,12 +67,25 @@
- Magento\BraintreeTwo\Gateway\Request\CustomerDataBuilder
- Magento\BraintreeTwo\Gateway\Request\PaymentDataBuilder
- Magento\BraintreeTwo\Gateway\Request\AddressDataBuilder
+ - Magento\BraintreeTwo\Gateway\Request\VaultDataBuilder
+ - Magento\BraintreeTwo\Gateway\Request\ThreeDSecureDataBuilder
+ - Magento\BraintreeTwo\Gateway\Request\KountPaymentDataBuilder
- BraintreeTwoLogger
+ BraintreeTwoLogger
+
+
+
+
+ BraintreeTwoLogger
+
+
+
+
+ BraintreeTwoLogger
@@ -83,6 +104,44 @@
+
+
+
+ BraintreeTwoCaptureDataBuilder
+ Magento\BraintreeTwo\Gateway\Http\TransferFactory
+ Magento\BraintreeTwo\Gateway\Http\Client\TransactionSubmitForSettlement
+ Magento\BraintreeTwo\Gateway\Response\CaptureDetailsHandler
+ Magento\BraintreeTwo\Gateway\Validator\ResponseValidator
+
+
+
+
+
+
+ - Magento\BraintreeTwo\Gateway\Request\CaptureDataBuilder
+
+
+
+
+
+
+
+ BraintreeTwoCloneDataBuilder
+ Magento\BraintreeTwo\Gateway\Http\TransferFactory
+ Magento\BraintreeTwo\Gateway\Http\Client\TransactionClone
+ BraintreeTwoCloneResponseHandler
+ Magento\BraintreeTwo\Gateway\Validator\ResponseValidator
+
+
+
+
+
+ - Magento\BraintreeTwo\Gateway\Request\CaptureDataBuilder
+ - Magento\BraintreeTwo\Gateway\Request\SettlementDataBuilder
+
+
+
+
@@ -101,6 +160,17 @@
- Magento\BraintreeTwo\Gateway\Response\PaymentDetailsHandler
- Magento\BraintreeTwo\Gateway\Response\CardDetailsHandler
+ - Magento\BraintreeTwo\Gateway\Response\RiskDataHandler
+ - Magento\BraintreeTwo\Gateway\Response\VaultDetailsHandler
+ - Magento\BraintreeTwo\Gateway\Response\ThreeDSecureDetailsHandler
+
+
+
+
+
+
+ - Magento\BraintreeTwo\Gateway\Response\CaptureDetailsHandler
+ - Magento\BraintreeTwo\Gateway\Response\CloneDetailsHandler
@@ -124,5 +194,11 @@
Magento\BraintreeTwo\Gateway\Config\Config
-
-
\ No newline at end of file
+
+
+
+ - Magento\Vault\Model\PaymentTokenRepository
+
+
+
+
diff --git a/app/code/Magento/BraintreeTwo/etc/events.xml b/app/code/Magento/BraintreeTwo/etc/events.xml
index def66f4b308ed..2123566b73ab6 100644
--- a/app/code/Magento/BraintreeTwo/etc/events.xml
+++ b/app/code/Magento/BraintreeTwo/etc/events.xml
@@ -10,4 +10,4 @@
-
\ No newline at end of file
+
diff --git a/app/code/Magento/BraintreeTwo/etc/frontend/di.xml b/app/code/Magento/BraintreeTwo/etc/frontend/di.xml
index b0238c838bbc0..2ab0103b00e55 100644
--- a/app/code/Magento/BraintreeTwo/etc/frontend/di.xml
+++ b/app/code/Magento/BraintreeTwo/etc/frontend/di.xml
@@ -27,4 +27,12 @@
-
\ No newline at end of file
+
+
+
+
+ - Magento\BraintreeTwo\Model\Ui\TokenUiComponentProvider
+
+
+
+
diff --git a/app/code/Magento/BraintreeTwo/etc/module.xml b/app/code/Magento/BraintreeTwo/etc/module.xml
index 26ac385107f85..eecb50c95c45c 100644
--- a/app/code/Magento/BraintreeTwo/etc/module.xml
+++ b/app/code/Magento/BraintreeTwo/etc/module.xml
@@ -8,8 +8,10 @@
+
+
-
\ No newline at end of file
+
diff --git a/app/code/Magento/BraintreeTwo/i18n/en_US.csv b/app/code/Magento/BraintreeTwo/i18n/en_US.csv
index 098107d193268..0ab3924ae13c9 100644
--- a/app/code/Magento/BraintreeTwo/i18n/en_US.csv
+++ b/app/code/Magento/BraintreeTwo/i18n/en_US.csv
@@ -5,4 +5,9 @@
"cvvResponseCode","CVV Response Code"
"processorAuthorizationCode","Processor Authorization Code"
"processorResponseCode","Processor Response Code"
-"processorResponseText","Processor Response Text"
\ No newline at end of file
+"processorResponseText","Processor Response Text"
+"braintreetwo", "Braintree"
+"liabilityShifted", "Liability Shifted"
+"liabilityShiftPossible", "Liability Shift Possible"
+"riskDataId", "Risk ID"
+"riskDataDecision", "Risk Decision"
diff --git a/app/code/Magento/BraintreeTwo/view/adminhtml/templates/form/cc.phtml b/app/code/Magento/BraintreeTwo/view/adminhtml/templates/form/cc.phtml
index d62624fd02b0d..8eb77bc890bbe 100644
--- a/app/code/Magento/BraintreeTwo/view/adminhtml/templates/form/cc.phtml
+++ b/app/code/Magento/BraintreeTwo/view/adminhtml/templates/form/cc.phtml
@@ -39,8 +39,8 @@ $ccType = $block->getInfoData('cc_type');
-
- escapeHtml(__('Please enter valid Credit Card Number')); ?>
+
+ escapeHtml(__('Please, enter valid Credit Card Number')); ?>
@@ -57,7 +57,7 @@ $ccType = $block->getInfoData('cc_type');
- escapeHtml(__('Please enter valid Expiration Date')); ?>
+ escapeHtml(__('Please, enter valid Expiration Date')); ?>
@@ -70,8 +70,8 @@ $ccType = $block->getInfoData('cc_type');
-
- escapeHtml(__('Please enter valid Card Verification Number')); ?>
+
+ escapeHtml(__('Please, enter valid Card Verification Number')); ?>
diff --git a/app/code/Magento/BraintreeTwo/view/adminhtml/web/js/braintree.js b/app/code/Magento/BraintreeTwo/view/adminhtml/web/js/braintree.js
index 57586aaf41693..4127b417427a7 100644
--- a/app/code/Magento/BraintreeTwo/view/adminhtml/web/js/braintree.js
+++ b/app/code/Magento/BraintreeTwo/view/adminhtml/web/js/braintree.js
@@ -148,9 +148,13 @@ define([
return false;
}
+ // Handle a change in validation or card type
+ if (event.target.fieldKey === 'number') {
+ self.selectedCardType(null);
+ }
+
// remove previously set classes
$cardType.attr('class', 'icon-type');
- self.selectedCardType(null);
if (event.card) {
$cardType.addClass('icon-type-' + event.card.type);
diff --git a/app/code/Magento/BraintreeTwo/view/base/web/js/validator.js b/app/code/Magento/BraintreeTwo/view/base/web/js/validator.js
index 084c61795d75a..fb17fba51a1dc 100644
--- a/app/code/Magento/BraintreeTwo/view/base/web/js/validator.js
+++ b/app/code/Magento/BraintreeTwo/view/base/web/js/validator.js
@@ -30,7 +30,7 @@ define([
/**
* Get list of card types
- * @returns {exports.defaults.ccTypesMapper|{}|*}
+ * @returns {Object}
*/
getCcTypesMapper: function () {
return this.config.ccTypesMapper;
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/requirejs-config.js b/app/code/Magento/BraintreeTwo/view/frontend/requirejs-config.js
new file mode 100644
index 0000000000000..97890fb321fdb
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/requirejs-config.js
@@ -0,0 +1,12 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+var config = {
+ map: {
+ '*': {
+ braintree: 'https://js.braintreegateway.com/js/braintree-2.17.4.min.js'
+ }
+ }
+};
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/3d-secure.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/3d-secure.js
new file mode 100644
index 0000000000000..917267bf2339c
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/3d-secure.js
@@ -0,0 +1,115 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+
+define([
+ 'jquery',
+ 'Magento_BraintreeTwo/js/view/payment/adapter',
+ 'Magento_Checkout/js/model/quote',
+ 'mage/translate'
+], function ($, braintree, quote, $t) {
+ 'use strict';
+
+ return {
+ config: null,
+
+ /**
+ * Set 3d secure config
+ * @param {Object} config
+ */
+ setConfig: function (config) {
+ this.config = config;
+ this.config.thresholdAmount = parseFloat(config.thresholdAmount);
+ },
+
+ /**
+ * Get code
+ * @returns {String}
+ */
+ getCode: function () {
+ return 'three_d_secure';
+ },
+
+ /**
+ * Validate Braintree payment nonce
+ * @param {Object} context
+ * @returns {Object}
+ */
+ validate: function (context) {
+ var client = braintree.getApiClient(),
+ state = $.Deferred(),
+ totalAmount = quote.totals()['base_grand_total'],
+ billingAddress = quote.billingAddress();
+
+ if (!this.isAmountAvailable(totalAmount) || !this.isCountryAvailable(billingAddress.countryId)) {
+ state.resolve();
+
+ return state.promise();
+ }
+
+ client.verify3DS({
+ amount: totalAmount,
+ creditCard: context.paymentMethodNonce
+ }, function (error, response) {
+ var liability;
+
+ if (error) {
+ state.reject(error.message);
+
+ return;
+ }
+
+ liability = {
+ shifted: response.verificationDetails.liabilityShifted,
+ shiftPossible: response.verificationDetails.liabilityShiftPossible
+ };
+
+ if (liability.shifted || !liability.shifted && !liability.shiftPossible) {
+ context.paymentMethodNonce = response.nonce;
+ state.resolve();
+ } else {
+ state.reject($t('Please try again with another form of payment.'));
+ }
+ });
+
+ return state.promise();
+ },
+
+ /**
+ * Check minimal amount for 3d secure activation
+ * @param {Number} amount
+ * @returns {Boolean}
+ */
+ isAmountAvailable: function (amount) {
+ amount = parseFloat(amount);
+
+ return amount >= this.config.thresholdAmount;
+ },
+
+ /**
+ * Check if current country is available for 3d secure
+ * @param {String} countryId
+ * @returns {Boolean}
+ */
+ isCountryAvailable: function (countryId) {
+ var key,
+ specificCountries = this.config.specificCountries;
+
+ // all countries are available
+ if (!specificCountries.length) {
+ return true;
+ }
+
+ for (key in specificCountries) {
+ if (countryId === specificCountries[key]) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ };
+});
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/adapter.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/adapter.js
new file mode 100644
index 0000000000000..27dd325d96d72
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/adapter.js
@@ -0,0 +1,55 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define([
+ 'jquery',
+ 'braintree'
+], function ($, braintree) {
+ 'use strict';
+
+ return {
+ apiClient: null,
+
+ /**
+ * Get Braintree api client
+ * @returns {Object}
+ */
+ getApiClient: function () {
+ if (!this.apiClient) {
+ this.apiClient = new braintree.api.Client({
+ clientToken: this.getClientToken()
+ });
+ }
+
+ return this.apiClient;
+ },
+
+ /**
+ * Get Braintree SDK client
+ * @returns {Object}
+ */
+ getSdkClient: function () {
+ return braintree;
+ },
+
+ /**
+ * Get payment name
+ * @returns {String}
+ */
+ getCode: function () {
+ return 'braintreetwo';
+ },
+
+ /**
+ * Get client token
+ * @returns {String|*}
+ */
+ getClientToken: function () {
+
+ return window.checkoutConfig.payment[this.getCode()].clientToken;
+ }
+ };
+});
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/braintree.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/braintree.js
index 9331298ac2849..b5bed2304ccee 100644
--- a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/braintree.js
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/braintree.js
@@ -18,7 +18,7 @@ define(
rendererList.push(
{
type: 'braintreetwo',
- component: 'Magento_BraintreeTwo/js/view/payment/method-renderer/braintree'
+ component: 'Magento_BraintreeTwo/js/view/payment/method-renderer/hosted-fields'
}
);
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/braintree.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/braintree.js
deleted file mode 100644
index ec458a62c616a..0000000000000
--- a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/braintree.js
+++ /dev/null
@@ -1,284 +0,0 @@
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*browser:true*/
-/*global define*/
-define(
- [
- 'jquery',
- 'Magento_Payment/js/view/payment/cc-form',
- 'Magento_Ui/js/model/messageList',
- 'Magento_Checkout/js/model/quote',
- 'mage/translate',
- 'Magento_BraintreeTwo/js/validator'
- ],
- function (
- $,
- Component,
- globalMessageList,
- quote,
- $t,
- validator
- ) {
- 'use strict';
-
- return Component.extend({
- defaults: {
- template: 'Magento_BraintreeTwo/payment/form',
- active: false,
- scriptLoaded: false,
- braintreeClient: null,
- paymentMethodNonce: null,
- lastBillingAddress: null,
- imports: {
- onActiveChange: 'active'
- }
- },
-
- /**
- * Set list of observable attributes
- * @returns {exports.initObservable}
- */
- initObservable: function () {
- validator.setConfig(window.checkoutConfig.payment[this.getCode()]);
-
- this._super()
- .observe('active scriptLoaded');
-
- return this;
- },
-
- /**
- * Get payment name
- * @returns {String}
- */
- getCode: function () {
- return 'braintreetwo';
- },
-
- /**
- * Get full selector name
- * @param {String} field
- * @returns {String}
- */
- getSelector: function (field) {
- return '#' + this.getCode() + '_' + field;
- },
-
- /**
- * Check if payment is active
- * @returns {Boolean}
- */
- isActive: function () {
- var active = this.getCode() === this.isChecked();
-
- this.active(active);
-
- return active;
- },
-
- /**
- * Triggers on payment change
- * @param {Boolean} isActive
- */
- onActiveChange: function (isActive) {
- if (!isActive) {
- return;
- }
-
- if (this.getClientToken()) {
- if (!this.scriptLoaded()) {
- this.loadScript();
- }
- } else {
- globalMessageList.addErrorMessage({
- 'message': $t('Sorry, but something went wrong')
- });
- }
- },
-
- /**
- * Load Braintree SDK
- */
- loadScript: function () {
- var state = this.scriptLoaded,
- self = this;
-
- $('body').trigger('processStart');
- require([this.getSdkUrl()], function (braintree) {
- state(true);
- self.braintreeClient = braintree;
- self.initBraintree();
- $('body').trigger('processStop');
- });
- },
-
- /**
- * Init Braintree client
- */
- initBraintree: function () {
- var self = this,
- fields = {
- number: {
- selector: self.getSelector('cc_number')
- },
- expirationMonth: {
- selector: self.getSelector('expirationMonth'),
- placeholder: $t('MM')
- },
- expirationYear: {
- selector: self.getSelector('expirationYear'),
- placeholder: $t('YY')
- },
-
- /**
- * Triggers on Hosted Field changes
- * @param {Object} event
- * @returns {Boolean}
- */
- onFieldEvent: function (event) {
- if (event.isEmpty === false) {
- self.validateCardType();
- }
-
- if (event.type === 'fieldStateChange') {
- // Handle a change in validation or card type
- self.selectedCardType(null);
-
- if (!event.isPotentiallyValid && !event.isValid) {
- return false;
- }
-
- if (event.card) {
- self.selectedCardType(
- validator.getMageCardType(event.card.type, self.getCcAvailableTypes())
- );
- }
- }
- }
- };
-
- if (self.hasVerification()) {
- fields.cvv = {
- selector: self.getSelector('cc_cid')
- };
- }
-
- this.braintreeClient.setup(this.getClientToken(), 'custom', {
- id: 'co-transparent-form-braintree',
- hostedFields: fields,
-
- /**
- * Triggers on payment nonce receive
- * @param {Object} response
- */
- onPaymentMethodReceived: function (response) {
- self.paymentMethodNonce = response.nonce;
- self.placeOrder();
- },
-
- /**
- * Triggers on any Braintree error
- * @param {Object} response
- */
- onError: function (response) {
- self.messageContainer.addErrorMessage({
- 'message': response.message
- });
- }
- });
- },
-
- /**
- * Validate current credit card type
- * @returns {Boolean}
- */
- validateCardType: function () {
- var $selector = $(this.getSelector('cc_number')),
- invalidClass = 'braintree-hosted-fields-invalid';
-
- $selector.removeClass(invalidClass);
-
- if (this.selectedCardType() === null) {
- $(this.getSelector('cc_number')).addClass('class', invalidClass);
-
- return false;
- }
-
- return true;
- },
-
- /**
- * Get url of Braintree SDK
- * @returns {String}
- */
- getSdkUrl: function () {
-
- return window.checkoutConfig.payment[this.getCode()].sdkUrl;
- },
-
- /**
- * Get client token
- * @returns {String|*}
- */
- getClientToken: function () {
-
- return window.checkoutConfig.payment[this.getCode()].clientToken;
- },
-
- /**
- * Get list of available CC types
- */
- getCcAvailableTypes: function () {
- var availableTypes = validator.getAvailableCardTypes(),
- billingAddress = quote.billingAddress(),
- billingCountryId;
-
- this.lastBillingAddress = quote.shippingAddress();
-
- if (!billingAddress) {
- billingAddress = this.lastBillingAddress;
- }
-
- billingCountryId = billingAddress.countryId;
-
- if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {
-
- return validator.collectTypes(
- availableTypes, validator.getCountrySpecificCardTypes(billingCountryId)
- );
- }
-
- return availableTypes;
- },
-
- /**
- * Get data
- * @returns {Object}
- */
- getData: function () {
- return {
- 'method': this.item.method,
- 'additional_data': {
- 'payment_method_nonce': this.paymentMethodNonce
- }
- };
- },
-
- /**
- * Trigger order placing
- */
- placeOrderClick: function () {
- if (this.validateCardType()) {
- $(this.getSelector('submit')).trigger('click');
- } else {
- this.messageContainer.addErrorMessage({
- 'message': $t('Please enter a valid credit card type number')
- });
- }
- }
-
- });
- }
-);
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/cc-form.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/cc-form.js
new file mode 100644
index 0000000000000..a55247593b940
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/cc-form.js
@@ -0,0 +1,304 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+ [
+ 'underscore',
+ 'jquery',
+ 'Magento_Payment/js/view/payment/cc-form',
+ 'Magento_Checkout/js/model/quote',
+ 'Magento_BraintreeTwo/js/view/payment/adapter',
+ 'Magento_Ui/js/model/messageList',
+ 'mage/translate',
+ 'Magento_BraintreeTwo/js/validator',
+ 'Magento_BraintreeTwo/js/view/payment/validator-handler'
+ ],
+ function (
+ _,
+ $,
+ Component,
+ quote,
+ braintree,
+ globalMessageList,
+ $t,
+ validator,
+ validatorManager
+ ) {
+ 'use strict';
+
+ return Component.extend({
+ defaults: {
+ active: false,
+ isInitialized: false,
+ braintreeClient: null,
+ braintreeDeviceData: null,
+ paymentMethodNonce: null,
+ lastBillingAddress: null,
+ validatorManager: validatorManager,
+
+ /**
+ * Additional payment data
+ *
+ * {Object}
+ */
+ additionalData: {},
+
+ /**
+ * {String}
+ */
+ integration: 'custom',
+
+ /**
+ * Braintree client configuration
+ *
+ * {Object}
+ */
+ clientConfig: {
+
+ /**
+ * Triggers on payment nonce receive
+ *
+ * @param {Object} response
+ */
+ onPaymentMethodReceived: function (response) {
+ this.paymentMethodNonce = response.nonce;
+ this.placeOrder();
+ },
+
+ /**
+ * Triggers on any Braintree error
+ */
+ onError: function () {
+ this.paymentMethodNonce = '';
+ }
+ }
+ },
+
+ /**
+ * Init config
+ */
+ initClientConfig: function () {
+ // Advanced fraud tools settings
+ if (this.hasFraudProtection()) {
+ this.clientConfig = _.extend(this.clientConfig, this.kountConfig());
+ }
+
+ _.each(this.clientConfig, function (fn, name) {
+ if (typeof fn === 'function') {
+ this.clientConfig[name] = fn.bind(this);
+ }
+ }, this);
+ },
+
+ /**
+ * @returns {Object}
+ */
+ kountConfig: function () {
+ var config = {
+ dataCollector: {
+ kount: {
+ environment: this.getEnvironment()
+ }
+ },
+
+ /**
+ * Device data initialization
+ *
+ * @param {Object} braintreeInstance
+ */
+ onReady: function (braintreeInstance) {
+ this.additionalData['device_data'] = braintreeInstance.deviceData;
+ }
+ };
+
+ if (this.getKountMerchantId()) {
+ config.dataCollector.kount.merchantId = this.getKountMerchantId();
+ }
+
+ return config;
+ },
+
+ /**
+ * Set list of observable attributes
+ *
+ * @returns {exports.initObservable}
+ */
+ initObservable: function () {
+ validator.setConfig(window.checkoutConfig.payment[this.getCode()]);
+ this._super()
+ .observe(['active', 'isInitialized']);
+ this.validatorManager.initialize();
+ this.braintreeClient = braintree;
+ this.initBraintree();
+
+ return this;
+ },
+
+ /**
+ * Get payment name
+ *
+ * @returns {String}
+ */
+ getCode: function () {
+ return 'braintreetwo';
+ },
+
+ /**
+ * Check if payment is active
+ *
+ * @returns {Boolean}
+ */
+ isActive: function () {
+ var active = this.getCode() === this.isChecked();
+
+ this.active(active);
+
+ return active;
+ },
+
+ /**
+ * Init Braintree handlers
+ */
+ initBraintree: function () {
+ if (!this.braintreeClient.getClientToken()) {
+ this.showError($t('Sorry, but something went wrong.'));
+ }
+
+ if (!this.isInitialized()) {
+ this.isInitialized(true);
+ this.initClient();
+ }
+ },
+
+ /**
+ * Init Braintree client
+ */
+ initClient: function () {
+ this.initClientConfig();
+ this.braintreeClient.getSdkClient().setup(
+ this.braintreeClient.getClientToken(),
+ this.integration,
+ this.clientConfig
+ );
+ },
+
+ /**
+ * Show error message
+ *
+ * @param {String} errorMessage
+ */
+ showError: function (errorMessage) {
+ globalMessageList.addErrorMessage({
+ message: errorMessage
+ });
+ },
+
+ /**
+ * Get full selector name
+ *
+ * @param {String} field
+ * @returns {String}
+ */
+ getSelector: function (field) {
+ return '#' + this.getCode() + '_' + field;
+ },
+
+ /**
+ * Get list of available CC types
+ *
+ * @returns {Object}
+ */
+ getCcAvailableTypes: function () {
+ var availableTypes = validator.getAvailableCardTypes(),
+ billingAddress = quote.billingAddress(),
+ billingCountryId;
+
+ this.lastBillingAddress = quote.shippingAddress();
+
+ if (!billingAddress) {
+ billingAddress = this.lastBillingAddress;
+ }
+
+ billingCountryId = billingAddress.countryId;
+
+ if (billingCountryId && validator.getCountrySpecificCardTypes(billingCountryId)) {
+
+ return validator.collectTypes(
+ availableTypes, validator.getCountrySpecificCardTypes(billingCountryId)
+ );
+ }
+
+ return availableTypes;
+ },
+
+ /**
+ * @returns {Boolean}
+ */
+ hasFraudProtection: function () {
+ return window.checkoutConfig.payment[this.getCode()].hasFraudProtection;
+ },
+
+ /**
+ * @returns {String}
+ */
+ getEnvironment: function () {
+ return window.checkoutConfig.payment[this.getCode()].environment;
+ },
+
+ /**
+ * @returns {String}
+ */
+ getKountMerchantId: function () {
+ return window.checkoutConfig.payment[this.getCode()].kountMerchantId;
+ },
+
+ /**
+ * Get data
+ *
+ * @returns {Object}
+ */
+ getData: function () {
+ var data = {
+ 'method': this.getCode(),
+ 'additional_data': {
+ 'payment_method_nonce': this.paymentMethodNonce
+ }
+ };
+
+ data['additional_data'] = _.extend(data['additional_data'], this.additionalData);
+
+ return data;
+ },
+
+ /**
+ * Set payment nonce
+ * @param {String} paymentMethodNonce
+ */
+ setPaymentMethodNonce: function (paymentMethodNonce) {
+ this.paymentMethodNonce = paymentMethodNonce;
+ },
+
+ /**
+ * Action to place order
+ *
+ * @param {String} key
+ */
+ placeOrder: function (key) {
+ var self = this;
+
+ if (key) {
+ return self._super();
+ }
+ // place order on success validation
+ self.validatorManager.validate(self, function () {
+ return self.placeOrder('parent');
+ });
+
+ return false;
+ }
+ });
+ }
+);
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js
new file mode 100644
index 0000000000000..2ac97155a279f
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js
@@ -0,0 +1,157 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+
+define([
+ 'jquery',
+ 'Magento_BraintreeTwo/js/view/payment/method-renderer/cc-form',
+ 'Magento_BraintreeTwo/js/validator',
+ 'Magento_Vault/js/view/payment/vault-enabler',
+ 'mage/translate'
+], function ($, Component, validator, vaultEnabler, $t) {
+ 'use strict';
+
+ return Component.extend({
+
+ defaults: {
+ template: 'Magento_BraintreeTwo/payment/form',
+ clientConfig: {
+
+ /**
+ * {String}
+ */
+ id: 'co-transparent-form-braintree'
+ }
+ },
+
+ /**
+ * @returns {exports.initialize}
+ */
+ initialize: function () {
+ this._super();
+ this.vaultEnabler = vaultEnabler();
+ this.vaultEnabler.setPaymentCode(this.getCode());
+
+ return this;
+ },
+
+ /**
+ * Init config
+ */
+ initClientConfig: function () {
+ this._super();
+
+ // Hosted fields settings
+ this.clientConfig.hostedFields = this.getHostedFields();
+ },
+
+ /**
+ * @returns {Object}
+ */
+ getData: function () {
+ var data = this._super();
+
+ this.vaultEnabler.visitAdditionalData(data);
+
+ return data;
+ },
+
+ /**
+ * @returns {Bool}
+ */
+ isVaultEnabled: function () {
+ return this.vaultEnabler.isVaultEnabled();
+ },
+
+ /**
+ * Get Braintree Hosted Fields
+ * @returns {Object}
+ */
+ getHostedFields: function () {
+ var self = this,
+ fields = {
+ number: {
+ selector: self.getSelector('cc_number')
+ },
+ expirationMonth: {
+ selector: self.getSelector('expirationMonth'),
+ placeholder: $t('MM')
+ },
+ expirationYear: {
+ selector: self.getSelector('expirationYear'),
+ placeholder: $t('YY')
+ }
+ };
+
+ if (self.hasVerification()) {
+ fields.cvv = {
+ selector: self.getSelector('cc_cid')
+ };
+ }
+
+ /**
+ * Triggers on Hosted Field changes
+ * @param {Object} event
+ * @returns {Boolean}
+ */
+ fields.onFieldEvent = function (event) {
+ if (event.isEmpty === false) {
+ self.validateCardType();
+ }
+
+ if (event.type !== 'fieldStateChange') {
+
+ return false;
+ }
+
+ // Handle a change in validation or card type
+ if (event.target.fieldKey === 'number') {
+ self.selectedCardType(null);
+ }
+
+ if (!event.isValid) {
+ return false;
+ }
+
+ if (event.card) {
+ self.selectedCardType(
+ validator.getMageCardType(event.card.type, self.getCcAvailableTypes())
+ );
+ }
+ };
+
+ return fields;
+ },
+
+ /**
+ * Validate current credit card type
+ * @returns {Boolean}
+ */
+ validateCardType: function () {
+ var $selector = $(this.getSelector('cc_number')),
+ invalidClass = 'braintree-hosted-fields-invalid';
+
+ $selector.removeClass(invalidClass);
+
+ if (this.selectedCardType() === null) {
+ $(this.getSelector('cc_number')).addClass(invalidClass);
+
+ return false;
+ }
+
+ return true;
+ },
+
+ /**
+ * Trigger order placing
+ */
+ placeOrderClick: function () {
+ if (this.validateCardType()) {
+ $(this.getSelector('submit')).trigger('click');
+ }
+ }
+ });
+});
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/vault.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/vault.js
new file mode 100644
index 0000000000000..f9efa111ed500
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/method-renderer/vault.js
@@ -0,0 +1,98 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define([
+ 'jquery',
+ 'Magento_BraintreeTwo/js/view/payment/method-renderer/cc-form',
+ 'Magento_Vault/js/view/payment/method-renderer/vault',
+ 'Magento_Ui/js/model/messageList',
+ 'Magento_Checkout/js/model/full-screen-loader'
+], function ($, Component, VaultComponent, globalMessageList, fullScreenLoader) {
+ 'use strict';
+
+ return VaultComponent.extend({
+ defaults: {
+ template: 'Magento_BraintreeTwo/payment/vault',
+ modules: {
+ hostedFields: '${ $.parentName }.braintreetwo'
+ }
+ },
+
+ /**
+ * Get current Braintree vault id
+ * @returns {String}
+ */
+ getId: function () {
+ return 'braintreetwo_' + this.index;
+ },
+
+ /**
+ * Get name of scope
+ * @returns {String}
+ */
+ getScopeName: function () {
+ return this.parentName + '.braintreetwo';
+ },
+
+ /**
+ * Get last 4 digits of card
+ * @returns {String}
+ */
+ getMaskedCard: function () {
+ return this.details.maskedCC;
+ },
+
+ /**
+ * Get expiration date
+ * @returns {String}
+ */
+ getExpirationDate: function () {
+ return this.details.expirationDate;
+ },
+
+ /**
+ * Get card type
+ * @returns {String}
+ */
+ getCardType: function () {
+ return this.details.type;
+ },
+
+ /**
+ * Place order
+ */
+ placeOrder: function () {
+ this.getPaymentMethodNonce();
+ },
+
+ /**
+ * Send request to get payment method nonce
+ */
+ getPaymentMethodNonce: function () {
+ var self = this;
+
+ fullScreenLoader.startLoader();
+ $.get(self.nonceUrl, {
+ 'public_hash': self.publicHash
+ })
+ .done(function (response) {
+ fullScreenLoader.stopLoader();
+ self.hostedFields(function (formComponent) {
+ formComponent.setPaymentMethodNonce(response.paymentMethodNonce);
+ formComponent.placeOrder();
+ });
+ })
+ .fail(function (response) {
+ var error = JSON.parse(response.responseText);
+
+ fullScreenLoader.stopLoader();
+ globalMessageList.addErrorMessage({
+ message: error.message
+ });
+ });
+ }
+ });
+});
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/validator-handler.js b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/validator-handler.js
new file mode 100644
index 0000000000000..f3c9c89ed1ed2
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/js/view/payment/validator-handler.js
@@ -0,0 +1,85 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+
+define([
+ 'jquery',
+ 'Magento_Ui/js/model/messageList',
+ 'Magento_BraintreeTwo/js/view/payment/3d-secure'
+], function ($, globalMessageList, verify3DSecure) {
+ 'use strict';
+
+ return {
+ validators: [],
+
+ /**
+ * Get payment config
+ * @returns {Object}
+ */
+ getConfig: function () {
+ return window.checkoutConfig.payment;
+ },
+
+ /**
+ * Init list of validators
+ */
+ initialize: function () {
+ var config = this.getConfig();
+
+ if (config[verify3DSecure.getCode()].enabled) {
+ verify3DSecure.setConfig(config[verify3DSecure.getCode()]);
+ this.add(verify3DSecure);
+ }
+ },
+
+ /**
+ * Add new validator
+ * @param {Object} validator
+ */
+ add: function (validator) {
+ this.validators.push(validator);
+ },
+
+ /**
+ * Run pull of validators
+ * @param {Object} context
+ * @param {Function} callback
+ */
+ validate: function (context, callback) {
+ var self = this,
+ deferred;
+
+ // no available validators
+ if (!self.validators.length) {
+ callback();
+
+ return;
+ }
+
+ // get list of deferred validators
+ deferred = $.map(self.validators, function (current) {
+ return current.validate(context);
+ });
+
+ $.when.apply($, deferred)
+ .done(function () {
+ callback();
+ }).fail(function (error) {
+ self.showError(error);
+ });
+ },
+
+ /**
+ * Show error message
+ * @param {String} errorMessage
+ */
+ showError: function (errorMessage) {
+ globalMessageList.addErrorMessage({
+ message: errorMessage
+ });
+ }
+ };
+});
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/template/payment/form.html b/app/code/Magento/BraintreeTwo/view/frontend/web/template/payment/form.html
index 1531ceb73f23e..5e5046412c71e 100644
--- a/app/code/Magento/BraintreeTwo/view/frontend/web/template/payment/form.html
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/template/payment/form.html
@@ -4,12 +4,12 @@
* See COPYING.txt for license details.
*/
-->
-
+
+ name="payment[method]"
+ class="radio"
+ data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
@@ -34,15 +34,15 @@
-
+ _active: $parent.selectedCardType() == item,
+ _inactive: $parent.selectedCardType() != null && $parent.selectedCardType() != item
+ } ">
+ 'src': $parent.getIcons(item).url,
+ 'width': $parent.getIcons(item).width,
+ 'height': $parent.getIcons(item).height
+ }">
@@ -52,8 +52,8 @@
class="input-text"
value=""
data-bind="attr: {id: getCode() + '_cc_type', 'data-container': getCode() + '-cc-type'},
- value: creditCardType
- ">
+ value: creditCardType
+ ">
@@ -88,7 +88,7 @@
diff --git a/app/code/Magento/BraintreeTwo/view/frontend/web/template/payment/vault.html b/app/code/Magento/BraintreeTwo/view/frontend/web/template/payment/vault.html
new file mode 100644
index 0000000000000..2dad98628932c
--- /dev/null
+++ b/app/code/Magento/BraintreeTwo/view/frontend/web/template/payment/vault.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
index 95bd7ed91cecc..257e937ab6886 100644
--- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
+++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
@@ -574,8 +574,12 @@ protected function _prepareOptions(\Magento\Framework\DataObject $buyRequest, $p
{
$transport = new \StdClass();
$transport->options = [];
+ $options = null;
if ($product->getHasOptions()) {
- foreach ($product->getOptions() as $option) {
+ $options = $product->getOptions();
+ }
+ if ($options !== null) {
+ foreach ($options as $option) {
/* @var $option \Magento\Catalog\Model\Product\Option */
$group = $option->groupFactory($option->getType())
->setOption($option)
diff --git a/app/code/Magento/CatalogRule/Api/CatalogRuleRepositoryInterface.php b/app/code/Magento/CatalogRule/Api/CatalogRuleRepositoryInterface.php
new file mode 100644
index 0000000000000..88a716ecd25b4
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Api/CatalogRuleRepositoryInterface.php
@@ -0,0 +1,41 @@
+getRequest()->getParam('id');
if ($id) {
try {
- /** @var \Magento\CatalogRule\Model\Rule $model */
- $model = $this->_objectManager->create('Magento\CatalogRule\Model\Rule');
- $model->load($id);
- $model->delete();
+ /** @var \Magento\CatalogRule\Api\CatalogRuleRepositoryInterface $ruleRepository */
+ $ruleRepository = $this->_objectManager->create(
+ 'Magento\CatalogRule\Api\CatalogRuleRepositoryInterface'
+ );
+ $ruleRepository->deleteById($id);
+
$this->_objectManager->create('Magento\CatalogRule\Model\Flag')->loadSelf()->setState(1)->save();
$this->messageManager->addSuccess(__('You deleted the rule.'));
$this->_redirect('catalog_rule/*/');
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Edit.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Edit.php
index 97495f7d0d48f..82b356da5884b 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Edit.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Edit.php
@@ -14,11 +14,19 @@ class Edit extends \Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog
public function execute()
{
$id = $this->getRequest()->getParam('id');
+
+ /** @var \Magento\CatalogRule\Model\Rule $model */
$model = $this->_objectManager->create('Magento\CatalogRule\Model\Rule');
+ /** @var \Magento\CatalogRule\Api\CatalogRuleRepositoryInterface $ruleRepository */
+ $ruleRepository = $this->_objectManager->create(
+ 'Magento\CatalogRule\Api\CatalogRuleRepositoryInterface'
+ );
+
if ($id) {
- $model->load($id);
- if (!$model->getRuleId()) {
+ try {
+ $model = $ruleRepository->get($id);
+ } catch (\Magento\Framework\Exception\NoSuchEntityException $exception) {
$this->messageManager->addError(__('This rule no longer exists.'));
$this->_redirect('catalog_rule/*');
return;
@@ -39,12 +47,9 @@ public function execute()
$this->_view->getPage()->getConfig()->getTitle()->prepend(
$model->getRuleId() ? $model->getName() : __('New Catalog Price Rule')
);
- $this->_view->getLayout()->getBlock(
- 'promo_catalog_edit'
- )->setData(
- 'action',
- $this->getUrl('catalog_rule/promo_catalog/save')
- );
+ $this->_view->getLayout()
+ ->getBlock('promo_catalog_edit')
+ ->setData('action', $this->getUrl('catalog_rule/promo_catalog/save'));
$breadcrumb = $id ? __('Edit Rule') : __('New Rule');
$this->_addBreadcrumb($breadcrumb, $breadcrumb);
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php
index 2a1d8aaf878d0..a1ec19988911e 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php
@@ -19,17 +19,12 @@ public function execute()
$typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
$type = $typeArr[0];
- $model = $this->_objectManager->create(
- $type
- )->setId(
- $id
- )->setType(
- $type
- )->setRule(
- $this->_objectManager->create('Magento\CatalogRule\Model\Rule')
- )->setPrefix(
- 'actions'
- );
+ $model = $this->_objectManager->create($type)
+ ->setId($id)
+ ->setType($type)
+ ->setRule($this->_objectManager->create('Magento\CatalogRule\Model\Rule'))
+ ->setPrefix('actions');
+
if (!empty($typeArr[1])) {
$model->setAttribute($typeArr[1]);
}
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php
index 977806d176b76..50b10d6b51fb0 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php
@@ -19,17 +19,12 @@ public function execute()
$typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type')));
$type = $typeArr[0];
- $model = $this->_objectManager->create(
- $type
- )->setId(
- $id
- )->setType(
- $type
- )->setRule(
- $this->_objectManager->create('Magento\CatalogRule\Model\Rule')
- )->setPrefix(
- 'conditions'
- );
+ $model = $this->_objectManager->create($type)
+ ->setId($id)
+ ->setType($type)
+ ->setRule($this->_objectManager->create('Magento\CatalogRule\Model\Rule'))
+ ->setPrefix('conditions');
+
if (!empty($typeArr[1])) {
$model->setAttribute($typeArr[1]);
}
diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php
index 16415977b5582..6aaf1216d3e18 100644
--- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php
+++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Save.php
@@ -17,9 +17,16 @@ class Save extends \Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog
public function execute()
{
if ($this->getRequest()->getPostValue()) {
+
+ /** @var \Magento\CatalogRule\Api\CatalogRuleRepositoryInterface $ruleRepository */
+ $ruleRepository = $this->_objectManager->create(
+ 'Magento\CatalogRule\Api\CatalogRuleRepositoryInterface'
+ );
+
+ /** @var \Magento\CatalogRule\Model\Rule $model */
+ $model = $this->_objectManager->create('Magento\CatalogRule\Model\Rule');
+
try {
- /** @var \Magento\CatalogRule\Model\Rule $model */
- $model = $this->_objectManager->create('Magento\CatalogRule\Model\Rule');
$this->_eventManager->dispatch(
'adminhtml_controller_catalogrule_prepare_save',
['request' => $this->getRequest()]
@@ -33,10 +40,7 @@ public function execute()
$data = $inputFilter->getUnescaped();
$id = $this->getRequest()->getParam('rule_id');
if ($id) {
- $model->load($id);
- if ($id != $model->getId()) {
- throw new LocalizedException(__('Wrong rule specified.'));
- }
+ $model = $ruleRepository->get($id);
}
$validateResult = $model->validateData(new \Magento\Framework\DataObject($data));
@@ -55,8 +59,7 @@ public function execute()
$model->loadPost($data);
$this->_objectManager->get('Magento\Backend\Model\Session')->setPageData($model->getData());
-
- $model->save();
+ $ruleRepository->save($model);
$this->messageManager->addSuccess(__('You saved the rule.'));
$this->_objectManager->get('Magento\Backend\Model\Session')->setPageData(false);
@@ -85,7 +88,7 @@ public function execute()
__('Something went wrong while saving the rule data. Please review the error log.')
);
$this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e);
- $this->_objectManager->get('Magento\Backend\Model\Session')->setPageData($data);
+ $this->_objectManager->get('Magento\Backend\Model\Session')->setPageData($model->getData());
$this->_redirect('catalog_rule/*/edit', ['id' => $this->getRequest()->getParam('rule_id')]);
return;
}
diff --git a/app/code/Magento/CatalogRule/Model/CatalogRuleRepository.php b/app/code/Magento/CatalogRule/Model/CatalogRuleRepository.php
new file mode 100644
index 0000000000000..2c869a0661d8b
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Model/CatalogRuleRepository.php
@@ -0,0 +1,102 @@
+ruleResource = $ruleResource;
+ $this->ruleFactory = $ruleFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save(Data\RuleInterface $rule)
+ {
+ if ($rule->getRuleId()) {
+ $rule = $this->get($rule->getRuleId())->addData($rule->getData());
+ }
+
+ try {
+ $this->ruleResource->save($rule);
+ unset($this->rules[$rule->getId()]);
+ } catch (\Exception $e) {
+ throw new CouldNotSaveException(__('Unable to save rule %1', $rule->getRuleId()));
+ }
+ return $rule;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($ruleId)
+ {
+ if (!isset($this->rules[$ruleId])) {
+ /** @var \Magento\CatalogRule\Model\RuleFactory $rule */
+ $rule = $this->ruleFactory->create();
+
+ /* TODO: change to resource model after entity manager will be fixed */
+ $rule->load($ruleId);
+ if (!$rule->getRuleId()) {
+ throw new NoSuchEntityException(__('Rule with specified ID "%1" not found.', $ruleId));
+ }
+ $this->rules[$ruleId] = $rule;
+ }
+ return $this->rules[$ruleId];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(Data\RuleInterface $rule)
+ {
+ try {
+ $this->ruleResource->delete($rule);
+ unset($this->rules[$rule->getId()]);
+ } catch (\Exception $e) {
+ throw new CouldNotDeleteException(__('Unable to remove rule %1', $rule->getRuleId()));
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteById($ruleId)
+ {
+ $model = $this->get($ruleId);
+ $this->delete($model);
+ return true;
+ }
+}
diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/ReadHandler.php b/app/code/Magento/CatalogRule/Model/ResourceModel/ReadHandler.php
new file mode 100644
index 0000000000000..f38a0158a71aa
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Model/ResourceModel/ReadHandler.php
@@ -0,0 +1,51 @@
+ruleResource = $ruleResource;
+ $this->metadataPool = $metadataPool;
+ }
+
+ /**
+ * @param string $entityType
+ * @param array $entityData
+ * @return array
+ * @throws \Exception
+ */
+ public function execute($entityType, $entityData)
+ {
+ $linkField = $this->metadataPool->getMetadata($entityType)->getLinkField();
+ $entityId = $entityData[$linkField];
+
+ $entityData['customer_group_ids'] = $this->ruleResource->getCustomerGroupIds($entityId);
+ $entityData['website_ids'] = $this->ruleResource->getWebsiteIds($entityId);
+
+ return $entityData;
+ }
+}
diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Rule.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Rule.php
index 7a0e2cec1f24c..b4e5a2f544ee6 100644
--- a/app/code/Magento/CatalogRule/Model/ResourceModel/Rule.php
+++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Rule.php
@@ -30,24 +30,6 @@ class Rule extends \Magento\Rule\Model\ResourceModel\AbstractResource
*/
protected $_logger;
- /**
- * Store associated with rule entities information map
- *
- * @var array
- */
- protected $_associatedEntitiesMap = [
- 'website' => [
- 'associations_table' => 'catalogrule_website',
- 'rule_id_field' => 'rule_id',
- 'entity_id_field' => 'website_id',
- ],
- 'customer_group' => [
- 'associations_table' => 'catalogrule_customer_group',
- 'rule_id_field' => 'rule_id',
- 'entity_id_field' => 'customer_group_id',
- ],
- ];
-
/**
* Catalog rule data
*
@@ -93,6 +75,12 @@ class Rule extends \Magento\Rule\Model\ResourceModel\AbstractResource
protected $priceCurrency;
/**
+ * @var \Magento\Framework\Model\EntityManager
+ */
+ protected $entityManager;
+
+ /**
+ * Rule constructor.
* @param \Magento\Framework\Model\ResourceModel\Db\Context $context
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param Product\ConditionFactory $conditionFactory
@@ -103,7 +91,9 @@ class Rule extends \Magento\Rule\Model\ResourceModel\AbstractResource
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Stdlib\DateTime $dateTime
* @param PriceCurrencyInterface $priceCurrency
- * @param string $connectionName
+ * @param \Magento\Framework\Model\EntityManager $entityManager
+ * @param array $associatedEntitiesMap
+ * @param null $connectionName
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -117,6 +107,8 @@ public function __construct(
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Stdlib\DateTime $dateTime,
PriceCurrencyInterface $priceCurrency,
+ \Magento\Framework\Model\EntityManager $entityManager,
+ array $associatedEntitiesMap = [],
$connectionName = null
) {
$this->_storeManager = $storeManager;
@@ -128,6 +120,8 @@ public function __construct(
$this->_logger = $logger;
$this->dateTime = $dateTime;
$this->priceCurrency = $priceCurrency;
+ $this->entityManager = $entityManager;
+ $this->_associatedEntitiesMap = $associatedEntitiesMap;
parent::__construct($context, $connectionName);
}
@@ -142,49 +136,6 @@ protected function _construct()
$this->_init('catalogrule', 'rule_id');
}
- /**
- * Add customer group ids and website ids to rule data after load
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
- */
- protected function _afterLoad(AbstractModel $object)
- {
- $object->setData('customer_group_ids', (array)$this->getCustomerGroupIds($object->getId()));
- $object->setData('website_ids', (array)$this->getWebsiteIds($object->getId()));
-
- return parent::_afterLoad($object);
- }
-
- /**
- * Bind catalog rule to customer group(s) and website(s).
- * Update products which are matched for rule.
- *
- * @param AbstractModel $object
- * @return $this
- */
- protected function _afterSave(AbstractModel $object)
- {
- if ($object->hasWebsiteIds()) {
- $websiteIds = $object->getWebsiteIds();
- if (!is_array($websiteIds)) {
- $websiteIds = explode(',', (string)$websiteIds);
- }
- $this->bindRuleToEntity($object->getId(), $websiteIds, 'website');
- }
-
- if ($object->hasCustomerGroupIds()) {
- $customerGroupIds = $object->getCustomerGroupIds();
- if (!is_array($customerGroupIds)) {
- $customerGroupIds = explode(',', (string)$customerGroupIds);
- }
- $this->bindRuleToEntity($object->getId(), $customerGroupIds, 'customer_group');
- }
-
- parent::_afterSave($object);
- return $this;
- }
-
/**
* @param \Magento\Framework\Model\AbstractModel $rule
* @return $this
@@ -196,10 +147,6 @@ protected function _afterDelete(\Magento\Framework\Model\AbstractModel $rule)
$this->getTable('catalogrule_product'),
['rule_id=?' => $rule->getId()]
);
- $connection->delete(
- $this->getTable('catalogrule_customer_group'),
- ['rule_id=?' => $rule->getId()]
- );
$connection->delete(
$this->getTable('catalogrule_group_website'),
['rule_id=?' => $rule->getId()]
@@ -240,22 +187,13 @@ public function getRulePrice($date, $wId, $gId, $pId)
public function getRulePrices(\DateTime $date, $websiteId, $customerGroupId, $productIds)
{
$connection = $this->getConnection();
- $select = $connection->select()->from(
- $this->getTable('catalogrule_product_price'),
- ['product_id', 'rule_price']
- )->where(
- 'rule_date = ?',
- $date->format('Y-m-d')
- )->where(
- 'website_id = ?',
- $websiteId
- )->where(
- 'customer_group_id = ?',
- $customerGroupId
- )->where(
- 'product_id IN(?)',
- $productIds
- );
+ $select = $connection->select()
+ ->from($this->getTable('catalogrule_product_price'), ['product_id', 'rule_price'])
+ ->where('rule_date = ?', $date->format('Y-m-d'))
+ ->where('website_id = ?', $websiteId)
+ ->where('customer_group_id = ?', $customerGroupId)
+ ->where('product_id IN(?)', $productIds);
+
return $connection->fetchPairs($select);
}
@@ -274,25 +212,77 @@ public function getRulesFromProduct($date, $websiteId, $customerGroupId, $produc
if (is_string($date)) {
$date = strtotime($date);
}
- $select = $connection->select()->from(
- $this->getTable('catalogrule_product')
- )->where(
- 'website_id = ?',
- $websiteId
- )->where(
- 'customer_group_id = ?',
- $customerGroupId
- )->where(
- 'product_id = ?',
- $productId
- )->where(
- 'from_time = 0 or from_time < ?',
- $date
- )->where(
- 'to_time = 0 or to_time > ?',
- $date
- );
+ $select = $connection->select()
+ ->from($this->getTable('catalogrule_product'))
+ ->where('website_id = ?', $websiteId)
+ ->where('customer_group_id = ?', $customerGroupId)
+ ->where('product_id = ?', $productId)
+ ->where('from_time = 0 or from_time < ?', $date)
+ ->where('to_time = 0 or to_time > ?', $date);
return $connection->fetchAll($select);
}
+
+ /**
+ * @param \Magento\Framework\Model\AbstractModel $object
+ * @param mixed $value
+ * @param string $field
+ * @return $this
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null)
+ {
+ $this->entityManager->load('Magento\CatalogRule\Api\Data\RuleInterface', $object, $value);
+
+ $this->unserializeFields($object);
+ $this->_afterLoad($object);
+
+ return $this;
+ }
+
+ /**
+ * @param AbstractModel $object
+ * @return $this
+ * @throws \Exception
+ */
+ public function save(\Magento\Framework\Model\AbstractModel $object)
+ {
+ if ($object->isDeleted()) {
+ return $this->delete($object);
+ }
+
+ $this->beginTransaction();
+
+ try {
+ if (!$this->isModified($object)) {
+ $this->processNotModifiedSave($object);
+ $this->commit();
+ $object->setHasDataChanges(false);
+ return $this;
+ }
+ $object->validateBeforeSave();
+ $object->beforeSave();
+ if ($object->isSaveAllowed()) {
+ $this->_serializeFields($object);
+ $this->_beforeSave($object);
+ $this->_checkUnique($object);
+ $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
+
+ $this->entityManager->save(
+ 'Magento\CatalogRule\Api\Data\RuleInterface',
+ $object
+ );
+
+ $this->unserializeFields($object);
+ $this->processAfterSaves($object);
+ }
+ $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
+ $object->setHasDataChanges(false);
+ } catch (\Exception $e) {
+ $this->rollBack();
+ $object->setHasDataChanges(true);
+ throw $e;
+ }
+ return $this;
+ }
}
diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Rule/Collection.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Rule/Collection.php
index 33a9c5c81320f..62dd61ea82989 100644
--- a/app/code/Magento/CatalogRule/Model/ResourceModel/Rule/Collection.php
+++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Rule/Collection.php
@@ -12,13 +12,36 @@ class Collection extends \Magento\Rule\Model\ResourceModel\Rule\Collection\Abstr
*
* @var array
*/
- protected $_associatedEntitiesMap = [
- 'website' => [
- 'associations_table' => 'catalogrule_website',
- 'rule_id_field' => 'rule_id',
- 'entity_id_field' => 'website_id',
- ],
- ];
+ protected $_associatedEntitiesMap;
+
+ /**
+ * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
+ * @param \Psr\Log\LoggerInterface $logger
+ * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
+ * @param \Magento\Framework\Event\ManagerInterface $eventManager
+ * @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection
+ * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb|null $resource
+ * @param array $associatedEntitiesMap
+ */
+ public function __construct(
+ \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
+ \Psr\Log\LoggerInterface $logger,
+ \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
+ \Magento\Framework\Event\ManagerInterface $eventManager,
+ \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
+ \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null,
+ array $associatedEntitiesMap = []
+ ) {
+ parent::__construct(
+ $entityFactory,
+ $logger,
+ $fetchStrategy,
+ $eventManager,
+ $connection,
+ $resource
+ );
+ $this->_associatedEntitiesMap = $associatedEntitiesMap;
+ }
/**
* Set resource model
@@ -45,4 +68,73 @@ public function addAttributeInConditionFilter($attributeCode)
return $this;
}
+
+ /**
+ * @param string $entityType
+ * @param string $objectField
+ * @throws \Magento\Framework\Exception\LocalizedException
+ * @return void
+ */
+ protected function mapAssociatedEntities($entityType, $objectField)
+ {
+ if (!$this->_items) {
+ return;
+ }
+
+ $entityInfo = $this->_getAssociatedEntityInfo($entityType);
+ $ruleIdField = $entityInfo['rule_id_field'];
+ $entityIds = $this->getColumnValues($ruleIdField);
+
+ $select = $this->getConnection()->select()->from(
+ $this->getTable($entityInfo['associations_table'])
+ )->where(
+ $ruleIdField . ' IN (?)',
+ $entityIds
+ );
+
+ $associatedEntities = $this->getConnection()->fetchAll($select);
+
+ array_map(function ($associatedEntity) use ($entityInfo, $ruleIdField, $objectField) {
+ $item = $this->getItemByColumnValue($ruleIdField, $associatedEntity[$ruleIdField]);
+ $itemAssociatedValue = $item->getData($objectField) === null ? [] : $item->getData($objectField);
+ $itemAssociatedValue[] = $associatedEntity[$entityInfo['entity_id_field']];
+ $item->setData($objectField, $itemAssociatedValue);
+ }, $associatedEntities);
+ }
+
+ /**
+ * @return $this
+ * @throws \Exception
+ */
+ protected function _afterLoad()
+ {
+ $this->mapAssociatedEntities('website', 'website_ids');
+ $this->mapAssociatedEntities('customer_group', 'customer_group_ids');
+
+ $this->setFlag('add_websites_to_result', false);
+ return parent::_afterLoad();
+ }
+
+ /**
+ * Limit rules collection by specific customer group
+ *
+ * @param int $customerGroupId
+ * @return $this
+ */
+ public function addCustomerGroupFilter($customerGroupId)
+ {
+ $entityInfo = $this->_getAssociatedEntityInfo('customer_group');
+ if (!$this->getFlag('is_customer_group_joined')) {
+ $this->setFlag('is_customer_group_joined', true);
+ $this->getSelect()->join(
+ ['customer_group' => $this->getTable($entityInfo['associations_table'])],
+ $this->getConnection()
+ ->quoteInto('customer_group.' . $entityInfo['entity_id_field'] . ' = ?', $customerGroupId)
+ . ' AND main_table.' . $entityInfo['rule_id_field'] . ' = customer_group.'
+ . $entityInfo['rule_id_field'],
+ []
+ );
+ }
+ return $this;
+ }
}
diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/SaveHandler.php b/app/code/Magento/CatalogRule/Model/ResourceModel/SaveHandler.php
new file mode 100644
index 0000000000000..fabb45960109b
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Model/ResourceModel/SaveHandler.php
@@ -0,0 +1,61 @@
+ruleResource = $ruleResource;
+ $this->metadataPool = $metadataPool;
+ }
+
+ /**
+ * @param string $entityType
+ * @param array $entityData
+ * @return array
+ * @throws \Exception
+ */
+ public function execute($entityType, $entityData)
+ {
+ $linkField = $this->metadataPool->getMetadata($entityType)->getLinkField();
+ if (isset($entityData['website_ids'])) {
+ $websiteIds = $entityData['website_ids'];
+ if (!is_array($websiteIds)) {
+ $websiteIds = explode(',', (string)$websiteIds);
+ }
+ $this->ruleResource->bindRuleToEntity($entityData[$linkField], $websiteIds, 'website');
+ }
+
+ if (isset($entityData['customer_group_ids'])) {
+ $customerGroupIds = $entityData['customer_group_ids'];
+ if (!is_array($customerGroupIds)) {
+ $customerGroupIds = explode(',', (string)$customerGroupIds);
+ }
+ $this->ruleResource->bindRuleToEntity($entityData[$linkField], $customerGroupIds, 'customer_group');
+ }
+ return $entityData;
+ }
+}
diff --git a/app/code/Magento/CatalogRule/Model/Rule.php b/app/code/Magento/CatalogRule/Model/Rule.php
index dcd36cfaf3086..d89b7d6e4c143 100644
--- a/app/code/Magento/CatalogRule/Model/Rule.php
+++ b/app/code/Magento/CatalogRule/Model/Rule.php
@@ -12,35 +12,16 @@
*
* @method \Magento\CatalogRule\Model\ResourceModel\Rule _getResource()
* @method \Magento\CatalogRule\Model\ResourceModel\Rule getResource()
- * @method string getName()
- * @method \Magento\CatalogRule\Model\Rule setName(string $value)
- * @method string getDescription()
- * @method \Magento\CatalogRule\Model\Rule setDescription(string $value)
- * @method string getFromDate()
* @method \Magento\CatalogRule\Model\Rule setFromDate(string $value)
- * @method string getToDate()
* @method \Magento\CatalogRule\Model\Rule setToDate(string $value)
* @method \Magento\CatalogRule\Model\Rule setCustomerGroupIds(string $value)
- * @method int getIsActive()
- * @method \Magento\CatalogRule\Model\Rule setIsActive(int $value)
- * @method string getConditionsSerialized()
- * @method \Magento\CatalogRule\Model\Rule setConditionsSerialized(string $value)
- * @method string getActionsSerialized()
- * @method \Magento\CatalogRule\Model\Rule setActionsSerialized(string $value)
- * @method int getStopRulesProcessing()
- * @method \Magento\CatalogRule\Model\Rule setStopRulesProcessing(int $value)
- * @method int getSortOrder()
- * @method \Magento\CatalogRule\Model\Rule setSortOrder(int $value)
- * @method string getSimpleAction()
- * @method \Magento\CatalogRule\Model\Rule setSimpleAction(string $value)
- * @method float getDiscountAmount()
- * @method \Magento\CatalogRule\Model\Rule setDiscountAmount(float $value)
* @method string getWebsiteIds()
* @method \Magento\CatalogRule\Model\Rule setWebsiteIds(string $value)
* @SuppressWarnings(PHPMD.TooManyFields)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ * @SuppressWarnings(PHPMD.ExcessivePublicCount)
*/
-class Rule extends \Magento\Rule\Model\AbstractModel
+class Rule extends \Magento\Rule\Model\AbstractModel implements \Magento\CatalogRule\Api\Data\RuleInterface
{
/**
* Prefix of model events names
@@ -138,11 +119,6 @@ class Rule extends \Magento\Rule\Model\AbstractModel
*/
protected $_productCollectionFactory;
- /**
- * @var \Magento\Framework\Stdlib\DateTime
- */
- protected $dateTime;
-
/**
* @var \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor;
*/
@@ -151,28 +127,32 @@ class Rule extends \Magento\Rule\Model\AbstractModel
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
+ * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
+ * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
* @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\CatalogRule\Model\Rule\Condition\CombineFactory $combineFactory
- * @param \Magento\CatalogRule\Model\Rule\Action\CollectionFactory $actionCollectionFactory
+ * @param Rule\Condition\CombineFactory $combineFactory
+ * @param Rule\Action\CollectionFactory $actionCollectionFactory
* @param \Magento\Catalog\Model\ProductFactory $productFactory
* @param \Magento\Framework\Model\ResourceModel\Iterator $resourceIterator
* @param \Magento\Customer\Model\Session $customerSession
* @param \Magento\CatalogRule\Helper\Data $catalogRuleData
* @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypesList
- * @param \Magento\Framework\Stdlib\DateTime $dateTime
- * @param \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor $ruleProductProcessor
- * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
- * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
+ * @param Indexer\Rule\RuleProductProcessor $ruleProductProcessor
+ * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
+ * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
* @param array $relatedCacheTypes
* @param array $data
+ *
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
+ \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
+ \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
@@ -184,7 +164,6 @@ public function __construct(
\Magento\Customer\Model\Session $customerSession,
\Magento\CatalogRule\Helper\Data $catalogRuleData,
\Magento\Framework\App\Cache\TypeListInterface $cacheTypesList,
- \Magento\Framework\Stdlib\DateTime $dateTime,
\Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor $ruleProductProcessor,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
@@ -201,9 +180,18 @@ public function __construct(
$this->_catalogRuleData = $catalogRuleData;
$this->_cacheTypesList = $cacheTypesList;
$this->_relatedCacheTypes = $relatedCacheTypes;
- $this->dateTime = $dateTime;
$this->_ruleProductProcessor = $ruleProductProcessor;
- parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
+ parent::__construct(
+ $context,
+ $registry,
+ $extensionFactory,
+ $customAttributeFactory,
+ $formFactory,
+ $localeDate,
+ $resource,
+ $resourceCollection,
+ $data
+ );
}
/**
@@ -587,4 +575,203 @@ protected function dataDiff($array1, $array2)
}
return $result;
}
+
+ //@codeCoverageIgnoreStart
+ /**
+ * {@inheritdoc}
+ */
+ public function getRuleId()
+ {
+ return $this->getData(self::RULE_ID);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setRuleId($ruleId)
+ {
+ return $this->setData(self::RULE_ID, $ruleId);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return $this->getData(self::NAME);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setName($name)
+ {
+ return $this->setData(self::NAME, $name);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDescription()
+ {
+ return $this->getData(self::DESCRIPTION);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setDescription($description)
+ {
+ return $this->setData(self::DESCRIPTION, $description);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIsActive()
+ {
+ return $this->getData(self::IS_ACTIVE);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setIsActive($isActive)
+ {
+ return $this->setData(self::IS_ACTIVE, $isActive);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConditionsSerialized()
+ {
+ return $this->getData(self::CONDITIONS_SERIALIZED);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConditionsSerialized($conditions)
+ {
+ return $this->setData(self::CONDITIONS_SERIALIZED, $conditions);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getActionsSerialized()
+ {
+ return $this->getData(self::ACTIONS_SERIALIZED);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setActionsSerialized($actions)
+ {
+ return $this->setData(self::ACTIONS_SERIALIZED, $actions);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getStopRulesProcessing()
+ {
+ return $this->getData(self::STOP_RULES_PROCESSING);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setStopRulesProcessing($isStopProcessing)
+ {
+ return $this->setData(self::STOP_RULES_PROCESSING, $isStopProcessing);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSortOrder()
+ {
+ return $this->getData(self::SORT_ORDER);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setSortOrder($sortOrder)
+ {
+ return $this->setData(self::SORT_ORDER, $sortOrder);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSimpleAction()
+ {
+ return $this->getData(self::SIMPLE_ACTION);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setSimpleAction($action)
+ {
+ return $this->setData(self::SIMPLE_ACTION, $action);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDiscountAmount()
+ {
+ return $this->getData(self::DISCOUNT_AMOUNT);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setDiscountAmount($amount)
+ {
+ return $this->setData(self::DISCOUNT_AMOUNT, $amount);
+ }
+
+ /**
+ * @return string
+ */
+ public function getFromDate()
+ {
+ return $this->getData('from_date');
+ }
+
+ /**
+ * @return string
+ */
+ public function getToDate()
+ {
+ return $this->getData('to_date');
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return \Magento\CatalogRule\Api\Data\RuleExtensionInterface|null
+ */
+ public function getExtensionAttributes()
+ {
+ return $this->_getExtensionAttributes();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param \Magento\CatalogRule\Api\Data\RuleExtensionInterface $extensionAttributes
+ * @return $this
+ */
+ public function setExtensionAttributes(\Magento\CatalogRule\Api\Data\RuleExtensionInterface $extensionAttributes)
+ {
+ return $this->_setExtensionAttributes($extensionAttributes);
+ }
+ //@codeCoverageIgnoreEnd
}
diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/CatalogRuleRepositoryTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/CatalogRuleRepositoryTest.php
new file mode 100644
index 0000000000000..8bb0522fa564f
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Test/Unit/Model/CatalogRuleRepositoryTest.php
@@ -0,0 +1,146 @@
+ruleResourceMock = $this->getMock('Magento\CatalogRule\Model\ResourceModel\Rule', [], [], '', false);
+ $this->ruleFactoryMock = $this->getMock('Magento\CatalogRule\Model\RuleFactory', ['create'], [], '', false);
+ $this->ruleMock = $this->getMock('Magento\CatalogRule\Model\Rule', [], [], '', false);
+ $this->repository = new \Magento\CatalogRule\Model\CatalogRuleRepository(
+ $this->ruleResourceMock,
+ $this->ruleFactoryMock
+ );
+ }
+
+ public function testSave()
+ {
+ $this->ruleMock->expects($this->once())->method('getRuleId')->willReturn(null);
+ $this->ruleMock->expects($this->once())->method('getId')->willReturn(1);
+ $this->ruleResourceMock->expects($this->once())->method('save')->with($this->ruleMock);
+ $this->assertEquals($this->ruleMock, $this->repository->save($this->ruleMock));
+ }
+
+ public function testEditRule()
+ {
+ $ruleId = 1;
+ $ruleData = ['id' => $ruleId];
+ $this->ruleMock->expects($this->once())->method('getData')->willReturn($ruleData);
+ $ruleMock = $this->getMock('Magento\CatalogRule\Model\Rule', [], [], '', false);
+ $this->ruleMock->expects($this->exactly(2))->method('getRuleId')->willReturn($ruleId);
+ $ruleMock->expects($this->once())->method('addData')->with($ruleData)->willReturn($ruleMock);
+ $this->ruleFactoryMock->expects($this->once())->method('create')->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('load')->with($ruleId)->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('getRuleId')->willReturn($ruleId);
+ $this->ruleResourceMock->expects($this->once())->method('save')->with($ruleMock)->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('getId')->willReturn($ruleId);
+ $this->assertEquals($ruleMock, $this->repository->save($this->ruleMock));
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\CouldNotSaveException
+ * @expectedExceptionMessage Unable to save rule 1
+ */
+ public function testEnableSaveRule()
+ {
+ $this->ruleMock->expects($this->at(0))->method('getRuleId')->willReturn(null);
+ $this->ruleMock->expects($this->at(1))->method('getRuleId')->willReturn(1);
+ $this->ruleMock->expects($this->never())->method('getId');
+ $this->ruleResourceMock
+ ->expects($this->once())
+ ->method('save')
+ ->with($this->ruleMock)->willThrowException(new \Exception());
+ $this->repository->save($this->ruleMock);
+ }
+
+ public function testDeleteRule()
+ {
+ $this->ruleMock->expects($this->once())->method('getId')->willReturn(1);
+ $this->ruleResourceMock
+ ->expects($this->once())
+ ->method('delete')
+ ->with($this->ruleMock);
+ $this->assertEquals(true, $this->repository->delete($this->ruleMock));
+ }
+
+ public function testDeleteRuleById()
+ {
+ $ruleId = 1;
+ $ruleMock = $this->getMock('Magento\CatalogRule\Model\Rule', [], [], '', false);
+ $this->ruleFactoryMock->expects($this->once())->method('create')->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('getRuleId')->willReturn($ruleId);
+ $ruleMock->expects($this->once())->method('load')->with($ruleId)->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('getId')->willReturn($ruleId);
+ $this->ruleResourceMock
+ ->expects($this->once())
+ ->method('delete')
+ ->with($ruleMock);
+ $this->assertEquals(true, $this->repository->deleteById($ruleId));
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\CouldNotDeleteException
+ * @expectedExceptionMessage Unable to remove rule 1
+ */
+ public function testUnableDeleteRule()
+ {
+ $this->ruleMock->expects($this->once())->method('getRuleId')->willReturn(1);
+ $this->ruleResourceMock
+ ->expects($this->once())
+ ->method('delete')
+ ->with($this->ruleMock)->willThrowException(new \Exception());
+ $this->repository->delete($this->ruleMock);
+ }
+
+ public function testGetRule()
+ {
+ $ruleId = 1;
+ $ruleMock = $this->getMock('Magento\CatalogRule\Model\Rule', [], [], '', false);
+ $this->ruleFactoryMock->expects($this->once())->method('create')->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('load')->with($ruleId)->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('getRuleId')->willReturn($ruleId);
+ $this->assertEquals($ruleMock, $this->repository->get($ruleId));
+ /** verify that rule was cached */
+ $this->assertEquals($ruleMock, $this->repository->get($ruleId));
+ }
+
+ /**
+ * @expectedException \Magento\Framework\Exception\NoSuchEntityException
+ * @expectedExceptionMessage Rule with specified ID "1" not found.
+ */
+ public function testGetNonExistentRule()
+ {
+ $ruleId = 1;
+ $ruleMock = $this->getMock('Magento\CatalogRule\Model\Rule', [], [], '', false);
+ $this->ruleFactoryMock->expects($this->once())->method('create')->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('load')->with($ruleId)->willReturn($ruleMock);
+ $ruleMock->expects($this->once())->method('getRuleId')->willReturn(null);
+ $this->assertEquals($ruleMock, $this->repository->get($ruleId));
+ }
+}
diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/ResourceModel/ReadHandlerTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/ResourceModel/ReadHandlerTest.php
new file mode 100644
index 0000000000000..b6be4762de6da
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Test/Unit/Model/ResourceModel/ReadHandlerTest.php
@@ -0,0 +1,78 @@
+resourceMock = $this->getMock('\Magento\CatalogRule\Model\ResourceModel\Rule', [], [], '', false);
+ $this->metadataMock = $this->getMock('\Magento\Framework\Model\Entity\MetadataPool', [], [], '', false);
+ $this->subject = new \Magento\CatalogRule\Model\ResourceModel\ReadHandler(
+ $this->resourceMock,
+ $this->metadataMock
+ );
+ }
+
+ public function testExecute()
+ {
+ $linkedField = 'entity_id';
+ $entityId = 100;
+ $entityType = '\Magento\CatalogRule\Entity\Type';
+ $entityData = [
+ $linkedField => $entityId
+ ];
+
+ $customerGroupIds = [1, 2, 3];
+ $websiteIds = [4, 5, 6];
+
+ $metadataMock = $this->getMock(
+ '\Magento\Framework\Model\Entity\EntityMetadata',
+ ['getLinkField'],
+ [],
+ '',
+ false
+ );
+ $this->metadataMock->expects($this->once())
+ ->method('getMetadata')
+ ->with($entityType)
+ ->willReturn($metadataMock);
+
+ $metadataMock->expects($this->once())->method('getLinkField')->willReturn($linkedField);
+
+ $this->resourceMock->expects($this->once())
+ ->method('getCustomerGroupIds')
+ ->with($entityId)
+ ->willReturn($customerGroupIds);
+ $this->resourceMock->expects($this->once())
+ ->method('getWebsiteIds')
+ ->with($entityId)
+ ->willReturn($websiteIds);
+
+ $expectedResult = [
+ $linkedField => $entityId,
+ 'customer_group_ids' => $customerGroupIds,
+ 'website_ids' => $websiteIds
+ ];
+
+ $this->assertEquals($expectedResult, $this->subject->execute($entityType, $entityData));
+ }
+}
diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/ResourceModel/SaveHandlerTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/ResourceModel/SaveHandlerTest.php
new file mode 100644
index 0000000000000..e108d1103be4b
--- /dev/null
+++ b/app/code/Magento/CatalogRule/Test/Unit/Model/ResourceModel/SaveHandlerTest.php
@@ -0,0 +1,74 @@
+resourceMock = $this->getMock('\Magento\CatalogRule\Model\ResourceModel\Rule', [], [], '', false);
+ $this->metadataMock = $this->getMock('\Magento\Framework\Model\Entity\MetadataPool', [], [], '', false);
+ $this->subject = new \Magento\CatalogRule\Model\ResourceModel\SaveHandler(
+ $this->resourceMock,
+ $this->metadataMock
+ );
+ }
+
+ public function testExecute()
+ {
+ $linkedField = 'entity_id';
+ $entityId = 100;
+ $entityType = '\Magento\CatalogRule\Entity\Type';
+
+ $customerGroupIds = '1, 2, 3';
+ $websiteIds = '4, 5, 6';
+ $entityData = [
+ $linkedField => $entityId,
+ 'website_ids' => $websiteIds,
+ 'customer_group_ids' => $customerGroupIds
+ ];
+
+ $metadataMock = $this->getMock(
+ '\Magento\Framework\Model\Entity\EntityMetadata',
+ ['getLinkField'],
+ [],
+ '',
+ false
+ );
+ $this->metadataMock->expects($this->once())
+ ->method('getMetadata')
+ ->with($entityType)
+ ->willReturn($metadataMock);
+ $metadataMock->expects($this->once())->method('getLinkField')->willReturn($linkedField);
+
+ $this->resourceMock->expects($this->at(0))
+ ->method('bindRuleToEntity')
+ ->with($entityId, explode(',', (string)$websiteIds), 'website')
+ ->willReturnSelf();
+
+ $this->resourceMock->expects($this->at(1))
+ ->method('bindRuleToEntity')
+ ->with($entityId, explode(',', (string)$customerGroupIds), 'customer_group')
+ ->willReturnSelf();
+
+ $this->assertEquals($entityData, $this->subject->execute($entityType, $entityData));
+ }
+}
diff --git a/app/code/Magento/CatalogRule/etc/di.xml b/app/code/Magento/CatalogRule/etc/di.xml
index da4a8ad03cba6..5accde1deb86c 100644
--- a/app/code/Magento/CatalogRule/etc/di.xml
+++ b/app/code/Magento/CatalogRule/etc/di.xml
@@ -9,9 +9,36 @@
Magento\Framework\Event\Manager\Proxy
+
+ -
+
- catalogrule_website
+ - rule_id
+ - website_id
+
+ -
+
- catalogrule_customer_group
+ - rule_id
+ - customer_group_id
+
+
+
+
+
+
+
+ -
+
- catalogrule_website
+ - rule_id
+ - website_id
+
+ -
+
- catalogrule_customer_group
+ - rule_id
+ - customer_group_id
+
+
-
@@ -33,4 +60,44 @@
+
+
+
+
+
+ -
+
- catalogrule
+ - rule_id
+
+
+
+ - catalog_product
+
+
+
+
+
+
+ -
+
- Magento\Framework\Model\Operation\Read
+ - Magento\Framework\Model\Operation\Write\Create
+ - Magento\Framework\Model\Operation\Write\Update
+ - Magento\Framework\Model\Operation\Write\Delete
+
+
+
+
+
+
+
+ -
+
-
+
- Magento\CatalogRule\Model\ResourceModel\ReadHandler
+ - Magento\CatalogRule\Model\ResourceModel\SaveHandler
+ - Magento\CatalogRule\Model\ResourceModel\SaveHandler
+
+
+
+
+
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructureFactory.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructureFactory.php
new file mode 100644
index 0000000000000..49adbc21de059
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructureFactory.php
@@ -0,0 +1,85 @@
+objectManager = $objectManager;
+ $this->scopeConfig = $scopeConfig;
+ $this->configPath = $configPath;
+ $this->structures = $structures;
+ }
+
+ /**
+ * Create index structure
+ *
+ * @param array $data
+ * @return IndexStructureInterface
+ */
+ public function create(array $data = [])
+ {
+ $currentStructure = $this->scopeConfig->getValue($this->configPath, ScopeInterface::SCOPE_STORE);
+ if (!isset($this->structures[$currentStructure])) {
+ throw new \LogicException(
+ 'There is no such index structure: ' . $currentStructure
+ );
+ }
+ $indexStructure = $this->objectManager->create($this->structures[$currentStructure], $data);
+
+ if (!$indexStructure instanceof IndexStructureInterface) {
+ throw new \InvalidArgumentException(
+ $indexStructure . ' doesn\'t implement \Magento\Framework\Indexer\IndexStructureInterface'
+ );
+ }
+
+ return $indexStructure;
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructureProxy.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructureProxy.php
new file mode 100644
index 0000000000000..fd90d6d7e4179
--- /dev/null
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexStructureProxy.php
@@ -0,0 +1,64 @@
+indexStructureFactory = $indexStructureFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(
+ $index,
+ array $dimensions = []
+ ) {
+ return $this->getEntity()->delete($index, $dimensions);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create(
+ $index,
+ array $fields,
+ array $dimensions = []
+ ) {
+ return $this->getEntity()->create($index, $fields, $dimensions);
+ }
+
+ /**
+ * Get instance of current index structure
+ *
+ * @return IndexStructureInterface
+ */
+ private function getEntity()
+ {
+ if (empty($this->indexStructureEntity)) {
+ $this->indexStructureEntity = $this->indexStructureFactory->create();
+ }
+ return $this->indexStructureEntity;
+ }
+}
diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
index fa5ca4ba80a39..048086fdcacdf 100644
--- a/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
+++ b/app/code/Magento/CatalogSearch/Model/Indexer/IndexerHandler.php
@@ -9,6 +9,7 @@
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
+use Magento\Framework\Indexer\IndexStructureInterface;
use Magento\Framework\Search\Request\Dimension;
use Magento\Framework\Search\Request\IndexScopeResolverInterface;
use Magento\Framework\Indexer\SaveHandler\Batch;
@@ -17,7 +18,7 @@
class IndexerHandler implements IndexerInterface
{
/**
- * @var IndexStructure
+ * @var IndexStructureInterface
*/
private $indexStructure;
@@ -57,7 +58,7 @@ class IndexerHandler implements IndexerInterface
private $indexScopeResolver;
/**
- * @param IndexStructure $indexStructure
+ * @param IndexStructureInterface $indexStructure
* @param ResourceConnection $resource
* @param Config $eavConfig
* @param Batch $batch
@@ -66,7 +67,7 @@ class IndexerHandler implements IndexerInterface
* @param int $batchSize
*/
public function __construct(
- IndexStructure $indexStructure,
+ IndexStructureInterface $indexStructure,
ResourceConnection $resource,
Config $eavConfig,
Batch $batch,
diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml
index 815f2b223f04e..37d7cf2da1ed4 100644
--- a/app/code/Magento/CatalogSearch/etc/di.xml
+++ b/app/code/Magento/CatalogSearch/etc/di.xml
@@ -19,6 +19,15 @@
+
+
+ Magento\CatalogSearch\Model\ResourceModel\EngineInterface::CONFIG_ENGINE_PATH
+
+ - Magento\CatalogSearch\Model\Indexer\IndexStructure
+
+
+
+
diff --git a/app/code/Magento/CatalogWidget/Model/Rule.php b/app/code/Magento/CatalogWidget/Model/Rule.php
index 5ad9c4c4877fe..70f2d98733ea0 100644
--- a/app/code/Magento/CatalogWidget/Model/Rule.php
+++ b/app/code/Magento/CatalogWidget/Model/Rule.php
@@ -19,16 +19,21 @@ class Rule extends \Magento\Rule\Model\AbstractModel
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
+ * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
+ * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
* @param Rule\Condition\CombineFactory $conditionsFactory
- * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
- * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
+ * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
+ * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
* @param array $data
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
+ \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
+ \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\CatalogWidget\Model\Rule\Condition\CombineFactory $conditionsFactory,
@@ -37,7 +42,17 @@ public function __construct(
array $data = []
) {
$this->conditionsFactory = $conditionsFactory;
- parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
+ parent::__construct(
+ $context,
+ $registry,
+ $extensionFactory,
+ $customAttributeFactory,
+ $formFactory,
+ $localeDate,
+ $resource,
+ $resourceCollection,
+ $data
+ );
}
/**
diff --git a/app/code/Magento/Cms/Model/Block.php b/app/code/Magento/Cms/Model/Block.php
index 6b5c5b6d08a04..aa3109744dff6 100644
--- a/app/code/Magento/Cms/Model/Block.php
+++ b/app/code/Magento/Cms/Model/Block.php
@@ -6,15 +6,19 @@
namespace Magento\Cms\Model;
use Magento\Cms\Api\Data\BlockInterface;
+use Magento\Cms\Model\ResourceModel\Block as ResourceCmsBlock;
use Magento\Framework\DataObject\IdentityInterface;
+use Magento\Framework\Model\AbstractModel;
/**
* CMS block model
*
- * @method \Magento\Cms\Model\ResourceModel\Block _getResource()
- * @method \Magento\Cms\Model\ResourceModel\Block getResource()
+ * @method ResourceCmsBlock _getResource()
+ * @method ResourceCmsBlock getResource()
+ * @method Block setStoreId(array $storeId)
+ * @method array getStoreId()
*/
-class Block extends \Magento\Framework\Model\AbstractModel implements BlockInterface, IdentityInterface
+class Block extends AbstractModel implements BlockInterface, IdentityInterface
{
/**
* CMS block cache tag
@@ -51,7 +55,7 @@ protected function _construct()
/**
* Prevent blocks recursion
*
- * @return \Magento\Framework\Model\AbstractModel
+ * @return AbstractModel
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function beforeSave()
diff --git a/app/code/Magento/Cms/Model/Page.php b/app/code/Magento/Cms/Model/Page.php
index 04da7105c4d65..b248ad835d028 100644
--- a/app/code/Magento/Cms/Model/Page.php
+++ b/app/code/Magento/Cms/Model/Page.php
@@ -6,15 +6,19 @@
namespace Magento\Cms\Model;
use Magento\Cms\Api\Data\PageInterface;
+use Magento\Cms\Model\ResourceModel\Page as ResourceCmsPage;
use Magento\Framework\DataObject\IdentityInterface;
+use Magento\Framework\Model\AbstractModel;
/**
* Cms Page Model
*
- * @method \Magento\Cms\Model\ResourceModel\Page _getResource()
- * @method \Magento\Cms\Model\ResourceModel\Page getResource()
+ * @method ResourceCmsPage _getResource()
+ * @method ResourceCmsPage getResource()
+ * @method Page setStoreId(array $storeId)
+ * @method array getStoreId()
*/
-class Page extends \Magento\Framework\Model\AbstractModel implements PageInterface, IdentityInterface
+class Page extends AbstractModel implements PageInterface, IdentityInterface
{
/**
* No route page id
diff --git a/app/code/Magento/Cms/Model/ResourceModel/AbstractCollection.php b/app/code/Magento/Cms/Model/ResourceModel/AbstractCollection.php
index 7b2e0829cf4d3..b9f0f8006be30 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/AbstractCollection.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/AbstractCollection.php
@@ -17,12 +17,18 @@ abstract class AbstractCollection extends \Magento\Framework\Model\ResourceModel
*/
protected $storeManager;
+ /**
+ * @var \Magento\Framework\Model\Entity\MetadataPool
+ */
+ protected $metadataPool;
+
/**
* @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
+ * @param \Magento\Framework\Model\Entity\MetadataPool $metadataPool
* @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection
* @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb|null $resource
*/
@@ -32,45 +38,47 @@ public function __construct(
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Store\Model\StoreManagerInterface $storeManager,
+ \Magento\Framework\Model\Entity\MetadataPool $metadataPool,
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
\Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
) {
- parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
$this->storeManager = $storeManager;
+ $this->metadataPool = $metadataPool;
+ parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
}
/**
* Perform operations after collection load
*
* @param string $tableName
- * @param string $columnName
+ * @param string|null $linkField
* @return void
*/
- protected function performAfterLoad($tableName, $columnName)
+ protected function performAfterLoad($tableName, $linkField)
{
- $items = $this->getColumnValues($columnName);
- if (count($items)) {
+ $linkedIds = $this->getColumnValues($linkField);
+ if (count($linkedIds)) {
$connection = $this->getConnection();
$select = $connection->select()->from(['cms_entity_store' => $this->getTable($tableName)])
- ->where('cms_entity_store.' . $columnName . ' IN (?)', $items);
+ ->where('cms_entity_store.' . $linkField . ' IN (?)', $linkedIds);
$result = $connection->fetchPairs($select);
if ($result) {
foreach ($this as $item) {
- $entityId = $item->getData($columnName);
- if (!isset($result[$entityId])) {
+ $linkedId = $item->getData($linkField);
+ if (!isset($result[$linkedId])) {
continue;
}
- if ($result[$entityId] == 0) {
+ if ($result[$linkedId] == 0) {
$stores = $this->storeManager->getStores(false, true);
$storeId = current($stores)->getId();
$storeCode = key($stores);
} else {
- $storeId = $result[$item->getData($columnName)];
+ $storeId = $result[$linkedId];
$storeCode = $this->storeManager->getStore($storeId)->getCode();
}
$item->setData('_first_store_id', $storeId);
$item->setData('store_code', $storeCode);
- $item->setData('store_id', [$result[$entityId]]);
+ $item->setData('store_id', [$result[$linkedId]]);
}
}
}
@@ -129,18 +137,18 @@ protected function performAddStoreFilter($store, $withAdmin = true)
* Join store relation table if there is store filter
*
* @param string $tableName
- * @param string $columnName
+ * @param string|null $linkField
* @return void
*/
- protected function joinStoreRelationTable($tableName, $columnName)
+ protected function joinStoreRelationTable($tableName, $linkField)
{
if ($this->getFilter('store')) {
$this->getSelect()->join(
['store_table' => $this->getTable($tableName)],
- 'main_table.' . $columnName . ' = store_table.' . $columnName,
+ 'main_table.' . $linkField . ' = store_table.' . $linkField,
[]
)->group(
- 'main_table.' . $columnName
+ 'main_table.' . $linkField
);
}
parent::_renderFiltersBefore();
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block.php b/app/code/Magento/Cms/Model/ResourceModel/Block.php
index 2794d5d3228b5..04f2cdd5c4aed 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/Block.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/Block.php
@@ -5,6 +5,12 @@
*/
namespace Magento\Cms\Model\ResourceModel;
+use Magento\Cms\Api\Data\BlockInterface;
+use Magento\Framework\Model\Entity\MetadataPool;
+use Magento\Framework\Model\EntityManager;
+use Magento\Framework\Model\ResourceModel\Db\Context;
+use Magento\Store\Model\StoreManagerInterface;
+
/**
* CMS block model
*/
@@ -13,24 +19,38 @@ class Block extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
/**
* Store manager
*
- * @var \Magento\Store\Model\StoreManagerInterface
+ * @var StoreManagerInterface
*/
protected $_storeManager;
/**
- * Construct
- *
- * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+ * @var EntityManager
+ */
+ protected $entityManager;
+
+ /**
+ * @var MetadataPool
+ */
+ protected $metadataPool;
+
+ /**
+ * @param Context $context
+ * @param StoreManagerInterface $storeManager
+ * @param EntityManager $entityManager
+ * @param MetadataPool $metadataPool
* @param string $connectionName
*/
public function __construct(
- \Magento\Framework\Model\ResourceModel\Db\Context $context,
- \Magento\Store\Model\StoreManagerInterface $storeManager,
+ Context $context,
+ StoreManagerInterface $storeManager,
+ EntityManager $entityManager,
+ MetadataPool $metadataPool,
$connectionName = null
) {
- parent::__construct($context, $connectionName);
$this->_storeManager = $storeManager;
+ $this->entityManager = $entityManager;
+ $this->metadataPool = $metadataPool;
+ parent::__construct($context, $connectionName);
}
/**
@@ -43,21 +63,6 @@ protected function _construct()
$this->_init('cms_block', 'block_id');
}
- /**
- * Process block data before deleting
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return \Magento\Cms\Model\ResourceModel\Page
- */
- protected function _beforeDelete(\Magento\Framework\Model\AbstractModel $object)
- {
- $condition = ['block_id = ?' => (int)$object->getId()];
-
- $this->getConnection()->delete($this->getTable('cms_block_store'), $condition);
-
- return parent::_beforeDelete($object);
- }
-
/**
* Perform operations before object save
*
@@ -76,71 +81,39 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
}
/**
- * Perform operations after object save
+ * Load an object
*
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
- {
- $oldStores = $this->lookupStoreIds($object->getId());
- $newStores = (array)$object->getStores();
-
- $table = $this->getTable('cms_block_store');
- $insert = array_diff($newStores, $oldStores);
- $delete = array_diff($oldStores, $newStores);
-
- if ($delete) {
- $where = ['block_id = ?' => (int)$object->getId(), 'store_id IN (?)' => $delete];
-
- $this->getConnection()->delete($table, $where);
- }
-
- if ($insert) {
- $data = [];
-
- foreach ($insert as $storeId) {
- $data[] = ['block_id' => (int)$object->getId(), 'store_id' => (int)$storeId];
- }
-
- $this->getConnection()->insertMultiple($table, $data);
- }
-
- return parent::_afterSave($object);
- }
-
- /**
- * Load an object using 'identifier' field if there's no field specified and value is not numeric
- *
- * @param \Magento\Framework\Model\AbstractModel $object
+ * @param \Magento\Cms\Model\Block|\Magento\Framework\Model\AbstractModel $object
* @param mixed $value
- * @param string $field
+ * @param string $field field to load by (defaults to model id)
* @return $this
*/
public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null)
{
+ $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
+
if (!is_numeric($value) && $field === null) {
$field = 'identifier';
+ } elseif (!$field) {
+ $field = $entityMetadata->getIdentifierField();
}
- return parent::load($object, $value, $field);
- }
-
- /**
- * Perform operations after object load
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
- {
- if ($object->getId()) {
- $stores = $this->lookupStoreIds($object->getId());
- $object->setData('store_id', $stores);
- $object->setData('stores', $stores);
+ $isId = true;
+ if ($field != $entityMetadata->getIdentifierField() || $object->getStoreId()) {
+ $select = $this->_getLoadSelect($field, $value, $object);
+ $select->reset(\Magento\Framework\DB\Select::COLUMNS)
+ ->columns($this->getMainTable() . '.' . $entityMetadata->getIdentifierField())
+ ->limit(1);
+ $result = $this->getConnection()->fetchCol($select);
+ $value = count($result) ? $result[0] : $value;
+ $isId = count($result);
}
- return parent::_afterLoad($object);
+ if ($isId) {
+ $this->entityManager->load(BlockInterface::class, $object, $value);
+ $this->_afterLoad($object);
+ }
+ return $this;
}
/**
@@ -148,11 +121,14 @@ protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
*
* @param string $field
* @param mixed $value
- * @param \Magento\Cms\Model\Block $object
+ * @param \Magento\Cms\Model\Block|\Magento\Framework\Model\AbstractModel $object
* @return \Magento\Framework\DB\Select
*/
protected function _getLoadSelect($field, $value, $object)
{
+ $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
+ $linkField = $entityMetadata->getLinkField();
+
$select = parent::_getLoadSelect($field, $value, $object);
if ($object->getStoreId()) {
@@ -160,19 +136,13 @@ protected function _getLoadSelect($field, $value, $object)
$select->join(
['cbs' => $this->getTable('cms_block_store')],
- $this->getMainTable() . '.block_id = cbs.block_id',
+ $this->getMainTable() . '.' . $linkField . ' = cbs.' . $linkField,
['store_id']
- )->where(
- 'is_active = ?',
- 1
- )->where(
- 'cbs.store_id in (?)',
- $stores
- )->order(
- 'store_id DESC'
- )->limit(
- 1
- );
+ )
+ ->where('is_active = ?', 1)
+ ->where('cbs.store_id in (?)', $stores)
+ ->order('store_id DESC')
+ ->limit(1);
}
return $select;
@@ -187,28 +157,27 @@ protected function _getLoadSelect($field, $value, $object)
*/
public function getIsUniqueBlockToStores(\Magento\Framework\Model\AbstractModel $object)
{
+ $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
+ $linkField = $entityMetadata->getLinkField();
+
if ($this->_storeManager->hasSingleStore()) {
$stores = [\Magento\Store\Model\Store::DEFAULT_STORE_ID];
} else {
$stores = (array)$object->getData('stores');
}
- $select = $this->getConnection()->select()->from(
- ['cb' => $this->getMainTable()]
- )->join(
- ['cbs' => $this->getTable('cms_block_store')],
- 'cb.block_id = cbs.block_id',
- []
- )->where(
- 'cb.identifier = ?',
- $object->getData('identifier')
- )->where(
- 'cbs.store_id IN (?)',
- $stores
- );
+ $select = $this->getConnection()->select()
+ ->from(['cb' => $this->getMainTable()])
+ ->join(
+ ['cbs' => $this->getTable('cms_block_store')],
+ 'cb.' . $linkField . ' = cbs.' . $linkField,
+ []
+ )
+ ->where('cb.identifier = ?', $object->getData('identifier'))
+ ->where('cbs.store_id IN (?)', $stores);
if ($object->getId()) {
- $select->where('cb.block_id <> ?', $object->getId());
+ $select->where('cb.' . $entityMetadata->getIdentifierField() . ' <> ?', $object->getId());
}
if ($this->getConnection()->fetchRow($select)) {
@@ -228,15 +197,59 @@ public function lookupStoreIds($id)
{
$connection = $this->getConnection();
- $select = $connection->select()->from(
- $this->getTable('cms_block_store'),
- 'store_id'
- )->where(
- 'block_id = :block_id'
- );
+ $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
+ $linkField = $entityMetadata->getLinkField();
- $binds = [':block_id' => (int)$id];
+ $select = $connection->select()
+ ->from(['cbs' => $this->getTable('cms_block_store')], 'store_id')
+ ->join(
+ ['cb' => $this->getMainTable()],
+ 'cbs.' . $linkField . ' = cb.' . $linkField,
+ []
+ )
+ ->where('cb.' . $entityMetadata->getIdentifierField() . ' = :block_id');
+
+ return $connection->fetchCol($select, ['block_id' => (int)$id]);
+ }
- return $connection->fetchCol($select, $binds);
+ /**
+ * @param \Magento\Framework\Model\AbstractModel $object
+ * @return $this
+ * @throws \Exception
+ */
+ public function save(\Magento\Framework\Model\AbstractModel $object)
+ {
+ if ($object->isDeleted()) {
+ return $this->delete($object);
+ }
+
+ $this->beginTransaction();
+
+ try {
+ if (!$this->isModified($object)) {
+ $this->processNotModifiedSave($object);
+ $this->commit();
+ $object->setHasDataChanges(false);
+ return $this;
+ }
+ $object->validateBeforeSave();
+ $object->beforeSave();
+ if ($object->isSaveAllowed()) {
+ $this->_serializeFields($object);
+ $this->_beforeSave($object);
+ $this->_checkUnique($object);
+ $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
+ $this->entityManager->save(BlockInterface::class, $object);
+ $this->unserializeFields($object);
+ $this->processAfterSaves($object);
+ }
+ $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
+ $object->setHasDataChanges(false);
+ } catch (\Exception $e) {
+ $this->rollBack();
+ $object->setHasDataChanges(true);
+ throw $e;
+ }
+ return $this;
}
}
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php b/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php
index 5d2887f20ca05..773f92fa938b8 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/Block/Collection.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Cms\Model\ResourceModel\Block;
+use Magento\Cms\Api\Data\BlockInterface;
use \Magento\Cms\Model\ResourceModel\AbstractCollection;
/**
@@ -24,7 +25,9 @@ class Collection extends AbstractCollection
*/
protected function _afterLoad()
{
- $this->performAfterLoad('cms_block_store', 'block_id');
+ $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
+
+ $this->performAfterLoad('cms_block_store', $entityMetadata->getLinkField());
return parent::_afterLoad();
}
@@ -71,6 +74,7 @@ public function addStoreFilter($store, $withAdmin = true)
*/
protected function _renderFiltersBefore()
{
- $this->joinStoreRelationTable('cms_block_store', 'block_id');
+ $entityMetadata = $this->metadataPool->getMetadata(BlockInterface::class);
+ $this->joinStoreRelationTable('cms_block_store', $entityMetadata->getLinkField());
}
}
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block/Grid/Collection.php b/app/code/Magento/Cms/Model/ResourceModel/Block/Grid/Collection.php
index e658aa86cb571..d6cc7dc45bd37 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/Block/Grid/Collection.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/Block/Grid/Collection.php
@@ -25,6 +25,7 @@ class Collection extends BlockCollection implements SearchResultInterface
* @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
+ * @param \Magento\Framework\Model\Entity\MetadataPool $metadataPool
* @param string $mainTable
* @param string $eventPrefix
* @param string $eventObject
@@ -41,6 +42,7 @@ public function __construct(
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Store\Model\StoreManagerInterface $storeManager,
+ \Magento\Framework\Model\Entity\MetadataPool $metadataPool,
$mainTable,
$eventPrefix,
$eventObject,
@@ -55,6 +57,7 @@ public function __construct(
$fetchStrategy,
$eventManager,
$storeManager,
+ $metadataPool,
$connection,
$resource
);
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block/Relation/Store/ReadHandler.php b/app/code/Magento/Cms/Model/ResourceModel/Block/Relation/Store/ReadHandler.php
new file mode 100644
index 0000000000000..32e7ccd5452b0
--- /dev/null
+++ b/app/code/Magento/Cms/Model/ResourceModel/Block/Relation/Store/ReadHandler.php
@@ -0,0 +1,51 @@
+metadataPool = $metadataPool;
+ $this->resourceBlock = $resourceBlock;
+ }
+
+ /**
+ * @param string $entityType
+ * @param object $entity
+ * @return object
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function execute($entityType, $entity)
+ {
+ if ($entity->getId()) {
+ $stores = $this->resourceBlock->lookupStoreIds((int)$entity->getId());
+ $entity->setData('store_id', $stores);
+ $entity->setData('stores', $stores);
+ }
+ return $entity;
+ }
+}
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block/Relation/Store/SaveHandler.php b/app/code/Magento/Cms/Model/ResourceModel/Block/Relation/Store/SaveHandler.php
new file mode 100644
index 0000000000000..0c5f11785dd2f
--- /dev/null
+++ b/app/code/Magento/Cms/Model/ResourceModel/Block/Relation/Store/SaveHandler.php
@@ -0,0 +1,75 @@
+metadataPool = $metadataPool;
+ $this->resourceBlock = $resourceBlock;
+ }
+
+ /**
+ * @param string $entityType
+ * @param object $entity
+ * @return object
+ */
+ public function execute($entityType, $entity)
+ {
+ $entityMetadata = $this->metadataPool->getMetadata($entityType);
+ $linkField = $entityMetadata->getLinkField();
+
+ $connection = $entityMetadata->getEntityConnection();
+
+ $oldStores = $this->resourceBlock->lookupStoreIds((int)$entity->getId());
+ $newStores = (array)$entity->getStores();
+
+ $table = $this->resourceBlock->getTable('cms_block_store');
+
+ $delete = array_diff($oldStores, $newStores);
+ if ($delete) {
+ $where = [
+ $linkField . ' = ?' => (int)$entity->getData($linkField),
+ 'store_id IN (?)' => $delete,
+ ];
+ $connection->delete($table, $where);
+ }
+
+ $insert = array_diff($newStores, $oldStores);
+ if ($insert) {
+ $data = [];
+ foreach ($insert as $storeId) {
+ $data[] = [
+ $linkField => (int)$entity->getData($linkField),
+ 'store_id' => (int)$storeId,
+ ];
+ }
+ $connection->insertMultiple($table, $data);
+ }
+
+ return $entity;
+ }
+}
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page.php b/app/code/Magento/Cms/Model/ResourceModel/Page.php
index 334e7f66f6866..0d299cd345e01 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/Page.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/Page.php
@@ -8,47 +8,75 @@
namespace Magento\Cms\Model\ResourceModel;
+use Magento\Cms\Model\Page as CmsPage;
+use Magento\Framework\DB\Select;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Model\AbstractModel;
+use Magento\Framework\Model\Entity\MetadataPool;
+use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
+use Magento\Framework\Model\ResourceModel\Db\Context;
+use Magento\Framework\Stdlib\DateTime;
+use Magento\Store\Model\Store;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\Framework\Model\EntityManager;
+use Magento\Cms\Api\Data\PageInterface;
+
/**
* Cms page mysql resource
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
-class Page extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
+class Page extends AbstractDb
{
/**
* Store model
*
- * @var null|\Magento\Store\Model\Store
+ * @var null|Store
*/
protected $_store = null;
/**
* Store manager
*
- * @var \Magento\Store\Model\StoreManagerInterface
+ * @var StoreManagerInterface
*/
protected $_storeManager;
/**
- * @var \Magento\Framework\Stdlib\DateTime
+ * @var DateTime
*/
protected $dateTime;
/**
- * Construct
- *
- * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\Framework\Stdlib\DateTime $dateTime
+ * @var EntityManager
+ */
+ protected $entityManager;
+
+ /**
+ * @var MetadataPool
+ */
+ protected $metadataPool;
+
+ /**
+ * @param Context $context
+ * @param StoreManagerInterface $storeManager
+ * @param DateTime $dateTime
+ * @param EntityManager $entityManager
+ * @param MetadataPool $metadataPool
* @param string $connectionName
*/
public function __construct(
- \Magento\Framework\Model\ResourceModel\Db\Context $context,
- \Magento\Store\Model\StoreManagerInterface $storeManager,
- \Magento\Framework\Stdlib\DateTime $dateTime,
+ Context $context,
+ StoreManagerInterface $storeManager,
+ DateTime $dateTime,
+ EntityManager $entityManager,
+ MetadataPool $metadataPool,
$connectionName = null
) {
parent::__construct($context, $connectionName);
$this->_storeManager = $storeManager;
$this->dateTime = $dateTime;
+ $this->entityManager = $entityManager;
+ $this->metadataPool = $metadataPool;
}
/**
@@ -61,29 +89,14 @@ protected function _construct()
$this->_init('cms_page', 'page_id');
}
- /**
- * Process page data before deleting
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function _beforeDelete(\Magento\Framework\Model\AbstractModel $object)
- {
- $condition = ['page_id = ?' => (int)$object->getId()];
-
- $this->getConnection()->delete($this->getTable('cms_page_store'), $condition);
-
- return parent::_beforeDelete($object);
- }
-
/**
* Process page data before saving
*
- * @param \Magento\Framework\Model\AbstractModel $object
+ * @param AbstractModel $object
* @return $this
- * @throws \Magento\Framework\Exception\LocalizedException
+ * @throws LocalizedException
*/
- protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
+ protected function _beforeSave(AbstractModel $object)
{
/*
* For two attributes which represent timestamp data in DB
@@ -97,13 +110,13 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
}
if (!$this->isValidPageIdentifier($object)) {
- throw new \Magento\Framework\Exception\LocalizedException(
+ throw new LocalizedException(
__('The page URL key contains capital letters or disallowed symbols.')
);
}
if ($this->isNumericPageIdentifier($object)) {
- throw new \Magento\Framework\Exception\LocalizedException(
+ throw new LocalizedException(
__('The page URL key cannot be made of only numbers.')
);
}
@@ -111,73 +124,39 @@ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
}
/**
- * Assign page to store views
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
- {
- $oldStores = $this->lookupStoreIds($object->getId());
- $newStores = (array)$object->getStores();
- if (empty($newStores)) {
- $newStores = (array)$object->getStoreId();
- }
- $table = $this->getTable('cms_page_store');
- $insert = array_diff($newStores, $oldStores);
- $delete = array_diff($oldStores, $newStores);
-
- if ($delete) {
- $where = ['page_id = ?' => (int)$object->getId(), 'store_id IN (?)' => $delete];
-
- $this->getConnection()->delete($table, $where);
- }
-
- if ($insert) {
- $data = [];
-
- foreach ($insert as $storeId) {
- $data[] = ['page_id' => (int)$object->getId(), 'store_id' => (int)$storeId];
- }
-
- $this->getConnection()->insertMultiple($table, $data);
- }
-
- return parent::_afterSave($object);
- }
-
- /**
- * Load an object using 'identifier' field if there's no field specified and value is not numeric
+ * Load an object
*
- * @param \Magento\Framework\Model\AbstractModel $object
+ * @param CmsPage|AbstractModel $object
* @param mixed $value
- * @param string $field
+ * @param string $field field to load by (defaults to model id)
* @return $this
*/
- public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null)
+ public function load(AbstractModel $object, $value, $field = null)
{
- if (!is_numeric($value) && is_null($field)) {
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+
+ if (!is_numeric($value) && $field === null) {
$field = 'identifier';
+ } elseif (!$field) {
+ $field = $entityMetadata->getIdentifierField();
}
- return parent::load($object, $value, $field);
- }
-
- /**
- * Perform operations after object load
- *
- * @param \Magento\Framework\Model\AbstractModel $object
- * @return $this
- */
- protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
- {
- if ($object->getId()) {
- $stores = $this->lookupStoreIds($object->getId());
-
- $object->setData('store_id', $stores);
+ $isId = true;
+ if ($field != $entityMetadata->getIdentifierField() || $object->getStoreId()) {
+ $select = $this->_getLoadSelect($field, $value, $object);
+ $select->reset(Select::COLUMNS)
+ ->columns($this->getMainTable() . '.' . $entityMetadata->getIdentifierField())
+ ->limit(1);
+ $result = $this->getConnection()->fetchCol($select);
+ $value = count($result) ? $result[0] : $value;
+ $isId = count($result);
}
- return parent::_afterLoad($object);
+ if ($isId) {
+ $this->entityManager->load(PageInterface::class, $object, $value);
+ $this->_afterLoad($object);
+ }
+ return $this;
}
/**
@@ -185,30 +164,30 @@ protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object)
*
* @param string $field
* @param mixed $value
- * @param \Magento\Cms\Model\Page $object
- * @return \Magento\Framework\DB\Select
+ * @param CmsPage|AbstractModel $object
+ * @return Select
*/
protected function _getLoadSelect($field, $value, $object)
{
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+ $linkField = $entityMetadata->getLinkField();
+
$select = parent::_getLoadSelect($field, $value, $object);
if ($object->getStoreId()) {
- $storeIds = [\Magento\Store\Model\Store::DEFAULT_STORE_ID, (int)$object->getStoreId()];
+ $storeIds = [
+ Store::DEFAULT_STORE_ID,
+ (int)$object->getStoreId(),
+ ];
$select->join(
['cms_page_store' => $this->getTable('cms_page_store')],
- $this->getMainTable() . '.page_id = cms_page_store.page_id',
+ $this->getMainTable() . '.' . $linkField . ' = cms_page_store.' . $linkField,
[]
- )->where(
- 'is_active = ?',
- 1
- )->where(
- 'cms_page_store.store_id IN (?)',
- $storeIds
- )->order(
- 'cms_page_store.store_id DESC'
- )->limit(
- 1
- );
+ )
+ ->where('is_active = ?', 1)
+ ->where('cms_page_store.store_id IN (?)', $storeIds)
+ ->order('cms_page_store.store_id DESC')
+ ->limit(1);
}
return $select;
@@ -220,23 +199,22 @@ protected function _getLoadSelect($field, $value, $object)
* @param string $identifier
* @param int|array $store
* @param int $isActive
- * @return \Magento\Framework\DB\Select
+ * @return Select
*/
protected function _getLoadByIdentifierSelect($identifier, $store, $isActive = null)
{
- $select = $this->getConnection()->select()->from(
- ['cp' => $this->getMainTable()]
- )->join(
- ['cps' => $this->getTable('cms_page_store')],
- 'cp.page_id = cps.page_id',
- []
- )->where(
- 'cp.identifier = ?',
- $identifier
- )->where(
- 'cps.store_id IN (?)',
- $store
- );
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+ $linkField = $entityMetadata->getLinkField();
+
+ $select = $this->getConnection()->select()
+ ->from(['cp' => $this->getMainTable()])
+ ->join(
+ ['cps' => $this->getTable('cms_page_store')],
+ 'cp.' . $linkField . ' = cps.' . $linkField,
+ []
+ )
+ ->where('cp.identifier = ?', $identifier)
+ ->where('cps.store_id IN (?)', $store);
if (!is_null($isActive)) {
$select->where('cp.is_active = ?', $isActive);
@@ -248,10 +226,10 @@ protected function _getLoadByIdentifierSelect($identifier, $store, $isActive = n
/**
* Check whether page identifier is numeric
*
- * @param \Magento\Framework\Model\AbstractModel $object
+ * @param AbstractModel $object
* @return bool
*/
- protected function isNumericPageIdentifier(\Magento\Framework\Model\AbstractModel $object)
+ protected function isNumericPageIdentifier(AbstractModel $object)
{
return preg_match('/^[0-9]+$/', $object->getData('identifier'));
}
@@ -259,10 +237,10 @@ protected function isNumericPageIdentifier(\Magento\Framework\Model\AbstractMode
/**
* Check whether page identifier is valid
*
- * @param \Magento\Framework\Model\AbstractModel $object
+ * @param AbstractModel $object
* @return bool
*/
- protected function isValidPageIdentifier(\Magento\Framework\Model\AbstractModel $object)
+ protected function isValidPageIdentifier(AbstractModel $object)
{
return preg_match('/^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/', $object->getData('identifier'));
}
@@ -277,9 +255,14 @@ protected function isValidPageIdentifier(\Magento\Framework\Model\AbstractModel
*/
public function checkIdentifier($identifier, $storeId)
{
- $stores = [\Magento\Store\Model\Store::DEFAULT_STORE_ID, $storeId];
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+
+ $stores = [Store::DEFAULT_STORE_ID, $storeId];
$select = $this->_getLoadByIdentifierSelect($identifier, $stores, 1);
- $select->reset(\Magento\Framework\DB\Select::COLUMNS)->columns('cp.page_id')->order('cps.store_id DESC')->limit(1);
+ $select->reset(Select::COLUMNS)
+ ->columns('cp.' . $entityMetadata->getIdentifierField())
+ ->order('cps.store_id DESC')
+ ->limit(1);
return $this->getConnection()->fetchOne($select);
}
@@ -292,13 +275,16 @@ public function checkIdentifier($identifier, $storeId)
*/
public function getCmsPageTitleByIdentifier($identifier)
{
- $stores = [\Magento\Store\Model\Store::DEFAULT_STORE_ID];
+ $stores = [Store::DEFAULT_STORE_ID];
if ($this->_store) {
$stores[] = (int)$this->getStore()->getId();
}
$select = $this->_getLoadByIdentifierSelect($identifier, $stores);
- $select->reset(\Magento\Framework\DB\Select::COLUMNS)->columns('cp.title')->order('cps.store_id DESC')->limit(1);
+ $select->reset(Select::COLUMNS)
+ ->columns('cp.title')
+ ->order('cps.store_id DESC')
+ ->limit(1);
return $this->getConnection()->fetchOne($select);
}
@@ -312,12 +298,13 @@ public function getCmsPageTitleByIdentifier($identifier)
public function getCmsPageTitleById($id)
{
$connection = $this->getConnection();
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
- $select = $connection->select()->from($this->getMainTable(), 'title')->where('page_id = :page_id');
-
- $binds = ['page_id' => (int)$id];
+ $select = $connection->select()
+ ->from($this->getMainTable(), 'title')
+ ->where($entityMetadata->getIdentifierField() . ' = :page_id');
- return $connection->fetchOne($select, $binds);
+ return $connection->fetchOne($select, ['page_id' => (int)$id]);
}
/**
@@ -329,12 +316,13 @@ public function getCmsPageTitleById($id)
public function getCmsPageIdentifierById($id)
{
$connection = $this->getConnection();
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
- $select = $connection->select()->from($this->getMainTable(), 'identifier')->where('page_id = :page_id');
+ $select = $connection->select()
+ ->from($this->getMainTable(), 'identifier')
+ ->where($entityMetadata->getIdentifierField() . ' = :page_id');
- $binds = ['page_id' => (int)$id];
-
- return $connection->fetchOne($select, $binds);
+ return $connection->fetchOne($select, ['page_id' => (int)$id]);
}
/**
@@ -347,21 +335,25 @@ public function lookupStoreIds($pageId)
{
$connection = $this->getConnection();
- $select = $connection->select()->from(
- $this->getTable('cms_page_store'),
- 'store_id'
- )->where(
- 'page_id = ?',
- (int)$pageId
- );
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+ $linkField = $entityMetadata->getLinkField();
+
+ $select = $connection->select()
+ ->from(['cps' => $this->getTable('cms_page_store')], 'store_id')
+ ->join(
+ ['cp' => $this->getMainTable()],
+ 'cps.' . $linkField . ' = cp.' . $linkField,
+ []
+ )
+ ->where('cp.' . $entityMetadata->getIdentifierField() . ' = :page_id');
- return $connection->fetchCol($select);
+ return $connection->fetchCol($select, ['page_id' => (int)$pageId]);
}
/**
* Set store model
*
- * @param \Magento\Store\Model\Store $store
+ * @param Store $store
* @return $this
*/
public function setStore($store)
@@ -373,10 +365,51 @@ public function setStore($store)
/**
* Retrieve store model
*
- * @return \Magento\Store\Model\Store
+ * @return Store
*/
public function getStore()
{
return $this->_storeManager->getStore($this->_store);
}
+
+ /**
+ * @param AbstractModel $object
+ * @return $this
+ * @throws \Exception
+ */
+ public function save(AbstractModel $object)
+ {
+ if ($object->isDeleted()) {
+ return $this->delete($object);
+ }
+
+ $this->beginTransaction();
+
+ try {
+ if (!$this->isModified($object)) {
+ $this->processNotModifiedSave($object);
+ $this->commit();
+ $object->setHasDataChanges(false);
+ return $this;
+ }
+ $object->validateBeforeSave();
+ $object->beforeSave();
+ if ($object->isSaveAllowed()) {
+ $this->_serializeFields($object);
+ $this->_beforeSave($object);
+ $this->_checkUnique($object);
+ $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
+ $this->entityManager->save(PageInterface::class, $object);
+ $this->unserializeFields($object);
+ $this->processAfterSaves($object);
+ }
+ $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
+ $object->setHasDataChanges(false);
+ } catch (\Exception $e) {
+ $this->rollBack();
+ $object->setHasDataChanges(true);
+ throw $e;
+ }
+ return $this;
+ }
}
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page/Collection.php b/app/code/Magento/Cms/Model/ResourceModel/Page/Collection.php
index 401aac2d6900d..903448203d62f 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/Page/Collection.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/Page/Collection.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Cms\Model\ResourceModel\Page;
+use Magento\Cms\Api\Data\PageInterface;
use \Magento\Cms\Model\ResourceModel\AbstractCollection;
/**
@@ -98,7 +99,8 @@ public function addStoreFilter($store, $withAdmin = true)
*/
protected function _afterLoad()
{
- $this->performAfterLoad('cms_page_store', 'page_id');
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+ $this->performAfterLoad('cms_page_store', $entityMetadata->getLinkField());
$this->_previewFlag = false;
return parent::_afterLoad();
@@ -111,6 +113,7 @@ protected function _afterLoad()
*/
protected function _renderFiltersBefore()
{
- $this->joinStoreRelationTable('cms_page_store', 'page_id');
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+ $this->joinStoreRelationTable('cms_page_store', $entityMetadata->getLinkField());
}
}
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php b/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php
index 49fbeaa47d6d8..258391615b54a 100644
--- a/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php
+++ b/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php
@@ -26,6 +26,7 @@ class Collection extends PageCollection implements SearchResultInterface
* @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
+ * @param \Magento\Framework\Model\Entity\MetadataPool $metadataPool
* @param mixed|null $mainTable
* @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $eventPrefix
* @param mixed $eventObject
@@ -33,7 +34,7 @@ class Collection extends PageCollection implements SearchResultInterface
* @param string $model
* @param null $connection
* @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb|null $resource
- *
+ *
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -42,6 +43,7 @@ public function __construct(
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Store\Model\StoreManagerInterface $storeManager,
+ \Magento\Framework\Model\Entity\MetadataPool $metadataPool,
$mainTable,
$eventPrefix,
$eventObject,
@@ -56,6 +58,7 @@ public function __construct(
$fetchStrategy,
$eventManager,
$storeManager,
+ $metadataPool,
$connection,
$resource
);
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page/Relation/Store/ReadHandler.php b/app/code/Magento/Cms/Model/ResourceModel/Page/Relation/Store/ReadHandler.php
new file mode 100644
index 0000000000000..cc3edd8a98d03
--- /dev/null
+++ b/app/code/Magento/Cms/Model/ResourceModel/Page/Relation/Store/ReadHandler.php
@@ -0,0 +1,50 @@
+metadataPool = $metadataPool;
+ $this->resourcePage = $resourcePage;
+ }
+
+ /**
+ * @param string $entityType
+ * @param object $entity
+ * @return object
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function execute($entityType, $entity)
+ {
+ if ($entity->getId()) {
+ $stores = $this->resourcePage->lookupStoreIds((int)$entity->getId());
+ $entity->setData('store_id', $stores);
+ }
+ return $entity;
+ }
+}
diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page/Relation/Store/SaveHandler.php b/app/code/Magento/Cms/Model/ResourceModel/Page/Relation/Store/SaveHandler.php
new file mode 100644
index 0000000000000..7bf832fdbc453
--- /dev/null
+++ b/app/code/Magento/Cms/Model/ResourceModel/Page/Relation/Store/SaveHandler.php
@@ -0,0 +1,78 @@
+metadataPool = $metadataPool;
+ $this->resourcePage = $resourcePage;
+ }
+
+ /**
+ * @param string $entityType
+ * @param object $entity
+ * @return object
+ */
+ public function execute($entityType, $entity)
+ {
+ $entityMetadata = $this->metadataPool->getMetadata($entityType);
+ $linkField = $entityMetadata->getLinkField();
+
+ $connection = $entityMetadata->getEntityConnection();
+
+ $oldStores = $this->resourcePage->lookupStoreIds((int)$entity->getId());
+ $newStores = (array)$entity->getStores();
+ if (empty($newStores)) {
+ $newStores = (array)$entity->getStoreId();
+ }
+
+ $table = $this->resourcePage->getTable('cms_page_store');
+
+ $delete = array_diff($oldStores, $newStores);
+ if ($delete) {
+ $where = [
+ $linkField . ' = ?' => (int)$entity->getData($linkField),
+ 'store_id IN (?)' => $delete,
+ ];
+ $connection->delete($table, $where);
+ }
+
+ $insert = array_diff($newStores, $oldStores);
+ if ($insert) {
+ $data = [];
+ foreach ($insert as $storeId) {
+ $data[] = [
+ $linkField => (int)$entity->getData($linkField),
+ 'store_id' => (int)$storeId
+ ];
+ }
+ $connection->insertMultiple($table, $data);
+ }
+
+ return $entity;
+ }
+}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Block/Relation/Store/ReadHandlerTest.php b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Block/Relation/Store/ReadHandlerTest.php
new file mode 100644
index 0000000000000..724c01bd7c23f
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Block/Relation/Store/ReadHandlerTest.php
@@ -0,0 +1,85 @@
+metadataPool = $this->getMockBuilder('Magento\Framework\Model\Entity\MetadataPool')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->resourceBlock = $this->getMockBuilder('Magento\Cms\Model\ResourceModel\Block')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->model = new ReadHandler(
+ $this->metadataPool,
+ $this->resourceBlock
+ );
+ }
+
+ public function testExecute()
+ {
+ $entityId = 1;
+ $storeId = 1;
+
+ $this->resourceBlock->expects($this->once())
+ ->method('lookupStoreIds')
+ ->willReturn([$storeId]);
+
+ $block = $this->getMockBuilder('Magento\Cms\Model\Block')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $block->expects($this->exactly(2))
+ ->method('getId')
+ ->willReturn($entityId);
+ $block->expects($this->exactly(2))
+ ->method('setData')
+ ->willReturnMap([
+ ['store_id', [$storeId], $block],
+ ['stores', [$storeId], $block],
+ ]);
+
+ $result = $this->model->execute('', $block);
+ $this->assertInstanceOf('Magento\Cms\Model\Block', $result);
+ }
+
+ public function testExecuteWithNoId()
+ {
+ $block = $this->getMockBuilder('Magento\Cms\Model\Block')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $block->expects($this->once())
+ ->method('getId')
+ ->willReturn(false);
+
+ $result = $this->model->execute('', $block);
+ $this->assertInstanceOf('Magento\Cms\Model\Block', $result);
+ }
+}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Block/Relation/Store/SaveHandlerTest.php b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Block/Relation/Store/SaveHandlerTest.php
new file mode 100644
index 0000000000000..704eed3984615
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Block/Relation/Store/SaveHandlerTest.php
@@ -0,0 +1,119 @@
+metadataPool = $this->getMockBuilder('Magento\Framework\Model\Entity\MetadataPool')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->resourceBlock = $this->getMockBuilder('Magento\Cms\Model\ResourceModel\Block')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->model = new SaveHandler(
+ $this->metadataPool,
+ $this->resourceBlock
+ );
+ }
+
+ public function testExecute()
+ {
+ $entityId = 1;
+ $linkId = 2;
+ $oldStore = 1;
+ $newStore = 2;
+ $linkField = 'link_id';
+
+ $adapter = $this->getMockBuilder('Magento\Framework\DB\Adapter\AdapterInterface')
+ ->getMockForAbstractClass();
+
+ $whereForDelete = [
+ $linkField . ' = ?' => $linkId,
+ 'store_id IN (?)' => [$oldStore],
+ ];
+ $adapter->expects($this->once())
+ ->method('delete')
+ ->with('cms_block_store', $whereForDelete)
+ ->willReturnSelf();
+
+ $whereForInsert = [
+ $linkField => $linkId,
+ 'store_id' => $newStore,
+ ];
+ $adapter->expects($this->once())
+ ->method('insertMultiple')
+ ->with('cms_block_store', [$whereForInsert])
+ ->willReturnSelf();
+
+ $entityMetadata = $this->getMockBuilder('Magento\Framework\Model\Entity\EntityMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $entityMetadata->expects($this->once())
+ ->method('getEntityConnection')
+ ->willReturn($adapter);
+ $entityMetadata->expects($this->once())
+ ->method('getLinkField')
+ ->willReturn($linkField);
+
+ $this->metadataPool->expects($this->once())
+ ->method('getMetadata')
+ ->with('Magento\Cms\Model\Block')
+ ->willReturn($entityMetadata);
+
+ $this->resourceBlock->expects($this->once())
+ ->method('lookupStoreIds')
+ ->willReturn([$oldStore]);
+ $this->resourceBlock->expects($this->once())
+ ->method('getTable')
+ ->with('cms_block_store')
+ ->willReturn('cms_block_store');
+
+ $block = $this->getMockBuilder('Magento\Cms\Model\Block')
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'getStores',
+ 'getId',
+ 'getData',
+ ])
+ ->getMock();
+ $block->expects($this->once())
+ ->method('getStores')
+ ->willReturn($newStore);
+ $block->expects($this->once())
+ ->method('getId')
+ ->willReturn($entityId);
+ $block->expects($this->exactly(2))
+ ->method('getData')
+ ->with($linkField)
+ ->willReturn($linkId);
+
+ $result = $this->model->execute('Magento\Cms\Model\Block', $block);
+ $this->assertInstanceOf('Magento\Cms\Model\Block', $result);
+ }
+}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Relation/Store/ReadHandlerTest.php b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Relation/Store/ReadHandlerTest.php
new file mode 100644
index 0000000000000..7e32e6f1c8a59
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Relation/Store/ReadHandlerTest.php
@@ -0,0 +1,83 @@
+metadataPool = $this->getMockBuilder('Magento\Framework\Model\Entity\MetadataPool')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->resourcePage = $this->getMockBuilder('Magento\Cms\Model\ResourceModel\Page')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->model = new ReadHandler(
+ $this->metadataPool,
+ $this->resourcePage
+ );
+ }
+
+ public function testExecute()
+ {
+ $entityId = 1;
+ $storeId = 1;
+
+ $this->resourcePage->expects($this->once())
+ ->method('lookupStoreIds')
+ ->willReturn([$storeId]);
+
+ $page = $this->getMockBuilder('Magento\Cms\Model\Page')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page->expects($this->exactly(2))
+ ->method('getId')
+ ->willReturn($entityId);
+ $page->expects($this->once())
+ ->method('setData')
+ ->with('store_id', [$storeId])
+ ->willReturnSelf();
+
+ $result = $this->model->execute('', $page);
+ $this->assertInstanceOf('Magento\Cms\Model\Page', $result);
+ }
+
+ public function testExecuteWithNoId()
+ {
+ $page = $this->getMockBuilder('Magento\Cms\Model\Page')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page->expects($this->once())
+ ->method('getId')
+ ->willReturn(false);
+
+ $result = $this->model->execute('', $page);
+ $this->assertInstanceOf('Magento\Cms\Model\Page', $result);
+ }
+}
diff --git a/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Relation/Store/SaveHandlerTest.php b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Relation/Store/SaveHandlerTest.php
new file mode 100644
index 0000000000000..1a7a486d2530b
--- /dev/null
+++ b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Relation/Store/SaveHandlerTest.php
@@ -0,0 +1,123 @@
+metadataPool = $this->getMockBuilder('Magento\Framework\Model\Entity\MetadataPool')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->resourcePage = $this->getMockBuilder('Magento\Cms\Model\ResourceModel\Page')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->model = new SaveHandler(
+ $this->metadataPool,
+ $this->resourcePage
+ );
+ }
+
+ public function testExecute()
+ {
+ $entityId = 1;
+ $linkId = 2;
+ $oldStore = 1;
+ $newStore = 2;
+ $linkField = 'link_id';
+
+ $adapter = $this->getMockBuilder('Magento\Framework\DB\Adapter\AdapterInterface')
+ ->getMockForAbstractClass();
+
+ $whereForDelete = [
+ $linkField . ' = ?' => $linkId,
+ 'store_id IN (?)' => [$oldStore],
+ ];
+ $adapter->expects($this->once())
+ ->method('delete')
+ ->with('cms_page_store', $whereForDelete)
+ ->willReturnSelf();
+
+ $whereForInsert = [
+ $linkField => $linkId,
+ 'store_id' => $newStore,
+ ];
+ $adapter->expects($this->once())
+ ->method('insertMultiple')
+ ->with('cms_page_store', [$whereForInsert])
+ ->willReturnSelf();
+
+ $entityMetadata = $this->getMockBuilder('Magento\Framework\Model\Entity\EntityMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $entityMetadata->expects($this->once())
+ ->method('getEntityConnection')
+ ->willReturn($adapter);
+ $entityMetadata->expects($this->once())
+ ->method('getLinkField')
+ ->willReturn($linkField);
+
+ $this->metadataPool->expects($this->once())
+ ->method('getMetadata')
+ ->with('Magento\Cms\Model\Page')
+ ->willReturn($entityMetadata);
+
+ $this->resourcePage->expects($this->once())
+ ->method('lookupStoreIds')
+ ->willReturn([$oldStore]);
+ $this->resourcePage->expects($this->once())
+ ->method('getTable')
+ ->with('cms_page_store')
+ ->willReturn('cms_page_store');
+
+ $page = $this->getMockBuilder('Magento\Cms\Model\Page')
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'getStores',
+ 'getStoreId',
+ 'getId',
+ 'getData',
+ ])
+ ->getMock();
+ $page->expects($this->once())
+ ->method('getStores')
+ ->willReturn(null);
+ $page->expects($this->once())
+ ->method('getStoreId')
+ ->willReturn($newStore);
+ $page->expects($this->once())
+ ->method('getId')
+ ->willReturn($entityId);
+ $page->expects($this->exactly(2))
+ ->method('getData')
+ ->with($linkField)
+ ->willReturn($linkId);
+
+ $result = $this->model->execute('Magento\Cms\Model\Page', $page);
+ $this->assertInstanceOf('Magento\Cms\Model\Page', $result);
+ }
+}
diff --git a/app/code/Magento/Cms/etc/di.xml b/app/code/Magento/Cms/etc/di.xml
index 0c958b7bd00f7..1a06460a00949 100644
--- a/app/code/Magento/Cms/etc/di.xml
+++ b/app/code/Magento/Cms/etc/di.xml
@@ -100,4 +100,46 @@
CmsGirdFilterPool
+
+
+
+ -
+
- cms_page
+ - page_id
+
+ -
+
- cms_block
+ - block_id
+
+
+
+
+
+
+
+ -
+
-
+
- Magento\Cms\Model\ResourceModel\Page\Relation\Store\ReadHandler
+
+ -
+
- Magento\Cms\Model\ResourceModel\Page\Relation\Store\SaveHandler
+
+ -
+
- Magento\Cms\Model\ResourceModel\Page\Relation\Store\SaveHandler
+
+
+ -
+
-
+
- Magento\Cms\Model\ResourceModel\Block\Relation\Store\ReadHandler
+
+ -
+
- Magento\Cms\Model\ResourceModel\Block\Relation\Store\SaveHandler
+
+ -
+
- Magento\Cms\Model\ResourceModel\Block\Relation\Store\SaveHandler
+
+
+
+
+
diff --git a/app/code/Magento/Config/Block/System/Config/Form/Fieldset.php b/app/code/Magento/Config/Block/System/Config/Form/Fieldset.php
index 03576bf2e9d2e..67637f80f7093 100644
--- a/app/code/Magento/Config/Block/System/Config/Form/Fieldset.php
+++ b/app/code/Magento/Config/Block/System/Config/Form/Fieldset.php
@@ -54,22 +54,35 @@ public function __construct(
* @param AbstractElement $element
* @return string
*/
- public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element)
+ public function render(AbstractElement $element)
{
$this->setElement($element);
- $html = $this->_getHeaderHtml($element);
+ $header = $this->_getHeaderHtml($element);
+ $elements = $this->_getChildrenElementsHtml($element);
+
+ $footer = $this->_getFooterHtml($element);
+
+ return $header . $elements . $footer;
+ }
+
+ /**
+ * @param AbstractElement $element
+ * @return string
+ */
+ protected function _getChildrenElementsHtml(AbstractElement $element)
+ {
+ $elements = '';
foreach ($element->getElements() as $field) {
if ($field instanceof \Magento\Framework\Data\Form\Element\Fieldset) {
- $html .= '' . $field->toHtml() . ' |
';
+ $elements .= ''
+ . '' . $field->toHtml() . ' |
';
} else {
- $html .= $field->toHtml();
+ $elements .= $field->toHtml();
}
}
- $html .= $this->_getFooterHtml($element);
-
- return $html;
+ return $elements;
}
/**
diff --git a/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php b/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php
index 689d408926d0c..ec5419771a6fd 100644
--- a/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php
+++ b/app/code/Magento/Developer/Console/Command/XmlCatalogGenerateCommand.php
@@ -12,7 +12,6 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Magento\Framework\App\Filesystem\DirectoryList;
/**
* Class XmlCatalogGenerateCommand Generates dictionary of URNs for the IDE
@@ -42,9 +41,9 @@ class XmlCatalogGenerateCommand extends Command
private $urnResolver;
/**
- * @var \Magento\Framework\Filesystem\Directory\ReadInterface
+ * @var \Magento\Framework\Filesystem\Directory\ReadFactory
*/
- private $rootDirRead;
+ private $readFactory;
/**
* Supported formats
@@ -56,19 +55,19 @@ class XmlCatalogGenerateCommand extends Command
/**
* @param \Magento\Framework\App\Utility\Files $filesUtility
* @param \Magento\Framework\Config\Dom\UrnResolver $urnResolver
- * @param \Magento\Framework\Filesystem $filesystemFactory
+ * @param \Magento\Framework\Filesystem\Directory\ReadFactory $readFactory
* @param \Magento\Developer\Model\XmlCatalog\Format\FormatInterface[] $formats
*/
public function __construct(
\Magento\Framework\App\Utility\Files $filesUtility,
\Magento\Framework\Config\Dom\UrnResolver $urnResolver,
- \Magento\Framework\Filesystem $filesystemFactory,
+ \Magento\Framework\Filesystem\Directory\ReadFactory $readFactory,
array $formats = []
) {
$this->filesUtility = $filesUtility;
$this->urnResolver = $urnResolver;
$this->formats = $formats;
- $this->rootDirRead = $filesystemFactory->getDirectoryRead(DirectoryList::ROOT);
+ $this->readFactory = $readFactory;
parent::__construct();
}
@@ -111,9 +110,10 @@ private function getUrnDictionary(OutputInterface $output)
$urns = [];
foreach ($files as $file) {
- $content = $this->rootDirRead->readFile(
- $this->rootDirRead->getRelativePath($file[0])
- );
+ $fileDir = dirname($file[0]);
+ $fileName = basename($file[0]);
+ $read = $this->readFactory->create($fileDir);
+ $content = $read->readFile($fileName);
$matches = [];
preg_match_all('/schemaLocation="(urn\:magento\:[^"]*)"/i', $content, $matches);
if (isset($matches[1])) {
diff --git a/app/code/Magento/Developer/Test/Unit/Console/Command/XmlCatalogGenerateCommandTest.php b/app/code/Magento/Developer/Test/Unit/Console/Command/XmlCatalogGenerateCommandTest.php
index c894b93af9050..10d95dc3b6aa4 100644
--- a/app/code/Magento/Developer/Test/Unit/Console/Command/XmlCatalogGenerateCommandTest.php
+++ b/app/code/Magento/Developer/Test/Unit/Console/Command/XmlCatalogGenerateCommandTest.php
@@ -42,27 +42,23 @@ public function testExecuteBadType()
)->will($this->returnValue(null));
$formats = ['phpstorm' => $phpstormFormatMock];
- $filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
+ $readFactory = $this->getMock('Magento\Framework\Filesystem\Directory\ReadFactory', [], [], '', false);
$readDirMock = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadInterface', [], [], '', false);
$content = file_get_contents($fixtureXmlFile);
- $readDirMock->expects($this->once())
- ->method('getRelativePath')
- ->with($this->equalTo($fixtureXmlFile))
- ->will($this->returnValue('test'));
$readDirMock->expects($this->once())
->method('readFile')
- ->with($this->equalTo('test'))
+ ->with($this->equalTo('test.xml'))
->will($this->returnValue($content));
- $filesystem->expects($this->once())
- ->method('getDirectoryRead')
+ $readFactory->expects($this->once())
+ ->method('create')
->will($this->returnValue($readDirMock));
$this->command = new XmlCatalogGenerateCommand(
$filesMock,
$urnResolverMock,
- $filesystem,
+ $readFactory,
$formats
);
diff --git a/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php b/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php
index 963f61633c1ac..51c07dd02d603 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php
@@ -13,7 +13,7 @@
use Magento\Framework\Model\Operation\ContextHandlerInterface;
/**
- * Class ReadHandler
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ReadHandler
{
@@ -91,43 +91,6 @@ protected function getActionContext($entityType, $data)
);
}
- /**
- * @param string $entityType
- * @param array $entityData
- * @return array
- * @throws \Exception
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function executeOldGoodImplementation($entityType, $entityData)
- {
- $data = [];
- $metadata = $this->metadataPool->getMetadata($entityType);
- /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute */
- if ($metadata->getEavEntityType()) {
- foreach ($this->getAttributes($entityType) as $attribute) {
- if (!$attribute->isStatic()) {
- $select = $metadata->getEntityConnection()->select()
- ->from($attribute->getBackend()->getTable(), ['value'])
- ->where($metadata->getLinkField() . ' = ?', $entityData[$metadata->getLinkField()])
- ->where('attribute_id = ?', $attribute->getAttributeId());
- $context = $this->getActionContext($entityType, $entityData);
- foreach ($context as $field => $value) {
- //TODO: if (in table exists context field)
- $select->where(
- $metadata->getEntityConnection()->quoteIdentifier($field) . ' IN (?)',
- $value
- )->order($field . ' DESC');
- }
- $value = $metadata->getEntityConnection()->fetchOne($select);
- if ($value !== false) {
- $data[$attribute->getAttributeCode()] = $value;
- }
- }
- }
- }
- return $data;
- }
-
/**
* @param string $entityType
* @param array $entityData
diff --git a/app/code/Magento/PageCache/Helper/Data.php b/app/code/Magento/PageCache/Helper/Data.php
index aff4d6d6a6a27..3334243148cca 100644
--- a/app/code/Magento/PageCache/Helper/Data.php
+++ b/app/code/Magento/PageCache/Helper/Data.php
@@ -20,6 +20,19 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
*/
const PRIVATE_MAX_AGE_CACHE = 31536000;
+ /**
+ * @var \Magento\Framework\Session\Config
+ */
+ protected $config;
+
+ /**
+ * @param \Magento\Framework\Session\Config $config
+ */
+ public function __construct(\Magento\Framework\Session\Config $config)
+ {
+ $this->config;
+ }
+
/**
* Retrieve url
*
@@ -31,4 +44,12 @@ public function getUrl($route, array $params = [])
{
return $this->_getUrl($route, $params);
}
+
+ /**
+ * @return string
+ */
+ public function getDomain()
+ {
+ return $this->config->getValidDomain();
+ }
}
diff --git a/app/code/Magento/Payment/Gateway/CommandExecutorInterface.php b/app/code/Magento/Payment/Gateway/CommandExecutorInterface.php
index 0ddb423924e01..98c6dd4dbaf43 100644
--- a/app/code/Magento/Payment/Gateway/CommandExecutorInterface.php
+++ b/app/code/Magento/Payment/Gateway/CommandExecutorInterface.php
@@ -7,6 +7,7 @@
/**
* Interface CommandExecutorInterface
+ * @api
*/
interface CommandExecutorInterface
{
diff --git a/app/code/Magento/Payment/Gateway/Config/Config.php b/app/code/Magento/Payment/Gateway/Config/Config.php
index 8a0035e0ddf26..8de902d878ce2 100644
--- a/app/code/Magento/Payment/Gateway/Config/Config.php
+++ b/app/code/Magento/Payment/Gateway/Config/Config.php
@@ -19,23 +19,23 @@ class Config implements ConfigInterface
private $scopeConfig;
/**
- * @var string
+ * @var string|null
*/
private $methodCode;
/**
- * @var string
+ * @var string|null
*/
private $pathPattern;
/**
* @param ScopeConfigInterface $scopeConfig
- * @param string $methodCode
+ * @param string|null $methodCode
* @param string $pathPattern
*/
public function __construct(
ScopeConfigInterface $scopeConfig,
- $methodCode = '',
+ $methodCode = null,
$pathPattern = self::DEFAULT_PATH_PATTERN
) {
$this->scopeConfig = $scopeConfig;
@@ -75,6 +75,10 @@ public function setPathPattern($pathPattern)
*/
public function getValue($field, $storeId = null)
{
+ if ($this->methodCode === null || $this->pathPattern === null) {
+ return null;
+ }
+
return $this->scopeConfig->getValue(
sprintf($this->pathPattern, $this->methodCode, $field),
ScopeInterface::SCOPE_STORE,
diff --git a/app/code/Magento/Payment/Gateway/Config/ConfigFactory.php b/app/code/Magento/Payment/Gateway/Config/ConfigFactory.php
new file mode 100644
index 0000000000000..8bbb32c274ed9
--- /dev/null
+++ b/app/code/Magento/Payment/Gateway/Config/ConfigFactory.php
@@ -0,0 +1,45 @@
+om = $om;
+ }
+
+ /**
+ * @param string|null $paymentCode
+ * @param string|null $pathPattern
+ * @return mixed
+ */
+ public function create($paymentCode = null, $pathPattern = null)
+ {
+ $arguments = [
+ 'methodCode' => $paymentCode
+ ];
+
+ if ($pathPattern !== null) {
+ $arguments['pathPattern'] = $pathPattern;
+ }
+
+ return $this->om->create(Config::class, $arguments);
+ }
+}
diff --git a/app/code/Magento/Payment/Gateway/ConfigFactoryInterface.php b/app/code/Magento/Payment/Gateway/ConfigFactoryInterface.php
new file mode 100644
index 0000000000000..0b4b26b8eb039
--- /dev/null
+++ b/app/code/Magento/Payment/Gateway/ConfigFactoryInterface.php
@@ -0,0 +1,21 @@
+ccConfig->createAsset('Magento_Payment::images/cc/' . strtolower($code) . '.png');
- $placeholder = $this->assetSource->findRelativeSourceFilePath($asset);
+ $placeholder = $this->assetSource->findSource($asset);
if ($placeholder) {
list($width, $height) = getimagesize($asset->getSourceFile());
$icons[$code] = [
diff --git a/app/code/Magento/Payment/Model/Info.php b/app/code/Magento/Payment/Model/Info.php
index 4ba972b321f11..87aac12d4fa4f 100644
--- a/app/code/Magento/Payment/Model/Info.php
+++ b/app/code/Magento/Payment/Model/Info.php
@@ -188,9 +188,12 @@ public function unsAdditionalInformation($key = null)
if ($key && isset($this->_additionalInformation[$key])) {
unset($this->_additionalInformation[$key]);
return $this->setData('additional_information', $this->_additionalInformation);
+ } elseif (null === $key) {
+ $this->_additionalInformation = [];
+ return $this->unsetData('additional_information');
}
- $this->_additionalInformation = [];
- return $this->unsetData('additional_information');
+
+ return $this;
}
/**
diff --git a/app/code/Magento/Payment/Model/Method/Adapter.php b/app/code/Magento/Payment/Model/Method/Adapter.php
index 462f4e18fba86..5c1198b7b86de 100644
--- a/app/code/Magento/Payment/Model/Method/Adapter.php
+++ b/app/code/Magento/Payment/Model/Method/Adapter.php
@@ -7,6 +7,7 @@
use Magento\Framework\DataObject;
use Magento\Payment\Model\InfoInterface;
+use Magento\Payment\Observer\AbstractDataAssignObserver;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Payment\Model\MethodInterface;
use Magento\Framework\Event\ManagerInterface;
@@ -592,12 +593,21 @@ public function assignData(\Magento\Framework\DataObject $data)
$this->eventManager->dispatch(
'payment_method_assign_data_' . $this->getCode(),
[
- 'method' => $this,
- 'data' => $data
+ AbstractDataAssignObserver::METHOD_CODE => $this,
+ AbstractDataAssignObserver::MODEL_CODE => $this->getInfoInstance(),
+ AbstractDataAssignObserver::DATA_CODE => $data
+ ]
+ );
+
+ $this->eventManager->dispatch(
+ 'payment_method_assign_data',
+ [
+ AbstractDataAssignObserver::METHOD_CODE => $this,
+ AbstractDataAssignObserver::MODEL_CODE => $this->getInfoInstance(),
+ AbstractDataAssignObserver::DATA_CODE => $data
]
);
- $this->getInfoInstance()->addData($data->getData());
return $this;
}
diff --git a/app/code/Magento/Payment/Model/MethodInterface.php b/app/code/Magento/Payment/Model/MethodInterface.php
index 3819a1e62f010..53e1d73c9c8f0 100644
--- a/app/code/Magento/Payment/Model/MethodInterface.php
+++ b/app/code/Magento/Payment/Model/MethodInterface.php
@@ -344,6 +344,7 @@ public function assignData(DataObject $data);
*
* @param CartInterface|null $quote
* @return bool
+ * @api
*/
public function isAvailable(CartInterface $quote = null);
@@ -352,6 +353,7 @@ public function isAvailable(CartInterface $quote = null);
*
* @param int|null $storeId
* @return bool
+ * @api
*/
public function isActive($storeId = null);
@@ -365,7 +367,6 @@ public function isActive($storeId = null);
* @return $this
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @api
- * @deprecated
*/
public function initialize($paymentAction, $stateObject);
diff --git a/app/code/Magento/Payment/Observer/AbstractDataAssignObserver.php b/app/code/Magento/Payment/Observer/AbstractDataAssignObserver.php
index 930dfc702ad2f..dcccce5680e54 100644
--- a/app/code/Magento/Payment/Observer/AbstractDataAssignObserver.php
+++ b/app/code/Magento/Payment/Observer/AbstractDataAssignObserver.php
@@ -8,14 +8,22 @@
use Magento\Framework\DataObject;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
+use Magento\Payment\Model\InfoInterface;
use Magento\Payment\Model\MethodInterface;
+/**
+ * Class AbstractDataAssignObserver
+ * @package Magento\Payment\Observer
+ * @api
+ */
abstract class AbstractDataAssignObserver implements ObserverInterface
{
const METHOD_CODE = 'method';
const DATA_CODE = 'data';
+ const MODEL_CODE = 'payment_model';
+
/**
* Reads method argument
*
@@ -27,6 +35,17 @@ protected function readMethodArgument(Observer $observer)
return $this->readArgument($observer, static::METHOD_CODE, MethodInterface::class);
}
+ /**
+ * Reads payment model argument
+ *
+ * @param Observer $observer
+ * @return InfoInterface
+ */
+ protected function readPaymentModelArgument(Observer $observer)
+ {
+ return $this->readArgument($observer, static::MODEL_CODE, InfoInterface::class);
+ }
+
/**
* Reads data argument
*
diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Request/BuilderCompositeTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Request/BuilderCompositeTest.php
index 2c31c318db678..3655bbb35fa79 100644
--- a/app/code/Magento/Payment/Test/Unit/Gateway/Request/BuilderCompositeTest.php
+++ b/app/code/Magento/Payment/Test/Unit/Gateway/Request/BuilderCompositeTest.php
@@ -37,18 +37,13 @@ public function testBuildEmpty()
static::assertEquals([], $builder->build([]));
}
- public function testBuild()
+ /**
+ * @param array $expected
+ * @covers \Magento\Payment\Gateway\Request\BuilderComposite::build
+ * @dataProvider buildDataProvider
+ */
+ public function testBuild(array $expected)
{
- $expectedRequest = [
- 'user' => 'Mrs G. Crump',
- 'url' => 'https://url.in',
- 'amount' => 10.00,
- 'currency' => 'pound',
- 'address' => '46 Egernon Crescent',
- 'item' => 'gas cooker',
- 'quantity' => 1
- ];
-
$tMapFactory = $this->getMockBuilder('Magento\Framework\ObjectManager\TMapFactory')
->disableOriginalConstructor()
->setMethods(['create'])
@@ -67,25 +62,27 @@ public function testBuild()
->method('build')
->willReturn(
[
- 'user' => 'Mrs G. Crump',
- 'address' => '46 Egernon Crescent'
+ 'user' => $expected['user'],
+ 'address' => $expected['address']
]
);
$productBuilder->expects(static::once())
->method('build')
->willReturn(
[
- 'amount' => 10.00,
- 'currency' => 'pound',
- 'item' => 'gas cooker',
- 'quantity' => 1
+ 'amount' => $expected['amount'],
+ 'currency' => $expected['currency'],
+ 'item' => $expected['item'],
+ 'quantity' => $expected['quantity'],
+ 'options' => ['product' => $expected['options']['product']]
]
);
$magentoBuilder->expects(static::once())
->method('build')
->willReturn(
[
- 'url' => 'https://url.in'
+ 'url' => $expected['url'],
+ 'options' => ['magento' => $expected['options']['magento']]
]
);
@@ -115,6 +112,45 @@ public function testBuild()
]
);
- static::assertEquals($expectedRequest, $builder->build([]));
+ static::assertEquals($expected, $builder->build([]));
+ }
+
+ /**
+ * Get list of variations
+ */
+ public function buildDataProvider()
+ {
+ return [
+ [[
+ 'user' => 'Mrs G. Crump',
+ 'address' => '46 Egernon Crescent',
+ 'amount' => 10.00,
+ 'currency' => 'pound',
+ 'item' => 'gas cooker',
+ 'quantity' => 1,
+ 'options' => ['product' => '', 'magento' => 'magento'],
+ 'url' => 'https://url.in',
+ ]],
+ [[
+ 'user' => 'John Doe',
+ 'address' => '46 Main Street',
+ 'amount' => 250.00,
+ 'currency' => 'usd',
+ 'item' => 'phone',
+ 'quantity' => 2,
+ 'options' => ['product' => 'product', 'magento' => 'magento'],
+ 'url' => 'https://url.io',
+ ]],
+ [[
+ 'user' => 'John Smit',
+ 'address' => '46 Egernon Crescent',
+ 'amount' => 1100.00,
+ 'currency' => 'usd',
+ 'item' => 'notebook',
+ 'quantity' => 1,
+ 'options' => ['product' => ['discount' => ['price' => 2.00]], 'magento' => 'magento'],
+ 'url' => 'http://url.ua',
+ ]],
+ ];
}
}
diff --git a/app/code/Magento/Payment/Test/Unit/Model/CcConfigProviderTest.php b/app/code/Magento/Payment/Test/Unit/Model/CcConfigProviderTest.php
index 217ac20644e7e..233764c5316b8 100644
--- a/app/code/Magento/Payment/Test/Unit/Model/CcConfigProviderTest.php
+++ b/app/code/Magento/Payment/Test/Unit/Model/CcConfigProviderTest.php
@@ -77,7 +77,7 @@ public function testGetConfig()
[$ccAvailableTypesMock['ae']['fileId']]
)->willReturn($assetMock);
$this->assetSourceMock->expects($this->atLeastOnce())
- ->method('findRelativeSourceFilePath')
+ ->method('findSource')
->with($assetMock)
->willReturnOnConsecutiveCalls(
$ccAvailableTypesMock['vi']['path'],
diff --git a/app/code/Magento/Payment/etc/di.xml b/app/code/Magento/Payment/etc/di.xml
index 2d5be54204f42..b7b20ac1e4349 100644
--- a/app/code/Magento/Payment/etc/di.xml
+++ b/app/code/Magento/Payment/etc/di.xml
@@ -6,6 +6,9 @@
*/
-->
+
+
+
payment.xml
@@ -24,7 +27,6 @@
Magento\Payment\Model\Config\Data
-
Magento\Payment\Gateway\Config\Config
diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php
index 6f20d380b723d..2cd04398ecc86 100644
--- a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php
+++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php
@@ -52,9 +52,22 @@ protected function _getElementHtml(\Magento\Framework\Data\Form\Element\Abstract
$originalData = $element->getOriginalData();
$this->addData(
[
+ // Global
+ 'query' => $this->createQuery(
+ [
+ 'partnerId' => $originalData['partner_id'],
+ 'partnerLogoUrl' => $this->_assetRepo->getUrl($originalData['partner_logo_url']),
+ 'receiveCredentials' => $originalData['receive_credentials'],
+ 'showPermissions' => $originalData['show_permissions'],
+ 'displayMode' => $originalData['display_mode'],
+ 'productIntentID' => $originalData['product_intent_id'],
+ ]
+ ),
+ // Live
'button_label' => __($originalData['button_label']),
'button_url' => $originalData['button_url'],
'html_id' => $element->getHtmlId(),
+ // Sandbox
'sandbox_button_label' => __($originalData['sandbox_button_label']),
'sandbox_button_url' => $originalData['sandbox_button_url'],
'sandbox_html_id' => 'sandbox_' . $element->getHtmlId(),
@@ -62,4 +75,21 @@ protected function _getElementHtml(\Magento\Framework\Data\Form\Element\Abstract
);
return $this->_toHtml();
}
+
+ /**
+ * Create request query
+ *
+ * @param array $requestData
+ * @return string
+ */
+ private function createQuery(array $requestData)
+ {
+ $query = [];
+
+ foreach ($requestData as $name => $value) {
+ $query[] = sprintf('%s=%s', $name, $value);
+ }
+
+ return implode('&', $query);
+ }
}
diff --git a/app/code/Magento/Paypal/Model/Api/AbstractApi.php b/app/code/Magento/Paypal/Model/Api/AbstractApi.php
index d5a7298b886b3..590854023a136 100644
--- a/app/code/Magento/Paypal/Model/Api/AbstractApi.php
+++ b/app/code/Magento/Paypal/Model/Api/AbstractApi.php
@@ -5,8 +5,8 @@
*/
namespace Magento\Paypal\Model\Api;
+use Magento\Payment\Helper\Formatter;
use Magento\Payment\Model\Method\Logger;
-use Magento\Paypal\Helper\Formatter;
/**
* Abstract class for Paypal API wrappers
diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php
index 697b66ef7c823..cc90c97921ea1 100644
--- a/app/code/Magento/Paypal/Model/Config.php
+++ b/app/code/Magento/Paypal/Model/Config.php
@@ -8,7 +8,7 @@
namespace Magento\Paypal\Model;
-use Magento\Paypal\Helper\Formatter;
+use Magento\Payment\Helper\Formatter;
/**
* Config model that is aware of all \Magento\Paypal payment methods
diff --git a/app/code/Magento/Paypal/Model/Hostedpro/Request.php b/app/code/Magento/Paypal/Model/Hostedpro/Request.php
index ba009c1416e74..7cbacff0c7659 100644
--- a/app/code/Magento/Paypal/Model/Hostedpro/Request.php
+++ b/app/code/Magento/Paypal/Model/Hostedpro/Request.php
@@ -8,10 +8,10 @@
use Magento\Customer\Helper\Address;
use Magento\Framework\DataObject;
use Magento\Framework\Locale\Resolver;
+use Magento\Payment\Helper\Formatter;
use Magento\Paypal\Model\Hostedpro;
use Magento\Sales\Model\Order;
use Magento\Tax\Helper\Data;
-use Magento\Paypal\Helper\Formatter;
/**
* Website Payments Pro Hosted Solution request model to get token.
diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml
index b95f686a3db73..31cbe04f0b1ca 100644
--- a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml
+++ b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml
@@ -66,16 +66,31 @@
- Get Credentials from PayPal
-
-
-
+
+ Get Credentials from PayPal
+
+
+
+
Sandbox Credentials
-
+
+
+
+ NB9WWHYEMVUMS
+
+ Magento_Backend/web/images/logo-magento.png
+
+ FALSE
+
+ FALSE
+
+ embedded
+
+ pp_express
+
Magento\Paypal\Block\Adminhtml\System\Config\ApiWizard
-
1
diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/api_wizard.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/api_wizard.phtml
index 3f729e92cbf74..1ee532657b06f 100644
--- a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/api_wizard.phtml
+++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/api_wizard.phtml
@@ -10,22 +10,27 @@
*/
?>
diff --git a/app/code/Magento/Rule/Model/AbstractModel.php b/app/code/Magento/Rule/Model/AbstractModel.php
index 07bc7957bfbf8..6f2ca4f045fb8 100644
--- a/app/code/Magento/Rule/Model/AbstractModel.php
+++ b/app/code/Magento/Rule/Model/AbstractModel.php
@@ -4,12 +4,13 @@
* See COPYING.txt for license details.
*/
+namespace Magento\Rule\Model;
+
/**
* Abstract Rule entity data model
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
-namespace Magento\Rule\Model;
-
-abstract class AbstractModel extends \Magento\Framework\Model\AbstractModel
+abstract class AbstractModel extends \Magento\Framework\Model\AbstractExtensibleModel
{
/**
* Store rule combine conditions model
@@ -75,19 +76,23 @@ abstract public function getActionsInstance();
protected $_localeDate;
/**
- * Constructor
+ * AbstractModel constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
+ * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
+ * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
- * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
- * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
+ * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
+ * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
* @param array $data
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
+ \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
+ \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
@@ -96,7 +101,15 @@ public function __construct(
) {
$this->_formFactory = $formFactory;
$this->_localeDate = $localeDate;
- parent::__construct($context, $registry, $resource, $resourceCollection, $data);
+ parent::__construct(
+ $context,
+ $registry,
+ $extensionFactory,
+ $customAttributeFactory,
+ $resource,
+ $resourceCollection,
+ $data
+ );
}
/**
@@ -118,13 +131,13 @@ public function beforeSave()
// Serialize conditions
if ($this->getConditions()) {
$this->setConditionsSerialized(serialize($this->getConditions()->asArray()));
- $this->unsConditions();
+ $this->_conditions = null;
}
// Serialize actions
if ($this->getActions()) {
$this->setActionsSerialized(serialize($this->getActions()->asArray()));
- $this->unsActions();
+ $this->_actions = null;
}
/**
diff --git a/app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php b/app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php
index 0655ddb25a975..0e92eb3ffe60b 100644
--- a/app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php
+++ b/app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php
@@ -43,14 +43,14 @@ abstract class AbstractResource extends \Magento\Framework\Model\ResourceModel\D
*/
public function _beforeSave(\Magento\Framework\Model\AbstractModel $object)
{
- $fromDate = $object->getFromDate();
+ $fromDate = $object->getData('from_date');
if ($fromDate instanceof \DateTime) {
$object->setFromDate($fromDate->format('Y-m-d H:i:s'));
} elseif (!is_string($fromDate) || empty($fromDate)) {
$object->setFromDate(null);
}
- $toDate = $object->getToDate();
+ $toDate = $object->getData('to_date');
if ($toDate instanceof \DateTime) {
$object->setToDate($toDate->format('Y-m-d H:i:s'));
} elseif (!is_string($toDate) || empty($toDate)) {
diff --git a/app/code/Magento/Sales/Api/Data/TransactionInterface.php b/app/code/Magento/Sales/Api/Data/TransactionInterface.php
index 1e0de41ea000d..1f2eb75645d0e 100644
--- a/app/code/Magento/Sales/Api/Data/TransactionInterface.php
+++ b/app/code/Magento/Sales/Api/Data/TransactionInterface.php
@@ -13,6 +13,24 @@
*/
interface TransactionInterface extends \Magento\Framework\Api\ExtensibleDataInterface
{
+ /**#@+
+ * Supported transaction types
+ * @var string
+ */
+ const TYPE_PAYMENT = 'payment';
+
+ const TYPE_ORDER = 'order';
+
+ const TYPE_AUTH = 'authorization';
+
+ const TYPE_CAPTURE = 'capture';
+
+ const TYPE_VOID = 'void';
+
+ const TYPE_REFUND = 'refund';
+
+ /**#@-*/
+
/**#@+
* Constants for keys of data array. Identical to the name of the getter in snake case.
*/
diff --git a/app/code/Magento/Sales/Model/Order/Payment/Info.php b/app/code/Magento/Sales/Model/Order/Payment/Info.php
index 0abf5b513b82f..83f75d29e3c7c 100644
--- a/app/code/Magento/Sales/Model/Order/Payment/Info.php
+++ b/app/code/Magento/Sales/Model/Order/Payment/Info.php
@@ -193,9 +193,12 @@ public function unsAdditionalInformation($key = null)
if ($key && isset($this->additionalInformation[$key])) {
unset($this->additionalInformation[$key]);
return $this->setData('additional_information', $this->additionalInformation);
+ } elseif (null === $key) {
+ $this->additionalInformation = [];
+ return $this->unsetData('additional_information');
}
- $this->additionalInformation = [];
- return $this->unsetData('additional_information');
+
+ return $this;
}
/**
diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php
index 91269d66fbd98..37819329e8dd2 100644
--- a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php
+++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php
@@ -26,24 +26,6 @@
*/
class Transaction extends AbstractModel implements TransactionInterface
{
- /**#@+
- * Supported transaction types
- * @var string
- */
- const TYPE_PAYMENT = 'payment';
-
- const TYPE_ORDER = 'order';
-
- const TYPE_AUTH = 'authorization';
-
- const TYPE_CAPTURE = 'capture';
-
- const TYPE_VOID = 'void';
-
- const TYPE_REFUND = 'refund';
-
- /**#@-*/
-
/**
* Raw details key in additional info
*/
diff --git a/app/code/Magento/SalesRule/Model/Rule.php b/app/code/Magento/SalesRule/Model/Rule.php
index 4ecc75f77dd89..b6c23fc4cb2a5 100644
--- a/app/code/Magento/SalesRule/Model/Rule.php
+++ b/app/code/Magento/SalesRule/Model/Rule.php
@@ -175,22 +175,26 @@ class Rule extends \Magento\Rule\Model\AbstractModel
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
+ * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
+ * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
- * @param \Magento\SalesRule\Model\CouponFactory $couponFactory
- * @param \Magento\SalesRule\Model\Coupon\CodegeneratorFactory $codegenFactory
- * @param \Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory
- * @param \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF
- * @param \Magento\SalesRule\Model\ResourceModel\Coupon\Collection $couponCollection
+ * @param CouponFactory $couponFactory
+ * @param Coupon\CodegeneratorFactory $codegenFactory
+ * @param Rule\Condition\CombineFactory $condCombineFactory
+ * @param Rule\Condition\Product\CombineFactory $condProdCombineF
+ * @param ResourceModel\Coupon\Collection $couponCollection
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
- * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
+ * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
+ * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
* @param array $data
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
+ \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
+ \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\SalesRule\Model\CouponFactory $couponFactory,
@@ -209,7 +213,17 @@ public function __construct(
$this->_condProdCombineF = $condProdCombineF;
$this->_couponCollection = $couponCollection;
$this->_storeManager = $storeManager;
- parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
+ parent::__construct(
+ $context,
+ $registry,
+ $extensionFactory,
+ $customAttributeFactory,
+ $formFactory,
+ $localeDate,
+ $resource,
+ $resourceCollection,
+ $data
+ );
}
/**
diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php b/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php
index 5293d31d42a06..65243ee594e6e 100644
--- a/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php
+++ b/app/code/Magento/SalesRule/Test/Unit/Model/RuleTest.php
@@ -18,6 +18,16 @@ class RuleTest extends \PHPUnit_Framework_TestCase
*/
protected $coupon;
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\SalesRule\Model\Rule\Condition\CombineFactory
+ */
+ protected $conditionCombineFactoryMock;
+
+ /**
+ * @var \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $condProdCombineFactoryMock;
+
public function setUp()
{
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
@@ -35,10 +45,22 @@ public function setUp()
->method('create')
->willReturn($this->coupon);
+ $this->conditionCombineFactoryMock = $this->getMockBuilder(
+ '\Magento\SalesRule\Model\Rule\Condition\CombineFactory'
+ )->disableOriginalConstructor()
+ ->getMock();
+
+ $this->condProdCombineFactoryMock = $this->getMockBuilder(
+ '\Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory'
+ )->disableOriginalConstructor()
+ ->getMock();
+
$this->model = $objectManager->getObject(
'Magento\SalesRule\Model\Rule',
[
- 'couponFactory' => $couponFactory
+ 'couponFactory' => $couponFactory,
+ 'condCombineFactory' => $this->conditionCombineFactoryMock,
+ 'condProdCombineF' => $this->condProdCombineFactoryMock,
]
);
}
@@ -70,4 +92,62 @@ public function testLoadCouponCode()
$this->model->loadCouponCode();
$this->assertEquals(1, $this->model->getUsesPerCoupon());
}
+
+ public function testBeforeSaveResetConditionToNull()
+ {
+ $conditionMock = $this->setupConditionMock();
+
+ //Make sure that we reset _condition in beforeSave method
+ $this->conditionCombineFactoryMock->expects($this->exactly(2))
+ ->method('create')
+ ->willReturn($conditionMock);
+
+ $prodConditionMock = $this->setupProdConditionMock();
+ $this->condProdCombineFactoryMock->expects($this->exactly(2))
+ ->method('create')
+ ->willReturn($prodConditionMock);
+
+ $this->model->beforeSave();
+ $this->model->getConditions();
+ $this->model->getActions();
+ }
+
+ protected function setupProdConditionMock()
+ {
+ $prodConditionMock = $this->getMockBuilder('\Magento\SalesRule\Model\Rule\Condition\Product\Combine')
+ ->disableOriginalConstructor()
+ ->setMethods(['setRule', 'setId', 'loadArray', 'getConditions'])
+ ->getMock();
+
+ $prodConditionMock->expects($this->any())
+ ->method('setRule')
+ ->willReturnSelf();
+ $prodConditionMock->expects($this->any())
+ ->method('setId')
+ ->willReturnSelf();
+ $prodConditionMock->expects($this->any())
+ ->method('getConditions')
+ ->willReturn([]);
+
+ return $prodConditionMock;
+ }
+
+ protected function setupConditionMock()
+ {
+ $conditionMock = $this->getMockBuilder('\Magento\SalesRule\Model\Rule\Condition\Combine')
+ ->disableOriginalConstructor()
+ ->setMethods(['setRule', 'setId', 'loadArray', 'getConditions'])
+ ->getMock();
+ $conditionMock->expects($this->any())
+ ->method('setRule')
+ ->willReturnSelf();
+ $conditionMock->expects($this->any())
+ ->method('setId')
+ ->willReturnSelf();
+ $conditionMock->expects($this->any())
+ ->method('getConditions')
+ ->willReturn([]);
+
+ return $conditionMock;
+ }
}
diff --git a/app/code/Magento/Sitemap/Model/ResourceModel/Cms/Page.php b/app/code/Magento/Sitemap/Model/ResourceModel/Cms/Page.php
index 07640bb6a7f2e..0baf5374fbfd5 100644
--- a/app/code/Magento/Sitemap/Model/ResourceModel/Cms/Page.php
+++ b/app/code/Magento/Sitemap/Model/ResourceModel/Cms/Page.php
@@ -5,6 +5,10 @@
*/
namespace Magento\Sitemap\Model\ResourceModel\Cms;
+use Magento\Cms\Api\Data\PageInterface;
+use Magento\Framework\Model\Entity\MetadataPool;
+use Magento\Framework\Model\ResourceModel\Db\Context;
+
/**
* Sitemap cms page collection model
*
@@ -12,6 +16,25 @@
*/
class Page extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
+ /**
+ * @var MetadataPool
+ */
+ protected $metadataPool;
+
+ /**
+ * @param Context $context
+ * @param MetadataPool $metadataPool
+ * @param string $connectionName
+ */
+ public function __construct(
+ Context $context,
+ MetadataPool $metadataPool,
+ $connectionName = null
+ ) {
+ $this->metadataPool = $metadataPool;
+ parent::__construct($context, $connectionName);
+ }
+
/**
* Init resource model (catalog/category)
*
@@ -30,14 +53,15 @@ protected function _construct()
*/
public function getCollection($storeId)
{
- $pages = [];
+ $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
+ $linkField = $entityMetadata->getLinkField();
$select = $this->getConnection()->select()->from(
['main_table' => $this->getMainTable()],
[$this->getIdFieldName(), 'url' => 'identifier', 'updated_at' => 'update_time']
)->join(
['store_table' => $this->getTable('cms_page_store')],
- 'main_table.page_id = store_table.page_id',
+ "main_table.{$linkField} = store_table.$linkField",
[]
)->where(
'main_table.is_active = 1'
@@ -49,6 +73,7 @@ public function getCollection($storeId)
[0, $storeId]
);
+ $pages = [];
$query = $this->getConnection()->query($select);
while ($row = $query->fetch()) {
$page = $this->_prepareObject($row);
diff --git a/app/code/Magento/Vault/Api/Data/PaymentTokenInterface.php b/app/code/Magento/Vault/Api/Data/PaymentTokenInterface.php
index e42aee5094645..acb372a4e3725 100644
--- a/app/code/Magento/Vault/Api/Data/PaymentTokenInterface.php
+++ b/app/code/Magento/Vault/Api/Data/PaymentTokenInterface.php
@@ -10,7 +10,7 @@
*
* @api
*/
-interface PaymentTokenInterface extends \Magento\Framework\Api\ExtensibleDataInterface
+interface PaymentTokenInterface
{
/**#@+
* Constants for keys of data array. Identical to the name of the getter in snake case.
@@ -55,6 +55,10 @@ interface PaymentTokenInterface extends \Magento\Framework\Api\ExtensibleDataInt
* Is vault payment record active.
*/
const IS_ACTIVE = 'is_active';
+ /*
+ * Is vault payment token visible.
+ */
+ const IS_VISIBLE = 'is_visible';
/**
* Gets the entity ID.
@@ -208,17 +212,18 @@ public function getIsActive();
public function setIsActive($isActive);
/**
- * Retrieve existing extension attributes object or create a new one.
+ * Gets is vault payment record visible.
*
- * @return \Magento\Vault\Api\Data\PaymentTokenExtensionInterface|null
+ * @return bool Is visible.
+ * @SuppressWarnings(PHPMD.BooleanGetMethodName)
*/
- public function getExtensionAttributes();
+ public function getIsVisible();
/**
- * Set an extension attributes object.
+ * Sets is vault payment record visible.
*
- * @param \Magento\Vault\Api\Data\PaymentTokenExtensionInterface $extensionAttributes
+ * @param bool $isVisible
* @return $this
*/
- public function setExtensionAttributes(PaymentTokenExtensionInterface $extensionAttributes);
+ public function setIsVisible($isVisible);
}
diff --git a/app/code/Magento/Vault/Api/PaymentTokenManagementInterface.php b/app/code/Magento/Vault/Api/PaymentTokenManagementInterface.php
index 684d792401f2a..e80a7f4b834db 100644
--- a/app/code/Magento/Vault/Api/PaymentTokenManagementInterface.php
+++ b/app/code/Magento/Vault/Api/PaymentTokenManagementInterface.php
@@ -5,7 +5,7 @@
*/
namespace Magento\Vault\Api;
-use Magento\Sales\Model\Order\Payment;
+use Magento\Sales\Api\Data\OrderPaymentInterface;
use Magento\Vault\Api\Data\PaymentTokenInterface;
/**
@@ -32,18 +32,28 @@ public function getListByCustomerId($customerId);
public function getByPaymentId($paymentId);
/**
- * Get payment token by gateway token Id.
+ * Get payment token by gateway token.
*
- * @param int $customerId Customer ID.
* @param string $token The gateway token.
- * @return \Magento\Vault\Api\Data\PaymentTokenInterface Payment token interface.
+ * @param string $paymentMethodCode
+ * @param int $customerId Customer ID.
+ * @return PaymentTokenInterface|null Payment token interface.
+ */
+ public function getByGatewayToken($token, $paymentMethodCode, $customerId);
+
+ /**
+ * Get payment token by public hash.
+ *
+ * @param string $hash Public hash.
+ * @param int $customerId Customer ID.
+ * @return PaymentTokenInterface|null Payment token interface.
*/
- public function getByGatewayToken($customerId, $token);
+ public function getByPublicHash($hash, $customerId);
/**
* @param PaymentTokenInterface $token
- * @param Payment $payment
+ * @param OrderPaymentInterface $payment
* @return bool
*/
- public function saveTokenWithPaymentLink(PaymentTokenInterface $token, Payment $payment);
+ public function saveTokenWithPaymentLink(PaymentTokenInterface $token, OrderPaymentInterface $payment);
}
diff --git a/app/code/Magento/Vault/Block/System/Config/EmptyFieldsetDecorator.php b/app/code/Magento/Vault/Block/System/Config/EmptyFieldsetDecorator.php
new file mode 100644
index 0000000000000..fb45da905c322
--- /dev/null
+++ b/app/code/Magento/Vault/Block/System/Config/EmptyFieldsetDecorator.php
@@ -0,0 +1,26 @@
+_getChildrenElementsHtml($element);
+ if (empty($childrenHtml)) {
+ return '';
+ }
+
+ return parent::render($element);
+ }
+}
diff --git a/app/code/Magento/Vault/Block/System/Config/EmptySelectDecorator.php b/app/code/Magento/Vault/Block/System/Config/EmptySelectDecorator.php
new file mode 100644
index 0000000000000..f2bc2604dcc1a
--- /dev/null
+++ b/app/code/Magento/Vault/Block/System/Config/EmptySelectDecorator.php
@@ -0,0 +1,29 @@
+getData('values'))) {
+ return '';
+ }
+
+ return parent::render($element);
+ }
+}
diff --git a/app/code/Magento/Vault/Gateway/Config/ActiveHandler.php b/app/code/Magento/Vault/Gateway/Config/ActiveHandler.php
index 84ab987a09f0d..ae98ee3556814 100644
--- a/app/code/Magento/Vault/Gateway/Config/ActiveHandler.php
+++ b/app/code/Magento/Vault/Gateway/Config/ActiveHandler.php
@@ -6,7 +6,7 @@
namespace Magento\Vault\Gateway\Config;
use Magento\Payment\Gateway\ConfigInterface;
-use Magento\Vault\Model\Adminhtml\Source\VaultPayment;
+use Magento\Vault\Model\Adminhtml\Source\VaultProvidersMap;
use Magento\Payment\Gateway\Config\ValueHandlerInterface;
/**
@@ -32,10 +32,10 @@ public function __construct(ConfigInterface $config)
*/
public function handle(array $subject, $storeId = null)
{
- $vaultPaymentCode = $this->config->getValue(VaultPayment::VALUE_CODE, $storeId);
+ $vaultPaymentCode = $this->config->getValue(VaultProvidersMap::VALUE_CODE, $storeId);
return (int) ((int)$this->config->getValue('active', $storeId) === 1
&& $vaultPaymentCode
- && $vaultPaymentCode !== VaultPayment::EMPTY_VALUE);
+ && $vaultPaymentCode !== VaultProvidersMap::EMPTY_VALUE);
}
}
diff --git a/app/code/Magento/Vault/Model/Adminhtml/Source/VaultPayment.php b/app/code/Magento/Vault/Model/Adminhtml/Source/VaultPayment.php
deleted file mode 100644
index 0c3cc362ad433..0000000000000
--- a/app/code/Magento/Vault/Model/Adminhtml/Source/VaultPayment.php
+++ /dev/null
@@ -1,49 +0,0 @@
-options = array_merge(
- $options,
- [
- 'value' => self::EMPTY_VALUE,
- 'label' => __('Select a payment solution')
- ]
- );
- }
-
- /**
- * Return array of options as value-label pairs
- *
- * @return array Format: array(array('value' => '', 'label' => '
diff --git a/app/code/Magento/Vault/etc/frontend/di.xml b/app/code/Magento/Vault/etc/frontend/di.xml
index 4fad674cc8900..b9c48ad37bb4c 100644
--- a/app/code/Magento/Vault/etc/frontend/di.xml
+++ b/app/code/Magento/Vault/etc/frontend/di.xml
@@ -9,7 +9,8 @@
- - Magento\Vault\Model\Ui\ConfigProvider
+ - Magento\Vault\Model\Ui\VaultConfigProvider
+ - Magento\Vault\Model\Ui\TokensConfigProvider
diff --git a/app/code/Magento/Vault/etc/module.xml b/app/code/Magento/Vault/etc/module.xml
index cfc1e5735fef4..43d1d4dbbcb4f 100644
--- a/app/code/Magento/Vault/etc/module.xml
+++ b/app/code/Magento/Vault/etc/module.xml
@@ -9,8 +9,10 @@
+
+
diff --git a/app/code/Magento/Vault/view/frontend/web/js/view/payment/method-renderer/vault.js b/app/code/Magento/Vault/view/frontend/web/js/view/payment/method-renderer/vault.js
index c9652c06e0834..1b6259822fb33 100644
--- a/app/code/Magento/Vault/view/frontend/web/js/view/payment/method-renderer/vault.js
+++ b/app/code/Magento/Vault/view/frontend/web/js/view/payment/method-renderer/vault.js
@@ -15,8 +15,7 @@ define(
return Component.extend({
defaults: {
- template: 'Magento_Vault/payment/form',
- transactionResult: ''
+ template: 'Magento_Vault/payment/form'
},
/**
diff --git a/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault-enabler.js b/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault-enabler.js
new file mode 100644
index 0000000000000..1b8b68106bf67
--- /dev/null
+++ b/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault-enabler.js
@@ -0,0 +1,60 @@
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+/*browser:true*/
+/*global define*/
+define(
+ [
+ 'uiElement'
+ ],
+ function (
+ Component
+ ) {
+ 'use strict';
+
+ return Component.extend({
+ defaults: {
+ isActivePaymentTokenEnabler: true
+ },
+
+ /**
+ * @param {String} paymentCode
+ */
+ setPaymentCode: function (paymentCode) {
+ this.paymentCode = paymentCode;
+ },
+
+ /**
+ * @returns {Object}
+ */
+ initObservable: function () {
+ this._super()
+ .observe([
+ 'isActivePaymentTokenEnabler'
+ ]);
+
+ return this;
+ },
+
+ /**
+ * @param {Object} data
+ */
+ visitAdditionalData: function (data) {
+ if (!this.isVaultEnabled()) {
+ return;
+ }
+
+ data['additional_data']['is_active_payment_token_enabler'] = this.isActivePaymentTokenEnabler();
+ },
+
+ /**
+ * @returns {Boolean}
+ */
+ isVaultEnabled: function () {
+ return window.checkoutConfig.vault['is_enabled'] === true &&
+ window.checkoutConfig.vault['vault_provider_code'] === this.paymentCode;
+ }
+ });
+ }
+);
diff --git a/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js b/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js
index 5c1ab3d52c5fa..5075088e2ebd9 100644
--- a/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js
+++ b/app/code/Magento/Vault/view/frontend/web/js/view/payment/vault.js
@@ -21,8 +21,8 @@ define(
rendererList.push(
{
type: index,
- config: config,
- component: 'Magento_Vault/js/view/payment/method-renderer/vault'
+ config: config.config,
+ component: config.component
}
);
});
diff --git a/dev/tests/functional/composer.json b/dev/tests/functional/composer.json
index 532ccf5e82912..826255be7dfd1 100644
--- a/dev/tests/functional/composer.json
+++ b/dev/tests/functional/composer.json
@@ -1,6 +1,6 @@
{
"require": {
- "magento/mtf": "1.0.0-rc37",
+ "magento/mtf": "1.0.0-rc38",
"php": "~5.5.0|~5.6.0|~7.0.0",
"phpunit/phpunit": "4.1.0",
"phpunit/phpunit-selenium": ">=1.2"
diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Conditions.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Conditions.php
index ce80fa82d4074..63977fbf16630 100644
--- a/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Conditions.php
+++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Handler/Conditions.php
@@ -52,6 +52,8 @@ abstract class Conditions extends Curl
'is not' => '!=',
'equal to' => '==',
'matches' => '==',
+ 'greater than' => '>',
+ 'equals or greater than' => '>=',
],
'value_type' => [
'same_as' => 'the Same as Matched Product Categories',
@@ -60,9 +62,15 @@ abstract class Conditions extends Curl
'California' => '12',
'United States' => 'US',
'[flatrate] Fixed' => 'flatrate_flatrate',
+ 'FOUND' => '1',
+ 'TRUE' => '1',
],
'aggregator' => [
'ALL' => 'all',
+ 'ANY' => 'any',
+ ],
+ 'attribute'=> [
+ 'total quantity' => 'qty',
],
];
@@ -181,7 +189,7 @@ private function convertSingleCondition($condition)
);
}
- return $typeParam + $ruleParam;
+ return $ruleParam + $typeParam;
}
/**
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.php
index be7fada0f9b6c..729e796617d79 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.php
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Cc.php
@@ -6,11 +6,7 @@
namespace Magento\Braintree\Test\Block\Form;
-
-use Magento\Mtf\Block\Mapper;
use Magento\Mtf\Client\Locator;
-use Magento\Mtf\Block\BlockFactory;
-use Magento\Mtf\Client\BrowserInterface;
use Magento\Mtf\Client\Element\SimpleElement;
use Magento\Mtf\Fixture\FixtureInterface;
use Magento\Payment\Test\Block\Form\Cc as CreditCard;
@@ -37,8 +33,21 @@ public function fill(FixtureInterface $fixture, SimpleElement $element = null)
{
$mapping = $this->dataMapping($fixture->getData());
foreach ($this->braintreeForm as $field => $iframe) {
+ $element = $this->browser->find('body');
+ $this->browser->waitUntil(
+ function () use ($element, $iframe) {
+ $fieldElement = $element->find($iframe);
+ return $fieldElement->isVisible() ? true : null;
+ }
+ );
$this->browser->switchToFrame(new Locator($iframe));
$element = $this->browser->find('body');
+ $this->browser->waitUntil(
+ function () use ($element) {
+ $fieldElement = $element->find('input');
+ return $fieldElement->isVisible() ? true : null;
+ }
+ );
$this->_fill([$mapping[$field]], $element);
$this->browser->switchToFrame();
}
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.php
new file mode 100644
index 0000000000000..d7e947b7a7e9e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.php
@@ -0,0 +1,70 @@
+browser->switchToFrame(new Locator($locator, Locator::SELECTOR_XPATH));
+ $this->browser->switchToFrame(new Locator($locator, Locator::SELECTOR_XPATH));
+ }
+
+ /**
+ * Click Submit button.
+ *
+ * @return void
+ */
+ public function submit()
+ {
+ $this->browser->find($this->submitButton)->click();
+ }
+
+ /**
+ * Fill the 3D Secure form and submit it.
+ *
+ * @param FixtureInterface $fixture
+ * @param SimpleElement|null $element
+ * @return $this|void
+ */
+ public function fill(FixtureInterface $fixture, SimpleElement $element = null)
+ {
+ $mapping = $this->dataMapping($fixture->getData());
+ $this->switchToFrame($this->braintree3dSecure);
+ $element = $this->browser->find('body');
+ $this->_fill([$mapping['secure3d_password']], $element);
+ $this->submit();
+ $this->browser->switchToFrame();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.xml
new file mode 100644
index 0000000000000..c35c811b49880
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Form/Secure3d.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ input[name="external.field.password"]
+
+
+
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Info.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Info.php
new file mode 100644
index 0000000000000..2039ac0244cc1
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Block/Info.php
@@ -0,0 +1,38 @@
+_rootElement->getElements($this->info, Locator::SELECTOR_XPATH);
+ foreach ($elements as $row) {
+ $key = rtrim($row->find('./th', Locator::SELECTOR_XPATH)->getText(), ':');
+ $value = $row->find('./td', Locator::SELECTOR_XPATH)->getText();
+ $result[$key] = $value;
+ }
+ return $result;
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Constraint/Assert3dSecureInfoIsPresent.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/Constraint/Assert3dSecureInfoIsPresent.php
new file mode 100644
index 0000000000000..c34569487855b
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Constraint/Assert3dSecureInfoIsPresent.php
@@ -0,0 +1,47 @@
+getBraintreeInfoBlock()->getPaymentInfo();
+ foreach ($paymentInformation as $key => $value) {
+ \PHPUnit_Framework_Assert::assertArrayHasKey(
+ $key,
+ $actualPaymentInformation,
+ '3D Secure information is not present.'
+ );
+ \PHPUnit_Framework_Assert::assertEquals(
+ $paymentInformation[$key],
+ $value,
+ '3D Secure information is not equal to information from data set.'
+ );
+ }
+ }
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return '3D Secure information is present and equals to information from data set.';
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Fixture/Secure3dBraintree.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Fixture/Secure3dBraintree.xml
new file mode 100644
index 0000000000000..d0ab27253ecf4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Fixture/Secure3dBraintree.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/CheckoutOnepage.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/CheckoutOnepage.xml
index 4b885217858a1..604ffb277408e 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/CheckoutOnepage.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/CheckoutOnepage.xml
@@ -7,6 +7,7 @@
-->
-
+
+
\ No newline at end of file
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/adminhtml/SalesOrderView.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/adminhtml/SalesOrderView.xml
new file mode 100644
index 0000000000000..ec11c0e63bbfb
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Page/adminhtml/SalesOrderView.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml
index 080906f33d860..bce3cf16c8859 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/ConfigData.xml
@@ -32,19 +32,19 @@
- Yes
- PAYMENT_BRAINTREETWO_MERCHANT_ACCOUNT_ID
-
+
- payment
- 1
- Authorize
- authorize
-
+
- payment
- 1
- Yes
- 1
-
+
- payment
- 1
- Yes
@@ -111,5 +111,100 @@
- 0
+
+
+ - payment
+ - 1
+ - Yes
+ - 1
+
+
+
+
+ - payment
+ - 1
+ - Yes
+ - 0
+
+
+
+
+ - payment
+ - 1
+ - Yes
+ - 1
+
+
+ - payment
+ - 1
+ - Yes
+ - 1
+
+
+ - payment
+ - 1
+ -
+
- GB
+
+
+
+
+
+ - payment
+ - 1
+ - Yes
+ - 0
+
+
+ - payment
+ - 1
+ - Yes
+ - 0
+
+
+
+
+ - payment
+ - 1
+ - Yes
+ - 1
+
+
+ - payment
+ - 1
+ - Yes
+ - 300
+
+
+
+
+ - payment
+ - 1
+ - Yes
+ - 0
+
+
+ - payment
+ - 1
+ - Yes
+ - 0
+
+
+
+
+ - payment
+ - 1
+ - Braintree
+ - braintreetwo
+
+
+
+
+ - payment
+ - 1
+ - Select vault provider
+ - null
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml
index 855fc144880db..fad1bac29cd70 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/CreditCard.xml
@@ -13,5 +13,17 @@
2020
123
+
+ 4000000000000002
+ 01
+ 20
+ 123
+
+
+ 4000000000000028
+ 01
+ 2020
+ 123
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/Secure3d.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/Secure3d.xml
new file mode 100644
index 0000000000000..31aef3a0cd283
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/Repository/Secure3d.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ 1234
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml
new file mode 100644
index 0000000000000..ac570ec147ee3
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOnlineInvoiceEntityTest.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+ Full capture of order placed within Braintree Credit Card
+ catalogProductSimple::product_10_dollar, bundleProduct::bundle_fixed_100_dollar_product
+ default
+ us_ca_ny_rule
+ US_address_1_without_email
+ No
+ Flat Rate
+ Fixed
+
+ - 139.9
+
+ braintreetwo
+ credit_card_braintree
+ visa_braintree
+ braintreetwo
+ Processing
+ Back, Send Email, Credit Memo, Hold, Ship, Reorder
+ -
+ No
+ comments
+ test_type:3rd_party_test
+
+
+
+
+
+
+ Partial capture for order placed within Braintree Credit Card
+ catalogProductSimple::product_100_dollar
+ default
+ us_ca_ny_rule
+ US_address_1_without_email
+ No
+ Flat Rate
+ Fixed
+ Yes
+
+ - 108.25
+ - 118.25
+
+ braintreetwo
+ credit_card_braintree
+ visa_braintree
+ braintreetwo
+ Processing
+ Back, Send Email, Credit Memo, Hold, Ship, Reorder
+ 1
+ No
+ comments
+ test_type:3rd_party_test
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml
index f0a974b5b3983..3180271db86cb 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/CreateOrderBackendTest.xml
@@ -29,6 +29,7 @@
+
@@ -44,6 +45,9 @@
- 145.98
+
+ - 145.98
+
braintreetwo
credit_card_braintree
visa_braintree
@@ -54,6 +58,7 @@
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml
index 106f5d9c4ffba..40f8c0d5ef5eb 100644
--- a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutTest.xml
@@ -7,8 +7,49 @@
-->
-
- test_type:extended_acceptance_test, test_type:3rd_party_test
+
+ catalogProductSimple::product_10_dollar, configurableProduct::with_one_option, bundleProduct::bundle_fixed_100_dollar_product
+ default
+ us_ca_ny_rule
+ US_address_1_without_email
+ login
+ Flat Rate
+ Fixed
+
+ - 145.98
+
+ braintreetwo
+ credit_card_braintree
+ visa_braintree_3dsecure
+ braintreetwo, braintreetwo_3d_secure_not_triggered_due_threshold
+ Processing
+ test_type:3rd_party_test
+
+
+
+
+
+ catalogProductSimple::product_10_dollar, configurableProduct::with_one_option, bundleProduct::bundle_fixed_100_dollar_product
+ default
+ us_ca_ny_rule
+ US_address_1
+ guest
+ Flat Rate
+ Fixed
+
+ - 145.98
+
+ braintreetwo
+ credit_card_braintree
+ visa_braintree_3dsecure
+ braintreetwo, braintreetwo_3d_secure_uk
+ Processing
+ test_type:3rd_party_test
+
+
+
+
+
catalogProductSimple::product_10_dollar, configurableProduct::with_one_option, bundleProduct::bundle_fixed_100_dollar_product
default
us_ca_ny_rule
@@ -24,13 +65,13 @@
visa_braintree
braintreetwo
Processing
+ test_type:extended_acceptance_test, test_type:3rd_party_test
-
- test_type:3rd_party_test
+
catalogProductSimple::product_10_dollar, configurableProduct::with_one_option, bundleProduct::bundle_fixed_100_dollar_product
default
us_ca_ny_rule
@@ -41,15 +82,19 @@
- 145.98
+
+ - 145.98
+
braintreetwo
credit_card_braintree
visa_braintree
braintreetwo_sale
Processing
+ test_type:3rd_party_test
-
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.php
new file mode 100644
index 0000000000000..ea169a58e2ee7
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.php
@@ -0,0 +1,54 @@
+executeScenario();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml
new file mode 100644
index 0000000000000..106b7deaf3a75
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/OnePageCheckoutWith3dSecureTest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Registered Checkout with Braintree Credit Card from Storefront with success 3D Secure verification
+ catalogProductSimple::product_10_dollar, configurableProduct::with_one_option, bundleProduct::bundle_fixed_100_dollar_product
+ default
+ us_ca_ny_rule
+ US_address_1_without_email
+ login
+ Flat Rate
+ Fixed
+
+ - 145.98
+
+ braintreetwo
+ credit_card_braintree
+ visa_braintree_3dsecure
+
+ - 1
+ - 1
+
+ secure3d_braintree
+ braintreetwo, braintreetwo_3d_secure
+ Processing
+ test_type:3rd_party_test
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml
new file mode 100644
index 0000000000000..2be837de7a835
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestCase/UseVaultOnCheckoutTest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ Use saved for Braintree credit card on checkout
+ catalogProductSimple::product_10_dollar
+ default
+ US_address_1_without_email
+ login
+ Flat Rate
+ Fixed
+ braintreetwo
+ credit_card_braintree
+ visa_braintree
+ Yes
+ braintreetwo, braintreetwo_use_vault
+ Processing
+ test_type:3rd_party_test
+ Processing
+ Back, Cancel, Send Email, Hold, Invoice, Ship
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureStep.php b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureStep.php
new file mode 100644
index 0000000000000..b05aa585b5627
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/TestStep/PlaceOrderWith3dSecureStep.php
@@ -0,0 +1,92 @@
+checkoutOnepage = $checkoutOnepage;
+ $this->secure3d = $secure3d;
+ $this->assertGrandTotalOrderReview = $assertGrandTotalOrderReview;
+ $this->checkoutOnepageSuccess = $checkoutOnepageSuccess;
+ $this->prices = $prices;
+ }
+
+ /**
+ * Place order after checking order totals and passing 3D Secure on review step.
+ *
+ * @return array
+ */
+ public function run()
+ {
+ if (isset($this->prices['grandTotal'])) {
+ $this->assertGrandTotalOrderReview->processAssert($this->checkoutOnepage, $this->prices['grandTotal']);
+ }
+ $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->clickPlaceOrder();
+
+ $this->checkoutOnepage->getBraintree3dSecureBlock()->fill($this->secure3d);
+ return ['orderId' => $this->checkoutOnepageSuccess->getSuccessBlock()->getGuestOrderId()];
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/di.xml
new file mode 100644
index 0000000000000..7e766e837a4ff
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/di.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ high
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml
new file mode 100644
index 0000000000000..31e5d04fe186f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Braintree/Test/etc/testcase.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml
index 9b01310fbbc8c..3276e7cb8d4a3 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductSimple.xml
@@ -402,7 +402,7 @@
- - default
+ - custom_attribute_set_with_colors
Simple Product %isolation%
sku_simple_product_%isolation%
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php
index e101d911c0a84..d34763629a58a 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment.php
@@ -20,7 +20,7 @@ class Payment extends Block
*
* @var string
*/
- protected $paymentMethodInput = '#%s';
+ protected $paymentMethodInput = '[id^="%s"]';
/**
* Labels for payment methods.
@@ -34,7 +34,7 @@ class Payment extends Block
*
* @var string
*/
- protected $paymentMethodLabel = '[for="%s"]';
+ protected $paymentMethodLabel = '[for^="%s"]';
/**
* Continue checkout button.
@@ -71,7 +71,6 @@ class Payment extends Block
*/
protected $activePaymentMethodSelector = '.payment-method._active';
-
/**
* Select payment method.
*
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment/Method.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment/Method.php
index 59b43989031ff..5be56bef91f97 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment/Method.php
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Payment/Method.php
@@ -7,6 +7,7 @@
namespace Magento\Checkout\Test\Block\Onepage\Payment;
use Magento\Mtf\Block\Block;
+use Magento\Mtf\Client\Locator;
/**
* Checkout payment method block.
@@ -34,6 +35,13 @@ class Method extends Block
*/
protected $billingAddressSelector = '.payment-method-billing-address';
+ /**
+ * Save credit card check box.
+ *
+ * @var string
+ */
+ protected $vaultCheckbox = '#%s_vault_enabler';
+
/**
* Place order.
*
@@ -59,4 +67,17 @@ public function getBillingBlock()
['element' => $element]
);
}
+
+ /**
+ * Save credit card.
+ *
+ * @param string $paymentMethod
+ * @param string $creditCardSave
+ * @return void
+ */
+ public function saveCreditCard($paymentMethod, $creditCardSave)
+ {
+ $saveCard = sprintf($this->vaultCheckbox, $paymentMethod);
+ $this->_rootElement->find($saveCard, Locator::SELECTOR_CSS, 'checkbox')->setValue($creditCardSave);
+ }
}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php
index 88af288c29ce6..8a9b5bdb72ab6 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/AbstractItems.php
@@ -9,69 +9,68 @@
use Magento\Mtf\Block\Block;
/**
- * Class AbstractItems
- * Base Items block on Credit Memo, Invoice, Shipment view page
+ * Base Items block on Credit Memo, Invoice, Shipment view page.
*/
class AbstractItems extends Block
{
/**
- * Locator for row item
+ * Locator for row item.
*
* @var string
*/
- protected $rowItem = 'tbody tr';
+ protected $rowItem = 'tbody';
/**
- * Locator for "Product" column
+ * Locator for "Product" column.
*
* @var string
*/
protected $product = '.col-product';
/**
- * Locator for "Price" column
+ * Locator for "Price" column.
*
* @var string
*/
protected $price = '.col-price .price';
/**
- * Locator for "Qty" column
+ * Locator for "Qty" column.
*
* @var string
*/
protected $qty = '.col-qty';
/**
- * Locator for "Subtotal" column
+ * Locator for "Subtotal" column.
*
* @var string
*/
protected $subtotal = '.col-subtotal .price';
/**
- * Locator for "Tax Amount" column
+ * Locator for "Tax Amount" column.
*
* @var string
*/
protected $taxAmount = '.col-tax .price';
/**
- * Locator for "Discount Amount" column
+ * Locator for "Discount Amount" column.
*
* @var string
*/
protected $discountAmount = '.col-discount .price';
/**
- * Locator for "Row total" column
+ * Locator for "Row total" column.
*
* @var string
*/
protected $rowTotal = '.col-total .price';
/**
- * Get items data
+ * Get items data.
*
* @return array
*/
@@ -98,14 +97,14 @@ public function getData()
}
/**
- * Parse product name to title and sku product
+ * Parse product name to title and sku product.
*
* @param string $product
* @return array
*/
protected function parseProductName($product)
{
- $data = array_map('trim', explode('SKU:', $product));
+ $data = array_map('trim', explode('SKU:', str_replace("\n", '', $product)));
return [
'product' => $data[0],
'sku' => isset($data[1]) ? $data[1] : ''
@@ -113,7 +112,7 @@ protected function parseProductName($product)
}
/**
- * Prepare price
+ * Prepare price.
*
* @var string $price
* @return string
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/History.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/History.php
index 17d1dd67238c0..25ed6613a8e09 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/History.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/History.php
@@ -10,35 +10,33 @@
use Magento\Mtf\Client\Locator;
/**
- * Class Totals
- * Order totals block
- *
+ * Order comments block.
*/
class History extends Block
{
/**
- * Comment history Id
+ * Comment history Id.
*
* @var string
*/
protected $commentHistory = '.note-list-comment';
/**
- * Captured Amount from IPN
+ * Captured Amount from IPN.
*
* @var string
*/
- protected $capturedAmount = '//div[@class="note-list-comment"][contains(text(), "captured amount of")]';
+ protected $capturedAmount = '//div[@class="note-list-comment"][contains(text(), "Captured amount of")]';
/**
- * Note list locator
+ * Note list locator.
*
* @var string
*/
protected $noteList = '.note-list';
/**
- * Get comments history
+ * Get comments history.
*
* @return string
*/
@@ -49,18 +47,23 @@ public function getCommentsHistory()
}
/**
- * Get the captured amount from the comments history
+ * Get the captured amount from the comments history.
*
- * @return string
+ * @return array
*/
public function getCapturedAmount()
{
+ $result = [];
$this->waitCommentsHistory();
- return $this->_rootElement->find($this->capturedAmount, Locator::SELECTOR_XPATH)->getText();
+ $captureComments = $this->_rootElement->getElements($this->capturedAmount, Locator::SELECTOR_XPATH);
+ foreach ($captureComments as $captureComment) {
+ $result[] = $captureComment->getText();
+ }
+ return $result;
}
/**
- * Wait for comments history is visible
+ * Wait for comments history is visible.
*
* @return void
*/
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php
index 07dd426adc07f..1b697a839740b 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/View/Tab/Invoices/Grid.php
@@ -7,13 +7,12 @@
namespace Magento\Sales\Test\Block\Adminhtml\Order\View\Tab\Invoices;
/**
- * Class Grid
- * Invoices grid on order view page
+ * Invoices grid on order view page.
*/
class Grid extends \Magento\Backend\Test\Block\Widget\Grid
{
/**
- * Locator value for link in action column
+ * Locator value for link in action column.
*
* @var string
*/
@@ -24,10 +23,10 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid
*
* @var string
*/
- protected $invoiceId = 'tbody td[data-column="increment_id"]';
+ protected $invoiceId = 'tbody td:nth-child(2)';
/**
- * Filters array mapping
+ * Filters array mapping.
*
* @var array
*/
@@ -48,7 +47,7 @@ class Grid extends \Magento\Backend\Test\Block\Widget\Grid
];
/**
- * Get invoice ids
+ * Get invoice ids.
*
* @return array
*/
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php
index 3c56ce05d439b..c3b51812e7cce 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertCaptureInCommentsHistory.php
@@ -26,25 +26,26 @@ class AssertCaptureInCommentsHistory extends AbstractConstraint
* @param SalesOrderView $salesOrderView
* @param OrderIndex $salesOrder
* @param string $orderId
- * @param array $prices
+ * @param array $capturedPrices
* @return void
*/
public function processAssert(
SalesOrderView $salesOrderView,
OrderIndex $salesOrder,
$orderId,
- array $prices
+ array $capturedPrices
) {
$salesOrder->open();
$salesOrder->getSalesOrderGrid()->searchAndOpen(['id' => $orderId]);
- $actualCapturedAmount = $salesOrderView->getOrderHistoryBlock()->getCommentsHistory();
-
- \PHPUnit_Framework_Assert::assertContains(
- self::CAPTURED_AMOUNT . $prices['grandTotal'],
- $actualCapturedAmount,
- 'Incorrect captured amount value for the order #' . $orderId
- );
+ $actualCapturedAmount = $salesOrderView->getOrderHistoryBlock()->getCapturedAmount();
+ foreach ($capturedPrices as $key => $capturedPrice) {
+ \PHPUnit_Framework_Assert::assertContains(
+ self::CAPTURED_AMOUNT . $capturedPrice,
+ $actualCapturedAmount[$key],
+ 'Incorrect captured amount value for the order #' . $orderId
+ );
+ }
}
/**
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php
index dc3c3dea3aa1d..8337a29a3fe99 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertInvoiceItems.php
@@ -11,13 +11,12 @@
use Magento\Sales\Test\Page\Adminhtml\SalesInvoiceView;
/**
- * Class AssertInvoiceItems
- * Assert invoice items on invoice view page
+ * Assert invoice items on invoice view page.
*/
class AssertInvoiceItems extends AbstractAssertItems
{
/**
- * Assert invoice items on invoice view page
+ * Assert invoice items on invoice view page.
*
* @param InvoiceIndex $invoiceIndex
* @param SalesInvoiceView $salesInvoiceView
@@ -33,7 +32,6 @@ public function processAssert(
array $ids,
array $data = null
) {
- $invoiceIndex->open();
$orderId = $order->getId();
$productsData = $this->prepareOrderProducts($order, $data['items_data']);
foreach ($ids['invoiceIds'] as $invoiceId) {
@@ -41,6 +39,7 @@ public function processAssert(
'order_id' => $orderId,
'id' => $invoiceId,
];
+ $invoiceIndex->open();
$invoiceIndex->getInvoicesGrid()->searchAndOpen($filter);
$itemsData = $this->preparePageItems($salesInvoiceView->getItemsBlock()->getData());
$error = $this->verifyData($productsData, $itemsData);
@@ -49,7 +48,7 @@ public function processAssert(
}
/**
- * Returns a string representation of the object
+ * Returns a string representation of the object.
*
* @return string
*/
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineInvoiceEntityTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineInvoiceEntityTest.php
new file mode 100644
index 0000000000000..498289bd5f227
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateOnlineInvoiceEntityTest.php
@@ -0,0 +1,55 @@
+ Orders.
+ * 3. Click Create New Order.
+ * 4. Select Customer created in preconditions.
+ * 5. Add Product.
+ * 6. Fill data according dataset.
+ * 7. Click Update Product qty.
+ * 8. Fill data according dataset.
+ * 9. Click Get Shipping Method and rates.
+ * 10. Fill data according dataset.
+ * 11. Submit Order.
+ * 12. Go to Sales > Orders.
+ * 13. Select created order in the grid and open it.
+ * 14. Click 'Invoice' button.
+ * 15. Fill data according to dataset.
+ * 16. Click 'Submit Invoice' button.
+ * 17. Perform assertions.
+ *
+ * @group Order_Management_(CS)
+ * @ZephyrId MAGETWO-47010
+ */
+class CreateOnlineInvoiceEntityTest extends Scenario
+{
+ /* tags */
+ const MVP = 'yes';
+ const DOMAIN = 'CS';
+ const TEST_TYPE = '3rd_party_test';
+ /* end tags */
+
+ /**
+ * Runs sales order on backend.
+ *
+ * @return void
+ */
+ public function test()
+ {
+ $this->executeScenario();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateInvoiceStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateInvoiceStep.php
index 6f419896aa618..2840263ad9a86 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateInvoiceStep.php
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/CreateInvoiceStep.php
@@ -68,6 +68,13 @@ class CreateInvoiceStep implements TestStepInterface
*/
protected $data;
+ /**
+ * Whether Invoice is partial.
+ *
+ * @var string
+ */
+ protected $isInvoicePartial;
+
/**
* @construct
* @param OrderIndex $orderIndex
@@ -77,6 +84,7 @@ class CreateInvoiceStep implements TestStepInterface
* @param OrderInjectable $order
* @param OrderShipmentView $orderShipmentView
* @param array|null $data [optional]
+ * @param string $isInvoicePartial [optional]
*/
public function __construct(
OrderIndex $orderIndex,
@@ -85,7 +93,8 @@ public function __construct(
OrderInvoiceView $orderInvoiceView,
OrderInjectable $order,
OrderShipmentView $orderShipmentView,
- $data = null
+ $data = null,
+ $isInvoicePartial = null
) {
$this->orderIndex = $orderIndex;
$this->salesOrderView = $salesOrderView;
@@ -94,6 +103,7 @@ public function __construct(
$this->order = $order;
$this->orderShipmentView = $orderShipmentView;
$this->data = $data;
+ $this->isInvoicePartial = $isInvoicePartial;
}
/**
@@ -113,6 +123,10 @@ public function run()
);
$this->orderInvoiceNew->getFormBlock()->updateQty();
$this->orderInvoiceNew->getFormBlock()->fillFormData($this->data);
+ if (isset($this->isInvoicePartial)) {
+ $this->orderInvoiceNew->getFormBlock()->submit();
+ $this->salesOrderView->getPageActions()->invoice();
+ }
}
$this->orderInvoiceNew->getFormBlock()->submit();
$invoiceIds = $this->getInvoiceIds();
@@ -121,8 +135,10 @@ public function run()
}
return [
- 'invoiceIds' => $invoiceIds,
- 'shipmentIds' => isset($shipmentIds) ? $shipmentIds : null,
+ 'ids' => [
+ 'invoiceIds' => $invoiceIds,
+ 'shipmentIds' => isset($shipmentIds) ? $shipmentIds : null,
+ ]
];
}
diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml
index 6c5b7cdd1b66a..9d68c4263c6e6 100644
--- a/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/etc/testcase.xml
@@ -48,4 +48,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Block/Adminhtml/Promo/Quote/Edit/PromoQuoteForm.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Block/Adminhtml/Promo/Quote/Edit/PromoQuoteForm.php
index 9a2b007711a0d..62c9b3207a7b1 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Block/Adminhtml/Promo/Quote/Edit/PromoQuoteForm.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Block/Adminhtml/Promo/Quote/Edit/PromoQuoteForm.php
@@ -6,6 +6,8 @@
namespace Magento\SalesRule\Test\Block\Adminhtml\Promo\Quote\Edit;
use Magento\Backend\Test\Block\Widget\FormTabs;
+use Magento\Mtf\Client\Element\SimpleElement;
+use Magento\Mtf\Fixture\FixtureInterface;
/**
* Sales rule edit form.
@@ -25,4 +27,45 @@ class PromoQuoteForm extends FormTabs
* @var boolean
*/
protected $waitForSelectorVisible = false;
+
+ /**
+ * Fill form with tabs.
+ *
+ * @param FixtureInterface $fixture
+ * @param SimpleElement $element
+ * @param array $replace
+ * @return $this|FormTabs
+ */
+ public function fill(FixtureInterface $fixture, SimpleElement $element = null, array $replace = null)
+ {
+ $tabs = $this->getFieldsByTabs($fixture);
+ if ($replace) {
+ $tabs = $this->prepareData($tabs, $replace);
+ }
+ $this->fillTabs($tabs, $element);
+ }
+
+ /**
+ * Replace placeholders in each values of data.
+ *
+ * @param array $tabs
+ * @param array $replace
+ * @return array
+ */
+ protected function prepareData(array $tabs, array $replace)
+ {
+ foreach ($replace as $tabName => $fields) {
+ foreach ($fields as $key => $pairs) {
+ if (isset($tabs[$tabName][$key])) {
+ $tabs[$tabName][$key]['value'] = str_replace(
+ array_keys($pairs),
+ array_values($pairs),
+ $tabs[$tabName][$key]['value']
+ );
+ }
+ }
+ }
+
+ return $tabs;
+ }
}
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php
index a9307ce813213..6249fb5f56efd 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleApplying.php
@@ -88,6 +88,13 @@ abstract class AssertCartPriceRuleApplying extends AbstractConstraint
*/
protected $productForSalesRule2;
+ /**
+ * Cart prices to compare.
+ *
+ * @array cartPrice
+ */
+ protected $cartPrice;
+
/**
* Implementation assert.
*
@@ -120,15 +127,16 @@ abstract protected function assert();
* @param CustomerAccountLogout $customerAccountLogout
* @param CatalogCategoryView $catalogCategoryView
* @param CatalogProductView $catalogProductView
- * @param Customer $customer
* @param SalesRule $salesRule
* @param SalesRule $salesRuleOrigin
* @param array $productQuantity
* @param CatalogProductSimple $productForSalesRule1
* @param CatalogProductSimple $productForSalesRule2
+ * @param Customer $customer
* @param Address $address
* @param int|null $isLoggedIn
* @param array $shipping
+ * @param array $cartPrice
* @return void
*
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -140,15 +148,16 @@ public function processAssert(
CustomerAccountLogout $customerAccountLogout,
CatalogCategoryView $catalogCategoryView,
CatalogProductView $catalogProductView,
- Customer $customer,
SalesRule $salesRule,
SalesRule $salesRuleOrigin,
array $productQuantity,
CatalogProductSimple $productForSalesRule1,
CatalogProductSimple $productForSalesRule2 = null,
+ Customer $customer = null,
Address $address = null,
$isLoggedIn = null,
- array $shipping = []
+ array $shipping = [],
+ array $cartPrice = []
) {
$this->checkoutCart = $checkoutCart;
$this->cmsIndex = $cmsIndex;
@@ -156,9 +165,12 @@ public function processAssert(
$this->customerAccountLogout = $customerAccountLogout;
$this->catalogCategoryView = $catalogCategoryView;
$this->catalogProductView = $catalogProductView;
- $this->customer = $customer;
$this->productForSalesRule1 = $productForSalesRule1;
$this->productForSalesRule2 = $productForSalesRule2;
+ $this->cartPrice = $cartPrice;
+ if ($customer !== null) {
+ $this->customer = $customer;
+ }
$isLoggedIn ? $this->login() : $this->customerAccountLogout->open();
$this->checkoutCart->open()->getCartBlock()->clearShoppingCart();
$this->addProductsToCart($productQuantity);
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleConditionIsApplied.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleConditionIsApplied.php
index 55a3450a6e108..e4cc6a5f55f2e 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleConditionIsApplied.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Constraint/AssertCartPriceRuleConditionIsApplied.php
@@ -7,28 +7,28 @@
namespace Magento\SalesRule\Test\Constraint;
/**
- * Check that shopping cart subtotal not equals with grand total(excluding shipping price if exist).
+ * Assert that Catalog Price Rule is applied in Shopping Cart.
*/
class AssertCartPriceRuleConditionIsApplied extends AssertCartPriceRuleApplying
{
/**
- * Assert that shopping cart subtotal not equals with grand total.
+ * Assert that Catalog Price Rule is applied in Shopping Cart.
*
* @return void
*/
protected function assert()
{
- $subTotal = $this->checkoutCart->getTotalsBlock()->getSubtotal();
- $grandTotal = $this->checkoutCart->getTotalsBlock()->getGrandTotal();
+ $this->checkoutCart->getTotalsBlock()->waitForShippingPriceBlock();
+ $this->checkoutCart->getTotalsBlock()->waitForUpdatedTotals();
+ $actualPrices['sub_total'] = $this->checkoutCart->getTotalsBlock()->getSubtotal();
+ $actualPrices['grand_total'] = $this->checkoutCart->getTotalsBlock()->getGrandTotal();
+ $actualPrices['discount'] = $this->checkoutCart->getTotalsBlock()->getDiscount();
+ $expectedPrices = $this->cartPrice;
- if ($this->checkoutCart->getTotalsBlock()->isVisibleShippingPriceBlock()) {
- $shippingPrice = $this->checkoutCart->getTotalsBlock()->getShippingPrice();
- $grandTotal = number_format(($grandTotal - $shippingPrice), 2);
- }
- \PHPUnit_Framework_Assert::assertNotEquals(
- $subTotal,
- $grandTotal,
- 'Shopping cart subtotal: \'' . $subTotal . '\' equals with grand total: \'' . $grandTotal . '\''
+ \PHPUnit_Framework_Assert::assertEquals(
+ $expectedPrices,
+ $actualPrices,
+ 'Wrong total cart prices are displayed.'
);
}
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php
index e6a910a76fa65..65266446a3596 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Handler/SalesRule/Curl.php
@@ -41,11 +41,27 @@ class Curl extends Conditions implements SalesRuleInterface
'type' => 'Magento\SalesRule\Model\Rule\Condition\Address',
'attribute' => 'base_subtotal',
],
+ 'Total Items Quantity' => [
+ 'type' => 'Magento\SalesRule\Model\Rule\Condition\Address',
+ 'attribute' => 'total_qty',
+ ],
'Conditions combination' => [
'type' => 'Magento\SalesRule\Model\Rule\Condition\Combine',
'aggregator' => 'all',
'value' => '1',
],
+ 'Products subselection' => [
+ 'type' => 'Magento\SalesRule\Model\Rule\Condition\Product\Subselect',
+ 'attribute' => 'qty',
+ 'operator' => '==',
+ 'value' => '1',
+ 'aggregator' => 'all',
+ ],
+ 'Product attribute combination' => [
+ 'type' => 'Magento\SalesRule\Model\Rule\Condition\Product\Found',
+ 'value' => '1',
+ 'aggregator' => 'all',
+ ],
'Shipping Country' => [
'type' => 'Magento\SalesRule\Model\Rule\Condition\Address',
'attribute' => 'country_id',
@@ -57,6 +73,18 @@ class Curl extends Conditions implements SalesRuleInterface
'Category' => [
'type' => 'Magento\SalesRule\Model\Rule\Condition\Product',
'attribute' => 'category_ids',
+ ],
+ 'Price in cart' => [
+ 'type' => 'Magento\SalesRule\Model\Rule\Condition\Product',
+ 'attribute' => 'quote_item_price',
+ ],
+ 'Quantity in cart' => [
+ 'type' => 'Magento\SalesRule\Model\Rule\Condition\Product',
+ 'attribute' => 'quote_item_qty',
+ ],
+ 'Row total in cart' => [
+ 'type' => 'Magento\SalesRule\Model\Rule\Condition\Product',
+ 'attribute' => 'quote_item_row_total',
]
];
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
index 5f0d0df94604f..6250b30614abc 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/Repository/SalesRule.xml
@@ -189,5 +189,95 @@
Percent of product price discount
50
+
+
+ Cart Price Rule with product subselection %isolation%
+ Cart Price Rule with product subselection
+ Active
+
+ - Main Website
+
+
+ - NOT LOGGED IN
+
+ No Coupon
+ 0
+ Yes
+ {Products subselection|total quantity|is|2|:[[Price in cart|is|50]]}
+ [Price in cart|is|50]
+ Percent of product price discount
+ 10
+ 1
+ 0
+ No
+ No
+ No
+
+ - Cart Price Rule with subselection
+ - Cart Price Rule with subselection
+
+
+
+
+ Cart price rule with attribute conditions %isolation%
+ Active
+
+ - Main Website
+
+
+ - NOT LOGGED IN
+
+ No Coupon
+ 0
+ Yes
+ {Product attribute combination|FOUND|ANY|:[[Price in cart|greater than|99][Quantity in cart|greater than|3]]}
+ {Conditions combination|ANY|TRUE|:[[Price in cart|greater than|99][Quantity in cart|greater than|3]]}
+ Fixed amount discount
+ 6
+ No
+ No
+ No
+
+
+
+ Cart price rule with row total condition %isolation%
+ Active
+
+ - Main Website
+
+
+ - NOT LOGGED IN
+
+ No Coupon
+ 0
+ Yes
+ {Product attribute combination:[[Row total in cart|greater than|50]]}
+ [Row total in cart|greater than|50]
+ Fixed amount discount
+ 6
+ No
+ No
+ No
+
+
+
+ Cart price rule with total items %isolation%
+ Active
+
+ - Main Website
+
+
+ - NOT LOGGED IN
+
+ No Coupon
+ 1
+ Yes
+ [Total Items Quantity|equals or greater than|3]{Product attribute combination|FOUND|ALL|:[[Category|is|2]]}
+ Percent of product price discount
+ 25
+ No
+ No
+ No
+
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ApplySeveralSalesRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ApplySeveralSalesRuleEntityTest.php
new file mode 100644
index 0000000000000..ae907548b3ef0
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ApplySeveralSalesRuleEntityTest.php
@@ -0,0 +1,87 @@
+fixtureFactory = $fixtureFactory;
+ }
+
+ /**
+ * Apply several sales rules.
+ *
+ * @param array $salesRules
+ * @param CatalogProductSimple $productForSalesRule1
+ * @param CatalogProductSimple $productForSalesRule2
+ */
+ public function testApplySeveralSalesRules(
+ array $salesRules,
+ CatalogProductSimple $productForSalesRule1,
+ CatalogProductSimple $productForSalesRule2
+ ) {
+ // Preconditions
+ $productForSalesRule1->persist();
+ $productForSalesRule2->persist();
+
+ // Create sales rules
+ foreach ($salesRules as $key => $dataSet) {
+ $salesRule[$key] = $this->fixtureFactory->createByCode(
+ 'salesRule',
+ ['dataset' => $dataSet]
+ );
+ $salesRule[$key]->persist();
+ }
+ }
+
+ /**
+ * Clear data after test.
+ *
+ * @return void
+ */
+ public function tearDown()
+ {
+ $this->objectManager->create('\Magento\SalesRule\Test\TestStep\DeleteAllSalesRuleStep')->run();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ApplySeveralSalesRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ApplySeveralSalesRuleEntityTest.xml
new file mode 100644
index 0000000000000..1d419bbe3389f
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/ApplySeveralSalesRuleEntityTest.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+ active_sales_rule_product_subselection
+ active_sales_rule_product_attribute
+ 200.00
+ 204.00
+ 11.00
+ simple_for_salesrule_1
+ simple_for_salesrule_2
+ 1
+ 2
+
+
+
+ active_sales_rule_for_all_groups_no_coupon
+ active_sales_rule_row_total
+ 100.00
+ 55.00
+ 50.00
+ simple_for_salesrule_1
+ simple_for_salesrule_2
+ 1
+
+
+
+ active_sales_rule_product_attribute
+ active_sales_total_items
+ 250.00
+ 193.50
+ 71.50
+ simple_for_salesrule_1
+ simple_for_salesrule_2
+ 2
+ 1
+
+
+
+ active_sales_rule_row_total
+ active_sales_total_items
+ simple_for_salesrule_1
+ simple_for_salesrule_2
+ 1
+
+
+
+
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php
index cdb01841dd5f0..562e15ac5b001 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.php
@@ -12,6 +12,8 @@
use Magento\SalesRule\Test\Page\Adminhtml\PromoQuoteNew;
use Magento\Mtf\Fixture\FixtureFactory;
use Magento\Mtf\TestCase\Injectable;
+use Magento\Catalog\Test\Fixture\CatalogProductSimple;
+use Magento\Customer\Test\Fixture\Customer;
/**
* Precondition:
@@ -64,69 +66,102 @@ class CreateSalesRuleEntityTest extends Injectable
*/
protected $salesRuleName;
+ /**
+ * Fixture factory.
+ *
+ * @var FixtureFactory
+ */
+ protected $fixtureFactory;
+
/**
* Inject pages.
*
* @param PromoQuoteNew $promoQuoteNew
* @param PromoQuoteIndex $promoQuoteIndex
* @param PromoQuoteEdit $promoQuoteEdit
+ * @param FixtureFactory $fixtureFactory
* @return void
*/
public function __inject(
PromoQuoteNew $promoQuoteNew,
PromoQuoteIndex $promoQuoteIndex,
- PromoQuoteEdit $promoQuoteEdit
+ PromoQuoteEdit $promoQuoteEdit,
+ FixtureFactory $fixtureFactory
) {
$this->promoQuoteNew = $promoQuoteNew;
$this->promoQuoteIndex = $promoQuoteIndex;
$this->promoQuoteEdit = $promoQuoteEdit;
+ $this->fixtureFactory = $fixtureFactory;
}
/**
- * Create customer and 2 simple products with categories before run test.
+ * Create Sales Price Rule.
*
- * @param FixtureFactory $fixtureFactory
- * @return array
+ * @param SalesRule $salesRule
+ * @param CatalogProductSimple $productForSalesRule1
+ * @param CatalogProductSimple $productForSalesRule2
+ * @param Customer $customer
+ * @param string $conditionEntity
*/
- public function __prepare(FixtureFactory $fixtureFactory)
- {
- $customer = $fixtureFactory->createByCode('customer', ['dataset' => 'default']);
- $customer->persist();
+ public function testCreateSalesRule(
+ SalesRule $salesRule,
+ CatalogProductSimple $productForSalesRule1,
+ CatalogProductSimple $productForSalesRule2 = null,
+ Customer $customer = null,
+ $conditionEntity = null
+ ) {
+ $replace = null;
+ $this->salesRuleName = $salesRule->getName();
- $productForSalesRule1 = $fixtureFactory->createByCode(
- 'catalogProductSimple',
- ['dataset' => 'simple_for_salesrule_1']
- );
+ // Prepare data
+ if ($customer !== null) {
+ $customer->persist();
+ }
$productForSalesRule1->persist();
+ if ($productForSalesRule2 !== null) {
+ $productForSalesRule2->persist();
+ if ($conditionEntity !== null) {
+ $replace = $this->prepareCondition($productForSalesRule2, $conditionEntity);
+ }
+ }
- $productForSalesRule2 = $fixtureFactory->createByCode(
- 'catalogProductSimple',
- ['dataset' => 'simple_for_salesrule_2']
- );
- $productForSalesRule2->persist();
+ // Steps
+ $this->promoQuoteNew->open();
+ $this->promoQuoteNew->getSalesRuleForm()->fill($salesRule, null, $replace);
+ $this->promoQuoteNew->getFormPageActions()->save();
- return [
- 'customer' => $customer,
- 'productForSalesRule1' => $productForSalesRule1,
- 'productForSalesRule2' => $productForSalesRule2
- ];
}
/**
- * Create Sales Rule Entity.
+ * Prepare condition for Sales rule.
*
- * @param SalesRule $salesRule
- * @return void
+ * @param CatalogProductSimple $productSimple
+ * @param string $conditionEntity
+ * @return array
*/
- public function testCreateSalesRule(SalesRule $salesRule)
+ protected function prepareCondition(CatalogProductSimple $productSimple, $conditionEntity)
{
- // Preconditions
- $this->salesRuleName = $salesRule->getName();
+ $result = [];
+
+ switch ($conditionEntity) {
+ case 'category':
+ $result['%category_id%'] = $productSimple->getDataFieldConfig('category_ids')['source']->getIds()[0];
+ break;
+ case 'attribute':
+ /** @var \Magento\Catalog\Test\Fixture\CatalogProductAttribute[] $attrs */
+ $attributes = $productSimple->getDataFieldConfig('attribute_set_id')['source']
+ ->getAttributeSet()->getDataFieldConfig('assigned_attributes')['source']->getAttributes();
+
+ $result['%attribute_name%'] = $attributes[0]->getFrontendLabel();
+ $result['%attribute_value%'] = $attributes[0]->getOptions()[0]['view'];
+ break;
+ }
- // Steps
- $this->promoQuoteNew->open();
- $this->promoQuoteNew->getSalesRuleForm()->fill($salesRule);
- $this->promoQuoteNew->getFormPageActions()->save();
+ return [
+ 'conditions' => [
+ 'conditions_serialized' => $result,
+ ],
+ ];
}
/**
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml
index 0720e78078111..8b139628a11b7 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/CreateSalesRuleEntityTest.xml
@@ -19,6 +19,10 @@
No
No
Sales Cart Rule labels
+ 100.00
+ 55.00
+ 50.00
+ simple_for_salesrule_1
1
@@ -37,7 +41,11 @@
No
No
Coupon code+fixed amount discount
+ simple_for_salesrule_1
2
+ 200.00
+ 140.00
+ 70.00
@@ -55,7 +63,11 @@
No
No
Coupon code+Fixed amount discount for whole cart
+ simple_for_salesrule_1
3
+ 300.00
+ 255.00
+ 60.00
@@ -74,7 +86,11 @@
No
No
Buy X get Y free
+ simple_for_salesrule_1
4
+ 400.00
+ 320.00
+ 100.00
@@ -82,6 +98,7 @@
test_type:extended_acceptance_test
1
+ default
Cart Price Rule5 %isolation%
Cart Price Rule Description %isolation%
Active
@@ -93,7 +110,11 @@
2
No
No
+ simple_for_salesrule_1
3
+ 300.00
+ 215.00
+ 100.00
@@ -115,8 +136,13 @@
Yes
No
Apply discount to Shipping Amount
+ simple_for_salesrule_1
+ simple_for_salesrule_2
1
1
+ 150.00
+ 80.00
+ 80.00
@@ -138,14 +164,24 @@
No
For matching items only
Free Shipping in conditions
+ simple_for_salesrule_1
+ simple_for_salesrule_2
1
1
+ 150.00
+ 75.00
+ 75.00
+ United States
+ California
+ 95814
+ Flat Rate
+ Fixed
Cart Price Rule8 %isolation%
Cart Price Rule Description %isolation%
Active
@@ -158,8 +194,13 @@
No
No
Sales Cart Rule labels
+ simple_for_salesrule_1
+ simple_for_salesrule_2
1
1
+ 150.00
+ 85.00
+ 75.00
@@ -171,12 +212,13 @@
Main Website
NOT LOGGED IN
No Coupon
- [Subtotal|is|150]
+ [Total Items Quantity|is|3]
Percent of product price discount
50
No
No
- Subtotal Action-Condition test
+ Total Items Quantity-Not Applied test
+ simple_for_salesrule_1
2
@@ -189,13 +231,20 @@
Main Website
NOT LOGGED IN
No Coupon
- [Total Items Quantity|is|2]
+ category
+ {Product attribute combination:[Category|is|%category_id%]}
Percent of product price discount
50
No
No
- Total Items Quantity is 2
+ Product attribute combination - Category
+ simple_for_salesrule_1
+ simple_for_salesrule_2
2
+ 1
+ 250.00
+ 140.00
+ 125.00
@@ -207,14 +256,19 @@
Main Website
NOT LOGGED IN
No Coupon
- [Total Weight|is|150]
+ [Total Weight|is|200]
Percent of product price discount
50
No
No
- Total Weight is 150
+ Total Weight is 200
+ simple_for_salesrule_1
+ simple_for_salesrule_2
1
- 1
+ 2
+ 200.00
+ 115.00
+ 100.00
@@ -237,8 +291,13 @@
No
No
Rule applied conditions combination
+ simple_for_salesrule_1
+ simple_for_salesrule_2
1
1
+ 150.00
+ 85.00
+ 75.00
@@ -257,7 +316,35 @@
No
No
Product attribute discount
+ simple_for_salesrule_1
1
+ 100.00
+ 55.00
+ 50.00
+
+
+
+
+
+ Cart Price Rule14 %isolation%
+ Cart Price Rule Description %isolation%
+ Active
+ Main Website
+ NOT LOGGED IN
+ No Coupon
+ attribute
+ {Product attribute combination:[%attribute_name%|is|%attribute_value%]}
+ Percent of product price discount
+ 50
+ No
+ No
+ Product attribute combination - attribute
+ simple_for_salesrule_1
+ simple_for_salesrule_2
+ 1
+ 50.00
+ 30.00
+ 25.00
diff --git a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.xml
index 51362965e0f22..14d787e33ddeb 100644
--- a/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/SalesRule/Test/TestCase/UpdateSalesRuleEntityTest.xml
@@ -20,6 +20,9 @@
95814
Flat Rate
Fixed
+ 400.00
+ 300.00
+ 100.00
diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/UseVaultOnCheckoutTest.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/UseVaultOnCheckoutTest.php
new file mode 100644
index 0000000000000..a05decda594f2
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestCase/UseVaultOnCheckoutTest.php
@@ -0,0 +1,54 @@
+executeScenario();
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/SaveCreditCardStep.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/SaveCreditCardStep.php
new file mode 100644
index 0000000000000..47bafd49f7b03
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/SaveCreditCardStep.php
@@ -0,0 +1,66 @@
+checkoutOnepage = $checkoutOnepage;
+ $this->payment = $payment;
+ $this->creditCardSave = $creditCardSave;
+ }
+
+ /**
+ * Run step that saves credit card.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ $this->checkoutOnepage->getPaymentBlock()->getSelectedPaymentMethodBlock()->saveCreditCard(
+ $this->payment['method'],
+ $this->creditCardSave
+ );
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/UseSavedCreditCardStep.php b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/UseSavedCreditCardStep.php
new file mode 100644
index 0000000000000..02c7489d2c279
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Vault/Test/TestStep/UseSavedCreditCardStep.php
@@ -0,0 +1,52 @@
+checkoutOnepage = $checkoutOnepage;
+ $this->payment = $payment;
+ }
+
+ /**
+ * Run step that selects saved credit card.
+ *
+ * @return void
+ */
+ public function run()
+ {
+ $this->payment['method'] .= '_vault_item_';
+ $this->checkoutOnepage->getPaymentBlock()->selectPaymentMethod($this->payment);
+ }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml
new file mode 100644
index 0000000000000..3c106e36f1172
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Vault/Test/etc/testcase.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests/3rd_party.xml b/dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests/3rd_party.xml
new file mode 100644
index 0000000000000..80574d554209c
--- /dev/null
+++ b/dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests/3rd_party.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/integration/etc/install-config-mysql.travis.php.dist b/dev/tests/integration/etc/install-config-mysql.travis.php.dist
index 1359c82a334bd..22004fc345e64 100644
--- a/dev/tests/integration/etc/install-config-mysql.travis.php.dist
+++ b/dev/tests/integration/etc/install-config-mysql.travis.php.dist
@@ -6,7 +6,7 @@
return [
'db-host' => '127.0.0.1',
- 'db-user' => 'travis',
+ 'db-user' => 'root',
'db-password' => '',
'db-name' => 'magento_integration_tests',
'db-prefix' => 'trv_',
diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php
index 68c6cefb29a53..3ffc97f1129c3 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php
@@ -8,7 +8,9 @@
require dirname(dirname(__DIR__)) . '/Store/_files/second_store.php';
require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute.php';
-$productModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+$productModel = $objectManager->create('Magento\Catalog\Model\Product');
$customOptions = [
1 => [
@@ -57,4 +59,17 @@
[$product->getId() => ['position' => 1]]
);
-$product->setOptions($customOptions)->save();
+$options = [];
+
+/** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */
+$customOptionFactory = $objectManager->create('Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory');
+
+foreach ($customOptions as $option) {
+ /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterface $option */
+ $option = $customOptionFactory->create(['data' => $option]);
+ $option->setProductSku($productModel->getSku());
+
+ $options[] = $option;
+}
+
+$productModel->setOptions($options)->save();
diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_10_off_not_logged.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_10_off_not_logged.php
index 6701e35791b4e..b0d9b80409f7c 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_10_off_not_logged.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/catalog_rule_10_off_not_logged.php
@@ -19,6 +19,10 @@
->setDiscountAmount(10)
->setWebsiteIds([0 => 1])
->setSimpleAction('by_percent')
+ ->setStopRulesProcessing(false)
+ ->setSortOrder(0)
+ ->setSubIsEnable(0)
+ ->setSubDiscountAmount(0)
->save();
/** @var \Magento\CatalogRule\Model\Indexer\IndexBuilder $indexBuilder */
diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_attribute.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_attribute.php
index faa1927901fc5..0324199f93702 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_attribute.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/rule_by_attribute.php
@@ -11,12 +11,16 @@
$rule->loadPost([
'name' => 'test_rule',
'is_active' => '1',
+ 'stop_rules_processing' => 0,
'website_ids' => [1],
'customer_group_ids' => [0, 1],
'discount_amount' => 2,
'simple_action' => 'by_percent',
'from_date' => '',
'to_date' => '',
+ 'sort_order' => 0,
+ 'sub_is_enable' => 0,
+ 'sub_discount_amount' => 0,
'conditions' => [
'1' => [
'type' => 'Magento\CatalogRule\Model\Rule\Condition\Combine',
diff --git a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/two_rules.php b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/two_rules.php
index 2f6e0cd466b2c..8a35005923700 100644
--- a/dev/tests/integration/testsuite/Magento/CatalogRule/_files/two_rules.php
+++ b/dev/tests/integration/testsuite/Magento/CatalogRule/_files/two_rules.php
@@ -18,6 +18,9 @@
'simple_action' => 'by_percent',
'from_date' => '',
'to_date' => '',
+ 'sort_order' => 0,
+ 'sub_is_enable' => 0,
+ 'sub_discount_amount' => 0,
'conditions' => [
'1' => [
'type' => 'Magento\CatalogRule\Model\Rule\Condition\Combine',
@@ -42,6 +45,9 @@
'simple_action' => 'by_fixed',
'from_date' => '',
'to_date' => '',
+ 'sort_order' => 0,
+ 'sub_is_enable' => 0,
+ 'sub_discount_amount' => 0,
'conditions' => [
'1' => [
'type' => 'Magento\CatalogRule\Model\Rule\Condition\Combine',
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/ReaderTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/ReaderTest.php
index 274825a41ca5a..936ee8e20590e 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/ReaderTest.php
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/ReaderTest.php
@@ -116,10 +116,7 @@ public function testXmlConvertedConfigurationAndCompereStructure()
*/
protected function getActualContent()
{
- $files = $this->fileUtility->getFiles(
- [$this->fileUtility->getPathToSource() . static::ACTUAL],
- 'config.xml'
- );
+ $files = $this->fileUtility->getFiles([BP . static::ACTUAL], 'config.xml');
return file_get_contents(reset($files));
}
@@ -129,10 +126,7 @@ protected function getActualContent()
*/
protected function getExpectedContent()
{
- $files = $this->fileUtility->getFiles(
- [$this->fileUtility->getPathToSource() . static::EXPECTED],
- 'config.xml'
- );
+ $files = $this->fileUtility->getFiles([BP . static::EXPECTED], 'config.xml');
return file_get_contents(reset($files));
}
diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml b/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml
index 814a75cd06a4d..550aebc1c33d7 100644
--- a/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml
+++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/Config/Structure/Reader/_files/expected/config.xml
@@ -599,16 +599,30 @@
- Get Credentials from PayPal
-
-
-
+ Get Credentials from PayPal
+
+
+
+
Sandbox Credentials
-
+
+
+
+ NB9WWHYEMVUMS
+
+ Magento_Backend/web/images/logo-magento.png
+
+ FALSE
+
+ FALSE
+
+ embedded
+
+ pp_express
+
Magento\Paypal\Block\Adminhtml\System\Config\ApiWizard
-
1
diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php
index e6ba349fee089..1b67d126ac6e9 100644
--- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php
+++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php
@@ -17,7 +17,6 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase
*/
public function testSubmit()
{
- $this->markTestSkipped('Skipped because of MAGETWO-47215');
/**
* Preconditions:
* Load quote with Bundle product that has at least to child products
diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle.php
index 79d351914277d..833f08ee88214 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle.php
@@ -33,7 +33,10 @@
->setCategoryIds([2])
->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1])
->save();
-
+$productRepository = $objectManager->get(Magento\Catalog\Api\ProductRepositoryInterface::class);
+/**
+ * @var \Magento\Catalog\Model\Product $product
+ */
$product = $objectManager->create('Magento\Catalog\Model\Product');
$product
->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE)
@@ -96,24 +99,66 @@
]
],
]
- )
+ )->setCustomAttributes([
+ "price_type" => [
+ 'attribute_code' => 'price_type',
+ 'value' => \Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC
+ ],
+ "price_view" => [
+ "attribute_code" => "price_view",
+ "value" => "1",
+ ],
+ ])
->setCanSaveBundleSelections(true)
- ->setAffectBundleProductSelections(true)
- ->save();
+ ->setHasOptions(false)
+ ->setAffectBundleProductSelections(true);
+if ($product->getBundleOptionsData()) {
+ $options = [];
+ foreach ($product->getBundleOptionsData() as $key => $optionData) {
+ if (!(bool)$optionData['delete']) {
+ $option = $objectManager->create('Magento\Bundle\Api\Data\OptionInterfaceFactory')
+ ->create(['data' => $optionData]);
+ $option->setSku($product->getSku());
+ $option->setOptionId(null);
-//Load options
-$typeInstance = $product->getTypeInstance();
-$typeInstance->setStoreFilter($product->getStoreId(), $product);
-$optionCollection = $typeInstance->getOptionsCollection($product);
-$selectionCollection = $typeInstance->getSelectionsCollection($typeInstance->getOptionsIds($product), $product);
+ $links = [];
+ $bundleLinks = $product->getBundleSelectionsData();
+ if (!empty($bundleLinks[$key])) {
+ foreach ($bundleLinks[$key] as $linkData) {
+ if (!(bool)$linkData['delete']) {
+ /** @var \Magento\Bundle\Api\Data\LinkInterface$link */
+ $link = $objectManager->create('Magento\Bundle\Api\Data\LinkInterfaceFactory')
+ ->create(['data' => $linkData]);
+ $linkProduct = $productRepository->getById($linkData['product_id']);
+ $link->setSku($linkProduct->getSku());
+ $link->setQty($linkData['selection_qty']);
+ if (isset($linkData['selection_can_change_qty'])) {
+ $link->setCanChangeQuantity($linkData['selection_can_change_qty']);
+ }
+ $links[] = $link;
+ }
+ }
+ $option->setProductLinks($links);
+ $options[] = $option;
+ }
+ }
+ }
+ $extension = $product->getExtensionAttributes();
+ $extension->setBundleProductOptions($options);
+ $product->setExtensionAttributes($extension);
+}
+$productRepository->save($product);
+$product = $productRepository->get($product->getSku());
$bundleOptions = [];
$bundleOptionsQty = [];
/** @var $option \Magento\Bundle\Model\Option */
-foreach ($optionCollection as $option) {
- /** @var $selection \Magento\Bundle\Model\Selection */
- foreach ($selectionCollection as $selection) {
- $bundleOptions[$option->getId()][] = $selection->getSelectionId();
+foreach ($product->getExtensionAttributes()->getBundleProductOptions() as $option) {
+ foreach ($option->getProductLinks() as $selection) {
+ /**
+ * @var \Magento\Bundle\Api\Data\LinkInterface $selection
+ */
+ $bundleOptions[$option->getId()][] = $selection->getId();
$bundleOptionsQty[$option->getId()][] = 1;
}
}
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php
index 2d5e9026ceefe..cb8ee43f86cf3 100644
--- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php
+++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nCollectPhrasesCommandTest.php
@@ -75,4 +75,22 @@ public function testExecuteNonExistingPath()
]
);
}
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Directory path is not needed when --magento flag is set.
+ */
+ public function testExecuteMagentoFlagDirectoryPath()
+ {
+ $this->tester->execute(['directory' => 'a', '--magento' => true]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Directory path is needed when --magento flag is not set.
+ */
+ public function testExecuteNoMagentoFlagNoDirectoryPath()
+ {
+ $this->tester->execute([]);
+ }
}
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nPackCommandTest.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nPackCommandTest.php
index 6833e447bc13e..40f70f65c5192 100644
--- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nPackCommandTest.php
+++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/I18nPackCommandTest.php
@@ -30,9 +30,17 @@ public function setUp()
public function tearDown()
{
- if (file_exists(__DIR__ . '/_files/output/pack')) {
+ $this->removeCsv('A');
+ $this->removeCsv('B');
+ $this->removeCsv('C');
+ $this->removeCsv('D');
+ }
+
+ private function removeCsv($module)
+ {
+ if (file_exists(__DIR__ . "/_files/root/app/code/Magento/{$module}/i18n")) {
$helper = new \Magento\Framework\Backup\Filesystem\Helper();
- $helper->rm(__DIR__ . '/_files/output/pack', [], true);
+ $helper->rm(__DIR__ . "/_files/root/app/code/Magento/{$module}/i18n", [], true);
}
}
@@ -41,15 +49,13 @@ public function testExecute()
$this->tester->execute(
[
'source' => BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/i18n.csv',
- 'pack' => BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/output/pack',
'locale' => 'de_DE',
'--allow-duplicates' => true,
]
);
$this->assertEquals('Successfully saved de_DE language package.' . PHP_EOL, $this->tester->getDisplay());
- $basePath = BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/output/pack/'
- . 'dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code';
+ $basePath = BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/root/app/code';
$this->assertFileExists($basePath . '/Magento/A/i18n/de_DE.csv');
$this->assertFileExists($basePath . '/Magento/B/i18n/de_DE.csv');
$this->assertFileExists($basePath . '/Magento/C/i18n/de_DE.csv');
@@ -67,7 +73,6 @@ public function testExecuteNonExistingPath()
$this->tester->execute(
[
'source' => $nonExistPath,
- 'pack' => BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/output/pack',
'locale' => 'de_DE',
'--allow-duplicates' => true,
]
@@ -83,7 +88,6 @@ public function testExecuteInvalidMode()
$this->tester->execute(
[
'source' => BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/i18n.csv',
- 'pack' => BP . '/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/output/pack',
'locale' => 'de_DE',
'--allow-duplicates' => true,
'--mode' => 'invalid'
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/GeneratorTest.php b/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/GeneratorTest.php
index 5b467bf37a88a..2df0426e34bca 100644
--- a/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/GeneratorTest.php
+++ b/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Dictionary/GeneratorTest.php
@@ -104,6 +104,12 @@ public function testGenerationWithContext()
{
$this->generator->generate($this->source, $this->outputFileName, true);
- $this->assertFileEquals($this->expectedDir . '/with_context.csv', $this->outputFileName);
+ $expected = explode(PHP_EOL, file_get_contents($this->expectedDir . '/with_context.csv'));
+ $output = file_get_contents($this->outputFileName);
+ foreach ($expected as $line) {
+ if ($line) {
+ $this->assertContains($line, $output);
+ }
+ }
}
}
diff --git a/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Pack/GeneratorTest.php b/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Pack/GeneratorTest.php
index b9905d27bf4cb..218dd6890ce46 100644
--- a/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Pack/GeneratorTest.php
+++ b/dev/tests/integration/testsuite/Magento/Setup/Module/I18n/Pack/GeneratorTest.php
@@ -61,7 +61,6 @@ protected function setUp()
"/app/code/Magento/FirstModule/i18n/{$this->_locale}.csv",
"/app/code/Magento/SecondModule/i18n/{$this->_locale}.csv",
"/app/design/adminhtml/default/i18n/{$this->_locale}.csv",
- "/lib/web/i18n/{$this->_locale}.csv",
];
$this->_generator = ServiceLocator::getPackGenerator();
@@ -92,19 +91,20 @@ public function testGeneration()
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Magento_FirstModule',
- BP . '/app/code/Magento/FirstModule'
+ $this->_packPath . '/app/code/Magento/FirstModule'
);
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Magento_SecondModule',
- BP. '/app/code/Magento/SecondModule'
+ $this->_packPath. '/app/code/Magento/SecondModule'
);
ComponentRegistrar::register(
ComponentRegistrar::THEME,
'adminhtml/default',
- BP. '/app/design/adminhtml/default'
+ $this->_packPath. '/app/design/adminhtml/default'
);
- $this->_generator->generate($this->_dictionaryPath, $this->_packPath, $this->_locale);
+
+ $this->_generator->generate($this->_dictionaryPath, $this->_locale);
foreach ($this->_expectedFiles as $file) {
$this->assertFileEquals($this->_expectedDir . $file, $this->_packPath . $file);
diff --git a/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/BlockInstantiationTest.php b/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/BlockInstantiationTest.php
index 47e281a20d423..a896a632e8ba6 100644
--- a/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/BlockInstantiationTest.php
+++ b/dev/tests/integration/testsuite/Magento/Test/Integrity/Modular/BlockInstantiationTest.php
@@ -76,6 +76,7 @@ public function allBlocksDataProvider()
}
$templateBlocks = $this->_addBlock($module, $blockClass, $class, $templateBlocks);
}
+ asort($templateBlocks);
return $templateBlocks;
} catch (\Exception $e) {
trigger_error(
diff --git a/dev/tests/integration/testsuite/Magento/Vault/Model/VaultConfigMock.php b/dev/tests/integration/testsuite/Magento/Vault/Model/VaultConfigMock.php
deleted file mode 100644
index a5c0080127473..0000000000000
--- a/dev/tests/integration/testsuite/Magento/Vault/Model/VaultConfigMock.php
+++ /dev/null
@@ -1,46 +0,0 @@
-setId(null)->setAddressType('shipping');
+/** @var \Magento\Sales\Model\Order\Payment $payment */
$payment = $objectManager->create('Magento\Sales\Model\Order\Payment');
$payment->setMethod('checkmo');
@@ -65,6 +66,21 @@
$tokenString = 'asdfg';
$payment->setTransactionId('trx1');
$payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH);
-$payment->setTransactionAdditionalInfo('token', $tokenString);
+//$payment->setTransactionAdditionalInfo('token', $tokenString);
+
+
+/** @var \Magento\Vault\Model\PaymentToken $paymentToken */
+$paymentToken = $objectManager->create('Magento\Vault\Model\PaymentToken');
+$paymentToken->setCustomerId($customerIdFromFixture);
+$paymentToken->setGatewayToken($tokenString);
+$paymentToken->setPaymentMethodCode($payment->getMethod());
+$paymentToken->setCreatedAt('2015-12-08 18:06:10');
+
+/** @var \Magento\Sales\Api\Data\OrderPaymentExtensionFactory $orderPaymentExtensionFactory */
+$orderPaymentExtensionFactory = $objectManager->create('Magento\Sales\Api\Data\OrderPaymentExtensionFactory');
+$orderPaymentExtension = $orderPaymentExtensionFactory->create();
+$orderPaymentExtension->setVaultPaymentToken($paymentToken);
+$payment->setExtensionAttributes($orderPaymentExtension);
+
$order->save();
diff --git a/dev/tests/integration/testsuite/Magento/Vault/etc/di.php b/dev/tests/integration/testsuite/Magento/Vault/etc/di.php
index 1b537934038a7..b1015029a8854 100644
--- a/dev/tests/integration/testsuite/Magento/Vault/etc/di.php
+++ b/dev/tests/integration/testsuite/Magento/Vault/etc/di.php
@@ -5,5 +5,7 @@
*/
return [
- 'VaultPaymentConfig' => ['type' => 'Magento\Vault\Model\VaultConfigMock'],
+ 'preferences' => [
+ 'Magento\Vault\Model\VaultPaymentInterface' => 'Magento\Vault\Model\VaultPaymentMock',
+ ],
];
diff --git a/dev/tests/static/framework/Magento/TestFramework/Inspection/WordsFinder.php b/dev/tests/static/framework/Magento/TestFramework/Inspection/WordsFinder.php
index 9ee716602a8f6..0cf519d29a910 100644
--- a/dev/tests/static/framework/Magento/TestFramework/Inspection/WordsFinder.php
+++ b/dev/tests/static/framework/Magento/TestFramework/Inspection/WordsFinder.php
@@ -79,18 +79,27 @@ class WordsFinder
*/
protected $_baseDir;
+ /**
+ * Component Registrar
+ *
+ * @var \Magento\Framework\Component\ComponentRegistrar
+ */
+ protected $componentRegistrar;
+
/**
* @param string|array $configFiles
* @param string $baseDir
+ * @param \Magento\Framework\Component\ComponentRegistrar $componentRegistrar
* @param bool $isCopyrightChecked
* @throws \Magento\TestFramework\Inspection\Exception
*/
- public function __construct($configFiles, $baseDir, $isCopyrightChecked = false)
+ public function __construct($configFiles, $baseDir, $componentRegistrar, $isCopyrightChecked = false)
{
if (!is_dir($baseDir)) {
throw new \Magento\TestFramework\Inspection\Exception("Base directory {$baseDir} does not exist");
}
$this->_baseDir = str_replace('\\', '/', realpath($baseDir));
+ $this->componentRegistrar = $componentRegistrar;
// Load config files
if (!is_array($configFiles)) {
@@ -176,7 +185,15 @@ protected function _extractWhitelist(\SimpleXMLElement $configXml)
'A "path" must be defined for the whitelisted item'
);
}
- $path = $this->_baseDir . '/' . (string)$path[0];
+ $component = $node->xpath('component');
+ if ($component) {
+ $componentType = $component[0]->xpath('@type')[0];
+ $componentName = $component[0]->xpath('@name')[0];
+ $path = $this->componentRegistrar->getPath((string)$componentType, (string)$componentName)
+ . '/' . (string)$path[0];
+ } else {
+ $path = $this->_baseDir . '/' . (string)$path[0];
+ }
// Words
$words = [];
@@ -241,13 +258,12 @@ public function findWords($file)
protected function _findWords($file)
{
$checkContents = !$this->_isBinaryFile($file);
-
- $relPath = $this->_getRelPath($file);
+ $path = $this->getSearchablePath($file);
$contents = $checkContents ? file_get_contents($file) : '';
$foundWords = [];
foreach ($this->_words as $word) {
- if (stripos($relPath, $word) !== false || stripos($contents, $word) !== false) {
+ if (stripos($path, $word) !== false || stripos($contents, $word) !== false) {
$foundWords[] = $word;
}
}
@@ -314,13 +330,16 @@ protected function _removeWhitelistedWords($path, $foundWords)
}
/**
- * Return file path relative to base dir
+ * Return the path for words search
*
* @param string $file
* @return string
*/
- protected function _getRelPath($file)
+ protected function getSearchablePath($file)
{
+ if (strpos($file, $this->_baseDir) === false) {
+ return $file;
+ }
return substr($file, strlen($this->_baseDir) + 1);
}
}
diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Inspection/WordsFinderTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Inspection/WordsFinderTest.php
index 7ac952b65276a..cf6ede2e04635 100644
--- a/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Inspection/WordsFinderTest.php
+++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/TestFramework/Inspection/WordsFinderTest.php
@@ -5,6 +5,8 @@
*/
namespace Magento\TestFramework\Inspection;
+use Magento\Framework\Component\ComponentRegistrar;
+
class WordsFinderTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -15,7 +17,7 @@ class WordsFinderTest extends \PHPUnit_Framework_TestCase
*/
public function testConstructorException($configFile, $baseDir)
{
- new \Magento\TestFramework\Inspection\WordsFinder($configFile, $baseDir);
+ new \Magento\TestFramework\Inspection\WordsFinder($configFile, $baseDir, new ComponentRegistrar());
}
public function constructorExceptionDataProvider()
@@ -40,7 +42,8 @@ public function testFindWords($configFiles, $file, $expected)
{
$wordsFinder = new \Magento\TestFramework\Inspection\WordsFinder(
$configFiles,
- __DIR__ . '/_files/words_finder'
+ __DIR__ . '/_files/words_finder',
+ new ComponentRegistrar()
);
$actual = $wordsFinder->findWords($file);
$this->assertEquals($expected, $actual);
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php
index 5d2b0626b4b4b..04c90dacf004e 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFiles.php
@@ -25,7 +25,7 @@ protected function setUp()
*/
public function getLocalePlacePath()
{
- $pathToSource = \Magento\Framework\App\Utility\Files::init()->getPathToSource();
+ $pathToSource = BP;
$places = [];
$componentRegistrar = new ComponentRegistrar();
foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $modulePath) {
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFilesTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFilesTest.php
index b5409544a60cd..b096322e8169c 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFilesTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/App/Language/TranslationFilesTest.php
@@ -52,7 +52,7 @@ public function defaultLocaleDataProvider()
$parser = $this->prepareParser();
$optionResolverFactory = new ResolverFactory();
- $optionResolver = $optionResolverFactory->create(Files::init()->getPathToSource(), true);
+ $optionResolver = $optionResolverFactory->create(BP, true);
$parser->parse($optionResolver->getOptions());
@@ -80,8 +80,7 @@ public function defaultLocaleDataProvider()
protected function buildFilePath($phrase, $context)
{
$path = $this->getContext()->buildPathToLocaleDirectoryByContext($phrase->getContextType(), $context);
- $sourcePath = Files::init()->getPathToSource();
- return $sourcePath . '/' . $path . Locale::DEFAULT_SYSTEM_LOCALE . '.' . Csv::FILE_EXTENSION;
+ return $path . Locale::DEFAULT_SYSTEM_LOCALE . '.' . Csv::FILE_EXTENSION;
}
/**
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php
index bae290d83ff8e..4d08ff438ea1e 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php
@@ -209,11 +209,7 @@ public function testClassNamespaces()
* @param array $file
*/
function ($file) {
- $relativePath = str_replace(
- Files::init()->getPathToSource() . "/",
- "",
- $file
- );
+ $relativePath = str_replace(BP . "/", "", $file);
// exceptions made for fixture files from tests
if (strpos($relativePath, '/_files/') !== false) {
return;
@@ -291,11 +287,7 @@ public function testClassReferences()
* @param string $file
*/
function ($file) {
- $relativePath = str_replace(
- Files::init()->getPathToSource(),
- "",
- $file
- );
+ $relativePath = str_replace(BP, "", $file);
// Due to the examples given with the regex patterns, we skip this test file itself
if ($relativePath == "/dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php") {
return;
@@ -575,7 +567,7 @@ private function removeSpecialCasesForAllOthers($componentRegistrar, $namespaceP
'/dev/tests/static/testsuite/',
'/setup/src/',
];
- $pathToSource = Files::init()->getPathToSource();
+ $pathToSource = BP;
$libraryPaths = $this->getLibraryPaths($componentRegistrar, $pathToSource);
$directories = array_merge($directories, $libraryPaths);
// Full list of directories where there may be namespace classes
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php
index 7391f2f0727ae..085270afadeab 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/ComposerTest.php
@@ -53,7 +53,7 @@ public static function setUpBeforeClass()
}
self::$shell = self::createShell();
self::$isComposerAvailable = self::isComposerAvailable();
- self::$root = Files::init()->getPathToSource();
+ self::$root = BP;
self::$rootJson = json_decode(file_get_contents(self::$root . '/composer.json'), true);
self::$dependencies = [];
}
@@ -84,7 +84,7 @@ function ($dir, $packageType) {
*/
public function validateComposerJsonDataProvider()
{
- $root = \Magento\Framework\App\Utility\Files::init()->getPathToSource();
+ $root = BP;
$componentRegistrar = new ComponentRegistrar();
$result = [];
foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $dir) {
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php
index 673a6ffe87b94..e21884aecb8e9 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/DependencyTest.php
@@ -143,7 +143,7 @@ class DependencyTest extends \PHPUnit_Framework_TestCase
*/
public static function setUpBeforeClass()
{
- $root = Files::init()->getPathToSource();
+ $root = BP;
$rootJson = json_decode(file_get_contents($root . '/composer.json'), true);
if (preg_match('/magento\/project-*/', $rootJson['name']) == 1) {
@@ -274,23 +274,24 @@ public function testUndeclared()
*/
function ($fileType, $file) {
// Validates file when it is belonged to default themes
- $filename = self::_getRelativeFilename($file);
- $isThemeFile = (bool)preg_match(self::$_defaultThemes, $filename);
-
$componentRegistrar = new ComponentRegistrar();
- $foundModuleName = '';
- if (!$isThemeFile) {
- foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $moduleDir) {
- if (strpos($file, $moduleDir . '/') !== false) {
- $foundModuleName = str_replace('_', '\\', $moduleName);
- break;
- }
- }
- if (empty($foundModuleName)) {
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::THEME) as $themeDir) {
+ if (strpos($file, $themeDir . '/') !== false) {
return;
}
}
+ $foundModuleName = '';
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $moduleDir) {
+ if (strpos($file, $moduleDir . '/') !== false) {
+ $foundModuleName = str_replace('_', '\\', $moduleName);
+ break;
+ }
+ }
+ if (empty($foundModuleName)) {
+ return;
+ }
+
$module = $foundModuleName;
$contents = $this->_getCleanedFileContents($fileType, $file);
@@ -435,19 +436,6 @@ public function testRedundant()
}
}
- /**
- * Extract Magento relative filename from absolute filename
- *
- * @param string $absoluteFilename
- * @return string
- */
- protected static function _getRelativeFilename($absoluteFilename)
- {
- $pathToSource = Files::init()->getPathToSource();
- $relativeFileName = str_replace($pathToSource, '', $absoluteFilename);
- return trim(str_replace('\\', '/', $relativeFileName), '/');
- }
-
/**
* Convert file list to data provider structure
*
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Di/CompilerTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Di/CompilerTest.php
index 3678497fafab1..3c3878f4906fa 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Di/CompilerTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Di/CompilerTest.php
@@ -9,6 +9,7 @@
use Magento\Framework\Api\Code\Generator\Mapper;
use Magento\Framework\Api\Code\Generator\SearchResults;
+use Magento\Framework\Component\ComponentRegistrar;
use Magento\Framework\ObjectManager\Code\Generator\Converter;
use Magento\Framework\ObjectManager\Code\Generator\Factory;
use Magento\Framework\ObjectManager\Code\Generator\Repository;
@@ -66,7 +67,7 @@ class CompilerTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->_shell = new \Magento\Framework\Shell(new \Magento\Framework\Shell\CommandRenderer());
- $basePath = Files::init()->getPathToSource();
+ $basePath = BP;
$basePath = str_replace('\\', '/', $basePath);
@@ -195,25 +196,27 @@ protected function _classExistsAsReal($instanceName)
*/
protected function _phpClassesDataProvider()
{
- $basePath = Files::init()->getPathToSource();
-
- $libPath = 'lib\\internal';
- $appPath = 'app\\code';
- $generationPathPath = str_replace('/', '\\', str_replace($basePath . '/', '', $this->_generationDir));
+ $generationPath = str_replace('/', '\\', $this->_generationDir);
$files = Files::init()->getPhpFiles(Files::INCLUDE_APP_CODE | Files::INCLUDE_LIBS);
- $patterns = [
- '/' . preg_quote($libPath) . '/',
- '/' . preg_quote($appPath) . '/',
- '/' . preg_quote($generationPathPath) . '/',
- ];
- $replacements = ['', '', ''];
+ $patterns = ['/' . preg_quote($generationPath) . '/',];
+ $replacements = [''];
+
+ $componentRegistrar = new ComponentRegistrar();
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $modulePath) {
+ $patterns[] = '/' . preg_quote(str_replace('/', '\\', $modulePath)) . '/';
+ $replacements[] = '\\' . str_replace('_', '\\', $moduleName);
+ }
+
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::LIBRARY) as $libPath) {
+ $patterns[] = '/' . preg_quote(str_replace('/', '\\', $libPath)) . '/';
+ $replacements[] = '\\Magento\\Framework';
+ }
/** Convert file names into class name format */
$classes = [];
foreach ($files as $file) {
- $file = str_replace($basePath . '/', '', $file);
$file = str_replace('/', '\\', $file);
$filePath = preg_replace($patterns, $replacements, $file);
$className = substr($filePath, 0, -4);
@@ -258,10 +261,7 @@ protected function _buildInheritanceHierarchyTree($className, array $allowedFile
$parent = $class->getParentClass();
$file = false;
if ($parent) {
- $basePath = Files::init()->getPathToSource();
$file = str_replace('\\', DIRECTORY_SEPARATOR, $parent->getFileName());
- $basePath = str_replace('\\', DIRECTORY_SEPARATOR, $basePath);
- $file = str_replace($basePath . DIRECTORY_SEPARATOR, '', $file);
}
/** Prevent analysis of non Magento classes */
if ($parent && in_array($file, $allowedFiles)) {
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php
index a81176dbee21c..fbeb4fa665f97 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/HhvmCompatibilityTest.php
@@ -72,7 +72,7 @@ protected function getFiles()
| Files::INCLUDE_NON_CLASSES
),
Files::init()->getPhtmlFiles(false, false),
- Files::init()->getFiles([Files::init()->getPathToSource() . '/dev/'], '*.php')
+ Files::init()->getFiles([BP . '/dev/'], '*.php')
);
}
@@ -95,10 +95,9 @@ protected function parseDirectives($file)
*/
protected function createMessage($deniedDirectives)
{
- $rootPath = Files::init()->getPathToSource();
$message = 'HHVM-incompatible ini_get/ini_set options were found:';
foreach ($deniedDirectives as $file => $fileDeniedDirectives) {
- $message .= "\n" . str_replace($rootPath, '', $file) . ': [' . implode(', ', $fileDeniedDirectives) . ']';
+ $message .= "\n" . $file . ': [' . implode(', ', $fileDeniedDirectives) . ']';
}
return $message;
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Library/DependencyTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Library/DependencyTest.php
index 7cc87d570344c..b2ef80867c9a5 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Library/DependencyTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Library/DependencyTest.php
@@ -79,18 +79,21 @@ function ($file) {
public function testAppCodeUsage()
{
$files = Files::init();
- $path = $files->getPathToSource();
+ $componentRegistrar = new ComponentRegistrar();
+ $libPaths = $componentRegistrar->getPaths(ComponentRegistrar::LIBRARY);
$invoker = new AggregateInvoker($this);
$invoker(
- function ($file) use ($path) {
+ function ($file) use ($libPaths) {
$content = file_get_contents($file);
- if (strpos($file, $path . '/lib/') === 0) {
- $this->assertSame(
- 0,
- preg_match('~(?|function\\s)__\\s*\\(~iS', $content),
- 'Function __() is defined outside of the library and must not be used there. ' .
- 'Replacement suggestion: new \\Magento\\Framework\\Phrase()'
- );
+ foreach ($libPaths as $libPath) {
+ if (strpos($file, $libPath) === 0) {
+ $this->assertSame(
+ 0,
+ preg_match('~(?|function\\s)__\\s*\\(~iS', $content),
+ 'Function __() is defined outside of the library and must not be used there. ' .
+ 'Replacement suggestion: new \\Magento\\Framework\\Phrase()'
+ );
+ }
}
},
$files->getPhpFiles(
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Phrase/AbstractTestCase.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Phrase/AbstractTestCase.php
index 6d062cc46bc49..89b5070fe07de 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/Phrase/AbstractTestCase.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Phrase/AbstractTestCase.php
@@ -9,6 +9,7 @@
*/
namespace Magento\Test\Integrity\Phrase;
+use Magento\Framework\Component\ComponentRegistrar;
use Magento\Setup\Module\I18n\FilesCollector;
class AbstractTestCase extends \PHPUnit_Framework_TestCase
@@ -36,10 +37,14 @@ protected function _createMissedPhraseError($phrase)
*/
protected function _getFiles()
{
- $filesCollector = new \Magento\Setup\Module\I18n\FilesCollector();
-
+ $filesCollector = new FilesCollector();
+ $componentRegistrar = new ComponentRegistrar();
+ $paths = array_merge(
+ $componentRegistrar->getPaths(ComponentRegistrar::MODULE),
+ $componentRegistrar->getPaths(ComponentRegistrar::LIBRARY)
+ );
return $filesCollector->getFiles(
- [\Magento\Framework\App\Utility\Files::init()->getPathToSource()],
+ $paths,
'/\.(php|phtml)$/'
);
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/TestPlacementTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/TestPlacementTest.php
index 9cc806fa91028..81e66f1c51c34 100644
--- a/dev/tests/static/testsuite/Magento/Test/Integrity/TestPlacementTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Integrity/TestPlacementTest.php
@@ -24,7 +24,7 @@ class TestPlacementTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
- $this->root = Files::init()->getPathToSource();
+ $this->root = BP;
}
public function testUnitTestFilesPlacement()
diff --git a/dev/tests/static/testsuite/Magento/Test/Js/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Js/LiveCodeTest.php
index 94913c98be5ad..1894917502382 100644
--- a/dev/tests/static/testsuite/Magento/Test/Js/LiveCodeTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Js/LiveCodeTest.php
@@ -58,7 +58,7 @@ protected static function _scanJsFile($path)
*/
public static function setUpBeforeClass()
{
- $reportDir = Files::init()->getPathToSource() . '/dev/tests/static/report';
+ $reportDir = BP . '/dev/tests/static/report';
if (!is_dir($reportDir)) {
mkdir($reportDir, 0770);
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt
index b78c57607c0ec..9e71665b5e1d6 100644
--- a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt
@@ -1055,3 +1055,4 @@ vendor/magento/theme-adminhtml-backend/web/js/theme.js
vendor/magento/theme-frontend-blank/web/js/navigation-menu.js
vendor/magento/theme-frontend-blank/web/js/responsive.js
vendor/magento/theme-frontend-blank/web/js/theme.js
+app/code/Magento/BraintreeTwo/view/frontend/requirejs-config.js
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php
index d3fe7736e7f60..bb025beb6f444 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/FilesystemTest.php
@@ -22,7 +22,7 @@ public function testRelocations()
*/
function ($path) {
$this->assertFileNotExists(
- \Magento\Framework\App\Utility\Files::init()->getPathToSource() . '/' . $path
+ BP . '/' . $path
);
},
$this->relocationsDataProvider()
@@ -58,19 +58,22 @@ public function relocationsDataProvider()
public function testObsoleteDirectories()
{
- $area = '*';
- $theme = '*';
- $root = \Magento\Framework\App\Utility\Files::init()->getPathToSource();
- $dirs = glob("{$root}/app/design/{$area}/{$theme}/template", GLOB_ONLYDIR);
+ $componentRegistrar = new ComponentRegistrar();
+ $dirs = [];
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::THEME) as $path) {
+ $dirs = array_merge($dirs, glob($path . '/template', GLOB_ONLYDIR));
+ }
$msg = [];
if ($dirs) {
$msg[] = 'Theme "template" directories are obsolete. Relocate files as follows:';
foreach ($dirs as $dir) {
- $msg[] = str_replace($root, '', "{$dir} => " . realpath($dir . '/..') . '/Namespace_Module/*');
+ $msg[] = "{$dir} => " . realpath($dir . '/..') . '/Namespace_Module/*';
}
}
-
- $dirs = glob("{$root}/app/design/{$area}/{$theme}/layout", GLOB_ONLYDIR);
+ $dirs = [];
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::THEME) as $path) {
+ $dirs = array_merge($dirs, glob($path . '/layout', GLOB_ONLYDIR));
+ }
if ($dirs) {
$msg[] = 'Theme "layout" directories are obsolete. Relocate layout files into the root of theme directory.';
$msg = array_merge($msg, $dirs);
@@ -86,26 +89,26 @@ public function testObsoleteViewPaths()
$allowedFiles = ['requirejs-config.js', 'layouts.xml'];
$allowedThemeFiles = array_merge(
$allowedFiles,
- ['composer.json', 'theme.xml', 'LICENSE.txt', 'LICENSE_AFL.txt']
+ ['composer.json', 'theme.xml', 'LICENSE.txt', 'LICENSE_EE.txt', 'LICENSE_AFL.txt', 'registration.php']
);
$areas = '{frontend,adminhtml,base}';
- $ns = '*';
- $mod = '*';
- $pathsToCheck = [
- BP . "/app/design/{$areas}/{$ns}/{$mod}/*" => [
+ $componentRegistrar = new ComponentRegistrar();
+ $pathsToCheck = [];
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::THEME) as $themeDir) {
+ $pathsToCheck[$themeDir . '/*'] = [
'allowed_files' => $allowedThemeFiles,
'allowed_dirs' => ['layout', 'page_layout', 'templates', 'web', 'etc', 'i18n', 'media', '\w+_\w+'],
- ],
- BP . "app/design/{$areas}/{$ns}/{$mod}/{$ns}_{$mod}/*" => [
+ ];
+ $pathsToCheck[$themeDir . '/*_*/*'] = [
'allowed_files' => $allowedThemeFiles,
- 'allowed_dirs' => ['layout', 'page_layout', 'templates', 'web'],
- ],
- ];
- $componentRegistrar = new ComponentRegistrar();
+ 'allowed_dirs' => ['layout', 'page_layout', 'templates', 'web', 'email'],
+ ];
+ }
+
foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleDir) {
$pathsToCheck[$moduleDir . "/view/{$areas}/*"] = [
'allowed_files' => $allowedFiles,
- 'allowed_dirs' => ['layout', 'page_layout', 'templates', 'web']
+ 'allowed_dirs' => ['layout', 'page_layout', 'templates', 'web', 'ui_component', 'email']
];
}
$errors = [];
@@ -114,7 +117,7 @@ public function testObsoleteViewPaths()
$allowedDirs = $allowed['allowed_dirs'];
$foundFiles = glob($path, GLOB_BRACE);
if (!$foundFiles) {
- $this->fail("Glob pattern returned empty result: {$path}");
+ continue;
}
foreach ($foundFiles as $file) {
$baseName = basename($file);
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/LibraryLocationTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/LibraryLocationTest.php
index 9f09259a3da34..4c456327ef8c3 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/LibraryLocationTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/LibraryLocationTest.php
@@ -20,7 +20,7 @@ class LibraryLocationTest extends \PHPUnit_Framework_TestCase
public static function setUpBeforeClass()
{
- self::$root = \Magento\Framework\App\Utility\Files::init()->getPathToSource();
+ self::$root = BP;
}
public function testOldWebLibrariesLocation()
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/LicenseTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/LicenseTest.php
index 2e1d4a214f858..1b270f3fe731a 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/LicenseTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/LicenseTest.php
@@ -37,29 +37,13 @@ function ($filename) {
public function legacyCommentDataProvider()
{
- $root = \Magento\Framework\App\Utility\Files::init()->getPathToSource();
- $recursiveIterator = new \RecursiveIteratorIterator(
- new \RecursiveDirectoryIterator($root, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS)
- );
-
- $rootFolderName = substr(strrchr($root, '/'), 1);
- $extensions = '(xml|css|php|phtml|js|dist|sample|additional)';
- $paths = [
- $rootFolderName . '/[^/]+\.' . $extensions,
- $rootFolderName . '/app/.+\.' . $extensions,
- $rootFolderName . '/dev/(?!tests/integration/tmp|tests/functional).+\.' . $extensions,
- $rootFolderName . '/lib/internal/(Mage|Magento|Varien)/.+\.' . $extensions,
- $rootFolderName . '/pub/.+\.' . $extensions,
- ];
- $regexIterator = new \RegexIterator($recursiveIterator, '#(' . implode(' | ', $paths) . ')$#x');
-
+ $allFiles = \Magento\Framework\App\Utility\Files::init()->getAllFiles();
$result = [];
- foreach ($regexIterator as $fileInfo) {
- $filename = (string)$fileInfo;
- if (!file_exists($filename) || !is_readable($filename)) {
+ foreach ($allFiles as $file) {
+ if (!file_exists($file[0]) || !is_readable($file[0])) {
continue;
}
- $result[] = [$filename];
+ $result[] = [$file[0]];
}
return $result;
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php
index 813aababf3b6b..2fd1427270d33 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php
@@ -12,6 +12,7 @@
use Magento\Framework\App\Utility\Files;
use Magento\Framework\App\Utility\AggregateInvoker;
+use Magento\Framework\Component\ComponentRegistrar;
use Magento\TestFramework\Utility\ChangedFiles;
/**
@@ -111,7 +112,7 @@ public function testPhpFiles()
$changedFiles = ChangedFiles::getPhpFiles(__DIR__ . '/_files/changed_files*');
$blacklistFiles = $this->getBlacklistFiles();
foreach ($blacklistFiles as $blacklistFile) {
- unset($changedFiles[$blacklistFile]);
+ unset($changedFiles[BP . $blacklistFile]);
}
$invoker(
function ($file) {
@@ -289,7 +290,7 @@ protected function _testObsoleteMethods($content, $file)
}
/**
- * Assert that obsolete pathes are not used in the content
+ * Assert that obsolete paths are not used in the content
*
* This method will search the content for references to class
* that start with obsolete namespace
@@ -300,7 +301,7 @@ protected function _testObsoletePaths($file)
{
foreach (self::$_paths as $row) {
list($obsoletePath, , $replacementPath) = $row;
- $relativePath = str_replace(Files::init()->getPathToSource(), "", $file);
+ $relativePath = str_replace(BP, '', $file);
$message = $this->_suggestReplacement(
"Path '{$obsoletePath}' is obsolete.",
$replacementPath
@@ -324,13 +325,16 @@ protected function _testObsoletePaths($file)
*/
protected function _testGetChildSpecialCase($content, $file)
{
- if (0 === strpos($file, Files::init()->getPathToSource() . '/app/')) {
- $this->_assertNotRegexp(
- '/[^a-z\d_]getChild\s*\(/iS',
- $content,
- 'Block method getChild() is obsolete. ' .
- 'Replacement suggestion: \Magento\Framework\View\Element\AbstractBlock::getChildBlock()'
- );
+ $componentRegistrar = new ComponentRegistrar();
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $modulePath) {
+ if (0 === strpos($file, $modulePath)) {
+ $this->_assertNotRegexp(
+ '/[^a-z\d_]getChild\s*\(/iS',
+ $content,
+ 'Block method getChild() is obsolete. ' .
+ 'Replacement suggestion: \Magento\Framework\View\Element\AbstractBlock::getChildBlock()'
+ );
+ }
}
}
@@ -933,7 +937,7 @@ private function getBlacklistFiles($absolutePath = false)
{
$blackList = include __DIR__ . '/_files/blacklist/obsolete_mage.php';
$ignored = [];
- $appPath = Files::init()->getPathToSource();
+ $appPath = BP;
foreach ($blackList as $file) {
if ($absolutePath) {
$ignored = array_merge($ignored, glob($appPath . DIRECTORY_SEPARATOR . $file, GLOB_NOSORT));
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteConnectionTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteConnectionTest.php
index 9fe3039599956..2adede623a62a 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteConnectionTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteConnectionTest.php
@@ -3,9 +3,10 @@
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-
namespace Magento\Test\Legacy;
+use Magento\Framework\Component\ComponentRegistrar;
+
/**
* Temporary test
* Test verifies obsolete usages in modules that were refactored to work with getConnection.
@@ -34,7 +35,6 @@ class ObsoleteConnectionTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
- $this->appPath = \Magento\Framework\App\Utility\Files::init()->getPathToSource();
$this->obsoleteMethods = [
'_getReadConnection',
'_getWriteConnection',
@@ -106,13 +106,15 @@ function ($file) {
public function modulesFilesDataProvider()
{
$filesList = [];
-
- foreach ($this->getFilesData('whitelist/refactored_modules*') as $refactoredFolder) {
- $files = \Magento\Framework\App\Utility\Files::init()->getFiles(
- [$this->appPath . $refactoredFolder],
- '*.php'
- );
- $filesList = array_merge($filesList, $files);
+ $componentRegistrar = new ComponentRegistrar();
+ foreach ($this->getFilesData('whitelist/refactored_modules*') as $refactoredModule) {
+ if ($componentRegistrar->getPath(ComponentRegistrar::MODULE, $refactoredModule)) {
+ $files = \Magento\Framework\App\Utility\Files::init()->getFiles(
+ [$componentRegistrar->getPath(ComponentRegistrar::MODULE, $refactoredModule)],
+ '*.php'
+ );
+ $filesList = array_merge($filesList, $files);
+ }
}
$result = array_map('realpath', $filesList);
@@ -126,8 +128,10 @@ public function modulesFilesDataProvider()
protected function getBlackList()
{
$blackListFiles = [];
- foreach ($this->getFilesData('blacklist/files_list*') as $file) {
- $blackListFiles[] = realpath($this->appPath . $file);
+ $componentRegistrar = new ComponentRegistrar();
+ foreach ($this->getFilesData('blacklist/files_list*') as $fileInfo) {
+ $blackListFiles[] = $componentRegistrar->getPath(ComponentRegistrar::MODULE, $fileInfo[0])
+ . DIRECTORY_SEPARATOR . $fileInfo[1];
}
return $blackListFiles;
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteResponseTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteResponseTest.php
index 73282abd58718..b35780fa22708 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteResponseTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteResponseTest.php
@@ -3,9 +3,10 @@
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-
namespace Magento\Test\Legacy;
+use Magento\Framework\Component\ComponentRegistrar;
+
/**
* Temporary test that will be removed in scope of MAGETWO-28356.
* Test verifies obsolete usages in modules that were refactored to work with ResultInterface.
@@ -29,7 +30,6 @@ class ObsoleteResponseTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
- $this->appPath = \Magento\Framework\App\Utility\Files::init()->getPathToSource();
$this->obsoleteMethods = include __DIR__ . '/_files/response/obsolete_response_methods.php';
$this->filesBlackList = $this->getBlackList();
}
@@ -64,13 +64,15 @@ function ($file) {
public function modulesFilesDataProvider()
{
$filesList = [];
-
- foreach ($this->getFilesData('whitelist/refactored_modules*') as $refactoredFolder) {
- $files = \Magento\Framework\App\Utility\Files::init()->getFiles(
- [$this->appPath . $refactoredFolder],
- '*.php'
- );
- $filesList = array_merge($filesList, $files);
+ $componentRegistrar = new ComponentRegistrar();
+ foreach ($this->getFilesData('whitelist/refactored_modules*') as $refactoredModule) {
+ if ($componentRegistrar->getPath(ComponentRegistrar::MODULE, $refactoredModule)) {
+ $files = \Magento\Framework\App\Utility\Files::init()->getFiles(
+ [$componentRegistrar->getPath(ComponentRegistrar::MODULE, $refactoredModule)],
+ '*.php'
+ );
+ $filesList = array_merge($filesList, $files);
+ }
}
$result = array_map('realpath', $filesList);
@@ -84,8 +86,10 @@ public function modulesFilesDataProvider()
protected function getBlackList()
{
$blackListFiles = [];
- foreach ($this->getFilesData('blacklist/files_list*') as $file) {
- $blackListFiles[] = realpath($this->appPath . $file);
+ $componentRegistrar = new ComponentRegistrar();
+ foreach ($this->getFilesData('blacklist/files_list*') as $fileInfo) {
+ $blackListFiles[] = $componentRegistrar->getPath(ComponentRegistrar::MODULE, $fileInfo[0])
+ . DIRECTORY_SEPARATOR . $fileInfo[1];
}
return $blackListFiles;
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php
index 12b052cab56f1..cb6e9e69d8288 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php
@@ -9,6 +9,8 @@
*/
namespace Magento\Test\Legacy;
+use Magento\Framework\Component\ComponentRegistrar;
+
class RestrictedCodeTest extends \PHPUnit_Framework_TestCase
{
/**@#+
@@ -47,7 +49,7 @@ protected static function _loadData(array &$data, $filePattern)
$relativePath = str_replace(
'\\',
'/',
- str_replace(\Magento\Framework\App\Utility\Files::init()->getPathToSource(), '', $file)
+ str_replace(BP, '', $file)
);
array_push(self::$_fixtureFiles, $relativePath);
$data = array_merge_recursive($data, self::_readList($file));
@@ -74,8 +76,8 @@ public function testPhpFiles()
$invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
$testFiles = \Magento\TestFramework\Utility\ChangedFiles::getPhpFiles(__DIR__ . '/_files/changed_files*');
foreach (self::$_fixtureFiles as $fixtureFile) {
- if (array_key_exists($fixtureFile, $testFiles)) {
- unset($testFiles[$fixtureFile]);
+ if (array_key_exists(BP . $fixtureFile, $testFiles)) {
+ unset($testFiles[BP . $fixtureFile]);
}
}
$invoker(
@@ -95,33 +97,24 @@ function ($file) {
protected function _testRestrictedClasses($file)
{
$content = file_get_contents($file);
+ $componentRegistrar = new ComponentRegistrar();
foreach (self::$_classes as $restrictedClass => $classRules) {
- foreach ($classRules['exclude'] as $skippedPath) {
- if ($this->_isFileInPath($skippedPath, $file)) {
+ foreach ($classRules['exclude'] as $skippedPathInfo) {
+ $skippedPath = $componentRegistrar->getPath($skippedPathInfo['type'], $skippedPathInfo['name'])
+ . '/' . $skippedPathInfo['path'];
+ if (strpos($file, $skippedPath) === 0) {
continue 2;
}
}
$this->assertFalse(
\Magento\TestFramework\Utility\CodeCheck::isClassUsed($restrictedClass, $content),
sprintf(
- "Class '%s' is restricted. Suggested replacement: %s",
+ "Class '%s' is restricted in %s. Suggested replacement: %s",
$restrictedClass,
+ $file,
$classRules['replacement']
)
);
}
}
-
- /**
- * Checks if the file path (relative to Magento folder) starts with the given path
- *
- * @param string $subPath
- * @param string $file
- * @return bool
- */
- protected function _isFileInPath($subPath, $file)
- {
- $relativePath = str_replace(\Magento\Framework\App\Utility\Files::init()->getPathToSource(), '', $file);
- return 0 === strpos($relativePath, $subPath);
- }
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/WordsTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/WordsTest.php
index d70e846742640..0b8b92e00c79e 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/WordsTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/WordsTest.php
@@ -9,6 +9,8 @@
*/
namespace Magento\Test\Legacy;
+use Magento\Framework\Component\ComponentRegistrar;
+
class WordsTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -20,7 +22,8 @@ public static function setUpBeforeClass()
{
self::$_wordsFinder = new \Magento\TestFramework\Inspection\WordsFinder(
glob(__DIR__ . '/_files/words_*.xml'),
- \Magento\Framework\App\Utility\Files::init()->getPathToSource()
+ BP,
+ new ComponentRegistrar()
);
}
@@ -32,7 +35,7 @@ public function testWords()
* @param string $file
*/
function ($file) {
- $words = self::$_wordsFinder->findWords($file);
+ $words = self::$_wordsFinder->findWords(realpath($file));
if ($words) {
$this->fail("Found words: '" . implode("', '", $words) . "' in '{$file}' file");
}
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/blacklist/files_list.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/blacklist/files_list.php
index 7b4ddc53272ae..faa315fdb70ed 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/blacklist/files_list.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/blacklist/files_list.php
@@ -8,11 +8,11 @@
* Files that excluded from results
*/
return [
- '/app/code/Magento/AdvancedPricingImportExport/Test/Unit/Model/Export/AdvancedPricingTest.php',
- '/app/code/Magento/AdvancedPricingImportExport/Model/Export/AdvancedPricing.php',
- '/app/code/Magento/CatalogImportExport/Test/Unit/Model/Export/ProductTest.php',
- '/app/code/Magento/CatalogImportExport/Model/Export/Product.php',
- '/app/code/Magento/EncryptionKey/Controller/Adminhtml/Crypt/Key/Index.php',
- '/app/code/Magento/EncryptionKey/Model/Resource/Key/Change.php',
- //example '/app/code/Magento/Backend/Model/View.php',
+ ['Magento_AdvancedPricingImportExport', 'Test/Unit/Model/Export/AdvancedPricingTest.php'],
+ ['Magento_AdvancedPricingImportExport', 'Model/Export/AdvancedPricing.php'],
+ ['Magento_CatalogImportExport', 'Test/Unit/Model/Export/ProductTest.php'],
+ ['Magento_CatalogImportExport' , 'Model/Export/Product.php'],
+ ['Magento_EncryptionKey', 'Controller/Adminhtml/Crypt/Key/Index.php'],
+ ['Magento_EncryptionKey', 'Model/Resource/Key/Change.php'],
+ //example ['Magento_Backend', 'Model/View.php'],
];
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/whitelist/refactored_modules.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/whitelist/refactored_modules.php
index 784541bfad676..82dbce0e2c366 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/whitelist/refactored_modules.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/connection/whitelist/refactored_modules.php
@@ -8,18 +8,18 @@
* Modules that were refactored
*/
return [
- '/app/code/Magento/AdminNotification',
- '/app/code/Magento/AdvancedPricingImportExport',
- '/app/code/Magento/Authorization',
- '/app/code/Magento/Authorizenet',
- '/app/code/Magento/Backend',
- '/app/code/Magento/Captcha',
- '/app/code/Magento/Catalog',
- '/app/code/Magento/CatalogImportExport',
- '/app/code/Magento/CatalogInventory',
- '/app/code/Magento/CatalogRule',
- '/app/code/Magento/CatalogSearch',
- '/app/code/Magento/CatalogUrlRewrite',
- '/app/code/Magento/CatalogWidget',
- // example '/app/code/Magento/Catalog',
+ 'Magento_AdminNotification',
+ 'Magento_AdvancedPricingImportExport',
+ 'Magento_Authorization',
+ 'Magento_Authorizenet',
+ 'Magento_Backend',
+ 'Magento_Captcha',
+ 'Magento_Catalog',
+ 'Magento_CatalogImportExport',
+ 'Magento_CatalogInventory',
+ 'Magento_CatalogRule',
+ 'Magento_CatalogSearch',
+ 'Magento_CatalogUrlRewrite',
+ 'Magento_CatalogWidget',
+ // example 'Magento_Catalog',
];
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
index 0777e3e2b5287..5d5b4ccb0a025 100644
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
+++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php
@@ -2505,4 +2505,12 @@
['get', 'Magento\Quote\Api\ShippingMethodManagementInterface', 'Magento\Quote\Model\ShippingMethodManagementInterface::get'],
['set', 'Magento\Quote\Api\ShippingMethodManagementInterface', 'Magento\Quote\Model\ShippingMethodManagementInterface::get'],
['getTypeSwitcherData', 'Magento\Catalog\Block\Adminhtml\Product'],
+ ['_afterLoad', 'Magento\CatalogRule\Model\ResourceModel\Rule'],
+ ['_afterSave', 'Magento\CatalogRule\Model\ResourceModel\Rule'],
+ ['_beforeDelete', 'Magento\Cms\Model\ResourceModel\Page'],
+ ['_afterSave', 'Magento\Cms\Model\ResourceModel\Page', 'Magento\Cms\Model\ResourceModel\Page\Relation\Store\SaveHandler::execute'],
+ ['_afterLoad', 'Magento\Cms\Model\ResourceModel\Page', 'Magento\Cms\Model\ResourceModel\Page\Relation\Store\ReadHandler::execute'],
+ ['_beforeDelete', 'Magento\Cms\Model\ResourceModel\Block'],
+ ['_afterSave', 'Magento\Cms\Model\ResourceModel\Block', 'Magento\Cms\Model\ResourceModel\Block\Relation\Store\SaveHandler::execute'],
+ ['_afterLoad', 'Magento\Cms\Model\ResourceModel\Block', 'Magento\Cms\Model\ResourceModel\Block\Relation\Store\ReadHandler::execute'],
];
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_response_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_response_methods.php
deleted file mode 100644
index 8102968e13d82..0000000000000
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_response_methods.php
+++ /dev/null
@@ -1,22 +0,0 @@
- [
'replacement' => '\Magento\Framework\DB\Select',
'exclude' => [
- '/lib/internal/Magento/Framework/DB/Select.php',
- '/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php',
- '/lib/internal/Magento/Framework/Model/Resource/Iterator.php',
+ ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Select.php'],
+ ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'],
+ ['type' => 'library', 'name' => 'magento/framework', 'path' => 'Model/ResourceModel/Iterator.php'],
]
],
'Zend_Db_Adapter_Pdo_Mysql' => [
'replacement' => '\Magento\Framework\DB\Adapter\Pdo\Mysql',
'exclude' => [
- '/lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php',
+ ['type' => 'library', 'name' => 'magento/framework', 'path' => 'DB/Adapter/Pdo/Mysql.php'],
]
],
];
diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/whitelist/refactored_controllers.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/whitelist/refactored_controllers.php
deleted file mode 100644
index e75568b7125f0..0000000000000
--- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/whitelist/refactored_controllers.php
+++ /dev/null
@@ -1,17 +0,0 @@
-dev/tests/api-functional/testsuite/Magento/Webapi/Routing/RequestIdOverrideTest.php
overriden
+ -
+ composer.lock
+
diff --git a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php
index 4a2aef8eaac43..c667e01ecad22 100644
--- a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php
+++ b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php
@@ -39,7 +39,7 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase
*/
public static function setUpBeforeClass()
{
- self::$pathToSource = Utility\Files::init()->getPathToSource();
+ self::$pathToSource = BP;
self::$reportDir = self::$pathToSource . '/dev/tests/static/report';
if (!is_dir(self::$reportDir)) {
mkdir(self::$reportDir, 0770);
diff --git a/lib/internal/Magento/Framework/App/ResourceConnection.php b/lib/internal/Magento/Framework/App/ResourceConnection.php
index 56d220ebb57f4..2747bef243e5b 100644
--- a/lib/internal/Magento/Framework/App/ResourceConnection.php
+++ b/lib/internal/Magento/Framework/App/ResourceConnection.php
@@ -152,6 +152,18 @@ public function getTableName($modelEntity, $connectionName = self::DEFAULT_CONNE
return $this->getConnection($connectionName)->getTableName($tableName);
}
+ /**
+ * Gets table placeholder by table name
+ *
+ * @param string $tableName
+ * @return string
+ */
+ public function getTablePlaceholder($tableName)
+ {
+ $tableName = preg_replace('/^' . preg_quote($this->getTablePrefix()) . '_/', '', $tableName);
+ return $tableName;
+ }
+
/**
* Build a trigger name
*
diff --git a/lib/internal/Magento/Framework/App/Utility/Classes.php b/lib/internal/Magento/Framework/App/Utility/Classes.php
index 8956ce88c342d..d8d5c1aef7ccc 100644
--- a/lib/internal/Magento/Framework/App/Utility/Classes.php
+++ b/lib/internal/Magento/Framework/App/Utility/Classes.php
@@ -7,7 +7,7 @@
*/
namespace Magento\Framework\App\Utility;
-use Magento\Framework\App\Utility\Files;
+use Magento\Framework\Component\ComponentRegistrar;
class Classes
{
@@ -186,21 +186,18 @@ public static function collectLayoutClasses(\SimpleXMLElement $xml)
*/
public static function collectModuleClasses($subTypePattern = '[A-Za-z]+')
{
- $pattern = '/^' . preg_quote(
- Files::init()->getPathToSource(),
- '/'
- ) . '\/app\/code\/([A-Za-z]+)\/([A-Za-z]+)\/(' . $subTypePattern . '\/.+)\.php$/';
+ $componentRegistrar = new ComponentRegistrar();
$result = [];
- foreach (Files::init()->getPhpFiles(Files::INCLUDE_APP_CODE | Files::INCLUDE_NON_CLASSES) as $file) {
- if (preg_match($pattern, $file, $matches)) {
- $module = "{$matches[1]}_{$matches[2]}";
- $class = "{$module}" . '\\' . str_replace(
- '/',
- '\\',
- $matches[3]
- );
- $key = str_replace('_', '\\', $class);
- $result[$key] = $module;
+ foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $modulePath) {
+ $pattern = '/^' . preg_quote($modulePath, '/') . '\/(' . $subTypePattern . '\/.+)\.php$/';
+ foreach (Files::init()->getFiles([$modulePath], '*.php') as $file) {
+ if (preg_match($pattern, $file)) {
+ $partialFileName = substr($file, strlen($modulePath) + 1);
+ $partialFileName = substr($partialFileName, 0, strlen($partialFileName) - strlen('.php'));
+ $partialClassName = str_replace('/', '\\', $partialFileName);
+ $className = str_replace('_', '\\', $moduleName) . '\\' . $partialClassName;
+ $result[$className] = $moduleName;
+ }
}
}
return $result;
diff --git a/lib/internal/Magento/Framework/App/Utility/Files.php b/lib/internal/Magento/Framework/App/Utility/Files.php
index 79891dc769296..d405454e3024e 100644
--- a/lib/internal/Magento/Framework/App/Utility/Files.php
+++ b/lib/internal/Magento/Framework/App/Utility/Files.php
@@ -106,7 +106,7 @@ public static function composeDataSets(array $files)
{
$result = [];
foreach ($files as $file) {
- $result[substr($file, strlen(BP))] = [$file];
+ $result[$file] = [$file];
}
return $result;
}
@@ -339,7 +339,7 @@ public function getXmlFiles()
*/
public function getMainConfigFiles($asDataSet = true)
{
- $cacheKey = __METHOD__ . '|' . BP . '|' . serialize(func_get_args());
+ $cacheKey = __METHOD__ . '|' . serialize(func_get_args());
if (!isset(self::$_cache[$cacheKey])) {
$configXmlPaths = [];
foreach ($this->componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleDir) {
@@ -375,7 +375,7 @@ public function getConfigFiles(
$excludedFileNames = ['wsdl.xml', 'wsdl2.xml', 'wsi.xml'],
$asDataSet = true
) {
- $cacheKey = __METHOD__ . '|' . BP . '|' . serialize(func_get_args());
+ $cacheKey = __METHOD__ . '|' . serialize(func_get_args());
if (!isset(self::$_cache[$cacheKey])) {
$files = $this->dirSearch->collectFiles(ComponentRegistrar::MODULE, "/etc/{$fileNamePattern}");
$files = array_filter(
@@ -406,7 +406,7 @@ public function getXmlCatalogFiles(
$excludedFileNames = [],
$asDataSet = true
) {
- $cacheKey = __METHOD__ . '|' . BP . '|' . serialize(func_get_args());
+ $cacheKey = __METHOD__ . '|' . serialize(func_get_args());
if (!isset(self::$_cache[$cacheKey])) {
$files = $this->getFilesSubset(
$this->componentRegistrar->getPaths(ComponentRegistrar::MODULE),
@@ -457,7 +457,7 @@ function ($file) use ($excludedFileNames) {
*/
public function getLayoutConfigFiles($fileNamePattern = '*.xml', $asDataSet = true)
{
- $cacheKey = __METHOD__ . '|' . BP . '|' . serialize(func_get_args());
+ $cacheKey = __METHOD__ . '|' . serialize(func_get_args());
if (!isset(self::$_cache[$cacheKey])) {
self::$_cache[$cacheKey] = $this->dirSearch->collectFiles(
ComponentRegistrar::THEME,
@@ -538,7 +538,7 @@ protected function getLayoutXmlFiles($location, $incomingParams = [], $asDataSet
$params[$key] = $incomingParams[$key];
}
}
- $cacheKey = md5(BP . '|' . $location . '|' . implode('|', $params));
+ $cacheKey = md5($location . '|' . implode('|', $params));
if (!isset(self::$_cache[__METHOD__][$cacheKey])) {
$files = [];
@@ -689,7 +689,7 @@ public function getPageTypeFiles($incomingParams = [], $asDataSet = true)
$params[$key] = $incomingParams[$key];
}
}
- $cacheKey = md5(BP . '|' . implode('|', $params));
+ $cacheKey = md5(implode('|', $params));
if (!isset(self::$_cache[__METHOD__][$cacheKey])) {
self::$_cache[__METHOD__][$cacheKey] = self::getFiles(
@@ -795,7 +795,7 @@ private function getThemePaths($area, $module, $subFolder)
*/
public function getStaticHtmlFiles($area = '*', $themePath = '*/*', $namespace = '*', $module = '*')
{
- $key = $area . $themePath . $namespace . $module . __METHOD__ . BP;
+ $key = $area . $themePath . $namespace . $module . __METHOD__;
if (isset(self::$_cache[$key])) {
return self::$_cache[$key];
}
@@ -829,7 +829,7 @@ public function getStaticHtmlFiles($area = '*', $themePath = '*/*', $namespace =
*/
public function getStaticPreProcessingFiles($filePattern = '*')
{
- $key = __METHOD__ . BP . '|' . $filePattern;
+ $key = __METHOD__ . '|' . $filePattern;
if (isset(self::$_cache[$key])) {
return self::$_cache[$key];
}
@@ -1032,7 +1032,7 @@ public function getJsFilesForArea($area)
*/
public function getPhtmlFiles($withMetaInfo = false, $asDataSet = true)
{
- $key = __METHOD__ . BP . '|' . (int)$withMetaInfo;
+ $key = __METHOD__ . (int)$withMetaInfo;
if (!isset(self::$_cache[$key])) {
$result = [];
$this->accumulateModuleTemplateFiles($withMetaInfo, $result);
@@ -1129,7 +1129,7 @@ private function accumulateModuleTemplateFiles($withMetaInfo, array &$result)
*/
public function getEmailTemplates()
{
- $key = __METHOD__ . BP;
+ $key = __METHOD__;
if (isset(self::$_cache[$key])) {
return self::$_cache[$key];
}
@@ -1343,7 +1343,7 @@ private function classFileExistsCheckContent($fullPath, $namespace, $className)
*/
public function getNamespaces()
{
- $key = __METHOD__ . BP;
+ $key = __METHOD__;
if (isset(self::$_cache[$key])) {
return self::$_cache[$key];
}
@@ -1405,7 +1405,7 @@ public function getModulePhpFiles($module, $asDataSet = true)
*/
public function getComposerFiles($componentType, $asDataSet = true)
{
- $key = __METHOD__ . '|' . BP . '|' . serialize(func_get_args());
+ $key = __METHOD__ . '|' . serialize(func_get_args());
if (!isset(self::$_cache[$key])) {
$excludes = $componentType == ComponentRegistrar::MODULE ? $this->getModuleTestDirsRegex() : [];
$files = $this->getFilesSubset(
@@ -1456,7 +1456,7 @@ public function readLists($globPattern)
* Note that glob() for directories will be returned as is,
* but passing directory is supported by the tools (phpcpd, phpmd, phpcs)
*/
- $files = glob($this->getPathToSource() . '/' . $pattern, GLOB_BRACE);
+ $files = glob(BP . '/' . $pattern, GLOB_BRACE);
} else {
throw new \UnexpectedValueException(
"Incorrect pattern record '$pattern'. Supported formats: "
diff --git a/lib/internal/Magento/Framework/DB/Ddl/Sequence.php b/lib/internal/Magento/Framework/DB/Ddl/Sequence.php
index 1f0a4ca99c807..895243dd52903 100644
--- a/lib/internal/Magento/Framework/DB/Ddl/Sequence.php
+++ b/lib/internal/Magento/Framework/DB/Ddl/Sequence.php
@@ -15,16 +15,18 @@ class Sequence
*
* @param string $name
* @param int $startNumber
+ * @param string $columnType
+ * @param bool|true $unsigned
* @return string
*/
- public function getCreateSequenceDdl($name, $startNumber = 1)
+ public function getCreateSequenceDdl($name, $startNumber = 1, $columnType = Table::TYPE_INTEGER, $unsigned = true)
{
$format = "CREATE TABLE %s (
- sequence_value %s UNSIGNED NOT NULL AUTO_INCREMENT,
+ sequence_value %s %s NOT NULL AUTO_INCREMENT,
PRIMARY KEY (sequence_value)
) AUTO_INCREMENT = %d";
- return sprintf($format, $name, Table::TYPE_INTEGER, $startNumber);
+ return sprintf($format, $name, $columnType, $unsigned ? 'UNSIGNED' : '', $startNumber);
}
/**
diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/CreateEntityRow.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/CreateEntityRow.php
index a2c3d624f2cd6..cc90efda449ea 100755
--- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/CreateEntityRow.php
+++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/CreateEntityRow.php
@@ -42,7 +42,7 @@ protected function prepareData(EntityMetadata $metadata, $data)
}
if (isset($data[strtolower($column['COLUMN_NAME'])])) {
$output[strtolower($column['COLUMN_NAME'])] = $data[strtolower($column['COLUMN_NAME'])];
- } else {
+ } elseif ($column['DEFAULT'] === null) {
$output[strtolower($column['COLUMN_NAME'])] = null;
}
}
diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/ExtensionPool.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/ExtensionPool.php
index 6146d9765d0a4..745d4afac8963 100644
--- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/ExtensionPool.php
+++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/ExtensionPool.php
@@ -45,10 +45,10 @@ public function getActions($entityType, $actionName)
{
$actions = [];
foreach ($this->extensionActions as $name => $actionGroup) {
- if (!isset($actionGroup[$entityType][$actionName])) {
- $actions[$name] = $this->objectManager->get($actionGroup['default'][$actionName]);
- } else {
+ if (isset($actionGroup[$entityType][$actionName])) {
$actions[$name] = $this->objectManager->get($actionGroup[$entityType][$actionName]);
+ } elseif (isset($actionGroup['default'])) {
+ $actions[$name] = $this->objectManager->get($actionGroup['default'][$actionName]);
}
}
return $actions;
diff --git a/lib/internal/Magento/Framework/Module/Setup.php b/lib/internal/Magento/Framework/Module/Setup.php
index 3a3d6049074d2..d201ae71b2fdf 100644
--- a/lib/internal/Magento/Framework/Module/Setup.php
+++ b/lib/internal/Magento/Framework/Module/Setup.php
@@ -80,6 +80,17 @@ public function setTable($tableName, $realTableName)
return $this;
}
+ /**
+ * Gets table placeholder by table name
+ *
+ * @param string $tableName
+ * @return string
+ */
+ public function getTablePlaceholder($tableName)
+ {
+ return $this->resourceModel->getTablePlaceholder($tableName);
+ }
+
/**
* Get table name (validated by db adapter) by table placeholder
*
diff --git a/lib/internal/Magento/Framework/Setup/ExternalFKSetup.php b/lib/internal/Magento/Framework/Setup/ExternalFKSetup.php
new file mode 100644
index 0000000000000..762db7708f9a6
--- /dev/null
+++ b/lib/internal/Magento/Framework/Setup/ExternalFKSetup.php
@@ -0,0 +1,223 @@
+setup = $setup;
+ $this->entityTable = $entityTable;
+ $this->entityColumn = $entityColumn;
+ $this->externalTable = $externalTable;
+ $this->externalColumn = $externalColumn;
+
+ $this->execute();
+ }
+
+ /**
+ * Set external foreign key
+ *
+ * @return void
+ */
+ protected function execute()
+ {
+ $entityTableInfo = $this->setup->getConnection()->describeTable(
+ $this->setup->getTable($this->entityTable)
+ );
+ if (!$entityTableInfo[$this->entityColumn]['PRIMARY']) {
+ $this->dropOldForeignKey();
+ $this->addForeignKeys();
+ } else {
+ $this->addDefaultForeignKey();
+ }
+ }
+
+ /**
+ * Get foreign keys for tables and columns
+ *
+ * @param string $refTable
+ * @param string $refColumn
+ * @param string $targetTable
+ * @param string $targetColumn
+ * @return array
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ protected function getForeignKeys(
+ $targetTable,
+ $targetColumn,
+ $refTable,
+ $refColumn
+ ) {
+ $foreignKeys = $this->setup->getConnection()->getForeignKeys(
+ $this->setup->getTable($targetTable)
+ );
+ $foreignKeys = array_filter(
+ $foreignKeys,
+ function ($key) use ($targetColumn, $refTable, $refColumn) {
+ return $key['COLUMN_NAME'] == $targetColumn
+ && $key['REF_TABLE_NAME'] == $refTable;
+ }
+ );
+ return $foreignKeys;
+ }
+
+ /**
+ * Remove foreign key if exists
+ *
+ * @param string $targetTable
+ * @param string $targetColumn
+ * @param string $refTable
+ * @param string $refColumn
+ * @return void
+ */
+ protected function clearForeignKey(
+ $targetTable,
+ $targetColumn,
+ $refTable,
+ $refColumn
+ ) {
+ $foreignKeys = $this->getForeignKeys($targetTable, $targetColumn, $refTable, $refColumn);
+ foreach ($foreignKeys as $foreignKey) {
+ $this->setup->getConnection()->dropForeignKey(
+ $foreignKey['TABLE_NAME'],
+ $foreignKey['FK_NAME']
+ );
+ }
+ }
+
+ /**
+ * Add default foreign key
+ *
+ * @return void
+ */
+ protected function addDefaultForeignKey()
+ {
+ if (!count($this->getForeignKeys(
+ $this->externalTable,
+ $this->externalColumn,
+ $this->entityTable,
+ $this->entityColumn
+ ))) {
+ $this->setup->getConnection()->addForeignKey(
+ $this->setup->getFkName(
+ $this->externalTable,
+ $this->externalColumn,
+ $this->entityTable,
+ $this->entityColumn
+ ),
+ $this->setup->getTable($this->externalTable),
+ $this->externalColumn,
+ $this->setup->getTable($this->entityTable),
+ $this->entityColumn
+ );
+ }
+ }
+
+ /**
+ * Add foreign keys to entity table
+ *
+ * @return void
+ */
+ protected function addForeignKeys()
+ {
+ $foreignKeys = $this->setup->getConnection()->getForeignKeys(
+ $this->setup->getTable($this->entityTable)
+ );
+ $foreignKeys = array_filter(
+ $foreignKeys,
+ function ($key) {
+ return $key['COLUMN_NAME'] == $this->entityColumn;
+ }
+ );
+ foreach ($foreignKeys as $foreignKeyInfo) {
+ if (!count($this->getForeignKeys(
+ $this->externalTable,
+ $this->externalColumn,
+ $this->setup->getTablePlaceholder($foreignKeyInfo['REF_TABLE_NAME']),
+ $foreignKeyInfo['REF_COLUMN_NAME']
+ ))) {
+ $this->setup->getConnection()->addForeignKey(
+ $this->setup->getFkName(
+ $this->externalTable,
+ $this->externalColumn,
+ $this->setup->getTablePlaceholder($foreignKeyInfo['REF_TABLE_NAME']),
+ $foreignKeyInfo['REF_COLUMN_NAME']
+ ),
+ $this->setup->getTable($this->externalTable),
+ $this->externalColumn,
+ $foreignKeyInfo['REF_TABLE_NAME'],
+ $foreignKeyInfo['REF_COLUMN_NAME']
+ );
+ }
+ }
+ }
+
+ /**
+ * Drop old foreign key
+ *
+ * @return void
+ */
+ protected function dropOldForeignKey()
+ {
+ if (count($this->getForeignKeys(
+ $this->externalTable,
+ $this->externalColumn,
+ $this->entityTable,
+ $this->entityColumn
+ ))) {
+ $this->clearForeignKey(
+ $this->externalTable,
+ $this->externalColumn,
+ $this->entityTable,
+ $this->entityColumn
+ );
+ }
+ }
+}
diff --git a/lib/internal/Magento/Framework/Setup/SetupInterface.php b/lib/internal/Magento/Framework/Setup/SetupInterface.php
index 1274112345d42..7bd097812ec4c 100644
--- a/lib/internal/Magento/Framework/Setup/SetupInterface.php
+++ b/lib/internal/Magento/Framework/Setup/SetupInterface.php
@@ -34,6 +34,13 @@ public function setTable($tableName, $realTableName);
*/
public function getTable($tableName);
+ /**
+ * Gets table placeholder by table name
+ *
+ * @param string $tableName
+ * @return string
+ */
+ public function getTablePlaceholder($tableName);
/**
* Checks if table exists
diff --git a/lib/internal/Magento/Framework/View/Asset/File.php b/lib/internal/Magento/Framework/View/Asset/File.php
index 19a8026f4668d..02eb9aa728610 100644
--- a/lib/internal/Magento/Framework/View/Asset/File.php
+++ b/lib/internal/Magento/Framework/View/Asset/File.php
@@ -115,7 +115,7 @@ public function getPath()
public function getRelativeSourceFilePath()
{
$path = $this->filePath;
- $sourcePath = $this->source->findRelativeSourceFilePath($this);
+ $sourcePath = $this->source->findSource($this);
if ($sourcePath) {
$origExt = pathinfo($path, PATHINFO_EXTENSION);
$ext = pathinfo($sourcePath, PATHINFO_EXTENSION);
diff --git a/lib/internal/Magento/Framework/View/Asset/Source.php b/lib/internal/Magento/Framework/View/Asset/Source.php
index d47a76a4fe58c..b6af6e7d897d3 100644
--- a/lib/internal/Magento/Framework/View/Asset/Source.php
+++ b/lib/internal/Magento/Framework/View/Asset/Source.php
@@ -7,6 +7,7 @@
namespace Magento\Framework\View\Asset;
use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Filesystem\Directory\ReadFactory;
use Magento\Framework\View\Asset\PreProcessor\ChainFactoryInterface;
use Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Simple;
@@ -53,7 +54,15 @@ class Source
private $chainFactory;
/**
+ * @var ReadFactory
+ */
+ private $readFactory;
+
+ /**
+ * Constructor
+ *
* @param \Magento\Framework\Filesystem $filesystem
+ * @param ReadFactory $readFactory
* @param PreProcessor\Pool $preProcessorPool
* @param \Magento\Framework\View\Design\FileResolution\Fallback\StaticFile $fallback
* @param \Magento\Framework\View\Design\Theme\ListInterface $themeList
@@ -61,12 +70,14 @@ class Source
*/
public function __construct(
\Magento\Framework\Filesystem $filesystem,
+ ReadFactory $readFactory,
PreProcessor\Pool $preProcessorPool,
\Magento\Framework\View\Design\FileResolution\Fallback\StaticFile $fallback,
\Magento\Framework\View\Design\Theme\ListInterface $themeList,
ChainFactoryInterface $chainFactory
) {
$this->filesystem = $filesystem;
+ $this->readFactory = $readFactory;
$this->rootDir = $filesystem->getDirectoryRead(DirectoryList::ROOT);
$this->varDir = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
$this->preProcessorPool = $preProcessorPool;
@@ -87,8 +98,8 @@ public function getFile(LocalInterface $asset)
if (!$result) {
return false;
}
- list($dirCode, $path) = $result;
- return $this->filesystem->getDirectoryRead($dirCode)->getAbsolutePath($path);
+ list($dir, $path) = $result;
+ return $this->readFactory->create($dir)->getAbsolutePath($path);
}
/**
@@ -103,15 +114,15 @@ public function getContent(LocalInterface $asset)
if (!$result) {
return false;
}
- list($dirCode, $path) = $result;
- return $this->filesystem->getDirectoryRead($dirCode)->readFile($path);
+ list($dir, $path) = $result;
+ return $this->readFactory->create($dir)->readFile($path);
}
/**
* Perform necessary preprocessing and materialization when the specified asset is requested
*
* Returns an array of two elements:
- * - directory code where the file is supposed to be found
+ * - directory where the file is supposed to be found
* - relative path to the file
*
* returns false if source file was not found
@@ -122,18 +133,22 @@ public function getContent(LocalInterface $asset)
private function preProcess(LocalInterface $asset)
{
$sourceFile = $this->findSourceFile($asset);
- $path = $this->rootDir->getRelativePath($sourceFile);
+ $dir = $this->rootDir->getAbsolutePath();
+ $path = '';
+ if ($sourceFile) {
+ $path = basename($sourceFile);
+ $dir = dirname($sourceFile);
+ }
- $chain = $this->createChain($asset, $path);
+ $chain = $this->createChain($asset, $dir, $path);
$this->preProcessorPool->process($chain);
$chain->assertValid();
- $dirCode = DirectoryList::ROOT;
if ($chain->isChanged()) {
- $dirCode = DirectoryList::VAR_DIR;
+ $dir = $this->varDir->getAbsolutePath();
$path = DirectoryList::TMP_MATERIALIZATION_DIR . '/source/' . $chain->getTargetAssetPath();
$this->varDir->writeFile($path, $chain->getContent());
}
- $result = [$dirCode, $path];
+ $result = [$dir, $path];
return $result;
}
@@ -218,6 +233,7 @@ private function findFile(LocalInterface $asset, \Magento\Framework\View\Asset\F
* @param \Magento\Framework\View\Asset\LocalInterface $asset
*
* @return bool|string
+ * @deprecated If custom vendor directory is outside Magento root, then this method will return unexpected result
*/
public function findRelativeSourceFilePath(LocalInterface $asset)
{
@@ -232,13 +248,14 @@ public function findRelativeSourceFilePath(LocalInterface $asset)
* Creates a chain for pre-processing
*
* @param LocalInterface $asset
+ * @param string|bool $dir
* @param string|bool $path
* @return PreProcessor\Chain
*/
- private function createChain(LocalInterface $asset, $path)
+ private function createChain(LocalInterface $asset, $dir, $path)
{
if ($path) {
- $origContent = $this->rootDir->readFile($path);
+ $origContent = $this->readFactory->create($dir)->readFile($path);
$origContentType = $this->getContentType($path);
} else {
$origContent = '';
@@ -250,7 +267,7 @@ private function createChain(LocalInterface $asset, $path)
'asset' => $asset,
'origContent' => $origContent,
'origContentType' => $origContentType,
- 'origAssetPath' => $path
+ 'origAssetPath' => $dir . '/' . $path
]
);
return $chain;
diff --git a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Alternative.php b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Alternative.php
index c8872027ad2af..ab4228a24e175 100644
--- a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Alternative.php
+++ b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Alternative.php
@@ -6,7 +6,7 @@
namespace Magento\Framework\View\Design\FileResolution\Fallback\Resolver;
-use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Directory\ReadFactory;
use Magento\Framework\View\Design\Fallback\Rule\RuleInterface;
use Magento\Framework\View\Design\FileResolution\Fallback;
@@ -23,12 +23,12 @@ class Alternative extends Simple
/**
* Constructor
*
- * @param Filesystem $filesystem
+ * @param ReadFactory $readFactory
* @param \Magento\Framework\View\Design\Fallback\RulePool $rulePool
* @param array $alternativeExtensions
*/
public function __construct(
- Filesystem $filesystem,
+ ReadFactory $readFactory,
\Magento\Framework\View\Design\Fallback\RulePool $rulePool,
array $alternativeExtensions = []
) {
@@ -41,7 +41,7 @@ public function __construct(
}
}
$this->alternativeExtensions = $alternativeExtensions;
- parent::__construct($filesystem, $rulePool);
+ parent::__construct($readFactory, $rulePool);
}
/**
diff --git a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Simple.php b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Simple.php
index 3524480c27099..ec7c73eaa0bce 100644
--- a/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Simple.php
+++ b/lib/internal/Magento/Framework/View/Design/FileResolution/Fallback/Resolver/Simple.php
@@ -6,9 +6,7 @@
namespace Magento\Framework\View\Design\FileResolution\Fallback\Resolver;
-use Magento\Framework\App\Filesystem\DirectoryList;
-use Magento\Framework\Filesystem;
-use Magento\Framework\Filesystem\Directory\ReadInterface;
+use Magento\Framework\Filesystem\Directory\ReadFactory;
use Magento\Framework\View\Design\Fallback\Rule\RuleInterface;
use Magento\Framework\View\Design\Fallback\RulePool;
use Magento\Framework\View\Design\FileResolution\Fallback;
@@ -20,11 +18,11 @@
class Simple implements Fallback\ResolverInterface
{
/**
- * Root directory
+ * Directory read factory
*
- * @var ReadInterface
+ * @var ReadFactory
*/
- protected $rootDirectory;
+ protected $readFactory;
/**
* Fallback factory
@@ -36,12 +34,12 @@ class Simple implements Fallback\ResolverInterface
/**
* Constructor
*
- * @param Filesystem $filesystem
+ * @param ReadFactory $readFactory
* @param RulePool $rulePool
*/
- public function __construct(Filesystem $filesystem, RulePool $rulePool)
+ public function __construct(ReadFactory $readFactory, RulePool $rulePool)
{
- $this->rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT);
+ $this->readFactory = $readFactory;
$this->rulePool = $rulePool;
}
@@ -92,7 +90,8 @@ protected function resolveFile(RuleInterface $fallbackRule, $file, array $params
{
foreach ($fallbackRule->getPatternDirs($params) as $dir) {
$path = "{$dir}/{$file}";
- if ($this->rootDirectory->isExist($this->rootDirectory->getRelativePath($path))) {
+ $dirRead = $this->readFactory->create($dir);
+ if ($dirRead->isExist($file)) {
return $path;
}
}
diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php
index 880b6bc6e1ce7..f05a064a173b5 100644
--- a/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php
+++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Config/FileCollector/AggregatedFileCollector.php
@@ -5,9 +5,8 @@
*/
namespace Magento\Framework\View\Element\UiComponent\Config\FileCollector;
-use Magento\Framework\Filesystem;
+use Magento\Framework\Filesystem\Directory\ReadFactory;
use Magento\Framework\View\DesignInterface;
-use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\View\File\CollectorInterface;
use Magento\Framework\View\Element\UiComponent\Config\FileCollectorInterface;
@@ -34,28 +33,28 @@ class AggregatedFileCollector implements FileCollectorInterface
protected $design;
/**
- * @var Filesystem
+ * @var ReadFactory
*/
- protected $filesystem;
+ protected $readFactory;
/**
* Constructor
*
* @param CollectorInterface $collectorAggregated
* @param DesignInterface $design
- * @param Filesystem $filesystem
+ * @param ReadFactory $readFactory
* @param string $searchPattern
*/
public function __construct(
CollectorInterface $collectorAggregated,
DesignInterface $design,
- Filesystem $filesystem,
+ ReadFactory $readFactory,
$searchPattern = null
) {
$this->searchPattern = $searchPattern;
$this->collectorAggregated = $collectorAggregated;
$this->design = $design;
- $this->filesystem = $filesystem;
+ $this->readFactory = $readFactory;
}
/**
@@ -75,10 +74,12 @@ public function collectFiles($searchPattern = null)
throw new \Exception('Search pattern cannot be empty.');
}
$files = $this->collectorAggregated->getFiles($this->design->getDesignTheme(), $searchPattern);
- $fileReader = $this->filesystem->getDirectoryRead(DirectoryList::ROOT);
foreach ($files as $file) {
- $filePath = $fileReader->getRelativePath($file->getFilename());
- $result[sprintf('%x', crc32($filePath))] = $fileReader->readFile($filePath);
+ $fullFileName = $file->getFileName();
+ $fileDir = dirname($fullFileName);
+ $fileName = basename($fullFileName);
+ $dirRead = $this->readFactory->create($fileDir);
+ $result[$fullFileName] = $dirRead->readFile($fileName);
}
return $result;
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php
index 427ed2bc15578..cec61e94cb8bd 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Asset/SourceTest.php
@@ -69,6 +69,11 @@ class SourceTest extends \PHPUnit_Framework_TestCase
*/
private $chain;
+ /**
+ * @var \Magento\Framework\Filesystem\Directory\ReadFactory|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $readFactory;
+
protected function setUp()
{
$this->preProcessorPool = $this->getMock(
@@ -96,10 +101,17 @@ protected function setUp()
->with('frontend/magento_theme')
->willReturn($this->theme);
+ $this->readFactory = $this->getMock('Magento\Framework\Filesystem\Directory\ReadFactory', [], [], '', false);
+
$this->initFilesystem();
$this->object = new Source(
- $this->filesystem, $this->preProcessorPool, $this->viewFileResolution, $themeList, $this->chainFactory
+ $this->filesystem,
+ $this->readFactory,
+ $this->preProcessorPool,
+ $this->viewFileResolution,
+ $themeList,
+ $this->chainFactory
);
}
@@ -115,18 +127,13 @@ protected function setUp()
public function testGetFile($origFile, $origPath, $origContent, $isMaterialization, $isExist)
{
$filePath = 'some/file.ext';
+ $read = $this->getMock('Magento\Framework\Filesystem\Directory\Read', [], [], '', false);
+ $read->expects($this->at(0))->method('readFile')->with($origPath)->willReturn($origContent);
+ $this->readFactory->expects($this->atLeastOnce())->method('create')->willReturn($read);
$this->viewFileResolution->expects($this->once())
->method('getFile')
->with('frontend', $this->theme, 'en_US', $filePath, 'Magento_Module')
->willReturn($origFile);
- $this->rootDirRead->expects($this->once())
- ->method('getRelativePath')
- ->with($origFile)
- ->willReturn($origPath);
- $this->rootDirRead->expects($this->once())
- ->method('readFile')
- ->with($origPath)
- ->willReturn($origContent);
$this->preProcessorPool->expects($this->once())
->method('process')
->with($this->chain);
@@ -151,12 +158,16 @@ public function testGetFile($origFile, $origPath, $origContent, $isMaterializati
->with('view_preprocessed/source/some/file.ext', 'processed');
$this->varDir->expects($this->once())
->method('getAbsolutePath')
- ->with('view_preprocessed/source/some/file.ext')->willReturn('result');
+ ->willReturn('var');
+ $read->expects($this->once())
+ ->method('getAbsolutePath')
+ ->with('view_preprocessed/source/some/file.ext')
+ ->willReturn('result');
} else {
$this->varDir->expects($this->never())->method('writeFile');
- $this->rootDirRead->expects($this->once())
+ $read->expects($this->at(1))
->method('getAbsolutePath')
- ->with('source/some/file.ext')
+ ->with('file.ext')
->willReturn('result');
}
$this->assertSame('result', $this->object->getFile($this->getAsset()));
@@ -201,10 +212,10 @@ public function chainTestCallback(Chain $chain)
public function getFileDataProvider()
{
return [
- ['/root/some/file.ext', 'source/some/file.ext', 'processed', false, true],
- ['/root/some/file.ext', 'source/some/file.ext', 'not_processed', true, false],
- ['/root/some/file.ext2', 'source/some/file.ext2', 'processed', true, true],
- ['/root/some/file.ext2', 'source/some/file.ext2', 'not_processed', true, false],
+ ['/root/some/file.ext', 'file.ext', 'processed', false, true],
+ ['/root/some/file.ext', 'file.ext', 'not_processed', true, false],
+ ['/root/some/file.ext2', 'file.ext2', 'processed', true, true],
+ ['/root/some/file.ext2', 'file.ext2', 'not_processed', true, false],
];
}
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/AlternativeTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/AlternativeTest.php
index 2dbaa2e6c6066..891c03f4f4fbd 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/AlternativeTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/AlternativeTest.php
@@ -32,13 +32,9 @@ class AlternativeTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->directory = $this->getMock('\Magento\Framework\Filesystem\Directory\Read', [], [], '', false);
- $this->directory->expects($this->any())
- ->method('getRelativePath')
- ->will($this->returnArgument(0));
- $filesystem = $this->getMock('\Magento\Framework\Filesystem', [], [], '', false);
- $filesystem->expects($this->once())
- ->method('getDirectoryRead')
- ->with(DirectoryList::ROOT)
+ $readFactory = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadFactory', [], [], '', false);
+ $readFactory->expects($this->any())
+ ->method('create')
->will($this->returnValue($this->directory));
$this->rule = $this->getMock(
'\Magento\Framework\View\Design\Fallback\Rule\RuleInterface', [], [], '', false
@@ -48,7 +44,7 @@ protected function setUp()
->method('getRule')
->with('type')
->will($this->returnValue($this->rule));
- $this->object = new Alternative($filesystem, $rulePool, ['css' => ['less']]);
+ $this->object = new Alternative($readFactory, $rulePool, ['css' => ['less']]);
}
/**
@@ -61,9 +57,9 @@ public function testConstructorException(array $alternativeExtensions)
$this->setExpectedException('\InvalidArgumentException', "\$alternativeExtensions must be an array with format:"
. " array('ext1' => array('ext1', 'ext2'), 'ext3' => array(...)]");
- $filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false);
+ $readFactory = $this->getMock('Magento\Framework\Filesystem\Directory\ReadFactory', [], [], '', false);
$rulePool = $this->getMock('Magento\Framework\View\Design\Fallback\RulePool', [], [], '', false);
- new Alternative($filesystem, $rulePool, $alternativeExtensions);
+ new Alternative($readFactory, $rulePool, $alternativeExtensions);
}
/**
@@ -91,8 +87,8 @@ public function testResolve()
->will($this->returnValue(['some/dir']));
$fileExistsMap = [
- ['some/dir/file.css', false],
- ['some/dir/file.less', true],
+ ['file.css', false],
+ ['file.less', true],
];
$this->directory->expects($this->any())
->method('isExist')
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/SimpleTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/SimpleTest.php
index 14411757fc878..6ae8f5f71f593 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/SimpleTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Design/FileResolution/Fallback/Resolver/SimpleTest.php
@@ -30,13 +30,9 @@ class SimpleTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->directory = $this->getMock('\Magento\Framework\Filesystem\Directory\Read', [], [], '', false);
- $this->directory->expects($this->any())
- ->method('getRelativePath')
- ->will($this->returnArgument(0));
- $filesystem = $this->getMock('\Magento\Framework\Filesystem', [], [], '', false);
- $filesystem->expects($this->once())
- ->method('getDirectoryRead')
- ->with(DirectoryList::ROOT)
+ $readFactory = $this->getMock('\Magento\Framework\Filesystem\Directory\ReadFactory', [], [], '', false);
+ $readFactory->expects($this->any())
+ ->method('create')
->will($this->returnValue($this->directory));
$this->rule = $this->getMock('\Magento\Framework\View\Design\Fallback\Rule\RuleInterface', [], [], '', false);
$rulePool = $this->getMock('Magento\Framework\View\Design\Fallback\RulePool', [], [], '', false);
@@ -45,7 +41,7 @@ protected function setUp()
->with('type')
->will($this->returnValue($this->rule));
- $this->object = new Simple($filesystem, $rulePool);
+ $this->object = new Simple($readFactory, $rulePool);
}
/**
@@ -65,15 +61,13 @@ public function testResolve($area, $themePath, $locale, $module, array $expected
$expectedParams['theme'] = $this->getMockForTheme($expectedParams['theme']);
}
- $this->directory->expects($this->never())
- ->method('getAbsolutePath');
$this->rule->expects($this->once())
->method('getPatternDirs')
->with($expectedParams)
->will($this->returnValue(['/some/dir']));
$this->directory->expects($this->once())
->method('isExist')
- ->with($expectedPath)
+ ->with('file.ext')
->will($this->returnValue(true));
$actualPath = $this->object->resolve('type', 'file.ext', $area, $theme, $locale, $module);
$this->assertSame($expectedPath, $actualPath);
diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php
index adecba17d959e..00d864460f810 100644
--- a/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php
+++ b/lib/internal/Magento/Framework/View/Test/Unit/Element/Js/CookieTest.php
@@ -13,17 +13,17 @@ class CookieTest extends \PHPUnit_Framework_TestCase
protected $model;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\View\Element\Template\Context
*/
protected $contextMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Framework\Session\Config\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $sessionConfigMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Framework\Validator\Ip|\PHPUnit_Framework_MockObject_MockObject
*/
protected $ipValidatorMock;
diff --git a/setup/src/Magento/Setup/Console/Command/I18nCollectPhrasesCommand.php b/setup/src/Magento/Setup/Console/Command/I18nCollectPhrasesCommand.php
index afb277dab8062..674e8c33e5549 100644
--- a/setup/src/Magento/Setup/Console/Command/I18nCollectPhrasesCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/I18nCollectPhrasesCommand.php
@@ -35,7 +35,11 @@ protected function configure()
$this->setName('i18n:collect-phrases')
->setDescription('Discovers phrases in the codebase');
$this->setDefinition([
- new InputArgument(self::INPUT_KEY_DIRECTORY, InputArgument::REQUIRED, 'Directory path to parse'),
+ new InputArgument(
+ self::INPUT_KEY_DIRECTORY,
+ InputArgument::OPTIONAL,
+ 'Directory path to parse. Not needed if --magento flag is set'
+ ),
new InputOption(
self::INPUT_KEY_OUTPUT,
self::SHORTCUT_KEY_OUTPUT,
@@ -46,8 +50,8 @@ protected function configure()
self::INPUT_KEY_MAGENTO,
self::SHORTCUT_KEY_MAGENTO,
InputOption::VALUE_NONE,
- 'Use the --magento parameter to specify the directory is the Magento root directory.' .
- ' Omit the parameter if the directory is not the Magento root directory.'
+ 'Use the --magento parameter to parse the current Magento codebase.' .
+ ' Omit the parameter if a directory is specified.'
),
]);
}
@@ -57,9 +61,18 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $directory = $input->getArgument(self::INPUT_KEY_DIRECTORY);
+ if ($input->getOption(self::INPUT_KEY_MAGENTO)) {
+ $directory = BP;
+ if ($input->getArgument(self::INPUT_KEY_DIRECTORY)) {
+ throw new \InvalidArgumentException('Directory path is not needed when --magento flag is set.');
+ }
+ } elseif (!$input->getArgument(self::INPUT_KEY_DIRECTORY)) {
+ throw new \InvalidArgumentException('Directory path is needed when --magento flag is not set.');
+ }
$generator = ServiceLocator::getDictionaryGenerator();
$generator->generate(
- $input->getArgument(self::INPUT_KEY_DIRECTORY),
+ $directory,
$input->getOption(self::INPUT_KEY_OUTPUT),
$input->getOption(self::INPUT_KEY_MAGENTO)
);
diff --git a/setup/src/Magento/Setup/Console/Command/I18nPackCommand.php b/setup/src/Magento/Setup/Console/Command/I18nPackCommand.php
index 82ff951a89e0d..bb6ce5d2c8afe 100644
--- a/setup/src/Magento/Setup/Console/Command/I18nPackCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/I18nPackCommand.php
@@ -21,7 +21,6 @@ class I18nPackCommand extends Command
* Keys and shortcuts for input arguments and options
*/
const INPUT_KEY_SOURCE = 'source';
- const INPUT_KEY_PACK = 'pack';
const INPUT_KEY_LOCALE = 'locale';
const INPUT_KEY_MODE = 'mode';
const INPUT_KEY_ALLOW_DUPLICATES = 'allow-duplicates';
@@ -50,11 +49,6 @@ protected function configure()
InputArgument::REQUIRED,
'Path to source dictionary file with translations'
),
- new InputArgument(
- self::INPUT_KEY_PACK,
- InputArgument::REQUIRED,
- 'Path to language package'
- ),
new InputArgument(
self::INPUT_KEY_LOCALE,
InputArgument::REQUIRED,
@@ -92,7 +86,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
$locale = $input->getArgument(self::INPUT_KEY_LOCALE);
$generator->generate(
$input->getArgument(self::INPUT_KEY_SOURCE),
- $input->getArgument(self::INPUT_KEY_PACK),
$locale,
$input->getOption(self::INPUT_KEY_MODE),
$input->getOption(self::INPUT_KEY_ALLOW_DUPLICATES)
diff --git a/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php b/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php
index 3fd0e674ec200..29134e5a06e1a 100644
--- a/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php
+++ b/setup/src/Magento/Setup/Fixtures/CatalogPriceRulesFixture.php
@@ -34,6 +34,10 @@ public function execute()
$category = $this->fixtureModel->getObjectManager()->get('Magento\Catalog\Model\Category');
/** @var $model \Magento\CatalogRule\Model\Rule*/
$model = $this->fixtureModel->getObjectManager()->get('Magento\CatalogRule\Model\Rule');
+ /** @var \Magento\Framework\Model\Entity\MetadataPool $metadataPool */
+ $metadataPool = $this->fixtureModel->getObjectManager()->get('Magento\Framework\Model\Entity\MetadataPool');
+ $metadata = $metadataPool->getMetadata('Magento\CatalogRule\Api\Data\RuleInterface');
+
//Get all websites
$categoriesArray = [];
$websites = $storeManager->getWebsites();
@@ -57,12 +61,14 @@ public function execute()
}
asort($categoriesArray);
$categoriesArray = array_values($categoriesArray);
- $idField = $model->getIdFieldName();
+ $linkField = $metadata->getLinkField();
+ $idField = $metadata->getIdentifierField();
for ($i = 0; $i < $catalogPriceRulesCount; $i++) {
$ruleName = sprintf('Catalog Price Rule %1$d', $i);
$data = [
$idField => null,
+ $linkField => null,
'name' => $ruleName,
'description' => '',
'is_active' => '1',
diff --git a/setup/src/Magento/Setup/Model/ConfigGenerator.php b/setup/src/Magento/Setup/Model/ConfigGenerator.php
index 812cbd1830a38..a7007998445fe 100644
--- a/setup/src/Magento/Setup/Model/ConfigGenerator.php
+++ b/setup/src/Magento/Setup/Model/ConfigGenerator.php
@@ -235,7 +235,9 @@ public function createXFrameConfig()
public function createModeConfig()
{
$configData = new ConfigData(ConfigFilePool::APP_ENV);
- $configData->set(State::PARAM_MODE, State::MODE_DEFAULT);
+ if ($this->deploymentConfig->get(State::PARAM_MODE) === null) {
+ $configData->set(State::PARAM_MODE, State::MODE_DEFAULT);
+ }
return $configData;
}
diff --git a/setup/src/Magento/Setup/Module/I18n/Context.php b/setup/src/Magento/Setup/Module/I18n/Context.php
index 4944390f175c3..fac38bf96d7c1 100644
--- a/setup/src/Magento/Setup/Module/I18n/Context.php
+++ b/setup/src/Magento/Setup/Module/I18n/Context.php
@@ -100,15 +100,13 @@ public function buildPathToLocaleDirectoryByContext($type, $value)
{
switch ($type) {
case self::CONTEXT_TYPE_MODULE:
- $absolutePath = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $value);
- $path = str_replace(BP . '/', '', $absolutePath);
+ $path = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $value);
break;
case self::CONTEXT_TYPE_THEME:
- $absolutePath = $this->componentRegistrar->getPath(ComponentRegistrar::THEME, $value);
- $path = str_replace(BP . '/', '', $absolutePath);
+ $path = $this->componentRegistrar->getPath(ComponentRegistrar::THEME, $value);
break;
case self::CONTEXT_TYPE_LIB:
- $path = 'lib/web';
+ $path = BP . '/lib/web';
break;
default:
throw new \InvalidArgumentException(sprintf('Invalid context given: "%s".', $type));
diff --git a/setup/src/Magento/Setup/Module/I18n/Dictionary/Options/Resolver.php b/setup/src/Magento/Setup/Module/I18n/Dictionary/Options/Resolver.php
index 07a469246bd46..967054587a9e7 100644
--- a/setup/src/Magento/Setup/Module/I18n/Dictionary/Options/Resolver.php
+++ b/setup/src/Magento/Setup/Module/I18n/Dictionary/Options/Resolver.php
@@ -134,9 +134,7 @@ private function getComponentDirectories($componentType)
{
$dirs = [];
foreach ($this->componentRegistrar->getPaths($componentType) as $componentDir) {
- if (strstr($componentDir, $this->directory)) {
- $dirs[] = $componentDir . '/';
- }
+ $dirs[] = $componentDir . '/';
}
return $dirs;
}
diff --git a/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php b/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php
index bbc0cecfa9ce6..fcf35932c412f 100644
--- a/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php
+++ b/setup/src/Magento/Setup/Module/I18n/Pack/Generator.php
@@ -56,7 +56,6 @@ public function __construct(
* Generate language pack
*
* @param string $dictionaryPath
- * @param string $packPath
* @param string $locale
* @param string $mode One of const of WriterInterface::MODE_
* @param bool $allowDuplicates
@@ -65,7 +64,6 @@ public function __construct(
*/
public function generate(
$dictionaryPath,
- $packPath,
$locale,
$mode = WriterInterface::MODE_REPLACE,
$allowDuplicates = false
@@ -84,7 +82,7 @@ public function generate(
);
}
- $this->packWriter->write($dictionary, $packPath, $locale, $mode);
+ $this->packWriter->writeDictionary($dictionary, $locale, $mode);
}
/**
diff --git a/setup/src/Magento/Setup/Module/I18n/Pack/Writer/File/AbstractFile.php b/setup/src/Magento/Setup/Module/I18n/Pack/Writer/File/AbstractFile.php
index e5909fb68296f..50757c7c80159 100644
--- a/setup/src/Magento/Setup/Module/I18n/Pack/Writer/File/AbstractFile.php
+++ b/setup/src/Magento/Setup/Module/I18n/Pack/Writer/File/AbstractFile.php
@@ -37,13 +37,6 @@ abstract class AbstractFile implements WriterInterface
*/
protected $_factory;
- /**
- * Pack path
- *
- * @var string
- */
- protected $_packPath;
-
/**
* Locale
*
@@ -77,7 +70,14 @@ public function __construct(Context $context, Dictionary\Loader\FileInterface $d
*/
public function write(Dictionary $dictionary, $packPath, Locale $locale, $mode = self::MODE_REPLACE)
{
- $this->_packPath = rtrim($packPath, '\\/') . '/';
+ $this->writeDictionary($dictionary, $locale, $mode);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function writeDictionary(Dictionary $dictionary, Locale $locale, $mode = self::MODE_REPLACE)
+ {
$this->_locale = $locale;
$this->_mode = $mode;
@@ -121,7 +121,7 @@ protected function _buildPackFilesData(Dictionary $dictionary)
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException($e->getMessage() . ' Row #' . ($key + 1) . '.');
}
- $filename = $this->_packPath . $path . $this->_locale . '.' . $this->_getFileExtension();
+ $filename = $path . $this->_locale . '.' . $this->_getFileExtension();
$files[$filename][$phrase->getPhrase()] = $phrase;
}
}
diff --git a/setup/src/Magento/Setup/Module/I18n/Pack/WriterInterface.php b/setup/src/Magento/Setup/Module/I18n/Pack/WriterInterface.php
index 19159add87aec..edb898ac73270 100644
--- a/setup/src/Magento/Setup/Module/I18n/Pack/WriterInterface.php
+++ b/setup/src/Magento/Setup/Module/I18n/Pack/WriterInterface.php
@@ -30,6 +30,18 @@ interface WriterInterface
* @param \Magento\Setup\Module\I18n\Locale $locale
* @param string $mode One of const of WriterInterface::MODE_
* @return void
+ * @deprecated Writing to a specified pack path is not supported after custom vendor directory support.
+ * Dictionary data will be written to current Magento codebase.
*/
public function write(Dictionary $dictionary, $packPath, Locale $locale, $mode);
+
+ /**
+ * Write dictionary data to current Magento codebase
+ *
+ * @param \Magento\Setup\Module\I18n\Dictionary $dictionary
+ * @param \Magento\Setup\Module\I18n\Locale $locale
+ * @param string $mode One of const of WriterInterface::MODE_
+ * @return void
+ */
+ public function writeDictionary(Dictionary $dictionary, Locale $locale, $mode);
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Fixtures/CatalogPriceRulesFixtureTest.php b/setup/src/Magento/Setup/Test/Unit/Fixtures/CatalogPriceRulesFixtureTest.php
index 2e6625e107abb..71241d9d58004 100644
--- a/setup/src/Magento/Setup/Test/Unit/Fixtures/CatalogPriceRulesFixtureTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Fixtures/CatalogPriceRulesFixtureTest.php
@@ -73,20 +73,27 @@ public function testExecute()
->will($this->returnValue('category_id'));
$modelMock = $this->getMock('Magento\CatalogRule\Model\Rule', [], [], '', false);
- $modelMock->expects($this->once())
- ->method('getIdFieldName')
+ $metadataMock = $this->getMock('\Magento\Framework\Model\Entity\EntityMetadata', [], [], '', false);
+ $metadataPoolMock = $this->getMock('Magento\Framework\Model\Entity\MetadataPool', [], [], '', false);
+ $metadataMock->expects($this->once())
+ ->method('getLinkField')
->will($this->returnValue('Field Id Name'));
$valueMap = [
['Magento\CatalogRule\Model\Rule', $modelMock],
- ['Magento\Catalog\Model\Category', $categoryMock]
+ ['Magento\Catalog\Model\Category', $categoryMock],
+ ['Magento\Framework\Model\Entity\MetadataPool', $metadataPoolMock]
];
-
+ $metadataPoolMock
+ ->expects($this->once())
+ ->method('getMetadata')
+ ->with('Magento\CatalogRule\Api\Data\RuleInterface')
+ ->willReturn($metadataMock);
$objectManagerMock = $this->getMock('Magento\Framework\ObjectManager\ObjectManager', [], [], '', false);
$objectManagerMock->expects($this->once())
->method('create')
->will($this->returnValue($storeManagerMock));
- $objectManagerMock->expects($this->exactly(2))
+ $objectManagerMock->expects($this->exactly(3))
->method('get')
->will($this->returnValueMap($valueMap));
@@ -95,7 +102,7 @@ public function testExecute()
->method('getValue')
->will($this->returnValue(1));
$this->fixtureModelMock
- ->expects($this->exactly(3))
+ ->expects($this->exactly(4))
->method('getObjectManager')
->will($this->returnValue($objectManagerMock));
diff --git a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php
index 65df905990221..0e892b753c395 100644
--- a/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Model/ConfigGeneratorTest.php
@@ -3,16 +3,16 @@
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-
namespace Magento\Setup\Test\Unit\Model;
-
use Magento\Framework\Config\ConfigOptionsListConstants;
+use Magento\Framework\App\State;
class ConfigGeneratorTest extends \PHPUnit_Framework_TestCase
{
/** @var \Magento\Framework\App\DeploymentConfig | \PHPUnit_Framework_MockObject_MockObject */
private $deploymentConfigMock;
+
/** @var \Magento\Setup\Model\ConfigGenerator | \PHPUnit_Framework_MockObject_MockObject */
private $model;
@@ -58,4 +58,24 @@ public function testCreateCacheHostsConfig()
$configData = $this->model->createCacheHostsConfig($data);
$this->assertEquals($expectedData, $configData->getData()[ConfigOptionsListConstants::CONFIG_PATH_CACHE_HOSTS]);
}
+
+ public function testCreateModeConfig()
+ {
+ $this->deploymentConfigMock->expects($this->once())
+ ->method('get')
+ ->with(State::PARAM_MODE)
+ ->willReturn(null);
+ $configData = $this->model->createModeConfig();
+ $this->assertSame(State::MODE_DEFAULT, $configData->getData()[State::PARAM_MODE]);
+ }
+
+ public function testCreateModeConfigIfAlreadySet()
+ {
+ $this->deploymentConfigMock->expects($this->once())
+ ->method('get')
+ ->with(State::PARAM_MODE)
+ ->willReturn(State::MODE_PRODUCTION);
+ $configData = $this->model->createModeConfig();
+ $this->assertSame([], $configData->getData());
+ }
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/ContextTest.php b/setup/src/Magento/Setup/Test/Unit/Module/I18n/ContextTest.php
index 4972001695db1..89dfe454de3ef 100644
--- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/ContextTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/ContextTest.php
@@ -117,12 +117,12 @@ public function dataProviderPathToLocaleDirectoryByContext()
{
return [
[
- 'app/code/Magento/Module/i18n/',
+ BP . '/app/code/Magento/Module/i18n/',
[Context::CONTEXT_TYPE_MODULE, 'Magento_Module'],
[[ComponentRegistrar::MODULE, 'Magento_Module', BP . '/app/code/Magento/Module']]
],
['/i18n/', [Context::CONTEXT_TYPE_THEME, 'theme/test.phtml'], []],
- ['lib/web/i18n/', [Context::CONTEXT_TYPE_LIB, 'lib/web/module/test.phtml'], []],
+ [BP . '/lib/web/i18n/', [Context::CONTEXT_TYPE_LIB, 'lib/web/module/test.phtml'], []],
];
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php
index 0866b50cf75aa..36600df2570f4 100644
--- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Pack/GeneratorTest.php
@@ -56,7 +56,6 @@ protected function setUp()
public function testGenerate()
{
$dictionaryPath = 'dictionary_path';
- $packPath = 'pack_path';
$localeString = 'locale';
$mode = 'mode';
$allowDuplicates = true;
@@ -76,10 +75,10 @@ public function testGenerate()
->with($dictionaryPath)
->will($this->returnValue($this->dictionaryMock));
$this->packWriterMock->expects($this->once())
- ->method('write')
- ->with($this->dictionaryMock, $packPath, $localeMock, $mode);
+ ->method('writeDictionary')
+ ->with($this->dictionaryMock, $localeMock, $mode);
- $this->_generator->generate($dictionaryPath, $packPath, $localeString, $mode, $allowDuplicates);
+ $this->_generator->generate($dictionaryPath, $localeString, $mode, $allowDuplicates);
}
/**
@@ -89,7 +88,6 @@ public function testGenerate()
public function testGenerateEmptyFile()
{
$dictionaryPath = 'dictionary_path';
- $packPath = 'pack_path';
$localeString = 'locale';
$mode = 'mode';
$allowDuplicates = true;
@@ -104,7 +102,7 @@ public function testGenerateEmptyFile()
->with($dictionaryPath)
->will($this->returnValue($this->dictionaryMock));
- $this->_generator->generate($dictionaryPath, $packPath, $localeString, $mode, $allowDuplicates);
+ $this->_generator->generate($dictionaryPath, $localeString, $mode, $allowDuplicates);
}
public function testGenerateWithNotAllowedDuplicatesAndDuplicatesExist()
@@ -132,6 +130,6 @@ public function testGenerateWithNotAllowedDuplicatesAndDuplicatesExist()
->method('getDuplicates')
->will($this->returnValue([[$phraseFirstMock], [$phraseSecondMock]]));
- $this->_generator->generate('dictionary_path', 'pack_path', 'locale', 'mode', $allowDuplicates);
+ $this->_generator->generate('dictionary_path', 'locale', 'mode', $allowDuplicates);
}
}