Issues (13)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

code/models/EditableField.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Moo_EditableField is a base class for editable fields to extend.
5
 *
6
 * @author  Mohamed Alsharaf <[email protected]>
7
 *
8
 * @property string $Title
9
 * @property string $Name
10
 * @property int    $Required
11
 * @property string $CustomErrorMessage
12
 * @property string $CustomSettings
13
 */
14
class Moo_EditableField extends DataObject
15
{
16
    private static $db = [
17
        'Name'               => 'Varchar',
18
        'Title'              => 'Varchar(255)',
19
        'Required'           => 'Boolean',
20
        'CustomErrorMessage' => 'Varchar(255)',
21
        'CustomSettings'     => 'Text',
22
    ];
23
    private static $singular_name = 'Editable Field';
24
    private static $plural_name   = 'Editable Fields';
25
26
    /**
27
     * List of fields names part of the custom settings.
28
     *
29
     * @var array
30
     */
31
    protected $customSettingsFields = [];
32
33
    /**
34
     * Instance of FormField.
35
     *
36
     * @var FormField
37
     */
38
    protected $field;
39
40
    /**
41
     * To prevent having tables for each fields minor settings we store it as
42
     * a serialized array in the database.
43
     *
44
     * @return array Return all the Settings
45
     */
46 8
    public function getSettings()
47 1
    {
48 8
        return (!empty($this->CustomSettings)) ? unserialize($this->CustomSettings) : [];
49
    }
50
51
    /**
52
     * Set the custom settings for this field as we store the minor details in
53
     * a serialized array in the database.
54
     *
55
     * @param array $settings the custom settings
56
     */
57 8
    public function setSettings($settings = [])
58 1
    {
59 8
        $this->CustomSettings = serialize($settings);
60 8
    }
61
62
    /**
63
     * Set a given field setting. Appends the option to the settings or overrides
64
     * the existing value.
65
     *
66
     * @param string $key
67
     * @param string $value
68
     */
69 1
    public function setSetting($key, $value)
70
    {
71 1
        $settings       = $this->getSettings();
72 1
        $settings[$key] = $value;
73
74 1
        $this->setSettings($settings);
75 1
    }
76
77
    /**
78
     * Return just one custom setting or empty string if it does
79
     * not exist.
80
     *
81
     * @param string $setting
82
     *
83
     * @return string
84
     */
85 3
    public function getSetting($setting)
86
    {
87 3
        $settings = $this->getSettings();
88 3
        if (isset($settings) && count($settings) > 0) {
89 2
            if (isset($settings[$setting])) {
90 2
                return $settings[$setting];
91
            }
92
        }
93
94 3
        return '';
95
    }
96
97
    /**
98
     * Get the path to the icon for this field type, relative to the site root.
99
     *
100
     * @return string
101
     */
102 1
    public function getIcon()
103
    {
104 1
        return 'editablefield/images/formfields/' . strtolower(substr($this->class, 4)) . '.png';
105
    }
106
107
    /**
108
     * Get the icon HTML tag.
109
     *
110
     * @return string
111
     */
112 1
    public function getIconTag()
113
    {
114 1
        return '<img src="' . $this->getIcon() . '"/>';
115
    }
116
117 1
    public function getCMSFields()
118
    {
119 1
        $fields = parent::getCMSFields();
120
121
        // Remove field to be recreated in separate tabs
122 1
        $fields->removeByName([
123 1
            'Required', 'CustomErrorMessage', 'CustomSettings', 'Options',
124 1
        ]);
125
126
        // Add default field configurations "custom settings"
127 1
        $fields->addFieldsToTab('Root.FieldConfiguration', [
128 1
            new TextField(
129 1
                $this->getSettingName('RightTitle'), _t('Moo_EditableField.RIGHTTITLE', 'Right Title'),
130 1
                $this->getSetting('RightTitle')
131 1
            ),
132 1
        ]);
133
134
        // Add default validation fields
135
        $validateFields = [
136 1
            new CheckboxField('Required', _t('Moo_EditableField.REQUIRED', 'Is this field Required?'), $this->Required),
137 1
            new TextField('CustomErrorMessage', _t('Moo_EditableField.CUSTOMERROR', 'Custom Error Message'), $this->CustomErrorMessage),
138 1
        ];
139 1
        $fields->addFieldsToTab('Root.Validation', $validateFields);
140
141
        // Add extra field configurations "custom settings" from the subclass
142 1
        if (method_exists($this, 'getFieldConfiguration')) {
143 1
            $fields->addFieldsToTab('Root.FieldConfiguration', $this->getFieldConfiguration());
0 ignored issues
show
The method getFieldConfiguration() does not exist on Moo_EditableField. Did you maybe mean config()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
144 1
        }
145
146
        // Add extra validation fields from the subclass
147 1
        if (method_exists($this, 'getFieldValidationOptions')) {
148
            $fields->addFieldsToTab('Root.Validation', $this->getFieldValidationOptions());
0 ignored issues
show
Documentation Bug introduced by
The method getFieldValidationOptions does not exist on object<Moo_EditableField>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
149
        }
150
151 1
        return $fields;
152
    }
153
154 1
    public function getCMSValidator()
155
    {
156 1
        return new RequiredFields(
157 1
            'Title', 'Name'
158 1
        );
159
    }
160
161
    /**
162
     * Returns the Title for rendering in the front-end (with XML values escaped).
163
     *
164
     * @return string
165
     */
166 8
    public function getTitle()
167
    {
168 8
        return Convert::raw2att($this->getField('Title'));
0 ignored issues
show
Bug Compatibility introduced by
The expression \Convert::raw2att($this->getField('Title')); of type array|string adds the type array to the return on line 168 which is incompatible with the return type of the parent method DataObject::getTitle of type string.
Loading history...
169
    }
170
171
    /**
172
     * Generate a name for the Setting field.
173
     *
174
     * @param string $field
175
     *
176
     * @return string
177
     */
178 1
    public function getSettingName($field)
179
    {
180 1
        return 'CustomSettings[' . $field . ']';
181
    }
182
183
    /**
184
     * How to save the data submitted in this field into the database object
185
     * which this field represents.
186
     *
187
     * Any class's which call this should also call
188
     * {@link parent::populateFromPostData()} to ensure that this method is
189
     * called
190
     *
191
     * @throws ValidationException
192
     */
193 8
    public function onBeforeWrite()
194
    {
195 8
        $return = parent::onBeforeWrite();
0 ignored issues
show
Are you sure the assignment to $return is correct as parent::onBeforeWrite() (which targets DataObject::onBeforeWrite()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
196
197
        // Field name must be unique
198 8
        $exists = self::get()->filter('Name', $this->Name)->exclude('ID', $this->ID);
199 8
        if ($exists->count()) {
200
            throw new ValidationException(
201
                _t('Moo_EditableField.UNIQUENAME', 'Field name "{name}" must be unique', '',
202
                    ['name' => $this->Name])
0 ignored issues
show
array('name' => $this->Name) is of type array<string,string,{"name":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
203
            );
204
        }
205
206
        // Filter field name from un-supported HTML attribute value
207 8
        $this->Name = preg_replace('/[^a-zA-Z0-9_]+/', '', $this->Name);
208
209
        // Get custom settings from the current object of request POST
210 8
        $customSettings = $this->getSettings();
211 8
        if (empty($customSettings)) {
212 8
            $customSettings = (array) Controller::curr()->getRequest()->postVar('CustomSettings');
213 8
        }
214
215
        // Filter out any un-supported settings by the subclasss
216 8
        if (!empty($this->customSettingsFields)) {
217 5
            $customSettings = array_intersect_key($customSettings, array_flip((array) $this->customSettingsFields));
218 5
        }
219
220
        // Set the filtered settings
221 8
        $this->setSettings($customSettings);
222
223 8
        return $return;
224
    }
225
226
    /**
227
     * Return a FormField.
228
     *
229
     * @return FormField
230
     */
231 1
    public function getFormField()
232
    {
233 1
        if (null === $this->field) {
234 1
            $this->field = $this->initFormField();
235 1
        }
236
237 1
        return $this->field;
238
    }
239
240
    /**
241
     * Initiate a form field.
242
     *
243
     * @return FormField
244
     */
245
    protected function initFormField()
246
    {
247
        throw new DomainException(sprintf('%s must be implemented by the class %s', __METHOD__, $this->class));
248
    }
249
250
    /**
251
     * Return the error message for this field. Either uses the custom
252
     * one (if provided) or the default SilverStripe message.
253
     *
254
     * @return Varchar
255
     */
256
    public function getErrorMessage()
257
    {
258
        $title    = strip_tags("'" . ($this->Title ? $this->Title : $this->Name) . "'");
259
        $standard = _t('Form.FIELDISREQUIRED', '{name} is required', ['name' => $title]);
0 ignored issues
show
array('name' => $title) is of type array<string,string,{"name":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
260
261
        // only use CustomErrorMessage if it has a non empty value
262
        $errorMessage = (!empty($this->CustomErrorMessage)) ? $this->CustomErrorMessage : $standard;
263
264
        return DBField::create_field('Varchar', $errorMessage);
265
    }
266
267 1
    public function onBeforeDuplicate(Moo_EditableField $field)
268
    {
269
        // The name field must be unique, this is temporary workaround
270 1
        $this->setField('Name', $field->Name . uniqid());
271 1
    }
272
}
273