Completed
Push — master ( 366a5b...a17b2a )
by
unknown
17:34 queued 14:29
created

ext_update::updateMetadataConfig()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 49

Duplication

Lines 13
Ratio 26.53 %

Importance

Changes 0
Metric Value
cc 5
nc 7
nop 0
dl 13
loc 49
rs 8.8016
c 0
b 0
f 0
1
<?php
2
/**
3
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
4
 *
5
 * This file is part of the Kitodo and TYPO3 projects.
6
 *
7
 * @license GNU General Public License version 3 or later.
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
use Kitodo\Dlf\Common\Helper;
13
use Kitodo\Dlf\Common\Solr;
14
15
/**
16
 * Update class 'ext_update' for the 'dlf' extension
17
 *
18
 * @author Sebastian Meyer <[email protected]>
19
 * @package TYPO3
20
 * @subpackage dlf
21
 * @access public
22
 */
23
class ext_update {
24
    /**
25
     * This holds the output ready to return
26
     *
27
     * @var string
28
     * @access protected
29
     */
30
    protected $content = '';
31
32
    /**
33
     * Triggers the update option in the extension manager
34
     *
35
     * @access public
36
     *
37
     * @return boolean Should the update option be shown?
38
     */
39
    public function access() {
40
        if (count($this->getMetadataConfig())) {
41
            return TRUE;
42
        } elseif ($this->oldIndexRelatedTableNames()) {
43
            return TRUE;
44
        } elseif ($this->solariumSolrUpdateRequired()) {
45
            return TRUE;
46
        } elseif (count($this->oldFormatClasses())) {
47
            return TRUE;
48
        }
49
        return FALSE;
50
    }
51
52
    /**
53
     * Get all outdated metadata configuration records
54
     *
55
     * @access protected
56
     *
57
     * @return array Array of UIDs of outdated records
58
     */
59
    protected function getMetadataConfig() {
60
        $uids = [];
61
        // check if tx_dlf_metadata.xpath exists anyhow
62
        $fieldsInDatabase = $GLOBALS['TYPO3_DB']->admin_get_fields('tx_dlf_metadata');
63
        if (!in_array('xpath', array_keys($fieldsInDatabase))) {
64
            return $uids;
65
        }
66
        // Get all records with outdated configuration.
67
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
68
            'tx_dlf_metadata.uid AS uid',
69
            'tx_dlf_metadata',
70
            'tx_dlf_metadata.format=0'
71
                .' AND NOT tx_dlf_metadata.xpath=""'
72
                .Helper::whereClause('tx_dlf_metadata'),
73
            '',
74
            '',
75
            ''
76
        );
77
        if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
78
            while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
79
                $uids[] = intval($resArray['uid']);
80
            }
81
        }
82
        return $uids;
83
    }
84
85
    /**
86
     * The main method of the class
87
     *
88
     * @access public
89
     *
90
     * @return string The content that is displayed on the website
91
     */
92
    public function main() {
93
        // Load localization file.
94
        $GLOBALS['LANG']->includeLLFile('EXT:dlf/Resources/Private/Language/FlashMessages.xml');
95
        // Update the metadata configuration.
96
        if (count($this->getMetadataConfig())) {
97
            $this->updateMetadataConfig();
98
        }
99
        if ($this->oldIndexRelatedTableNames()) {
100
            $this->renameIndexRelatedColumns();
101
        }
102
        if ($this->solariumSolrUpdateRequired()) {
103
            $this->doSolariumSolrUpdate();
104
        }
105
        if (count($this->oldFormatClasses())) {
106
            $this->updateFormatClasses();
107
        }
108
        return $this->content;
109
    }
110
111
    /**
112
     * Check for old format classes
113
     *
114
     * @access protected
115
     *
116
     * @return boolean true if old format classes exist
117
     */
118
    protected function oldFormatClasses() {
119
        $oldRecords = [];
120
        // Get all records with outdated configuration.
121
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
122
            'tx_dlf_formats.uid AS uid,tx_dlf_formats.type AS type',
123
            'tx_dlf_formats',
124
            'tx_dlf_formats.class NOT LIKE "%\\\\\\\\%"' // We are looking for a single backslash...
125
                .Helper::whereClause('tx_dlf_formats'),
126
            '',
127
            '',
128
            ''
129
        );
130
        while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
131
            $oldRecords[$resArray['uid']] = $resArray['type'];
132
        }
133
        return $oldRecords;
134
    }
135
136
    /**
137
     * Check for old index related colums
138
     *
139
     * @access protected
140
     *
141
     * @return boolean TRUE if old index related columns exist
142
     */
143
    protected function oldIndexRelatedTableNames() {
144
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
145
            'column_name',
146
            'INFORMATION_SCHEMA.COLUMNS',
147
            'TABLE_NAME = "tx_dlf_metadata"',
148
            '',
149
            '',
150
            ''
151
        );
152
        while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
153
            if ($resArray['column_name'] == 'tokenized'
154
                || $resArray['column_name'] == 'stored'
155
                || $resArray['column_name'] == 'indexed'
156
                || $resArray['column_name'] == 'boost'
157
                || $resArray['column_name'] == 'autocomplete') {
158
                    return TRUE;
159
            }
160
        }
161
    }
162
163
    /**
164
     * Copy the data of the old index related columns to the new columns
165
     *
166
     * @access protected
167
     *
168
     * @return void
169
     */
170
    protected function renameIndexRelatedColumns() {
171
        $sqlQuery = 'UPDATE tx_dlf_metadata'
172
            .' SET `index_tokenized` = `tokenized`'
173
            .', `index_stored` = `stored`'
174
            .', `index_indexed` = `indexed`'
175
            .', `index_boost` = `boost`'
176
            .', `index_autocomplete` = `autocomplete`';
177
        // Copy the content of the old tables to the new ones
178
        $result = $GLOBALS['TYPO3_DB']->sql_query($sqlQuery);
179 View Code Duplication
        if ($result) {
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...
180
            Helper::addMessage(
181
                $GLOBALS['LANG']->getLL('update.copyIndexRelatedColumnsOkay', TRUE),
182
                $GLOBALS['LANG']->getLL('update.copyIndexRelatedColumns', TRUE),
183
                \TYPO3\CMS\Core\Messaging\FlashMessage::OK
184
            );
185
        } else {
186
            Helper::addMessage(
187
                $GLOBALS['LANG']->getLL('update.copyIndexRelatedColumnsNotOkay', TRUE),
188
                $GLOBALS['LANG']->getLL('update.copyIndexRelatedColumns', TRUE),
189
                \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING
190
            );
191
        }
192
        $this->content .= Helper::renderFlashMessages();
193
    }
194
195
    /**
196
     * Update all outdated format records
197
     *
198
     * @access protected
199
     *
200
     * @return void
201
     */
202
    protected function updateFormatClasses() {
203
        $oldRecords = $this->oldFormatClasses();
204
        $newValues = [
205
            'ALTO' => 'Kitodo\\\\Dlf\\\\Format\\\\Alto', // Those are effectively single backslashes
206
            'MODS' => 'Kitodo\\\\Dlf\\\\Format\\\\Mods',
207
            'TEIHDR' => 'Kitodo\\\\Dlf\\\\Format\\\\TeiHeader'
208
        ];
209
        foreach ($oldRecords as $uid => $type) {
210
            $sqlQuery = 'UPDATE tx_dlf_formats SET class="'.$newValues[$type].'" WHERE uid='.$uid;
211
            $GLOBALS['TYPO3_DB']->sql_query($sqlQuery);
212
        }
213
        Helper::addMessage(
214
            $GLOBALS['LANG']->getLL('update.FormatClassesOkay', TRUE),
215
            $GLOBALS['LANG']->getLL('update.FormatClasses', TRUE),
216
            \TYPO3\CMS\Core\Messaging\FlashMessage::OK
217
        );
218
        $this->content .= Helper::renderFlashMessages();
219
    }
220
221
    /**
222
     * Update all outdated metadata configuration records
223
     *
224
     * @access protected
225
     *
226
     * @return void
227
     */
228
    protected function updateMetadataConfig() {
229
        $metadataUids = $this->getMetadataConfig();
230
        if (!empty($metadataUids)) {
231
            $data = [];
232
            // Get all old metadata configuration records.
233
            $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
234
                'tx_dlf_metadata.uid AS uid,tx_dlf_metadata.pid AS pid,tx_dlf_metadata.cruser_id AS cruser_id,tx_dlf_metadata.encoded AS encoded,tx_dlf_metadata.xpath AS xpath,tx_dlf_metadata.xpath_sorting AS xpath_sorting',
235
                'tx_dlf_metadata',
236
                'tx_dlf_metadata.uid IN ('.implode(',', $metadataUids).')'
237
                    .Helper::whereClause('tx_dlf_metadata'),
238
                '',
239
                '',
240
                ''
241
            );
242
            while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
243
                $newId = uniqid('NEW');
244
                // Copy record to new table.
245
                $data['tx_dlf_metadataformat'][$newId] = [
246
                    'pid' => $resArray['pid'],
247
                    'cruser_id' => $resArray['cruser_id'],
248
                    'parent_id' => $resArray['uid'],
249
                    'encoded' => $resArray['encoded'],
250
                    'xpath' => $resArray['xpath'],
251
                    'xpath_sorting' => $resArray['xpath_sorting']
252
                ];
253
                // Add reference to old table.
254
                $data['tx_dlf_metadata'][$resArray['uid']]['format'] = $newId;
255
            }
256
            if (!empty($data)) {
257
                // Process datamap.
258
                $substUids = Helper::processDBasAdmin($data);
259
                unset ($data);
260 View Code Duplication
                if (!empty($substUids)) {
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...
261
                    Helper::addMessage(
262
                        $GLOBALS['LANG']->getLL('update.metadataConfigOkay', TRUE),
263
                        $GLOBALS['LANG']->getLL('update.metadataConfig', TRUE),
264
                        \TYPO3\CMS\Core\Messaging\FlashMessage::OK
265
                    );
266
                } else {
267
                    Helper::addMessage(
268
                        $GLOBALS['LANG']->getLL('update.metadataConfigNotOkay', TRUE),
269
                        $GLOBALS['LANG']->getLL('update.metadataConfig', TRUE),
270
                        \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING
271
                    );
272
                }
273
                $this->content .= Helper::renderFlashMessages();
274
            }
275
        }
276
    }
277
278
    /**
279
     * Check all configured Solr cores
280
     *
281
     * @access protected
282
     *
283
     * @return boolean
284
     */
285
    protected function solariumSolrUpdateRequired() {
286
        // Get all Solr cores that were not deleted.
287
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
288
            'index_name',
289
            'tx_dlf_solrcores',
290
            'deleted=0',
291
            '',
292
            '',
293
            ''
294
        );
295
        while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
296
            // Instantiate search object.
297
            $solr = Solr::getInstance($resArray['index_name']);
298
            if (!$solr->ready) {
0 ignored issues
show
Documentation introduced by
The property $ready is declared protected in Kitodo\Dlf\Common\Solr. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
299
                return TRUE;
300
            }
301
        }
302
        return FALSE;
303
    }
304
305
    /**
306
     * Create all configured Solr cores
307
     *
308
     * @access protected
309
     *
310
     * @return void
311
     */
312
    protected function doSolariumSolrUpdate() {
313
        // Get all Solr cores that were not deleted.
314
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
315
            'index_name',
316
            'tx_dlf_solrcores',
317
            'deleted=0',
318
            '',
319
            '',
320
            ''
321
        );
322
        while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
323
            // Instantiate search object.
324
            $solr = Solr::getInstance($resArray['index_name']);
325
            if (!$solr->ready) {
0 ignored issues
show
Documentation introduced by
The property $ready is declared protected in Kitodo\Dlf\Common\Solr. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
326
                $conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
327
                $solrInfo = Solr::getSolrConnectionInfo();
328
                // Prepend username and password to hostname.
329 View Code Duplication
                if ($solrInfo['username']
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...
330
                    && $solrInfo['password']) {
331
                    $host = $solrInfo['username'].':'.$solrInfo['password'].'@'.$solrInfo['host'];
332
                } else {
333
                    $host = $solrInfo['host'];
334
                }
335
                $context = stream_context_create([
336
                    'http' => [
337
                        'method' => 'GET',
338
                        'user_agent' => ($conf['useragent'] ? $conf['useragent'] : ini_get('user_agent'))
339
                    ]
340
                ]);
341
                // Build request for adding new Solr core.
342
                // @see http://wiki.apache.org/solr/CoreAdmin
343
                $url = $solrInfo['scheme'].'://'.$host.':'.$solrInfo['port'].'/'.$solrInfo['path'].'/admin/cores?wt=xml&action=CREATE&name='.$resArray['index_name'].'&instanceDir='.$resArray['index_name'].'&dataDir=data&configSet=dlf';
344
                $response = @simplexml_load_string(file_get_contents($url, FALSE, $context));
345
                // Process response.
346
                if ($response) {
347
                    $status = $response->xpath('//lst[@name="responseHeader"]/int[@name="status"]');
348
                    if ($status
349
                        && $status[0] == 0) {
350
                        continue;
351
                    }
352
                }
353
                Helper::addMessage(
354
                    $GLOBALS['LANG']->getLL('update.solariumSolrUpdateNotOkay', TRUE),
355
                    sprintf($GLOBALS['LANG']->getLL('update.solariumSolrUpdate', TRUE), $resArray['index_name']),
356
                    \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
357
                );
358
                $this->content .= Helper::renderFlashMessages();
359
                return;
360
            }
361
        }
362
        Helper::addMessage(
363
            $GLOBALS['LANG']->getLL('update.solariumSolrUpdateOkay', TRUE),
364
            $GLOBALS['LANG']->getLL('update.solariumSolrUpdate', TRUE),
365
            \TYPO3\CMS\Core\Messaging\FlashMessage::OK
366
        );
367
        $this->content .= Helper::renderFlashMessages();
368
    }
369
}
370