diff options
Diffstat (limited to 'framework')
31 files changed, 1076 insertions, 228 deletions
diff --git a/framework/3rdParty/WsdlGen/WsdlMessage.php b/framework/3rdParty/WsdlGen/WsdlMessage.php index 164d81f1..2ba2cef6 100644 --- a/framework/3rdParty/WsdlGen/WsdlMessage.php +++ b/framework/3rdParty/WsdlGen/WsdlMessage.php @@ -30,13 +30,13 @@ class WsdlMessage * @var string */ private $name; - + /** * Represents the parameters for this message * @var array */ private $parts; - + /** * Creates a new message * @param string $messageName The name of the message @@ -46,9 +46,9 @@ class WsdlMessage { $this->name = $messageName; $this->parts = $parts; - + } - + /** * Gets the name of this message * @return string The name @@ -57,7 +57,7 @@ class WsdlMessage { return $this->name; } - + /** * Return the message as a DOM element * @param DOMDocument $wsdl The wsdl document the messages will be children of @@ -66,7 +66,7 @@ class WsdlMessage { $message = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:message'); $message->setAttribute('name', $this->name); - + foreach ($this->parts as $part) { if (isset($part['name'])) { $partElement = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:part'); @@ -75,7 +75,7 @@ class WsdlMessage $message->appendChild($partElement); } } - + return $message; } } diff --git a/framework/3rdParty/WsdlGen/WsdlOperation.php b/framework/3rdParty/WsdlGen/WsdlOperation.php index 58690a23..75e21308 100644 --- a/framework/3rdParty/WsdlGen/WsdlOperation.php +++ b/framework/3rdParty/WsdlGen/WsdlOperation.php @@ -29,38 +29,38 @@ class WsdlOperation * The name of the operation */ private $operationName; - + /** * Documentation for the operation */ private $documentation; - + /** * The input wsdl message */ private $inputMessage; - + /** * The output wsdl message */ private $outputMessage; - + public function __construct($name, $doc='') { $this->operationName = $name; $this->documentation = $doc; } - + public function setInputMessage(WsdlMessage $msg) { $this->inputMessage = $msg; } - + public function setOutputMessage(WsdlMessage $msg) { $this->outputMessage = $msg; } - + /** * Sets the message elements for this operation into the wsdl document * @param DOMElement $wsdl The parent domelement for the messages @@ -68,14 +68,14 @@ class WsdlOperation */ public function setMessageElements(DOMElement $wsdl, DOMDocument $dom) { - + $input = $this->inputMessage->getMessageElement($dom); $output = $this->outputMessage->getMessageElement($dom); - + $wsdl->appendChild($input); $wsdl->appendChild($output); } - + /** * Get the port operations for this operation * @param DomDocument $dom The dom document to create the messages as children of @@ -85,20 +85,20 @@ class WsdlOperation { $operation = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:operation'); $operation->setAttribute('name', $this->operationName); - + $documentation = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:documentation', htmlentities($this->documentation)); $input = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:input'); $input->setAttribute('message', 'tns:'.$this->inputMessage->getName()); $output = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:output'); $output->setAttribute('message', 'tns:'.$this->outputMessage->getName()); - + $operation->appendChild($documentation); $operation->appendChild($input); $operation->appendChild($output); - + return $operation; } - + /** * Build the binding operations. * TODO: Still quite incomplete with all the things being stuck in, I don't understand @@ -111,26 +111,26 @@ class WsdlOperation { $operation = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:operation'); $operation->setAttribute('name', $this->operationName); - + $soapOperation = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/soap/', 'soap:operation'); $method = $this->operationName; $soapOperation->setAttribute('soapAction', $namespace.'#'.$method); $soapOperation->setAttribute('style', $style); - + $input = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:input'); $output = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/', 'wsdl:output'); - + $soapBody = $dom->createElementNS('http://schemas.xmlsoap.org/wsdl/soap/', 'soap:body'); $soapBody->setAttribute('use', 'encoded'); $soapBody->setAttribute('namespace', $namespace); $soapBody->setAttribute('encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/'); $input->appendChild($soapBody); $output->appendChild(clone $soapBody); - + $operation->appendChild($soapOperation); $operation->appendChild($input); $operation->appendChild($output); - + return $operation; } } diff --git a/framework/Data/ActiveRecord/Exceptions/messages.txt b/framework/Data/ActiveRecord/Exceptions/messages.txt index 53d8f4e3..2af62bb5 100644 --- a/framework/Data/ActiveRecord/Exceptions/messages.txt +++ b/framework/Data/ActiveRecord/Exceptions/messages.txt @@ -13,4 +13,5 @@ ar_invalid_tablename_property = ActiveRecord tablename property '{0}::${1}' m ar_value_must_not_be_null = Property '{0}::${2}' must not be null as defined by column '{2}' in table '{1}'.
ar_missing_pk_values = Missing primary key values in forming IN(key1, key2, ...) for table '{0}'.
ar_pk_value_count_mismatch = Composite key value count mismatch in forming IN( (key1, key2, ..), (key3, key4, ..)) for table '{0}'.
-ar_must_copy_from_array_or_object = $data in {0}::copyFrom($data) must be an object or an array.
\ No newline at end of file +ar_must_copy_from_array_or_object = $data in {0}::copyFrom($data) must be an object or an array.
+ar_mismatch_column_names = In dynamic __call() method '{0}', no matching columns were found, valid columns for table '{2}' are '{1}'.
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php index c6fc6902..89df0f2e 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php @@ -2,7 +2,7 @@ Prado::using('System.Data.ActiveRecord.Scaffold.InputBuilder.TScaffoldInputCommon');
-class MysqlScaffoldInput extends TScaffoldInputCommon
+class TMysqlScaffoldInput extends TScaffoldInputCommon
{
protected function createControl($container, $column, $record)
{
diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php index 40a14fbc..f5e11eae 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php @@ -2,7 +2,7 @@ Prado::using('System.Data.ActiveRecord.Scaffold.InputBuilder.TScaffoldInputCommon');
-class PgsqlScaffoldInput extends ScaffoldInputCommon
+class TPgsqlScaffoldInput extends TScaffoldInputCommon
{
protected function createControl($container, $column, $record)
{
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php index dc464245..b55ceedc 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php @@ -1,12 +1,49 @@ <?php
-
+/**
+ * TScaffoldBase class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Scaffold
+ */
+
+/**
+ * Include the base Active Record class.
+ */
Prado::using('System.Data.ActiveRecord.TActiveRecord');
+/**
+ * Base class for Active Record scaffold views.
+ *
+ * Provides common properties for all scaffold views (such as, TScaffoldListView,
+ * TScaffoldEditView, TScaffoldListView and TScaffoldView).
+ *
+ * During the OnPrRender stage the default css style file (filename style.css)
+ * is published and registered. To override the default style, provide your own stylesheet
+ * file explicitly.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Scaffold
+ * @since 3.1
+ */
abstract class TScaffoldBase extends TTemplateControl
{
+ /**
+ * @var TActiveRecord record instance (may be new or retrieved from db)
+ */
private $_record;
+ /**
+ * @var TDbMetaData table/view information.
+ */
private $_meta;
+ /**
+ * @return TDbMetaData table/view information
+ */
protected function getTableMetaData()
{
if($this->_meta===null)
@@ -18,7 +55,11 @@ abstract class TScaffoldBase extends TTemplateControl return $this->_meta;
}
- protected function getRecordProperties($record)
+ /**
+ * @param TActiveRecord record instance
+ * @return array record property values
+ */
+ protected function getRecordPropertyValues($record)
{
$data = array();
foreach($this->getTableMetaData()->getColumns() as $name=>$column)
@@ -26,7 +67,11 @@ abstract class TScaffoldBase extends TTemplateControl return $data;
}
- public function getRecordObjectPk($record)
+ /**
+ * @param TActiveRecord record instance
+ * @return array record primary key values.
+ */
+ protected function getRecordPkValues($record)
{
$pk = array();
foreach($this->getTableMetaData()->getColumns() as $name=>$column)
@@ -37,76 +82,116 @@ abstract class TScaffoldBase extends TTemplateControl return $data;
}
+ /**
+ * Name of the Active Record class to be viewed or scaffolded.
+ * @return string Active Record class name.
+ */
public function getRecordClass()
{
return $this->getViewState('RecordClass');
}
+ /**
+ * Name of the Active Record class to be viewed or scaffolded.
+ * @param string Active Record class name.
+ */
public function setRecordClass($value)
{
$this->setViewState('RecordClass', $value);
}
- public function copyFrom(TScaffoldBase $obj)
+ /**
+ * Copy the view details from another scaffold view instance.
+ * @param TScaffoldBase scaffold view.
+ */
+ protected function copyFrom(TScaffoldBase $obj)
{
$this->_record = $obj->_record;
$this->_meta = $obj->_meta;
$this->setRecordClass($obj->getRecordClass());
}
+ /**
+ * Unset the current record instance and table information.
+ */
protected function clearRecordObject()
{
$this->_record=null;
$this->_meta=null;
}
- public function getRecordObject($pk=null)
+ /**
+ * Gets the current Active Record instance. Creates new instance if the
+ * primary key value is null otherwise the record is fetched from the db.
+ * @param array primary key value
+ * @return TActiveRecord record instance
+ */
+ protected function getRecordObject($pk=null)
{
if($this->_record===null)
{
if($pk!==null)
+ {
$this->_record=$this->getRecordFinder()->findByPk($pk);
+ if($this->_record===null)
+ throw new TConfigurationException('scaffold_invalid_record_pk',
+ $this->getRecordClass(), $pk);
+ }
else
{
$class = $this->getRecordClass();
if($class!==null)
$this->_record=Prado::createComponent($class);
else
- throw new TConfigurationException('scaffold_invalid_record_class', $this->getID());
+ {
+ throw new TConfigurationException('scaffold_invalid_record_class',
+ $this->getRecordClass(),$this->getID());
+ }
}
}
return $this->_record;
}
- public function getRecordFinder()
+ /**
+ * @param TActiveRecord Active Record instance.
+ */
+ protected function setRecordObject(TActiveRecord $value)
{
- return TActiveRecord::getRecordFinder(get_class($this->getRecordObject()));
+ $this->_record=$value;
}
- public function setRecordObject($value)
+ /**
+ * @return TActiveRecord Active Record finder instance
+ */
+ protected function getRecordFinder()
{
- if($value instanceof TActiveRecord)
- $this->_record=$value;
- else
- throw new TConfigurationException('scaffold_object_must_be_tactiverecord', $this->getID());
+ return TActiveRecord::getRecordFinder($this->getRecordClass());
}
+ /**
+ * @return string default scaffold stylesheet name
+ */
public function getDefaultStyle()
{
return $this->getViewState('DefaultStyle', 'style');
}
+ /**
+ * @param string default scaffold stylesheet name
+ */
public function setDefaultStyle($value)
{
$this->setViewState('DefaultStyle', TPropertyValue::ensureString($value), 'style');
}
+ /**
+ * Publish the default stylesheet file.
+ */
public function onPreRender($param)
{
parent::onPreRender($param);
$url = $this->publishAsset($this->getDefaultStyle().'.css');
- $cs = $this->getPage()->getClientScript();
- $cs->registerStyleSheetFile($url,$url);
+ $this->getPage()->getClientScript()->registerStyleSheetFile($url,$url);
}
}
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php index a8faa6c8..a792aeb9 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php @@ -1,29 +1,82 @@ <?php
+/**
+ * TScaffoldEditView class and IScaffoldEditRenderer interface file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Scaffold
+ */
+/**
+ * Load scaffold base.
+ */
Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase');
-Prado::using('System.Data.ActiveRecord.Scaffold.InputBuilder.TScaffoldInputBase');
+/**
+ * Template control for editing an Active Record instance.
+ *
+ * The default editor input controls are created based on the column types.
+ *
+ * The editor layout can be specified by a renderer. A renderer is an external
+ * template control that implements IScaffoldEditRenderer.
+ *
+ * The <b>Data</b> of the IScaffoldEditRenderer will be set as the current Active
+ * Record to be edited. The <b>UpdateRecord()</b> method of IScaffoldEditRenderer
+ * is called when request to save the record is requested.
+ *
+ * Validators in the custom external editor template should have the
+ * {@link TBaseValidator::setValidationGroup ValidationGroup} property set to the
+ * value of the {@link getValidationGroup} of the TScaffoldEditView instance
+ * (the edit view instance is the <b>Parent</b> of the IScaffoldEditRenderer in most
+ * cases.
+ *
+ * The <b>RecordClass</b> determines the Active Record class to be edited.
+ * A particular record can be edited by specifying the {@link setRecordPk RecordPk}
+ * value (may be an array for composite keys).
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Scaffold
+ * @since 3.1
+ */
class TScaffoldEditView extends TScaffoldBase
{
- private static $_builders=array();
+ /**
+ * @var IScaffoldEditRenderer custom scaffold edit renderer
+ */
private $_editRenderer;
+ /**
+ * Initialize the editor form if it is Visible.
+ */
public function onLoad($param)
{
if($this->getVisible())
$this->initializeEditForm();
}
+ /**
+ * @return string the class name for scaffold editor. Defaults to empty, meaning not set.
+ */
public function getEditRenderer()
{
return $this->getViewState('EditRenderer', '');
}
+ /**
+ * @param string the class name for scaffold editor. Defaults to empty, meaning not set.
+ */
public function setEditRenderer($value)
{
$this->setViewState('EditRenderer', $value, '');
}
+ /**
+ * @param array Active Record primary key value to be edited.
+ */
public function setRecordPk($value)
{
$this->clearRecordObject();
@@ -31,16 +84,25 @@ class TScaffoldEditView extends TScaffoldBase $this->setViewState('PK', count($val) > 0 ? $val : null);
}
+ /**
+ * @return array Active Record primary key value.
+ */
public function getRecordPk()
{
return $this->getViewState('PK');
}
+ /**
+ * @return TActiveRecord current Active Record instance
+ */
protected function getCurrentRecord()
{
return $this->getRecordObject($this->getRecordPk());
}
+ /**
+ * Initialize the editor form
+ */
public function initializeEditForm()
{
$record = $this->getCurrentRecord();
@@ -60,6 +122,13 @@ class TScaffoldEditView extends TScaffoldBase }
}
+ /**
+ * Instantiate the external edit renderer.
+ * @param TActiveRecord record to be edited
+ * @param string external edit renderer class name.
+ * @throws TConfigurationException raised when renderer is not an
+ * instance of IScaffoldEditRenderer.
+ */
protected function createEditRenderer($record, $classPath)
{
$this->_editRenderer = Prado::createComponent($classPath);
@@ -76,7 +145,10 @@ class TScaffoldEditView extends TScaffoldBase }
}
- protected function repeaterItemCreated($sender, $param)
+ /**
+ * Initialize the default editor using the scaffold input builder.
+ */
+ protected function createRepeaterEditItem($sender, $param)
{
$type = $param->getItem()->getItemType();
if($type==TListItemType::Item || $type==TListItemType::AlternatingItem)
@@ -92,14 +164,16 @@ class TScaffoldEditView extends TScaffoldBase }
}
+ /**
+ * Bubble the command name event. Stops bubbling when the page validator false.
+ * Otherwise, the bubble event is continued.
+ */
public function bubbleEvent($sender, $param)
{
switch(strtolower($param->getCommandName()))
{
case 'save':
- if($this->getPage()->getIsValid())
- return $this->doSave() === true ? false : true;
- return true;
+ return $this->doSave() ? false : true;
case 'clear':
$this->setRecordPk(null);
$this->initializeEditForm();
@@ -109,68 +183,116 @@ class TScaffoldEditView extends TScaffoldBase }
}
+ /**
+ * Check the validators, then tries to save the record.
+ * @return boolean true if the validators are true, false otherwise.
+ */
protected function doSave()
{
- $record = $this->getCurrentRecord();
- if($this->_editRenderer===null)
+ if($this->getPage()->getIsValid())
{
- $table = $this->getTableMetaData();
- $builder = $this->getScaffoldInputBuilder($record);
- foreach($this->getInputRepeater()->getItems() as $item)
+ $record = $this->getCurrentRecord();
+ if($this->_editRenderer===null)
{
- $column = $table->getColumn($item->getCustomData());
- $builder->loadScaffoldInput($this, $item, $column, $record);
+ $table = $this->getTableMetaData();
+ $builder = $this->getScaffoldInputBuilder($record);
+ foreach($this->getInputRepeater()->getItems() as $item)
+ {
+ $column = $table->getColumn($item->getCustomData());
+ $builder->loadScaffoldInput($this, $item, $column, $record);
+ }
}
+ else
+ {
+ $this->_editRenderer->updateRecord($record);
+ }
+ $record->save();
+ return true;
}
- else
- {
- $this->_editRenderer->updateRecord($record);
- }
-
- $record->save();
- return true;
+ return false;
}
+ /**
+ * @return TRepeater default editor input controls repeater
+ */
protected function getInputRepeater()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_repeater');
}
+ /**
+ * @return TButton Button triggered to save the Active Record.
+ */
public function getSaveButton()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_save');
}
+ /**
+ * @return TButton Button to clear the editor inputs.
+ */
public function getClearButton()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_clear');
}
+ /**
+ * @return TButton Button to cancel the edit action (e.g. hide the edit view).
+ */
public function getCancelButton()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_cancel');
}
+ /**
+ * Create the default scaffold editor control factory.
+ * @param TActiveRecord record instance.
+ * @return TScaffoldInputBase scaffold editor control factory.
+ */
protected function getScaffoldInputBuilder($record)
{
+ static $_builders=array();
$class = get_class($record);
- if(!isset(self::$_builders[$class]))
- self::$_builders[$class] = TScaffoldInputBase::createInputBuilder($record);
- return self::$_builders[$class];
+ if(!isset($_builders[$class]))
+ {
+ Prado::using('System.Data.ActiveRecord.Scaffold.InputBuilder.TScaffoldInputBase');
+ $_builders[$class] = TScaffoldInputBase::createInputBuilder($record);
+ }
+ return $_builders[$class];
}
+ /**
+ * @return string editor validation group name.
+ */
public function getValidationGroup()
{
return 'group_'.$this->getUniqueID();
}
}
+/**
+ * IScaffoldEditRenderer interface.
+ *
+ * IScaffoldEditRenderer defines the interface that an edit renderer
+ * needs to implement. Besides the {@link getData Data} property, an edit
+ * renderer also needs to provide {@link updateRecord updateRecord} method
+ * that is called before the save() method is called on the TActiveRecord.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Scaffold
+ * @since 3.1
+ */
interface IScaffoldEditRenderer extends IDataRenderer
{
+ /**
+ * This method should update the record with the user input data.
+ * @param TActiveRecord record to be saved.
+ */
public function updateRecord($record);
}
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl index 8cba7ec4..884ec2a3 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl @@ -1,7 +1,8 @@ +<div class="scaffold_edit_view">
<div class="edit-inputs">
-<com:TRepeater ID="_repeater" onItemCreated="repeaterItemCreated">
+<com:TRepeater ID="_repeater" onItemCreated="createRepeaterEditItem">
<prop:ItemTemplate>
- <div class="edit-item item_<%# $this->ItemIndex % 2 %>
+ <div class="edit-item item_<%# $this->ItemIndex % 2 %>
input_<%# $this->ItemIndex %> property_<%# $this->DataItem->Property %>">
<com:TLabel ID="_label" CssClass="item-label"/>
<span class="item-input">
@@ -16,4 +17,5 @@ <com:TButton ID="_save" Text="Save" CommandName="save" ValidationGroup=<%= $this->ValidationGroup %>/>
<com:TButton ID="_clear" Text="Clear" CommandName="clear" CausesValidation="false"/>
<com:TButton ID="_cancel" Text="Cancel" CommandName="cancel" CausesValidation="false" Visible="false"/>
+</div>
</div>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php index 35c53473..2ac3fe99 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php @@ -1,7 +1,28 @@ <?php
-
+/**
+ * TScaffoldListView class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Scaffold
+ */
+
+/**
+ * Load the scaffold base class.
+ */
Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase');
+/**
+ * TScaffoldListView displays instance of Active Record class.
+ *
+ * @author Wei Zhuo <weizho[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Scaffold
+ * @since 3.1
+ */
class TScaffoldListView extends TScaffoldBase
{
public function onLoad($param)
@@ -32,31 +53,26 @@ class TScaffoldListView extends TScaffoldBase public function onPreRender($param)
{
parent::onPreRender($param);
- $this->initializeItemCount();
$this->loadRecordData();
}
- protected function initializeItemCount()
- {
- $this->_list->setVirtualItemCount($this->getRecordFinder()->count());
- }
-
protected function loadRecordData()
{
+ $this->_list->setVirtualItemCount($this->getRecordFinder()->count());
$finder = $this->getRecordFinder();
- $criteria = $this->getPagingCriteria();
+ $criteria = $this->getRecordCriteria();
$this->_list->setDataSource($finder->findAll($criteria));
$this->_list->dataBind();
}
- protected function getPagingCriteria()
+ protected function getRecordCriteria()
{
$total = $this->_list->getVirtualItemCount();
$limit = $this->_list->getPageSize();
$offset = $this->_list->getCurrentPageIndex()*$limit;
if($offset + $limit > $total)
$limit = $total - $offset;
- $criteria = new TActiveRecordCriteria;
+ $criteria = new TActiveRecordCriteria($this->getSearchCondition(), $this->getSearchParameters());
$criteria->setLimit($limit);
$criteria->setOffset($offset);
$order = explode(' ',$this->_sort->getSelectedValue(), 2);
@@ -65,6 +81,26 @@ class TScaffoldListView extends TScaffoldBase return $criteria;
}
+ public function setSearchCondition($value)
+ {
+ $this->setViewState('SearchCondition', $value);
+ }
+
+ public function getSearchCondition()
+ {
+ return $this->getViewState('SearchCondition');
+ }
+
+ public function setSearchParameters($value)
+ {
+ $this->setViewState('SearchParameters', TPropertyValue::ensureArray($value),array());
+ }
+
+ public function getSearchParameters()
+ {
+ return $this->getViewState('SearchParameters', array());
+ }
+
public function bubbleEvent($sender, $param)
{
switch(strtolower($param->getCommandName()))
@@ -72,21 +108,26 @@ class TScaffoldListView extends TScaffoldBase case 'delete':
return $this->deleteRecord($sender, $param);
case 'edit':
- if(($ctrl=$this->getEditViewControl())!==null)
- {
- if($param instanceof TRepeaterCommandEventParameter)
- {
- $pk = $param->getItem()->getCustomData();
- $ctrl->setRecordPk($pk);
- $ctrl->initializeEditForm();
- }
- }
+ $this->initializeEdit($sender, $param);
}
$this->raiseBubbleEvent($this, $param);
return true;
}
- public function deleteRecord($sender, $param)
+ protected function initializeEdit($sender, $param)
+ {
+ if(($ctrl=$this->getEditViewControl())!==null)
+ {
+ if($param instanceof TRepeaterCommandEventParameter)
+ {
+ $pk = $param->getItem()->getCustomData();
+ $ctrl->setRecordPk($pk);
+ $ctrl->initializeEditForm();
+ }
+ }
+ }
+
+ protected function deleteRecord($sender, $param)
{
if($param instanceof TRepeaterCommandEventParameter)
{
@@ -111,10 +152,10 @@ class TScaffoldListView extends TScaffoldBase $item = $param->getItem();
if(($data = $item->getData()) !== null)
{
- $item->setCustomData($this->getRecordObjectPk($data));
+ $item->setCustomData($this->getRecordPkValues($data));
if(($prop = $item->findControl('_properties'))!==null)
{
- $item->_properties->setDataSource($this->getRecordProperties($data));
+ $item->_properties->setDataSource($this->getRecordPropertyValues($data));
$item->_properties->dataBind();
}
}
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.tpl b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.tpl index 7b8854f0..c70e864d 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.tpl +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.tpl @@ -1,4 +1,4 @@ -
+<div class="scaffold_list_view">
<div class="item-header">
<com:TRepeater ID="_header">
<prop:ItemTemplate>
@@ -21,7 +21,7 @@ PageSize="10">
<prop:ItemTemplate>
<div class="item item_<%# $this->ItemIndex % 2 %>">
-
+
<com:TRepeater ID="_properties">
<prop:ItemTemplate>
<span class="field field_<%# $this->ItemIndex %>">
@@ -29,20 +29,20 @@ </span>
</prop:ItemTemplate>
</com:TRepeater>
-
+
<span class="edit-delete-buttons">
- <com:TButton Text="Edit"
+ <com:TButton Text="Edit"
Visible=<%# $this->NamingContainer->Parent->EditViewID !== Null %>
- CommandName="edit"
+ CommandName="edit"
CssClass="edit-button"
CausesValidation="false" />
- <com:TButton Text="Delete"
- CommandName="delete"
+ <com:TButton Text="Delete"
+ CommandName="delete"
CssClass="delete-button"
CausesValidation="false"
Attributes.onclick="if(!confirm('Are you sure?')) return false;" />
</span>
-
+
</div>
</prop:ItemTemplate>
</com:TRepeater>
@@ -53,4 +53,5 @@ ControlToPaginate="_list"
PageButtonCount="10"
Mode="Numeric"
- OnPageIndexChanged="pageChanged" />
\ No newline at end of file + OnPageIndexChanged="pageChanged" />
+</div>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.php new file mode 100644 index 00000000..a47a1a47 --- /dev/null +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.php @@ -0,0 +1,89 @@ +<?php +
+Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase');
+
+class TScaffoldSearch extends TScaffoldBase
+{
+ private $_list;
+
+ public function getListView()
+ {
+ if($this->_list===null && ($id = $this->getListViewID()) !== null)
+ {
+ $this->_list = $this->getParent()->findControl($id);
+ if($this->_list ===null)
+ throw new TConfigurationException('scaffold_unable_to_find_list_view', $id);
+ }
+ return $this->_list;
+ }
+
+ public function setListView($value)
+ {
+ $this->_list = $value;
+ }
+
+ public function setListViewID($value)
+ {
+ $this->setViewState('ListViewID', $value);
+ }
+
+ public function getListViewID()
+ {
+ return $this->getViewState('ListViewID');
+ }
+
+ public function bubbleEvent($sender, $param)
+ {
+ if(strtolower($param->getCommandName())==='search')
+ {
+ if(($list = $this->getListView()) !== null)
+ {
+ $list->setSearchCondition($this->createSearchCondition());
+ $list->setSearchParameters(array());
+ return false;
+ }
+ }
+ $this->raiseBubbleEvent($this, $param);
+ return true;
+ }
+
+ protected function createSearchCondition()
+ {
+ $table = $this->getTableMetaData();
+ if(strlen($str=$this->getSearchText()->getText()) > 0)
+ return $table->getSearchRegExpCriteria($this->getFields(), $str);
+ }
+
+ protected function getFields()
+ {
+ if(strlen(trim($str=$this->getSearchableFields()))>0)
+ $fields = preg_split('/\s*,\s*/', $str);
+ else
+ $fields = array_keys($this->getTableMetaData()->getColumns());
+ return $fields;
+ }
+
+ public function getSearchableFields()
+ {
+ return $this->getViewState('SearchableFields','');
+ }
+
+ public function setSearchableFields($value)
+ {
+ $this->setViewState('SearchableFields', $value, '');
+ }
+
+ public function getSearchButton()
+ {
+ $this->ensureChildControls();
+ return $this->getRegisteredObject('_search');
+ }
+
+ public function getSearchText()
+ {
+ $this->ensureChildControls();
+ return $this->getRegisteredObject('_textbox');
+ }
+}
+ +?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.tpl b/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.tpl new file mode 100644 index 00000000..a5f56b55 --- /dev/null +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldSearch.tpl @@ -0,0 +1,4 @@ +<span class="scaffold_search">
+<com:TTextBox ID="_textbox" />
+<com:TButton ID="_search" Text="Search" CommandName="search" />
+</span>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php index 668ede61..5401c764 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.php @@ -3,6 +3,7 @@ Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase');
Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldListView');
Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldEditView');
+Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldSearch');
class TScaffoldView extends TScaffoldBase
{
@@ -11,6 +12,7 @@ class TScaffoldView extends TScaffoldBase parent::onLoad($param);
$this->getListView()->copyFrom($this);
$this->getEditView()->copyFrom($this);
+ $this->getSearchControl()->copyFrom($this);
}
public function getListView()
@@ -25,6 +27,12 @@ class TScaffoldView extends TScaffoldBase return $this->getRegisteredObject('_editView');
}
+ public function getSearchControl()
+ {
+ $this->ensureChildControls();
+ return $this->getRegisteredObject('_search');
+ }
+
public function getAddButton()
{
$this->ensureChildControls();
@@ -50,6 +58,7 @@ class TScaffoldView extends TScaffoldBase $this->getListView()->setVisible(false);
$this->getEditView()->setVisible(true);
$this->getAddButton()->setVisible(false);
+ $this->getSearchControl()->setVisible(false);
$this->getEditView()->getCancelButton()->setVisible(true);
$this->getEditView()->getClearButton()->setVisible(false);
}
@@ -59,6 +68,7 @@ class TScaffoldView extends TScaffoldBase $this->getListView()->setVisible(true);
$this->getEditView()->setVisible(false);
$this->getAddButton()->setVisible(true);
+ $this->getSearchControl()->setVisible(true);
}
protected function showAddView($sender, $param)
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.tpl b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.tpl index 0ae8b8b0..01cceb07 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldView.tpl +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldView.tpl @@ -1,7 +1,9 @@ +<div class="scaffold_view">
+<com:TScaffoldSearch ID="_search" ListViewID="_listView" />
<com:TScaffoldListView ID="_listView" EditViewID="_editView" />
-
-<div class="auxilary-button buttons">
+<span class="auxilary-button buttons">
<com:TButton ID="_newButton" Text="Add new record" CssClass="new-button" CommandName="new" />
-</div>
+</span>
-<com:TScaffoldEditView ID="_editView" Visible="false"/>
\ No newline at end of file +<com:TScaffoldEditView ID="_editView" Visible="false"/>
+</div>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Scaffold/style.css b/framework/Data/ActiveRecord/Scaffold/style.css index eb31e9a5..a1fc7a16 100644 --- a/framework/Data/ActiveRecord/Scaffold/style.css +++ b/framework/Data/ActiveRecord/Scaffold/style.css @@ -1,3 +1,4 @@ +/* $Id$ */
body
{
font-family: Cambria, Georgia, "Times New Roman", Times, serif;
@@ -116,7 +117,7 @@ body font-weight: bold;
padding: 0.2em;
}
-.edit-inputs .required-input
+.edit-inputs .required-input, .edit-inputs .required-input2
{
border: 1px solid red;
background-color: #FFF5EE;
diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php index 91ae971a..bdb03596 100644 --- a/framework/Data/ActiveRecord/TActiveRecord.php +++ b/framework/Data/ActiveRecord/TActiveRecord.php @@ -384,6 +384,8 @@ abstract class TActiveRecord extends TComponent /**
* Find records using full SQL, returns corresponding record object.
+ * The names of the column retrieved must be defined in your Active Record
+ * class.
* @param string select SQL
* @param array $parameters
* @return array matching active records.
@@ -439,8 +441,8 @@ abstract class TActiveRecord extends TComponent * $finder->find('Name = ?', $name);
* </code>
* <code>
- * $finder->findByUsernameAndPassword($name,$pass);
- * $finder->findBy_Username_And_Password($name,$pass);
+ * $finder->findByUsernameAndPassword($name,$pass); // OR may be used
+ * $finder->findBy_Username_And_Password($name,$pass); // _OR_ may be used
* $finder->find('Username = ? AND Password = ?', $name, $pass);
* </code>
* <code>
@@ -481,13 +483,43 @@ abstract class TActiveRecord extends TComponent */
private function createCriteriaFromString($method, $condition, $args)
{
- $fields = array();
- foreach(preg_split('/and|_and_/i',$condition) as $field)
- $fields[] = $field.' = ?';
+ $fields = $this->extractMatchingConditions($method, $condition);
$args=count($args) === 1 && is_array($args[0]) ? $args[0] : $args;
if(count($fields)>count($args))
- throw new TActiveRecordException('ar_mismatch_args_exception',$method,count($fields),count($args));
- return new TActiveRecordCriteria(implode(' AND ',$fields),$args);
+ {
+ throw new TActiveRecordException('ar_mismatch_args_exception',
+ $method,count($fields),count($args));
+ }
+ return new TActiveRecordCriteria(implode(' ',$fields),$args);
+ }
+
+ /**
+ * Calculates the AND/OR condition from dynamic method substrings using
+ * table meta data, allows for any AND-OR combinations.
+ * @param string dynamic method name
+ * @param string dynamic method search criteria
+ * @return array search condition substrings
+ */
+ private function extractMatchingConditions($method, $condition)
+ {
+ $meta = $this->getRecordManager()->getRecordGateway()->getMetaData($this);
+ $search = implode('|', $meta->getColumnNames());
+ $regexp = '/('.$search.')(and|_and_|or|_or_)?/i';
+ $matches = array();
+ if(!preg_match_all($regexp, strtolower($condition), $matches,PREG_SET_ORDER))
+ {
+ throw new TActiveRecordException('ar_mismatch_column_names',
+ $method, implode(', ', $meta->getColumnNames()), $meta->getTableName());
+ }
+ $fields = array();
+ foreach($matches as $match)
+ {
+ $sql = $meta->getColumn($match[1])->getName() . ' = ? ';
+ if(count($match) > 2)
+ $sql .= strtoupper(str_replace('_', '', $match[2]));
+ $fields[] = $sql;
+ }
+ return $fields;
}
} ?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/TActiveRecordManager.php b/framework/Data/ActiveRecord/TActiveRecordManager.php index 7f239a34..bd672c3b 100644 --- a/framework/Data/ActiveRecord/TActiveRecordManager.php +++ b/framework/Data/ActiveRecord/TActiveRecordManager.php @@ -164,6 +164,9 @@ class TActiveRecordManager extends TComponent case 'sqlite2': //sqlite 2
Prado::using('System.Data.ActiveRecord.Vendor.TSqliteMetaDataInspector');
return new TSqliteMetaDataInspector($conn);
+ case 'ibm':
+ Prado::using('System.Data.ActiveRecord.Vendor.TIbmMetaDataInspector');
+ return new TIbmMetaDataInspector($conn);
default:
throw new TActiveRecordConfigurationException(
'ar_invalid_database_driver',$driver);
diff --git a/framework/Data/ActiveRecord/Vendor/TDbMetaData.php b/framework/Data/ActiveRecord/Vendor/TDbMetaData.php index 38a82aef..3a959ba4 100644 --- a/framework/Data/ActiveRecord/Vendor/TDbMetaData.php +++ b/framework/Data/ActiveRecord/Vendor/TDbMetaData.php @@ -20,8 +20,7 @@ * @version $Id$
* @package System.Data.ActiveRecord.Vendor
* @since 3.1
- */ -
+ */
abstract class TDbMetaData extends TComponent
{
private $_primaryKeys=array();
@@ -91,6 +90,11 @@ abstract class TDbMetaData extends TComponent return $this->_columns[$name];
}
+ public function getColumnNames()
+ {
+ return array_keys($this->_columns);
+ }
+
/**
* Post process the rows after returning from a 1 row query.
* @param mixed row data, may be null.
@@ -187,7 +191,7 @@ abstract class TDbMetaData extends TComponent foreach($keys as $i => $key)
{
$value = isset($values[$i]) ? $values[$i] : $values[$key];
- $command->bindValue(':'.$key, $value);
+ $this->bindValue($command, ':'.$key, $value);
}
$command->prepare();
}
@@ -249,7 +253,7 @@ abstract class TDbMetaData extends TComponent /**
* Gets a comma delimited string of name parameters for update.
-x * @param array name value pairs of columns for update.
+ * @param array name value pairs of columns for update.
* @return string update named parameter string.
*/
protected function getUpdateBindings($columns)
@@ -294,19 +298,27 @@ x * @param array name value pairs of columns for update. if($criteria->getIsNamedParameters())
{
foreach($criteria->getParameters() as $name=>$value)
- $command->bindValue($name,$value);
+ $this->bindValue($command, $name, $value);
}
else
{
$index=1;
foreach($criteria->getParameters() as $value)
- $command->bindValue($index++,$value);
+ $this->bindValue($command, $index++,$value);
}
}
$command->prepare();
return $command;
}
+ protected function bindValue($command, $name, $value)
+ {
+ if(is_bool($value))
+ $command->bindValue($name,$value, PDO::PARAM_BOOL);
+ else
+ $command->bindValue($name,$value);
+ }
+
/**
* Bind parameter values.
*/
@@ -316,9 +328,9 @@ x * @param array name value pairs of columns for update. foreach($parameters as $key=>$value)
{
if(is_string($key))
- $command->bindValue($key,$value);
+ $this->bindValue($command,$key,$value);
else
- $command->bindValue($index++,$value);
+ $this->bindValue($command, $index++,$value);
}
$command->prepare();
}
@@ -345,5 +357,15 @@ x * @param array name value pairs of columns for update. return implode(', ', $fields);
}
+ /**
+ * @param string ordering column name
+ * @param string ordering direction
+ * @return string DESC or ASC
+ */
+ protected function getOrdering($by, $direction)
+ {
+ $dir = strtolower($direction) == 'desc' ? 'DESC' : 'ASC';
+ return $this->getColumn($by)->getName(). ' '.$dir;
+ }
} ?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Vendor/TDbMetaDataCommon.php b/framework/Data/ActiveRecord/Vendor/TDbMetaDataCommon.php index 826654dc..a41e87ad 100644 --- a/framework/Data/ActiveRecord/Vendor/TDbMetaDataCommon.php +++ b/framework/Data/ActiveRecord/Vendor/TDbMetaDataCommon.php @@ -186,7 +186,7 @@ abstract class TDbMetaDataCommon extends TDbMetaData return $command;
}
-
+
/**
* SQL command to delete records by criteria
* @param TDbConnection database connection.
diff --git a/framework/Data/ActiveRecord/Vendor/TIbmColumnMetaData.php b/framework/Data/ActiveRecord/Vendor/TIbmColumnMetaData.php new file mode 100644 index 00000000..65e40a59 --- /dev/null +++ b/framework/Data/ActiveRecord/Vendor/TIbmColumnMetaData.php @@ -0,0 +1,149 @@ +<?php
+/**
+ * TIbmColumnMetaData class file.
+ *
+ * @author Cesar Ramos <cramos[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Vendor
+ */
+
+/**
+ * TIbmColumnMetaData class.
+ *
+ * Column details for IBM DB2 database. Using php_pdo_ibm.dll extension.
+ *
+ * @author Cesar Ramos <cramos[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Vendor
+ * @since 3.1
+ */
+class TIbmColumnMetaData extends TComponent
+{
+ private $_name;
+ private $_type;
+ private $_length;
+ private $_autoIncrement;
+ private $_default;
+ private $_notNull=true;
+
+ private $_isPrimary=null;
+
+ private $_property;
+
+ /**
+ * Initialize column meta data.
+ *
+ * @param string column name.
+ * @param string column data type.
+ * @param string column data length.
+ * @param boolean column can not be null.
+ * @param string serial name.
+ * @param string default value.
+ */
+ public function __construct($name,$type,$length,$notNull,$autoIncrement,$default,$primary)
+ {
+ $this->_property = $name;
+ $this->_name=$name;
+ $this->_type=$type;
+ $this->_length=$length;
+ $this->_notNull=$notNull;
+ $this->_autoIncrement=$autoIncrement;
+ $this->_default=$default;
+ $this->_isPrimary=$primary;
+ }
+
+ /**
+ * @return string quoted column name.
+ */
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ /**
+ * @return string active record property name
+ */
+ public function getProperty()
+ {
+ return $this->_property;
+ }
+
+ /**
+ * @return boolean true if column is a sequence, false otherwise.
+ */
+ public function hasSequence()
+ {
+ return $this->_autoIncrement;
+ }
+
+ /**
+ * @return null no sequence name.
+ */
+ public function getSequenceName()
+ {
+ return null;
+ }
+
+ /**
+ * @return boolean true if the column is a primary key, or part of a composite primary key.
+ */
+ public function getIsPrimaryKey()
+ {
+ return $this->_isPrimary;
+ }
+
+ /**
+ * @return string column type
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+
+ /**
+ * @return boolean false if column can be null, true otherwise.
+ */
+ public function getNotNull()
+ {
+ return $this->_notNull;
+ }
+
+ /**
+ * @return boolean true if column has default value, false otherwise.
+ */
+ public function hasDefault()
+ {
+ return $this->_default !== null;
+ }
+
+ /**
+ * @return string default column value.
+ */
+ public function getDefaultValue()
+ {
+ return $this->_default;
+ }
+
+ /**
+ * @return string PHP primative type derived from the column type.
+ */
+ public function getPHPType()
+ {
+ switch(strtolower($this->_type))
+ {
+ case 'smallint': case 'integer':
+ return 'integer';
+ case 'real': case 'float': case 'double': case 'decimal': case 'bigint':
+ return 'float';
+ default:
+ return 'string';
+ }
+ }
+
+}
+
+?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Vendor/TIbmMetaData.php b/framework/Data/ActiveRecord/Vendor/TIbmMetaData.php new file mode 100644 index 00000000..4f923406 --- /dev/null +++ b/framework/Data/ActiveRecord/Vendor/TIbmMetaData.php @@ -0,0 +1,80 @@ +<?php
+
+/**
+ * TIbmMetaData class file.
+ *
+ * @author Cesar Ramos <cramos[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Vendor
+ */
+Prado::using('System.Data.ActiveRecord.Vendor.TDbMetaDataCommon');
+
+/**
+ * TIbmMetaData class.
+ *
+ * Column details for IBM DB2 database. Using php_pdo_ibm.dll extension.
+ *
+ * Does not support LIMIT and OFFSET criterias.
+ *
+ * @author Cesar Ramos <cramos[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Vendor
+ * @since 3.1
+ */
+class TIbmMetaData extends TDbMetaDataCommon
+{
+ /**
+ * Build the SQL search string from the criteria object for IBM DB2 database.
+ * @param TDbConnection database connection.
+ * @param TActiveRecordCriteria search criteria.
+ * @return string SQL search.
+ */
+ protected function getSqlFromCriteria($conn, $criteria)
+ {
+ if($criteria===null) return '';
+ $sql = '';
+ if(($condition = $criteria->getCondition())!==null)
+ $sql .= ' WHERE '.$condition;
+ $orders=array();
+ foreach($criteria->getOrdersBy() as $by=>$ordering)
+ $orders[] = $this->getOrdering($by, $ordering);
+ if(count($orders) > 0)
+ $sql .= ' ORDER BY '.implode(', ', $orders);
+ //if(($limit = $criteria->getLimit())!==null)
+ //{
+ // $sql .= ' FETCH FIRST '.intval($limit).' ROWS ONLY';
+ //}
+ return strlen($sql) > 0 ? $sql : '';
+ }
+
+ /**
+ * Lowercase the data keys, IBM DB2 returns uppercase column names
+ * @param mixed record row
+ * @return array record row
+ */
+ public function postQueryRow($row)
+ {
+ if(!is_array($row)) return $row;
+ $result=array();
+ foreach($row as $k=>$v)
+ $result[strtolower($k)]=$v;
+ return $result;
+ }
+
+ /**
+ * Lowercase the data keys, IBM DB2 returns uppercase column names
+ * @param mixed record row
+ * @return array record row
+ */
+ public function postQuery($rows)
+ {
+ $data = array();
+ foreach($rows as $k=>$v)
+ $data[$k] = $this->postQueryRow($v);
+ return $data;
+ }
+}
+?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Vendor/TIbmMetaDataInspector.php b/framework/Data/ActiveRecord/Vendor/TIbmMetaDataInspector.php new file mode 100644 index 00000000..0ccc05ae --- /dev/null +++ b/framework/Data/ActiveRecord/Vendor/TIbmMetaDataInspector.php @@ -0,0 +1,113 @@ +<?php
+/**
+ * TIbmMetaDataInspector class file.
+ *
+ * @author Cesar Ramos <cramos[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Vendor
+ */
+Prado::using('System.Data.ActiveRecord.Vendor.TDbMetaDataInspector');
+Prado::using('System.Data.ActiveRecord.Vendor.TIbmColumnMetaData');
+Prado::using('System.Data.ActiveRecord.Vendor.TIbmMetaData');
+
+/**
+ * TIbmMetaDataInspector class.
+ *
+ * Column details for IBM DB2 database. Using php_pdo_ibm.dll extension.
+ *
+ * @author Cesar Ramos <cramos[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Data.ActiveRecord.Vendor
+ * @since 3.1
+ */
+class TIbmMetaDataInspector extends TDbMetaDataInspector
+{
+ private $_schema;
+
+ /**
+ * @param string default schema.
+ */
+ public function setSchema($schema)
+ {
+ $this->_schema=$schema;
+ }
+
+ /**
+ * @return string default schema.
+ */
+ public function getSchema()
+ {
+ return $this->_schema;
+ }
+ /**
+ * Get the column definitions for given table.
+ * @param string table name.
+ * @return array column name value pairs of column meta data.
+ */
+ protected function getColumnDefinitions($table)
+ {
+ if(count($parts= explode('.', $table)) > 1)
+ {
+ $tablename = $parts[1];
+ $schema = $parts[0];
+ }
+ else
+ {
+ $tablename = $parts[0];
+ $schema = $this->getSchema();
+ }
+ $sql="SELECT * FROM SYSCAT.COLUMNS WHERE TABNAME='".strtoupper($tablename)."'";
+ if ($schema)
+ $sql=$sql." AND TABSCHEMA='".strtoupper($schema)."'";
+
+ $conn = $this->getDbConnection();
+ $conn->setActive(true);
+ $command = $conn->createCommand($sql);
+ $command->prepare();
+ $result=$command->query($sql);
+ foreach ($result as $col)
+ $cols[strtolower($col['COLNAME'])] = $this->getColumnMetaData($col);
+ return $cols;
+ }
+
+ protected function getColumnMetaData($col)
+ {
+ $name = strtolower($col['COLNAME']);
+ $type = $col['TYPENAME'];
+ $length = $col['LENGTH'];
+ $notNull = $col['NULLS']==='N';
+ $autoIncrement=$col['IDENTITY']==='N';
+ $default = $col['DEFAULT'];
+ $primaryKey = $col['KEYSEQ']?1:0;
+ return new TIbmColumnMetaData($name,$type,$length,$notNull,$autoIncrement,$default,$primaryKey);
+ }
+
+ /**
+ * Not implemented, IBM does not always have foreign key constraints.
+ */
+ protected function getConstraintKeys($table)
+ {
+ return array('primary'=>array(), 'foreign'=>array());
+ }
+
+ /**
+ * Create a new instance of meta data.
+ * @param string table name
+ * @param array column meta data
+ * @param array primary key meta data
+ * @param array foreign key meta data.
+ * @return TDbMetaData table meta data.
+ */
+ protected function createMetaData($table, $columns, $primary, $foreign)
+ {
+ $pks = array();
+ foreach($columns as $name=>$column)
+ if($column->getIsPrimaryKey())
+ $pks[] = $name;
+ return new TIbmMetaData($table,$columns,$pks);
+ }
+}
+?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Vendor/TMysqlMetaData.php b/framework/Data/ActiveRecord/Vendor/TMysqlMetaData.php index 0cbd0b7c..03aba53f 100644 --- a/framework/Data/ActiveRecord/Vendor/TMysqlMetaData.php +++ b/framework/Data/ActiveRecord/Vendor/TMysqlMetaData.php @@ -1,4 +1,4 @@ -<?php +<?php
/**
* TMysqlMetaData class file.
*
@@ -48,10 +48,24 @@ class TMysqlMetaData extends TDbMetaDataCommon return strlen($sql) > 0 ? $sql : '';
}
- protected function getOrdering($by, $direction)
+ public function getSearchRegExpCriteria($fields, $keywords)
{
- $dir = strtolower($direction) == 'desc' ? 'DESC' : 'ASC';
- return $this->getColumn($by)->getName(). ' '.$dir;
+ if(strlen(trim($keywords)) == 0) return '';
+ $words = preg_split('/\s/', preg_quote($keywords, '\''));
+ $result = array();
+ foreach($fields as $field)
+ {
+ $column = $this->getColumn($field);
+ $result[] = $this->getRegexpCriteriaStr($column->getName(), $words);
+ }
+ return '('.implode(' OR ', $result).')';
+ }
+
+ protected function getRegexpCriteriaStr($column, $words)
+ {
+ $regexp = implode('|', $words);
+ return "({$column} REGEXP '{$regexp}')";
}
+
}
?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Vendor/TMysqlMetaDataInspector.php b/framework/Data/ActiveRecord/Vendor/TMysqlMetaDataInspector.php index 5e438e37..23c483d1 100644 --- a/framework/Data/ActiveRecord/Vendor/TMysqlMetaDataInspector.php +++ b/framework/Data/ActiveRecord/Vendor/TMysqlMetaDataInspector.php @@ -1,4 +1,4 @@ -<?php +<?php
/**
* TMysqlMetaDataInspector class file.
*
@@ -39,7 +39,7 @@ class TMysqlMetaDataInspector extends TDbMetaDataInspector $command = $conn->createCommand($sql);
$command->prepare();
foreach($command->query() as $col)
- $cols[$col['Field']] = $this->getColumnMetaData($col);
+ $cols[strtolower($col['Field'])] = $this->getColumnMetaData($col);
return $cols;
}
@@ -51,7 +51,8 @@ class TMysqlMetaDataInspector extends TDbMetaDataInspector $autoIncrement=is_int(strpos(strtolower($col['Extra']), 'auto_increment'));
$default = $col['Default'];
$primaryKey = $col['Key']==='PRI';
- return new TMysqlColumnMetaData($col['Field'],$name,$type,$notNull,$autoIncrement,$default,$primaryKey);
+ return new TMysqlColumnMetaData(strtolower($col['Field']),$name,$type,
+ $notNull,$autoIncrement,$default,$primaryKey);
}
/**
diff --git a/framework/Data/ActiveRecord/Vendor/TPgsqlColumnMetaData.php b/framework/Data/ActiveRecord/Vendor/TPgsqlColumnMetaData.php index a51c435d..2774bb54 100644 --- a/framework/Data/ActiveRecord/Vendor/TPgsqlColumnMetaData.php +++ b/framework/Data/ActiveRecord/Vendor/TPgsqlColumnMetaData.php @@ -44,13 +44,30 @@ class TPgsqlColumnMetaData extends TComponent {
$this->_property=$property;
$this->_name=$name;
- $this->_type=$type;
$this->_length=$length;
+ $this->processType($type);
$this->_notNull=$notNull;
$this->_sequenceName=$serial;
$this->_default=$default;
}
+ protected function processType($type)
+ {
+ if(is_int($pos=strpos($type, '(')))
+ {
+ $match=array();
+ if(preg_match('/\((.*)\)/', $type, $match))
+ {
+ $this->_length=floatval($match[1]);
+ $this->_type = substr($type,0,$pos);
+ }
+ else
+ $this->_type = $type;
+ }
+ else
+ $this->_type = $type;
+ }
+
/**
* @return string quoted column name.
*/
diff --git a/framework/Data/ActiveRecord/Vendor/TPgsqlMetaData.php b/framework/Data/ActiveRecord/Vendor/TPgsqlMetaData.php index d968267a..45e9c7e4 100644 --- a/framework/Data/ActiveRecord/Vendor/TPgsqlMetaData.php +++ b/framework/Data/ActiveRecord/Vendor/TPgsqlMetaData.php @@ -48,11 +48,31 @@ class TPgsqlMetaData extends TDbMetaDataCommon return strlen($sql) > 0 ? $sql : '';
}
- protected function getOrdering($by, $direction)
+ public function getSearchRegExpCriteria($fields, $keywords)
{
- $dir = strtolower($direction) == 'desc' ? 'DESC' : 'ASC';
- return $this->getColumn($by)->getName(). ' '.$dir;
+ if(strlen(trim($keywords)) == 0) return '';
+ $words = preg_split('/\s/', preg_quote($keywords, '\''));
+ $result = array();
+ foreach($fields as $field)
+ {
+ $column = $this->getColumn($field);
+ if($this->isSearchableColumn($column))
+ $result[] = $this->getRegexpCriteriaStr($column->getName(), $words);
+ }
+ return '('.implode(' OR ', $result).')';
}
+
+ protected function isSearchableColumn($column)
+ {
+ $type = strtolower($column->getType());
+ return $type === 'character varying' || $type === 'varchar' ||
+ $type === 'character' || $type === 'char' || $type === 'text';
+ }
+ protected function getRegexpCriteriaStr($column, $words)
+ {
+ $regexp = implode('|', $words);
+ return "({$column} ~ '{$regexp}')";
+ }
} ?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/Vendor/TPgsqlMetaDataInspector.php b/framework/Data/ActiveRecord/Vendor/TPgsqlMetaDataInspector.php index 2f7202cf..16326353 100644 --- a/framework/Data/ActiveRecord/Vendor/TPgsqlMetaDataInspector.php +++ b/framework/Data/ActiveRecord/Vendor/TPgsqlMetaDataInspector.php @@ -130,7 +130,7 @@ EOD; $command->bindValue(':schema', $schema);
$cols = array();
foreach($command->query() as $col)
- $cols[$col['attname']] = $this->getColumnMetaData($schema,$col);
+ $cols[strtolower($col['attname'])] = $this->getColumnMetaData($schema,$col);
return $cols;
}
@@ -148,19 +148,26 @@ EOD; // A specific constant in the 7.0 source, the length is offset by 4.
$length = $col['atttypmod'] > 0 ? $col['atttypmod'] - 4 : null;
$notNull = $col['attnotnull'];
- $serial = $col['attisserial'] ? $schema.'.'.$this->getSerialName($col['adsrc']) : null;
+ $nextval_serial = substr($col['adsrc'],0,8) === 'nextval(';
+ $serial = $col['attisserial'] || $nextval_serial ? $this->getSerialName($schema,$col['adsrc']) : null;
$default = $serial === null && $col['atthasdef'] ? $col['adsrc'] : null;
- return new TPgsqlColumnMetaData($col['attname'],$name,$type,$length,$notNull,$serial,$default);
+ return new TPgsqlColumnMetaData(strtolower($col['attname']),$name,
+ $type,$length,$notNull,$serial,$default);
}
/**
* @return string serial name if found, null otherwise.
*/
- protected function getSerialName($src)
+ protected function getSerialName($schema,$src)
{
$matches = array();
- if(preg_match('/nextval\(\'([^\']+)\'::regclass\)/i',$src,$matches))
- return $matches[1];
+ if(preg_match('/nextval\([^\']*\'([^\']+)\'[^\)]*\)/i',$src,$matches))
+ {
+ if(is_int(strpos($matches[1], '.')))
+ return $matches[1];
+ else
+ return $schema.'.'.$matches[1];
+ }
}
/**
diff --git a/framework/Data/ActiveRecord/Vendor/TSqliteMetaData.php b/framework/Data/ActiveRecord/Vendor/TSqliteMetaData.php index c82a99ad..c44d73cb 100644 --- a/framework/Data/ActiveRecord/Vendor/TSqliteMetaData.php +++ b/framework/Data/ActiveRecord/Vendor/TSqliteMetaData.php @@ -48,10 +48,23 @@ class TSqliteMetaData extends TDbMetaDataCommon return strlen($sql) > 0 ? $sql : '';
}
- protected function getOrdering($by, $direction)
+ public function getSearchRegExpCriteria($fields, $keywords)
{
- $dir = strtolower($direction) == 'desc' ? 'DESC' : 'ASC';
- return $this->getColumn($by)->getName(). ' '.$dir;
+ if(strlen(trim($keywords)) == 0) return '';
+ $words = array();
+ preg_match_all('/([a-zA-Z0-9-+]+)/', $keywords, $words);
+ $result = array();
+ foreach($fields as $field)
+ $result[] = $this->getLikeCriteriaStr($this->getColumn($field)->getName(), $words[0]);
+ return '('.implode(' OR ', $result).')';
+ }
+
+ protected function getLikeCriteriaStr($column, $words)
+ {
+ $result=array();
+ foreach($words as $word)
+ $result[] = "({$column} LIKE \"%{$word}%\")";
+ return '('.implode(' AND ', $result).')';
}
/**
diff --git a/framework/Data/ActiveRecord/Vendor/TSqliteMetaDataInspector.php b/framework/Data/ActiveRecord/Vendor/TSqliteMetaDataInspector.php index 3621c666..1d4599a8 100644 --- a/framework/Data/ActiveRecord/Vendor/TSqliteMetaDataInspector.php +++ b/framework/Data/ActiveRecord/Vendor/TSqliteMetaDataInspector.php @@ -55,7 +55,7 @@ class TSqliteMetaDataInspector extends TDbMetaDataInspector $command->prepare();
$cols = array();
foreach($command->query() as $col)
- $cols[$col['name']] = $this->getColumnMetaData($col);
+ $cols[strtolower($col['name'])] = $this->getColumnMetaData($col);
return $cols;
}
@@ -73,7 +73,8 @@ class TSqliteMetaDataInspector extends TDbMetaDataInspector $primary = $col['pk']==='1';
$autoIncrement = strtolower($type)==='integer' && $primary;
$default = $col['dflt_value'];
- return new TSqliteColumnMetaData($col['name'],$name,$type,$notNull,$autoIncrement,$default,$primary);
+ return new TSqliteColumnMetaData(strtolower($col['name']),$name,$type,
+ $notNull,$autoIncrement,$default,$primary);
}
/**
diff --git a/framework/I18N/core/ChoiceFormat.php b/framework/I18N/core/ChoiceFormat.php index 29391135..d36ab57b 100644 --- a/framework/I18N/core/ChoiceFormat.php +++ b/framework/I18N/core/ChoiceFormat.php @@ -20,18 +20,18 @@ /**
* ChoiceFormat class.
- *
- * ChoiceFormat converts between ranges of numeric values and string
+ *
+ * ChoiceFormat converts between ranges of numeric values and string
* names for those ranges.
*
- * A ChoiceFormat splits the real number line -Inf to +Inf into two or
- * more contiguous ranges. Each range is mapped to a string.
- * ChoiceFormat is generally used in a MessageFormat for displaying
+ * A ChoiceFormat splits the real number line -Inf to +Inf into two or
+ * more contiguous ranges. Each range is mapped to a string.
+ * ChoiceFormat is generally used in a MessageFormat for displaying
* grammatically correct plurals such as "There are 2 files."
*
* <code>
* $string = '[0] are no files |[1] is one file |(1,Inf] are {number} files';
- *
+ *
* $formatter = new MessageFormat(...); //init for a source
* $translated = $formatter->format($string);
*
@@ -44,7 +44,7 @@ * # <t>[1,2]</t> -- accepts values between 1 and 2, inclusive.
* # <t>(1,2)</t> -- accepts values between 1 and 2, excluding 1 and 2.
* # <t>{1,2,3,4}</t> -- only values defined in the set are accepted.
- * # <t>[-Inf,0)</t> -- accepts value greater or equal to negative infinity
+ * # <t>[-Inf,0)</t> -- accepts value greater or equal to negative infinity
* and strictly less than 0
* Any non-empty combinations of the delimiters of square and round brackets
* are acceptable.
@@ -57,26 +57,26 @@ class ChoiceFormat {
/**
* The pattern to validate a set notation
- * @var string
+ * @var string
*/
- protected $validate = '/[\(\[\{]|[-Inf\d]+|,|[\+Inf\d]+|[\)\]\}]/ms';
+ protected $validate = '/[\(\[\{]|[-Inf\d:\s]+|,|[\+Inf\d\s:\?\-=!><%\|&\(\)]+|[\)\]\}]/ms';
/**
* The pattern to parse the formatting string.
- * @var string
+ * @var string
*/
- protected $parse = '/\s?\|?([\(\[\{]([-Inf\d]+,?[\+Inf\d]*)+[\)\]\}])\s?/';
+ protected $parse = '/\s*\|?([\(\[\{]([-Inf\d:\s]+,?[\+Inf\d\s:\?\-=!><%\|&\(\)]*)+[\)\]\}])\s*/';
/**
* The value for positive infinity.
- * @var float
+ * @var float
*/
protected $inf;
/**
* Constructor.
- */
+ */
function __construct()
{
$this->inf = -log(0);
@@ -88,19 +88,23 @@ class ChoiceFormat * @param float the number to test.
* @param string the set, in set notation.
* @return boolean true if number is in the set, false otherwise.
- */
+ */
function isValid($number, $set)
{
$n = preg_match_all($this->validate,$set,$matches,PREG_SET_ORDER);
-
+
if($n < 3) throw new Exception("Invalid set \"{$set}\"");
-
+
+ if(preg_match('/\{\s*n:([^\}]+)\}/', $set, $def))
+ {
+ return $this->isValidSetNotation($number, $def[1]);
+ }
+
$leftBracket = $matches[0][0];
$rightBracket = $matches[$n-1][0];
$i = 0;
$elements = array();
-
foreach($matches as $match)
{
$string = $match[0];
@@ -132,19 +136,32 @@ class ChoiceFormat $right = $number <= $elements[$total-1];
else if($rightBracket == ')')
$right = $number < $elements[$total-1];
-
- if($left && $right) return true;
+
+ if($left && $right) return true;
return false;
- }
+ }
+ protected function isValidSetNotation($number, $set)
+ {
+ $str = '$result = '.str_replace('n', '$number', $set).';';
+ try
+ {
+ eval($str);
+ return $result;
+ }
+ catch(Exception $e)
+ {
+ return false;
+ }
+ }
/**
- * Parse a choice string and get a list of sets and a list of strings
+ * Parse a choice string and get a list of sets and a list of strings
* corresponding to the sets.
* @param string the string containing the choices
* @return array array($sets, $strings)
- */
+ */
function parse($string)
{
$n = preg_match_all($this->parse,$string,$matches, PREG_OFFSET_CAPTURE);
@@ -157,19 +174,19 @@ class ChoiceFormat {
$len = strlen($offset[$i][0]);
$begin = $i == 0? $len : $offset[$i][1] + $len;
- $end = $i == $n-1 ? strlen($string) : $offset[$i+1][1];
+ $end = $i == $n-1 ? strlen($string) : $offset[$i+1][1];
$strings[] = substr($string, $begin, $end - $begin);
}
return array($sets, $strings);
}
/**
- * For the choice string, and a number, find and return the
+ * For the choice string, and a number, find and return the
* string that satisfied the set within the choices.
* @param string the choices string.
* @param float the number to test.
* @return string the choosen string.
- */
+ */
public function format($string, $number)
{
list($sets, $strings) = $this->parse($string);
diff --git a/framework/Web/Services/TSoapService.php b/framework/Web/Services/TSoapService.php index 087b5664..e598d796 100644 --- a/framework/Web/Services/TSoapService.php +++ b/framework/Web/Services/TSoapService.php @@ -287,10 +287,10 @@ class TSoapServer extends TApplicationComponent private $_uri=''; private $_classMap; private $_persistent=false; - private $_wsdlUri='';
-
- private $_requestedMethod;
-
+ private $_wsdlUri=''; + + private $_requestedMethod; + private $_server; /** @@ -321,7 +321,7 @@ class TSoapServer extends TApplicationComponent { Prado::using($provider); $providerClass=($pos=strrpos($provider,'.'))!==false?substr($provider,$pos+1):$provider; - $this->guessMethodCallRequested($providerClass);
+ $this->guessMethodCallRequested($providerClass); $server=$this->createServer(); $server->setClass($providerClass, $this); if($this->_persistent) @@ -330,72 +330,73 @@ class TSoapServer extends TApplicationComponent else $server=$this->createServer(); try - {
+ { $server->handle(); } catch (Exception $e) - {
- if($this->getApplication()->getMode()===TApplicationMode::Debug)
- $this->fault($e->getMessage(), $e->__toString());
- else
+ { + if($this->getApplication()->getMode()===TApplicationMode::Debug) + $this->fault($e->getMessage(), $e->__toString()); + else $this->fault($e->getMessage()); } - }
-
- /**
- * Generate a SOAP fault message.
- * @param string message title
- * @param mixed message details
- * @param string message code, defalt is 'SERVER'.
- * @param string actors
- * @param string message name
- */
- public function fault($title, $details='', $code='SERVER', $actor='', $name='')
- {
- $this->_server->fault($code, $title, $actor, $details, $name);
- }
-
- /**
- * Guess the SOAP method request from the actual SOAP message
- *
- * @param string $class current handler class.
- */
- protected function guessMethodCallRequested($class)
- {
- $namespace = $class.'wsdl';
- $message = file_get_contents("php://input");
- $matches= array();
- if(preg_match('/xmlns:([^=]+)="urn:'.$namespace.'"/', $message, $matches))
- {
- if(preg_match('/<'.$matches[1].':([a-zA-Z_]+[a-zA-Z0-9_]+)/', $message, $method))
- {
- $this->_requestedMethod = $method[1];
- }
- }
- }
-
- /**
- * Soap method guessed from the SOAP message received.
- * @return string soap method request, null if not found.
- */
- public function getRequestedMethod()
- {
- return $this->_requestedMethod;
- } - - /** - * Creates the SoapServer instance.
+ } + + /** + * Generate a SOAP fault message. + * @param string message title + * @param mixed message details + * @param string message code, defalt is 'SERVER'. + * @param string actors + * @param string message name + */ + public function fault($title, $details='', $code='SERVER', $actor='', $name='') + { + Prado::trace('SOAP-Fault '.$code. ' '.$title.' : '.$details, 'System.Web.Services.TSoapService'); + $this->_server->fault($code, $title, $actor, $details, $name); + } + + /** + * Guess the SOAP method request from the actual SOAP message + * + * @param string $class current handler class. + */ + protected function guessMethodCallRequested($class) + { + $namespace = $class.'wsdl'; + $message = file_get_contents("php://input"); + $matches= array(); + if(preg_match('/xmlns:([^=]+)="urn:'.$namespace.'"/', $message, $matches)) + { + if(preg_match('/<'.$matches[1].':([a-zA-Z_]+[a-zA-Z0-9_]+)/', $message, $method)) + { + $this->_requestedMethod = $method[1]; + } + } + } + + /** + * Soap method guessed from the SOAP message received. + * @return string soap method request, null if not found. + */ + public function getRequestedMethod() + { + return $this->_requestedMethod; + } + + /** + * Creates the SoapServer instance. * @return SoapServer */ protected function createServer() - {
- if($this->_server===null)
- {
+ { + if($this->_server===null) + { if($this->getApplication()->getMode()===TApplicationMode::Debug) ini_set("soap.wsdl_cache_enabled",0); - $this->_server = new SoapServer($this->getWsdlUri(),$this->getOptions());
+ $this->_server = new SoapServer($this->getWsdlUri(),$this->getOptions()); } - return $this->_server;
+ return $this->_server; } /** |