PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Plugin/Payment/Method/PaymentMethodBase.php

https://gitlab.com/Drulenium-bot/payment
PHP | 404 lines | 186 code | 50 blank | 168 comment | 14 complexity | 1b0330ba415edc6b8acaccf98b4af1ff MD5 | raw file
  1. <?php
  2. /**
  3. * Contains \Drupal\payment\Plugin\Payment\Method\PaymentMethodBase.
  4. */
  5. namespace Drupal\payment\Plugin\Payment\Method;
  6. use Drupal\Component\Plugin\ConfigurablePluginInterface;
  7. use Drupal\Core\Access\AccessResult;
  8. use Drupal\Core\Cache\Cache;
  9. use Drupal\Core\Cache\CacheableDependencyInterface;
  10. use Drupal\Core\Extension\ModuleHandlerInterface;
  11. use Drupal\Core\Form\FormStateInterface;
  12. use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
  13. use Drupal\Core\Plugin\PluginBase;
  14. use Drupal\Core\Plugin\PluginFormInterface;
  15. use Drupal\Core\Session\AccountInterface;
  16. use Drupal\Core\Utility\Token;
  17. use Drupal\payment\EventDispatcherInterface;
  18. use Drupal\payment\PaymentAwareTrait;
  19. use Drupal\payment\OperationResult;
  20. use Drupal\payment\Plugin\Payment\Status\PaymentStatusManagerInterface;
  21. use Symfony\Component\DependencyInjection\ContainerInterface;
  22. /**
  23. * A base payment method plugin.
  24. *
  25. * Plugins that extend this class must have the following two keys in their
  26. * plugin definitions:
  27. * - message_text: The translated human-readable text to display in the payment
  28. * form.
  29. * - message_text_format: The ID of the text format to format message_text with.
  30. */
  31. abstract class PaymentMethodBase extends PluginBase implements ContainerFactoryPluginInterface, PaymentMethodInterface, PaymentMethodCapturePaymentInterface, PaymentMethodRefundPaymentInterface, PluginFormInterface, CacheableDependencyInterface, ConfigurablePluginInterface {
  32. use PaymentAwareTrait;
  33. /**
  34. * The event dispatcher.
  35. *
  36. * @var \Drupal\payment\EventDispatcherInterface
  37. */
  38. protected $eventDispatcher;
  39. /**
  40. * The module handler.
  41. *
  42. * @var \Drupal\Core\Extension\ModuleHandlerInterface
  43. */
  44. protected $moduleHandler;
  45. /**
  46. * The token API.
  47. *
  48. * @var \Drupal\Core\Utility\Token
  49. */
  50. protected $token;
  51. /**
  52. * Constructs a new instance.
  53. *
  54. * @param mixed[] $configuration
  55. * A configuration array containing information about the plugin instance.
  56. * @param string $plugin_id
  57. * The plugin_id for the plugin instance.
  58. * @param mixed[] $plugin_definition
  59. * The plugin implementation definition.
  60. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
  61. * The module handler.
  62. * @param \Drupal\payment\EventDispatcherInterface $event_dispatcher
  63. * The event dispatcher.
  64. * @param \Drupal\Core\Utility\Token $token
  65. * The token API.
  66. * @param \Drupal\payment\Plugin\Payment\Status\PaymentStatusManagerInterface
  67. * The payment status manager.
  68. */
  69. public function __construct(array $configuration, $plugin_id, array $plugin_definition, ModuleHandlerInterface $module_handler, EventDispatcherInterface $event_dispatcher, Token $token, PaymentStatusManagerInterface $payment_status_manager) {
  70. $configuration += $this->defaultConfiguration();
  71. parent::__construct($configuration, $plugin_id, $plugin_definition);
  72. $this->eventDispatcher = $event_dispatcher;
  73. $this->moduleHandler = $module_handler;
  74. $this->paymentStatusManager = $payment_status_manager;
  75. $this->token = $token;
  76. }
  77. /**
  78. * {@inheritdoc}
  79. */
  80. public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  81. return new static($configuration, $plugin_id, $plugin_definition, $container->get('module_handler'), $container->get('payment.event_dispatcher'), $container->get('token'), $container->get('plugin.manager.payment.status'));
  82. }
  83. /**
  84. * {@inheritdoc}
  85. */
  86. public function getCacheContexts() {
  87. return [];
  88. }
  89. /**
  90. * {@inheritdoc}
  91. */
  92. public function getCacheTags() {
  93. // The default payment method manager caches definitions using the
  94. // "payment_method" tag.
  95. return ['payment_method'];
  96. }
  97. /**
  98. * {@inheritdoc}
  99. */
  100. public function getCacheMaxAge() {
  101. return Cache::PERMANENT;
  102. }
  103. /**
  104. * {@inheritdoc}
  105. */
  106. public function calculateDependencies() {
  107. return [];
  108. }
  109. /**
  110. * {@inheritdoc}
  111. */
  112. public function defaultConfiguration() {
  113. return [];
  114. }
  115. /**
  116. * {@inheritdoc}
  117. */
  118. public function getConfiguration() {
  119. return $this->configuration;
  120. }
  121. /**
  122. * {@inheritdoc}
  123. */
  124. public function setConfiguration(array $configuration) {
  125. $this->configuration = $configuration + $this->defaultConfiguration();
  126. }
  127. /**
  128. * Gets the payer message text.
  129. *
  130. * @return string
  131. */
  132. public function getMessageText() {
  133. return $this->pluginDefinition['message_text'];
  134. }
  135. /**
  136. * Gets the payer message text format.
  137. *
  138. * @return string
  139. */
  140. public function getMessageTextFormat() {
  141. return $this->pluginDefinition['message_text_format'];
  142. }
  143. /**
  144. * {@inheritdoc}
  145. */
  146. public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
  147. $message_text = $this->token->replace($this->getMessageText(), array(
  148. 'payment' => $this->getPayment(),
  149. ), array(
  150. 'clear' => TRUE,
  151. ));
  152. if ($this->moduleHandler->moduleExists('filter')) {
  153. $elements['message'] = array(
  154. '#type' => 'processed_text',
  155. '#text' => $message_text,
  156. '#format' => $this->getMessageTextFormat(),
  157. );
  158. }
  159. else {
  160. $elements['message'] = array(
  161. '#type' => 'markup',
  162. '#markup' => $message_text,
  163. );
  164. }
  165. return $elements;
  166. }
  167. /**
  168. * {@inheritdoc}
  169. */
  170. public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
  171. }
  172. /**
  173. * {@inheritdoc}
  174. */
  175. public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
  176. }
  177. /**
  178. * {@inheritdoc}
  179. */
  180. public function executePaymentAccess(AccountInterface $account) {
  181. if (!$this->getPayment()) {
  182. throw new \LogicException('Trying to check access for a non-existing payment. A payment must be set trough self::setPayment() first.');
  183. }
  184. return AccessResult::allowedIf($this->pluginDefinition['active'])
  185. ->andIf($this->executePaymentAccessCurrency($account))
  186. ->andIf($this->eventDispatcher->executePaymentAccess($this->getPayment(), $this, $account))
  187. ->andIf($this->doExecutePaymentAccess($account))
  188. ->addCacheableDependency($this->getPayment())
  189. ->addCacheTags(['payment_method']);
  190. }
  191. /**
  192. * Performs a payment method-specific access check for payment execution.
  193. *
  194. * @param \Drupal\Core\Session\AccountInterface $account
  195. *
  196. * @return \Drupal\Core\Access\AccessResultInterface
  197. */
  198. protected function doExecutePaymentAccess(AccountInterface $account) {
  199. return AccessResult::allowed();
  200. }
  201. /**
  202. * {@inheritdoc}
  203. */
  204. public function executePayment() {
  205. if (!$this->getPayment()) {
  206. throw new \LogicException('Trying to execute a non-existing payment. A payment must be set trough self::setPayment() first.');
  207. }
  208. $this->eventDispatcher->preExecutePayment($this->getPayment());
  209. $this->payment->setPaymentStatus($this->paymentStatusManager->createInstance('payment_pending'));
  210. $this->doExecutePayment();
  211. $this->getPayment()->save();
  212. return $this->getPaymentExecutionResult();
  213. }
  214. /**
  215. * Performs the actual payment execution.
  216. */
  217. protected function doExecutePayment() {
  218. // This method is empty so child classes can override it and provide their
  219. // own implementation.
  220. }
  221. /**
  222. * {@inheritdoc}
  223. */
  224. public function getPaymentExecutionResult() {
  225. return new OperationResult();
  226. }
  227. /**
  228. * {@inheritdoc}
  229. */
  230. public function capturePaymentAccess(AccountInterface $account) {
  231. if (!$this->getPayment()) {
  232. throw new \LogicException('Trying to check access for a non-existing payment. A payment must be set trough self::setPayment() first.');
  233. }
  234. return $this->doCapturePaymentAccess($account);
  235. }
  236. /**
  237. * Performs a payment method-specific access check for payment capture.
  238. *
  239. * @param \Drupal\Core\Session\AccountInterface $account
  240. *
  241. * @return bool
  242. */
  243. protected function doCapturePaymentAccess(AccountInterface $account) {
  244. // Child classes must override this method to support payment capture.
  245. return AccessResult::forbidden();
  246. }
  247. /**
  248. * {@inheritdoc}
  249. */
  250. public function capturePayment() {
  251. if (!$this->getPayment()) {
  252. throw new \LogicException('Trying to capture a non-existing payment. A payment must be set trough self::setPayment() first.');
  253. }
  254. $this->eventDispatcher->preCapturePayment($this->getPayment());
  255. $this->doCapturePayment();
  256. return $this->getPaymentCaptureResult();
  257. }
  258. /**
  259. * {@inheritdoc}
  260. */
  261. public function getPaymentCaptureResult() {
  262. return new OperationResult();
  263. }
  264. /**
  265. * Performs the actual payment capture.
  266. */
  267. protected function doCapturePayment() {
  268. throw new \Exception('Child classes must override this method to support payment capture.');
  269. }
  270. /**
  271. * {@inheritdoc}
  272. */
  273. public function refundPaymentAccess(AccountInterface $account) {
  274. if (!$this->getPayment()) {
  275. throw new \LogicException('Trying to check access for a non-existing payment. A payment must be set trough self::setPayment() first.');
  276. }
  277. return $this->doRefundPaymentAccess($account);
  278. }
  279. /**
  280. * Performs a payment method-specific access check for payment refunds.
  281. *
  282. * @param \Drupal\Core\Session\AccountInterface $account
  283. *
  284. * @return bool
  285. */
  286. protected function doRefundPaymentAccess(AccountInterface $account) {
  287. // Child classes must override this method to support payment refund.
  288. return AccessResult::forbidden();
  289. }
  290. /**
  291. * {@inheritdoc}
  292. */
  293. public function refundPayment() {
  294. if (!$this->getPayment()) {
  295. throw new \LogicException('Trying to refund a non-existing payment. A payment must be set trough self::setPayment() first.');
  296. }
  297. $this->eventDispatcher->preRefundPayment($this->getPayment());
  298. $this->doRefundPayment();
  299. return $this->getPaymentRefundResult();
  300. }
  301. /**
  302. * {@inheritdoc}
  303. */
  304. public function getPaymentRefundResult() {
  305. return new OperationResult();
  306. }
  307. /**
  308. * Performs the actual payment refund.
  309. */
  310. protected function doRefundPayment() {
  311. throw new \Exception('Child classes must override this method to support payment refund.');
  312. }
  313. /**
  314. * Checks a payment's currency against this plugin.
  315. *
  316. * @param \Drupal\Core\Session\AccountInterface $account
  317. *
  318. * @return \Drupal\Core\Access\AccessResultInterface
  319. */
  320. protected function executePaymentAccessCurrency(AccountInterface $account) {
  321. $supported_currencies = $this->getSupportedCurrencies();
  322. $payment_currency_code = $this->getPayment()->getCurrencyCode();
  323. $payment_amount = $this->getPayment()->getAmount();
  324. // If all currencies are allowed, grant access.
  325. if ($supported_currencies === TRUE) {
  326. return AccessResult::allowed();
  327. }
  328. // If the payment's currency is not specified, access is denied.
  329. foreach ($supported_currencies as $supported_currency) {
  330. if ($supported_currency->getCurrencyCode() != $payment_currency_code) {
  331. continue;
  332. }
  333. // Confirm the payment amount is higher than the supported minimum.
  334. elseif ($supported_currency->getMinimumAmount() && $payment_amount < $supported_currency->getMinimumAmount()) {
  335. return AccessResult::forbidden();
  336. }
  337. // Confirm the payment amount does not exceed the maximum.
  338. elseif ($supported_currency->getMaximumAmount() && $payment_amount > $supported_currency->getMaximumAmount()) {
  339. return AccessResult::forbidden();
  340. }
  341. else {
  342. return AccessResult::allowed();
  343. }
  344. }
  345. return AccessResult::forbidden();
  346. }
  347. /**
  348. * Returns the supported currencies.
  349. *
  350. * @return \Drupal\payment\Plugin\Payment\Method\SupportedCurrencyInterface[]|true
  351. * Return TRUE to allow all currencies and amounts.
  352. */
  353. abstract protected function getSupportedCurrencies();
  354. }