Completed
Push — master ( 24afac...326dfc )
by Damian
03:43 queued 01:35
created

GenerateCSVJob::getOutputPath()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 15
rs 9.2
cc 4
eloc 8
nc 8
nop 0
1
<?php
2
3
/**
4
 * Iteratively exports GridField data to a CSV file on disk, in order to support large exports.
5
 * The generated file can be downloaded by the user through a CMS UI provided in {@link GridFieldQueuedExportButton}.
6
 *
7
 * Simulates a request to the GridFieldQueuedExportButton controller to retrieve the GridField instance,
8
 * from which the original data context can be derived (as an {@link SS_List instance).
9
 * This is a necessary workaround due to the limitations on serialising GridField's data description logic.
10
 * While a DataList is serialisable, other SS_List instances might not be.
11
 * We'd also need to consider custom value transformations applied via GridField->customDataFields lambdas.
12
 *
13
 * Relies on GridField being accessible in its original CMS controller context to the user
14
 * who triggered the export.
15
 */
16
class GenerateCSVJob extends AbstractQueuedJob {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
17
18
    public function __construct() {
19
        $this->ID = uniqid();
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
20
        $this->Seperator = ',';
0 ignored issues
show
Documentation introduced by
The property Seperator does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
21
        $this->IncludeHeader = true;
0 ignored issues
show
Documentation introduced by
The property IncludeHeader does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
22
        $this->HeadersOutput = false;
0 ignored issues
show
Documentation introduced by
The property HeadersOutput does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
23
        $this->totalSteps = 1;
24
    }
25
26
    /**
27
     * @return string
28
     */
29
    public function getJobType() {
30
        return QueuedJob::QUEUED;
31
    }
32
33
    /**
34
     * @return string
35
     */
36
    public function getTitle() {
37
        return "Export a CSV of a Gridfield";
38
    }
39
40
    /**
41
     * @return string
42
     */
43
    public function getSignature() {
44
        return md5(get_class($this) . '-' . $this->ID);
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GenerateCSVJob>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
45
    }
46
    /**
47
     * @param GridField $gridField
48
     */
49
    function setGridField(GridField $gridField) {
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...
50
        $this->GridFieldName = $gridField->getName();
0 ignored issues
show
Documentation introduced by
The property GridFieldName does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
51
        $this->GridFieldURL = $gridField->Link();
0 ignored issues
show
Documentation introduced by
The property GridFieldURL does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
52
    }
53
54
    /**
55
     * @param $session
56
     */
57
    function setSession($session) {
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...
58
        // None of the gridfield actions are needed, and they make the stored session bigger, so pull
59
        // them out.
60
        $actionkeys = array_filter(array_keys($session), function ($i) {
61
            return strpos($i, 'gf_') === 0;
62
        });
63
64
        $session = array_diff_key($session, array_flip($actionkeys));
65
66
        // This causes problems with logins
67
        unset($session['HTTP_USER_AGENT']);
68
69
        $this->Session = $session;
0 ignored issues
show
Documentation introduced by
The property Session does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
70
    }
71
72
    function setColumns($columns) {
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...
73
        $this->Columns = $columns;
0 ignored issues
show
Documentation introduced by
The property Columns does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
74
    }
75
76
    function setSeparator($seperator) {
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...
77
        $this->Separator = $seperator;
0 ignored issues
show
Documentation introduced by
The property Separator does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
78
    }
79
80
    function setIncludeHeader($includeHeader) {
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...
81
        $this->IncludeHeader = $includeHeader;
0 ignored issues
show
Documentation introduced by
The property IncludeHeader does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
82
    }
83
84
    protected function getOutputPath() {
85
        $base = ASSETS_PATH . '/.exports';
86
        if (!is_dir($base)) mkdir($base, 0770, true);
87
88
        // Although the string is random, so should be hard to guess, also try and block access directly.
89
        // Only works in Apache though
90
        if (!file_exists("$base/.htaccess")) {
91
            file_put_contents("$base/.htaccess", "Deny from all\nRewriteRule .* - [F]\n");
92
        }
93
94
        $folder = $base.'/'.$this->getSignature();
95
        if (!is_dir($folder)) mkdir($folder, 0770, true);
96
97
        return $folder.'/'.$this->getSignature().'.csv';
98
    }
99
100
    /**
101
     * @return GridField
102
     * @throws SS_HTTPResponse_Exception
103
     */
104
    protected function getGridField() {
105
        $session = $this->Session;
0 ignored issues
show
Documentation introduced by
The property Session does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
106
107
        // Store state in session, and pass ID to client side.
108
        $state = array(
109
            'grid'       => $this->GridFieldName,
0 ignored issues
show
Documentation introduced by
The property GridFieldName does not exist on object<GenerateCSVJob>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
110
            'actionName' => 'findgridfield',
111
            'args'       => null
112
        );
113
114
        // Ensure $id doesn't contain only numeric characters
115
        $id = 'gf_' . substr(md5(serialize($state)), 0, 8);
116
117
        // Simulate CSRF token use, hardcode to a random value in our fake session
118
        // so GridField can evaluate it in the Director::test() execution
119
        $token = Injector::inst()->create('RandomGenerator')->randomToken('sha1');
120
121
        // Add new form action into session for GridField to find when Director::test is called below
122
        $session[$id] = $state;
123
        $session['SecurityID'] = $token;
124
125
        // Construct the URL
126
        $actionKey = 'action_gridFieldAlterAction?' . http_build_query(['StateID' => $id]);
127
        $actionValue = 'Find Gridfield';
128
129
        $url = Controller::join_links(
130
            $this->GridFieldURL,
0 ignored issues
show
Documentation introduced by
The property GridFieldURL does not exist on object<GenerateCSVJob>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
131
            '?' .http_build_query([$actionKey => $actionValue, 'SecurityID' => $token])
132
        );
133
134
        // Restore into the current session the user the job is exporting as
135
        Session::set("loggedInAs", $session['loggedInAs']);
136
137
        // Then make a sub-query that should return a special SS_HTTPResponse with the gridfield object
138
        $res = Director::test($url, null, new Session($session), 'GET');
139
140
        // Great, it did, we can return it
141
        if ($res instanceof GridFieldQueuedExportButton_Response) {
142
            $gridField = $res->getGridField();
143
            $gridField->getConfig()->removeComponentsByType('GridFieldPaginator');
144
            $gridField->getConfig()->removeComponentsByType('GridFieldPageCount');
145
146
            return $gridField;
147
        } else {
148
            user_error('Couldn\'t restore GridField', E_USER_ERROR);
149
        }
150
    }
151
152
    /**
153
     * @param $gridField
154
     * @param $columns
155
     */
156
    protected function outputHeader($gridField, $columns) {
0 ignored issues
show
Unused Code introduced by
The parameter $gridField is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
157
        $fileData = '';
158
        $separator = $this->Separator;
0 ignored issues
show
Documentation introduced by
The property Separator does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
159
160
        $headers = array();
161
162
        // determine the CSV headers. If a field is callable (e.g. anonymous function) then use the
163
        // source name as the header instead
164
        foreach ($columns as $columnSource => $columnHeader) {
165
            $headers[] = (!is_string($columnHeader) && is_callable($columnHeader)) ? $columnSource : $columnHeader;
166
        }
167
168
        $fileData .= "\"" . implode("\"{$separator}\"", array_values($headers)) . "\"";
169
        $fileData .= "\n";
170
171
        file_put_contents($this->getOutputPath(), $fileData, FILE_APPEND);
172
    }
173
174
    /**
175
     * This method is adapted from GridField->generateExportFileData()
176
     *
177
     * @param GridField $gridField
178
     * @param array $columns
179
     * @param int $start
180
     * @param int $count
181
     */
182
    protected function outputRows(GridField $gridField, $columns, $start, $count) {
183
        $fileData = '';
184
        $separator = $this->Separator;
0 ignored issues
show
Documentation introduced by
The property Separator does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
185
186
        $items = $gridField->getManipulatedList();
187
        $items = $items->limit($count, $start);
188
189
        foreach ($items as $item) {
190
            if (!$item->hasMethod('canView') || $item->canView()) {
191
                $columnData = array();
192
193
                foreach ($columns as $columnSource => $columnHeader) {
194
                    if (!is_string($columnHeader) && is_callable($columnHeader)) {
195
                        if ($item->hasMethod($columnSource)) {
196
                            $relObj = $item->{$columnSource}();
197
                        } else {
198
                            $relObj = $item->relObject($columnSource);
199
                        }
200
201
                        $value = $columnHeader($relObj);
202
                    } else {
203
                        $value = $gridField->getDataFieldValue($item, $columnSource);
204
205
                        if ($value === null) {
206
                            $value = $gridField->getDataFieldValue($item, $columnHeader);
207
                        }
208
                    }
209
210
                    $value = str_replace(array("\r", "\n"), "\n", $value);
211
                    $columnData[] = '"' . str_replace('"', '""', $value) . '"';
212
                }
213
214
                $fileData .= implode($separator, $columnData);
215
                $fileData .= "\n";
216
            }
217
218
            if ($item->hasMethod('destroy')) {
219
                $item->destroy();
220
            }
221
        }
222
223
        file_put_contents($this->getOutputPath(), $fileData, FILE_APPEND);
224
    }
225
226
    public function setup() {
227
        $gridField = $this->getGridField();
228
        $this->totalSteps = $gridField->getManipulatedList()->count();
229
    }
230
231
    /**
232
     * Generate export fields for CSV.
233
     *
234
     * @param GridField $gridField
0 ignored issues
show
Bug introduced by
There is no parameter named $gridField. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
235
     * @return array
236
     */
237
    public function process() {
238
        $gridField = $this->getGridField();
239
        $columns = $this->Columns ?: singleton($gridField->getModelClass())->summaryFields();
0 ignored issues
show
Documentation introduced by
The property Columns does not exist on object<GenerateCSVJob>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
240
241
        if ($this->IncludeHeader && !$this->HeadersOutput) {
0 ignored issues
show
Documentation introduced by
The property IncludeHeader does not exist on object<GenerateCSVJob>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
Documentation introduced by
The property HeadersOutput does not exist on object<GenerateCSVJob>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
242
            $this->outputHeader($gridField, $columns);
243
            $this->HeadersOutput = true;
0 ignored issues
show
Documentation introduced by
The property HeadersOutput does not exist on object<GenerateCSVJob>. Since you implemented __set, maybe consider adding a @property annotation.

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...
244
        }
245
246
        $this->outputRows($gridField, $columns, $this->currentStep, 100);
0 ignored issues
show
Bug introduced by
It seems like $gridField defined by $this->getGridField() on line 238 can be null; however, GenerateCSVJob::outputRows() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
247
248
        $this->currentStep += 100;
249
250
        if ($this->currentStep >= $this->totalSteps) {
251
            $this->isComplete = true;
252
        }
253
    }
254
}
255