Completed
Push — 2.0.0 ( 2709ae...062d78 )
by John
04:52 queued 10s
created

MarkdownFacade::__construct()   D

Complexity

Conditions 14
Paths 168

Size

Total Lines 77
Code Lines 47

Duplication

Lines 37
Ratio 48.05 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
c 3
b 1
f 1
dl 37
loc 77
rs 4.8435
cc 14
eloc 47
nc 168
nop 2

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
namespace Alpha\Util\Extension;
4
5
use Alpha\Util\Config\ConfigProvider;
6
use Alpha\View\Widget\Image;
7
use Alpha\Exception\AlphaException;
8
9
/**
10
 * A facade class for the Markdown library.
11
 *
12
 * @since 1.0
13
 *
14
 * @author John Collins <[email protected]>
15
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
16
 * @copyright Copyright (c) 2015, John Collins (founder of Alpha Framework).
17
 * All rights reserved.
18
 *
19
 * <pre>
20
 * Redistribution and use in source and binary forms, with or
21
 * without modification, are permitted provided that the
22
 * following conditions are met:
23
 *
24
 * * Redistributions of source code must retain the above
25
 *   copyright notice, this list of conditions and the
26
 *   following disclaimer.
27
 * * Redistributions in binary form must reproduce the above
28
 *   copyright notice, this list of conditions and the
29
 *   following disclaimer in the documentation and/or other
30
 *   materials provided with the distribution.
31
 * * Neither the name of the Alpha Framework nor the names
32
 *   of its contributors may be used to endorse or promote
33
 *   products derived from this software without specific
34
 *   prior written permission.
35
 *
36
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
37
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
38
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
39
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
41
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
47
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
48
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49
 * </pre>
50
 */
51
class MarkdownFacade
52
{
53
    /**
54
     * The markdown-format content that we will render.
55
     *
56
     * @var string
57
     *
58
     * @since 1.0
59
     */
60
    private $content;
61
62
    /**
63
     * The business object that stores the content will be rendered to Markdown.
64
     *
65
     * @var Alpha\Model\ActiveRecord
66
     *
67
     * @since 1.0
68
     */
69
    private $BO = null;
70
71
    /**
72
     * The auto-generated name of the Markdown HTML cache file for the BO.
73
     *
74
     * @var string
75
     *
76
     * @since 1.0
77
     */
78
    private $filename;
79
80
    /**
81
     * The constructor.
82
     *
83
     * @param Alpha\Model\ActiveRecord $BO
84
     * @param bool                     $useCache
85
     *
86
     * @since 1.0
87
     */
88
    public function __construct($BO, $useCache = true)
89
    {
90
        $config = ConfigProvider::getInstance();
91
92
        $this->BO = $BO;
93
94
        if ($this->BO instanceof \Alpha\Model\Article && $this->BO->isLoadedFromFile()) {
95
            $underscoreTimeStamp = str_replace(array('-', ' ', ':'), '_', $this->BO->getContentFileDate());
96
            $this->filename = $config->get('app.file.store.dir').'cache/html/'.get_class($this->BO).'_'.$this->BO->get('title').'_'.$underscoreTimeStamp.'.html';
97
        } else {
98
            $this->filename = $config->get('app.file.store.dir').'cache/html/'.get_class($this->BO).'_'.$this->BO->getID().'_'.$this->BO->getVersion().'.html';
99
        }
100
101
        if (!$useCache) {
102
            $this->content = $this->markdown($this->BO->get('content', true));
103
        } else {
104
            if ($this->checkCache()) {
105
                $this->loadCache();
106
            } else {
107
                if ($this->BO->get('content', true) == '') {
108
                    // the content may not be loaded from the DB at this stage due to a previous soft-load
109
                    $this->BO->reload();
110
                }
111
112
                $this->content = $this->markdown($this->BO->get('content', true));
113
114
                $this->cache();
115
            }
116
        }
117
118
        // Replace all instances of $attachURL in link tags to links to the ViewAttachment controller
119
        $attachments = array();
120
        preg_match_all('/href\=\"\$attachURL\/.*\"/', $this->content, $attachments);
121
122 View Code Duplication
        foreach ($attachments[0] as $attachmentURL) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123
            $start = mb_strpos($attachmentURL, '/');
124
            $end = mb_strrpos($attachmentURL, '"');
125
            $fileName = mb_substr($attachmentURL, $start + 1, $end - ($start + 1));
126
127
            if (method_exists($this->BO, 'getAttachmentSecureURL')) {
128
                $this->content = str_replace($attachmentURL, 'href="'.$this->BO->getAttachmentSecureURL($fileName).'" rel="nofollow"', $this->content);
129
            }
130
        }
131
132
        // Handle image attachments
133
        $attachments = array();
134
        preg_match_all('/\<img\ src\=\"\$attachURL\/.*\".*\>/', $this->content, $attachments);
135
136 View Code Duplication
        foreach ($attachments[0] as $attachmentURL) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
137
            $start = mb_strpos($attachmentURL, '/');
138
            $end = mb_strrpos($attachmentURL, '" alt');
139
            $fileName = mb_substr($attachmentURL, $start + 1, $end - ($start + 1));
140
141
            if ($config->get('cms.images.widget')) {
142
                // get the details of the source image
143
                $path = $this->BO->getAttachmentsLocation().'/'.$fileName;
144
                $image_details = getimagesize($path);
145
                $imgType = $image_details[2];
146
                if ($imgType == 1) {
147
                    $type = 'gif';
148
                } elseif ($imgType == 2) {
149
                    $type = 'jpg';
150
                } elseif ($imgType == 3) {
151
                    $type = 'png';
152
                }
153
154
                $img = new Image($path, $image_details[0], $image_details[1], $type, 0.95, false, (boolean) $config->get('cms.images.widget.secure'));
0 ignored issues
show
Bug introduced by
The variable $type does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
155
156
                $this->content = str_replace($attachmentURL, $img->renderHTMLLink(), $this->content);
157
            } else {
158
                // render a normal image link to the ViewAttachment controller
159
                if (method_exists($this->BO, 'getAttachmentSecureURL')) {
160
                    $this->content = str_replace($attachmentURL, '<img src="'.$this->BO->getAttachmentSecureURL($fileName).'">', $this->content);
161
                }
162
            }
163
        }
164
    }
165
166
    /**
167
     * Facade method which will invoke our custom markdown class rather than the standard one.
168
     *
169
     * @return string
170
     *
171
     * @since 1.0
172
     */
173 View Code Duplication
    public function markdown($text)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
174
    {
175
        $config = ConfigProvider::getInstance();
176
177
        // Initialize the parser and return the result of its transform method.
178
        static $parser;
179
180
        if (!isset($parser)) {
181
            $parser = new \Alpha\Util\Extension\Markdown();
182
        }
183
184
        /*
185
         * Replace all instances of $sysURL in the text with the app.url setting from config
186
         */
187
        $text = str_replace('$sysURL', $config->get('app.url'), $text);
188
189
        // transform text using parser.
190
        return $parser->transform($text);
191
    }
192
193
    /**
194
     * Getter for the content.
195
     *
196
     * @return string
197
     *
198
     * @since 1.0
199
     */
200
    public function getContent()
201
    {
202
        return $this->content;
203
    }
204
205
    /**
206
     * Saves the HTML generated by Markdown to the cache directory.
207
     *
208
     * @throws Alpha\Exception\AlphaException
209
     *
210
     * @since 1.0
211
     */
212 View Code Duplication
    private function cache()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
213
    {
214
        // check to ensure that the article is not transient before caching it
215
        if (!$this->BO->isTransient() && $this->filename != '') {
216
            $fp = fopen($this->filename, 'w');
217
            if (!$fp) {
218
                throw new AlphaException('Failed to open the cache file for writing, directory permissions my not be set correctly!');
219
            } else {
220
                flock($fp, 2); // locks the file for writting
221
                fwrite($fp, $this->content);
222
                flock($fp, 3); // unlocks the file
223
                fclose($fp); //closes the file
224
            }
225
        }
226
    }
227
228
    /**
229
     * Used to check the HTML cache for the BO cache file.
230
     *
231
     * @return bool
232
     *
233
     * @since 1.0
234
     */
235
    public function checkCache()
236
    {
237
        return file_exists($this->filename);
238
    }
239
240
    /**
241
     * Method to load the content of the cache file to the $content attribute of this object.
242
     *
243
     * @throws Alpha\Exception\AlphaException
244
     *
245
     * @since 1.0
246
     */
247 View Code Duplication
    public function loadCache()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
    {
249
        $fp = fopen($this->filename, 'r');
250
251
        if (!$fp) {
252
            throw new AlphaException('Failed to open the cache file for reading, directory permissions my not be set correctly!');
253
        } else {
254
            $this->content = fread($fp, filesize($this->filename));
255
            fclose($fp); //closes the file
256
        }
257
    }
258
}
259