Completed
Push — dev ( 23d1c0...3bd0e2 )
by Nicolas
04:05
created

FieldReverse_Relationship::deleteFieldTable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
/**
3
 * Copyright: Deux Huit Huit 2017
4
 * LICENCE: MIT https://deuxhuithuit.mit-license.org
5
 */
6
7
if (!defined('__IN_SYMPHONY__')) die('<h2>Symphony Error</h2><p>You cannot directly access this file</p>');
8
9
require_once(EXTENSIONS . '/entry_relationship_field/lib/class.field.relationship.php');
10
require_once(EXTENSIONS . '/entry_relationship_field/lib/class.cacheablefetch.php');
11
require_once(EXTENSIONS . '/entry_relationship_field/lib/class.erfxsltutilities.php');
12
13
/**
14
 *
15
 * Field class that will represent a reverse relationship between entries
16
 * @author Deux Huit Huit
17
 *
18
 */
19
class FieldReverse_Relationship extends FieldRelationship
20
{
21
    /**
22
     *
23
     * Name of the field table
24
     *  @var string
25
     */
26
    const FIELD_TBL_NAME = 'tbl_fields_reverse_relationship';
27
28
    /**
29
     *
30
     * Constructor for the Reverse_Relationship Field object
31
     */
32
    public function __construct()
33
    {
34
        // call the parent constructor
35
        parent::__construct();
36
        // set the name of the field
37
        $this->_name = __('Reverse Relationship');
38
        // permits to make it required
39
        $this->_required = true;
40
        // forbid the make it show in the table columns
41
        $this->_showcolumn = false;
42
        // forbid association
43
        $this->_showassociation = false;
44
        // set as not required by default
45
        $this->set('required', 'no');
46
        // show header by default
47
        $this->set('show_header', 'yes');
48
        // allow link by default
49
        $this->set('allow_unlink', 'yes');
50
        // allow go to by default
51
        $this->set('allow_goto', 'yes');
52
    }
53
54
    public function isSortable()
55
    {
56
        return false;
57
    }
58
59
    public function canFilter()
60
    {
61
        return false;
62
    }
63
    
64
    public function canPublishFilter()
65
    {
66
        return false;
67
    }
68
69
    public function canImport()
70
    {
71
        return false;
72
    }
73
74
    public function canPrePopulate()
75
    {
76
        return false;
77
    }
78
    
79
    public function mustBeUnique()
80
    {
81
        return false;
82
    }
83
84
    public function allowDatasourceOutputGrouping()
85
    {
86
        return false;
87
    }
88
89
    public function requiresSQLGrouping()
90
    {
91
        return false;
92
    }
93
94
    public function allowDatasourceParamOutput()
95
    {
96
        return false;
97
    }
98
99
    public function requiresTable()
100
    {
101
        return false;
102
    }
103
104
    public function createTable()
105
    {
106
        return false;
107
    }
108
109
    public function fetchIncludableElements()
110
    {
111
    }
112
113
    /* ********** INPUT AND FIELD *********** */
114
115
    /**
116
     * 
117
     * Validates input
118
     * Called before <code>processRawFieldData</code>
119
     * @param $data
120
     * @param $message
121
     * @param $entry_id
122
     */
123
    public function checkPostFieldData($data, &$message, $entry_id=null)
124
    {
125
        return self::__OK__;
126
    }
127
128
129
    /**
130
     *
131
     * Process data before saving into database.
132
     *
133
     * @param array $data
134
     * @param int $status
135
     * @param boolean $simulate
136
     * @param int $entry_id
137
     *
138
     * @return Array - data to be inserted into DB
139
     */
140
    public function processRawFieldData($data, &$status, &$message = null, $simulate = false, $entry_id = null)
141
    {
142
        $status = self::__OK__;
143
        return null;
144
    }
145
146
147
    /**
148
     *
149
     * Validates the field settings before saving it into the field's table
150
     */
151
    public function checkFields(Array &$errors, $checkForDuplicates = true)
152
    {
153
        $parent = parent::checkFields($errors, $checkForDuplicates);
154
        if ($parent != self::__OK__) {
155
            return $parent;
156
        }
157
        
158
        $sections = $this->get('linked_section_id');
159
        if (empty($sections)) {
160
            $errors['sections'] = __('A section must be chosen');
161
        }
162
        $field = $this->get('linked_field_id');
163
        if (empty($field)) {
164
            $errors['field'] = __('A field must be chosen');
165
        }
166
167
        return (!empty($errors) ? self::__ERROR__ : self::__OK__);
168
    }
169
170
    /**
171
     *
172
     * Save field settings into the field's table
173
     */
174
    public function commit()
175
    {
176
        // if the default implementation works...
177
        if(!parent::commit()) return false;
178
        
179
        $id = $this->get('id');
180
        
181
        // exit if there is no id
182
        if ($id == false) return false;
183
        
184
        // declare an array contains the field's settings
185
        $settings = array(
186
            'linked_section_id' => $this->get('linked_section_id'),
187
            'linked_field_id' => $this->get('linked_field_id'),
188
        );
189
        
190
        return FieldManager::saveSettings($id, $settings);
191
    }
192
193
    /**
194
     * Appends data into the XML tree of a Data Source
195
     * @param $wrapper
196
     * @param $data
197
     */
198
    public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = false, $mode = null, $entry_id = null)
199
    {
200
        // nothing to do
201
    }
202
203
    /* ********* UI *********** */
204
    
205
    /**
206
     *
207
     * Builds the UI for the field's settings when creating/editing a section
208
     * @param XMLElement $wrapper
209
     * @param array $errors
210
     */
211
    public function displaySettingsPanel(XMLElement &$wrapper, $errors = null)
212
    {
213
        /* first line, label and such */
214
        parent::displaySettingsPanel($wrapper, $errors);
215
        
216
        // fieldset
217
        $fieldset = new XMLElement('fieldset', null);
218
        
219
        // group
220
        $group = new XMLElement('div', null, array('class' => 'two columns'));
221
        $fieldset->appendChild($group);
222
        
223
        // sections
224
        $sections = new XMLElement('div', null, array('class' => 'column'));
225
        $this->appendSelectionSelect($sections);
226 View Code Duplication
        if (is_array($errors) && isset($errors['sections'])) {
227
            $sections = Widget::Error($sections, $errors['sections']);
228
        }
229
        $group->appendChild($sections);
230
        
231
        // field
232
        $field = new XMLElement('div', null, array('class' => 'column'));
233
        $this->appendFieldSelect($field);
234 View Code Duplication
        if (is_array($errors) && isset($errors['field'])) {
235
            $field = Widget::Error($field, $errors['field']);
236
        }
237
        $group->appendChild($field);
238
        
239
        $wrapper->appendChild($fieldset);
240
    }
241
242
    /**
243
     *
244
     * Builds the UI for the publish page
245
     * @param XMLElement $wrapper
246
     * @param mixed $data
247
     * @param mixed $flagWithError
248
     * @param string $fieldnamePrefix
249
     * @param string $fieldnamePostfix
250
     */
251
    public function displayPublishPanel(XMLElement &$wrapper, $data = null, $flagWithError = null, $fieldnamePrefix = null, $fieldnamePostfix = null, $entry_id = null)
252
    {
253
        if (!$entry_id) {
254
            return;
255
        }
256
        $field = FieldManager::fetch($this->get('linked_field_id'));
257
        $section = SectionManager::fetch($this->get('linked_section_id'));
258
        if (!($field instanceof FieldRelationship)) {
259
            $flagWithError = __('Linked field is not valid. Please edit this field to set it to a valid ER field.');
260
        }
261
        
262
        $label = Widget::Label($this->get('label'));
263
        // label error management
264
        if ($flagWithError != null) {
265
            $wrapper->appendChild(Widget::Error($label, $flagWithError));
266
        } else {
267
            $wrapper->appendChild($label);
268
            $wrapper->appendChild($this->createEntriesList(array()));
269
            $wrapper->appendChild($this->createActionBarMenu($field));
270
        }
271
        
272
        $wrapper->setAttribute('data-field-id', $this->get('id'));
273
        $wrapper->setAttribute('data-linked-field-id', $this->get('linked_field_id'));
274
        $wrapper->setAttribute('data-linked-section-id', $this->get('linked_section_id'));
275
        $wrapper->setAttribute('data-linked-section', $section->get('handle'));
276
        $wrapper->setAttribute('data-field-label', $field->get('label'));
277
        $wrapper->setAttribute(
278
            'data-entries',
279
            implode(self::SEPARATOR, $field->findRelatedEntries($entry_id, null))
280
        );
281
        if (isset($_REQUEST['debug'])) {
282
            $wrapper->setAttribute('data-debug', true);
283
        }
284
    }
285
286
    private function createActionBarMenu($field)
287
    {
288
        $section = SectionManager::fetch($this->get('linked_section_id'));
289
        $wrap = new XMLElement('div');
290
291
        $fieldset = new XMLElement('fieldset');
292
        $fieldset->setAttribute('class', 'single');
293
        $fieldset->appendChild(new XMLElement(
294
            'span',
295
            __('Related section: '),
296
            array('class' => 'reverse-selection')
297
        ));
298
        $fieldset->appendChild(new XMLElement(
299
            'label',
300
            General::sanitize($section->get('name') . ': ' . $field->get('label')),
301
            array('class' => 'reverse-selection')
302
        ));
303
        $fieldset->appendChild(new XMLElement('button', __('Add to entry'), array(
304
            'type' => 'button',
305
            'class' => 'add',
306
            'data-add' => $section->get('handle'),
307
        )));
308
309
        $wrap->appendChild($fieldset);
310
311
        return $wrap;
312
    }
313
314
    private static $erFields = array();
315
    private function getERFields()
316
    {
317
        if (empty(self::$erFields)) {
318
            self::$erFields = FieldManager::fetch(null, null, null, 'id', 'entry_relationship');
319
        }
320
        return self::$erFields;
321
    }
322
323
    private static $erSections = array();
324
    private function getERSections()
325
    {
326
        if (empty(self::$erSections)) {
327
            $erFields = self::getERFields();
328
            $sectionIds = array_map(function ($erField) {
329
                return $erField->get('parent_section');
330
            }, $erFields);
331
            self::$erSections = SectionManager::fetch($sectionIds);
332
        }
333
        return self::$erSections;
334
    }
335
336
    private function buildSectionSelect($name)
337
    {
338
        $sections = static::getERSections();
0 ignored issues
show
Bug introduced by
Since getERSections() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of getERSections() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
339
        $options = array();
340
        
341 View Code Duplication
        foreach ($sections as $section) {
342
            $driver = $section->get('id');
343
            $selected = $driver === $this->get('linked_section_id');
344
            $options[] = array($driver, $selected, General::sanitize($section->get('name')));
345
        }
346
        
347
        return Widget::Select($name, $options);
348
    } 
349
350 View Code Duplication
    private function appendSelectionSelect(&$wrapper)
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...
351
    {
352
        $name = $this->createSettingsFieldName('linked_section_id', false);
353
354
        $input = $this->buildSectionSelect($name);
355
        $input->setAttribute('class', 'reverse_relationship-sections');
356
357
        $label = Widget::Label();
358
359
        $label->setValue(__('Available sections %s', array($input->generate())));
360
361
        $wrapper->appendChild($label);
362
    }
363
364
    private function buildFieldSelect($name)
365
    {
366
        $section = $this->get('linked_section_id') ? SectionManager::fetch($this->get('linked_section_id')) : null;
367
        $fields = static::getERFields();
0 ignored issues
show
Bug introduced by
Since getERFields() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of getERFields() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
368
        $options = array();
369
        
370
        foreach ($fields as $field) {
371
            if ($section && $section->get('id') !== $field->get('parent_section')) {
372
                continue;
373
            }
374
            $driver = $field->get('id');
375
            $selected = $driver === $this->get('linked_field_id');
376
            $options[] = array($driver, $selected, General::sanitize($field->get('label')));
377
        }
378
        
379
        return Widget::Select($name, $options);
380
    } 
381
382 View Code Duplication
    protected function appendFieldSelect(&$wrapper)
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...
383
    {
384
        $name = $this->createSettingsFieldName('linked_field_id', false);
385
386
        $input = $this->buildFieldSelect($name);
387
        $input->setAttribute('class', 'reverse_relationship-field');
388
389
        $label = Widget::Label();
390
391
        $label->setValue(__('Available Fields %s', array($input->generate())));
392
393
        $wrapper->appendChild($label);
394
    }
395
396
    /**
397
     * Creates the table needed for the settings of the field
398
     */
399
    public static function createFieldTable()
400
    {
401
        $tbl = self::FIELD_TBL_NAME;
402
403
        return Symphony::Database()->query("
404
            CREATE TABLE IF NOT EXISTS `$tbl` (
405
                `id`                int(11) unsigned NOT NULL AUTO_INCREMENT,
406
                `field_id`          int(11) unsigned NOT NULL,
407
                `linked_section_id` int(11) unsigned NOT NULL,
408
                `linked_field_id`   int(11) unsigned NOT NULL,
409
                PRIMARY KEY (`id`),
410
                UNIQUE KEY `field_id` (`field_id`)
411
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
412
        ");
413
    }
414
415
    public static function update_200()
416
    {
417
        return static::createFieldTable();
418
    }
419
420
    /**
421
     *
422
     * Drops the table needed for the settings of the field
423
     */
424
    public static function deleteFieldTable()
425
    {
426
        $tbl = self::FIELD_TBL_NAME;
427
        
428
        return Symphony::Database()->query("
429
            DROP TABLE IF EXISTS `$tbl`
430
        ");
431
    }
432
}
433