PageContentReader::normalizePath()   B
last analyzed

Complexity

Conditions 8
Paths 8

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
rs 7.7777
cc 8
eloc 7
nc 8
nop 1
1
<?php
2
3
/**
4
 * @author    Markus Tacker <[email protected]>
5
 * @copyright 2013-2016 Verein zur Förderung der Netzkultur im Rhein-Main-Gebiet e.V. | http://netzkultur-rheinmain.de/
6
 */
7
8
namespace BCRM\WebBundle\Content;
9
10
use BCRM\BackendBundle\Content\Content;
11
use BCRM\BackendBundle\Content\FileContentReader;
12
use Doctrine\Common\Collections\ArrayCollection;
13
use Knp\Bundle\MarkdownBundle\MarkdownParserInterface;
14
15
class PageContentReader extends FileContentReader implements ContentReader
16
{
17
    /**
18
     * @var \Knp\Bundle\MarkdownBundle\MarkdownParserInterface
19
     */
20
    private $parser;
21
22
    public function __construct($contentDir, $contentPath, MarkdownParserInterface $parser)
23
    {
24
        parent::__construct($contentDir, $contentPath);
25
        $this->parser = $parser;
26
    }
27
28
    /**
29
     * @param string $path
30
     *
31
     * @return Page
32
     */
33
    public function getPage($path)
34
    {
35
        return $this->buildPage($path);
36
    }
37
38
    /**
39
     * @param string $path
40
     * @param bool   $fetchSubNav
41
     *
42
     * @return Page
43
     */
44
    protected function buildPage($path, $fetchSubNav = true)
45
    {
46
        $p = $this->transformContent(parent::getContent($path), $path);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getContent() instead of buildPage()). Are you sure this is correct? If so, you might want to change this to $this->getContent().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
47
        if ($fetchSubNav) {
48
            $subNav = array();
49
            foreach ($this->getSubnav($this->getFilePath($path)) as $subPage) {
50
                $s = $this->buildPage($subPage, false);
51
                if ($s->isHidden()) continue;
52
                $n = new Nav();
53
                $n->setTitle($s->getProperties()->get('title'));
54
                $n->setPath(str_replace('.md', '', $subPage));
55
                $subNav[]      = $n;
56
                $subNavOrder[] = (int)$s->getProperties()->get('order');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$subNavOrder was never initialized. Although not strictly required by PHP, it is generally a good practice to add $subNavOrder = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
57
            }
58
            array_multisort($subNavOrder, SORT_ASC, $subNav);
59
            $p->setSubnav(new ArrayCollection($subNav));
60
        }
61
        return $p;
62
    }
63
64
    /**
65
     * @param Content $c
66
     * @param string  $path
67
     *
68
     * @return Page
69
     */
70 View Code Duplication
    protected function transformContent(Content $c, $path)
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...
71
    {
72
        $markdown = $c->getContent();
73
        $markdown = $this->removeProperties($markdown);
74
        $html     = $this->parser->transformMarkdown($markdown);
75
        $html     = $this->fixLinks($html, $path);
76
        $page     = new Page();
77
        $page->setContent($html);
78
        $page->setProperties(new ArrayCollection(array_merge($page->getProperties()->toArray(), $c->getProperties()->toArray())));
79
        return $page;
80
    }
81
82
    protected function fixLinks($html, $page)
83
    {
84
        if (!preg_match_all('/src="([^"]+)"/', $html, $matches, PREG_SET_ORDER)) return $html;
85
        $path = $this->contentPath . '/' . dirname($page) . '/';
86
        foreach ($matches as $match) {
87
            $srcpath = $this->normalizePath($path . $match[1]);
88
            $html    = str_replace($match[1], $srcpath, $html);
89
        }
90
        return $html;
91
    }
92
93
    /**
94
     * @param $path
95
     *
96
     * @return string
97
     * @see http://www.php.net/manual/en/function.realpath.php#81935
98
     */
99
    protected function normalizePath($path)
100
    {
101
        $out = array();
102
        foreach (explode('/', $path) as $i => $fold) {
103
            if ($fold == '' || $fold == '.') continue;
104
            if ($fold == '..' && $i > 0 && end($out) != '..') array_pop($out);
105
            else $out[] = $fold;
106
        }
107
        return ($path{0} == '/' ? '/' : '') . join('/', $out);
108
    }
109
110
    protected function getSubnav(\SplFileInfo $file)
111
    {
112
        $dir        = dirname($file->getPathname()) . DIRECTORY_SEPARATOR;
113
        $contentdir = $this->contentDir->getPathname() . DIRECTORY_SEPARATOR;
114
        return array_map(function ($entry) use ($contentdir) {
115
            $entry = str_replace($contentdir, '', $entry);
116
            return $entry;
117
        }, glob($dir . '*.md'));
118
    }
119
}
120