diff --git a/CODING.md b/CODING.md index ffb9ae07833d5ffda7bf0c743d28b421a373b23b..a959d34b567d8a36302d4d44ec031738cf71c8e0 100644 --- a/CODING.md +++ b/CODING.md @@ -80,21 +80,26 @@ Debug / Log / Errormessages * Before firing a SQL or doing processing of an FormElement, set some debugging / error variables: -[src] $this->store->setVar(SYSTEM_SQL_RAW, STORE_SYSTEM) + [src] $this->store->setVar(SYSTEM_SQL_RAW, STORE_SYSTEM) * Available fields: -<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> + + <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> * Form.debugShowInfo: yes|no will display a tooltip near beside every formelement and show parse/evaluate as tooltip. +* Check to display debug info: + + $this->store->getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM) === 'yes' + Stores ====== diff --git a/extension/Documentation/AdministratorManual/Index.rst b/extension/Documentation/AdministratorManual/Index.rst index 2445fef0350f53b115ac5a0a4e1337127fceb70c..e993503509fe7bcb4acd56e92d12339434ba58f8 100644 --- a/extension/Documentation/AdministratorManual/Index.rst +++ b/extension/Documentation/AdministratorManual/Index.rst @@ -60,13 +60,15 @@ Setup a *report* to manage all *forms*: Create a Typo3 page and insert a content :: form = {{form}} - 10.sql = SELECT CONCAT('{{pageId}}&form=Form&r=', f.id) as Pagee, f.id, f.name, f.title, f.tableName FROM FormEditor As f ORDER BY f.name - 10.head = <br><table class="table"> - 10.tail = </table> - 10.rbeg = <tr class="table-hover"> - 10.rend = </tr> - 10.fbeg = <td> - 10.fend = </td> + 10 { + sql = SELECT CONCAT('{{pageId}}&form=Form&r=', f.id) as Pagee, f.id, f.name, f.title, f.tableName FROM FormEditor As f ORDER BY f.name + head = <br><table class="table"> + tail = </table> + rbeg = <tr class="table-hover"> + rend = </tr> + fbeg = <td> + fend = </td> + } <ext_dir>/config.ini -------------------- diff --git a/extension/Documentation/UsersManual/Index.rst b/extension/Documentation/UsersManual/Index.rst index 5eb8d2639595e1579ba819262e73654a5019fc66..cc43ec62025a6d2d999c8ec55bc6a0c961a33207 100644 --- a/extension/Documentation/UsersManual/Index.rst +++ b/extension/Documentation/UsersManual/Index.rst @@ -38,43 +38,45 @@ The title of the QFQ content element will not be rendered. It's only visible in QFQ Keywords (Bodytext) ^^^^^^^^^^^^^^^^^^^^^^^ - +-----------------+---------------------------------------------------------------------------------+ - | Name | Explanation | - +=================+=================================================================================+ - | form | Formname defined in ttcontent record bodytext | - | | * Fix. E.g.: **form = person** | - | | * by SIP: **form = {{form}}** | - | | * by SQL: **form = {{SELECT c.form FROM conference AS c WHERE c.id={{a:C}} }}** | - +-----------------+---------------------------------------------------------------------------------+ - | r | recordId. If specified, the form will load the record with the specified id | - | | * Fix. E.g.: **r = 123**, by SQL: **r = {{SELECT ...}}** | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.db | Select a DB. Only necessary if a different than the standard DB should be used. | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.fbeg | Start token for every field (=column) | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.fend | End token for every field (=column) | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.head | Start token for whole <level> | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.tail | End token for whole <level> | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.rbeg | Start token for row. | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.rbgd | Alternating (per row) token | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.rend | End token for row. Will be rendered **before** subsequent levels are processed | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.renr | End token for row. Will be rendered **after** subsequent levels are processed | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.rsep | Seperator token between rows | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.fsep | Seperator token between fields (=columns) | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.sql | SQL Query | - +-----------------+---------------------------------------------------------------------------------+ - | <level>.althead | If <level>.sql is empty, these token will be rendered | - +-----------------+---------------------------------------------------------------------------------+ + +-------------------+---------------------------------------------------------------------------------+ + | Name | Explanation | + +===================+=================================================================================+ + | form | Formname defined in ttcontent record bodytext | + | | * Fix. E.g.: **form = person** | + | | * by SIP: **form = {{form}}** | + | | * by SQL: **form = {{SELECT c.form FROM conference AS c WHERE c.id={{a:C}} }}** | + +-------------------+---------------------------------------------------------------------------------+ + | r | recordId. If specified, the form will load the record with the specified id | + | | * Fix. E.g.: **r = 123**, by SQL: **r = {{SELECT ...}}** | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.db | Select a DB. Only necessary if a different than the standard DB should be used. | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.fbeg | Start token for every field (=column) | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.fend | End token for every field (=column) | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.head | Start token for whole <level> | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.tail | End token for whole <level> | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.rbeg | Start token for row. | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.rbgd | Alternating (per row) token | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.rend | End token for row. Will be rendered **before** subsequent levels are processed | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.renr | End token for row. Will be rendered **after** subsequent levels are processed | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.rsep | Seperator token between rows | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.fsep | Seperator token between fields (=columns) | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.sql | SQL Query | + +-------------------+---------------------------------------------------------------------------------+ + | <level>.althead | If <level>.sql is empty, these token will be rendered | + +-------------------+---------------------------------------------------------------------------------+ + | debugShowBodyText | If ='1' and config.ini:*showDebugInfo=yes*: shows a tooltip with bodytext | + +-------------------+---------------------------------------------------------------------------------+ .. _debug: @@ -201,16 +203,21 @@ Only variables that are known in a specified store can be substituted. +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ | P | Parent record. E.g.: on multi forms the current record of the outer query | All columns of the MultiSQL Statement from the table for the current row | +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ - | D | The *table.column* specified *default value*. | | + | D | Default values column : The *table.column* specified *default value*. | | +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ - | M | The *table.column* specified *type* | | + | M | Column type: The *table.column* specified *type* | | +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ | C | Client: POST variable, if not found: GET variable | Parameter sent from the Client (=Browser). | +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ | T | Typo3: a) Bodytext (ttcontent record), b) Typo3 internal varibles like fe_user_uid, ...| See Typo3 tt_content record configuration | +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ - | 0 | Value: 0, might be helpful if variable is empty but used in an SQL statement, which | All possible keys | - | | might produce a SQL error otherwise if substituted with an empty string | | + | V | Vars - Generic variables | | + +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ + | 0 | Zero - allways value: 0, might be helpful if a variable is empty or undefined and will | All possible keys | + | | be used in an SQL statement. | | + +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ + | E | Empty - allways value: 0, might be helpful if a variable is empty or undefined and will| All possible keys | + | | be used in an SQL statement | | +-----+----------------------------------------------------------------------------------------+----------------------------------------------------------------------------+ | Y | System: a) Database credentials, b) helper vars for logging/debugging: | | | | SYSTEM_SQL_RAW ... SYSTEM_FORM_ELEMENT_COLUMN | | @@ -242,12 +249,6 @@ Store: *CLIENT* - C +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ | keySemIdUser | *{{keySemIdUser}}*, may be changed by user | +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ - | pageId | current T3 page Id | - +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ - | pageType | T3 GET Parameter 'type' | - +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ - | pageLanguage | T3 GET Parameter 'L' | - +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ | HTTP_HOST | current HTTP HOST | +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ | REMOTE_ADDR | Client IP address | @@ -256,8 +257,6 @@ Store: *CLIENT* - C +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ | form | Unique name of current form | +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ - | random | random string with length of 32 chars, alphanum | - +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ | ANREDE | *{{sex}}* == male >> Sehr geehrter Herr, *{{sex}}* == female Sehr geehrte Frau | +---------------+------------------------------------------------------------------------------------------------------------------------------------------+ | EANREDE | *{{sex}}* == male >> Dear Mr., *{{sex}}* == female >> Dear Mrs. | @@ -274,15 +273,19 @@ Store: *TYPO3* (Bodytext) - T | | * Fix. E.g. *form = person* | | | * via SIP. E.g. *form = {{form}}* | +---------------+-------------------------------------------------------------------+ - | feUser | Logged in Typo3 FE User | + | pageId | Record id of current Typo3 page | +---------------+-------------------------------------------------------------------+ - | feUserUid | Logged in Typo3 FE User uid | + | pageType | Current selected page type (typically URL parameter 'type') | +---------------+-------------------------------------------------------------------+ - | feUserGroup | FE groups of logged in Typo3 FE User | + | pageLanguage | Current selected page language (typically URL parameter 'L') | +---------------+-------------------------------------------------------------------+ | ttcontentUid | Record id of current Typo3 content element | +---------------+-------------------------------------------------------------------+ - | typo3PageId | Record id of current Typo3 page | + | feUser | Logged in Typo3 FE User | + +---------------+-------------------------------------------------------------------+ + | feUserUid | Logged in Typo3 FE User uid | + +---------------+-------------------------------------------------------------------+ + | feUserGroup | FE groups of logged in Typo3 FE User | +---------------+-------------------------------------------------------------------+ @@ -309,6 +312,15 @@ Store: *RECORD* - R | record column name | Name of a column of the primary table (as defined in the current form). To get, exactly and only, the specified form element: *{{p_id:R}}* | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ +Store: *VARS* - V +^^^^^^^^^^^^^^^^^ + + +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ + | Name | Explanation | + +====================+============================================================================================================================================+ + | random | random string with length of 32 chars, alphanum | + +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ + SQL --- @@ -773,7 +785,7 @@ Type: subrecord * *<number>*: any 'digit only' will be treated as '''width'''. * *width=<number>*: max. number of chars displayed per cell in the column. * *nostrip*: by default, html tags will be stripped off the cell content before rendering. This protects the table layout. 'nostrip' deactivates the cleaning to make links, images, ... possible. - * *icon*: the cell value contains the name of an icon in *fileadmin/icons*. Empty cell values will omit an html image tag (=nothing renderd in the cell). + * *icon*: the cell value contains the name of an icon in *typo3conf/ext/qfq/Resources/Public/icons*. Empty cell values will omit an html image tag (=nothing renderd in the cell). * *mailto*: value will be rendered as a mailto link. * *url*: value will be rendered as a link. * *title=<text>* or '<none of the above>': column '''title'''. @@ -941,7 +953,7 @@ Syntax Global variables: {{global.<name>}} - Sanitized URL (Post/Get) variables: {{url.<name>}} + Variables from specific stores: {{<name>[:<store/s>[:<sanitize class>]]}} Row index and total rows: {{<level>.line.count}} or {{<level>.line.total}} @@ -974,6 +986,7 @@ The parsed bodytext could be displayed by activating 'showDebugInfo' (:ref:`debu debugShowBodyText = 1 A small symbol with a tooltip will be shown, where the content record will be displayed on the webpage. +Note: :ref:`debug` information will only be shown with *showDebugInfo=yes* in config.ini . Structure --------- @@ -1011,7 +1024,7 @@ Across several lines ^^^^^^^^^^^^^^^^^^^^ To make SQL quieres more readable, it's possible to split a line across several lines. Lines with keywords are on their -own - if there are non 'keyword' lines, they will be appended at the last keyword line. 'Keyword' lines: +own - if a line is not a 'keyword' line, it will be appended at the last keyword line. 'Keyword' lines are detected on: * <level>.<keyword> = * { @@ -1274,17 +1287,17 @@ Link Examples +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ |SELECT "p:form_person&S_person=Text|t:Person" AS link |<a class="internal" href="?form_person&S_person=Text">Person</a> | +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -|SELECT "p:form_person|e" AS link |<a class="internal" href="?form_person"><img alttext="Edit" src="fileadmin/typo3conf/ext/formreport/icons/edit.gif"></a> | +|SELECT "p:form_person|e" AS link |<a class="internal" href="?form_person"><img alttext="Edit" src="typo3conf/ext/qfq/Resources/Public/icons/edit.gif"></a> | +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -|SELECT "p:form_person|e|g:_blank" AS link |<a target="_blank" class="internal" href="?form_person"><img alttext="Edit" src="fileadmin/typo3conf/ext/formreport/icons/edit.gif"></a>| +|SELECT "p:form_person|e|g:_blank" AS link |<a target="_blank" class="internal" href="?form_person"><img alttext="Edit" src="typo3conf/ext/qfq/Resources/Public/icons/edit.gif"></a>| +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -|SELECT "p:form_person|C" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="fileadmin/typo3conf/ext/formreport/icons/checked-green.gif"></a> | +|SELECT "p:form_person|C" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="typo3conf/ext/qfq/Resources/Public/icons/checked-green.gif"></a> | +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -|SELECT "p:form_person|C:green" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="fileadmin/typo3conf/ext/formreport/icons/checked-green.gif"></a> | +|SELECT "p:form_person|C:green" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="typo3conf/ext/qfq/Resources/Public/icons/checked-green.gif"></a> | +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -|SELECT "A:p:form_person|G:C" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="fileadmin/typo3conf/ext/formreport/icons/checked-green.gif"></a> | +|SELECT "A:p:form_person|G:C" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="typo3conf/ext/qfq/Resources/Public/icons/checked-green.gif"></a> | +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -|SELECT "A:u:www.example.com|G:P:home.gif|t:Home" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="ffileadmin/typo3conf/ext/formreport/icons/home.gif">Home</a> | +|SELECT "A:u:www.example.com|G:P:home.gif|t:Home" AS link |<a class="internal" href="?form_person"><img alttext="Check" src="typo3conf/ext/qfq/Resources/Public/icons/home.gif">Home</a> | +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ @@ -1505,7 +1518,7 @@ Send simple plain text emails. Every mail will be logged in the mail log. The lo :: - 10.sql = SELECT "john.doe@example.com|company@example.com|Latest News|The new version of FormReport is now available." AS sendmail + 10.sql = SELECT "john.doe@example.com|company@example.com|Latest News|The new version is now available." AS sendmail .. @@ -1518,7 +1531,7 @@ This will send an email with subject *Latest News* from company@example.com to j :: - 10.sql = SELECT "customer1@example.com, customer2@example.com|company@example.com|Latest News|The new version of FormReport is now available." AS sendmail + 10.sql = SELECT "customer1@example.com, customer2@example.com|company@example.com|Latest News|The new version is now available." AS sendmail .. @@ -1803,7 +1816,8 @@ Solution for *#Challenge_2*: Include a form via link/url ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In most occasions it is handy if a formname does not have to be hard-coded in report but can be passed to the page as a parameter. To achieve this, first build a link on page A which includes the required parameters: +In most occasions it is handy if a formname does not have to be hard-coded in report but can be passed to the page as a +parameter. To achieve this, first build a link on page A which includes the required parameters: **page A** @@ -1814,9 +1828,8 @@ In most occasions it is handy if a formname does not have to be hard-coded in re .. - - -The above example builds a link to pageB - refer to the 'link'-manual for details. The link tells page B to render the form with name formname and load the record with id id for editing. +The above example builds a link to pageB - refer to the :ref:`column-link`-manual for details. The link tells page B to +render the form with name formname and load the record with id id for editing. Examples -------- @@ -2032,7 +2045,18 @@ Formating (i.e. wrapping of data with HTML tags etc.) can be achieved in two dif .. +The same as above, but with braces:: + + + 10 { + sql = SELECT p.name FROM exp_person AS p + head = <ul> + tail = </ul> + rbeg = <li> + rend = </li> + } +:: Two queries @@ -2086,7 +2110,7 @@ Two queries: nested with variables * For every record of '10', all assigned records of 10.10 will be printed. - Two queries: nested with hidden variables in a table +Two queries: nested with hidden variables in a table :: @@ -2100,8 +2124,63 @@ Two queries: nested with variables .. +Same as above, but written in the nested notation:: + + 10 { + sql = SELECT p.id AS _p_id, p.name FROM exp_person AS p + rend = <br /> + 10 { + # inner query + sql = SELECT a.street FROM exp_address AS a WHERE a.p_id='{{10.p_id}}' + rend = <br /> + } + } * Columns starting with a '_' won't be printed but can be accessed as regular columns. +Best practice +============= + +Debug Report +------------ + +Writing "report's" in the nested notation or long queries broken over several lines, might not interpreted as wished. +Best for debugging is to specify in the tt-content record:: + + debugShowBodyText = 1 + +Note: Debug information is only display if it's enabled in *config.ini* by + * *SHOW_DEBUG_INFO=yes* or + * *SHOW_DEBUG_INFO=auto* and logged in in the same Browser as a Typo3 backend user. + +More detailed error messages +---------------------------- + +If *SHOW_DEBUG_INFO* is enabled, a full stacktrace and variable contents are displayed in case of an error. + +Person search form +------------------ + +QFQ content record:: + + # Creates a small form that redirects back to this page + 10 { + sql = SELECT '_' + head = <form action='#' method='get'><input type='hidden' name='id' value='{{pageId:T}}'>Search: <input type='text' name='search' value='{{search:CE:all}}'><input type='submit' value='Submit'></form> + } + + # SQL statement will find and list all the relevant forms + 20 { + sql = SELECT CONCAT('?detail&form=form&r=', f.id) AS Pagee, f.id, f.name, f.title + FROM Form AS f + WHERE f.name LIKE '%{{search:CE:all}}%' + head = <table class='table'> + tail = </table> + rbeg = <tr> + rend = </tr> + fbeg = <td> + fend = </td> + } + diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index c2363b61b582f529b0ed3c59aae667448fd4953f..0809666328eb699151c03c7244d55f32330a2c90 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -380,16 +380,18 @@ abstract class AbstractBuildForm { public function deriveNewRecordUrlFromExistingSip(&$toolTipNew) { $urlParam = $this->store->getStore(STORE_SIP); $urlParam[SIP_RECORD_ID] = 0; + unset($urlParam[SIP_SIP]); unset($urlParam[SIP_URLPARAM]); - $urlParam['id'] = $this->store->getVar(TYPO3_PAGE_ID, STORE_TYPO3); - $urlParam['type'] = $this->store->getVar(TYPO3_PAGE_TYPE, STORE_TYPO3); + + Support::appendTypo3ParameterToArray($urlParam); $sip = $this->store->getSipInstance(); $url = $sip->queryStringToSip(OnArray::toString($urlParam)); if ($this->showDebugInfo) { + //TODO: missing decoding of SIP $toolTipNew .= PHP_EOL . PHP_EOL . OnArray::toString($urlParam, ' = ', PHP_EOL, "'"); } diff --git a/extension/qfq/qfq/BodytextParser.php b/extension/qfq/qfq/BodytextParser.php index 44e8bb99677228c57d7e4e6ce6e356066ca16f3a..fd9899d07aa5f5a332d8af2a1160548e769123b1 100644 --- a/extension/qfq/qfq/BodytextParser.php +++ b/extension/qfq/qfq/BodytextParser.php @@ -61,7 +61,8 @@ class BodytextParser { $full = ''; foreach ($bodytextArray as $row) { // Valid 'new line' starts indicators: form, <level>, <level.sublevel>, <level>.<keyword>, {, <level> {, } - if ((1 === preg_match('/^\s*(\d*(\.)?)*\s*(head|althead|tail|sql|rbeg|rend|renr|rsep|fbeg|fend|fsep|form|debugShowBodyText|r) *=/', $row)) + if ((1 === preg_match('/^\s*(\d*(\.)?)*\s*(head|althead|tail|sql|rbeg|rend|renr|rsep|fbeg|fend|fsep|' . + TYPO3_FORM . '|' . TYPO3_DEBUG_SHOW_BODY_TEXT . '|' . TYPO3_RECORD_ID . ') *=/', $row)) || (1 === preg_match('/^\s*(\d*(\.)?)*\s*({|})\s*/', $row)) || (1 === preg_match('/^\s*(\d+(\.)?)+/', $row)) ) { @@ -96,8 +97,7 @@ class BodytextParser { // Replace '\{' | '\}' by internal token. All remaining '}' | '{' means: 'nested' $bodytext = str_replace('\{', '#&[_#', $bodytext); $bodytext = str_replace('\}', '#&]_#', $bodytext); - $bodytext = str_replace('{{', '#&[[_#', $bodytext); - $bodytext = str_replace('}}', '#&]]_#', $bodytext); + $bodytext = Support::encryptDoubleCurlyBraces($bodytext); $result = $bodytext; $posFirstClose = strpos($result, '}'); @@ -143,9 +143,7 @@ class BodytextParser { $result = str_replace('#&[_#', '{', $result); $result = str_replace('#&]_#', '}', $result); - $result = str_replace('#&[[_#', '{{', $result); - $result = str_replace('#&]]_#', '}}', $result); - + $result = Support::decryptDoubleCurlyBraces($result); return $result; } diff --git a/extension/qfq/qfq/BuildFormBootstrap.php b/extension/qfq/qfq/BuildFormBootstrap.php index aa94e679507767362759fb403546eb92d223fd27..ff688059f0c3470549481b01563a664913e2bce0 100644 --- a/extension/qfq/qfq/BuildFormBootstrap.php +++ b/extension/qfq/qfq/BuildFormBootstrap.php @@ -10,6 +10,7 @@ namespace qfq; use qfq; use qfq\UserFormException; +use TYPO3\CMS\Form\Domain\Model\Element\ButtonElement; require_once(__DIR__ . '/../qfq/Constants.php'); require_once(__DIR__ . '/../qfq/helper/OnArray.php'); @@ -112,71 +113,102 @@ class BuildFormBootstrap extends AbstractBuildForm { } /** - * Simlute Submit Button: http://www.javascript-coder.com/javascript-form/javascript-form-submit.phtml + * Simulate Submit Button: http://www.javascript-coder.com/javascript-form/javascript-form-submit.phtml * * @return string */ private function buildButtons() { - $toolTipNew = 'New'; - $toolTipDelete = 'Delete'; - $buttonDelete = ''; $buttonNew = ''; - $buttonDebug = ''; + $buttonDelete = ''; + $buttonClose = ''; + $buttonSave = ''; + $buttonEditForm = ''; $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP); // Button: FormEdit if ($this->showDebugInfo) { - $tooltipFormEdit = "Edit form" . PHP_EOL . PHP_EOL . OnArray::toString($this->store->getStore(STORE_SIP), ' = ', PHP_EOL, "'"); - $urlFormEdit = $this->createFormEditUrl(); - // Edit Form - $buttonDebug = <<<BUTTON - <div class="btn-group" role="group"> - <a href="$urlFormEdit" id="form-edit-button" class="btn btn-default navbar-btn" title="$tooltipFormEdit"><span class="glyphicon glyphicon-wrench"></span></a> - </div> -BUTTON; + $toolTip = "Edit form" . PHP_EOL . PHP_EOL . OnArray::toString($this->store->getStore(STORE_SIP), ' = ', PHP_EOL, "'"); + $url = $this->createFormEditUrl(); + + $buttonEditForm = $this->buildButtonAnchor('form-edit-button', $url, $toolTip, 'glyphicon-wrench'); + } + + // Button: Save + if (Support::findInSet(FORM_BUTTON_SAVE, $this->formSpec['showButton'])) { + $toolTip = 'Save'; + + if ($this->showDebugInfo) { + $toolTip .= PHP_EOL . "table = '" . $this->formSpec['tableName'] . "'" . PHP_EOL . "r = '" . $recordId . "'"; + } + + $buttonSave = $this->buildButtonCode('save-button', $toolTip, 'glyphicon-ok'); + } + + // Button: Close + if (Support::findInSet(FORM_BUTTON_CLOSE, $this->formSpec['showButton'])) { + $toolTip = 'Close'; + + if ($this->showDebugInfo) { + $toolTip .= PHP_EOL . "table = '" . $this->formSpec['tableName'] . "'" . PHP_EOL . "r = '" . $recordId . "'"; + } + + $buttonClose = $this->buildButtonCode('close-button', 'Close', 'glyphicon-remove'); } // Button: Delete if (Support::findInSet(FORM_BUTTON_DELETE, $this->formSpec['showButton'])) { + $toolTip = 'Delete'; + if ($this->showDebugInfo && $recordId > 0) { - $toolTipDelete .= PHP_EOL . "table = '" . $this->formSpec['tableName'] . "'" . PHP_EOL . "r = '" . $recordId . "'"; + $toolTip .= PHP_EOL . "table = '" . $this->formSpec['tableName'] . "'" . PHP_EOL . "r = '" . $recordId . "'"; } - $buttonDeleteDisabled = ($recordId > 0) ? '' : 'disabled'; + $disabled = ($recordId > 0) ? '' : 'disabled'; - $buttonDelete = <<<BUTTON - <div class="btn-group" role="group"> - <button id="delete-button" type="button" class="btn btn-default navbar-btn $buttonDeleteDisabled" title="$toolTipDelete"><span class="glyphicon glyphicon-trash"></span></button> - </div> -BUTTON; + $buttonDelete = $this->buildButtonCode('delete-button', $toolTip, 'glyphicon-trash', $disabled); } // Button: New if (Support::findInSet(FORM_BUTTON_NEW, $this->formSpec['showButton'])) { - $formNewUrl = $this->deriveNewRecordUrlFromExistingSip($toolTipNew); + $toolTip = 'New'; + $url = $this->deriveNewRecordUrlFromExistingSip($toolTip); - $buttonNew = <<<BUTTON - <div class="btn-group" role="group"> - <a href="$formNewUrl" id="form-new-button" class="btn btn-default navbar-btn" title="$toolTipNew"><span class="glyphicon glyphicon-plus"></span></a> - </div> -BUTTON; + $buttonNew = $this->buildButtonAnchor('form-new-button', $url, $toolTip, 'glyphicon-plus'); } -// <div class="btn-toolbar pull-right" role="toolbar"> - $html = <<<BUTTON - <div class="btn-toolbar" role="toolbar"> - $buttonDebug - <div class="btn-group" role="group"> - <button id="save-button" type="button" class="btn btn-default navbar-btn" title="Save"><span class="glyphicon glyphicon-ok"></span></button> - <button id="close-button" type="button" class="btn btn-default navbar-btn" title="Close"><span class="glyphicon glyphicon-remove"></span></button> - </div> - $buttonDelete - $buttonNew - </div> -BUTTON; + $html = Support::wrapTag('<div class="btn-group" role="group">', $buttonEditForm); + $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonSave . $buttonClose); + $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonDelete); + $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonNew); + + $html = Support::wrapTag('<div class="btn-toolbar" role="toolbar">', $html); + return $html; } + /** + * @param $id + * @param $url + * @param $title + * @param $icon + * @param string $disabled + * @return string + */ + private function buildButtonAnchor($id, $url, $title, $icon, $disabled = '') { + return "<a href='$url' id='$id' class='btn btn-default navbar-btn $disabled' " . Support::doAttribute('title', $title) . "><span class='glyphicon $icon'></span></a>"; + } + + /** + * @param $id + * @param $title + * @param $icon + * @param string $disabled + * @return string + */ + private function buildButtonCode($id, $title, $icon, $disabled = '') { + return "<button id='$id' type='button' class='btn btn-default navbar-btn $disabled' " . Support::doAttribute('title', $title) . "><span class='glyphicon $icon'></span></button>"; + } + /** * @param $pillArray * @return string diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index a9a9f97b9e0130f1d9eb9a3bafbcb591be9eaa8a..04202e5c7ae49097e16cbf22f51b4ba81c854b34 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -26,6 +26,8 @@ const FORM_PERMISSION_ALWAYS = 'always'; const FORM_PERMISSION_NEVER = 'never'; const FORM_BUTTON_NEW = 'new'; const FORM_BUTTON_DELETE = 'delete'; +const FORM_BUTTON_CLOSE = 'close'; +const FORM_BUTTON_SAVE = 'save'; const FORM_FORWARD_MODE_NO = 'no'; const FORM_FORWARD_MODE_AUTO = 'auto'; @@ -35,6 +37,7 @@ const SESSION_FE_USER_UID = 'fe_user_uid'; const RETURN_URL = 'return_url'; const RETURN_SIP = 'return_sip'; +const RETURN_ARRAY = 'return_array'; const SQL_FORM_ELEMENT_SPECIFIC_CONTAINER = "SELECT *, ? AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = ? AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, ? ) AND fe.feIdContainer = ? AND fe.enabled='yes' ORDER BY fe.ord, fe.id"; const SQL_FORM_ELEMENT_ALL_CONTAINER = "SELECT *, ? AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = ? AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, ? ) AND fe.enabled='yes' ORDER BY fe.ord, fe.id"; @@ -171,7 +174,9 @@ const STORE_TABLE_DEFAULT = "D"; // definition of primary table. const STORE_TABLE_COLUMN_TYPES = "M"; // column types of primary table. const STORE_CLIENT = "C"; // Client: POST variable, if not found: GET variable const STORE_TYPO3 = "T"; // Typo3 > Page content record > bodytext +const STORE_VAR = "V"; // Generic Vars const STORE_ZERO = "0"; // value: 0, might helpfull if variable is empty but used in an SQL statement, which might produce a SQL error otherwise if substituted with an empty string +const STORE_EMPTY = "E"; // value: '', might helpfull if variable is not defined and should result in an empty string instead of {{...}} (cause not replaced) const STORE_SYSTEM = "Y"; // various system values like db connection credentials const STORE_USE_DEFAULT = "FSRD"; @@ -209,12 +214,15 @@ const CLIENT_PHP_SELF = 'PHP_SELF'; // T3 Bodytext Keywords const TYPO3_FORM = CLIENT_FORM; +const TYPO3_RECORD_ID = CLIENT_RECORD_ID; const TYPO3_FE_USER = 'feUser'; const TYPO3_FE_USER_UID = 'feUserUid'; const TYPO3_FE_USER_GROUP = 'feUserGroup'; const TYPO3_TT_CONTENT_UID = 'ttcontentUid'; -const TYPO3_PAGE_ID = 'typo3PageId'; -const TYPO3_PAGE_TYPE = 'typo33PageType'; +const TYPO3_PAGE_ID = 'pageId'; +const TYPO3_PAGE_TYPE = 'pageType'; +const TYPO3_PAGE_LANGUAGE = 'pageLanguage'; +const TYPO3_DEBUG_SHOW_BODY_TEXT = 'debugShowBodyText'; // System const SYSTEM_DB_USER = 'DB_USER'; @@ -260,6 +268,12 @@ const SIP_TABLE = 'table'; // delete a record from 'table' const SIP_URLPARAM = 'urlparam'; // FURTHER: all extracted params from 'urlparam +const VAR_RANDOM = 'random'; + + +const RANDOM_LENGTH = 32; + + // FORM - copy from table 'form' of processed form //const DEF_FORM_NAME = CLIENT_FORM; @@ -317,3 +331,6 @@ const GLYPH_ICON_SHOW = 'glyphicon glyphicon-search'; const GLYPH_ICON_TOOL = 'glyphicon-wrench'; const GLYPH_ICON_CHECK = 'glyphicon glyphicon-ok'; +// SUPPORT +const PARAM_T3_ALL = 't3 all'; +const PARAM_T3_NO_ID = "t3 no id"; \ No newline at end of file diff --git a/extension/qfq/qfq/Evaluate.php b/extension/qfq/qfq/Evaluate.php index 3638b75bbbbb1f19e07cc934b864ecf2cc3a9020..bea3de79a1ba55b3bb8c06e2b25a8d851465ac1c 100644 --- a/extension/qfq/qfq/Evaluate.php +++ b/extension/qfq/qfq/Evaluate.php @@ -84,7 +84,6 @@ class Evaluate { $posFirstClose = strpos($result, $this->endDelimiter); while ($posFirstClose !== false) { - $flagTokenReplaced = true; $posMatchOpen = strrpos(substr($result, 0, $posFirstClose), $this->startDelimiter); if ($posMatchOpen === false) { @@ -96,32 +95,42 @@ class Evaluate { $match = substr($result, $posMatchOpen + $this->startDelimiterLength, $posFirstClose - $posMatchOpen - $this->startDelimiterLength); $evaluated = $this->substitute($match, $foundInStore); + $debugLocal[] = $debugIndent . "#Replace: '$match'"; - // If an array is returned, break everything and return this assoc array. - if (is_array($evaluated)) { - $result = $evaluated; - $debugLocal[] = $debugIndent . "#By: 'array(" . count($result) . ")'"; - break; - } + if ($foundInStore === '') { + // Encode the non replaceable part as preparation not to process again and to recode at the end. + $evaluated = Support::encryptDoubleCurlyBraces($this->startDelimiter . $match . $this->endDelimiter); + $debugLocal[] = $debugIndent . "#By: <nothing found - not replaced>"; + } else { + + $flagTokenReplaced = true; - $debugLocal[] = $debugIndent . "#By: '$evaluated'"; + // If an array is returned, break everything and return this assoc array. + if (is_array($evaluated)) { + $result = $evaluated; + $debugLocal[] = $debugIndent . "#By: 'array(" . count($result) . ")'"; + break; + } - // More to substitute in the new evaluated result? Start recursion just with the new result.. - if (strpos($evaluated, $this->endDelimiter) !== false) { - $evaluated = $this->parse($evaluated, $recursion + 1, $debugLocal, $foundInStore); - } + $debugLocal[] = $debugIndent . "#By: '$evaluated'"; + // More to substitute in the new evaluated result? Start recursion just with the new result.. + if (strpos($evaluated, $this->endDelimiter) !== false) { + $evaluated = $this->parse($evaluated, $recursion + 1, $debugLocal, $foundInStore); + } + } $result = $pre . $evaluated . $post; + $posFirstClose = strpos($result, $this->endDelimiter); } if ($flagTokenReplaced === true) { - $debugLocal[] = $debugIndent . "#Final: " . is_array($result) ? "array(" . count($result) .")" : "'$result'" ; + $debugLocal[] = $debugIndent . "#Final: " . is_array($result) ? "array(" . count($result) . ")" : "'$result'"; $debugStack = $debugLocal; } - return $result; + return Support::decryptDoubleCurlyBraces($result); } /** @@ -133,7 +142,7 @@ class Evaluate { * If neither a) or b) match, return the token itself, surrounded by single ticks, to emphase that substition failed. * * @param $token - * @param string $foundInStore + * @param string $foundInStore Returns the name of the store where $key has been found. If $key is not found, return ''. * @return array|mixed|null|string * @throws CodeException * @throws DbException @@ -154,6 +163,7 @@ class Evaluate { // SQL Statement? if (in_array(strtoupper($arr[0] . ' '), $this->sqlKeywords)) { + $foundInStore = 'query'; return $this->db->sql($token, $sqlMode); } @@ -168,8 +178,11 @@ class Evaluate { // search for value in stores $value = $this->store->getVar($arr[0], $arr[1], $arr[2], $foundInStore); - // nothing replaced: put ticks around, to sanitize strings for SQL statements. Nothing to substitute is not a wished situation. - return ($value === false) ? "'" . $token . "'" : $value; + // OLD: nothing replaced: put ticks around, to sanitize strings for SQL statements. Nothing to substitute is not a wished situation. +// return ($value === false) ? "'" . $token . "'" : $value; + + // NEW: nothing replaced: higher level should decide what to do + return $value; } public function getDebug() { diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php index 01cf3c7c9534050523b2ec60fbea4aab4f1ef386..ae672a63f21d3a8c067a02fdfdcc1d3c34babf1d 100644 --- a/extension/qfq/qfq/QuickFormQuery.php +++ b/extension/qfq/qfq/QuickFormQuery.php @@ -158,7 +158,7 @@ class QuickFormQuery { public function process() { $html = ''; - if ($this->store->getVar('debugShowBodyText', STORE_TYPO3) === '1') { + if ($this->store->getVar(TYPO3_DEBUG_SHOW_BODY_TEXT, STORE_TYPO3) === '1') { $html .= Support::appendTooltip('', $this->t3data['bodytext']); } @@ -418,7 +418,7 @@ class QuickFormQuery { * @return string */ private function doReport() { - $report = new Report($this->t3data, $this->store->getVar(SYSTEM_SESSION_NAME, STORE_SYSTEM), $this->phpUnit); + $report = new Report($this->t3data, $this->store->getVar(SYSTEM_SESSION_NAME, STORE_SYSTEM), $this->eval, $this->phpUnit); $html = $report->process(); diff --git a/extension/qfq/qfq/helper/Support.php b/extension/qfq/qfq/helper/Support.php index 598e7ecb49af8f1abb7e2e14ef2bd551d8095cec..d57833ef6be9540a9a0b2ff6db57066958c6f07d 100644 --- a/extension/qfq/qfq/helper/Support.php +++ b/extension/qfq/qfq/helper/Support.php @@ -14,19 +14,29 @@ class Support { /** * @param array $queryArray Empty or prefilled assoc array with url parameter + * @param string $mode PARAM_T3_NO_ID, PARAM_T3_ALL */ - public static function appendTypo3ParameterToArray(array &$queryArray) { + public static function appendTypo3ParameterToArray(array &$queryArray, $mode = PARAM_T3_ALL) { // if (isset($_GET['id'])) // $queryArray['id'] = self::getCurrentPage(); - if (isset($GLOBALS["TSFE"]->id)) - $queryArray['id'] = $GLOBALS["TSFE"]->id; - if (isset($_GET['L'])) - $queryArray['L'] = $_GET['L']; + $store = Store::getInstance(); - if (isset($_GET['type'])) - $queryArray['type'] = $_GET['type']; + if ($mode === PARAM_T3_ALL) { + $queryArray['id'] = $store->getVar(TYPO3_PAGE_ID, STORE_TYPO3); + } + + // TYPE + $tmp = $store->getVar(TYPO3_PAGE_TYPE, STORE_TYPO3); + if ($tmp !== false && $tmp != 0) { + $queryArray['type'] = $tmp; + } + // Language + $tmp = $store->getVar(TYPO3_PAGE_LANGUAGE, STORE_TYPO3); + if ($tmp !== false && $tmp != 0) { + $queryArray['L'] = $tmp; + } } /** @@ -186,4 +196,57 @@ class Support { return $date . ' ' . $time; } + + /** + * Encrypt curly braces by an uncommon string. Helps preventing unwished action on curly braces. + * + * @param $text + * @return mixed + */ + public static function encryptDoubleCurlyBraces($text) { + $text = str_replace('{{', '#&@[[@_#', $text); + $text = str_replace('}}', '#&@]]@_#', $text); + + return $text; + } + + /** + * Decrypt curly braces by an uncommon string. Helps preventing unwished action on curly braces + * + * @param $text + * @return mixed + */ + public static function decryptDoubleCurlyBraces($text) { + $text = str_replace('#&@[[@_#', '{{', $text); + $text = str_replace('#&@]]@_#', '}}', $text); + + return $text; + } + + /** + * @param int $length Length of the required hash string + * @return string A random alphanumeric hash + */ + public static function randomAlphaNum($length) { + $possible_characters = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $string = ""; + while (strlen($string) < $length) { + $string .= substr($possible_characters, rand() % (strlen($possible_characters)), 1); + } + + return ($string); + } + + /** + * @param $url + * @param $param + * @return string + */ + public static function concatUrlParam($url, $param) { + if ($param == '') + return $url; + + $token = (strpos($url, '?') === false) ? '?' : '&'; + return $url . $token . $param; + } } \ No newline at end of file diff --git a/extension/qfq/qfq/report/Link.php b/extension/qfq/qfq/report/Link.php index 5ae9e55f8d6eb518276c30c8946019489d87e14a..407bd3d13a1b61c420f54ac4043e8a57bbb00e14 100644 --- a/extension/qfq/qfq/report/Link.php +++ b/extension/qfq/qfq/report/Link.php @@ -70,6 +70,7 @@ const NAME_PAGE = 'page'; const NAME_TEXT = 'text'; const NAME_ALT_TEXT = 'altText'; const NAME_TOOL_TIP = 'toolTip'; +const NAME_TOOL_TIP_JS = 'toolTipJs'; const NAME_IMAGE = 'image'; const NAME_IMAGE_TITLE = 'imageTitle'; const NAME_GLYPH = 'glyph'; @@ -85,6 +86,8 @@ const NAME_HASH = 'hash'; const NAME_URL_PARAM = 'param'; const NAME_RIGHT_PICTURE_POSITION = 'picturePosition'; +const NO_CLASS = 'no_class'; + /** * Class Link * @package qfq @@ -123,6 +126,7 @@ class Link { 'u' => 'buildUrl', 'm' => 'buildMail', 'p' => 'buildPage', + 'o' => 'buildToolTip', 'P' => 'buildPicture', 'B' => 'buildBullet', 'C' => 'buildCheck', @@ -178,7 +182,7 @@ class Link { $this->utils = new Utils(); $this->varsDefault[NAME_QUESTION] = 'Please confirm'; - $this->varsDefault[NAME_PAGE] = $this->store->getVar(TYPO3_PAGE_ID, STORE_TYPO3); +// $this->varsDefault[NAME_PAGE] = $this->store->getVar(TYPO3_PAGE_ID, STORE_TYPO3); $this->varsDefault[NAME_ENCRYPTION] = '0'; $this->varsDefault[NAME_RIGHT_PICTURE_POSITION] = 'l'; $this->varsDefault[NAME_RENDER] = 0; @@ -270,7 +274,12 @@ class Link { $this->doCssClass($vars); - $htmlUrl = $this->doHtmlUrl($vars); + // Set default tooltip + if ($vars[NAME_TOOL_TIP] == '' && $vars[NAME_GLYPH_TITLE] !== '') { + $vars[NAME_TOOL_TIP] = $vars[NAME_GLYPH_TITLE]; + } + + $htmlUrl = $this->doAnchor($vars); $htmlImage = $this->doHtmlImageGlyph($vars); // Compose Image & Text @@ -281,8 +290,8 @@ class Link { // ToolTip $extraSpan = ['', '']; - if ($vars[NAME_TOOL_TIP]) { - $extraSpan[0] = "<span " . $vars[NAME_TOOL_TIP][0] . ">" . $vars[NAME_TOOL_TIP][1]; + if ($vars[NAME_TOOL_TIP] !== '') { + $extraSpan[0] = "<span " . $vars[NAME_TOOL_TIP_JS][0] . ">" . $vars[NAME_TOOL_TIP_JS][1]; $extraSpan[1] = "</span>"; } @@ -337,7 +346,7 @@ class Link { // 3: <a href=url>url</a> case '3': - $link = $htmlUrl . $vars[NAME_URL] . '</a>' . $vars[NAME_TOOL_TIP][1]; + $link = $htmlUrl . $vars[NAME_URL] . '</a>' . $vars[NAME_TOOL_TIP_JS][1]; break; case '13': $vars[NAME_TEXT] = $vars[NAME_MAIL]; @@ -346,7 +355,7 @@ class Link { // 4: <a href=url>Text</a> case '4': - $link = $htmlUrl . $vars[NAME_TEXT] . '</a>' . $vars[NAME_TOOL_TIP][1]; + $link = $htmlUrl . $vars[NAME_TEXT] . '</a>' . $vars[NAME_TOOL_TIP_JS][1]; break; case '14': $link = $this->encryptMailtoJS($vars, TRUE); @@ -385,7 +394,8 @@ class Link { $vars[NAME_GLYPH_TITLE] = ''; $vars[NAME_QUESTION] = ''; $vars[NAME_TARGET] = ''; - $vars[NAME_TOOL_TIP] = ['', '']; + $vars[NAME_TOOL_TIP] = ''; + $vars[NAME_TOOL_TIP_JS] = ['', '']; $vars[NAME_URL_PARAM] = ''; $vars[NAME_RENDER] = ''; @@ -426,7 +436,7 @@ class Link { $keyName = $this->tableVarName[$key]; - // A few keys do not have necessarily a value: fake the definition by manual assigning the default + // A few keys do not have necessarily a value: fake the definition by manual creating a value. if ($value == '') { switch ($key) { case 'R': @@ -443,12 +453,12 @@ class Link { } } - // Take defaults + // Defaults if ($value === '' && isset($this->varsDefault[$keyName])) { $value = $this->varsDefault[$keyName]; } - // Check for empty values. Some keys are allowed to be empty. + // Check for empty values. Respect: some keys are allowed to be empty. if ($value === '' && strpos('uENDHIS', $key) === false) { throw new UserReportException ("Missing value for '$key'", ERROR_MISSING_VALUE); } @@ -493,44 +503,52 @@ class Link { $vars[NAME_LINK_CLASS] = ($vars[NAME_LINK_CLASS] == '') ? $vars[NAME_LINK_CLASS_DEFAULT] : $vars[NAME_LINK_CLASS]; break; } + + if ($vars[NAME_LINK_CLASS] === NO_CLASS) { + $vars[NAME_LINK_CLASS] = ''; + } } /** - * Builds complete HTML anchor. - * - <a href="mailto:info@example.com:>info@example.com</a> - * - <a href="http://example.com:>http://example.com</a> - * - If $this->modeHash is set, create a + * Create the HTML anchor. + * - <a href="mailto:info@example.com" title=".." class=".."> + * - <a href="http://example.com" title=".." class=".."> + * - If $this->modeHash is set, create a hash (sip) * * @param array $vars * @return string * @throws UserReportException */ - private function doHtmlUrl(array &$vars) { - $tags = ''; + private function doAnchor(array &$vars) { + $attributes = ''; // build URL - $htmlUrl = ""; $anchorTitle = ''; + // Link: URL if ($vars[NAME_URL] !== '') { if ($vars[NAME_HASH] === "1") { - $vars[NAME_URL] = $this->sip->queryStringToSip($vars[NAME_PAGE] . '&' . $vars[NAME_URL_PARAM]); + $paramArray = $this->sip->queryStringToSip(Support::concatUrlParam($vars[NAME_URL], $vars[NAME_URL_PARAM]), RETURN_ARRAY); + $vars[NAME_URL] = $paramArray['_url']; + if ($this->store->getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM) === 'yes') { + + $vars[NAME_TOOL_TIP] .= PHP_EOL . PHP_EOL . OnArray::toString($paramArray, ' = ', PHP_EOL, "'"); + $this->buildToolTip($vars, 'o', $vars[NAME_TOOL_TIP]); + } } else { if ($vars[NAME_URL_PARAM] != '') { - // Append '&' or '?' depending if there is already a '?' - $vars[NAME_URL] .= (strpos($vars[NAME_URL], '?') >= 0) ? '&' : '?'; - // Append all additional params. - $vars[NAME_URL] .= $vars[NAME_URL_PARAM]; + $vars[NAME_URL] = Support::concatUrlParam($vars[NAME_URL], $vars[NAME_URL_PARAM]); } } } - // If there is no encryption: handle the mailto as an ordinary URL + // Link: MAILTO if ($vars[NAME_MAIL] !== '') { + // If there is no encryption: handle the mailto as an ordinary URL if ($vars[NAME_ENCRYPTION] === '0') { $vars[NAME_URL] = "mailto:" . $vars[NAME_MAIL]; $vars[NAME_MAIL] = ""; @@ -542,22 +560,25 @@ class Link { if ($vars[NAME_GLYPH] !== '') { $vars[NAME_LINK_CLASS] .= ' btn btn-default '; - if ($vars[NAME_GLYPH_TITLE] !== '') { - $anchorTitle = $vars[NAME_GLYPH_TITLE]; - } +// if ($vars[NAME_GLYPH_TITLE] !== '') { +// $anchorTitle = $vars[NAME_GLYPH_TITLE]; +// } } - $tags .= Support::doAttribute('href', $vars[NAME_URL]); - $tags .= Support::doAttribute('class', $vars[NAME_LINK_CLASS]); - $tags .= Support::doAttribute('target', $vars[NAME_TARGET]); - $tags .= Support::doAttribute('title', $anchorTitle); + $attributes .= Support::doAttribute('href', $vars[NAME_URL]); + $attributes .= Support::doAttribute('class', $vars[NAME_LINK_CLASS]); + $attributes .= Support::doAttribute('target', $vars[NAME_TARGET]); +// $attributes .= Support::doAttribute('title', $anchorTitle); + $attributes .= Support::doAttribute('title', $vars[NAME_TOOL_TIP]); + if ($vars[NAME_QUESTION]) { - $tags .= Support::doAttribute('onclick', 'confirm(\'' . $vars[NAME_QUESTION] . '\')'); + $attributes .= Support::doAttribute('onclick', 'confirm(\'' . $vars[NAME_QUESTION] . '\')'); } - $htmlUrl = '<a ' . $tags . $vars[NAME_TOOL_TIP][0] . '>'; +// $anchor = '<a ' . $attributes . $vars[NAME_TOOL_TIP_JS][0] . '>'; + $anchor = '<a ' . $attributes . '>'; - return ($htmlUrl); + return ($anchor); } // @@ -569,6 +590,34 @@ class Link { // <img src="typo3conf/ext/qfq/Resources/Public/icons/edit.gif" title="Edit" > //</a> + /** + * Create a ToolTip: $toolTip[0] and $toolTip[1] have to inserted in HTML code accordingly. + * $vars[NAME_TOOL_TIP_JS][0]: JS to show '$toolTip[1]'. + * $vars[NAME_TOOL_TIP_JS][1]: '<span>...</span>' with the tooltip text. + * + * @param $vars + * @param $key + * @param $value + */ + private function buildToolTip(&$vars, $key, $value) { + static $count = 0; + + $toolTipIndex = 'tooltip.' . $GLOBALS["TSFE"]->currentRecord . '.' . ++$count; + $vars[NAME_TOOL_TIP_JS] = array(); + + // Expample: <img src="fileadmin/icons/bullet-gray.gif" onmouseover="document.getElementById('gm167979').style. + // display='block';" onmouseout="document.getElementById('gm167979').style.display='none';" /> + $vars[NAME_TOOL_TIP_JS][0] = " onmouseover=\"document.getElementById('" . $toolTipIndex . + "').style.display='block';\" onmouseout=\"document.getElementById('" . $toolTipIndex . "').style.display='none';\""; + + // Example: <span id="gm167979" style="display:none; position:absolute; border:solid 1px black; background-color:#F9F3D0; + // padding:3px;">My pesonal tooltip</span> + $vars[NAME_TOOL_TIP_JS][1] = '<span id="' . $toolTipIndex . + '" style="display:none; position:absolute; border:solid 1px black; background-color:#F9F3D0; padding:3px;">' . + $value . '</span>'; + + return; + } /** * Create Image HTML Tag @@ -629,7 +678,7 @@ class Link { // Compose $dw (documentwrite statement) $dw .= ' + mm' . $ii++; } - $dw .= ' + "' . $vars[NAME_LINK_CLASS] . str_replace('"', '\\"', $vars[NAME_TOOL_TIP][0]) . '>"'; + $dw .= ' + "' . $vars[NAME_LINK_CLASS] . str_replace('"', '\\"', $vars[NAME_TOOL_TIP_JS][0]) . '>"'; $closeDw = '"</a>")'; } else { $dw = 'document.write('; @@ -649,7 +698,7 @@ class Link { } $tt .= '//--></script>'; - if ($href) $tt .= $vars[NAME_TOOL_TIP][1]; + if ($href) $tt .= $vars[NAME_TOOL_TIP_JS][1]; return ($tt); } @@ -699,6 +748,7 @@ class Link { */ private function buildMail(&$vars, $key, $value) { $vars[NAME_LINK_CLASS_DEFAULT] = $this->cssLinkClassExternal; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } /** @@ -733,6 +783,7 @@ class Link { private function buildPicture(&$vars, $key, $value) { $vars[NAME_ALT_TEXT] = "Grafic: " . $value; $vars[NAME_IMAGE_TITLE] = $value; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } /** @@ -745,6 +796,7 @@ class Link { private function buildBullet(&$vars, $key, $value) { $vars[NAME_IMAGE] = PATH_ICONS . "bullet-" . $value . '.gif'; $vars[NAME_IMAGE_TITLE] = $value; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } /** @@ -757,6 +809,7 @@ class Link { private function buildCheck(&$vars, $key, $value) { $vars[NAME_IMAGE] = PATH_ICONS . "checked-" . $value . '.gif'; $vars[NAME_IMAGE_TITLE] = $value; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } /** @@ -773,6 +826,7 @@ class Link { $vars[NAME_GLYPH] = GLYPH_ICON_DELETE; $vars[NAME_GLYPH_TITLE] = "Delete"; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; // Include Extjs library $this->utils->loadJSlib($this->fr_error); @@ -790,9 +844,9 @@ class Link { // $vars[NAME_IMAGE_TITLE] = "Edit"; $vars[NAME_GLYPH] = GLYPH_ICON_EDIT; $vars[NAME_GLYPH_TITLE] = "Edit"; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } - /** * Called by $this->callTable * @@ -805,6 +859,8 @@ class Link { // $vars[NAME_IMAGE_TITLE] = "Help"; $vars[NAME_GLYPH] = GLYPH_ICON_HELP; $vars[NAME_GLYPH_TITLE] = "Help"; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; + } /** @@ -820,6 +876,7 @@ class Link { $vars[NAME_GLYPH] = GLYPH_ICON_INFO; $vars[NAME_GLYPH_TITLE] = "Information"; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } @@ -836,6 +893,7 @@ class Link { $vars[NAME_GLYPH] = GLYPH_ICON_NEW; $vars[NAME_GLYPH_TITLE] = "New"; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } @@ -852,6 +910,8 @@ class Link { $vars[NAME_GLYPH] = GLYPH_ICON_SHOW; $vars[NAME_GLYPH_TITLE] = "Details"; + $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS; } + } \ No newline at end of file diff --git a/extension/qfq/qfq/report/Report.php b/extension/qfq/qfq/report/Report.php index 62f3f5fc7495a837fa1ee9261433dbf8508f14fb..34b802584c8a3b62c5eccd8cdc25a7630b758e6f 100644 --- a/extension/qfq/qfq/report/Report.php +++ b/extension/qfq/qfq/report/Report.php @@ -20,6 +20,7 @@ require_once(__DIR__ . '/../Database.php'); require_once(__DIR__ . '/Link.php'); require_once(__DIR__ . '/Sendmail.php'); require_once(__DIR__ . '/../exceptions/UserReportExtension.php'); +require_once(__DIR__ . '/../Evaluate.php'); class Report { @@ -89,7 +90,7 @@ class Report { * * @param array $t3data */ - public function __construct(array $t3data, $sessionName, $phpUnit = false) { + public function __construct(array $t3data, $sessionName, Evaluate $eval, $phpUnit = false) { $this->phpUnit = $phpUnit; @@ -114,7 +115,7 @@ class Report { $this->db = new Database(); $this->utils = new Utils(); - $this->variables = new Variables($t3data["uid"]); + $this->variables = new Variables($eval, $t3data["uid"]); // Set static values, which won't change during this run. $this->fr_error["pid"] = isset($this->variables->resultArray['global.']['page_id']) ? $this->variables->resultArray['global.']['page_id'] : 0; @@ -123,8 +124,7 @@ class Report { // Sanitize function for POST and GET Parameters. // Merged URL-Parameter (key1, id etc...) in resultArray. - $this->variables->resultArray = array_merge($this->variables->resultArray, array("url." => $this->utils->sanitize()), - array("global." => $this->variables->collectGlobalVariables())); + $this->variables->resultArray = array_merge($this->variables->resultArray, array("global." => $this->variables->collectGlobalVariables())); // Create Logclass. $this->log = new Log($this->variables->resultArray['global.']); @@ -878,27 +878,6 @@ class Report { return ($columnValue); } - /** - * Prepare Session Array with Hash Entry: Only for form - * - * @param $formName - * @param $formRecordId - * @return string - */ - private function form2hash($formName, $formRecordId) { - $hash = $this->utils->randomAlphaNumUnique(); - - $_SESSION[FORMREPORT][$hash]['formName'][0] = $formName; - $_SESSION[FORMREPORT][$hash]['referrer'] = $_SERVER['REQUEST_URI']; - - if (is_numeric($formRecordId) && $formRecordId >= 0) { - $_SESSION[FORMREPORT][$hash]['idMap'][1]['recordId'] = $formRecordId; - $_SESSION[FORMREPORT][$hash]['idMap'][1]['param'] = ""; - } - - return ($hash); - } - /** * Generate SortArgument * diff --git a/extension/qfq/qfq/report/Utils.php b/extension/qfq/qfq/report/Utils.php index 65ff353d3de4ff1baf31a0d29c91222cfd355f49..e2fe65e05d55111eae03c436d6bb7741ba28b976 100644 --- a/extension/qfq/qfq/report/Utils.php +++ b/extension/qfq/qfq/report/Utils.php @@ -29,174 +29,6 @@ class Utils { $this->db = null; } - /** - * Sanitize GET and POST Parameters. Categorize Parameter: name begins with: - * 'S_' String: sanitize via t3lib_db::quoteStr, htmltospecialchars - * 'H_' HTML: no sanitize at all - * [Typo3, xdebug, zend debugger] special - no change - * [rest] has to be numeric - if not, will not be copied. - * - * @return Array of sanitized GET and POST Variables. Only correctly filled variables will be returned. - */ - public function sanitize() { - $arr = array(); - // Merge GET and POST arrays. GET will be preferred. - $params = array_merge($_POST, $_GET); - - foreach ($params as $key => $value) { - - // if $value is an array (e.g. when using checkboxes on a 'set' field), convert it to a csv list. - if (is_array($value)) { - $value = implode(",", $value); - } - - switch (substr($key, 0, 2)) { - //alphanum - // String values. HTML entitites will be converted, strings escaped. - case "S_": -// $arr[$key] = mysql_real_escape_string(htmlspecialchars($value)); -// TA: htmlspecialchars darf hier nicht angewendet werden - Daten sollen so in DB geschrieben werden wie sie angegeben werden - $arr[$key] = mysql_real_escape_string($value); - break; - //default (F_ kommt vom ursprünglichen namen form) - //Tags werden bis auf die Whitelist LIST_MARKUP_TAGS (siehe define) ersetzt - case "F_": - $arr[$key] = addslashes(strip_tags($value, LIST_MARKUP_TAGS)); - break; - //email - //ExtJs definition (unterstützt nicht alle erlaubten Emailadressen) - case "E_": - $pattern = "/^((\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6})?$/"; - if (preg_match($pattern, $value) > 0) { - $arr[$key] = $value; - } - break; - //url - //Protokoll http / https muss angegeben werden. Definition ExtJs - case "U_": - $pattern = "/((((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?))?$/i"; - if (preg_match($pattern, $value) > 0) { - $arr[$key] = $value; - } - break; - //html - // HTML allowed: no sanitize at all. - case "H_": - $arr[$key] = addslashes($value); - break; - //date - //DD.MM.YYYY or DD/MM/YYYY - case "D_": -// $pattern = "/^\d\d[(.|\/)]\d\d[(.|\/)]\d\d\d\d$/"; -// if(preg_match($pattern, $value)>0){ -// $arr[$key] = $value; -// } - - // use strtotime instead of a complex regex: - // - the function accepts different formats of times / dates (e.g. speaking names) - this is extremely powerful - // - the date is automatically converted to a defined format, which makes it easier to process in later steps - if (strtotime($value)) { - $arr[$key] = date("Y-m-d", strtotime($value)); - } - break; - //time - //hh:mm:ss - case "T_": - //$pattern = "/^(((0|1)\d|2[0-4])[:]([0-6]\d)[:]([0-6]\d))?$/"; // CR: restriction to 00-23 is to strong -// $pattern = "/^\d?\d[:]\d?\d[:]?\d?\d?$/"; -// if(preg_match($pattern, $value)>0){ -// $arr[$key] = $value; -// } - - // use strtotime instead of a complex regex: - // - the function accepts different formats of times / dates (e.g. speaking names) - this is extremely powerful - // - the date is automatically converted to a defined format, which makes it easier to process in later steps - if (strtotime($value)) { - $arr[$key] = date("h:i:s", strtotime($value)); - } - break; - //date_time - //DD.MM.YYYY hh:mm:ss - case "Z_": - //$pattern = "/^((0[1-9]|[12][0-9]|3[01])[.](0[1-9]|1[012])[.](19|20)\d\d[ ]((0|1)\d|2[0-4])[:]([0-6]\d)[:]([0-6]\d))?$/"; -// $pattern = "/^(\d*\d[.]\d*\d[.]\d*\d*\d*\d[ ]\d?\d[:]\d?\d[:]?\d?\d?$/"; -// if(preg_match($pattern, $value)>0){ -// $arr[$key] = $value; -// } - - // use strtotime instead of a complex regex: - // - the function accepts different formats of times / dates (e.g. speaking names) - this is extremely powerful - // - the date is automatically converted to a defined format, which makes it easier to process in later steps - if (strtotime($value)) { - $arr[$key] = date("Y-m-d h:i:s", strtotime($value)); - } - - break; - case "N_": - //num - //Only numeric-value allowed - $pattern = "/^-?[0-9]*$/"; - if (preg_match($pattern, $value) > 0) { - $arr[$key] = $value; - } - break; - default: - /* 'id' (T3 page identifier) and ZEND 'debugger' GET_VARS won't be sanitized*/ - ; - switch ($key) { - case 'id': - case 'start_debug': - case 'debug_host': - case 'send_sess_end': - case 'debug_session_id': - case 'original_url': - case 'debug_start_session': - case 'debug_no_cache': - case 'debug_port': - $arr[$key] = $value; - continue 2; - } - break; - } - } - return ($arr); - } // sanitize() - - /** - * Create a new _unique_ (max 20 tries, else breaks) hash string and saves it in $_SESSION[FORMREPORT][$hash] - * - * @return string A random alphanumeric hash, or - * false if it was not possible to create a unique hash. - */ - public function randomAlphaNumUnique() { - - for ($i = 0; $i < 20; $i++) { - - $hash = $this->randomAlphaNum(LENGTH_HASH); - - if (!isset($_SESSION[FORMREPORT][$hash])) { - $_SESSION[FORMREPORT][$hash] = array(); - return ($hash); - } - } - // Too much tries without success - return (false); - } // randomAlphaNum () - - /** - * @param int $length Length of the required hash string - * @return string A random alphanumeric hash - */ - private function randomAlphaNum($length) { - $possible_characters = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - $string = ""; - while (strlen($string) < $length) { - $string .= substr($possible_characters, rand() % (strlen($possible_characters)), 1); - } - - return ($string); - } // randomAlphaNumUnique() - /** * If record locking has been enabled in ext_localconf.php, create a record in the lock table * @@ -213,8 +45,7 @@ class Utils { $query = "INSERT INTO `" . FR_LOCK . "` (`phpsession_id`, `fe_user_uid`, `form`, `record_id`, `tablename`, `dbalias`) VALUES ('" . session_id() . "', '" . $GLOBALS["TSFE"]->fe_user->user["uid"] . "', '" . $form . "', '" . $record_id . "', '" . $tablename . "', '" . $dbalias . "')"; $this->db->doQuery(DB, $query, $result, ROW_EXPECT_0); } // if - } // eo setLockRecord - + } // randomAlphaNumUnique() /** * If record locking has been enabled in ext_localconf.php, @@ -275,19 +106,19 @@ class Utils { $this->db->doQuery(T3, $query, $result, ROW_EXPECT_1); $username = ($result['username']) ?: "anonymous"; return $username; - } + } // eo setLockRecord /** * Create a unique directory in $path * - * @param string $path path - * @return string path/uniqedir - * @throws codeException + * @param $path + * @return string + * @throws CodeReportException */ function createUniqueDir($path) { // Try max. 20 times for ($i = 0; $i < 20; $i++) { - $dirname = $this->randomAlphaNum(5); + $dirname = Support::randomAlphaNum(5); $dirpath = $path . "/" . $dirname; if (!file_exists($dirpath)) { @@ -297,28 +128,5 @@ class Utils { } // Too many tries without success throw new CodeReportException ("Could not create unique directory.", __FILE__, __LINE__); - } // eo createUniqueDir - - /** - * Create a ToolTip: $toolTip[0] and $toolTip[1] have to inserted in HTML code accordingly. - * - * @param string $note Text to be shown in the tooltip - * @return array $toolTip $toolTip[0]: JS to show '$toolTip[1]'. - * $toolTip[1]: '<span>...</span>' with the tooltip text. - */ - public function createToolTip($note) { - static $count = 0; - - $toolTipIndex = 'tooltip.' . $GLOBALS["TSFE"]->currentRecord . '.' . ++$count; - $toolTip = array(); - - // Expample: <img src="fileadmin/icons/bullet-gray.gif" onmouseover="document.getElementById('gm167979').style.display='block';" onmouseout="document.getElementById('gm167979').style.display='none';" /> - $toolTip[0] = " onmouseover=\"document.getElementById('" . $toolTipIndex . "').style.display='block';\" onmouseout=\"document.getElementById('" . $toolTipIndex . "').style.display='none';\""; - - // Example: <span id="gm167979" style="display:none; position:absolute; border:solid 1px black; background-color:#F9F3D0; padding:3px;">My pesonal tooltip</span> - $toolTip[1] = '<span id="' . $toolTipIndex . '" style="display:none; position:absolute; border:solid 1px black; background-color:#F9F3D0; padding:3px;">' . $note . '</span>'; - - return ($toolTip); - } // createToolTip() - + } } diff --git a/extension/qfq/qfq/report/Variables.php b/extension/qfq/qfq/report/Variables.php index 3819460a305b5f48c5393da7156a062068178fc7..839417039520e5d2960a75e08179aeb78e475dc1 100644 --- a/extension/qfq/qfq/report/Variables.php +++ b/extension/qfq/qfq/report/Variables.php @@ -24,6 +24,8 @@ namespace qfq; +require_once(__DIR__ . '/../Evaluate.php'); + //use qfq; class Variables { @@ -32,11 +34,17 @@ class Variables { // TODO to explain private $tt_content_uid = 0; + /** + * @var Evaluate + */ + private $eval; /** * @param int $tmp_ttcontent_uid */ - public function __construct($tt_content_uid = 0) { + public function __construct(Evaluate $eval, $tt_content_uid = 0) { + + $this->eval = $eval; // specified once during initialisation. $this->tt_content_uid = $tt_content_uid; @@ -51,7 +59,7 @@ class Variables { */ public function doVariables($text) { // $str = preg_replace_callback("/(~([a-zA-Z0-9._])*)/", array($this, 'replaceVariables'), $text); - $str = preg_replace_callback("/{{(([a-zA-Z0-9._])*)}}/", array($this, 'replaceVariables'), $text); + $str = preg_replace_callback("/{{(([a-zA-Z0-9.:_])*)}}/", array($this, 'replaceVariables'), $text); return $str; } @@ -72,12 +80,21 @@ class Variables { // index of last '.' $pos = strrpos($matches[1], "."); + if ($pos !== false) { + $fullLevel = substr($matches[1], 0, $pos + 1); + $varName = substr($matches[1], $pos + 1, strlen($matches[1])); - $fullLevel = substr($matches[1], 0, $pos + 1); - $varName = substr($matches[1], $pos + 1, strlen($matches[1])); + if (isset($this->resultArray[$fullLevel][$varName])) { + $data = $this->resultArray[$fullLevel][$varName]; + } + } - if (isset($this->resultArray[$fullLevel][$varName])) - $data = $this->resultArray[$fullLevel][$varName]; + // If not replaced, try the Stores + if ($data === $matches[0]) { + $dataTmp = $this->eval->parse($data); + if ($dataTmp !== false) + $data = $dataTmp; + } return $data; } diff --git a/extension/qfq/qfq/store/Sip.php b/extension/qfq/qfq/store/Sip.php index a747f2ac2db0a6f12793151a32de862d844a2e5f..29c15889a84ec83b2d398ad612b8f9239a51b825 100644 --- a/extension/qfq/qfq/store/Sip.php +++ b/extension/qfq/qfq/store/Sip.php @@ -64,9 +64,10 @@ class Sip { * * a=1&s=4b3403665fea6&r=45&type=99&id=person * * @param string $mode Possible values: RETURN_URL|RETURN_SIP - * @return string + * @return string/array * * mode=RETURN_URL: return complete URL * * mode=RETURN_SIP: returns only the sip + * * mode=RETURN_ARRAY: returns array with url ('_url') and all decoded and created parameters. * @throws CodeException * @throws UserFormException */ @@ -103,17 +104,29 @@ class Sip { $_SESSION[$s] = $sipParamString; } - if ($mode == RETURN_URL) { - // Append SIP to final parameter - $clientArray[CLIENT_SIP] = $s; - - if ($script[0] === '?') - $script = $scriptName . $script; - - return $script . OnArray::toString($clientArray); - } else { - return $s; + // Append SIP to final parameter + $clientArray[CLIENT_SIP] = $s; + + if ($script[0] === '?') + $script = $scriptName . $script; + + $clientArray['_url'] = $script . OnArray::toString($clientArray); + + switch ($mode) { + case RETURN_URL: + $rc = $clientArray['_url']; + break; + case RETURN_SIP: + $rc = $s; + break; + case RETURN_ARRAY: + $rc = array_merge($clientArray, $sipArray); + break; + default: + throw new CodeException('Unknown Mode: "' . $mode . '"', ERROR_UNKNOWN_MODE); } + + return $rc; } /** diff --git a/extension/qfq/qfq/store/Store.php b/extension/qfq/qfq/store/Store.php index f4fc7e2cd4b1277f6a0757dee384abe22360ac3a..648377e33e5210b0126c7083ec7499603b2638b5 100644 --- a/extension/qfq/qfq/store/Store.php +++ b/extension/qfq/qfq/store/Store.php @@ -246,6 +246,9 @@ class Store { if (isset($GLOBALS["TSFE"]->type)) $arr[TYPO3_PAGE_TYPE] = $GLOBALS["TSFE"]->type; + if (isset($GLOBALS["TSFE"]->sys_language_uid)) + $arr[TYPO3_PAGE_LANGUAGE] = $GLOBALS["TSFE"]->sys_language_uid; + self::setVarArray($arr, STORE_TYPO3, true); } @@ -254,7 +257,15 @@ class Store { */ private function fillStoreClient() { // copy GET and POST and SERVER Parameter. Priority: SERVER, POST, GET - $arr = array_merge($_GET, $_POST, $_SERVER); + $arr = array(); + if (isset($_GET)) + $arr = array_merge($arr, $_GET); + + if (isset($_POST)) + $arr = array_merge($arr, $_POST); + + if (isset($_SERVER)) + $arr = array_merge($arr, $_SERVER); self::setVarArray($arr, STORE_CLIENT, true); } @@ -311,16 +322,26 @@ class Store { $useStores = substr($useStores, 1); // shift left remaining stores if (!isset(self::$raw[$store][$key])) { - if ($store === STORE_ZERO) { - return 0; - } else { - continue; // no value provided + switch ($store) { + case STORE_ZERO: + return 0; + case STORE_EMPTY: + return ''; + case STORE_VAR: + if ($key === VAR_RANDOM) { + return Support::randomAlphaNum(RANDOM_LENGTH); + } else { + continue 2; // no value provided, continue with while loop + } + break; + default: + continue 2; // no value provided, continue with while loop + break; } } $rawVal = isset(self::$raw[$store][$key]) ? self::$raw[$store][$key] : null; if (self::$sanitizeStore[$store] && $sanitizeClass != '') { -// return \qfq\Sanitize::sanitize($rawVal, $sanitizeClass); if ($sanitizeClass == SANITIZE_ALLOW_PATTERN || $sanitizeClass == SANITIZE_ALLOW_MIN_MAX || $sanitizeClass == SANITIZE_ALLOW_MIN_MAX_DATE) { // We do not have any pattern or min|max values at this point. For those who be affected, they already checked earlier. So set 'no check' $sanitizeClass = SANITIZE_ALLOW_ALL; @@ -363,12 +384,20 @@ class Store { self::fillStoreTypo3($bodytext); } + // Disable TYPO3_DEBUG_SHOW_BODY_TEXT=1 if SYSTEM_SHOW_DEBUG_INFO!='yes' + if (self::getVar(TYPO3_DEBUG_SHOW_BODY_TEXT, STORE_TYPO3) === '1' && + self::getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM) !== 'yes' + ) { + self::setVar(TYPO3_DEBUG_SHOW_BODY_TEXT, '0', STORE_TYPO3); + } + return self::$instance; } - /** * @param $store + * @throws UserFormException + * @throws \qfq\CodeException */ public static function unsetStore($store) { // Check valid Storename @@ -384,12 +413,34 @@ class Store { } + /** + * @param $key + * @param $value + * @param $store + * @param bool|true $overWrite + * @throws UserFormException + * @throws \qfq\CodeException + */ + public static function setVar($key, $value, $store, $overWrite = true) { + // Check valid Storename + if (!isset(self::$sanitizeStore)) + throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE); + + if ($store === STORE_ZERO) + throw new CodeException("setVar() for STORE_ZERO is impossible - there are no values.", ERROR_SET_STORE_ZERO); + + if ($overWrite === false && isset(self::$raw[$store][$key])) { + throw new UserFormException("Value of '$key' already be set in store '$store'.", ERROR_STORE_KEY_EXIST); + } + + self::$raw[$store][$key] = $value; + } + /** * @param $formName * @throws CodeException */ - public - static function createSipAfterFormLoad($formName) { + public static function createSipAfterFormLoad($formName) { $recordId = self::getVar(CLIENT_RECORD_ID, STORE_TYPO3 . STORE_CLIENT); if ($recordId === false) { $recordId = 0; @@ -418,30 +469,10 @@ class Store { } /** - * @param $key - * @param $value * @param $store - * @param bool|true $overWrite + * @return array * @throws UserFormException - */ - public static function setVar($key, $value, $store, $overWrite = true) { - // Check valid Storename - if (!isset(self::$sanitizeStore)) - throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE); - - if ($store === STORE_ZERO) - throw new CodeException("setVar() for STORE_ZERO is impossible - there are no values.", ERROR_SET_STORE_ZERO); - - if ($overWrite === false && isset(self::$raw[$store][$key])) { - throw new UserFormException("Value of '$key' already be set in store '$store'.", ERROR_STORE_KEY_EXIST); - } - - self::$raw[$store][$key] = $value; - } - - /** - * @param $store - * @return mixed + * @throws \qfq\CodeException */ public static function getStore($store) { // Check valid Storename diff --git a/extension/qfq/sql/formEditor.sql b/extension/qfq/sql/formEditor.sql index 32285d41f87fde6bda9fc0e638ed366abd387564..37bffb79f4b2ba1b52b8acb912d9a18156f0e587 100644 --- a/extension/qfq/sql/formEditor.sql +++ b/extension/qfq/sql/formEditor.sql @@ -10,7 +10,7 @@ CREATE TABLE IF NOT EXISTS `Form` ( `permitNew` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip', `permitEdit` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip', `render` ENUM('plain', 'table', 'bootstrap') NOT NULL DEFAULT 'plain', - `showButton` SET('new', 'delete') NOT NULL DEFAULT 'new,delete', + `showButton` SET('new', 'delete', 'close', 'save') NOT NULL DEFAULT 'new,delete,close,save', `multiMode` ENUM('none', 'horizontal', 'vertical') NOT NULL DEFAULT 'none', `multiSql` TEXT NOT NULL, `multiDetailForm` VARCHAR(255) NOT NULL DEFAULT '', @@ -120,7 +120,7 @@ CREATE TABLE IF NOT EXISTS `FormElement` ( # FormEditor: Form INSERT INTO Form (name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter) VALUES ('form', 'Form Editor: {{SELECT id, " / ", name FROM Form WHERE id = {{r:S0}}}}', 'Please secure the form', - 'Form', 'always', 'always', 'bootstrap', '', 'maxVisiblePill=3\nclass=container-fluid'); + 'Form', 'always', 'always', 'bootstrap', '', 'maxVisiblePill=5\nclass=container-fluid'); # FormEditor: FormElements INSERT INTO FormElement (formId, name, label, mode, type, checkType, class, ord, size, maxLength, note, clientJs, value, sql1, sql2, parameter, feIdContainer, subrecordOption) diff --git a/extension/qfq/tests/phpunit/LinkTest.php b/extension/qfq/tests/phpunit/LinkTest.php index e2c7dce6135c779f0fc000c2ee9ee5cee0f43ced..0443314ca8e8495c4109687c423ef92ee60edb5e 100644 --- a/extension/qfq/tests/phpunit/LinkTest.php +++ b/extension/qfq/tests/phpunit/LinkTest.php @@ -25,7 +25,6 @@ class LinkTest extends \PHPUnit_Framework_TestCase { */ private $store = null; - /** * @throws SyntaxReportException */ @@ -89,10 +88,10 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $link = new Link(null, $this->sip, true); $result = $link->renderLink('m:john@doe.com'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >mailto:john@doe.com</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >mailto:john@doe.com</a>', $result); $result = $link->renderLink('m:john@doe.com|t:John Doe'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >John Doe</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >John Doe</a>', $result); } /** @@ -152,7 +151,8 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('<a href="http://example.com" class="external" >http://example.com</a>', $result); $result = $link->renderLink('t:Example|r:1'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:1'); $this->assertEquals('<a href="http://example.com" class="external" >Example</a>', $result); @@ -175,26 +175,32 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('', $result); $result = $link->renderLink('u:http://example.com|r:3'); - $this->assertEquals('<span >http://example.com</span>', $result); +// $this->assertEquals('<span >http://example.com</span>', $result); + $this->assertEquals('http://example.com', $result); $result = $link->renderLink('t:Example|r:3'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:3'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); // r: 4 $result = $link->renderLink('u|r:4'); $this->assertEquals('', $result); $result = $link->renderLink('u:http://example.com|r:4'); - $this->assertEquals('<span >http://example.com</span>', $result); +// $this->assertEquals('<span >http://example.com</span>', $result); + $this->assertEquals('http://example.com', $result); $result = $link->renderLink('t:Example|r:4'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:4'); - $this->assertEquals('<span >http://example.com</span>', $result); +// $this->assertEquals('<span >http://example.com</span>', $result); + $this->assertEquals('http://example.com', $result); // r: 5 $result = $link->renderLink('u|r:5'); @@ -248,7 +254,8 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('<a href="?id=secondPage" class="internal" >?id=secondPage</a>', $result); $result = $link->renderLink('t:Example|r:1'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('p:secondPage|t:Example|r:1'); $this->assertEquals('<a href="?id=secondPage" class="internal" >Example</a>', $result); @@ -268,29 +275,37 @@ class LinkTest extends \PHPUnit_Framework_TestCase { // r: 3 $result = $link->renderLink('p|r:3'); - $this->assertEquals('<span >?id=firstPage</span>', $result); +// $this->assertEquals('<span >?id=firstPage</span>', $result); + $this->assertEquals('?id=firstPage', $result); $result = $link->renderLink('p:secondPage|r:3'); - $this->assertEquals('<span >?id=secondPage</span>', $result); +// $this->assertEquals('<span >?id=secondPage</span>', $result); + $this->assertEquals('?id=secondPage', $result); $result = $link->renderLink('t:Example|r:3'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('p:secondPage|t:Example|r:3'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); // r: 4 $result = $link->renderLink('p|r:4'); - $this->assertEquals('<span >?id=firstPage</span>', $result); +// $this->assertEquals('<span >?id=firstPage</span>', $result); + $this->assertEquals('?id=firstPage', $result); $result = $link->renderLink('p:secondPage|r:4'); - $this->assertEquals('<span >?id=secondPage</span>', $result); +// $this->assertEquals('<span >?id=secondPage</span>', $result); + $this->assertEquals('?id=secondPage', $result); $result = $link->renderLink('t:Example|r:4'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('p:secondPage|t:Example|r:4'); - $this->assertEquals('<span >?id=secondPage</span>', $result); +// $this->assertEquals('<span >?id=secondPage</span>', $result); + $this->assertEquals('?id=secondPage', $result); // r: 5 $result = $link->renderLink('p|r:5'); @@ -314,39 +329,40 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >mailto:john@doe.com</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >mailto:john@doe.com</a>', $result); $result = $link->renderLink('t:Example'); $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com|t:Example'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >Example</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >Example</a>', $result); // r: 0 $result = $link->renderLink('u|r:0'); $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com|r:0'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >mailto:john@doe.com</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >mailto:john@doe.com</a>', $result); $result = $link->renderLink('t:Example|r:0'); $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com|t:Example|r:0'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >Example</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >Example</a>', $result); // r: 1 $result = $link->renderLink('u|r:1'); $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com|r:1'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >mailto:john@doe.com</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >mailto:john@doe.com</a>', $result); $result = $link->renderLink('t:Example|r:1'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('m:john@doe.com|t:Example|r:1'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >Example</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >Example</a>', $result); // r: 2 $result = $link->renderLink('u|r:2'); @@ -359,33 +375,39 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com|t:Example|r:2'); - $this->assertEquals('<a href="mailto:john@doe.com" class="external" >Example</a>', $result); + $this->assertEquals('<a href="mailto:john@doe.com" >Example</a>', $result); // r: 3 $result = $link->renderLink('u|r:3'); $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com|r:3'); - $this->assertEquals('<span >mailto:john@doe.com</span>', $result); +// $this->assertEquals('<span >mailto:john@doe.com</span>', $result); + $this->assertEquals('mailto:john@doe.com', $result); $result = $link->renderLink('t:Example|r:3'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('m:john@doe.com|t:Example|r:3'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); // r: 4 $result = $link->renderLink('u|r:4'); $this->assertEquals('', $result); $result = $link->renderLink('m:john@doe.com|r:4'); - $this->assertEquals('<span >mailto:john@doe.com</span>', $result); +// $this->assertEquals('<span >mailto:john@doe.com</span>', $result); + $this->assertEquals('mailto:john@doe.com', $result); $result = $link->renderLink('t:Example|r:4'); - $this->assertEquals('<span >Example</span>', $result); +// $this->assertEquals('<span >Example</span>', $result); + $this->assertEquals('Example', $result); $result = $link->renderLink('m:john@doe.com|t:Example|r:4'); - $this->assertEquals('<span >mailto:john@doe.com</span>', $result); +// $this->assertEquals('<span >mailto:john@doe.com</span>', $result); + $this->assertEquals('mailto:john@doe.com', $result); // r: 5 $result = $link->renderLink('u|r:5'); @@ -409,39 +431,41 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('', $result); $result = $link->renderLink('u:http://example.com|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); $result = $link->renderLink('t:Example|P:picture.gif'); $this->assertEquals('', $result); $result = $link->renderLink('u:http://example.com|t:Example|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); // r: 0 $result = $link->renderLink('u|r:0|P:picture.gif'); $this->assertEquals('', $result); $result = $link->renderLink('u:http://example.com|r:0|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); $result = $link->renderLink('t:Example|r:0|P:picture.gif'); $this->assertEquals('', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:0|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); // r: 1 $result = $link->renderLink('u|r:1|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > ', $result); $result = $link->renderLink('u:http://example.com|r:1|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); $result = $link->renderLink('t:Example|r:1|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:1|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); // r: 2 $result = $link->renderLink('u|r:2|P:picture.gif'); @@ -449,39 +473,47 @@ class LinkTest extends \PHPUnit_Framework_TestCase { //TODO: no link if text is empty - image is linked here: this is not what the user expects. $result = $link->renderLink('u:http://example.com|r:2|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </a>', $result); $result = $link->renderLink('t:Example|r:2|P:picture.gif'); $this->assertEquals('', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:2|P:picture.gif'); - $this->assertEquals('<a href="http://example.com" class="external" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); + $this->assertEquals('<a href="http://example.com" ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</a>', $result); // r: 3: $result = $link->renderLink('u|r:3|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > ', $result); $result = $link->renderLink('u:http://example.com|r:3|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > ', $result); $result = $link->renderLink('t:Example|r:3|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:3|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example', $result); // r: 4 $result = $link->renderLink('u|r:4|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > </span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > ', $result); $result = $link->renderLink('u:http://example.com|r:4|P:picture.gif'); - $this->assertEquals('<span >http://example.com</span>', $result); +// $this->assertEquals('<span >http://example.com</span>', $result); + $this->assertEquals('http://example.com', $result); $result = $link->renderLink('t:Example|r:4|P:picture.gif'); - $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); +// $this->assertEquals('<span ><img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example</span>', $result); + $this->assertEquals('<img alt="Grafic: picture.gif" src="picture.gif" title="picture.gif" > Example', $result); $result = $link->renderLink('u:http://example.com|t:Example|r:4|P:picture.gif'); - $this->assertEquals('<span >http://example.com</span>', $result); +// $this->assertEquals('<span >http://example.com</span>', $result); + $this->assertEquals('http://example.com', $result); // r: 5 $result = $link->renderLink('u|r:5|P:picture.gif'); @@ -497,9 +529,6 @@ class LinkTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('', $result); } - - - public function testLinkClass() { } diff --git a/extension/qfq/tests/phpunit/SupportTest.php b/extension/qfq/tests/phpunit/SupportTest.php index 38cc0c9a2e62b5ed167b615c406ab2fe4418247d..91ba7777b5e312771c461c4e8169ca4224c6afd4 100644 --- a/extension/qfq/tests/phpunit/SupportTest.php +++ b/extension/qfq/tests/phpunit/SupportTest.php @@ -14,42 +14,38 @@ require_once(__DIR__ . '/../../qfq/Evaluate.php'); class FakeTSFE { public $id = 1; + public $type = 2; + public $sys_language_uid = 3; } class SupportTest extends \PHPUnit_Framework_TestCase { + + /** + * @var Store + */ + private $store = null; + public function testAppendTypo3ParameterToArray() { unset($_GET); - $GLOBALS["TSFE"] = new FakeTSFE(); $queryArray = array(); Support::appendTypo3ParameterToArray($queryArray); - $this->assertEquals(['id' => 1], $queryArray); + $this->assertEquals(['id' => 1, 'type' => 2, 'L' => 3], $queryArray); - $queryArray = ['id' => '1', 'a' => '100']; - $expected = $queryArray; + $queryArray = array(); + $this->store->setVar(TYPO3_PAGE_LANGUAGE, 0, STORE_TYPO3, true); Support::appendTypo3ParameterToArray($queryArray); - $this->assertEquals($expected, $queryArray); + $this->assertEquals(['id' => 1, 'type' => 2], $queryArray); - $_GET['L'] = 1; - $_GET['type'] = 100; - $queryArray = ['id' => '1', 'a' => '100']; - $expected = array_merge($_GET, $queryArray); - Support::appendTypo3ParameterToArray($queryArray); - $this->assertEquals($expected, $queryArray); - - unset($_GET); - $_GET['L'] = 1; - $queryArray = ['id' => '1', 'a' => '100']; - $expected = array_merge($_GET, $queryArray); + $queryArray = array(); + $this->store->setVar(TYPO3_PAGE_TYPE, 0, STORE_TYPO3, true); Support::appendTypo3ParameterToArray($queryArray); - $this->assertEquals($expected, $queryArray); + $this->assertEquals(['id' => 1], $queryArray); - unset($_GET); - $_GET['type'] = 1; - $queryArray = ['id' => '1', 'a' => '100']; - $expected = array_merge($_GET, $queryArray); + $queryArray = ['a' => '100']; + $expected = ['a' => '100', 'id' => 1]; Support::appendTypo3ParameterToArray($queryArray); $this->assertEquals($expected, $queryArray); @@ -75,7 +71,6 @@ class SupportTest extends \PHPUnit_Framework_TestCase { $actual = Support::arrayToQueryString(['id' => '55', 'name' => 'He<b>inz']); $expected = ''; $this->assertEquals('id=55&name=He%3Cb%3Einz', $actual); - } public function testWrapTag() { @@ -104,7 +99,6 @@ class SupportTest extends \PHPUnit_Framework_TestCase { $result = Support::wrapTag("<p>", 'Hello World', false); $this->assertEquals('<p>Hello World</p>', $result); - } public function testDateTime2mysql() { @@ -127,6 +121,56 @@ class SupportTest extends \PHPUnit_Framework_TestCase { // date time $this->assertEquals('2069-02-01 01:02:00', Support::dateTime2mysql('1.2.69 1:2')); $this->assertEquals('2016-12-31 23:48:59', Support::dateTime2mysql('31.12.2016 23:48:59')); + } + public function testEncryptDoubleCurlyBraces() { + + $arr = [ + ['', ''], + ['1', '1'], + ["1\n2", "1\n2"], + ['{', '{'], + ['#&@[[@_#', '{{'], + ['-\{-', '-\{-'], + ['#&@[[@_##&@]]@_#-#&@[[@_##&@]]@_#', '{{}}-{{}}'], + ['#&@[[@_#hello#&@[[@_#world#&@]]@_##&@]]@_#', '{{hello{{world}}}}'], + ["\n\n##&@[[@_#\n#&@]]@_#", "\n\n#{{\n}}"], + ]; + + foreach ($arr as $tuple) { + $this->assertEquals($tuple[0], Support::encryptDoubleCurlyBraces($tuple[1])); + $this->assertEquals($tuple[1], Support::decryptDoubleCurlyBraces($tuple[0])); + } } + + public function testConcatUrlParam() { + $url = Support::concatUrlParam('', ''); + $this->assertEquals('', $url); + + $url = Support::concatUrlParam('http://example.com', ''); + $this->assertEquals('http://example.com', $url); + + $url = Support::concatUrlParam('', 'a=1'); + $this->assertEquals('?a=1', $url); + + $url = Support::concatUrlParam('http://example.com', 'a=100'); + $this->assertEquals('http://example.com?a=100', $url); + + $url = Support::concatUrlParam('http://example.com?id=2', 'a=100'); + $this->assertEquals('http://example.com?id=2&a=100', $url); + + $url = Support::concatUrlParam('http://example.com', 'a=100&b=201'); + $this->assertEquals('http://example.com?a=100&b=201', $url); + + $url = Support::concatUrlParam('http://example.com?id=34', 'a=100&b=201'); + $this->assertEquals('http://example.com?id=34&a=100&b=201', $url); + } + + protected function setUp() { + parent::setUp(); + + $GLOBALS["TSFE"] = new FakeTSFE(); + $this->store = Store::getInstance('', true); + } + }