Completed
Pull Request — devel (#1212)
by Aric
02:57
created

getBlockAction()   D

Complexity

Conditions 15
Paths 86

Size

Total Lines 87
Code Lines 76

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 87
rs 4.9121
cc 15
eloc 76
nc 86
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Nexcess.net Turpentine Extension for Magento
5
 * Copyright (C) 2012  Nexcess.net L.L.C.
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 */
21
22
class Nexcessnet_Turpentine_EsiController extends Mage_Core_Controller_Front_Action {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
23
    /**
24
     * It seems this has to exist so we just make it redirect to the base URL
25
     * for lack of anything better to do.
26
     *
27
     * @return null
28
     */
29
    public function indexAction() {
30
        $this->getResponse()->setRedirect(Mage::getBaseUrl());
31
    }
32
33
    /**
34
     * Spit out the form key for this session
35
     *
36
     * @return null
37
     */
38
    public function getFormKeyAction() {
39
        $resp = $this->getResponse();
40
        $resp->setBody(
41
            Mage::getSingleton('core/session')->real_getFormKey() );
42
        $resp->setHeader('X-Turpentine-Cache', '1');
43
        $resp->setHeader('X-Turpentine-Flush-Events',
44
            implode(',', Mage::helper('turpentine/esi')
45
                ->getDefaultCacheClearEvents()));
46
        $resp->setHeader('X-Turpentine-Block', 'form_key');
47
        Mage::register('turpentine_nocache_flag', false, true);
48
49
        Mage::helper('turpentine/debug')->logDebug('Generated form_key: %s',
50
            $resp->getBody());
51
    }
52
53
    /**
54
     * Spit out the rendered block from the URL-encoded data
55
     *
56
     * @return null
57
     */
58
    public function getBlockAction() {
59
        $resp = $this->getResponse();
60
        $cacheFlag = false;
61
        if (Mage::helper('turpentine/esi')->shouldResponseUseEsi()) {
62
            $req = $this->getRequest();
63
            $esiHelper = Mage::helper('turpentine/esi');
64
            $dataHelper = Mage::helper('turpentine/data');
65
            $debugHelper = Mage::helper('turpentine/debug');
66
            $esiDataHmac = $req->getParam($esiHelper->getEsiHmacParam());
67
            $esiDataParamValue = $req->getParam($esiHelper->getEsiDataParam());
68
            if ($esiDataHmac !== ($hmac = $dataHelper->getHmac($esiDataParamValue))) {
69
                $debugHelper->logWarn('ESI data HMAC mismatch, expected (%s) but received (%s)',
70
                    $hmac, $esiDataHmac);
71
                $resp->setHttpResponseCode(500);
72
                $resp->setBody('ESI data is not valid');
73
            } elseif ( ! ($esiDataArray = $dataHelper->thaw($esiDataParamValue))) {
74
                $debugHelper->logWarn('Invalid ESI data in URL: %s',
75
                    $esiDataParamValue);
76
                $resp->setHttpResponseCode(500);
77
                $resp->setBody('ESI data is not valid');
78
            } elseif ( ! $esiHelper->getEsiDebugEnabled() &&
79
                    $esiDataArray['esi_method'] !==
80
                    $req->getParam($esiHelper->getEsiMethodParam())) {
81
                $resp->setHttpResponseCode(403);
82
                $resp->setBody('ESI method mismatch');
83
                $debugHelper->logWarn('Blocking change of ESI method: %s -> %s',
84
                    $esiDataArray['esi_method'],
85
                    $req->getParam($esiHelper->getEsiMethodParam()));
86
            } else {
87
                $esiData = new Varien_Object($esiDataArray);
88
                $origRequest = Mage::app()->getRequest();
89
                Mage::app()->setCurrentStore(
90
                    Mage::app()->getStore($esiData->getStoreId()) );
91
                $appShim = Mage::getModel('turpentine/shim_mage_core_app');
92
                if ($referer = $this->_getRefererUrl()) {
93
                    $referer = htmlspecialchars_decode($referer);
94
                    $dummyRequest = Mage::helper('turpentine/esi')
95
                        ->getDummyRequest($referer);
96
                } else {
97
                    $dummyRequest = Mage::helper('turpentine/esi')
98
                        ->getDummyRequest();
99
                }
100
                $appShim->shim_setRequest($dummyRequest);
101
                $block = $this->_getEsiBlock($esiData);
102
                if ($block) {
103
                    $blockEsiOptions = $block->getEsiOptions();
104
                    $block->setEsiOptions(false);
105
                    $resp->setBody($block->toHtml());
106
                    if ((int) $req->getParam($esiHelper->getEsiTtlParam()) > 0) {
107
                        $cacheFlag = true;
108
                        if (isset($blockEsiOptions['only_cache_if'])) {
109
                            switch ($blockEsiOptions['only_cache_if']) {
110
                                case 'empty':
111
                                    $cacheFlag = ('' === $resp->getBody());
112
                                    break;
113
                                case 'no_text':
114
                                    $cacheFlag = ('' === trim(strip_tags($resp->getBody())));
115
                                    break;
116
                                default:
117
                                    $cacheFlag = false;
118
                            }
119
                        }
120
                    }
121
                    if ($esiData->getEsiMethod() == 'ajax') {
122
                        $resp->setHeader('Access-Control-Allow-Origin',
123
                            $esiHelper->getCorsOrigin());
124
                    }
125
                    if ( ! is_null($flushEvents = $esiData->getFlushEvents())) {
126
                        $resp->setHeader('X-Turpentine-Flush-Events',
127
                            implode(',', $flushEvents));
128
                    }
129
                    if ($esiHelper->getEsiDebugEnabled()) {
130
                        $resp->setHeader('X-Turpentine-Block',
131
                            $block->getNameInLayout());
132
                    }
133
                } else {
134
                    $resp->setHttpResponseCode(404);
135
                    $resp->setBody('ESI block not found');
136
                }
137
                $appShim->shim_setRequest($origRequest);
138
            }
139
        } else {
140
            $resp->setHttpResponseCode(403);
141
            $resp->setBody('ESI includes are not enabled');
142
        }
143
        Mage::register('turpentine_nocache_flag', ! $cacheFlag, true);
144
    }
145
146
    /**
147
     * Need to disable this flag to prevent setting the last URL but we
148
     * don't want to completely break sessions.
149
     *
150
     * see Mage_Core_Controller_Front_Action::postDispatch
151
     *
152
     * @return null
153
     */
154
    public function postDispatch() {
155
        $flag = $this->getFlag('', self::FLAG_NO_START_SESSION);
156
        $this->setFlag('', self::FLAG_NO_START_SESSION, true);
157
        parent::postDispatch();
158
        $this->setFlag('', self::FLAG_NO_START_SESSION, $flag);
159
    }
160
161
    /**
162
     * Generate the ESI block
163
     *
164
     * @param  Varien_Object $esiData
165
     * @return Mage_Core_Block_Template|null
166
     */
167
    protected function _getEsiBlock($esiData) {
168
        $block = null;
0 ignored issues
show
Unused Code introduced by
$block is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
169
        Varien_Profiler::start('turpentine::controller::esi::_getEsiBlock');
170
        foreach ($esiData->getSimpleRegistry() as $key => $value) {
171
            Mage::register($key, $value, true);
172
        }
173
        foreach ($esiData->getComplexRegistry() as $key => $data) {
174
            $value = Mage::getModel($data['model']);
175
            if ( ! is_object($value)) {
176
                Mage::helper('turpentine/debug')->logWarn(
177
                    'Failed to register key/model: %s as %s(%s)',
178
                    $key, $data['model'], $data['id'] );
179
                continue;
180
            } else {
181
                $value->load($data['id']);
182
                Mage::register($key, $value, true);
183
            }
184
        }
185
        $layout = Mage::getSingleton('core/layout');
186
187
        // dispatch event for adding handles to layout update
188
        Mage::dispatchEvent(
189
            'controller_action_layout_load_before',
190
            array('action'=>$this, 'layout'=>$layout)
191
        );
192
193
        $layoutUpdate = $layout->getUpdate();
194
        $layoutUpdate->load($this->_swapCustomerHandles(
195
            $esiData->getLayoutHandles() ));
196
        foreach ($esiData->getDummyBlocks() as $blockName) {
197
            $layout->createBlock('Mage_Core_Block_Template', $blockName);
198
        }
199
200
        if ( ! $this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) {
201
            Mage::dispatchEvent(
202
                'controller_action_layout_generate_xml_before',
203
                array('action'=>$this, 'layout'=>$layout)
204
            );
205
        }
206
        $layout->generateXml();
207
208
        /** @var Nexcessnet_Turpentine_Helper_Data $turpentineHelper */
209
        $turpentineHelper = Mage::helper('turpentine/data')
210
            ->setLayout($layout);
211
212
        $blockNode = current($layout->getNode()->xpath(
213
                sprintf('//block[@name=\'%s\']', $esiData->getNameInLayout())
214
            ));
215
216
        if ( ! ($blockNode instanceof Mage_Core_Model_Layout_Element)) {
0 ignored issues
show
Bug introduced by
The class Mage_Core_Model_Layout_Element does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
217
            Mage::helper('turpentine/debug')->logWarn(
218
                            'No block node found with @name="%s"',
219
                            $esiData->getNameInLayout() );
220
            return null;
221
        }
222
223
        $nodesToGenerate = $turpentineHelper->getChildBlockNames($blockNode);
224
        Mage::getModel('turpentine/shim_mage_core_layout')
225
            ->shim_generateFullBlock($blockNode);
226
227
        //find addional blocks that aren't defined in the <block/> but via <reference name="%s">
228
        $referenceNodes = $layout->getNode()->xpath(sprintf(
229
            '//reference[@name=\'%s\']',
230
            $esiData->getNameInLayout() ));
231
        if ($referenceNodes) {
232
            foreach ($referenceNodes as $referenceNode) {
233
                if ($referenceNode instanceof Mage_Core_Model_Layout_Element) {
0 ignored issues
show
Bug introduced by
The class Mage_Core_Model_Layout_Element does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
234
                    $referencesToGenerate = $turpentineHelper
235
                        ->getChildBlockNames($referenceNode);
236
                    $nodesToGenerate =
237
                        array_merge($nodesToGenerate, $referencesToGenerate);
238
                }
239
            }
240
        }
241
242
        // dispatch event for adding xml layout elements
243
        if ( ! $this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) {
244
            Mage::dispatchEvent(
245
                'controller_action_layout_generate_blocks_before',
246
                array('action'=>$this, 'layout'=>$layout)
247
            );
248
        }
249
250
        foreach (array_unique($nodesToGenerate) as $nodeName) {
251
            foreach ($layout->getNode()->xpath(sprintf(
252
                    '//reference[@name=\'%s\']', $nodeName )) as $node) {
253
                $layout->generateBlocks($node);
254
            }
255
        }
256
        $block = $layout->getBlock($esiData->getNameInLayout());
257
258
        if ( ! $this->getFlag('', self::FLAG_NO_DISPATCH_BLOCK_EVENT)) {
259
            Mage::dispatchEvent(
260
                'controller_action_layout_generate_blocks_after',
261
                array('action'=>$this, 'layout'=>$layout)
262
            );
263
        }
264
265
        $this->_isLayoutLoaded = true;
266
        Varien_Profiler::stop('turpentine::controller::esi::_getEsiBlock');
267
        return $block;
268
    }
269
270
    /**
271
     * Swap customer_logged_in and customer_logged_out cached handles based on
272
     * actual customer login status. Fixes stale Login/Logout links (and
273
     * probably other things).
274
     *
275
     * This is definitely a hack, need a more general solution to this problem.
276
     *
277
     * @param  array $handles
278
     * @return array
279
     */
280
    protected function _swapCustomerHandles($handles) {
281
        if (Mage::helper('customer')->isLoggedIn()) {
282
            $replacement = array('customer_logged_out', 'customer_logged_in');
283
        } else {
284
            $replacement = array('customer_logged_in', 'customer_logged_out');
285
        }
286
        if (($pos = array_search($replacement[0], $handles)) !== false) {
287
            $handles[$pos] = $replacement[1];
288
        }
289
        return $handles;
290
    }
291
}
292