- Fixed various references.
[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.10.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, $parameters )
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                 $debug = eZDebug::instance();
231                 $debug->writeError( 'Unknown custom HTTP action: ' . $action, 'eZMatrixType' );
232             }break;
233         }
234     }
235
236     /*!
237      Returns the integer value.
238     */
239     function title( $contentObjectAttribute, $name = 'name' )
240     {
241         $matrix = $contentObjectAttribute->content( );
242
243         $value = $matrix->attribute( $name );
244
245         return $value;
246     }
247
248     /*!
249      Sets the default value.
250     */
251     function initializeObjectAttribute( &$contentObjectAttribute, $currentVersion, &$originalContentObjectAttribute )
252     {
253
254         if ( $currentVersion != false )
255         {
256             $matrix = $originalContentObjectAttribute->content();
257             $contentClassAttribute = $contentObjectAttribute->contentClassAttribute();
258             // make sure that $matrix contains right columns
259             $matrix->adjustColumnsToDefinition( $contentClassAttribute->attribute( 'content' ) );
260
261             $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
262             $contentObjectAttribute->setContent( $matrix );
263         }
264         else
265         {
266             $contentClassAttribute = $contentObjectAttribute->contentClassAttribute();
267             $numRows = $contentClassAttribute->attribute( 'data_int1' );
268             $matrix = new eZMatrix( '', $numRows, $contentClassAttribute->attribute( 'content' ) );
269             // 'default name' is never used => just a stub
270             // $matrix->setName( $contentClassAttribute->attribute( 'data_text1' ) );
271             $contentObjectAttribute->setAttribute( 'data_text', $matrix->xmlString() );
272             $contentObjectAttribute->setContent( $matrix );
273         }
274
275     }
276
277     /*!
278      \reimp
279     */
280     function fetchClassAttributeHTTPInput( $http, $base, $classAttribute )
281     {
282         // 'default name' is never used => just a stub
283         // $defaultValueName = $base . EZ_MATRIX_DEFAULT_NAME_VARIABLE . $classAttribute->attribute( 'id' );
284         $defaultValueName = '';
285         $defaultNumColumnsName = $base . EZ_MATRIX_NUMCOLUMNS_VARIABLE . $classAttribute->attribute( 'id' );
286         $defaultNumRowsName = $base . EZ_MATRIX_NUMROWS_VARIABLE . $classAttribute->attribute( 'id' );
287         $dataFetched = false;
288         // 'default name' is never used => just a stub
289         /*
290         if ( $http->hasPostVariable( $defaultValueName ) )
291         {
292             $defaultValueValue = $http->postVariable( $defaultValueName );
293
294             if ( $defaultValueValue == '' )
295             {
296                 $defaultValueValue = '';
297             }
298             $classAttribute->setAttribute( 'data_text1', $defaultValueValue );
299             $dataFetched = true;
300         }
301         */
302
303         if ( $http->hasPostVariable( $defaultNumRowsName ) )
304         {
305             $defaultNumRowsValue = $http->postVariable( $defaultNumRowsName );
306
307             if ( $defaultNumRowsValue == '' )
308             {
309                 $defaultNumRowsValue = '1';
310             }
311             $classAttribute->setAttribute( 'data_int1', $defaultNumRowsValue );
312             $dataFetched = true;
313         }
314
315         $columnNameVariable = $base . '_data_ezmatrix_column_name_' . $classAttribute->attribute( 'id' );
316         $columnIDVariable = $base . '_data_ezmatrix_column_id_' . $classAttribute->attribute( 'id' );
317
318
319         if ( $http->hasPostVariable( $columnNameVariable ) && $http->hasPostVariable( $columnIDVariable ) )
320         {
321             $columns = array();
322             $i = 0;
323             $columnNameList = $http->postVariable( $columnNameVariable );
324             $columnIDList = $http->postVariable( $columnIDVariable );
325
326             $matrixDefinition = $classAttribute->attribute( 'content' );
327             $columnNames = $matrixDefinition->attribute( 'columns' );
328             foreach ( $columnNames as $columnName )
329             {
330                 $columnID = '';
331                 $name = '';
332                 $index = $columnName['index'];
333
334                 // after adding a new column $columnIDList and $columnNameList doesn't contain values for new column.
335                 // if so just add column with empty 'name' and 'columnID'.
336                 if ( isset( $columnIDList[$index] ) && isset( $columnNameList[$index] ) )
337                 {
338                     $columnID = $columnIDList[$index];
339                     $name = $columnNameList[$index];
340                     if ( strlen( $columnID ) == 0 )
341                     {
342                         $columnID = $name;
343                         // Initialize transformation system
344                         include_once( 'lib/ezi18n/classes/ezchartransform.php' );
345                         $trans = eZCharTransform::instance();
346                         $columnID = $trans->transformByGroup( $columnID, 'identifier' );
347                     }
348                 }
349
350                 $columns[] = array( 'name' => $name,
351                                     'identifier' => $columnID,
352                                     'index' => $i );
353
354                 $i++;
355             }
356
357             $matrixDefinition->ColumnNames = $columns;
358             $classAttribute->setContent( $matrixDefinition );
359             $classAttribute->setAttribute( 'data_text5', $matrixDefinition->xmlString() );
360
361             $dataFetched = true;
362         }
363         if ( $dataFetched )
364         {
365             return true;
366         }
367         return false;
368
369     }
370
371
372     /*!
373      Returns the content.
374     */
375     function classAttributeContent( $contentClassAttribute )
376     {
377         $matrixDefinition = new eZMatrixDefinition();
378         $matrixDefinition->decodeClassAttribute( $contentClassAttribute->attribute( 'data_text5' ) );
379         return $matrixDefinition;
380     }
381
382     /*!
383     */
384     function customClassAttributeHTTPAction( $http, $action, $contentClassAttribute )
385     {
386         $id = $contentClassAttribute->attribute( 'id' );
387         switch ( $action )
388         {
389             case 'new_ezmatrix_column' :
390             {
391                 $matrixDefinition = $contentClassAttribute->content( );
392                 $matrixDefinition->addColumn( '' );
393                 $contentClassAttribute->setContent( $matrixDefinition );
394                 $contentClassAttribute->store();
395             }break;
396             case 'remove_selected' :
397             {
398                 $matrixDefinition = $contentClassAttribute->content( );
399
400                 $postvarname = 'ContentClass' . '_data_ezmatrix_column_remove_' . $contentClassAttribute->attribute( 'id' );
401                 $array_remove = $http->postVariable( $postvarname );
402                 foreach( $array_remove as $columnIndex )
403                 {
404                     $matrixDefinition->removeColumn( $columnIndex );
405                 }
406                 $contentClassAttribute->setContent( $matrixDefinition );
407             }break;
408             default :
409             {
410                 $debug = eZDebug::instance();
411                 $debug->writeError( 'Unknown custom HTTP action: ' . $action, 'eZEnumType' );
412             }break;
413         }
414     }
415
416     /*!
417      \reimp
418     */
419     function isIndexable()
420     {
421         return true;
422     }
423
424     /*!
425      \return string representation of an contentobjectattribute data for simplified export
426
427     */
428     function toString( $contentObjectAttribute )
429     {
430         $matrix = $contentObjectAttribute->attribute( 'content' );
431         $matrixArray = array();
432         $rows = $matrix->attribute( 'rows' );
433
434         foreach( $rows['sequential'] as $row )
435         {
436             $matrixArray[] = eZStringUtils::implodeStr( $row['columns'], '|' );
437         }
438
439         return eZStringUtils::implodeStr( $matrixArray, '&' );
440
441     }
442
443     function fromString( &$contentObjectAttribute, $string )
444     {
445         if ( $string != '' )
446         {
447             $matrix = $contentObjectAttribute->attribute( 'content' );
448             $matrixRowsList = eZStringUtils::explodeStr( $string, "&" );
449             $cells = array();
450             $matrix->Matrix['rows']['sequential'] = array();
451             $matrix->NumRows = 0;
452
453             foreach( $matrixRowsList as $key => $value )
454             {
455                 $newCells = eZStringUtils::explodeStr( $value, '|' );
456                 $matrixArray[] = $newCells;
457                 $cells = array_merge( $cells, $newCells );
458
459                 $newRow['columns'] = $newCells;
460                 $newRow['identifier'] =  'row_' . ( $numRows + 1 );
461                 $newRow['name'] = 'Row_' . ( $numRows + 1 );
462                 $matrix->NumRows++;
463
464
465                 $matrix->Matrix['rows']['sequential'][] = $newRow;
466             }
467             $matrix->Cells = $cells;
468         }
469         return true;
470     }
471
472     /*!
473      \reimp
474     */
475     function serializeContentClassAttribute( &$classAttribute, &$attributeNode, &$attributeParametersNode )
476     {
477         $content = $classAttribute->content();
478         if ( $content )
479         {
480             $defaultName = $classAttribute->attribute( 'data_text1' );
481             $defaultRowCount = $classAttribute->attribute( 'data_int1' );
482             $columns = $content->attribute( 'columns' );
483
484             $dom = $attributeParametersNode->ownerDocument;
485             $defaultNameNode = $dom->createElement( 'default-name', $defaultName );
486             $attributeParametersNode->appendChild( $defaultNameNode );
487             $defaultRowCountNode = $dom->createElement( 'default-row-count', $defaultRowCount );
488             $attributeParametersNode->appendChild( $defaultRowCountNode );
489             $columnsNode = $dom->createElement( 'columns' );
490             $attributeParametersNode->appendChild( $columnsNode );
491             foreach ( $columns as $column )
492             {
493                 unset( $columnNode );
494                 $columnNode = $dom->createElement( 'column' );
495                 $columnNode->setAttribute( 'name', $column['name'] );
496                 $columnNode->setAttribute( 'identifier', $column['identifier'] );
497                 $columnNode->setAttribute( 'index', $column['index'] );
498                 $columnsNode->appendChild( $columnNode );
499             }
500         }
501     }
502
503     /*!
504      \reimp
505     */
506     function unserializeContentClassAttribute( &$classAttribute, &$attributeNode, &$attributeParametersNode )
507     {
508         $defaultName = $attributeParametersNode->getElementsByTagName( 'default-name' )->item( 0 )->textContent;
509         $defaultRowCount = $attributeParametersNode->getElementsByTagName( 'default-row-count' )->item( 0 )->textContent;
510         $classAttribute->setAttribute( 'data_text1', $defaultName );
511         $classAttribute->setAttribute( 'data_int1', $defaultRowCount );
512
513         $matrixDefinition = new eZMatrixDefinition();
514         $columnsNode = $attributeParametersNode->getElementsByTagName( 'columns' )->item( 0 );
515         $columnsList = $columnsNode->getElementsByTagName( 'column' );
516         foreach ( $columnsList  as $columnNode )
517         {
518             $columnName = $columnNode->getAttribute( 'name' );
519             $columnIdentifier = $columnNode->getAttribute( 'identifier' );
520             $matrixDefinition->addColumn( $columnName, $columnIdentifier );
521         }
522         $classAttribute->setAttribute( 'data_text5', $matrixDefinition->xmlString() );
523     }
524
525     /*!
526      \reimp
527     */
528     function serializeContentObjectAttribute( $package, $objectAttribute )
529     {
530         $node = $this->createContentObjectAttributeDOMNode( $objectAttribute );
531
532         $dom = new DOMDocument();
533         $success = $dom->loadXML( $objectAttribute->attribute( 'data_text' ) );
534
535         $importedRoot = $node->ownerDocument->importNode( $dom->documentElement, true );
536         $node->appendChild( $importedRoot );
537
538         return $node;
539     }
540
541     /*!
542      \reimp
543     */
544     function unserializeContentObjectAttribute( $package, $objectAttribute, $attributeNode )
545     {
546         $rootNode = $attributeNode->getElementsByTagName( 'ezmatrix' )->item( 0 );
547         $xmlString = $rootNode ? $rootNode->ownerDocument->saveXML( $rootNode ) : '';
548         $objectAttribute->setAttribute( 'data_text', $xmlString );
549     }
550 }
551
552 eZDataType::register( EZ_DATATYPESTRING_MATRIX, 'ezmatrixtype' );
553
554 ?>