-
Notifications
You must be signed in to change notification settings - Fork 0
/
Categorisable.php
155 lines (138 loc) · 5.92 KB
/
Categorisable.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
/**
* Copyright 2010 Zikula Foundation.
*
* This work is contributed to the Zikula Foundation under one or more
* Contributor Agreements and licensed to You under the following license:
*
* @license GNU/LGPLv3 (or at your option, any later version).
* @package Zikula
* @subpackage Zikula_Doctrine
*
* Please see the NOTICE file distributed with this source code for further
* information regarding copyright and licensing.
*/
/**
* This behavior add categories to the record.
*/
class Zikula_Doctrine_Template_Categorisable extends Doctrine_Template
{
/**
* Adds an one-to-many relationship named Categories to Zikula_Doctrine_Model_EntityCategory.
*
* @return void
* @throws Exception Throws when the record uses Categorisable template AND a composite primary key.
*/
public function setUp()
{
$record = $this->getInvoker();
$recordClass = get_class($record);
$subclassName = 'GeneratedDoctrineModel_'. $recordClass.'_EntityCategory';
$module = substr($recordClass, 0, strpos($recordClass, '_'));
if (!class_exists($subclassName)) {
self::_generateSubclassForCategorisableTemplate($module, $recordClass);
}
$idColumn = $record->getTable()->getIdentifier();
if (is_array($idColumn)) {
if (count($idColumn) > 1) {
throw new LogicException(sprintf('Error: Doctrine record %s uses Categorisable template AND a composite primary key', $recordClass));
}
$idColumn = $idColumn[0];
}
$this->hasMany($subclassName.' as Categories', array(
'local' => $idColumn,
'foreign' => 'obj_id',
'cascade' => array('delete')
));
$this->addListener(new Zikula_Doctrine_Template_Listener_Categorisable());
}
/**
* Generates an subclass of the Zikula_Doctrine_Model_EntityCategory class and caches the generated class in a file.
*
* @param string $module Name of the Module to that the model belongs to.
* @param string $modelClass Classname of the model.
*
* @return void
* @throws Exception Throws when the create of the cache directory fails.
*/
private static function _generateSubclassForCategorisableTemplate($module, $modelClass)
{
$table = Doctrine::getTable($modelClass);
sscanf($table->getTableName(), Doctrine_Manager::getInstance()->getAttribute(Doctrine::ATTR_TBLNAME_FORMAT), $tableName);
$dir = 'doctrinemodels/GeneratedDoctrineModel/' . str_replace('_', DIRECTORY_SEPARATOR, $modelClass);
if (CacheUtil::createLocalDir($dir, System::getVar('system.chmod_dir'))) {
$subclassName = 'GeneratedDoctrineModel_'.$modelClass.'_EntityCategory';
$fileContents = '<?php class '.$subclassName.' extends Zikula_Doctrine_Model_EntityCategory { }';
$fileName = 'EntityCategory.php';
// save new model
file_put_contents(CacheUtil::getLocalDir().'/'.$dir.'/'.$fileName, $fileContents);
// save required data for later use
$modelsInfo = ModUtil::getVar('Categories', 'EntityCategorySubclasses', array());
$modelsInfo[$subclassName] = array('module' => $module, 'table' => $tableName);
ModUtil::setVar('Categories', 'EntityCategorySubclasses', $modelsInfo);
} else {
throw new Exception('Creation of the cache directory '.$dir.' failed');
}
}
/**
* Allows to sets multiple categories with one call.
*
* @param array $categories Array of property => Category id or Category Object.
*
* @return void
*/
public function setCategories(array $categories)
{
foreach ($categories as $prop => $category) {
$this->setCategory($prop, $category);
}
}
/**
* Set/adds an category to requested property.
*
* @param string $prop Property name as definied in the registry.
* @param string $category Category id or Object.
*
* @return void
* @throws Exception If this table has not the property $prop.
*/
public function setCategory($prop, $category)
{
$rec = $this->getInvoker();
sscanf($rec->getTable()->getTableName(), Doctrine_Manager::getInstance()->getAttribute(Doctrine::ATTR_TBLNAME_FORMAT), $tableName);
// get the registry object
$registry = Doctrine::getTable('Zikula_Doctrine_Model_Registry')->findOneByModuleAndTableAndProperty(substr(get_class($rec), 0, strpos(get_class($rec), '_')),
$tableName,
$prop);
// throw an excption when $prop is not valid
if (!$registry) {
throw new Exception('Property '.$prop.' not found');
}
// search for existring object
$mapobjFound = null;
foreach ($rec['Categories'] as $mapobj) {
if ($mapobj['reg_property'] == $prop) {
$mapobjFound = $mapobj;
break;
}
}
// update existring object
if ($mapobjFound != null) {
if (is_object($category) && $category instanceof Zikula_Doctrine_Model_Category) {
$mapobjFound['Category'] = $category;
} else {
$mapobjFound['category_id'] = (int)$category;
}
// create new object
} else {
$rec['Categories'][]['Registry'] = $registry;
$newmapobj = $rec['Categories']->getLast();
$newmapobj['reg_property'] = $prop;
if (is_object($category) && $category instanceof Zikula_Doctrine_Model_Category) {
$newmapobj['Category'] = $category;
} else {
$newmapobj['category_id'] = (int)$category;
}
}
}
}