Documentation (together with my other libs)
0001.
<?php
0002.
0003.
0004.
0005.
// --- INCLUDES --- //
0006.
require_once
dirname(
__FILE__
).
'/'
.
'inc.php4'
;
0007.
require_once
dirname(
__FILE__
).
'/'
.
'lib.cDBAccess_MySQL.php4'
;
0008.
// Event Logging
0009.
require_once
dirname(
__FILE__
).
'/'
.
'lib.cApp.php'
;
0010.
require_once
dirname(
__FILE__
).
'/'
.
'lib.cLog.php'
;
0011.
require_once
dirname(
__FILE__
).
'/'
.
'lib.cObjectPersistence_ColumnTypes.php'
;
0012.
0013.
0014.
0015.
// --- CONSTANTS --- //
0016.
0017.
// Column types
0018.
define(
'DWOP_TYPE_STR'
, 1);
0019.
define(
'DWOP_TYPE_NUM'
, 2);
0020.
define(
'DWOP_TYPE_REAL'
, 3);
0021.
define(
'DWOP_TYPE_BOOL'
, 4);
0022.
define(
'DWOP_TYPE_ENUM'
, 5);
0023.
define(
'DWOP_TYPE_SET'
, 6);
0024.
0025.
// Column flags
0026.
define(
'DWOP_NOT_NULL'
, 1);
0027.
define(
'DWOP_BINARY'
, 2);
0028.
//define('DWOP_BINARY', 2);
0029.
0030.
// For cDwOpClass::GetObjectMultiIdString()
0031.
define(
'DWOP_VALUE_DUMP_MODE__SQL'
, 0);
0032.
define(
'DWOP_VALUE_DUMP_MODE__SQL_SHORT'
, 2);
0033.
define(
'DWOP_VALUE_DUMP_MODE__SQL_VALUES'
, 3);
0034.
define(
'DWOP_VALUE_DUMP_MODE__ESCAPED_VALUES'
, 4);
0035.
define(
'DWOP_VALUE_DUMP_MODE__COMA'
, 5);
0036.
0037.
0038.
/** *********************************************************************************
0039.
<h1> RDBMS Object Loader for PHP </h1>
0040.
0041.
@version 2.4.6
0042.
@author Ondra Zizka, Dynawest; ondra@dynawest.cz
0043.
0044.
<h2>Plan:</h2>
0045.
3.0.0:
0046.
- Add: Complete cross-class references handling
0047.
2.x.x:
0048.
- Class::RemProperty() - handle removal of ID and KEY properties.
0049.
Class::aoIdProperties - rewrite so that GetIdProperties etc will compute from properties themselves. ??? Good idea???
0050.
0051.
<h2>History:</h2>
0052.
2.4.7:
0053.
- Fixed: cDwOpProperty::FormatForSql() returns correctly for DWOP_TYPE_REAL column types.
0054.
2.4.7:
0055.
- Added: DeleteObject() supports multi-property PRIMARY KEYS in it's second parameter
0056.
2.4.6:
0057.
- Added: Object Pool supports multi-property PRIMARY KEYS
0058.
2.4.5:
0059.
- Fixed: Fix in SaveObject() - now saves all properties that are set. Null values for NOT NULL columns converted to default.
0060.
- Added: function GetNonKeyProperties()
0061.
- Added: DeleteObject() now can take Class name and single ID as parameters.
0062.
- Added: cDwOpProperty now remembers it's PRIMARY KEY properties added through AddIdProperty() etc.
0063.
- Added: cDwOpProperty::IsKey()
0064.
- Changed: cDwOpColumnType::GetDefaultDefault() is not abstract returns a value according to basic column type.
0065.
- Fixed: DwFwIdAndProperties::HasProperty() now uses array_key_exists() instead of fucking isset().
0066.
2.4.4:
0067.
- Fixed: Massive fix in SaveObject() and one in DeleteObject()
0068.
- Added: param $sGlue to GetIdPropertiesSql($oObject, $sGlue=', ')
0069.
2.4.3:
0070.
- Added: Support for multi-property PRIMARY KEYs in SaveObject(), DeleteObject()
0071.
2.4.2:
0072.
- Added: DeleteObject($oObject);
0073.
- Added: GetIdPropertiesSql()
0074.
2.4.1:
0075.
- Added: param $bOverwrite to function AddObjectIntoPool( $oObject, $bOverwrite=true )
0076.
2.4.0:
0077.
- Added: M : N cross-class references
0078.
- Added: function SetMnRelation($oClass1, $oClassGlue, $oClass2)
0079.
- Added: function LoadObjectsByMnRelation($oObject, $oClassGlue, $oClass2, $xId=null)
0080.
0081.
- Added: Support for multi-property PRIMARY key - but only for keeping it, not for loading or saving
0082.
0083.
- Added: Real column types
0084.
(abstract class cDwOpColumnType_Real extends cDwOpColumnType) and derived classes)
0085.
- Added: Ordinal column types can take possible values definiton as they go from the DB:
0086.
"'value', 'value', ..."
0087.
- Added: Column types BIGINT and MEDIUMINT
0088.
0089.
Objects loading:
0090.
- Added: function LoadObjects($oClass)
0091.
- Added: function LoadObjectsBySql($xClass, $sSQL)
0092.
- Added: function LoadObjectsFromResult($xClass, $oRes)
0093.
0094.
Class related:
0095.
- Added: function ConvertAndCheckClass( $oClass )
0096.
- Added: function CreateClassCopy( $sName, $xClass )
0097.
- Added: function CreateClassByTable( $sName, $sTable )
0098.
- Added: function CreateColumnTypeObject($sTypeString, $bNull, $sDefault)
0099.
0100.
0101.
2.3.0:
0102.
- Added: CreateClassByTable()
0103.
Creates class definition according to a table in a database.
0104.
2.2.1:
0105.
- Added: LoadObjectsFromResult().
0106.
- Changed: LoadObjectsByValue() now uses LoadObjectsFromResult().
0107.
2.2.0:
0108.
- Added: Ordering by properties support.
0109.
GetOrderProperties(), SetOrderProperties()
0110.
2.1.0:
0111.
- Added: Default values, better checking.
0112.
GetDefault(), SetDefault(), GetDefaultDefault()
0113.
2.0.2:
0114.
- Added: Load* functions' first parameter can be also a class name string.
0115.
2.0.1:
0116.
- Added: GetPoolCount()
0117.
- Changed: SaveObject() adds UPDATEd (overwrite) and INSERTed objects into pool
0118.
2.0.0:
0119.
- Add central object registry - object is loaded only once,
0120.
then return the formerly loaded
0121.
1.1.0:
0122.
- Added support for AUTO_INCREMENT when creating objects.
0123.
- Added possibility to load objects by values.
0124.
***********************************************************************************/
0125.
class
cDwObjectPersistence_DB {
0126.
0127.
var
$oDB
= null;
0128.
function
&GetDB() {
return
$this
->oDB; }
0129.
0130.
var
$sError
= null;
0131.
function
GetError() {
return
$this
->sError; }
0132.
function
SetError(
$sError
){
$this
->sError =
$sError
; }
0133.
0134.
0135.
function
cDwObjectPersistence_DB(
$oDB
){
0136.
$this
->oDB =
$oDB
;
0137.
}
0138.
0139.
0140.
/**<***********************************************************************>
0141.
* Class objects dictionary *
0142.
***************************************************************************/
0143.
var
$aoClassesDictionary
= Array();
0144.
function
GetClassNames(){
return
array_keys
(
$this
->aoClassesDictionary); }
0145.
function
AddClassIntoDictionary(
$oClass
){
0146.
$this
->aoClassesDictionary[
$oClass
->GetName()] =
$oClass
;
0147.
}
0148.
function
GetClassFromDictionary(
$sClassName
){
0149.
return
isset(
$this
->aoClassesDictionary[
$sClassName
]) ?
$this
->aoClassesDictionary[
$sClassName
] : null;
0150.
}
0151.
0152.
0153.
/**<***********************************************************************>
0154.
* Objects pool *
0155.
***************************************************************************/
0156.
var
$aaoObjectPool
= Array();
0157.
0158.
function
AddObjectIntoPool(
$oObject
,
$bOverwrite
=true ){
0159.
if
( !
is_object
(
$oObject
) )
return
false;
0160.
$sClassName
= get_class(
$oObject
);
0161.
//App::Log("\$sClassName: ".$sClassName);///
0162.
if
( !
$oClass
=
$this
->GetClassFromDictionary(
$sClassName
) ){
return
false; }
0163.
0164.
// Get the object unique PRIMARY KEYs string
0165.
//App::Log("GetIdPropertiesCount(): ".$oClass->GetIdPropertiesCount());///
0166.
switch
(
$oClass
->GetIdPropertiesCount() ){
0167.
case
0:
$bUsePool
= false;
return
false;
break
;
0168.
case
1:
$xId
=
$oObject
->GetId();
break
;
0169.
default
:
$xId
=
$oClass
->GetObjectMultiIdString(
$oObject
, DWOP_VALUE_DUMP_MODE__SQL_VALUES );
break
;
0170.
}
0171.
//if( 0 == $oClass->GetIdPropertiesCount() ) return false;
0172.
//$xId = $oClass->GetObjectMultiIdString( $oObject, DWOP_VALUE_DUMP_MODE__SQL_VALUES );
0173.
0174.
// If we should not overwrite...
0175.
if
( !
$bOverwrite
){
0176.
// and the object exists, don't write and return true.
0177.
if
( isset(
$this
->aaoObjectPool[get_class(
$oObject
)][
$xId
] ) )
0178.
return
true;
0179.
}
0180.
0181.
// Save the object handle.
0182.
$this
->aaoObjectPool[get_class(
$oObject
)][
$xId
] =
$oObject
;
0183.
return
true;
0184.
}
0185.
0186.
function
AddObjectIntoPool_SingleId(
$oObject
,
$bOverwrite
=true ){
0187.
if
( !
is_object
(
$oObject
) )
return
false;
0188.
0189.
// If we should not overwrite...
0190.
if
( !
$bOverwrite
){
0191.
// and the object exists, don't write and return true.
0192.
if
( isset(
$this
->aaoObjectPool[get_class(
$oObject
)][
$oObject
->GetId()] ) )
0193.
return
true;
0194.
}
0195.
0196.
// Save the object handle.
0197.
$this
->aaoObjectPool[get_class(
$oObject
)][
$oObject
->GetId()] =
$oObject
;
0198.
return
true;
0199.
}
0200.
0201.
function
GetObjectFromPool(
$sClassName
,
$xId
){
0202.
$oObject
= null;
0203.
if
( isset(
$this
->aaoObjectPool[
$sClassName
][
$xId
]) ){
0204.
$oObject
=
$this
->aaoObjectPool[
$sClassName
][
$xId
];
0205.
//echo "<pre><strong>Pool hit!</strong></pre>";///
0206.
}
0207.
return
$oObject
;
0208.
}
0209.
0210.
0211.
function
RemObjectFromPool(
$oObject
){
0212.
if
( !
is_object
(
$oObject
) )
return
false;
0213.
// Get the Class object
0214.
$sClassName
= get_class(
$oObject
);
0215.
if
( !(
$oClass
=
$this
->GetClassFromDictionary(
$sClassName
)) ){
return
false; }
0216.
0217.
// Get the object unique PRIMARY KEYs string
0218.
//App::Log("GetIdPropertiesCount(): ".$oClass->GetIdPropertiesCount());///
0219.
switch
(
$oClass
->GetIdPropertiesCount() ){
0220.
case
0:
$bUsePool
= false;
return
false;
break
;
0221.
case
1:
$xId
=
$oObject
->GetId();
break
;
0222.
default
:
$xId
=
$oClass
->GetObjectMultiIdString(
$oObject
, DWOP_VALUE_DUMP_MODE__SQL_VALUES );
break
;
0223.
}
0224.
// Remove the object with the acquired ID
0225.
if
( isset(
$this
->aaoObjectPool[
$sClassName
][
$xId
] ) )
0226.
unset(
$this
->aaoObjectPool[
$sClassName
][
$xId
]);
0227.
return
true;
0228.
}
0229.
0230.
function
RemObjectFromPool_SingleId(
$oObject
){
0231.
if
( !
is_object
(
$oObject
) )
return
false;
0232.
$sClassName
= get_class(
$oObject
);
0233.
$xId
=
$oObject
->GetId();
0234.
if
( isset(
$this
->aaoObjectPool[
$sClassName
][
$xId
] ) )
0235.
unset(
$this
->aaoObjectPool[
$sClassName
][
$xId
]);
0236.
return
true;
0237.
}
0238.
0239.
0240.
function
HasObjectInPool(
$oObject
){
0241.
if
( !
is_object
(
$oObject
) )
return
false;
0242.
// Get the Class object
0243.
$sClassName
= get_class(
$oObject
);
0244.
if
( !(
$oClass
=
$this
->GetClassFromDictionary(
$sClassName
)) ){
return
false; }
0245.
0246.
// Get the object unique PRIMARY KEYs string
0247.
switch
(
$oClass
->GetIdPropertiesCount() ){
0248.
case
0:
$bUsePool
= false;
break
;
0249.
case
1:
$xId
=
$oObject
->GetId();
break
;
0250.
default
:
$xId
=
$oClass
->GetObjectMultiIdString(
$oObject
, DWOP_VALUE_DUMP_MODE__SQL_VALUES );
break
;
0251.
}
0252.
// $xId = $oObject->GetId();
0253.
0254.
$xId
=
$oClass
->GetObjectMultiIdString(
$oObject
, DWOP_VALUE_DUMP_MODE__SQL_VALUES );
0255.
0256.
if
( isset(
$this
->aaoObjectPool[get_class(
$oObject
)][
$xId
] ) )
0257.
return
true;
0258.
return
false;
0259.
}
0260.
0261.
function
HasObjectInPool_SingleId(
$oObject
){
0262.
if
( !
is_object
(
$oObject
) )
return
false;
0263.
$xId
=
$oObject
->GetId();
0264.
if
( isset(
$this
->aaoObjectPool[get_class(
$oObject
)][
$xId
] ) )
0265.
return
true;
0266.
return
false;
0267.
}
0268.
0269.
0270.
function
GetPoolCount(){
0271.
return
array_sum
(
array_map
(
'Count'
,
$this
->aaoObjectPool));
0272.
}
0273.
0274.
0275.
0276.
0277.
0278.
0279.
/**<***********************************************************************>
0280.
* Converts the class name to the DwOpClass object and checks the class. *
0281.
***************************************************************************/
0282.
function
ConvertAndCheckClass(
$oClass
){
0283.
0284.
// $oClass can be either cDwOpClass object or a class name
0285.
if
( !
$oClass
){
$this
->SetError(
"Bad param (null) \$oClass for "
.
__METHOD__
.
" in "
.CallInfo(-2));
return
false; }
0286.
0287.
// A string - try to find the Class in the Dictionary
0288.
if
(
is_string
(
$oClass
) ){
0289.
$sClassName
=
$oClass
;
0290.
$oClass
=
$this
->GetClassFromDictionary(
$sClassName
);
0291.
if
( !
is_object
(
$oClass
) ){
$this
->SetError(
"Class [$sClassName] not found in dictionary."
);
return
false; }
0292.
}
0293.
// Not a string - either the Class object or an object of some Class.
0294.
else
{
0295.
if
( !
is_object
(
$oClass
) ){
$this
->SetError(
"Bad param (not string or object) \$oClass for "
.
__METHOD__
.
" in "
.CallInfo(-2));
return
false; }
0296.
0297.
if
(
$oClass
instanceof cDwOpClass ){
0298.
$sClassName
=
$oClass
->GetName();
0299.
}
else
{
0300.
// object of some Class - try to find the Class object.
0301.
$sClassName
= get_class(
$oClass
);
0302.
$oClass
=
$this
->GetClassFromDictionary(
$sClassName
);
0303.
if
( !
is_object
(
$oClass
) ){
$this
->SetError(
"Object's Class [$sClassName] not found in dictionary."
);
return
false; }
0304.
}
0305.
}
0306.
0307.
// Check class existence
0308.
if
( !
class_exists
(
$sClassName
) ){
$this
->SetError(
"Non-existent PHP class [$sClassName]. in "
.
__METHOD__
.
" in "
.CallInfo(-2));
return
false; }
0309.
0310.
return
$oClass
;
0311.
}
0312.
0313.
0314.
/**<***********************************************************************>
0315.
* Deletes an object with ID $iID of the given class $oClass *
0316.
Deletes the given object from the DB.
0317.
***************************************************************************/
0318.
function
DeleteObject(
$oObject
,
$xId
=null){
0319.
//echo "<pre>\n class object: ".AdjustedPrintR($oClass)."</pre>";///
0320.
//if( !is_object( $oObject ) ) return false;
0321.
$bSucc
= false;
0322.
do
{
0323.
0324.
/*// Find the Class object in the Dictionary
0325.
$sClassName = get_class($oObject);
0326.
do{
0327.
$oClass = $this->GetClassFromDictionary($sClassName);
0328.
$sClassName = get_parent_class($sClassName);
0329.
}while( $sClassName && !$oClass );
0330.
0331.
// Check class object //
0332.
//if( !$oClass ){ $this->SetError("Class [$sClassName] not found in the dictionary in ".__METHOD__." @ ".__LINE__); break; }
0333.
/*/
0334.
if
( !(
$oClass
=
$this
->ConvertAndCheckClass(
$oObject
)) ){
$this
->SetError(
"!\$oClass in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
0335.
$sClassName
=
$oClass
->GetName();
0336.
/**/
0337.
0338.
// If $oObject is an instance of Class, get it's ID.
0339.
0340.
// If $oObject was just identification of a Class, create a temporary object with just IDs.
0341.
if
( !(
$oObject
instanceof
$sClassName
) ){
0342.
// Check the ID - false, null, or empty array? -> fail.
0343.
if
( !
$xId
){
$this
->SetError(
"Unknown object ID to delete in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
0344.
0345.
// If $xId is multiple ID - associative array of ids
0346.
if
(
is_array
(
$xId
) ){
0347.
$oObject
=
new
$sClassName
();
0348.
foreach
(
$xId
as
$k
=>
$v
)
0349.
$oObject
->SetProperty(
$k
,
$v
);
0350.
}
0351.
// Single ID
0352.
else
{
0353.
//$oObject = $this->LoadObjectById($oClass, $xId);
0354.
//if(!$oObject) { $this->SetError("!LoadObjectById(".$oClass->GetName().", $xId) in ".__METHOD__." @ ".__LINE__); break; }
0355.
$oObject
=
new
$sClassName
();
0356.
$oObject
->SetId(
$xId
);
0357.
}
0358.
}
0359.
0360.
// -- From here further, we have DwOpClass $oClass and it's (pseudo)instance $oObject. -- //
0361.
0362.
0363.
// Remove from the Object Pool
0364.
if
( !
$this
->RemObjectFromPool(
$oObject
) ){
$this
->SetError(
"!RemObjectFromPool() in "
.
__METHOD__
.
" @ "
.
__LINE__
); }
0365.
0366.
0367.
$sTable
=
$oClass
->GetTable();
0368.
0369.
/*/ For one ID (PRIMARY KEY) property only...
0370.
$oIdProp = $oClass->GetIdProperty();
0371.
$sColId = $oIdProp->GetColName();
0372.
$xId = $oIdProp->FormatForSql( $oObject->GetProperty($oIdProp->GetColName()) );
0373.
$sSQL = "DELETE FROM $sTable WHERE $sColId = $xId";
0374.
/*/
0375.
// For all PRIMARY KEYs:
0376.
$saxIdsCond
=
$oClass
->GetIdPropertiesSql(
$oObject
,
' AND '
);
0377.
$sSQL
=
"DELETE FROM $sTable WHERE $saxIdsCond"
;
0378.
/**/
0379.
0380.
// Perform SQL query
0381.
$oRes
=
$this
->GetDB()->Execute(
$sSQL
);
0382.
if
( !
$oRes
|| !
$oRes
->IsOK() ){
$this
->SetError(
"SQL error ["
.
$oRes
->GetError().
"] SQL: [$sSQL]"
);
break
; }
0383.
0384.
$bSucc
= true;
0385.
}
while
(false);
0386.
return
$bSucc
;
0387.
}
// cDwObjectPersistence_DB::DeleteObject()
0388.
0389.
0390.
/**<*********************************************************************************>
0391.
* Deletes objects of the given class $oClass
0392.
* with some property equal to the given value.
0393.
0394.
@param oClass: cDwOpClass object or a class name to find in dictionary.
0395.
@param sPropertyName: Name of the property to compare with $xVal.
0396.
@param xVal: Value to compare property with.
0397.
@returns array of objects with value $sPropertyName equal to $xVal.
0398.
*************************************************************************************/
0399.
function
DeleteObjectsByValueBad(
$oClass
,
$sPropertyName
,
$xVal
){
0400.
//echo "<pre>\n class object: ".AdjustedPrintR($oClass)."</pre>";///
0401.
0402.
if
( !(
$oClass
=
$this
->ConvertAndCheckClass(
$oClass
) ) )
return
false;
0403.
$sClassName
=
$oClass
->GetName();
0404.
0405.
0406.
// Get the property by which to recognize the object to load
0407.
$oProp
=
$oClass
->GetProperty(
$sPropertyName
);
0408.
if
( null ==
$oProp
){
$this
->SetError(
"No such property in class [$sClassName]: [$sPropertyName]"
);
return
false; }
0409.
0410.
// Create SQL query
0411.
$sTable
=
$oClass
->GetTable();
0412.
$sCol
=
$oProp
->GetColName();
0413.
$oIdProp
=
$oClass
->GetIdProperty();
0414.
$sColId
=
$oIdProp
->GetColName();
0415.
0416.
$sOrderSql
=
$oClass
->GetOrderPropertiesSql();
// ORDER BY part
0417.
$sSQL
=
"DELETE FROM $sTable WHERE $sCol = "
.
$oProp
->FormatForSql(
$xVal
).
" "
.
$sOrderSql
;
0418.
0419.
// Perform SQL query
0420.
$oRes
=
$this
->GetDB()->Execute(
$sSQL
);
0421.
if
( !
$oRes
|| !
$oRes
->IsOK() ){
$this
->SetError(
"SQL error ["
.
$oRes
->GetError().
"] SQL: [$sSQL] in "
.
__METHOD__
.
' @ '
.
__LINE__
);
return
false; }
0422.
0423.
// TODO: Remove objects from Object Pool!
0424.
$this
->RemObjectFromPool(
$oObject
);
0425.
0426.
return
true;
0427.
}
// LoadObjectsByValue($oClass, $sPropertyName, $xVal)
0428.
0429.
0430.
/**<***********************************************************************>
0431.
* Second version *
0432.
***************************************************************************/
0433.
function
DeleteObjectsByValue(
$oClass
,
$sPropertyName
,
$xVal
){
0434.
0435.
$aoObjects
=
$this
->LoadObjectsByValue(
$oClass
,
$sPropertyName
,
$xVal
);
0436.
if
(!
is_array
(
$aoObjects
))
return
false;
0437.
0438.
foreach
(
$aoObjects
as
$oObject
){
0439.
$this
->DeleteObject(
$oObject
);
0440.
}
0441.
0442.
return
true;
0443.
}
// LoadObjectsByValue($oClass, $sPropertyName, $xVal)
0444.
0445.
0446.
0447.
0448.
/**<***********************************************************************>
0449.
* Loads an object with ID $iID of the given class $oClass *
0450.
***************************************************************************/
0451.
function
LoadObjectById(
$oClass
,
$iID
){
0452.
//echo "<pre>\n class object: ".AdjustedPrintR($oClass)."</pre>";///
0453.
0454.
0455.
/*/ First parameter can be either cDwOpClass object or a class name
0456.
if( is_string($oClass) ){
0457.
$sClassName = $oClass;
0458.
$oClass = $this->GetClassFromDictionary($sClassName);
0459.
if( !$oClass ) return false;
0460.
}else{
0461.
$sClassName = $oClass->GetName();
0462.
}
0463.
// Check class existence
0464.
if( !class_exists($sClassName) )
0465.
return false;
0466.
/*/
0467.
if
( !(
$oClass
=
$this
->ConvertAndCheckClass(
$oClass
) ) )
return
false;
0468.
$sClassName
=
$oClass
->GetName();
/**/
0469.
0470.
0471.
// Look for the object in the pool
0472.
if
(
$oObject
=
$this
->GetObjectFromPool(
$sClassName
,
$iID
) )
0473.
return
$oObject
;
0474.
0475.
0476.
0477.
$sTable
=
$oClass
->GetTable();
0478.
$oIdProp
=
$oClass
->GetIdProperty();
0479.
$sColId
=
$oIdProp
->GetColName();
0480.
0481.
// Create and perform SQL query
0482.
$sSQL
=
"SELECT * FROM $sTable WHERE $sColId = "
.
$oIdProp
->FormatForSql(
$iID
);
0483.
$oRet
=
$this
->GetDB()->Select(
$sSQL
);
0484.
if
( !
$oRet
->IsOK() )
return
false;
0485.
if
( 0 ==
$oRet
->NumRows() )
return
null;
0486.
0487.
$aData
=
$oRet
->FetchRow(MYSQL_ASSOC);
0488.
0489.
// Create the object
0490.
$oObject
=
new
$sClassName
();
0491.
0492.
// Load all declared properties
0493.
foreach
(
$oClass
->GetProperties()
as
$oProperty
){
0494.
//echo "<div>\$oObject->SetProperty( ".$oProperty->GetColName().", \$aData[".$oProperty->GetColName()."] );</div>";///
0495.
$oObject
->SetProperty(
$oProperty
->GetColName(),
$oProperty
->GetColType()->ConvertFromResult(
$aData
[
$oProperty
->GetColName()] ) );
0496.
}
0497.
0498.
$this
->AddObjectIntoPool(
$oObject
);
0499.
return
$oObject
;
0500.
}
// LoadObjectById($oClass, $iID)
0501.
0502.
0503.
0504.
0505.
0506.
/**<***********************************************************************************>
0507.
* Loads all objects of the given class $oClass.
0508.
0509.
@param oClass: cDwOpClass object or a class name to find in dictionary.
0510.
@returns array of objects of the specified class.
0511.
***************************************************************************************/
0512.
function
LoadObjects(
$oClass
){
0513.
0514.
/*/ First parameter can be either cDwOpClass object or a class name
0515.
if( is_string($oClass) ){
0516.
$sClassName = $oClass;
0517.
$oClass = $this->GetClassFromDictionary($sClassName);
0518.
if( !is_object($oClass) ){ $this->SetError("Class [$sClassName] not found in dictionary."); return false; }
0519.
}else{
0520.
$sClassName = $oClass->GetName();
0521.
}
0522.
0523.
// Check class existence
0524.
if( !class_exists($sClassName) ){ $this->SetError("Non-existent class [$sClassName]."); return false; }
0525.
/*/
0526.
if
( !(
$oClass
=
$this
->ConvertAndCheckClass(
$oClass
) ) )
return
false;
0527.
$sClassName
=
$oClass
->GetName();
/**/
0528.
0529.
0530.
// Create SQL query
0531.
$sTable
=
$oClass
->GetTable();
0532.
$sOrderSql
=
$oClass
->GetOrderPropertiesSql();
// ORDER BY part
0533.
$sSQL
=
"SELECT * FROM $sTable "
.
$sOrderSql
;
0534.
0535.
// Perform SQL query
0536.
$oRes
=
$this
->GetDB()->Select(
$sSQL
);
0537.
if
( !
$oRes
|| !
$oRes
->IsOK() ){
0538.
$this
->SetError(
"SQL error ["
.
$oRes
->GetError().
"] SQL: [$sSQL]"
);
0539.
return
false;
0540.
}
0541.
0542.
// Load Objects
0543.
$aoObjects
=
$this
->LoadObjectsFromResult(
$oClass
,
$oRes
);
0544.
$oRes
->FreeResult();
0545.
0546.
return
$aoObjects
;
0547.
0548.
}
// cDwObjectPersistence_DB::LoadObjects()
0549.
0550.
0551.
0552.
/**<*********************************************************************************>
0553.
* Loads an objects of the given class $oClass
0554.
* with some property equal to the given value.
0555.
0556.
@param oClass: cDwOpClass object or a class name to find in dictionary.
0557.
@param sPropertyName: Name of the property to compare with $xVal.
0558.
@param xVal: Value to compare property with.
0559.
@returns array of objects with value $sPropertyName equal to $xVal.
0560.
*************************************************************************************/
0561.
function
LoadObjectsByValue(
$oClass
,
$sPropertyName
,
$xVal
){
0562.
//echo "<pre>\n class object: ".AdjustedPrintR($oClass)."</pre>";///
0563.
0564.
0565.
/*/ First parameter can be either cDwOpClass object or a class name
0566.
if( is_string($oClass) ){
0567.
$sClassName = $oClass;
0568.
$oClass = $this->GetClassFromDictionary($sClassName);
0569.
if( !is_object($oClass) ){
0570.
$this->SetError("Class [$sClassName] not found in dictionary.");
0571.
return false;
0572.
}
0573.
}else{
0574.
$sClassName = $oClass->GetName();
0575.
}
0576.
0577.
// Check class existence
0578.
if( !class_exists($sClassName) ){ $this->SetError("Non-existent class [$sClassName]."); return false; }
0579.
/*/
0580.
if
( !(
$oClass
=
$this
->ConvertAndCheckClass(
$oClass
) ) )
return
false;
0581.
$sClassName
=
$oClass
->GetName();
/**/
0582.
0583.
0584.
// Get the property by which to recognize the object to load
0585.
$oProp
=
$oClass
->GetProperty(
$sPropertyName
);
0586.
if
( null ==
$oProp
){
0587.
$this
->SetError(
"No such property in class [$sClassName]: [$sPropertyName]"
);
0588.
return
false;
0589.
}
0590.
0591.
// Create SQL query
0592.
$sTable
=
$oClass
->GetTable();
0593.
$sCol
=
$oProp
->GetColName();
0594.
$oIdProp
=
$oClass
->GetIdProperty();
0595.
$sColId
=
$oIdProp
->GetColName();
0596.
0597.
$sOrderSql
=
$oClass
->GetOrderPropertiesSql();
// ORDER BY part
0598.
$sSQL
=
"SELECT * FROM $sTable WHERE $sCol = "
.
$oProp
->FormatForSql(
$xVal
).
" "
.
$sOrderSql
;
0599.
0600.
/*// Perform SQL query
0601.
$oRes = $this->GetDB()->Select($sSQL);
0602.
if( !$oRes || !$oRes->IsOK() ){
0603.
$this->SetError("SQL error [".$oRes->GetError()."] SQL: [$sSQL]");
0604.
return false;
0605.
}
0606.
0607.
// Load Objects
0608.
$aoObjects = $this->LoadObjectsFromResult($oClass, $oRes);
0609.
$oRes->FreeResult();/*/
0610.
0611.
$aoObjects
=
$this
->LoadObjectsBySql(
$oClass
,
$sSQL
);
/**/
0612.
0613.
return
$aoObjects
;
0614.
}
// LoadObjectsByValue($oClass, $sPropertyName, $xVal)
0615.
0616.
0617.
0618.
0619.
0620.
/**<*********************************************************************************>
0621.
* Performs SQL query and converts the result to an array of objects. *
0622.
*************************************************************************************/
0623.
function
LoadObjectsBySql(
$xClass
,
$sSQL
){
0624.
0625.
// Perform SQL query
0626.
$oRes
=
$this
->GetDB()->Select(
$sSQL
);
0627.
if
( !
$oRes
|| !
$oRes
->IsOK() ){
0628.
$this
->SetError(
"SQL error ["
.
$oRes
->GetError().
"] SQL: [$sSQL]"
);
0629.
return
false;
0630.
}
0631.
0632.
// Load Objects
0633.
$aoObjects
=
$this
->LoadObjectsFromResult(
$xClass
,
$oRes
);
0634.
$oRes
->FreeResult();
0635.
0636.
return
$aoObjects
;
0637.
}
0638.
0639.
0640.
0641.
/**<*********************************************************************************>
0642.
* Converts the result to an array of objects. *
0643.
*************************************************************************************/
0644.
function
LoadObjectsFromResult(
$xClass
,
$oRes
){
0645.
0646.
// Convert and check the class
0647.
if
( !(
$oClass
=
$this
->ConvertAndCheckClass(
$xClass
) ) ){
0648.
$this
->SetError(
"!ConvertAndCheckClass("
.
gettype
(
$xClass
).
"): "
.
$this
->GetError());
return
false;
0649.
}
0650.
$sClassName
=
$oClass
->GetName();
0651.
0652.
0653.
$aoObjects
= Array();
0654.
//if( 0 == $oRes->NumRows() ) return $aoObjects;
0655.
0656.
// Class Name
0657.
//if( !is_object($oClass) ) echo CallInfo(-2);
0658.
0659.
0660.
0661.
$aoPropertiesToTraverse
= Array();
0662.
// Get the list of the properties that will be set from the result.
0663.
// Check column existence for all declared properties
0664.
$aoFields
=
$oRes
->GetColumns();
0665.
$absFieldsContained
= Array();
0666.
foreach
(
$aoFields
as
$oField
){
$absFieldsContained
[
$oField
->name] = 1; }
0667.
//App::Log("\$absFieldsContained: ".AdjustedPrintR($absFieldsContained));///
0668.
foreach
(
$oClass
->GetProperties()
as
$oProperty
){
0669.
$sColName
=
$oProperty
->GetColName();
0670.
if
( !
array_key_exists
(
$sColName
,
$absFieldsContained
) ){
0671.
$this
->SetError(
"Warn: Column [$sColName] for property ["
.
$oProperty
->GetName().
"] is not set; in "
.
__METHOD__
.
" in "
.CallInfo(-2));
0672.
App::Log(
"Warn: Column [$sColName] for property ["
.
$oProperty
->GetName().
"] is not set; in "
.
__METHOD__
);
continue
;
0673.
}
0674.
$aoPropertiesToTraverse
[] =
$oProperty
;
0675.
}
/**/
0676.
0677.
// Create the objects. For each row:
0678.
while
(
$aData
=
$oRes
->FetchRow(MYSQL_ASSOC) ){
0679.
$oObject
=
new
$sClassName
();
0680.
/*// Load all declared properties
0681.
foreach( $oClass->GetProperties() as $oProperty ){
0682.
//echo "<div>\$oObject->SetProperty( ".$oProperty->GetColName().", \$aData[".$oProperty->GetColName()."] );</div>";///
0683.
$sColName = $oProperty->GetColName();
0684.
//if( !isset( $aData[$sColName] ) && !is_null($aData[$sColName]) ){
0685.
if( !array_key_exists($sColName, $aData) ){
0686.
App::Log("Warn: Column [$sColName] for property [".$oProperty->GetName()."] is not set."); continue;
0687.
} // DONE: Move before the while - fetch_fields()
0688.
$oObject->SetProperty( $oProperty->GetColName(), $aData[$sColName] );
0689.
}/**/
0690.
// Load properties that are present in the result
0691.
foreach
(
$aoPropertiesToTraverse
as
$oProperty
){
0692.
//echo "<div>\$oObject->SetProperty( ".$oProperty->GetColName().", \$aData[".$oProperty->GetColName()."] );</div>";///
0693.
$sColName
=
$oProperty
->GetColName();
0694.
$oObject
->SetProperty(
$sColName
,
$oProperty
->GetColType()->ConvertFromResult(
$aData
[
$sColName
]) );
0695.
}
0696.
0697.
// Get object's unique ID, if possible
0698.
$bUsePool
= true;
0699.
//App::Log("GetIdPropertiesCount(): ".$oClass->GetIdPropertiesCount());///
0700.
switch
(
$oClass
->GetIdPropertiesCount() ){
0701.
case
0:
$bUsePool
= false;
break
;
0702.
case
1:
$xId
=
$oObject
->GetId();
break
;
0703.
default
:
$xId
=
$oClass
->GetObjectMultiIdString(
$oObject
, DWOP_VALUE_DUMP_MODE__SQL_VALUES );
break
;
0704.
}
0705.
0706.
// Look for the object in the pool
0707.
if
(!
$bUsePool
)
0708.
$aoObjects
[] =
$oObject
;
0709.
else
0710.
if
(
$oObjectFromPool
=
$this
->GetObjectFromPool(
$sClassName
,
$xId
) ){
0711.
//App::Log("Pool hit [$sClassName, ".$xId."]");///
0712.
$aoObjects
[] =
$oObjectFromPool
;
0713.
}
else
{
0714.
//App::Log("Pool miss [$sClassName, ".$xId."]");///
0715.
$aoObjects
[] =
$oObject
;
0716.
$this
->AddObjectIntoPool(
$oObject
);
0717.
}
0718.
0719.
}
// while( for each row in result )
0720.
0721.
return
$aoObjects
;
0722.
0723.
}
// cDwObjectPersistence::LoadObjectsFromResult($oClass, $oRes)
0724.
0725.
0726.
0727.
0728.
/**<***********************************************************************>
0729.
* Saves an object with ID $iID of the given class $oClass *
0730.
***************************************************************************/
0731.
function
SaveObject(
$oObject
){
0732.
//echo "<pre>\n class object: ".AdjustedPrintR($oClass)."</pre>";///
0733.
//App::Log("Object: ".AdjustedPrintR($oObject));///
0734.
if
( !
is_object
(
$oObject
) )
return
false;
0735.
0736.
0737.
// Whether to try UPDATE first before INSERT
0738.
$bDoUpdate
= true;
0739.
$bZeroUpdatedRows
= false;
0740.
0741.
0742.
// Add this Class object into the dictionary
0743.
0744.
// Get the Class object - for this PHP class or some ancestor class
0745.
$sClassName
= get_class(
$oObject
);
0746.
do
{
0747.
$oClass
=
$this
->GetClassFromDictionary(
$sClassName
);
0748.
$sClassName
= get_parent_class(
$sClassName
);
0749.
}
while
(
$sClassName
&& !
$oClass
);
0750.
0751.
// Check class object //
0752.
if
( !
$oClass
)
0753.
return
false;
0754.
0755.
$sTable
=
$oClass
->GetTable();
0756.
0757.
0758.
0759.
/// --- PRIMARY KEYS --- ///
0760.
0761.
0762.
/*/ For one ID (PRIMARY KEY) property only...
0763.
$oIdProp = $oClass->GetIdProperty(); //x Single-ID way
0764.
$sColId = $oIdProp->GetColName(); //x Single-ID way
0765.
$iID = $oObject->GetProperty( $oIdProp->GetColName() );
0766.
$sIdForSql = $oIdProp->FormatForSql($iID); //x Single-ID way
0767.
/*/
0768.
// For all PRIMARY KEYs:
0769.
$saxIds
=
$oClass
->GetIdPropertiesSql(
$oObject
);
0770.
$saxIdsCond
=
$oClass
->GetIdPropertiesSql(
$oObject
,
' AND '
);
0771.
/**/
0772.
0773.
0774.
0775.
0776.
0777.
/// --- VALUES --- ///
0778.
0779.
0780.
// Store all declared properties - create the SQL part
0781.
$asSqlParts
= Array();
0782.
$aoIdProps
=
$oClass
->GetIdProperties();
0783.
foreach
(
$oClass
->GetProperties()
as
$oProperty
){
0784.
//echo "<div>\$oObject->GetProperty( ".$oProperty->GetColName()." );</div>";///
0785.
$bPropertySet
=
$oObject
->HasProperty(
$oProperty
->GetName() );
0786.
//App::Log("HasProperty(".$oProperty->GetName().") ? : ".(int)$oObject->HasProperty($oProperty->GetName()) );///
0787.
0788.
0789.
// Check whether PRIMARY KEY properties are set and skip them.
0790.
//if( $oProperty == $oIdProp ) continue;
0791.
//if( $oProperty->IsIdProperty() ) continue;
0792.
if
( in_array(
$oProperty
,
$aoIdProps
) ){
0793.
// Multi-property PRIMARY key and some is not set -> error
0794.
if
( !
$bPropertySet
&& 1 <
Count
(
$aoIdProps
) ){
0795.
$this
->SetError(
"Multi-property PRIMARY - property ["
.
$oProperty
->GetName().
"] not set! in "
.
__METHOD__
.
" @ "
.
__LINE__
);
0796.
//App::Log("Error!");///
0797.
return
false;
0798.
}
0799.
// Skip ID column(s) - we don't want to set them as other properties
0800.
//App::Log("Skipping ID col [".$oProperty->GetName()."]");///
0801.
continue
;
0802.
}
0803.
0804.
// Skip undefined properties - or set them to DEFAULT ??? -> TODO
0805.
if
( !
$bPropertySet
){
0806.
//$xVal = $oProperty->GetDefault();
0807.
continue
;
0808.
}
0809.
0810.
//App::Log("Adding col [".$oProperty->GetName()."]");///
0811.
$sPropColName
=
$oProperty
->GetColName();
0812.
$xVal
=
$oObject
->GetProperty(
$sPropColName
);
0813.
//if( $sPropColName == 'targeting_fee' ) App::Log("FDG: (".gettype($xVal).") $xVal, ".AdjustedPrintR($oProperty));///
0814.
if
( null ===
$xVal
&& !
$oProperty
->GetColType()->IsNull() )
0815.
$xVal
=
$oProperty
->GetColType()->GetDefault();
0816.
$asSqlParts
[] =
$sPropColName
.
'='
.
$oProperty
->FormatForSql(
$xVal
);
0817.
}
0818.
$saParts
= implode(
', '
,
$asSqlParts
);
0819.
//App::Log("\$saParts: ".$saParts);///
0820.
0821.
// Multiple KEY and nothing set - error (we do not INSERT unset multi-column rows )
0822.
// So other way: Don't try UPDATE if no other property set.
0823.
if
( 0 ==
Count
(
$asSqlParts
) && 1 <
Count
(
$aoIdProps
) ){
0824.
//$this->SetError("Multiple KEY and no normal properties set. in ".__METHOD__." @ ".__LINE__);); return false;
0825.
$bDoUpdate
= false;
0826.
$bZeroUpdatedRows
= true;
0827.
}
0828.
0829.
0830.
0831.
0832.
// Whether to add the object into the Object Pool.
0833.
// Generally, add if the object was created; don't overwrite we are only saving existing object.
0834.
$bAddObjectIntoPool
= true;
0835.
$bOverwriteObjectInPool
= false;
0836.
0837.
// If we are saving single-prop PRIMARY KEYed object and it is set to null, we should inser new.
0838.
//App::Log("ID: (".gettype($oObject->GetId()).") ".$oObject->GetId());///
0839.
if
( 1 ==
$oClass
->GetIdPropertiesCount() && (null ===
$oObject
->GetId()) ){
0840.
$bDoUpdate
= false;
0841.
}
0842.
0843.
// Multi-property PRIMARY key and some is not set -> error
0844.
//if( 1 < $oClass->GetIdPropertiesCount() ){ } // Done above
0845.
0846.
// UPDATE
0847.
//if( null !== $oObject->GetId() )
0848.
if
(
$bDoUpdate
){
0849.
// Create SQL query
0850.
//$sSQL = "UPDATE $sTable SET %s WHERE $sColId = ".$sIdForSql; //x Single-ID way
0851.
$sSQL
=
"UPDATE $sTable SET %s WHERE $saxIdsCond"
;
0852.
$sSQL
= sprintf(
$sSQL
,
$saParts
);
0853.
//echo "<div>$sSQL</div>";///
0854.
0855.
// Perform SQL query
0856.
$oRet
=
$this
->GetDB()->Execute(
$sSQL
);
0857.
//echo $oRet->GetError();///
0858.
if
( !(
$oRet
->IsOK()) ){
$this
->SetError(
$oRet
->GetError());
return
false; }
0859.
if
( 0 <
$oRet
->NumRows() ){
0860.
$this
->AddObjectIntoPool(
$oObject
);
0861.
return
true;
0862.
}
0863.
$bZeroUpdatedRows
= true;
0864.
/*// If commented, tries to INSERT. If not, checks here for the row existence first.
0865.
// No rows affected - did we UPDATE with no changes, or the row was not found?
0866.
$sSQL = "SELECT COUNT(*) FROM $sTable WHERE $sColId = ".$sIdForSql;
0867.
//$oRet = $this->GetDB()->Execute($sSQL);
0868.
//if( !($oRet->IsOK()) ){ $this->SetError($oRet->GetError()); return false; }
0869.
//if( 0 != $oRet->GetCell(0,0) ){
0870.
$sVal = $oRet->SelectCell($sSQL, 0,0);
0871.
if( null === $sVal ){ $this->SetError("Error in SelectCell: [$sSQL]"); return false; }
0872.
if( 0 != $oRet->GetCell(0,0) ){
0873.
$this->AddObjectIntoPool( $oObject );
0874.
return true;
0875.
}/**/
0876.
}
0877.
0878.
// Row with ID not found or object ID is NULL -> INSERT
0879.
do
{
0880.
//$sSQL = "INSERT INTO $sTable SET $sColId = $sIdForSql, ".$saParts;
0881.
$sSQL
=
"INSERT INTO $sTable SET $saxIds "
;
0882.
if
(
$saParts
)
$sSQL
.=
", "
.
$saParts
;
0883.
//echo "<div>$sSQL</div>";///
0884.
0885.
0886.
// Perform SQL query
0887.
//echo "\nSelectMode: ".(int)$this->GetDB()->GetSelectMode();///
0888.
$oRet
=
$this
->GetDB()->Execute(
$sSQL
);
0889.
0890.
// If we did UPDATE with no changes,
0891.
if
(
$bZeroUpdatedRows
){
0892.
// And this insert caused error 1062, then it's OK - the row just existed before.
0893.
if
( !
$oRet
|| (!
$oRet
->IsOK() &&
$oRet
->GetErrno() == 1062 ) ){
0894.
break
;
0895.
}
0896.
}
0897.
/*/ Other way:
0898.
// If INSERT caused an error:
0899.
if( !$oRet || !$oRet->IsOK() ){
0900.
// If we did not UPDATE with no changes OR the error is DUPLICATE ENTRY
0901.
if(!$bZeroUpdatedRows || ( !$oRet || $oRet->GetErrno() == 1062 ) )
0902.
$this->SetError("INSERT failed. ".($oRet ? '['.$oRet->GetError().']' : '')); return false;
0903.
}/* Too complex */
0904.
if
( 0 ==
$oRet
->NumRows() ){
$this
->SetError(
"INSERT affected no rows. SQL: ["
.
$sSQL
.
"] Errno: "
.
$oRet
->GetErrno());
return
false; }
0905.
$oObject
->SetId(
$this
->GetDB()->GetLastInsertId() );
0906.
0907.
// We created a new object, thus if any of the same ID is in the pool, overwrite.
0908.
$bOverwriteObjectInPool
= true;
0909.
0910.
}
while
(false);
0911.
0912.
// If asked, put object into the bool. If already there, it's overwritten.
0913.
if
(
$bAddObjectIntoPool
)
0914.
$this
->AddObjectIntoPool(
$oObject
,
$bOverwriteObjectInPool
);
0915.
return
true;
0916.
0917.
}
// LoadObjectById($oClass, $iID)
0918.
0919.
0920.
0921.
0922.
0923.
/**<***********************************************************************>
0924.
* Creates a cDwOpClass object copy. *
0925.
***************************************************************************/
0926.
function
CreateClassCopy(
$sName
,
$xClass
){
0927.
0928.
// The second parameter can be either cDwOpClass object or a class name
0929.
if
(
is_string
(
$xClass
) ){
0930.
$sClassName
=
$xClass
;
0931.
$xClass
=
$this
->GetClassFromDictionary(
$sClassName
);
0932.
if
( !
is_object
(
$xClass
) ){
0933.
$this
->SetError(
"Class [$sClassName] not found in dictionary."
);
0934.
return
false;
0935.
}
0936.
}
else
{
0937.
$sClassName
=
$xClass
->GetName();
0938.
}
0939.
0940.
// Make a copy
0941.
$oClass
= clone
$xClass
;
0942.
$oClass
->SetName(
$sName
);
0943.
$this
->AddClassIntoDictionary(
$oClass
);
0944.
return
$oClass
;
0945.
}
0946.
0947.
0948.
/**<***********************************************************************>
0949.
* Creates a cDwOpClass using it's definition from database. *
0950.
***************************************************************************/
0951.
function
CreateClassByTable(
$sName
,
$sTable
){
0952.
0953.
do
{
0954.
$oClass
=
new
cDwOpClass(
$sName
,
$sTable
);
0955.
0956.
// Load columns info
0957.
$sSQL
=
"SHOW COLUMNS FROM $sTable"
;
0958.
$oRes
=
$this
->GetDB()->Select(
$sSQL
);
0959.
if
( !
$oRes
|| !
$oRes
->IsOK() ){
$this
->SetError(
"SQL error ["
.
$oRes
->GetError().
"] SQL: [$sSQL]"
);
return
null; }
0960.
0961.
// For each row (which represent columns in the table)
0962.
while
(
$a
=
$oRes
->FetchRow(MYSQL_ASSOC) ){
0963.
$oColObject
=
$this
->CreateColumnTypeObject(
$a
[
'Type'
],
$a
[
'Null'
]==
'YES'
,
$a
[
'Default'
] );
0964.
if
( null ===
$oColObject
){
0965.
$this
->SetError(
"Table column [$sTable."
.
$a
[
'Field'
].
"]: "
.
$this
->GetError().
" in "
.
__METHOD__
.
" @ "
.
__LINE__
);
0966.
//App::Log($this->GetError());///
0967.
$oClass
= null;
break
;
0968.
}
0969.
$oProp
=
$oClass
->AddProperty(
$a
[
'Field'
],
$oColObject
);
0970.
$oProp
->SetNull(
$a
[
'Null'
]==
'YES'
);
0971.
0972.
if
(
'PRI'
==
$a
[
'Key'
] ){
$oClass
->AddIdProperty(
$oProp
); }
0973.
0974.
$oProp
->SetUnique(
'PRI'
==
$a
[
'Key'
] ||
'UNI'
==
$a
[
'Key'
] );
0975.
}
0976.
$oRes
->FreeResult();
0977.
0978.
if
(
$oClass
)
0979.
$this
->AddClassIntoDictionary(
$oClass
);
0980.
0981.
}
while
(false);
0982.
return
$oClass
;
0983.
}
0984.
0985.
0986.
//$oClass = $oOP->ExtendClassByTable('cAdplazeAdPage_Coupon', 'cAdplazeAdPage', 'ap_adpages_coupons');/**/
0987.
/**<***********************************************************************>
0988.
* Extends an existings cDwOpClass with columns from a table. *
0989.
***************************************************************************/
0990.
function
ExtendClassByTable(
$sClassNameNew
,
$sClassNameOld
,
$sTable
){
0991.
0992.
// Old Class object
0993.
$oClassOld
=
$this
->ConvertAndCheckClass(
$sClassNameOld
);
0994.
if
(!
$oClassOld
){
$this
->SetError(
"!ConvertAndCheckClass($sClassNameOld)"
);
return
null; }
0995.
$sClassNameOld
=
$oClassOld
->GetName();
0996.
$aoOldIdProps
=
$oClassOld
->GetIdProperties();
0997.
0998.
//$oClass = $this->CreateClassCopy($sClassNameNew, $sClassNameOld);
0999.
//$oClass = $this->CreateClassByTable($sClassNameNew, $sTable);
1000.
$oClass
=
new
cDwOpClass(
$sClassNameNew
,
$sTable
);
1001.
$oClass
->_SetParentClass(
$oClassOld
);
1002.
1003.
// Load columns info
1004.
$sSQL
=
"SHOW COLUMNS FROM $sTable"
;
1005.
$oRes
=
$this
->GetDB()->Select(
$sSQL
);
1006.
if
( !
$oRes
|| !
$oRes
->IsOK() ){
$this
->SetError(
"SQL error ["
.
$oRes
->GetError().
"] SQL: [$sSQL]"
);
return
null; }
1007.
1008.
// --- Add the Properties to the Class --- //
1009.
1010.
// Temp array to store matched id properties //
1011.
$aoMatchedIdProps
= Array();
1012.
1013.
// For each row (which represent columns in the table)
1014.
while
(
$a
=
$oRes
->FetchRow(MYSQL_ASSOC) ){
1015.
$oColObject
=
$this
->CreateColumnTypeObject(
$a
[
'Type'
],
$a
[
'Null'
]==
'YES'
,
$a
[
'Default'
] );
1016.
if
( null ===
$oColObject
){
1017.
$this
->SetError(
"Table column [$sTable."
.
$a
[
'Field'
].
"]: "
.
$this
->GetError().
" in "
.
__METHOD__
.
" @ "
.
__LINE__
);
1018.
$oClass
= null;
break
;
1019.
}
1020.
$oProp
=
$oClass
->AddProperty(
$a
[
'Field'
],
$oColObject
);
1021.
$oProp
->SetNull(
$a
[
'Null'
]==
'YES'
);
1022.
1023.
// ID property
1024.
if
(
'PRI'
==
$a
[
'Key'
] ){
1025.
// Check whether the old Class has the same ID Property
1026.
if
( !
$oClassOld
->HasIdProperty(
$oProp
->GetName()) ){
1027.
$this
->SetError(
"Table column [$sTable."
.
$a
[
'Field'
].
"]: Extended Class [$sClassNameOld] doesn't have the ID column ["
.
$oProp
->GetName().
"] in "
.
__METHOD__
.
" @ "
.
__LINE__
);
1028.
$oClass
= null;
break
;
1029.
}
1030.
$oClass
->AddIdProperty(
$oProp
);
// To se tam dostane z CreateClassByTable()
1031.
// Add this old Class' Property to the list of matched ID Properties
1032.
$oOldClass_IdProp
=
$oClassOld
->GetProperty(
$oProp
->GetName());
1033.
$aoMatchedIdProps
[] =
$oOldClass_IdProp
;
1034.
}
1035.
1036.
$oProp
->SetUnique(
'PRI'
==
$a
[
'Key'
] ||
'UNI'
==
$a
[
'Key'
] );
1037.
}
1038.
$oRes
->FreeResult();
1039.
1040.
// Check whether all ID Properties of old Class were matched
1041.
foreach
(
$oClassOld
->GetIdProperties()
as
$oOldClass_IdProp
){
1042.
if
( !in_array(
$oOldClass_IdProp
,
$aoMatchedIdProps
) ){
1043.
$this
->SetError(
"Extended Class [$sClassNameOld] doesn't have the ID column ["
.
$oOldClass_IdProp
->GetName().
"] in "
.
__METHOD__
.
" @ "
.
__LINE__
);
1044.
$oClass
= null;
break
;
1045.
}
1046.
}
1047.
1048.
if
(
$oClass
)
$this
->AddClassIntoDictionary(
$oClass
);
1049.
return
$oClass
;
1050.
1051.
}
// cDwObjectPersistence::ExtendClassByTable()
1052.
1053.
1054.
1055.
/**<**********************************************************************************>
1056.
* Returns cDwOpColumnType object according to the definition in $sTypeString. *
1057.
**************************************************************************************/
1058.
function
CreateColumnTypeObject(
$sTypeString
,
$bNull
,
$sDefault
){
1059.
$oRet
= null;
1060.
1061.
//$sTypeName = substr( $sTypeString, 0, strpos($sTypeString, '(') );
1062.
//if( !ereg( '(.*)(\\((.*)\\))?(.*)?', $sTypeString, $asParts ) ) return $oRet;
1063.
//$asParts = array_map('strtoupper', array_map('trim', $asParts) );
1064.
//echo "<pre>\$asParts: ".AdjustedPrintR($asParts)."</pre>";///
1065.
// list($sTypeName, $sData, $sUnsigned) = $asParts;
1066.
$sTypeName
=
strtoupper
(trim(
strtok
(
$sTypeString
,
'('
) ));
1067.
$sData
= (trim(
strtok
(
')'
) ));
1068.
$sUnsigned
=
strtoupper
(trim(
strtok
(
''
) ));
1069.
//echo "<pre>$sTypeName, $sData, $sUnsigned</pre>";///
1070.
1071.
$sClassName
=
'cDwOpColumnType_'
;
1072.
1073.
/*switch($sTypeName){
1074.
case 'VARCHAR':
1075.
case '': $sClassName = '_'.$sTypeName; break;
1076.
}/**/
1077.
1078.
$saImplementedColumnTypes
= DWOP_IMPLEMENTED_COLUMN_TYPES;
1079.
$asImplementedTypes
=
array_map
(
'trim'
,
explode
(
','
,
$saImplementedColumnTypes
));
1080.
if
( !in_array(
$sTypeName
,
$asImplementedTypes
) ){
$this
->SetError(
"Column type [$sTypeName] not implemented."
);
return
null; }
1081.
1082.
$sClassName
.=
$sTypeName
;
1083.
1084.
if
(
$sUnsigned
==
'UNSIGNED'
)
1085.
$sClassName
.=
'_UNSIGNED'
;
1086.
1087.
if
(!
class_exists
(
$sClassName
)){
$this
->SetError(
"Undefined column class [$sClassName]."
);
return
null; }
1088.
1089.
switch
(
$sTypeName
){
1090.
case
'ENUM'
:
case
'SET'
:
1091.
$oRet
=
new
$sClassName
(
$sData
);
break
;
1092.
case
'CHAR'
:
case
'VARCHAR'
:
1093.
$oRet
=
new
$sClassName
((int)
$sData
);
break
;
1094.
default
:
1095.
$oRet
=
new
$sClassName
();
break
;
1096.
}
1097.
if
(
$oRet
){
1098.
$oRet
->SetDefault(
$sDefault
);
1099.
$oRet
->SetNull(
$bNull
);
1100.
}
1101.
1102.
1103.
return
$oRet
;
1104.
1105.
}
// cDwObjectPersistence::CreateColumnTypeObject()
1106.
1107.
1108.
/**<***********************************************************************>
1109.
* Sets M : N relation between two classes using third class as a glue. *
1110.
***************************************************************************/
1111.
function
SetMnRelation(
$oClass1
,
$oClassGlue
,
$oClass2
){
1112.
$bSucc
= false;
1113.
do
{
1114.
1115.
// Convert class names to Class objects and check the existence of the class.
1116.
if
( !(
$oClass1
=
$this
->ConvertAndCheckClass(
$oClass1
)) ){
$this
->SetError(
"!oClass1 in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
1117.
if
( !(
$oClass2
=
$this
->ConvertAndCheckClass(
$oClass2
)) ){
$this
->SetError(
"!oClass2 in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
1118.
if
( !(
$oClassGlue
=
$this
->ConvertAndCheckClass(
$oClassGlue
)) ){
$this
->SetError(
"!oClassGlue in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
1119.
1120.
// Check all classes whether suitable (PRIMARY KEYs etc.)
1121.
if
( !
$oClass1
->IsSuitableForMnRelationSide() ){
$this
->SetError(
"Class "
.
$oClass1
->GetName().
" not suitable for M:N side in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
1122.
if
( !
$oClass2
->IsSuitableForMnRelationSide() ){
$this
->SetError(
"Class "
.
$oClass2
->GetName().
" not suitable for M:N side in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
1123.
if
( !
$oClassGlue
->IsSuitableForMnRelationGlue() ){
$this
->SetError(
"Class "
.
$oClassGlue
->GetName().
" not suitable for M:N glue in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
1124.
1125.
// Check whether the types are the same
1126.
$oIdProp1
=
$oClass1
->GetIdProperty();
1127.
$oIdProp2
=
$oClass1
->GetIdProperty();
1128.
$aoIdProps
=
$oClassGlue
->GetIdProperties();
1129.
1130.
if
(
$oIdProp1
->GetColType()->
GetType
() !=
$aoIdProps
[0]->GetColType()->
GetType
() ){
1131.
$this
->SetError(
'Property types mismatch: "'
.
$oIdProp1
->GetName().
'" and "'
.
$aoIdProps
[0]->GetName().
' in '
.
__METHOD__
.
' @ '
.
__LINE__
);
break
; }
1132.
if
(
$oIdProp2
->GetColType()->
GetType
() !=
$aoIdProps
[1]->GetColType()->
GetType
() ){
1133.
$this
->SetError(
'Property types mismatch: "'
.
$oIdProp2
->GetName().
'" and "'
.
$aoIdProps
[1]->GetName().
' in '
.
__METHOD__
.
' @ '
.
__LINE__
);
break
; }
1134.
1135.
//$oIdProp1->CompareTo($aoIdProps[0]); // TODO
1136.
1137.
$b
=
$oClassGlue
->SetMnRelationGlue(
$oClass1
,
$oClass2
,
$aoIdProps
[0],
$aoIdProps
[1]);
1138.
if
( !
$b
){
$this
->SetError(
"!\$oClassGlue->SetMnRelationGlue @ "
.
__LINE__
);
break
; }
1139.
1140.
$bSucc
= true;
1141.
}
while
(false);
1142.
return
$bSucc
;
1143.
}
1144.
1145.
1146.
/**<*********************************************************************************************>
1147.
* *
1148.
@param $oObject1 is an object of which related objects of $oClass2 should be returned.
1149.
@param $oClass2 - can be:
1150.
(object) - the Class will be found by it's class name.
1151.
(cDwOpClass) Class object - that's what we need
1152.
(string) class name - the Class will be found in the dictionary.
1153.
*************************************************************************************************/
1154.
function
LoadObjectsByMnRelation(
$oObject
,
$oClassGlue
,
$oClass2
,
$xId
=null){
1155.
$bSucc
= false;
1156.
do
{
1157.
1158.
// Convert class names to Class objects and check the existence of the class.
1159.
if
( !(
$oClass1
=
$this
->ConvertAndCheckClass(
$oObject
)) ){
$this
->SetError(
"!oClass1 @ "
.
__LINE__
);
break
; }
1160.
if
( !(
$oClass2
=
$this
->ConvertAndCheckClass(
$oClass2
)) ){
$this
->SetError(
"!oClass2 @ "
.
__LINE__
);
break
; }
1161.
if
( !(
$oClassGlue
=
$this
->ConvertAndCheckClass(
$oClassGlue
)) ){
$this
->SetError(
"!oClassGlue @ "
.
__LINE__
);
break
; }
1162.
1163.
if
( !
$oClassGlue
->IsMnRelationGlue() ){
$this
->SetError(
$oClassGlue
->GetName().
" is not a M : N relation glue in "
.
__METHOD__
.
" @ "
.
__LINE__
);
break
; }
1164.
1165.
// Table names
1166.
$sTable1
=
$oClass1
->GetTable();
1167.
$sTable2
=
$oClass2
->GetTable();
1168.
$sTableGlue
=
$oClassGlue
->GetTable();
1169.
1170.
// Column names
1171.
$oClass1IdProp
=
$oClass1
->GetIdProperty();
1172.
$sIdCol1
=
$oClass1IdProp
->GetColName();
1173.
1174.
$sIdCol2
=
$oClass2
->GetIdProperty()->GetColName();
1175.
$sGluePropFrom
=
$oClassGlue
->oMnRelationProp1->GetColName();
1176.
$sGluePropTo
=
$oClassGlue
->oMnRelationProp2->GetColName();
1177.
1178.
if
(
is_object
(
$oObject
) )
1179.
$xId
=
$oClass1IdProp
->FormatForSql(
$oObject
->GetId() );
1180.
1181.
//if( !$xId ){ $this->SetError("Bad ID [$xId] in ".__METHOD__." @ ".__LINE__); break; }
1182.
1183.
1184.
// Create SQL
1185.
$sSQL
= "
1186.
-- Vypise reklamy a k nim kanaly, ktere jsou s reklamou spojeny.
1187.
SELECT table_to.*
1188.
FROM
$sTable1
AS table_from
1189.
INNER JOIN
$sTableGlue
AS glue ON table_from.
$sIdCol1
= glue.
$sGluePropFrom
1190.
LEFT JOIN
$sTable2
AS table_to ON glue.
$sGluePropTo
= table_to.
$sIdCol2
1191.
WHERE table_from.
$sIdCol1
=
$xId
1192.
;";
1193.
1194.
$aoObjects
=
$this
->LoadObjectsBySql(
$oClass2
,
$sSQL
);
1195.
1196.
$bSucc
= true;
1197.
}
while
(false);
1198.
1199.
return
$aoObjects
;
1200.
}
1201.
1202.
1203.
1204.
1205.
}
// cDwObjectPersistence
1206.
1207.
1208.
1209.
1210.
/**<***********************************************************************>
1211.
* cDwOpClass *
1212.
***************************************************************************/
1213.
class
cDwOpClass {
1214.
1215.
var
$sName
;
1216.
function
GetName() {
return
$this
->sName; }
1217.
function
SetName(
$sName
){
$this
->sName =
$sName
; }
1218.
1219.
var
$sTable
;
1220.
function
GetTable() {
return
$this
->sTable; }
1221.
function
SetTable(
$sTable
){
$this
->sTable =
$sTable
; }
1222.
1223.
var
$oParentClass
= null;
1224.
function
GetParentClass() {
return
$this
->oParentClass; }
1225.
function
_SetParentClass(
$oParentClass
){
$this
->oParentClass =
$oParentClass
; }
1226.
1227.
1228.
1229.
// -- Constructor -- //
1230.
function
cDwOpClass(
$sName
,
$sTable
){
$this
->sName =
$sName
;
$this
->SetTable(
$sTable
); }
1231.
1232.
// Properties //
1233.
var
$aoProperties
;
1234.
/** @returns cDwOpProperty[] array of this class' properties. */
1235.
function
GetProperties() {
return
$this
->aoProperties; }
1236.
/** @returns cDwOpProperty this class' property of given name or NULL if the class does not have such. */
1237.
function
GetProperty(
$sColName
){
1238.
if
( isset(
$this
->aoProperties[
$sColName
]) )
1239.
$oRet
=
$this
->aoProperties[
$sColName
];
1240.
else
$oRet
= null;
1241.
return
$oRet
;
1242.
}
1243.
function
AddPropertyObject(
$oProperty
){
return
$this
->aoProperties[
$oProperty
->GetColName()] =
$oProperty
; }
1244.
function
AddProperty(
$sColName
,
$oColType
){
1245.
$oProp
=
new
cDwOpProperty(
$sColName
,
$oColType
);
1246.
$this
->aoProperties[
$sColName
] =
$oProp
;
1247.
return
$oProp
;
1248.
}
1249.
function
RemProperty(
$sColName
){
1250.
if
( !isset(
$this
->aoProperties[
$sColName
]) )
return
false;
1251.
unset(
$this
->aoProperties[
$sColName
]);
1252.
return
true;
1253.
}
1254.
function
GetNonKeyProperties(){
1255.
$aoProps
= Array();
1256.
foreach
(
$this
->aoProperties
as
$oProp
){
1257.
//if( $oProp->IsKeyProp() ) continue;
1258.
$aoProps
[] =
$oProp
;
1259.
}
1260.
return
$aoProps
;
1261.
}
1262.
1263.
1264.
1265.
// --- M : N relation stuff --- //
1266.
1267.
1268.
// -- Is this class M : N relation "glue"? -- //
1269.
var
$bMnRelationGlue
= false;
1270.
function
IsMnRelationGlue() {
return
$this
->bMnRelationGlue; }
1271.
function
UnsetMnRelationGlue(){
$this
->bMnRelationGlue = false; }
1272.
1273.
var
$oMnRelationClass1
= null;
1274.
var
$oMnRelationClass2
= null;
1275.
function
GetMnRelationClass1() {
return
$this
->oMnRelationClass1; }
1276.
function
GetMnRelationClass2() {
return
$this
->oMnRelationClass2; }
1277.
function
GetMnRelationOtherClass(
$oClass
){
1278.
if
(
$oClass
===
$this
->oMnRelationClass1 )
return
$this
->oMnRelationClass2;
1279.
if
(
$oClass
===
$this
->oMnRelationClass2 )
return
$this
->oMnRelationClass1;
1280.
return
null;
1281.
}
1282.
1283.
var
$oMnRelationProp1
= null;
1284.
var
$oMnRelationProp2
= null;
1285.
function
GetMnRelationProp1() {
return
$this
->oMnRelationProp1; }
1286.
function
GetMnRelationProp2() {
return
$this
->oMnRelationProp2; }
1287.
function
GetMnRelationOtherProp(
$oProp
){
1288.
if
(
$oProp
===
$this
->oMnRelationProp1 )
return
$this
->oMnRelationProp2;
1289.
if
(
$oProp
===
$this
->oMnRelationProp2 )
return
$this
->oMnRelationProp1;
1290.
return
null;
1291.
}
1292.
function
GetMnRelationPropForClass(
$oClass
){
1293.
//App::Log($oClass->GetName()." ==? ".$this->oMnRelationClass1->GetName());///
1294.
//App::Log($oClass->GetName()." ==? ".$this->oMnRelationClass2->GetName());///
1295.
//if( $oClass === $this->oMnRelationClass1 ) return $this->oMnRelationProp1;
1296.
//if( $oClass === $this->oMnRelationClass2 ) return $this->oMnRelationProp2;
1297.
$asParents
= class_parents(
$oClass
->GetName());
1298.
array_unshift
(
$asParents
,
$oClass
->GetName());
1299.
//App::Log(implode(',',$asParents)." <==? ".$this->oMnRelationClass1->GetName());///
1300.
//App::Log(implode(',',$asParents)." <==? ".$this->oMnRelationClass2->GetName());///
1301.
if
( in_array(
$this
->oMnRelationClass1->GetName(),
$asParents
)){
return
$this
->oMnRelationProp1; }
1302.
if
( in_array(
$this
->oMnRelationClass2->GetName(),
$asParents
)){
return
$this
->oMnRelationProp2; }
1303.
return
null;
1304.
}
1305.
1306.
1307.
1308.
1309.
function
IsSuitableForMnRelationGlue(){
return
Count
(
$this
->aoIdProperties) == 2; }
1310.
function
IsSuitableForMnRelationSide(){
return
Count
(
$this
->aoIdProperties) == 1; }
1311.
1312.
function
SetMnRelationGlue(
$oClass1
,
$oClass2
,
$oProp1
,
$oProp2
){
1313.
$this
->bMnRelationGlue = false;
1314.
do
{
1315.
// Check everything and return false on failure.
1316.
if
( !
$this
->IsSuitableForMnRelationGlue() )
return
false;
1317.
if
( !
$oClass1
|| !(
$oClass1
instanceof cDwOpClass) )
return
false;
1318.
if
( !
$oClass2
|| !(
$oClass2
instanceof cDwOpClass) )
return
false;
1319.
1320.
if
( 1 !=
$oClass1
->GetIdPropertiesCount() )
return
false;
1321.
if
( 1 !=
$oClass2
->GetIdPropertiesCount() )
return
false;
1322.
1323.
if
(
is_string
(
$oProp1
) )
$oProp1
=
$this
->GetProperty(
$oProp1
);
1324.
if
(
is_string
(
$oProp2
) )
$oProp2
=
$this
->GetProperty(
$oProp2
);
1325.
1326.
if
( null ==
$oProp1
|| !(
$oProp1
instanceof cDwOpProperty) )
return
false;
1327.
if
( null ==
$oProp2
|| !(
$oProp2
instanceof cDwOpProperty) )
return
false;
1328.
1329.
// Seems to be ok, set the relation for this Class... (we have to set the sides, too)
1330.
$this
->oMnRelationClass1 =
$oClass1
;
1331.
$this
->oMnRelationClass2 =
$oClass2
;
1332.
$this
->oMnRelationProp1 =
$oProp1
;
1333.
$this
->oMnRelationProp2 =
$oProp2
;
1334.
1335.
$this
->bMnRelationGlue = true;
1336.
1337.
}
while
(false);
1338.
return
$this
->bMnRelationGlue;
1339.
}
1340.
1341.
1342.
1343.
// --- ID properties --- //
1344.
1345.
// ID property //
1346.
//var $oIdProperty;
1347.
function
GetIdProperty() { reset(
$this
->aoIdProperties);
return
current(
$this
->aoIdProperties); }
1348.
function
SetIdProperty(
$oIdProperty
){
1349.
if
(!
$oIdProperty
){
$this
->aoIdProperties = Array();
return
; }
1350.
$this
->aoIdProperties = Array(
$oIdProperty
);
1351.
$oIdProperty
->SetPrimaryKeyPart(true);
1352.
}
1353.
1354.
var
$aoIdProperties
= Array();
1355.
function
GetIdProperties() {
return
$this
->aoIdProperties; }
1356.
1357.
function
GetIdPropertiesCount() {
return
Count
(
$this
->aoIdProperties); }
1358.
1359.
1360.
/**<**********************************************************************************>
1361.
* @returns whether Class has given ID property or ID property of given name *
1362.
**************************************************************************************/
1363.
function
HasIdProperty(
$xProp
){
1364.
if
(
is_string
(
$xProp
) )
$xProp
=
$this
->GetProperty(
$xProp
);
1365.
if
( !
$xProp
)
return
false;
1366.
if
( in_array(
$xProp
,
$this
->aoIdProperties) )
return
true;
1367.
return
false;
1368.
}
1369.
1370.
function
AddIdProperty(
$oProperty
){
array_push
(
$this
->aoIdProperties,
$oProperty
);
$oProperty
->SetPrimaryKeyPart(true); }
1371.
1372.
/** @returns string Coma separated list of ID (PRIMARY KEY) values of the given object. */
1373.
function
GetIdPropertiesSql(
$oObject
,
$sGlue
=
', '
){
1374.
$asPropSqls
= Array();
1375.
foreach
(
$this
->GetIdProperties()
as
$oProp
){
1376.
$asPropSqls
[] =
$oProp
->GetColName() .
" = "
.
$oProp
->FormatForSql(
$oObject
->GetProperty(
$oProp
->GetName()) );
1377.
}
1378.
$saPropSqls
= implode(
$sGlue
,
$asPropSqls
);
1379.
//if( '' != $saPropSqls ) $saPropSqls = " WHERE $saPropSqls "; // We don't want this for ID - can be "ON ...", e.g.
1380.
return
$saPropSqls
;
1381.
}
1382.
1383.
/** @returns string Formatted list of ID (PRIMARY KEY) values of the given object. */
1384.
function
GetObjectMultiIdString(
$oObject
,
$iMode
=DWOP_VALUE_DUMP_MODE__SQL){
1385.
switch
(
$iMode
){
1386.
default
: trigger_error(
"Bad param 2 - must be one of DWOP_VALUE_DUMP_MODE__* constants"
);
return
null;
break
;
1387.
case
DWOP_VALUE_DUMP_MODE__SQL:
$sGlue
=
', '
;
$sEq
=
' = '
;
$fFunc
=
'sql'
;
break
;
1388.
case
DWOP_VALUE_DUMP_MODE__SQL_SHORT:
$sGlue
=
','
;
$sEq
=
'='
;
$fFunc
=
'sql'
;
break
;
1389.
case
DWOP_VALUE_DUMP_MODE__SQL_VALUES:
$sGlue
=
','
;
$sEq
=
''
;
$fFunc
=
'sql'
;
break
;
1390.
case
DWOP_VALUE_DUMP_MODE__ESCAPED_VALUES:
$sGlue
=
'\''
;
$sEq
=
''
;
$fFunc
=
'addslashes'
;
break
;
// Shortest unique
1391.
case
DWOP_VALUE_DUMP_MODE__COMA:
$sGlue
=
', '
;
$sEq
=
''
;
$fFunc
=
''
;
break
;
1392.
}
1393.
$asPropSqls
= Array();
1394.
foreach
(
$this
->GetIdProperties()
as
$oProp
){
1395.
$s
=
''
;
1396.
if
(
$sEq
)
$s
.=
$oProp
->GetColName() .
$sEq
;
// <col name> =
1397.
1398.
$xVal
=
$oObject
->GetProperty(
$oProp
->GetName());
1399.
if
(!
$fFunc
) ;
1400.
elseif
(
'sql'
==
$fFunc
)
$xVal
=
$oProp
->FormatForSql(
$xVal
);
1401.
else
/*if( function_exists($fFunc) ) */
$xVal
=
$fFunc
(
$xVal
);
1402.
//else ;
1403.
$s
.=
$xVal
;
1404.
1405.
$asPropSqls
[] =
$s
;
1406.
}
1407.
$saPropSqls
= implode(
$sGlue
,
$asPropSqls
);
1408.
//if( '' != $saPropSqls ) $saPropSqls = " WHERE $saPropSqls "; // We don't want this for ID - can be "ON ...", e.g.
1409.
return
$saPropSqls
;
1410.
}
1411.
1412.
1413.
/** Sets ID properties.
1414.
@param $xProperties can be:
1415.
- a Property name
1416.
- coma separated list of Property names
1417.
- array of Property objects
1418.
*/
1419.
function
SetIdProperties(
$xProperties
){
1420.
1421.
// If $xProperties param is string, convert to an array
1422.
if
(
is_string
(
$xProperties
) )
1423.
$xProperties
=
array_map
(
'trim'
,
explode
(
','
,
$xProperties
));
1424.
1425.
// Now the $xProperties must be an array.
1426.
if
( !
is_array
(
$xProperties
) ){
1427.
$this
->aoIdProperties = Array();
1428.
return
false;
1429.
}
1430.
1431.
1432.
1433.
// Go through all properties in the array and transform them to cDwOpIdingInfo objects.
1434.
$aoIdProperties
= Array();
1435.
foreach
(
$xProperties
as
$xProperty
){
1436.
$bDesc
= false;
1437.
// If the array item is a string, convert to a property object.
1438.
if
(
is_string
(
$xProperty
) )
1439.
$xProperty
=
$this
->GetProperty(
$xProperty
);
1440.
1441.
// If the $xProperty is not a cDwOpProperty object, move on.
1442.
if
( null ===
$xProperty
|| !(
$xProperty
instanceof cDwOpProperty) )
1443.
continue
;
1444.
1445.
$xProperty
->SetPrimaryKeyPart(true);
1446.
$aoIdProperties
[] =
$xProperty
;
1447.
}
1448.
1449.
$this
->aoIdProperties =
$aoIdProperties
;
1450.
//echo "<pre>".AdjustedPrintR($aoOrderProperties)."</pre>";///
1451.
1452.
}
// SetIdProperties($xProperties)
1453.
1454.
1455.
1456.
1457.
// --- Order properties --- //
1458.
var
$aoOrderProperties
= Array();
1459.
function
GetOrderProperties() {
return
$this
->aoOrderProperties; }
1460.
1461.
1462.
/** @returns string Coma separated list of Order Properties (column names). */
1463.
function
GetOrderPropertiesSql(){
1464.
$asPropSqls
= Array();
1465.
foreach
(
$this
->aoOrderProperties
as
$oOrderingInfo
){
1466.
$asPropSqls
[] =
$oOrderingInfo
->oProperty->GetColName() . (
$oOrderingInfo
->bDesc ?
' DESC'
:
' ASC'
);
1467.
}
1468.
$saPropSqls
= implode(
', '
,
$asPropSqls
);
1469.
if
(
''
!=
$saPropSqls
)
$saPropSqls
=
" ORDER BY $saPropSqls "
;
1470.
return
$saPropSqls
;
1471.
}
1472.
1473.
1474.
/**<*************************************************************************>
1475.
* Sets the ordering information for this class. Previous info is replaced. *
1476.
@param $xProperties can be a coma separated list of Property names,
1477.
an array of Property names, or
1478.
an array of Property objects.
1479.
*****************************************************************************/
1480.
function
SetOrderProperties(
$xProperties
){
1481.
// If $xProperties param is string, convert to an array
1482.
if
(
is_string
(
$xProperties
) )
1483.
$xProperties
=
array_map
(
'trim'
,
explode
(
','
,
$xProperties
));
1484.
1485.
// Now the $xProperties must be an array.
1486.
if
( !
is_array
(
$xProperties
) )
1487.
return
false;
1488.
1489.
// Go through all properties in the array and transform them to cDwOpOrderingInfo objects.
1490.
$aoOrderProperties
= Array();
1491.
foreach
(
$xProperties
as
$xProperty
){
1492.
$bDesc
= false;
1493.
// If the array item is a string, convert to a property object.
1494.
if
(
is_string
(
$xProperty
) ){
1495.
if
(
''
==
$xProperty
)
continue
;
1496.
if
(
$xProperty
[0] ==
'+'
||
$xProperty
[0] ==
'-'
){
1497.
$bDesc
= (
$xProperty
[0] ==
'-'
);
1498.
$xProperty
=
substr
(
$xProperty
, 1);
1499.
}
1500.
$xProperty
=
$this
->GetProperty(
$xProperty
);
1501.
}
1502.
1503.
// Instance of cDwOpProperty - convert to cDwOpOrderingInfo
1504.
if
(
$xProperty
instanceof cDwOpProperty ){
1505.
$xProperty
=
new
cDwOpOrderingInfo(
$xProperty
,
$bDesc
);
1506.
}
1507.
1508.
// If the $xProperty is not a cDwOpProperty object, move on.
1509.
if
( null ===
$xProperty
|| !(
$xProperty
instanceof cDwOpOrderingInfo) )
1510.
continue
;
1511.
1512.
$aoOrderProperties
[] =
$xProperty
;
1513.
}
1514.
1515.
$this
->aoOrderProperties =
$aoOrderProperties
;
1516.
//echo "<pre>".AdjustedPrintR($aoOrderProperties)."</pre>";///
1517.
1518.
}
// SetOrderProperties($xProperties)
1519.
1520.
1521.
}
// class cDwOpClass
1522.
1523.
1524.
1525.
1526.
1527.
1528.
/**<***********************************************************************>
1529.
* Holds information about ordering property - for cDwOpClass. *
1530.
***************************************************************************/
1531.
class
cDwOpOrderingInfo {
1532.
var
$oProperty
= null;
1533.
var
$bDesc
= false;
1534.
function
cDwOpOrderingInfo(
$oProperty
,
$bDesc
=false){
1535.
$this
->oProperty =
$oProperty
;
1536.
$this
->bDesc =
$bDesc
;
1537.
}
1538.
}
1539.
1540.
1541.
1542.
1543.
/**<***********************************************************************>
1544.
* cDwOpProperty *
1545.
***************************************************************************/
1546.
class
cDwOpProperty {
1547.
1548.
/** Name - currently we use the same as a Property name and database column name. */
1549.
//var $sName = null;
1550.
function
GetName() {
return
$this
->sColName; }
1551.
function
SetName(
$sColName
){
$this
->sColName =
$sColName
; }
1552.
1553.
/** Column name - currently used also as the name of the property */
1554.
var
$sColName
= null;
1555.
function
GetColName() {
return
$this
->sColName; }
1556.
function
SetColName(
$sColName
){
$this
->sColName =
$sColName
; }
1557.
1558.
/** Column type - an object derived from cDwOpColumnType class. */
1559.
var
$oColType
= null;
1560.
/** @returns cDwOpColumnType column type representing this property. */
1561.
function
GetColType() {
return
$this
->oColType; }
1562.
function
SetColType(
$oColType
){
$this
->oColType =
$oColType
; }
1563.
1564.
/** Whether the property is a part of a PRIMARY KEY for this Class. */
1565.
var
$bPrimaryKeyPart
= false;
1566.
function
IsPrimaryKeyPart() {
return
$this
->bPrimaryKeyPart; }
1567.
function
SetPrimaryKeyPart(
$bPrimaryKeyPart
){
$this
->bPrimaryKeyPart =
$bPrimaryKeyPart
; }
1568.
1569.
/** Whether the property is a FOREIGN KEY. */
1570.
var
$bForeignKey
= false;
1571.
function
IsForeignKey() {
return
$this
->bForeignKey; }
1572.
function
SetForeignKey(
$bForeignKey
){
$this
->bForeignKey =
$bForeignKey
; }
1573.
1574.
/** Whether the property is unique across all objects of this Class. */
1575.
var
$bUnique
= false;
1576.
function
IsUnique() {
return
$this
->bUnique; }
1577.
function
SetUnique(
$bUnique
){
$this
->bUnique =
$bUnique
; }
1578.
1579.
/** Whether this property can be NULL. */
1580.
var
$bCanBeNull
= false;
1581.
function
IsNull() {
return
$this
->bCanBeNull; }
1582.
function
SetNull(
$bCanBeNull
){
$this
->bCanBeNull =
$bCanBeNull
; }
1583.
1584.
function
IsKey(){
1585.
return
$this
->IsPrimaryKeyPart() ||
$this
->IsForeignKey() ||
$this
->IsUnique();
1586.
}
1587.
1588.
1589.
// -- Constructor -- //
1590.
function
cDwOpProperty(
$sColName
,
$oColType
,
$bUnique
=false){
1591.
$this
->SetColName(
$sColName
);
1592.
$this
->SetColType(
$oColType
);
1593.
$this
->SetUnique(
$bUnique
);
1594.
}
1595.
1596.
/** @returns SQL literal representing a value $xVal if it was held by this property. */
1597.
function
FormatForSql(
$xVal
){
1598.
if
( null ===
$xVal
&&
$this
->GetColType()->IsNull() )
1599.
return
'NULL'
;
1600.
//echo "\n".CallInfo()."; Val: ".$xVal." ColType:".$this->GetColType()->GetName();///
1601.
return
$this
->GetColType()->FormatForSql(
$xVal
);
1602.
}
1603.
1604.
}
// class cDwOpProperty
1605.
1606.
1607.
1608.
1609.
1610.
1611.
1612.
1613.
/**<***********************************************************************>
1614.
* cDwOpColumnType *
1615.
***************************************************************************/
1616.
abstract
class
cDwOpColumnType {
1617.
1618.
var
$sName
;
1619.
function
GetName() {
return
$this
->sName; }
1620.
function
SetName(
$sName
){
$this
->sName =
$sName
; }
1621.
1622.
var
$iType
;
1623.
/** @returns one of type constants: DWOP_TYPE_STR,DWOP_TYPE_NUM,DWOP_TYPE_BOOL,DWOP_TYPE_ENUM,DWOP_TYPE_SET, DWOP_TYPE_REAL */
1624.
function
GetType
() {
return
$this
->iType; }
1625.
/** @param iType one of type constants: DWOP_TYPE_STR,DWOP_TYPE_NUM,DWOP_TYPE_BOOL,DWOP_TYPE_ENUM,DWOP_TYPE_SET, DWOP_TYPE_REAL */
1626.
function
SetType(
$iType
){
1627.
if
(!in_array(
$iType
, Array(DWOP_TYPE_STR,DWOP_TYPE_NUM,DWOP_TYPE_BOOL,DWOP_TYPE_ENUM,DWOP_TYPE_SET, DWOP_TYPE_REAL))){
1628.
user_error(
"cDwOpColumnType::SetType(): Param \$iType must be some of DWOP_TYPE_* constants."
);
1629.
}
1630.
$this
->iType =
$iType
;
1631.
}
1632.
1633.
// Can be NULL?
1634.
var
$bCanBeNull
= true;
1635.
function
IsNull() {
return
$this
->bCanBeNull; }
1636.
function
SetNull(
$bCanBeNull
){
$this
->bCanBeNull =
$bCanBeNull
; }
1637.
1638.
// Default value
1639.
var
$xDefault
;
1640.
function
GetDefault() {
return
$this
->xDefault; }
1641.
function
SetDefault(
$xDefault
){
1642.
$bRet
= true;
1643.
if
( (null ===
$xDefault
&& !
$this
->IsNull() )
// Default value being set is NULL and must not be null
1644.
|| ( !
$this
->CheckValue(
$xDefault
) )
// or the default value is not allowed for this type,
1645.
){
1646.
$xDefault
=
$this
->GetDefaultDefault();
// then set the default to the default default,
1647.
$bRet
= false;
// and indicate failure by returning false.
1648.
}
1649.
$this
->xDefault =
$xDefault
;
1650.
return
$bRet
;
1651.
}
1652.
//function GetDefaultDefault(){ user_error(__METHOD__.' must be overriden.'); return null; }
1653.
function
GetDefaultDefault(){
1654.
switch
(
$this
->
GetType
() ){
1655.
case
DWOP_TYPE_STR:
return
''
;
break
;
1656.
case
DWOP_TYPE_NUM:
return
0;
break
;
1657.
case
DWOP_TYPE_BOOL:
return
false;
break
;
1658.
case
DWOP_TYPE_ENUM:
return
''
;
break
;
1659.
case
DWOP_TYPE_SET:
return
''
;
break
;
1660.
case
DWOP_TYPE_REAL:
return
0.0;
break
;
1661.
}
1662.
}
1663.
1664.
1665.
// Aditional data - possible values for ENUM and SET, etc
1666.
//var $aData;
1667.
1668.
1669.
1670.
/**<***********************************************************************>
1671.
* Constructor *
1672.
***************************************************************************/
1673.
function
cDwOpColumnType(
$iFlags
=0,
$xDefault
=null){
1674.
1675.
// Flags
1676.
if
(
$iFlags
& DWOP_NOT_NULL )
1677.
$this
->SetNull(false);
1678.
//if( $iFlags & DWOP_BINARY )
1679.
// $this->SetBinary(true);
1680.
1681.
// Default value
1682.
$this
->SetDefault(
$xDefault
);
1683.
1684.
}
// cDwOpColumnType::cDwOpColumnType()
1685.
1686.
1687.
// Useless
1688.
/*function cDwOpColumnType($sName, $iType, $aData){
1689.
$this->SetName($sName);
1690.
$this->SetType($iType);
1691.
$this->aData = $aData;
1692.
}// cDwOpColumnType::cDwOpColumnType()
1693.
/**/
1694.
1695.
1696.
/**<***********************************************************************>
1697.
* @returns the value in $xVal in the format suitable for SQL. *
1698.
***************************************************************************/
1699.
function
FormatForSql(
$xVal
){
1700.
//App::Log( CallInfo()." \$xVal: (".gettype($xVal).") $xVal" );
1701.
$sRet
= null;
1702.
1703.
if
( null ===
$xVal
){
1704.
if
(
$this
->IsNull() )
1705.
$sRet
=
'NULL'
;
1706.
else
1707.
$sRet
=
'nULl'
;
1708.
}
1709.
else
switch
(
$this
->
GetType
()){
1710.
case
DWOP_TYPE_STR:
$sRet
= asq((string)
$xVal
);
break
;
1711.
case
DWOP_TYPE_NUM:
$sRet
= (double)
$xVal
;
/*echo "<br>XXX".CallInfo(-2)."<br>".CallInfo(-3);*/
break
;
1712.
case
DWOP_TYPE_BOOL:
$sRet
= (integer)(boolean)
$xRet
;
break
;
1713.
case
DWOP_TYPE_ENUM:
$sRet
= asq((string)
$xVal
);
break
;
1714.
case
DWOP_TYPE_SET:
$sRet
= asq((string)
$xVal
);
break
;
1715.
case
DWOP_TYPE_REAL:
$sRet
= (double)
$xVal
;
break
;
1716.
//case DWOP_TYPE_: $sRet = ; break;
1717.
default
: trigger_error(
'Unknown value type! in '
.
__METHOD__
.
' @ '
.
__LINE__
);
$sRet
= asq((string)
$xVal
);
break
;
1718.
}
1719.
//App::Log( CallInfo()." \$sRet: $sRet" );
1720.
return
$sRet
;
1721.
}
1722.
1723.
function
ConvertFromResult(
$xVal
){
return
$xVal
; }
1724.
1725.
1726.
/**<***********************************************************************>
1727.
* Check whether the variable can fit in the column. *
1728.
***************************************************************************/
1729.
function
CheckValue(
$xVal
/*, $oProperty*/
){
1730.
1731.
if
( null ===
$xVal
&& !
$this
->IsNull() )
1732.
return
false;
1733.
1734.
$bFits
= true;
1735.
switch
(
$this
->
GetType
()){
1736.
case
DWOP_TYPE_STR:
$bFits
=
is_string
(
$xVal
) ||
is_numeric
(
$xVal
);
break
;
1737.
case
DWOP_TYPE_NUM:
$bFits
=
is_bool
(
$xVal
) ||
is_int
(
$xVal
);
break
;
1738.
case
DWOP_TYPE_BOOL:
$bFits
=
is_bool
(
$xRet
) ||
is_int
(
$xVal
);
break
;
1739.
//case DWOP_TYPE_ENUM: $bFits = is_string($xVal) /*&& in_array($xVal, $this->asMembers)/**/; break;
1740.
case
DWOP_TYPE_SET:
1741.
$asMembers
=
array_map
(
'trim'
,
explode
(
','
,
$xVal
));
1742.
foreach
(
$asMembers
as
$sMember
){
1743.
if
( !in_array(
$xVal
,
$this
->aData) ){
$bFits
= false;
break
; }
1744.
}
1745.
break
;
1746.
}
1747.
return
$bFits
;
1748.
}
1749.
1750.
}
// class cDwOpColumnType
1751.
1752.
1753.
1754.
1755.
1756.
1757.
/**<***********************************************************************>
1758.
* cDwOpColumnTypesRepository *
1759.
Skladiste casto pouzivanych typu sloupcu.
1760.
Nema cenu sem davat stringy - lisi se delkou.
1761.
Mozna je to uplne zbytecna trida...
1762.
***************************************************************************/
1763.
/*class cDwOpColumnTypesRepository {
1764.
var $aoColumnTypes;
1765.
function AddColumnType($sKey, &$oType){ $this->aoColumnTypes[$sKey] =& $oType; }
1766.
1767.
1768.
function cDwOpColumnTypesRepository(){
1769.
$this->aoColumnTypes = Array();
1770.
1771.
$oType =& new cDwOpColumnType_INT();
1772.
$this->AddColumnType('INT', $oType);
1773.
$oType =& new cDwOpColumnType_INT_UNSIGNED();
1774.
$this->AddColumnType('INT UNSIGNED', $oType);
1775.
$oType =& new cDwOpColumnType_SMALLINT();
1776.
$this->AddColumnType('SMALLINT', $oType);
1777.
$oType =& new cDwOpColumnType_SMALLINT_UNSIGNED();
1778.
$this->AddColumnType('SMALLINT UNSIGNED', $oType);
1779.
1780.
1781.
}// cDwOpColumnTypesRepository()
1782.
1783.
function &GetColumnType($sName){
1784.
return isset( $this->aoColumnTypes[$sName] ) ? $this->aoColumnTypes[$sName] : null;
1785.
}
1786.
1787.
}// class cDwOpColumnTypesRepository
1788.
/**/
1789.
1790.
1791.
1792.
1793.
1794.
1795.
/** ************************************************************************
1796.
* Simple class that holds item's ID and a hashmap of parameters. *
1797.
***************************************************************************/
1798.
abstract
class
DwFwIdAndProperties {
1799.
1800.
function
DwFwIdAndProperties(
$iId
=null){
1801.
$this
->SetId(
$iId
);
1802.
}
1803.
1804.
var
$sId
;
1805.
function
GetId() {
return
$this
->sId; }
1806.
function
SetId(
$sId
){
$this
->sId =
$sId
; }
1807.
1808.
var
$asParams
= Array();
1809.
function
SetProperty(
$sName
,
$sValue
){
$this
->asParams[(string)
$sName
] =
$sValue
; }
1810.
function
GetProperty(
$sName
){
return
isset(
$this
->asParams[(string)
$sName
]) ?
$this
->asParams[(string)
$sName
] : null; }
1811.
//function HasProperty($sName){ return isset($this->asParams[(string)$sName]); }
1812.
function
HasProperty(
$sName
){
return
array_key_exists
((string)
$sName
,
$this
->asParams); }
1813.
function
IsPropertySet(
$sName
){
return
$this
->HasProperty(
$sName
); }
1814.
1815.
function
GetProperties(){
return
$this
->asParams; }
1816.
function
SetProperties(
$asParams
,
$bOverwrite
=true){
1817.
foreach
(
$asParams
as
$sName
=>
$sValue
){
1818.
if
(
$bOverwrite
|| !isset(
$this
->asParams[(string)
$sName
]))
1819.
$this
->asParams[(string)
$sName
] =
$sValue
;
1820.
}
1821.
}
1822.
1823.
function
DwFwIdAndParams(
$sId
=null){
$this
->sId =
$sId
; }
1824.
1825.
}
// class DwFwIdAndParams
01.
/** ************************************************************************
02.
* Simple class that holds item's ID and a hashmap of parameters. *
03.
***************************************************************************/
04.
abstract
class
DwFwIdAndProperties {
05.
06.
function
DwFwIdAndProperties(
$iId
=null){
07.
$this
->SetId(
$iId
);
08.
}
09.
10.
var
$sId
;
11.
function
GetId() {
return
$this
->sId; }
12.
function
SetId(
$sId
){
$this
->sId =
$sId
; }
13.
14.
var
$asParams
= Array();
15.
function
SetProperty(
$sName
,
$sValue
){
$this
->asParams[(string)
$sName
] =
$sValue
; }
16.
function
GetProperty(
$sName
){
return
isset(
$this
->asParams[(string)
$sName
]) ?
$this
->asParams[(string)
$sName
] : null; }
17.
//function HasProperty($sName){ return isset($this->asParams[(string)$sName]); }
18.
function
HasProperty(
$sName
){
return
array_key_exists
((string)
$sName
,
$this
->asParams); }
19.
function
IsPropertySet(
$sName
){
return
$this
->HasProperty(
$sName
); }
20.
21.
function
GetProperties(){
return
$this
->asParams; }
22.
function
SetProperties(
$asParams
,
$bOverwrite
=true){
23.
foreach
(
$asParams
as
$sName
=>
$sValue
){
24.
if
(
$bOverwrite
|| !isset(
$this
->asParams[(string)
$sName
]))
25.
$this
->asParams[(string)
$sName
] =
$sValue
;
26.
}
27.
}
28.
29.
function
DwFwIdAndParams(
$sId
=null){
$this
->sId =
$sId
; }
30.
31.
}
// class DwFwIdAndParams
32.
33.
34.
35.
36.
37.
/***************************************************************************
38.
* User *
39.
***************************************************************************/
40.
class
cObjectPersistenceTestClass_User
extends
DwFwIdAndProperties {
41.
function
GetProperty(
$sName
) {
42.
if
(
'id'
==
$sName
)
return
$this
->GetId();
43.
else
return
parent::GetProperty(
$sName
);
44.
}
45.
function
SetProperty(
$sName
,
$sValue
){
46.
if
(
'id'
==
$sName
)
return
$this
->SetId(
$sValue
);
47.
else
return
parent::SetProperty(
$sName
,
$sValue
);
48.
}
49.
}
// class cObjectPersistenceTestClass_User
50.
51.
/***************************************************************************
52.
* Door *
53.
***************************************************************************/
54.
class
cObjectPersistence_TestClass_Door
extends
DwFwIdAndProperties {
55.
function
GetProperty(
$sName
) {
56.
if
(
'id'
==
$sName
)
return
$this
->GetId();
57.
else
return
parent::GetProperty(
$sName
);
58.
}
59.
function
SetProperty(
$sName
,
$sValue
){
60.
if
(
'id'
==
$sName
)
return
$this
->SetId(
$sValue
);
61.
else
return
parent::SetProperty(
$sName
,
$sValue
);
62.
}
63.
}
// class cObjectPersistenceTestClass_User
64.
65.
/***************************************************************************
66.
* Key *
67.
***************************************************************************/
68.
class
cObjectPersistence_TestClass_Key
extends
DwFwIdAndProperties {
69.
function
GetProperty(
$sName
) {
70.
if
(
'id'
==
$sName
)
return
$this
->GetId();
71.
else
return
parent::GetProperty(
$sName
);
72.
}
73.
function
SetProperty(
$sName
,
$sValue
){
74.
if
(
'id'
==
$sName
)
return
$this
->SetId(
$sValue
);
75.
else
return
parent::SetProperty(
$sName
,
$sValue
);
76.
}
77.
}
// class cObjectPersistenceTestClass_User
01.
// Create DB object
02.
$oDB
=
new
cDBAccess_MySQL(
'localhost:3350'
,
'test'
,
'test'
,
'test'
,
'cp1250'
);
03.
$oDB
->SetSelectMode(CDBA_SELECT_RETURNS_CRESULT_ON_ERROR);
04.
echo
"Connect: "
.
///
05.
$oDB
->Connect();
06.
echo
"<br/>\n"
;
///
07.
08.
//$xVal = $oDB->SelectCell("SELECT NULL"); // Test what NULL looks like in PHP
09.
//echo "\n".gettype($xVal)." ".ord($xVal); die();
10.
11.
// Create Object Persistence object
12.
$oOP
=
new
cDwObjectPersistence_DB(
$oDB
);
13.
//$oColTypes =& new cDwOpColumnTypesRepository();
01.
CREATE
TABLE
`ap_users` (
02.
`id`
int
(10) unsigned
NOT
NULL
auto_increment,
03.
`
user
`
varchar
(255)
NOT
NULL
,
04.
`pass`
varchar
(40)
default
NULL
,
05.
`fname`
varchar
(255)
NOT
NULL
,
06.
`lname`
varchar
(255)
NOT
NULL
,
07.
`addr`
varchar
(255)
NOT
NULL
,
08.
`city`
varchar
(255)
NOT
NULL
,
09.
`state` enum(
'good'
,
'bad'
)
NOT
NULL
DEFAULT
'good'
,
10.
`psc`
varchar
(255)
NOT
NULL
,
11.
`ctry` tinyint(3) unsigned
NOT
NULL
,
12.
`ppal`
varchar
(255)
default
NULL
13.
);
14.
INSERT
INTO
ap_users (id,
user
)
VALUES
15.
(10001,
'Ondra'
)
16.
, (10002,
'Zdenek'
)
17.
, (10003,
'Martin'
)
18.
, (10004,
'Zuzka'
)
19.
, (10005,
'David'
)
20.
, (10006,
'Satan'
)
21.
;
22.
23.
CREATE
TABLE
ap_doors (
24.
id
INT
UNSIGNED
NOT
NULL
auto_increment
PRIMARY
KEY
,
25.
txt
VARCHAR
(15)
26.
);
27.
INSERT
INTO
ap_doors
VALUES
(330,
'Nebe'
), (118,
'Bazina'
), (116,
'Peklo'
), (110,
'Curaprox'
), (222,
'Neznamo'
);
28.
29.
CREATE
TABLE
ap_keys (
30.
id_user
INT
UNSIGNED
NOT
NULL
,
31.
id_door
INT
UNSIGNED
NOT
NULL
,
32.
PRIMARY
KEY
pk( id_user, id_door )
33.
);
34.
INSERT
INTO
ap_keys
VALUES
35.
(10001, 330), (10001, 118), (10001, 110),
-- Ondra
36.
(10002, 118), (10002, 116),
-- Zdenek
37.
(10003, 118), (10003, 330), (10003, 116),
-- Martin
38.
(10004, 110), (10004, 330),
-- Zuzka
39.
(10006, 116), (10006, 118);
-- Satan
01.
$oClass
=
new
cDwOpClass(
'cObjectPersistenceTestClass_User'
,
'ap_users'
);
02.
//$oProp = $oClass->AddProperty('id', $oColTypes->GetColumnType('INT UNSIGNED'));
03.
$oProp
=
$oClass
->AddProperty(
'id'
,
new
cDwOpColumnType_INT_UNSIGNED() );
04.
$oClass
->SetIdProperty(
$oProp
);
05.
$oProp
=
$oClass
->AddProperty(
'user'
,
new
cDwOpColumnType_VARCHAR(255, DWOP_NOT_NULL) );
06.
$oProp
=
$oClass
->AddProperty(
'pass'
,
new
cDwOpColumnType_VARCHAR(40, DWOP_NOT_NULL) );
07.
$oProp
=
$oClass
->AddProperty(
'fname'
,
new
cDwOpColumnType_VARCHAR(255, DWOP_NOT_NULL) );
08.
$oProp
=
$oClass
->AddProperty(
'lname'
,
new
cDwOpColumnType_VARCHAR(255, DWOP_NOT_NULL) );
09.
$oProp
=
$oClass
->AddProperty(
'addr'
,
new
cDwOpColumnType_VARCHAR(255, DWOP_NOT_NULL) );
10.
$oProp
=
$oClass
->AddProperty(
'city'
,
new
cDwOpColumnType_VARCHAR(255, DWOP_NOT_NULL) );
11.
$oProp
=
$oClass
->AddProperty(
'state'
,
new
cDwOpColumnType_VARCHAR(255, DWOP_NOT_NULL) );
12.
$oProp
=
$oClass
->AddProperty(
'psc'
,
new
cDwOpColumnType_VARCHAR(255, DWOP_NOT_NULL) );
13.
$oProp
=
$oClass
->AddProperty(
'ctry'
,
new
cDwOpColumnType_TINYINT_UNSIGNED() );
14.
$oProp
=
$oClass
->AddProperty(
'ppal'
,
new
cDwOpColumnType_VARCHAR(255) );
15.
$oClass
->SetOrderProperties(
'lname, +fname, -id'
);
16.
$oOP
->AddClassIntoDictionary(
$oClass
);
17.
/*/
18.
$oClass
=
$oOP
->CreateClassByTable(
'cObjectPersistenceTestClass_User'
,
'ap_users'
);
19.
$oClass
->SetOrderProperties(
'lname, +fname, -id'
);
20.
//file_put_contents('x1.txt', AdjustedPrintR($oClass));///
21.
//echo "<pre>\$oClass: ".AdjustedPrintR($oClass)."</pre>";///
001.
srand(time());
002.
003.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
004.
005.
// Load by ID
006.
echo
"<h3>Load by ID</h3>"
;
007.
$iID
= 1;
008.
echo
"<pre>\$oObject = \$oOP->LoadObjectById("
.
$oClass
->GetName().
", $iID);</pre>"
;
009.
$oUser
=
$oOP
->LoadObjectById(
$oClass
,
$iID
);
010.
echo
"<pre>oUser: ["
.
gettype
(
$oUser
).
"]"
.AdjustedPrintR(
$oUser
).
"</pre>"
;
011.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
012.
013.
014.
// Load by ID, using class name string
015.
echo
"<h3>Load by ID, using class name string</h3>"
;
016.
$iID
= 1;
017.
echo
"<pre>\$oObject =& \$oOP->LoadObjectById('"
.
$oClass
->GetName().
"', $iID);</pre>"
;
018.
$oUser
=&
$oOP
->LoadObjectById(
$oClass
->GetName(),
$iID
);
019.
echo
"<pre>oUser: ["
.
gettype
(
$oUser
).
"]"
.AdjustedPrintR(
$oUser
).
"</pre>"
;
020.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
021.
022.
023.
024.
// Load by value
025.
echo
"<h3>Load by value</h3>"
;
026.
$xVal
=
'as'
;
027.
echo
"<pre>\$aoUsers = \$oOP->LoadObjectsByValue("
.
$oClass
->GetName().
", 'user', $xVal);</pre>"
;
028.
$aoUsers
=
$oOP
->LoadObjectsByValue(
$oClass
,
'user'
,
$xVal
);
029.
echo
"<pre>\$aoUsers: ["
.
gettype
(
$aoUsers
).
"]"
.AdjustedPrintR(
$aoUsers
).
"</pre>"
;
030.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
031.
032.
033.
034.
// Save
035.
echo
"<h3>Save</h3>"
;
036.
$oUser
=
new
cObjectPersistenceTestClass_User();
037.
$oUser
->SetId(1);
038.
$oUser
->SetProperty(
'user'
,
'as'
.rand());
039.
$oUser
->SetProperty(
'pass'
,
'as'
);
040.
$oUser
->SetProperty(
'fname'
,
'Astar'
);
041.
$oUser
->SetProperty(
'lname'
,
'Seran'
);
042.
echo
"<pre>oUser: ["
.
gettype
(
$oUser
).
"]"
.AdjustedPrintR(
$oUser
).
"</pre>"
;
043.
echo
"<pre>\$oOP->SaveObject(\$oUser);</pre>"
;
044.
$bSucc
=
$oOP
->SaveObject(
$oUser
);
045.
echo
"<div>"
.(
$bSucc
?
'saved'
:
'error'
).
"</div>"
;
046.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
047.
048.
049.
// Create
050.
echo
"<h3>Create</h3>"
;
051.
$oUser
=
new
cObjectPersistenceTestClass_User();
052.
$oUser
->SetId(null);
053.
$oUser
->SetProperty(
'user'
,
'as'
.rand());
054.
$oUser
->SetProperty(
'pass'
,
'as'
);
055.
$oUser
->SetProperty(
'fname'
,
'Astar'
);
056.
$oUser
->SetProperty(
'lname'
,
'Seran'
);
057.
echo
"<pre>oUser: ["
.
gettype
(
$oUser
).
"]"
.AdjustedPrintR(
$oUser
).
"</pre>"
;
058.
echo
"<pre>\$oOP->SaveObject(\$oUser);</pre>"
;
059.
$bSucc
=
$oOP
->SaveObject(
$oUser
);
060.
echo
"<div>"
.(
$bSucc
?
'saved'
:
'error'
).
"</div>"
;
061.
if
(!
$bSucc
)
echo
"<pre>"
.
$oOP
->GetDB()->GetLastErrorString().
"</pre>"
;
062.
echo
"<pre>\$oUser: ["
.
gettype
(
$oUser
).
"]"
.AdjustedPrintR(
$oUser
).
"</pre>"
;
063.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
064.
065.
066.
// Load by value - load object created above -> Object Pool hit
067.
echo
"<h3>Load by value 2</h3>"
;
068.
069.
$xVal
=
$oUser
->GetProperty(
'user'
);
070.
echo
"<pre>\$aoUsers = \$oOP->LoadObjectsByValue("
.
$oClass
->GetName().
", 'user', $xVal);</pre>"
;
071.
$aoUsers
=
$oOP
->LoadObjectsByValue(
$oClass
,
'user'
,
$xVal
);
072.
echo
"<pre>\$aoUsers: ["
.
gettype
(
$aoUsers
).
"]"
.AdjustedPrintR(
$aoUsers
).
"</pre>"
;
073.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
074.
075.
076.
077.
// Remove from pool - still that one object
078.
echo
"<h3>Remove from pool</h3>"
;
079.
080.
echo
"<pre>\$bSucc = \$oOP->RemObjectFromPool(\$oUser);</pre>"
;
081.
$bSucc
=
$oOP
->RemObjectFromPool(
$oUser
);
082.
echo
"<pre>\$oUser: ["
.
gettype
(
$oUser
).
"]"
.AdjustedPrintR(
$oUser
).
"</pre>"
;
083.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
084.
085.
086.
// Load by value - that object again
087.
echo
"<h3>Load by value 3</h3>"
;
088.
089.
$xVal
=
$oUser
->GetProperty(
'user'
);
090.
echo
"<pre>\$aoUsers = \$oOP->LoadObjectsByValue("
.
$oClass
->GetName().
", 'user', $xVal);</pre>"
;
091.
$aoUsers
=
$oOP
->LoadObjectsByValue(
$oClass
,
'user'
,
$xVal
);
092.
echo
"<pre>\$aoUsers: ["
.
gettype
(
$aoUsers
).
"]"
.AdjustedPrintR(
$aoUsers
).
"</pre>"
;
093.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
094.
095.
// Delete that object from DB
096.
echo
"<h3>Delete object by ID</h3>"
;
097.
098.
echo
"<pre>\$oOP->DeleteObject("
.
$oClass
->GetName().
", "
.
$oUser
->GetId().
");</pre>"
;
099.
$bSucc
=
$oOP
->DeleteObject(
$oClass
,
$oUser
->GetId());
100.
if
(!
$bSucc
)
echo
'<div style="font-color: red;">Delete failed. Error: '
.
$oOP
->GetError().
"</pre>"
;
101.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
102.
103.
104.
105.
// Load all objects
106.
echo
"<h3>Load all objects</h3>"
;
107.
108.
echo
"<pre>\$aoUsers = \$oOP->LoadObjects("
.
$oClass
->GetName().
");</pre>"
;
109.
$aoUsers
=
$oOP
->LoadObjects(
$oClass
);
110.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
111.
//echo "<pre>\$aoUsers: [".gettype($aoUsers)."]".AdjustedPrintR($aoUsers)."</pre>";
112.
113.
114.
115.
116.
// M : N relation
117.
$oClassUser
=
$oClass
;
118.
echo
"<h2>M : N Relation</h2>"
;
119.
120.
echo
"<div>\$oClassDoor = \$oOP->CreateClassByTable('cObjectPersistence_TestClass_Door', 'ap_doors');</div>"
;
121.
$oClassDoor
=
$oOP
->CreateClassByTable(
'cObjectPersistence_TestClass_Door'
,
'ap_doors'
);
122.
file_put_contents
(
'oClassDoor.txt'
, AdjustedPrintR(
$oClassDoor
));
///
123.
echo
"<div>\$oClassDoor->IsSuitableForMnRelationSide(): "
.(int)
$oClassDoor
->IsSuitableForMnRelationSide().
"</div>"
;
124.
echo
"<div>\$oClassUser->IsSuitableForMnRelationSide(): "
.(int)
$oClassUser
->IsSuitableForMnRelationSide().
"</div>"
;
125.
126.
echo
"<div>\$oClassKey = \$oOP->CreateClassByTable('cObjectPersistence_TestClass_Key', 'ap_keys');</div>"
;
127.
$oClassKey
=
$oOP
->CreateClassByTable(
'cObjectPersistence_TestClass_Key'
,
'ap_keys'
);
128.
file_put_contents
(
'oClassKey.txt'
, AdjustedPrintR(
$oClassKey
));
///
129.
echo
"\$oClassKey->IsSuitableForMnRelationGlue(): "
.(int)
$oClassKey
->IsSuitableForMnRelationGlue();
130.
131.
// Settin'up
132.
echo
'<pre>$oOP->SetMnRelation($oClassUser, $oClassKey, $oClassDoor);</pre>'
;
133.
$bSucc
=
$oOP
->SetMnRelation(
$oClassUser
,
$oClassKey
,
$oClassDoor
);
134.
file_put_contents
(
'oClassKey2.txt'
, AdjustedPrintR(
$oClassKey
));
///
135.
if
(!
$bSucc
)
echo
"<div>Error: "
.
$oOP
->GetError().
"</div>"
;
136.
137.
138.
139.
// Load objects by M : N relation
140.
141.
/*/ Determines the Class and the ID from the $oUser object.
142.
echo "<pre>\$aoDoors = \$oOP->LoadObjectsByMnRelation(\$oUser, \$oClassKey, \$oClassDoor)</pre>";
143.
$aoDoors = $oOP->LoadObjectsByMnRelation($oUser, $oClassKey, $oClassDoor);
144.
echo "<div>GetPoolCount(): ".$oOP->GetPoolCount()."</div>";
145.
echo "<pre>\$aoDoors: (".gettype($aoDoors).") ".AdjustedPrintR($aoDoors)."</pre>";
146.
/*/
// The same with ID explicitly set to 10001
147.
echo
"<pre>\$aoDoors = \$oOP->LoadObjectsByMnRelation('cObjectPersistenceTestClass_User', \$oClassKey, \$oClassDoor, 10001)</pre>"
;
148.
$aoDoors
=
$oOP
->LoadObjectsByMnRelation(
'cObjectPersistenceTestClass_User'
,
$oClassKey
,
$oClassDoor
, 10001);
149.
echo
"<div>GetPoolCount(): "
.
$oOP
->GetPoolCount().
"</div>"
;
150.
echo
"<pre>\$aoDoors: ("
.
gettype
(
$aoDoors
).
") "
.AdjustedPrintR(
$aoDoors
).
"</pre>"
;
151.
152.
// Multiple ID properties SQL for an object:
153.
echo
"<div>\$oClassDoor->GetIdPropertiesSql(\$aoDoors[0]): "
.
$oClassDoor
->GetIdPropertiesSql(
$aoDoors
[0]).
"</pre>"
;
154.
155.
$aoKeys
=
$oOP
->LoadObjectsByValue(
'cObjectPersistence_TestClass_Key'
,
'id_user'
, 10001);
156.
echo
"<div>\$oClassKey->GetIdPropertiesSql(\$aoDoors[0]): "
.
$oClassKey
->GetIdPropertiesSql(
$aoKeys
[0]).
"</pre>"
;
157.
158.
159.
160.
if
(
$oOP
->GetError() )
161.
echo
'<div style="color: red">Error from the past: '
.
$oOP
->GetError().
"</div>"
;