Skip to content

Commit 078c5e1

Browse files
committed
Initial commit
0 parents  commit 078c5e1

File tree

4,519 files changed

+812047
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

4,519 files changed

+812047
-0
lines changed

DB/Sync.php

+251
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<?php
2+
3+
4+
class DB_Sync {
5+
6+
var $db1;
7+
var $db2;
8+
9+
var $table1;
10+
var $table2;
11+
12+
var $table1Data;
13+
var $table2Data;
14+
15+
var $renamed = array();
16+
var $listeners = array();
17+
18+
function DB_Sync($db1, $db2, $table1=null, $table2=null, $renamed=null){
19+
$this->db1 = $db1;
20+
$this->db2 = $db2;
21+
22+
$this->init($table1, $table2, $renamed);
23+
}
24+
25+
26+
/**
27+
* Compares 2 tables to see if they are identical in definition.
28+
*
29+
* @param string $table1 The name of the first table.
30+
* @param string $table2 The name of the second table.
31+
* @returns boolean True if the tables have identical schemas.
32+
*
33+
*/
34+
function equals($table1=null, $table2=null){
35+
36+
$this->init($table1,$table2);
37+
echo "Now here";
38+
print_r($this->table1Data);
39+
print_r($this->table2Data);
40+
return ( $this->table1Data == $this->table2Data );
41+
42+
}
43+
44+
function init($table1, $table2, $renamed=null){
45+
46+
if ( isset($table1) and isset($table2) and ($table1 != $this->table1 || $table2 != $this->table2) ){
47+
48+
49+
$this->table1 = $table1;
50+
$this->table2 = $table2;
51+
if ( isset($renamed) ) $this->renamed = $renamed;
52+
$this->loadTableData();
53+
54+
}
55+
}
56+
57+
function checkTableNames(){
58+
59+
if ( !isset($this->table1) ){
60+
trigger_error("Attempt to load data for tables in DB_Sync, but table 1 has not been specified.", E_USER_ERROR);
61+
}
62+
63+
if ( !isset($this->table2) ){
64+
trigger_error("Attempt to load data for tables in DB_Sync, but table 2 has not been specified.", E_USER_ERROR);
65+
}
66+
67+
if ( !preg_match('/^[a-zA-Z0-9_]+$/', $this->table1) ){
68+
trigger_error("The table '{$this->table1}' has an invalid name.", E_USER_ERROR);
69+
}
70+
71+
if ( !preg_match('/^[a-zA-Z0-9_]+$/', $this->table2) ){
72+
trigger_error("The table '{$this->table2}' has an invalid name.", E_USER_ERROR);
73+
}
74+
75+
}
76+
77+
78+
79+
/**
80+
* Loads the table data for table 1 and table 2 into table1Data and table2Data respectively.
81+
*/
82+
function loadTableData(){
83+
84+
$this->checkTableNames();
85+
86+
$res = mysql_query("show full fields from `".$this->table1."`", $this->db1);
87+
if ( !$res ) trigger_error(mysql_error($this->db1));
88+
89+
90+
$this->table1Data = array();
91+
while ( $row = mysql_fetch_assoc($res) ){
92+
$this->table1Data[$row['Field']] = $row;
93+
}
94+
95+
@mysql_free_result($res);
96+
97+
98+
$res = mysql_query("show columns from `".$this->table2."`", $this->db2);
99+
if ( !$res ) trigger_error(mysql_error($this->db2));
100+
101+
$this->table2Data = array();
102+
while ( $row = mysql_fetch_assoc($res) ){
103+
$this->table2Data[$row['Field']] = $row;
104+
}
105+
106+
@mysql_free_result($res);
107+
108+
109+
}
110+
111+
/**
112+
* Converts a field's array data into an SQL string definition.
113+
* @param array $field The array data for a field.
114+
* @returns string SQL definition for field.
115+
*/
116+
function fieldArrayToSQLDef($field){
117+
118+
if ( $field['Default'] ){
119+
120+
if ( strcasecmp($field['Default'], 'NULL') === 0 ){
121+
122+
$default = 'default NULL';
123+
124+
} else if ( $field['Default'] ) {
125+
126+
$default = 'default \''.$field['Default'].'\'';
127+
} else {
128+
$default = '';
129+
}
130+
131+
} else {
132+
133+
$default = '';
134+
135+
}
136+
137+
if ( $field['Collation'] and strcasecmp($field['Collation'],'null') !== 0){
138+
139+
$charset = 'CHARACTER SET '.substr($field['Collation'],0, strpos($field['Collation'], '_')).' COLLATE '.
140+
$field['Collation'];
141+
142+
} else {
143+
144+
$charset = '';
145+
}
146+
147+
if ( $field['Null'] ){
148+
149+
$null = ( ( strcasecmp('yes',$field['Null'])===0 ) ? '' : 'NOT NULL');
150+
} else {
151+
$null = '';
152+
}
153+
154+
155+
156+
157+
158+
return "`{$field['Field']}` {$field['Type']} {$charset} {$null} {$field['Extra']} {$default}";
159+
160+
}
161+
162+
/**
163+
* Synchronizes the field named $fieldname.
164+
*/
165+
function syncField($fieldname, $after=null, $renameMap=null){
166+
167+
if (isset($renameMap) ) $this->renamed = $renameMap;
168+
169+
170+
171+
if ( !isset($this->table1Data[$fieldname]) ){
172+
173+
// Table 1 does not have this field... see if it has been renamed.
174+
175+
if ( isset($this->renamed[$fieldname]) ){
176+
177+
$newname = @$this->renamed[$fieldname];
178+
179+
if ( !$newname ){
180+
trigger_error("Attempt to rename field '{$fieldname}' in table '{$this->table2}' to {$newname} but the source table '{$this->table1}' has no such field to copy.", E_USER_ERROR);
181+
}
182+
183+
$sql = "alter table `{$this->table2}` change `{$fieldname}` ".$this->fieldArrayToSQLDef($this->table1Data[$newname]);
184+
$res = mysql_query($sql, $this->db2);
185+
if ( !$res ) trigger_error(mysql_error($this->db2), E_USER_ERROR);
186+
187+
} else {
188+
189+
trigger_error("Attempt to syncronize field '{$fieldname}' but the source table has no such field.", E_USER_ERROR);
190+
}
191+
192+
193+
} else if ( !isset( $this->table2Data[$fieldname] ) ) {
194+
195+
$sql = "alter table `{$this->table2}` add ".$this->fieldArrayToSQLDef($this->table1Data[$fieldname]);
196+
if ( isset($after) ){
197+
$sql .= "after `{$after}`";
198+
}
199+
$res = mysql_query($sql, $this->db2);
200+
if ( !$res ) trigger_error($sql."\n".mysql_error($this->db2), E_USER_ERROR);
201+
202+
} else if ( $this->table1Data[$fieldname] != $this->table2Data[$fieldname] ) {
203+
204+
$sql = "alter table `{$this->table2}` change `{$fieldname}` ".$this->fieldArrayToSQLDef($this->table1Data[$fieldname]);
205+
$res = mysql_query($sql, $this->db2);
206+
if ( !$res ) trigger_error(mysql_error($this->db2), E_USER_ERROR);
207+
208+
} else {
209+
210+
// nothing to do here.
211+
}
212+
}
213+
214+
215+
216+
function syncTables($table1=null, $table2=null, $renamedMap=null){
217+
218+
$this->init($table1, $table2, $renamedMap);
219+
220+
if (!$this->equals() ){
221+
echo "Here";
222+
$positions = array();
223+
$fieldnames = array_keys($this->table1Data);
224+
$i=0;
225+
foreach ($fieldnames as $f){
226+
$positions[$f] = $i++;
227+
228+
}
229+
230+
$fields = array_merge(array_keys($this->table1Data), array_keys($this->table2Data));
231+
$fields = array_unique($fields);
232+
print_r($fields);
233+
foreach ($fields as $field ){
234+
if ( isset( $positions[$field] ) and $positions[$field] > 0 ){
235+
$after = $fieldnames[$positions[$field]-1];
236+
} else if ( isset($positions[$field]) ){
237+
$after = "first";
238+
} else {
239+
$after = null;
240+
}
241+
$this->syncField($field, $after);
242+
}
243+
}
244+
245+
246+
247+
248+
}
249+
}
250+
251+
?>

Dataface/ActionHandler.php

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
/**
3+
* @brief Interface for action handlers in Xataface application. An action handler
4+
* serves as an HTTP access point for an application. Actions may be located
5+
* in the following locations:
6+
*
7+
* -# %DATAFACE_SITE_PATH%/tables/%tablename%/actions/%actionname%.php
8+
* -# %DATAFACE_SITE_PATH%/actions/%actionname%.php
9+
* -# %DATAFACE_SITE_PATH%/modules/%modulename%/actions/%actionname%.php
10+
* -# %DATAFACE_PATH/actions/%actionname%.php
11+
*
12+
* The action file should contain a class with a name that roughly matches
13+
* the path to the file.
14+
*
15+
* E.g. An action in the tables/%tablename%/actions/%actionname%.php file should
16+
* be named @p tables_%tablename%_actions_%actionname% . Similarly an action
17+
* in the actions/%actionname%.php file should be named
18+
* @p actions_%actionname% etc...
19+
*
20+
* This interface serves to document the available methods that may be defined in
21+
* an action handler and how they are expected to work.
22+
*
23+
* @par Example Action
24+
*
25+
* Consider a sample action located in the @p %DATAFACE_SITE_PATH%/actions/myaction.php
26+
* file:
27+
*
28+
* @code
29+
* class actions_myaction {
30+
* function handle($params){
31+
* echo "Hello World";
32+
* }
33+
* }
34+
* @endcode
35+
*
36+
* @section action_config_with_actions_ini Configuration With The actions.ini file
37+
*
38+
* An action handler is the PHP portion of an action that is defined in the
39+
* <a href="http://xataface.com/wiki/actions.ini_file">actions.ini file</a>. The actions.ini
40+
* file allows you to decide where the action appears in the application's user interface
41+
* as well as such things as permissions. You can also define permissions programmatically
42+
* inside your action.
43+
*
44+
*
45+
* @author Steve Hannah <[email protected]>
46+
* @created Nov. 26, 2011
47+
*/
48+
interface ActionHandler {
49+
50+
/**
51+
* @brief The entry point for this action.
52+
*
53+
* @param array $params Parameters passed to the action to determine how the
54+
* action should be executed. The only key that is currently set to be passed
55+
* is @p relationship but this can equivalently be obtained from the @p $query['-relationship']
56+
* Query parameter.
57+
*
58+
* @returns mixed If this method returns a PEAR_Error object, then Xataface will
59+
* do some additional processing depending on the type of error.
60+
*
61+
* @par Dealing with Permission Denied Errors
62+
*
63+
* If during the course of execution the current user is deemed to lack sufficient
64+
* permission to perform this action, then handle() may return a PEAR_Error
65+
* with the code @p DATAFACE_E_PERMISSION_DENIED. Equivalently it may return
66+
* the result of the Dataface_Error::permissionDenied() method:
67+
*
68+
* @code
69+
* if ( !$record->checkPermission('view') ){
70+
* return Dataface_Error::permissionDenied("You don't have permission for this.");
71+
* }
72+
* @endcode
73+
*
74+
* @par Request Not Handled Errors
75+
*
76+
* It is also possible to signal to Xataface that the action opted not to handle
77+
* the request at all, so that Xataface will pass the opportunity to handle the
78+
* request onto the next elligible action handler. This allows you to define
79+
* handlers specific to a table that may override default actions or choose to just
80+
* allow the default action to handle it.
81+
*
82+
* @code
83+
*
84+
* class tables_mytable_actions_list {
85+
* function handle($params){
86+
* $query = Dataface_Application::getInstance()->getQuery();
87+
* if ( !@$query['foo'] ) return PEAR::raiseError(
88+
* 'WE only handle requests when the foo parameter is provided. Use the default list action.',
89+
* DATAFACE_E_REQUEST_NOT_HANDLED
90+
* );
91+
* echo "WE are handling this request ourselves.";
92+
* }
93+
* }
94+
* @endcode
95+
*/
96+
public function handle($params);
97+
98+
/**
99+
* @brief An optional method to override the permissions granted to the current user
100+
* when this action is requested. This option is not often used and it is questionable
101+
* whether it is of any value since permissions can be amply defined in the table
102+
* or application delegate classes.
103+
*
104+
* @params array $params The parameters.
105+
* @see Dataface_Table::getPermissions() for available parameters.
106+
*/
107+
public function getPermissions($params);
108+
}

0 commit comments

Comments
 (0)