Passed
Push — develop ( 2d7b42...b3143e )
by Brent
03:12
created

Htaccess::getHeaderBlock()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 6
nop 0
dl 0
loc 18
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace Brendt\Stitcher\Site\Http;
4
5
use Brendt\Stitcher\Exception\ConfigurationException;
6
use Brendt\Stitcher\Site\Page;
7
use Symfony\Component\Filesystem\Filesystem;
8
use Tivie\HtaccessParser\Parser;
9
use Tivie\HtaccessParser\Token\Block;
10
11
class Htaccess
12
{
13
    /**
14
     * @var Filesystem
15
     */
16
    private $fs;
17
18
    /**
19
     * @var Parser
20
     */
21
    private $parser;
22
23
    /**
24
     * @var array
25
     */
26
    private $contents;
27
28
    /**
29
     * Htaccess constructor.
30
     *
31
     * @param string $path
32
     *
33
     * @throws ConfigurationException
34
     */
35
    function __construct(string $path) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
36
        $this->fs = new Filesystem();
37
38
        if (!$this->fs->exists($path)) {
39
            throw ConfigurationException::fileNotFound($path);
40
        }
41
42
        $this->parser = new Parser(new \SplFileObject($path));
43
        $this->parser->ignoreWhitelines(false);
44
        $this->contents = $this->parser->parse();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->parser->parse() can also be of type object<ArrayAccess>. However, the property $contents is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
45
    }
46
47
    /**
48
     * Parse the modified .htaccess
49
     *
50
     * @return string
51
     */
52
    public function parse() : string {
53
        return (string) $this->contents;
54
    }
55
56
    /**
57
     * Get or create the headers block
58
     *
59
     * @return Block
60
     */
61
    public function &getHeaderBlock() : Block {
62
        $headerBlock = null;
63
64
        foreach ($this->contents as $content) {
65
            if ($content instanceof Block && strtolower($content->getName()) === 'ifmodule' && $content->getArguments()[0] === 'mod_headers.c') {
66
                $headerBlock = $content;
67
68
                break;
69
            }
70
        }
71
72
        if (!$headerBlock) {
73
            $headerBlock = new Block('ifmodule', 'mod_headers.c');
74
            $this->contents->append($headerBlock);
0 ignored issues
show
Bug introduced by
The method append cannot be called on $this->contents (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
75
        }
76
77
        return $headerBlock;
78
    }
79
80
    /**
81
     * Get or create a page block within the headers block
82
     *
83
     * @param Page $page
84
     *
85
     * @return mixed|null|Block
86
     */
87
    public function &getPageBlock(Page $page) {
88
        $pageBlock = null;
89
        $headerBlock = $this->getHeaderBlock();
90
        $pageId = trim($page->getId(), '/');
91
        $pageName = '"^\/' . $pageId . '.html$"';
92
93
        foreach ($headerBlock as $content) {
94
            if ($content instanceof Block && strtolower($content->getName()) === 'filesmatch' && $content->getArguments()[0] === $pageName) {
95
                $pageBlock = $content;
96
                
97
                break;
98
            }
99
        }
100
101
        if (!$pageBlock) {
102
            $pageBlock = new Block('filesmatch');
103
            $pageBlock->addArgument($pageName);
104
            $headerBlock->addChild($pageBlock);
105
        }
106
        
107
        return $pageBlock;
108
    }
109
}
110