CODING.md 9.51 KB
Newer Older
Carsten  Rose's avatar
Carsten Rose committed
1
2
3
4
5
6
Notes / Best Practices for Coding
=================================

General
=======

Carsten  Rose's avatar
Carsten Rose committed
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
* Class QuickFormQuery is the main entry point called by:
  * T3 Extension 'QFQ': called once per tt_content-record. 'bodytext' will be transferred to class QuickFormQuery.
    * The 'bodytext' contains:
      * Report definiton: 10.sql=SELECT ...
      * Form definition (explizit): form=Person
      * <Empty>: do nothing
  * api/save.php: wrapper to receive AJAX post request and instantiate QuickFormQuery.
  * api/load.php: not implemented yet. 
    * Wrapper to receive AJAX get requests.
    * delivers data for jqw grid
    * delivers data for typeahed fields
    * delivers data for select list
    * delivers data for depended (user select/unselect former elements) form elements

LOAD
----
* When qfq starts, 
  * (Form) Looking for a formname at: 
    1. Typo3 Bodytext Element,
    2. For the 'SIP' ($_GET['s'])
    3. $_GET variables 'form' and 'r' (=recordId) - the parameter 'form' has to be allowed in 'Permit URL Parameter' of 
       the specified form. This means: load the form to check, if it is allowed to load the form!?
    * If a formname is found, the search stops and the specified form will be processed.
  * (Report)
    * Process all <number>.[<number.>].sql statements

* Access code variables:     
  * active/valid formname: [$this->store->setVar(SYSTEM_FORM, $formName, STORE_SYSTEM);]
  * SIP: [$this->store->getVar('form', STORE_SIP)]
  * All parameters from active SIP:  [$this->store->getStore(STORE_SIP)]
  * Check Contstants.php for known Store members
  
Carsten  Rose's avatar
Carsten Rose committed
39
40
* In QuickFormQuery.php the whole Form will be copied to $this->formSpec and depending on further processing, the elements are
available in $this->feNative and $this->feAction.
Carsten  Rose's avatar
Carsten Rose committed
41
  * The Form specificaton (table form) will be evaluated direct after loading.
Carsten  Rose's avatar
Carsten Rose committed
42
43
44
  * The FormElement specification will be evaluated later on in BuildForm*.php


Carsten  Rose's avatar
Carsten Rose committed
45
46
47
48
SAVE
----
* Via wrapper api/save.php
* SID must be supplied via FORM POST
Carsten  Rose's avatar
Carsten Rose committed
49
* The SID supplies the <formname> and the <recordid>
Carsten  Rose's avatar
Carsten Rose committed
50
51
52
53
* form.render: plain/table/bootstrap
  * Client will handle the response of save.php.
  * Optional redirection initiated by client.
  
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
DELETE
------
* Via wrapper api/delete.php
* The element who should dissappear after successfull deleting: class=record
* Button:

  * class=record-delete
  * Button: data-sip={{SIP}}

* Three possible variants with delete links:
  
   * Form: main record
   * HTML Code:
   
     <button id="delete-button" type="button" class="btn btn-default navbar-btn" ><span class="glyphicon glyphicon-trash"></span></button>
   
   * Form: subrecord, one delete button per record 
   * Report: typially inside a table, but maybe different.
   * HTML Code:
   
     <button type="button" class="record-delete" data-sip={{SIP}} ><span class="glyphicon glyphicon-trash"></span></button>

Carsten  Rose's avatar
Carsten Rose committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
USER INTERFACE
==============

Button status
-------------
* Form modified:
  * Buttons enabled: Save, Close, New, Delete
  * Button disable: -
  
* Form not modified:
  * Buttons enabled: Close, New, Delete
  * Button disabled: Save

Save Button 
-----------
* User presses the button
Rafael Ostertag's avatar
Rafael Ostertag committed
92
  * Reset all validation states
Rafael Ostertag's avatar
Rafael Ostertag committed
93
  * Client validates HTML Form
Carsten  Rose's avatar
Carsten Rose committed
94
95
  * Form is submitted to server
    * Success: 
Rafael Ostertag's avatar
Rafael Ostertag committed
96
       * Show message provided by server
Carsten  Rose's avatar
Carsten Rose committed
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
       * Current formelements and data will be reloaded.
       * Process server reponse 'redirect':
           * 'client': No redirect.
           * 'no': No redirect.
           * 'url': Redirect to URL
    * Failure: Happens on communication errors, if data validation fails, form actions fails or saving data fails. 
       * Show error message.
       * Client: Ignore server reponse 'redirect'. Client stays on current page.
    

Close Button
------------
* User presses the button
  * Form not modified by user: Client redirects to previous page.
  * Form modified by user: Ask User 'You have unsaved changes. Do you want to close?'
    * Yes: Client redirects to previous page.
    * No: Client stays on current page.
    * Save & Close: 
Rafael Ostertag's avatar
Rafael Ostertag committed
115
116
      * Client reset all validation states
      * Client validates HTML Form
Carsten  Rose's avatar
Carsten Rose committed
117
118
      * Client submits form to server.
      * Success: Process server response 'redirect':
119
        * 'client': Client shows previous page.
Carsten  Rose's avatar
Carsten Rose committed
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
        * 'no': No redirect.
        * 'url': Redirect to URL
      * Failure: Happens on communication errors, if data validation fails, form actions fails or saving data fails. 
        * Show error message. 
        * Client: No redirect. Ignore server reponse 'redirect'.

Delete Button: Main record
--------------------------
* User presses the button. Ask User 'Do you really want to delete the record?
  * Yes: 
    * Delete record on server.
    * Process server reponse 'redirect':
      * 'client': Client redirects to previous page.
      * 'no': Error message.
      * 'url': Redirect to URL
  * No:
    * Client does not delete record on server.
    * No redirect. Client stays on current page.

New Button
----------
* User presses the button
  * Form not modified by user: Client redirects to href url.
  * Form modified by user: Ask User 'You have unsaved changes. Do you want to save first?'
    * Yes:
Rafael Ostertag's avatar
Rafael Ostertag committed
145
146
      * Client reset all validation states
      * Client validates HTML Form
Carsten  Rose's avatar
Carsten Rose committed
147
148
149
150
151
152
153
154
155
156
157
158
159
      * Form is submitted to server
        * Success:
          * Client: Ignore server reponse 'redirect'. Client redirects to href url.
        * Failure: Happens on communication errors, if data validation fails, form actions fails or saving data fails. 
           * Show error message.
           * Client: Ignore server reponse 'redirect'. Client stays on current page.
    * No: 
      * Client does not save the modified record.
      * Client redirects to href url.
    * Cancel:
      * Client does not save the modified record.
      * Client stays on current page.
  
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
File Handling
-------------
* No previous uploaded file present
  1. User presses the Browse button
    1. User selects file
      1. File is uploaded to qfq immediately
      1. Browse button gets disabled and hidden
      1. File delete button is shown
    1. User cancels file selection
      1. no action
* Previous uploaded file present
  1. User deletes file
    1. File delete button gets disabled and hidden
    1. Browse button gets enabled and displayed
175
  
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
Formelement type: DATE / DATETIME / TIME
----------------------------------------
 * Available Formats:
   * 'yyyy-mm-dd' = FORMAT_DATE_INTERNATIONAL. 
   * 'dd.mm.yyyy' = FORMAT_DATE_GERMAN.
 * The 'DATE_FORMAT' can be specified systemwide in `config.ini`
 * The default format is FORMAT_DATE_INTERNATIONAL.
 * Optional: 'dateFormat' can be specified per form element in `form.parameter` - this overwrites 'systemwide'.
 * If there is no placeholder defined on the form element, the defined dateFormat is shown as placeholder.
 
 * Browser: 
   * checks the input with a system regexp.
   * regexp might be user defined. If given, do not use system regexp!
   * No min/max check.
 * Server: 
   * check with system wirde regexp 
   * regexp might be user defined. If given, do not use system regexp!
   * Do min/max check.
 
 * MySQL data: 1000-01-01 - 9999-12-31 and 0000-00-00
 * MySQL time: 00:00:00 - 23:59:59
 
 * datetime format: 'DATE TIME'

Carsten  Rose's avatar
Carsten Rose committed
201
202
203
204
205
Debug / Log / Errormessages
===========================

* Before firing a SQL or doing processing of an FormElement, set some debugging / error variables:

206
    [src] $this->store->setVar(SYSTEM_SQL_RAW, STORE_SYSTEM)
Carsten  Rose's avatar
Carsten Rose committed
207
208

* Available fields:
209
210
211
212
213
214
215
216
217
218

    <code>
    SYSTEM_SQL_RAW
    SYSTEM_SQL_FINAL
    SYSTEM_SQL_COUNT
    SYSTEM_SQL_PARAM_ARRAY
    SYSTEM_FORM = CLIENT_FORM;                        // '<formName> / <formId>'
    SYSTEM_FORM_ELEMENT = 'formElement';              // '<formElementName> / <formElementeId>'
    SYSTEM_FORM_ELEMENT_COLUMN = 'formElementColumn'; // '<columnname of current processed formElement>'
    </code>
Carsten  Rose's avatar
Carsten Rose committed
219

Carsten  Rose's avatar
Carsten Rose committed
220
221
* Form.debugShowInfo: yes|no will display a tooltip near beside every formelement and show parse/evaluate as tooltip.

222
223
224
225
* Check to display debug info:
 
    $this->store->getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM) === 'yes'

Carsten  Rose's avatar
Carsten Rose committed
226
227
228
Stores
======

229
* Retrieve 'get' or 'post' variables by:
Carsten  Rose's avatar
Carsten Rose committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243

[src] $values = $this->store->getStore(STORE_CLIENT)



Primary Table
=============
* For the primary table all informations are available in STORE_TABLE_DEFAULT and STORE_TABLE_COLUMN_TYPES.
* Get all columns of the primary table by

[src] array_keys($this->getStore(STORE_TABLE_COLUMN_TYPES))

* Get the recent record in STORE_RECORD and the parent record (multiforms) in STORE_PARENT_RECORD.

Carsten  Rose's avatar
Carsten Rose committed
244
245
246

Typo3
=====
Carsten  Rose's avatar
Carsten Rose committed
247
248
249
* PageId: $this->store->getVar(TYPO3_PAGE_ID, STORE_TYPO3)
  * Based on: $GLOBALS["TSFE"]->id   current Page
 
Carsten  Rose's avatar
Carsten Rose committed
250
251
252
253
254
255
256
257
* $GLOBALS["TSFE"]->fe_user->user["uid"]   fe_user_uid

* https://wiki.typo3.org/Extbase_HowTos
  * Old: $this->cObj->data['bodytext']
  * New:
        $contentObject = $this->configurationManager->getContentObject();
        $configuration = $contentObject->data['bodytext'];

258
259
260
* Verzeichnisstruktur Extension: https://docs.typo3.org/typo3cms/CoreApiReference/ExtensionArchitecture/FilesAndLocations/Index.html
* http://api.typo3.org/
  * http://api.typo3.org/typo3cms/62/html/index.html
Carsten  Rose's avatar
Carsten Rose committed
261
262
263
264
265
266
267
268
* https://docs.typo3.org/typo3cms/CoreApiReference/Introduction/Index.html

SIP
===
Page loaded: www.example.com?index.php&id=start&s=badcaffee1234&type=2&L=3, with $_SESSION['badcaffee1234'] => 'form=Person&r=1'

* $_SESSION[$sip] => <urlparam>  >> $_SESSION['badcaffee1234'] => 'form=Person&r=1'
* $_SESSION[$urlparam] => <sip>  >> $_SESSION['form=Person&r=1'] => 'badcaffee1234'
Carsten  Rose's avatar
Carsten Rose committed
269
270


271
272
273
274
275
276
277
278
279
280
FormElement
===========

Checkbox
--------

    <div class="checkbox">
        <label>
            <input type="checkbox">label 1
        </label>
Carsten  Rose's avatar
Carsten Rose committed
281
282
283
    </div>