- Configured trunk for the 3.9.0alpha1 subrelease.
[tinyz:tinyz.git] / kernel / classes / datatypes / ezmatrix / ezmatrixtype.php
1 <?php
2 //
3 // Definition of eZMatrixType class
4 //
5 // Created on: <30-May-2003 14:18:35 sp>
6 //
7 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
8 // SOFTWARE NAME: eZ publish
9 // SOFTWARE RELEASE: 3.9.x
10 // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS
11 // SOFTWARE LICENSE: GNU General Public License v2.0
12 // NOTICE: >
13 //   This program is free software; you can redistribute it and/or
14 //   modify it under the terms of version 2.0  of the GNU General
15 //   Public License as published by the Free Software Foundation.
16 // 
17 //   This program is distributed in the hope that it will be useful,
18 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 //   GNU General Public License for more details.
21 // 
22 //   You should have received a copy of version 2.0 of the GNU General
23 //   Public License along with this program; if not, write to the Free
24 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 //   MA 02110-1301, USA.
26 // 
27 // 
28 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
29 //
30
31 /*! \file ezmatrixtype.php
32 */
33
34 /*!
35   \class eZMatrixType ezmatrixtype.php
36   \ingroup eZDatatype
37   \brief The class eZMatrixType does
38
39 */
40
41 include_once( 'kernel/classes/ezdatatype.php' );
42 include_once( 'kernel/classes/datatypes/ezmatrix/ezmatrix.php' );
43 include_once( 'kernel/classes/datatypes/ezmatrix/ezmatrixdefinition.php' );
44 include_once( 'lib/ezutils/classes/ezstringutils.php' );
45
46 define( 'EZ_MATRIX_DEFAULT_NAME_VARIABLE', '_ezmatrix_default_name_' );
47
48 define( 'EZ_MATRIX_NUMCOLUMNS_VARIABLE', '_ezmatrix_default_num_columns_' );
49 define( 'EZ_MATRIX_NUMROWS_VARIABLE', '_ezmatrix_default_num_rows_' );
50 define( 'EZ_MATRIX_CELL_VARIABLE', '_ezmatrix_cell_' );
51 define( 'EZ_DATATYPESTRING_MATRIX', 'ezmatrix' );
52
53 class eZMatrixType extends eZDataType
54 {
55     /*!
56      Constructor
57     */
58     function eZMatrixType()
59     {
60         $this->eZDataType( EZ_DATATYPESTRING_MATRIX, ezi18n( 'kernel/classes/datatypes', 'Matrix', 'Datatype name' ),
61                            array( 'serialize_supported' => true ) );
62     }
63
64     /*!
65      Validates the input and returns true if the input was
66      valid for this datatype.
67     */
68     function validateObjectAttributeHTTPInput( &$http, $base, &$contentObjectAttribute )
69     {
70         $data = false;
71         if ( $http->hasPostVariable( $base . '_ezmatrix_cell_' . $contentObjectAttribute->attribute( 'id' ) ) )
72             $data = $http->PostVariable( $base . '_ezmatrix_cell_' . $contentObjectAttribute->attribute( 'id' ) );
73         $count = 0;
74         for ( $i = 0; $i < count( $data ); ++$i )
75              if ( trim( $data[$i] ) <> '' )
76              {
77                  ++$count;
78                  break;
79              }
80         if ( $contentObjectAttribute->validateIsRequired() and ( $count == 0 or $data === false ) )
81         {
82             $contentObjectAttribute->setValidationError( ezi18n( 'kernel/classes/datatypes',
83                                                                  'Missing matrix input.' ) );
84             return EZ_INPUT_VALIDATOR_STATE_INVALID;
85         }
86         return EZ_INPUT_VALIDATOR_STATE_ACCEPTED;
87     }
88
89     /*!
90      Store content
91     */
92     function storeObjectAttribute( &$contentObjectAttribute )
93     {
94         $matrix =& $contentObjectAttribute->content();
95         $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
96         $matrix->decodeXML( $contentObjectAttribute->attribute( 'data_text' ) );
97         $contentObjectAttribute->setContent( $matrix );
98     }
99
100     function storeClassAttribute( &$contentClassAttribute, $version )
101     {
102         $matrixDefinition =& $contentClassAttribute->content();
103         $contentClassAttribute->setAttribute( 'data_text5', $matrixDefinition->xmlString() );
104         $matrixDefinition->decodeClassAttribute( $contentClassAttribute->attribute( 'data_text5' ) );
105         $contentClassAttribute->setContent(  $matrixDefinition );
106     }
107
108     /*!
109      Returns the content.
110     */
111     function &objectAttributeContent( &$contentObjectAttribute )
112     {
113         $matrix = new eZMatrix( '' );
114
115         $matrix->decodeXML( $contentObjectAttribute->attribute( 'data_text' ) );
116
117         return $matrix;
118     }
119
120     function hasObjectAttributeContent( &$contentObjectAttribute )
121     {
122         $matrix =& $contentObjectAttribute->content();
123         $columnsArray =& $matrix->attribute( 'columns' );
124         $columns =& $columnsArray['sequential'];
125         $count = 0;
126         foreach ( $columns as $column )
127         {
128             $count += count( $column['rows'] );
129         }
130         return $count > 0;
131     }
132
133     /*!
134      Returns the meta data used for storing search indeces.
135     */
136     function metaData( $contentObjectAttribute )
137     {
138         $matrix =& $contentObjectAttribute->content();
139         $columnsArray =& $matrix->attribute( 'columns' );
140         $columns =& $columnsArray['sequential'];
141         $metaDataArray = array();
142         foreach ( $columns as $column )
143         {
144             $rows = $column['rows'];
145             foreach ( $rows as $row )
146             {
147                 $metaDataArray[] = array( 'id' => $column['identifier'],
148                                           'text' => $row );
149             }
150         }
151         return $metaDataArray;
152     }
153
154     /*!
155      Fetches the http post var matrix cells input and stores it in the data instance.
156     */
157     function fetchObjectAttributeHTTPInput( &$http, $base, &$contentObjectAttribute )
158     {
159         $cellsVarName = $base . EZ_MATRIX_CELL_VARIABLE . $contentObjectAttribute->attribute( 'id' );
160         if ( $http->hasPostVariable( $cellsVarName ) )
161         {
162             $cells = array();
163             foreach ( $http->postVariable( $cellsVarName ) as $cell )
164             {
165                 $cells[] = $cell;
166             }
167             $matrix =& $contentObjectAttribute->attribute( 'content' );
168             $matrix->Cells =& $cells;
169
170             $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
171             $matrix->decodeXML( $contentObjectAttribute->attribute( 'data_text' ) );
172             $contentObjectAttribute->setContent( $matrix );
173         }
174         return true;
175     }
176
177     /*!
178     */
179     function customObjectAttributeHTTPAction( $http, $action, &$contentObjectAttribute )
180     {
181         switch ( $action )
182         {
183             case 'new_row' :
184             {
185                 $matrix =& $contentObjectAttribute->content( );
186
187                 $postvarname = 'ContentObjectAttribute' . '_data_matrix_remove_' . $contentObjectAttribute->attribute( 'id' );
188                 $addCountName = 'ContentObjectAttribute' . '_data_matrix_add_count_' . $contentObjectAttribute->attribute( 'id' );
189
190                 $addCount = 1;
191                 if ( $http->hasPostVariable( $addCountName ) )
192                 {
193                     $addCount = $http->postVariable( $addCountName );
194                 }
195
196                 if ( $http->hasPostVariable( $postvarname ) )
197                 {
198                     $selected = $http->postVariable( $postvarname );
199                     $matrix->addRow( $selected[0], $addCount );
200                 }
201                 else
202                 {
203                     $matrix->addRow( false, $addCount );
204                 }
205
206                 $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
207                 $matrix->decodeXML( $contentObjectAttribute->attribute( 'data_text' ) );
208                 $contentObjectAttribute->setContent( $matrix );
209                 $contentObjectAttribute->store();
210             }break;
211             case 'remove_selected' :
212             {
213                 $matrix =& $contentObjectAttribute->content( );
214                 $postvarname = 'ContentObjectAttribute' . '_data_matrix_remove_' . $contentObjectAttribute->attribute( 'id' );
215                 $arrayRemove = $http->postVariable( $postvarname );
216
217                 rsort( $arrayRemove );
218                 foreach ( $arrayRemove as $rowNum)
219                 {
220                     $matrix->removeRow( $rowNum );
221                 }
222
223                 $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
224                 $matrix->decodeXML( $contentObjectAttribute->attribute( 'data_text' ) );
225                 $contentObjectAttribute->setContent( $matrix );
226                 $contentObjectAttribute->store();
227             }break;
228             default :
229             {
230                 eZDebug::writeError( 'Unknown custom HTTP action: ' . $action, 'eZMatrixType' );
231             }break;
232         }
233     }
234
235     /*!
236      Returns the integer value.
237     */
238     function title( &$contentObjectAttribute, $name = 'name' )
239     {
240         $matrix =& $contentObjectAttribute->content( );
241
242         $value = $matrix->attribute( $name );
243
244         return $value;
245     }
246
247     /*!
248      Sets the default value.
249     */
250     function initializeObjectAttribute( &$contentObjectAttribute, $currentVersion, &$originalContentObjectAttribute )
251     {
252
253         if ( $currentVersion != false )
254         {
255             $matrix =& $originalContentObjectAttribute->content();
256             $contentClassAttribute =& $contentObjectAttribute->contentClassAttribute();
257             // make sure that $matrix contains right columns
258             $matrix->adjustColumnsToDefinition( $contentClassAttribute->attribute( 'content' ) );
259
260             $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
261             $contentObjectAttribute->setContent( $matrix );
262         }
263         else
264         {
265             $contentClassAttribute =& $contentObjectAttribute->contentClassAttribute();
266             $numRows = $contentClassAttribute->attribute( 'data_int1' );
267             $matrix = new eZMatrix( '', $numRows, $contentClassAttribute->attribute( 'content' ) );
268             // 'default name' is never used => just a stub
269             // $matrix->setName( $contentClassAttribute->attribute( 'data_text1' ) );
270             $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
271             $contentObjectAttribute->setContent( $matrix );
272         }
273
274     }
275
276     /*!
277      \reimp
278     */
279     function fetchClassAttributeHTTPInput( &$http, $base, &$classAttribute )
280     {
281         // 'default name' is never used => just a stub
282         // $defaultValueName = $base . EZ_MATRIX_DEFAULT_NAME_VARIABLE . $classAttribute->attribute( 'id' );
283         $defaultValueName = '';
284         $defaultNumColumnsName = $base . EZ_MATRIX_NUMCOLUMNS_VARIABLE . $classAttribute->attribute( 'id' );
285         $defaultNumRowsName = $base . EZ_MATRIX_NUMROWS_VARIABLE . $classAttribute->attribute( 'id' );
286         $dataFetched = false;
287         // 'default name' is never used => just a stub
288         /*
289         if ( $http->hasPostVariable( $defaultValueName ) )
290         {
291             $defaultValueValue = $http->postVariable( $defaultValueName );
292
293             if ( $defaultValueValue == '' )
294             {
295                 $defaultValueValue = '';
296             }
297             $classAttribute->setAttribute( 'data_text1', $defaultValueValue );
298             $dataFetched = true;
299         }
300         */
301
302         if ( $http->hasPostVariable( $defaultNumRowsName ) )
303         {
304             $defaultNumRowsValue = $http->postVariable( $defaultNumRowsName );
305
306             if ( $defaultNumRowsValue == '' )
307             {
308                 $defaultNumRowsValue = '1';
309             }
310             $classAttribute->setAttribute( 'data_int1', $defaultNumRowsValue );
311             $dataFetched = true;
312         }
313
314         $columnNameVariable = $base . '_data_ezmatrix_column_name_' . $classAttribute->attribute( 'id' );
315         $columnIDVariable = $base . '_data_ezmatrix_column_id_' . $classAttribute->attribute( 'id' );
316
317
318         if ( $http->hasPostVariable( $columnNameVariable ) && $http->hasPostVariable( $columnIDVariable ) )
319         {
320             $columns = array();
321             $i = 0;
322             $columnNameList = $http->postVariable( $columnNameVariable );
323             $columnIDList = $http->postVariable( $columnIDVariable );
324
325             $matrixDefinition =& $classAttribute->attribute( 'content' );
326             $columnNames =& $matrixDefinition->attribute( 'columns' );
327             foreach ( $columnNames as $columnName )
328             {
329                 $columnID = '';
330                 $name = '';
331                 $index = $columnName['index'];
332
333                 // after adding a new column $columnIDList and $columnNameList doesn't contain values for new column.
334                 // if so just add column with empty 'name' and 'columnID'.
335                 if ( isset( $columnIDList[$index] ) && isset( $columnNameList[$index] ) )
336                 {
337                     $columnID = $columnIDList[$index];
338                     $name = $columnNameList[$index];
339                     if ( strlen( $columnID ) == 0 )
340                     {
341                         $columnID = $name;
342                         // Initialize transformation system
343                         include_once( 'lib/ezi18n/classes/ezchartransform.php' );
344                         $trans =& eZCharTransform::instance();
345                         $columnID = $trans->transformByGroup( $columnID, 'identifier' );
346                     }
347                 }
348
349                 $columns[] = array( 'name' => $name,
350                                     'identifier' => $columnID,
351                                     'index' => $i );
352
353                 $i++;
354             }
355
356             $matrixDefinition->ColumnNames =& $columns;
357             $classAttribute->setContent( $matrixDefinition );
358             $classAttribute->setAttribute( 'data_text5', $matrixDefinition->xmlString() );
359
360             $dataFetched = true;
361         }
362         if ( $dataFetched )
363         {
364             return true;
365         }
366         return false;
367
368     }
369
370
371     /*!
372      Returns the content.
373     */
374     function &classAttributeContent( &$contentClassAttribute )
375     {
376         $matrixDefinition = new eZMatrixDefinition();
377         $matrixDefinition->decodeClassAttribute( $contentClassAttribute->attribute( 'data_text5' ) );
378         return $matrixDefinition;
379     }
380
381     /*!
382     */
383     function customClassAttributeHTTPAction( &$http, $action, &$contentClassAttribute )
384     {
385         $id = $contentClassAttribute->attribute( 'id' );
386         switch ( $action )
387         {
388             case 'new_ezmatrix_column' :
389             {
390                 $matrixDefinition =& $contentClassAttribute->content( );
391                 $matrixDefinition->addColumn( '' );
392                 $contentClassAttribute->setContent( $matrixDefinition );
393                 $contentClassAttribute->store();
394             }break;
395             case 'remove_selected' :
396             {
397                 $matrixDefinition =& $contentClassAttribute->content( );
398
399                 $postvarname = 'ContentClass' . '_data_ezmatrix_column_remove_' . $contentClassAttribute->attribute( 'id' );
400                 $array_remove = $http->postVariable( $postvarname );
401                 foreach( $array_remove as $columnIndex )
402                 {
403                     $matrixDefinition->removeColumn( $columnIndex );
404                 }
405                 $contentClassAttribute->setContent( $matrixDefinition );
406             }break;
407             default :
408             {
409                 eZDebug::writeError( 'Unknown custom HTTP action: ' . $action, 'eZEnumType' );
410             }break;
411         }
412     }
413
414     /*!
415      \reimp
416     */
417     function isIndexable()
418     {
419         return true;
420     }
421
422     /*!
423      \return string representation of an contentobjectattribute data for simplified export
424
425     */
426     function toString( $contentObjectAttribute )
427     {
428         $matrix = $contentObjectAttribute->attribute( 'content' );
429         $matrixArray = array();
430         $rows = $matrix->attribute( 'rows' );
431
432         foreach( $rows['sequential'] as $row )
433         {
434             $matrixArray[] = eZStringUtils::implodeStr( $row['columns'], '|' );
435         }
436
437         return eZStringUtils::implodeStr( $matrixArray, '&' );
438
439     }
440
441     function fromString( &$contentObjectAttribute, $string )
442     {
443         if ( $string != '' )
444         {
445             $matrix =& $contentObjectAttribute->attribute( 'content' );
446             $matrixRowsList = eZStringUtils::explodeStr( $string, "&" );
447             $cells = array();
448             $matrix->Matrix['rows']['sequential'] = array();
449             $matrix->NumRows = 0;
450
451             foreach( $matrixRowsList as $key => $value )
452             {
453                 $newCells = eZStringUtils::explodeStr( $value, '|' );
454                 $matrixArray[] = $newCells;
455                 $cells = array_merge( $cells, $newCells );
456
457                 $newRow['columns'] = $newCells;
458                 $newRow['identifier'] =  'row_' . ( $numRows + 1 );
459                 $newRow['name'] = 'Row_' . ( $numRows + 1 );
460                 $matrix->NumRows++;
461
462
463                 $matrix->Matrix['rows']['sequential'][] = $newRow;
464             }
465             $matrix->Cells = $cells;
466         }
467         return true;
468     }
469
470     /*!
471      \reimp
472     */
473     function serializeContentClassAttribute( &$classAttribute, &$attributeNode, &$attributeParametersNode )
474     {
475         $content =& $classAttribute->content();
476         if ( $content )
477         {
478             $defaultName = $classAttribute->attribute( 'data_text1' );
479             $defaultRowCount = $classAttribute->attribute( 'data_int1' );
480             $columns = $content->attribute( 'columns' );
481             $attributeParametersNode->appendChild( eZDOMDocument::createElementTextNode( 'default-name', $defaultName ) );
482             $attributeParametersNode->appendChild( eZDOMDocument::createElementTextNode( 'default-row-count', $defaultRowCount ) );
483             $columnsNode = eZDOMDocument::createElementNode( 'columns' );
484             $attributeParametersNode->appendChild( $columnsNode );
485             foreach ( $columns as $column )
486             {
487                 $columnsNode->appendChild( eZDOMDocument::createElementNode( 'column',
488                                                                              array( 'name' => $column['name'],
489                                                                                     'identifier' => $column['identifier'],
490                                                                                     'index' => $column['index'] ) ) );
491             }
492         }
493     }
494
495     /*!
496      \reimp
497     */
498     function unserializeContentClassAttribute( &$classAttribute, &$attributeNode, &$attributeParametersNode )
499     {
500         $defaultName = $attributeParametersNode->elementTextContentByName( 'default-name' );
501         $defaultRowCount = $attributeParametersNode->elementTextContentByName( 'default-row-count' );
502         $classAttribute->setAttribute( 'data_text1', $defaultName );
503         $classAttribute->setAttribute( 'data_int1', $defaultRowCount );
504
505         $matrixDefinition = new eZMatrixDefinition();
506         $columnsNode =& $attributeParametersNode->elementByName( 'columns' );
507         $columnsList = $columnsNode->children();
508         foreach ( $columnsList  as $columnNode )
509         {
510             $columnName = $columnNode->attributeValue( 'name' );
511             $columnIdentifier = $columnNode->attributeValue( 'identifier' );
512             $matrixDefinition->addColumn( $columnName, $columnIdentifier );
513         }
514         $classAttribute->setAttribute( 'data_text5', $matrixDefinition->xmlString() );
515     }
516
517     /*!
518      \reimp
519     */
520     function serializeContentObjectAttribute( &$package, &$objectAttribute )
521     {
522         $node = $this->createContentObjectAttributeDOMNode( $objectAttribute );
523
524         $xml = new eZXML();
525         $domDocument = $xml->domTree( $objectAttribute->attribute( 'data_text' ) );
526         $node->appendChild( $domDocument->root() );
527
528         return $node;
529     }
530
531     /*!
532      \reimp
533     */
534     function unserializeContentObjectAttribute( &$package, &$objectAttribute, $attributeNode )
535     {
536         $rootNode = $attributeNode->firstChild();
537         $xmlString = $rootNode->attributeValue( 'local_name' ) == 'data-text' ? $rootNode->toString( 0 ) : '';
538         $objectAttribute->setAttribute( 'data_text', $xmlString );
539     }
540 }
541
542 eZDataType::register( EZ_DATATYPESTRING_MATRIX, 'ezmatrixtype' );
543
544 ?>