DisableSubmit::closest()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 16
rs 10
1
<?php
2
/**
3
 * Copyright (c) 2022. Volodymyr Hryvinskyi.  All rights reserved.
4
 * @author: <mailto:[email protected]>
5
 * @github: <https://github.com/hryvinskyi>
6
 */
7
8
declare(strict_types=1);
9
10
namespace Hryvinskyi\InvisibleCaptcha\Plugin;
11
12
use Hryvinskyi\InvisibleCaptcha\Helper\Config\General;
13
use Magento\Framework\App\Request\Http as RequestHttp;
14
use Magento\Framework\App\ResponseInterface;
15
use Magento\Framework\Controller\ResultInterface;
16
use Psr\Log\LoggerInterface;
17
use Symfony\Component\DomCrawler\Crawler;
18
use voku\helper\HtmlDomParser;
0 ignored issues
show
Bug introduced by
The type voku\helper\HtmlDomParser was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use voku\helper\SimpleHtmlDom;
20
use voku\helper\SimpleHtmlDomInterface;
21
22
/**
23
 * Class DisableSubmit
24
 */
25
class DisableSubmit
26
{
27
    /**
28
     * @var RequestHttp
29
     */
30
    private $request;
31
32
    /**
33
     * @var General
34
     */
35
    private $generalConfig;
36
37
    /**
38
     * @var LoggerInterface
39
     */
40
    private $logger;
41
42
    /**
43
     * MergeJson constructor.
44
     *
45
     * @param RequestHttp $request
46
     * @param General $generalConfig
47
     * @param LoggerInterface $logger
48
     */
49
    public function __construct(
50
        RequestHttp $request,
51
        General $generalConfig,
52
        LoggerInterface $logger
53
    ) {
54
        $this->request = $request;
55
        $this->generalConfig = $generalConfig;
56
        $this->logger = $logger;
57
    }
58
59
    /**
60
     * @param ResultInterface $subject
61
     * @param \Closure $proceed
62
     * @param ResponseInterface $response
63
     *
64
     * @return string
65
     */
66
    public function aroundRenderResult(
67
        ResultInterface $subject,
0 ignored issues
show
Unused Code introduced by
The parameter $subject is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

67
        /** @scrutinizer ignore-unused */ ResultInterface $subject,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
68
        \Closure $proceed,
69
        ResponseInterface $response
70
    ) {
71
        $result = $proceed($response);
72
73
        if (
74
            PHP_SAPI === 'cli' ||
75
            $this->request->isXmlHttpRequest() === true ||
76
            $this->generalConfig->isDisabledSubmitForm() === false
77
        ) {
78
            return $result;
79
        }
80
81
        $html = $response->getBody();
0 ignored issues
show
Bug introduced by
The method getBody() does not exist on Magento\Framework\App\ResponseInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Magento\Framework\App\Response\HttpInterface or Magento\Framework\App\Response\FileInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

81
        /** @scrutinizer ignore-call */ 
82
        $html = $response->getBody();
Loading history...
82
        $dom = new HtmlDomParser();
83
84
        $dom->overwriteSpecialScriptTags([
85
            'text/html',
86
            'text/x-magento-template',
87
            'text/x-custom-template',
88
            'text/x-handlebars-template',
89
        ]);
90
91
        $dom = $dom->loadHtml($html);
92
93
        try {
94
            $elements = $dom->findMultiOrFalse('[data-hryvinskyi-recaptcha="default"]');
95
96
            if ($elements !== false) {
97
                foreach ($elements as $element) {
98
                    $form = $this->closest($element, 'form');
99
100
                    $form->setAttribute('onsubmit', 'return false;' .
101
                        $form->getAttribute('onsubmit'));
102
                    $form->setAttribute('class', $form->getAttribute('class') .
103
                        ' hryvinskyi-recaptcha-disabled-submit');
104
                }
105
            }
106
107
            $elementsTarget = $dom->findMultiOrFalse('[data-hryvinskyi-recaptcha="target"]');
108
109
            if ($elementsTarget !== false) {
110
                foreach ($elementsTarget as $element) {
111
                    $target = $dom->findOneOrFalse($element->getAttribute('data-hryvinskyi-recaptcha-target'));
112
                    if ($target !== false) {
113
                        $target->setAttribute('onsubmit', 'return false;' .
114
                            $target->getAttribute('onsubmit'));
115
                        $target->setAttribute('class', $target->getAttribute('class') .
116
                            ' hryvinskyi-recaptcha-disabled-submit');
117
                    }
118
                }
119
            }
120
121
            if ($elements !== false || $elementsTarget !== false) {
122
                $response->setBody((string)$dom);
123
            }
124
        } catch (\Throwable $e) {
125
            $response->setBody($html);
126
            $this->logger->critical($e->getMessage());
127
        }
128
129
        return $result;
130
    }
131
132
    /**
133
     * Return first parents (heading toward the document root) of the Element that matches the provided selector.
134
     *
135
     * @param SimpleHtmlDomInterface $element
136
     * @param string $selector
137
     * @return \DOMNode|SimpleHtmlDom
138
     */
139
    public function closest($element, string $selector)
140
    {
141
        $domNode = $element->getNode();
142
143
        while (XML_ELEMENT_NODE === $domNode->nodeType) {
144
            $symfonyNode = new Crawler($domNode);
145
            $domNode = new SimpleHtmlDom($domNode);
146
147
            if ($symfonyNode->matches($selector)) {
148
                return $domNode;
149
            }
150
151
            $domNode = $symfonyNode->getNode(0)->parentNode;
152
        }
153
154
        return $domNode;
155
    }
156
}
157