AutomatedLinkReportTask::checkLinks()   B
last analyzed

Complexity

Conditions 8
Paths 21

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 8.1795
c 0
b 0
f 0
cc 8
nc 21
nop 0
1
<?php
2
3
/**
4
 * Class AutomatedLinkReportTask
5
 * Creates AutomatedLinkPageResult to be used in AutomatedLinkReport
6
 *
7
 * @see AutomatedLinkPageResult
8
 * @see AutomatedLinkReport
9
 *
10
 */
11
class AutomatedLinkReportTask extends Controller {
12
13
    private   $GlobalSettings;
14
    private   $Links;
15
16
    private static $exclude_classes = array('RedirectorPage', 'VirtualPage');
17
18
    public function index() {
19
        if (!Director::is_cli()) return 'Please run this controller in CLI';
20
21
        libxml_use_internal_errors(true);
22
        set_time_limit(600);
23
24
        $this->checkLinks();
25
26
        return array();
27
    }
28
29
    /**
30
     * Check each page on the site and add the data of the links
31
     * found in AutomatedLinkPageResult Objects
32
     *
33
     * @see AutomatedLinkPageResult
34
     * @return ArrayList
35
     */
36
    public function checkLinks() {
37
        $data = ArrayList::create();
38
39
        $run_in_realtime = Config::inst()->get('AutomatedLinkReport', 'run_in_realtime');
40
41
        // Enable this since we will need to render the pages for the report
42
        Config::inst()->update('SSViewer', 'theme_enabled', true);
43
44
        $this->GlobalSettings = GlobalAutoLinkSettings::get_current();
45
        $this->Links          = AutomatedLink::get()->sort('Priority');
46
        $includeInFields      = $this->GlobalSettings->IncludeInFields();
47
        if (!$this->GlobalSettings) {
48
            user_error('Run dev/build before starting to use SEOToolbox');
49
            return $data;
50
        }
51
52
        $exclude = Config::inst()->get($this->class, 'exclude_classes');
53
        $exclude = ($exclude) ? "'".implode("','", $exclude)."'" : '';
54
        foreach (SiteTree::get()->where("ClassName NOT IN($exclude)") as $page) {
55
            if (!$this->checkForPossibleLinks($page, $includeInFields)) continue;
56
            $page = $this->getLinkData($page, $includeInFields);
57
            if (!$page) continue;
58
59
            if (!$run_in_realtime) AutomatedLinkPageResult::add_or_update($page);
60
            $data->push($page);
61
        }
62
63
        if (!$run_in_realtime) AutomatedLinkPageResult::remove_old_data();
64
65
        return $data;
66
    }
67
68
    /**
69
     * Returns all the data on how the provided $page was
70
     * affected by automated links
71
     *
72
     * @param  SiteTree $page
73
     * @param  array $includeIn
74
     *
75
     * @return SiteTree|false $page
76
     */
77
    private function getLinkData(SiteTree $page, array $includeIn) {
78
        // Set a list of all fields that can have autolinks created in them
79
        $page->AutomateableFields = ArrayList::create();
80
81
        foreach (AutomatedLink::getAllDatabaseFields($page->class) as $field => $type)
82
            if (in_array($field, $includeIn) &&
83
                !$page->AutomateableFields->find('DataField', $field) &&
84
                AutomatedLink::isFieldParsable($page, $field)
85
            ) $page->AutomateableFields->push(DataObject::create(array('DataField' => $field)));
86
87
        // Get data Pre-Automated Links creation
88
        $withLinks = $this->getPageDOM($page);
89
        if (!$withLinks) return false;
90
91
        $links = $withLinks->getElementsByTagName('a');
92
93
        $page->TotalLinks           = $links->length;
94
        $page->OriginalLinkCount    = $page->TotalLinks;
95
        $page->LinkCount            = 0;
96
97
        // List all automated links that were created in this $page
98
        $linksUsed = array();
99
        foreach ($this->Links as $autolink)
100
            foreach ($links as $link) {
101
                if ($link->getAttribute('data-id') == $autolink->ID) {
102
                    $linksUsed[$autolink->ID] = $autolink->Phrase;
103
                    $page->OriginalLinkCount--;
104
                    $page->LinkCount++;
105
                }
106
            }
107
108
        $page->Links = implode(', ', $linksUsed);
109
110
        if ($page->LinkCount < 1) return false;
111
112
        return $page;
113
    }
114
115
    /**
116
     * Returns a rendered version of the page supplied
117
     * creating automated links according inside a DOMDocument
118
     * object or false if anything fails.
119
     *
120
     * @param SiteTree $page
121
     * @return DOMDocument|false
122
     */
123
    private function getPageDOM(SiteTree $page) {
124
        $controllerClass = $page->class.'_Controller';
125
        if (!class_exists($controllerClass))  $controllerClass = $page->class.'Controller';
126
        if (!class_exists($controllerClass)) return false;
127
128
        $controller = $controllerClass::create($page);
129
        $controller->invokeWithExtensions('addAutomatedLinks');
130
131
        // Set the fields with possible links into a single variable that
132
        // will be dumped in the link checker template
133
        $page->AutomateableText = '';
134
        foreach ($page->AutomateableFields as $field) {
135
            $field = $field->DataField;
136
            $page->AutomateableText .= $page->$field;
137
        }
138
139
        $content = mb_convert_encoding(
140
            $controller->renderWith('LinkCheckerTemplate'),
141
            'html-entities',
142
            GlobalAutoLinkSettings::$encoding
143
        );
144
145
        return (!$content) ? false : AutomatedLink::constructDOMDocument($content);
146
    }
147
148
    /**
149
     * Checks if the page could have the possibility of automated links
150
     *
151
     * @param SiteTree $page
152
     * @param array $includeIn
153
     *
154
     * @return Boolean
155
     */
156
    private function checkForPossibleLinks(SiteTree $page, array $includeIn) {
157
        foreach ($this->Links as $link)
158
            foreach ($includeIn as $possibleField)
159
                if (isset($page->$possibleField) && preg_match("/\b{$link->Phrase}\b/i", $page->$possibleField)) return true;
160
161
        return false;
162
    }
163
164
}
165