Save.php 7.85 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 1/30/16
 * Time: 7:59 PM
 */

namespace qfq;

require_once(__DIR__ . '/../qfq/store/Store.php');
require_once(__DIR__ . '/../qfq/Constants.php');
require_once(__DIR__ . '/../qfq/Evaluate.php');
//require_once(__DIR__ . '/../qfq/exceptions/UserException.php');
//require_once(__DIR__ . '/../qfq/exceptions/CodeException.php');
//require_once(__DIR__ . '/../qfq/exceptions/DbException.php');
//require_once(__DIR__ . '/../qfq/Evaluate.php');


class Save {

    private $formSpec = array();  // copy of the loaded form
    private $feSpecAction = array(); // copy of all formElement.class='action' of the loaded form
    private $feSpecNative = array(); // copy of all formElement.class='native' of the loaded form
    /**
     * @var null|Store
     */
    private $store = null;
    private $db = null;

    private $evaluate = null;

    /**
     * @param array $formSpec
     * @param array $feSpecAction
     * @param array $feSpecNative
     */
    public function __construct(array $formSpec, array $feSpecAction, array $feSpecNative) {
        $this->formSpec = $formSpec;
        $this->feSpecAction = $feSpecAction;
        $this->feSpecNative = $feSpecNative;
        $this->store = Store::getInstance();
        $this->db = new Database();
        $this->evaluate = new Evaluate($this->store, $this->db);
    }

    /**
48
49
     * Starts save process. On succcess, returns forwardmode/page.
     *
50
51
     * @throws CodeException
     * @throws DbException
52
     * @throws UserFormException
53
54
     */
    public function process() {
55
        $rc = 0;
56
57
58
59
60
61

        if ($this->formSpec['multiMode'] !== 'none') {

            $parentRecords = $this->db->sql($this->formSpec['multiSql']);
            foreach ($parentRecords as $row) {
                $this->store->setVarArray($row, STORE_PARENT_RECORD, true);
62
                $rc = $this->elements($row['_id']);
63
64
            }
        } else {
65
            $rc = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_ZERO));
66
        }
67
68

        return $rc;
69
70
71
72
    }

    /**
     * @param $recordId
73
     * @return int   record id (in case of insert, it's different from $recordId)
74
75
     * @throws CodeException
     * @throws DbException
76
     * @throws UserFormException
77
78
     */
    public function elements($recordId) {
Carsten  Rose's avatar
Carsten Rose committed
79

80
81
82
        $newValues = array();

        $tableColumns = array_keys($this->store->getStore(STORE_TABLE_COLUMN_TYPES));
83
        $formValues = $this->store->getStore(STORE_FORM);
84

85
86
        $this->processAllUploads($recordId, $formValues);

87
88
        // Iterate over all table.columns. Built an assoc array $newValues.
        foreach ($tableColumns AS $column) {
89

90
            // Never save a predefined 'id': autoincrement values will be given by database..
91
92
93
94
95
96
97
98
            if ($column === 'id')
                continue;

            // Get related formElement.
            $formElement = $this->getFormElementByName($column);
            if ($formElement === false)
                continue;

99
            // Preparation for Log, Debug
100
            $this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($formElement), STORE_SYSTEM);
101

102
103
            Support::setIfNotSet($formValues, $column);
            $newValues[$column] = $formValues[$column];
104
105
        }

106
107
108
109
110
111
112
113
        if ($recordId == 0) {
            $rc = $this->insertRecord($this->formSpec['tableName'], $newValues);
        } else {
            $this->updateRecord($this->formSpec['tableName'], $newValues, $recordId);
            $rc = $recordId;
        }

        return $rc;
114
115
    }

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    /**
     * Process all Upload Formelements for the given $recordId
     *
     * @param $recordId
     * @param array $formValues
     */
    private function processAllUploads($recordId, array &$formValues) {

        foreach ($this->feSpecNative AS $formElement) {
            // skip non upload formElements
            if ($formElement['type'] != 'upload') {
                continue;
            }

            $column = $formElement['name'];
            $file = $this->doUpload($formElement, $recordId, $formValues[$column]);
            if ($file !== false) {
                $formValues[$column] = $file;
            }
        }
    }

    /**
     * Process upload for the given Formelement.
     * - Check if there is an upload:
     *   yes: do the upload
     *   no: if there is an old file: delete it.
     * @param $formElement
     * @param $sipUpload
     * @return string|false  New filename or false on error
     * @throws CodeException
     * @throws UserFormException
     * @internal param $recordId
     */
    private function doUpload($formElement, $sipUpload) {

        $statusUpload = $this->store->getVar($sipUpload, STORE_EXTRA);
        if ($statusUpload === false) {
            return false;
        }

        // Delete existing old file.
        if (isset($statusUpload[FILES_FLAG_DELETE]) && $statusUpload[FILES_FLAG_DELETE] == '1') {
            $oldFile = $this->store->getVar($formElement['name'], STORE_RECORD);
            if (file_exists($oldFile)) {
                if (!unlink($oldFile)) {
                    throw new UserFormException('unlink file: ' . $oldFile, ERROR_IO_UNLINK);
                }
            }
        }

        // TODO: calculate destination
        $targetFile = $statusUpload[FILES_TMP_NAME] . '.final';

        if (file_exists($targetFile)) {
            throw new UserFormException('Copy upload failed - file already exist: ' . $targetFile, ERROR_IO_FILE_EXIST);
        }

        $uploadFile = Support::extendFilename($statusUpload[FILES_TMP_NAME], UPLOAD_CACHED);
        if (!rename($uploadFile, $targetFile)) {
            throw new UserFormException("Rename file: '$uploadFile' > '$targetFile'", ERROR_IO_RENAME);
        }

        $this->store->setVar($sipUpload, array(), STORE_EXTRA);

        return $targetFile;

    }

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    /**
     * Get the complete FormElement for $name
     *
     * @param $name
     * @return bool|array if found the FormElement, else false.
     */
    private function getFormElementByName($name) {
        foreach ($this->feSpecNative as $formElement) {
            if ($formElement['name'] === $name)
                return $formElement;
        }
        return false;
    }

    /**
     * Insert new record in table $this->formSpec['tableName'].
     *
     * @param array $values
203
     * @return int  last insert id
204
205
206
207
208
     * @throws DbException
     */
    public function insertRecord($tableName, array $values) {

        if (count($values) === 0)
209
            return 0; // nothing to write, last insert id=0
210
211
212
213
214
215
216

        $paramList = str_repeat('?, ', count($values));
        $paramList = substr($paramList, 0, strlen($paramList) - 2);
        $columnList = '`' . implode('`, `', array_keys($values)) . '`';

        $sql = 'INSERT INTO ' . $tableName . ' ( ' . $columnList . ' ) VALUES ( ' . $paramList . ' )';

217
        $rc = $this->db->sql($sql, ROW_REGULAR, array_values($values));
218

219
        return $rc;
220
221
222
    }

    /**
223
     * @param string $tableName
224
     * @param array $values
225
     * @param int $recordId
226
     * @return bool|int     false if $values is empty, else affectedrows
227
     * @throws CodeException
228
229
230
231
232
     * @throws DbException
     */
    public function updateRecord($tableName, array $values, $recordId) {

        if (count($values) === 0)
233
            return 0; // nothing to write, 0 rows affected
234
235
236
237

        if ($recordId === 0)
            throw new CodeException('RecordId=0 - this is not possible for update.', ERROR_RECORDID_0_FORBIDDEN);

238
239
//        $paramList = str_repeat('?, ', count($values));
//        $paramList = substr($paramList, 0, strlen($paramList) - 2);
240
241
242
243

        $sql = 'UPDATE `' . $tableName . '` SET ';

        foreach ($values as $column => $value) {
244

245
246
247
248
249
250
            $sql .= '`' . $column . '` = ?, ';
        }

        $sql = substr($sql, 0, strlen($sql) - 2) . ' WHERE id = ?';
        $values[] = $recordId;

251
252
253
        $rc = $this->db->sql($sql, ROW_REGULAR, array_values($values));

        return $rc;
254
255
256
    }

}