Location: PHPKode > projects > Sierra-php PHP Application Framework > sierra/lib/model/SRA_WSRequest.php
<?php
// {{{ Header
/*
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | SIERRA : PHP Application Framework  http://code.google.com/p/sierra-php |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | Copyright 2005 Jason Read                                               |
 |                                                                         |
 | Licensed under the Apache License, Version 2.0 (the "License");         |
 | you may not use this file except in compliance with the License.        |
 | You may obtain a copy of the License at                                 |
 |                                                                         |
 |     http://www.apache.org/licenses/LICENSE-2.0                          |
 |                                                                         |
 | Unless required by applicable law or agreed to in writing, software     |
 | distributed under the License is distributed on an "AS IS" BASIS,       |
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.|
 | See the License for the specific language governing permissions and     |
 | limitations under the License.                                          |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 */
// }}}

// {{{ Imports

// }}}

// {{{ Constants
/**
 * identifies that the service request is to create a new entity
 * @type string
 */
define('SRA_WS_REQUEST_CREATE', 'create');

/**
 * identifies that the service request is to delete an existing entity
 * @type string
 */
define('SRA_WS_REQUEST_DELETE', 'delete');

/**
 * the identifier that can be used in "include-attrs" to identify the primary 
 * key attribute
 * @type string
 */
define('SRA_WS_REQUEST_PK', '_pk_');

/**
 * identifies that the service request is to retrieve existing entities
 * @type string
 */
define('SRA_WS_REQUEST_RETRIEVE', 'retrieve');

/**
 * identifies that a request could not be performed because the app specified 
 * is not valid
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_APP', 'invalid-app');

/**
 * identifies that a request could not be performed because attributes were set 
 * that are not allowed to be set by the service or if attributes set do not 
 * exist or if attributes set are read only
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_ATTRS', 'invalid-attrs');

/**
 * identifies that an update/delete request that failed because the primary key 
 * specified was not valid
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_PK', 'invalid-pk');

/**
 * identifies that a request could not be performed because the output format 
 * requested is not valid for this service
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_FORMAT', 'invalid-format');

/**
 * identifies that a request could not be performed because the input specified 
 * for an update or create action did not pass validation. if this occurs, the 
 * "response" will be populated with the error messages resulting from the 
 * failed validation
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_INPUT', 'validation-error');

/**
 * identifies that a request could not be performed because the limit requested 
 * is not allowed for this service
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_LIMIT', 'invalid-limit');

/**
 * identifies that a request could not be performed because the output 
 * meta-format requested is not valid for this service
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_META_FORMAT', 'invalid-meta-format');

/**
 * identifies that a request could not be performed because the protocol used 
 * to invoke it is not allowed (rest or soap)
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_PROTO', 'invalid-protocol');

/**
 * identifies that a request could not be performed because the request 
 * specified was not valid. the server logs will provide more detail on the 
 * reason for this error
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_REQUEST', 'invalid-request');

/**
 * identifies that a request could not be performed because a request was made 
 * for an invalid service
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_INVALID_SERVICE', 'invalid-service');

/**
 * identifies that a request could not be performed because the client IP 
 * address is not allowed
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_IP_NOT_ALLOWED', 'ip-not-allowed');

/**
 * identifies that a request could not be performed because of another 
 * unspecified error. basically, anything else that can go wrong will fall under 
 * this category. the server logs will provide more detail on the reason for 
 * this error
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_FAILED', 'failed');

/**
 * identifies that a request could not be performed because the action requested 
 * (create, delete, retrieve or update) is not allowed via the web service 
 * specified
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_NOT_ALLOWED', 'not-allowed');

/**
 * identifies that a request could not be performed because http authentication 
 * failed
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_AUTH_FAILED', 'authentication-failed');

/**
 * identifies that a request to retrieve buffered results from a prior async 
 * invocation could not be performed because the buffer result is not available 
 * yet. if this response code is returned, you may wish to retry your request 
 * again after a short interval
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_RESULTS_NOT_AVAILABLE', 'not-available');

/**
 * identifies that a request to retrieve buffered results from a prior async 
 * invocation could not be performed because the 
 * SRA_WS_GATEWAY_REQUEST_BUFFER_TIMEOUT theshold was reached
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_TIMEOUT', 'timeout');

/**
 * identifies that a request was performed successfully
 * @type string
 */
define('SRA_WS_REQUEST_STATUS_SUCCESS', 'success');

/**
 * identifies that the service request is to update an existing entity
 * @type string
 */
define('SRA_WS_REQUEST_UPDATE', 'update');

/**
 * identifies the key within the results produces by a service of type 
 * SRA_WS_GLOBAL_TYPE_METHOD specifying the total count (count without 
 * applying limit or offset)
 * @type string
 */
define('SRA_WS_RESULT_COUNT_KEY', '_resultCount');
// }}}

// {{{ SRA_WSRequest
/**
 * This class is used to define an web service invocation
 * @author  Jason Read <hide@address.com>
 * @package sierra.model
 */
class SRA_WSRequest {
  /**
	 * the web service name
	 * @type string
	 */
	var $_id;
  
  /**
	 * identifies the action to take place for this service request. will 
   * correspond with one of the SRA_WS_REQUEST_* constants
	 * @type string
	 */
	var $_action;
  
  /**
	 * the application for this request
	 * @type string
	 */
	var $_app;
  
  /**
	 * specifies whether or not the output of this request should be buffered to a 
   * session variable instead of output to the client
	 * @type boolean
	 */
  var $_asynchronous;
  
  /**
	 * defines the names and values of the attributes to set if the action is 
   * SRA_WS_REQUEST_CREATE or SRA_WS_REQUEST_UPDATE. these will be subject to 
   * validation according to the constraints specified for the service. equality 
   * constraints will automatically be set and override any specified in the 
   * request. if any constraint groups fail to validate an attribute attempting 
   * to be set in the new entity, the gateway will return the status code 
   * SRA_WS_REQUEST_STATUS_NOT_ALLOWED
	 * @type array
	 */
	var $_attrs = NULL;
  
  /**
	 * optional constraint groups that should be applied to this request
	 * @type SRA_WSConstraintGroup[]
	 */
	var $_constraintGroups = array();
  
  /**
	 * a reference to the dao for non-global services
	 * @type DAO
	 */
	var $_dao;
  
  /**
	 * the formatting string to use in the response for date values. if not 
   * specified, the application date-only-format will be used
	 * @type string
	 */
	var $_dateFormat;
  
  /**
	 * for non-global requests when the request pertains to multiple entities
	 * @type object[]
	 */
	var $_entities;
  
  /**
	 * the names of attributes that should be excluded for this request
	 * @type array
	 */
	var $_excludeAttrs;
  
  /**
   * the desired response format for this request. either "json", "xml" or "raw"
   * @type string
   */
  var $_format;
  
  /**
   * TRUE if this request is for a global server (_server will be an 
   * SRA_WSGlobal instance)
   * @type boolean
   */
  var $_global = FALSE;
  
  /**
	 * the names of attributes that should be included for this request
	 * @type array
	 */
	var $_includeAttrs;
  
  /**
   * whether or not this is a soap request
   * @type boolean
   */
  var $_isSoap;
  
  /**
   * if true and the "format" is "json", date values will be encoded using the 
   * javascript Date constructor
   * @type boolean
   */
  var $_jsDates;
  
  /**
	 * the limit for this web service request
	 * @type int
	 */
	var $_limit;
  
  /**
	 * the desired response metadata format. either "json", "xml" or "none"
	 * @type string
	 */
	var $_metaFormat;
  
  /**
   * the request result set offset
   * @type int
   */
  var $_offset;
  
  /**
	 * the params associated with this web service request
	 * @type SRA_WSParam[]
	 */
	var $_params = array();
  
  /**
   * password for authentication. user and password can also be specified in the 
   * http headers. however, if user or password are specified in the get 
   * parameters or ws-request-xml, they will override the http header values
   * @type string
   */
  var $_password;
  
  /**
   * used to store the results of invoking the process method
   * @type boolean
   */
  var $_processed;
  
  /**
	 * primary key of the entity to retrieve, delete or update (only applies to 
   * those actions)
	 * @type mixed
	 */
	var $_primaryKey;
  
  /**
	 * used in conjunction with a previous "asynchronous" request in order to 
   * query for the results of that previous request
	 * @type boolean
	 */
  var $_query;
  
  /**
   * the query constraint groups corresponding with this service request
   * @type SRA_QueryBuilderConstraintGroup[]
   */
  var $_queryConstraintGroups = array();
  
  /**
	 * an optional identifier for the service request
	 * @type string
	 */
  var $_requestId;
  
  /**
	 * a second optional identifier for the service request
	 * @type string
	 */
  var $_requestId1;
  
	/**
	 * the results of the service invocation
	 * @type mixed
	 */
	var $_results;
	
	/**
	 * the total result count (without considering limit and offsets)
	 * @type int
	 */
	var $_resultCount;
  
  /**
   * the service that this request belongs to
   * @type mixed
   */
  var $_service;
  
  /**
	 * the soap version... one of the SRA_WS_SOAP_VERSION_* constant values
	 * @type string
	 */
  var $_soapVersion;
  
  /**
   * used to set an error status code if an error exists in the request
   * @type string
   */
  var $_status;
  
  /**
   * the request session id (if $_useSessions is true)
   * @type string
   */
  var $_sessionId;
  
  /**
	 * the formatting string to use in the response for time values. if not 
   * specified, the application date-format will be used
	 * @type string
	 */
	var $_timeFormat;
  
  /**
   * sessions can be used to improve response times and eliminate the need to 
   * send user and password information with each service request invocation. 
   * when this attribute is true, a session-id will be returned in the response. 
   * this session-id may them be used in future requests eliminating the need to 
   * provide user and password authentication information for those requests 
   * (assuming that authentication was successful in the original request, and 
   * the application authenticators allow for session-based authentication)
   * NOTE: if your web service client supports cookies, this option will not 
   * improve performance
   * @type boolean
   */
  var $_useSessions;
  
  /**
   * user for authentication. user and password can also be specified in the 
   * http headers. however, if user or password are specified in the get 
   * parameters or ws-request-xml, they will override the http header values
   * @type string
   */
  var $_user;
  
  /**
	 * an optional additional validators to invoke (applies only to entity 
   * create/update requests)
	 * @type array
	 */
  var $_validators;
  
  /**
	 * if the action is SRA_WS_REQUEST_RETRIEVE and the entity is stored 
   * within a workflow instance (see lib/workflow for more info), this attribute 
   * may be used to specify the workflow identifier
	 * @type int
	 */
	var $_workflowId;
  
  
	// {{{ SRA_WSRequest
	/**
	 * parses the service configuration data and sets the appropriate instance 
   * variables. if there is a problem with the configuration, the instance 
   * variable "err" will be assigned to an appropriate error object (the error 
   * will be logged)
   * @param mixed $conf the xml configuration to parse
   * @param boolean $isSoap whether or not this is a soap request
   * @param string $id the id of the service (optional)
   * 1.2)
   * @access  public
	 */
	function SRA_WSRequest($conf, $isSoap=FALSE, $id=NULL) {
    if (isset($conf['ws-request'])) {
      $keys = array_keys($conf['ws-request']);
      $conf = $conf['ws-request'][$keys[0]];
    }
    //sra_error::logerror($conf);
    $this->_isSoap = $isSoap;
    
    $this->_id = $id ? $id : $conf['attributes']['key'];
    $this->_action = isset($conf['ws-create']) ? SRA_WS_REQUEST_CREATE : (isset($conf['ws-delete']) ? SRA_WS_REQUEST_DELETE : (isset($conf['ws-update']) ? SRA_WS_REQUEST_UPDATE : SRA_WS_REQUEST_RETRIEVE));
    
    $this->_app = isset($conf['attributes']['app']) ? $conf['attributes']['app'] : NULL;
    $this->_asynchronous = SRA_Util::convertBoolean(isset($conf['attributes']['asynchronous']) ? $conf['attributes']['asynchronous'] : NULL);
    if (isset($conf['ws-constraint-group'])) {
      foreach (array_keys($conf['ws-constraint-group']) as $gkey) {
        if (!SRA_WSConstraintGroup::isValid($this->_constraintGroups[] = new SRA_WSConstraintGroup($conf['ws-constraint-group'][$gkey]))) {
          $this->_status = SRA_WS_REQUEST_STATUS_INVALID_REQUEST;
          break;
        }
        else {
          $this->_queryConstraintGroups[] =& $this->_constraintGroups[count($this->_constraintGroups) - 1]->toQueryConstraintGroup();
        }
      }
    }
    $this->_dateFormat = isset($conf['attributes']['date-format']) ? $conf['attributes']['date-format'] : NULL;
    $this->_excludeAttrs = isset($conf['attributes']['exclude-attrs']) ? explode(strpos($conf['attributes']['exclude-attrs'], ',') ? ',' : ' ', $conf['attributes']['exclude-attrs']) : array();
    $this->_format = isset($conf['attributes']['format']) ? $conf['attributes']['format'] : ($this->_id == SRA_WS_GATEWAY_NOOP ? ($this->_isSoap ? SRA_WS_FORMAT_XML : SRA_WS_FORMAT_JSON) : NULL);
    if ($this->_id == SRA_WS_GATEWAY_NOOP) { $this->_global = TRUE; }
    $this->_includeAttrs = isset($conf['attributes']['include-attrs']) ? explode(strpos($conf['attributes']['include-attrs'], ',') ? ',' : ' ', $conf['attributes']['include-attrs']) : array();
    if ($this->_includeAttrs) $this->_includeAttrs[] = SRA_WS_REQUEST_PK;
    $this->_limit = isset($conf['attributes']['limit']) ? $conf['attributes']['limit'] : NULL;
    $this->_metaFormat = isset($conf['attributes']['meta-format']) ? $conf['attributes']['meta-format'] : NULL;
    $this->_metaFormat = isset($conf['attributes']['meta-format']) ? $conf['attributes']['meta-format'] : ($this->_format ? ($this->_format == SRA_WS_FORMAT_RAW ? SRA_WS_META_FORMAT_NONE : $this->_format) : NULL);
    $this->_offset = isset($conf['attributes']['offset']) ? $conf['attributes']['offset'] : NULL;
    $this->_query = SRA_Util::convertBoolean(isset($conf['attributes']['query']) ? $conf['attributes']['query'] : NULL);
    if (isset($conf['ws-param'])) {
			foreach (array_keys($conf['ws-param']) as $pkey) {
				if (!SRA_WSParam::isValid($param = new SRA_WSParam($conf['ws-param'][$pkey]))) {
          $this->_status = SRA_WS_REQUEST_STATUS_INVALID_REQUEST;
          break;
        }
        else {
          $this->_params[$param->_name] = $param;
        }
			}
    }
    $key = $this->_action == SRA_WS_REQUEST_CREATE ? 'ws-create' : ($this->_action == SRA_WS_REQUEST_DELETE ? 'ws-delete' : ($this->_action == SRA_WS_REQUEST_UPDATE ? 'ws-update' : 'ws-retrieve'));
    $this->_password = isset($conf['attributes']['password']) ? $conf['attributes']['password'] : NULL;
    $this->_primaryKey = $this->_action != SRA_WS_REQUEST_CREATE && count($tmp = array_keys($conf[$key])) && isset($tmp[0]) ? (is_numeric($tmp[0]) ? $tmp[0]*1 : $tmp[0]) : NULL;
    $this->_requestId = isset($conf['attributes']['request-id']) ? $conf['attributes']['request-id'] : NULL;
    $this->_requestId1 = isset($conf['attributes']['request-id1']) ? $conf['attributes']['request-id1'] : NULL;
    $this->_sessionId = isset($conf['attributes']['session-id']) ? $conf['attributes']['session-id'] : NULL;
    $this->_timeFormat = isset($conf['attributes']['time-format']) ? $conf['attributes']['time-format'] : NULL;
    $this->_jsDates = !$this->_dateFormat && !$this->_timeFormat ? SRA_Util::convertBoolean(isset($conf['attributes']['js-dates']) ? $conf['attributes']['js-dates'] : NULL, FALSE) : FALSE;
    $this->_useSessions = SRA_Util::convertBoolean(isset($conf['attributes']['use-sessions']) ? $conf['attributes']['use-sessions'] : NULL);
    $this->_user = isset($conf['attributes']['user']) ? $conf['attributes']['user'] : NULL;
    $this->_validators = isset($conf['attributes']['validators']) ? explode(strpos($conf['attributes']['validators'], ',') ? ',' : ' ', $conf['attributes']['validators']) : array();
    $this->_workflowId = $this->_action == SRA_WS_REQUEST_RETRIEVE && isset($this->_primaryKey) && isset($conf[$key][$this->_primaryKey]['attributes']['workflow-id']) ? $conf[$key][$this->_primaryKey]['attributes']['workflow-id']*1 : NULL;
    if (($this->_action == SRA_WS_REQUEST_CREATE || $this->_action == SRA_WS_REQUEST_UPDATE) && count($tmp = array_keys($conf[$key]))) {
      if (isset($conf[$key][$tmp[0]]['ws-param'])) {
        foreach (array_keys($conf[$key][$tmp[0]]['ws-param']) as $pkey) {
          if (!SRA_WSParam::isValid($param = new SRA_WSParam($conf[$key][$tmp[0]]['ws-param'][$pkey]))) {
            $this->_status = SRA_WS_REQUEST_STATUS_INVALID_REQUEST;
            break;
          }
          else {
            if (isset($this->_params[$param->_name])) {
              if (!is_array($this->_params[$param->_name]->_value)) $this->_params[$param->_name]->_value = array($this->_params[$param->_name]->_value);
              $this->_params[$param->_name]->_value[] = $param->_value;
            }
            else {
              $this->_params[$param->_name] = $param;
            }
          }
        }
      }
    }
	}
	// }}}
  
  
	// {{{ getService
	/**
	 * prints the response of this request using the format and meta-format 
   * specified. returns TRUE on success, FALSE otherwise. this method should be 
   * invoked after 'process'
	 * @access public
	 * @return void
	 */
  function &getService() {
    if (!$this->_service && $this->_id != SRA_WS_GATEWAY_NOOP && $this->_id && ($this->_service =& SRA_WSGateway::getService($this->_id))) {
      $this->_global = SRA_WSGlobal::isValid($this->_service);
    }
    return $this->_service;
  }
  // }}}
  
  
	// {{{ process
	/**
	 * processes this request. returns TRUE on success, FALSE otherwise. if 
   * unsuccessful, a corresponding SRA_WS_REQUEST_STATUS_* code will be set to 
   * $this->_status
	 * @access public
	 * @return boolean
	 */
	function process() {
		if (!$this->validate()) { return TRUE; }
    if (isset($this->_processed)) { return $this->_processed; }
    
    $this->_processed = TRUE;
    
    if ($this->_id != SRA_WS_GATEWAY_NOOP && $this->_global) {
      switch ($this->_service->_type) {
        case SRA_WS_GLOBAL_TYPE_METHOD:
          $_params = $tmp = array($this->_attrs);
          if (isset($this->_limit)) $_params[] = $this->_limit;
          if (isset($this->_offset)) $_params[] = $this->_offset;
          if (SRA_Error::isError($results = SRA_Util::invokeStaticMethodPath($this->_service->_identifier, $_params))) {
            $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
            $this->_methodErrorMsg = $results->getErrorMessage();
          }
          
          // set result count
          if (is_array($results) && isset($results[SRA_WS_RESULT_COUNT_KEY])) {
            $this->_resultCount = $results[SRA_WS_RESULT_COUNT_KEY];
            unset($results[SRA_WS_RESULT_COUNT_KEY]);
          }
          else if (is_array($results)) {
            $this->_resultCount = count($results);
          }
          $this->_results =& $results;
          break;
        case SRA_WS_GLOBAL_TYPE_SQL:
          $sql = $this->_service->_identifier;
          $keys = array_keys($this->_attrs);
          foreach($keys as $key) {
            $sql = str_replace('#' . $key . '#', $this->_attrs[$key], $sql);
          }
          $db =& SRA_Controller::getAppDb();
          if (SRA_Util::beginsWith(strtolower(trim($sql)), 'select')) {
            $this->_results =& $db->fetch($sql, NULL, $this->_limit, $this->_offset);
            $this->_isSelectQuery = TRUE;
          }
          else {
            $this->_results =& $db->execute($sql);
          }
          if (!SRA_Error::isError($this->_results)) {
            $this->_resultCount = SRA_ResultSet::isValid($this->_results) ? $this->_results->getTotalCount() : $this->_results->getNumRowsAffected();
            if ($this->_isSelectQuery) {
              $results = array();
              while($row =& $this->_results->next(TRUE)) {
                $results[] = $row;
              }
              $this->_results =& $results;
            }
          }
          else {
            $msg = "SRA_WSGlobal::process: Failed - sql code '${sql}' failed to execute on db server for service " . $this->_id;
            SRA_Error::logError($msg, __FILE__, __LINE__);
            $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
            $this->_processed = FALSE;
          }
          break;
        case SRA_WS_GLOBAL_TYPE_RB:
          $this->_results = array();
          if (SRA_ResourceBundle::isValid($rb =& SRA_ResourceBundle::getBundle($this->_service->_identifier))) {
            if (isset($this->_attrs['keys'])) {
              $keys = explode(' ', $this->_attrs['keys']);
              foreach($keys as $key) {
                $this->_results[$key] = $rb->getString($key);
              }
            }
            else {
              foreach($rb->getKeys() as $key) {
                $add = TRUE;
                $str = $rb->getString($key);
                if (isset($this->_attrs['search'])) {
                  $add = strpos(strtolower($str), strtolower($this->_attrs['search']->_value)) !== FALSE;
                }
                if ($add && isset($this->_attrs['beginsWith'])) {
                  $add = SRA_Util::beginsWith($str, $this->_attrs['beginsWith']->_value, FALSE);
                }
                if ($add && isset($this->_attrs['endsWith'])) {
                  $add = SRA_Util::endsWith($str, $this->_attrs['endsWith']->_value, FALSE);
                }
                if ($add) {
                  $this->_results[$key] = $str;
                  if ($this->_limit && count($this->_results) == $this->_limit) {
                    break;
                  }
                }
              }
            }
            $this->_resultCount = count($this->_results);
          }
          else {
            $msg = 'SRA_WSGlobal::process: Failed - resource bundle "' . $this->_service->_identifier . '" is not valid for service ' . $this->_id;
            SRA_Error::logError($msg, __FILE__, __LINE__);
            $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
            $this->_processed = FALSE;
          }
          break;
      }
    }
    else if ($this->_id != SRA_WS_GATEWAY_NOOP) {
      // retrieve
      if ($this->_action == SRA_WS_REQUEST_RETRIEVE) {
        if (!$this->_entities) {
          // sql dao
          if (method_exists($this->_dao, 'getTableName')) {
            require_once('model/SRA_QueryBuilder.php');
            $queryBuilder = new SRA_QueryBuilder($this->_service->_entity, $this->_queryConstraintGroups, $this->_limit, $this->_offset);
            $this->_entities =& $queryBuilder->getEntities();
          }
          // non-sql dao
          else {
            $this->_entities = array();
            $tmp =& $this->_dao->findAll();
            foreach(array_keys($tmp) as $tkey) {
              $this->_entities[] =& $tmp[$tkey];
            }
            if (!$this->_entities) { $this->_entities = NULL; }
          }
          
          if (SRA_Error::isError($this->_entities)) {
            $msg = 'SRA_WS::process: Failed - unable to get entities from query builder for service ' . $this->_id;
            SRA_Error::logError($msg, __FILE__, __LINE__);
            $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
            $this->_processed = FALSE;
          }
          $baseCount = count($this->_entities);
          if ($this->_constraintGroups) {
            $updateEntities = FALSE;
            
            // apply non-sql sorting constraints
            if (!method_exists($this->_dao, 'getTableName')) {
              foreach(array_keys($this->_constraintGroups) as $ckey) {
                $this->_entities =& $this->_constraintGroups[$ckey]->applySortingConstraints($this->_entities);
                $updateEntities = TRUE;
              }
            }
            
            foreach(array_keys($this->_entities) as $key) {
              foreach(array_keys($this->_constraintGroups) as $ckey) {
                if (!$this->_constraintGroups[$ckey]->evaluateAllConstraints($this->_entities[$key], !method_exists($this->_dao, 'getTableName'))) {
                  unset($this->_entities[$key]);
                  $updateEntities = TRUE;
                }
              }
            }
            
            if ($updateEntities) {
              $tmp = array();
              foreach(array_keys($this->_entities) as $key) {
                $tmp[] =& $this->_entities[$key];
              }
              $this->_entities =& $tmp;
            }
          }
          if (!method_exists($this->_dao, 'getTableName')) {
            $this->_resultCount = count($this->_entities);
            if (isset($this->_limit) || isset($this->_offset)) {
              $this->_entities =& SRA_Util::applyLimitOffset($this->_entities, $this->_limit, $this->_offset);
            }
          }
          else {
            $this->_resultCount = method_exists($this->_dao, 'getTableName') ? $queryBuilder->getResultCount() : $this->_resultCount;
            $this->_resultCount = $this->_resultCount - ($baseCount - count($this->_entities));
          }
        }
        else {
          $this->_resultsCount = count($this->_entities);
        }
      }
      // create, update or delete
      else if ($this->_entities[0]) {
        switch($this->_action) {
          case SRA_WS_REQUEST_CREATE:
            $results = $this->_dao->insert($this->_entities[0], $this->_service->_subEntities);
            break;
          case SRA_WS_REQUEST_DELETE:
            $results = $this->_dao->delete($this->_entities[0]);
            break;
          case SRA_WS_REQUEST_UPDATE:
            $results = $this->_entities[0]->isDirty() ? $this->_dao->update($this->_entities[0], $this->_service->_subEntities) : TRUE;
            break;
        }
        if (SRA_Error::isError($results) || !$results) {
          $msg = 'SRA_WS::process: Failed - unable to perform requested action ' . $this->_action . ' for entity ' . $this->_service->_entity . '/' . $this->_primaryKey . ' and service ' . $this->_id;
          SRA_Error::logError($msg, __FILE__, __LINE__);
          $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
          $this->_processed = FALSE;
        }
        else {
          $this->_resultCount = $this->_action != SRA_WS_REQUEST_DELETE ? 1 : 0;
        }
      }
      else {
        
      }
    }
    else {
      $this->_global = TRUE;
      if ($this->_metaFormat != SRA_WS_META_FORMAT_JSON && $this->_metaFormat != SRA_WS_META_FORMAT_XML && $this->_metaFormat != SRA_WS_META_FORMAT_NONE) {
        $this->_status = SRA_WS_REQUEST_STATUS_INVALID_META_FORMAT;
        $this->_metaFormat = SRA_WS_META_FORMAT_XML;
      }
      if ($this->_format != SRA_WS_FORMAT_JSON && $this->_format != SRA_WS_FORMAT_RAW && $this->_format != SRA_WS_FORMAT_XML) {
        $this->_status = SRA_WS_REQUEST_STATUS_INVALID_FORMAT;
        $this->_format = SRA_WS_FORMAT_XML;
      }
    }
    
    return $this->_processed;
	}
	// }}}
  
  
	// {{{ printResponse
	/**
	 * prints the response of this request using the format and meta-format 
   * specified. returns TRUE on success, FALSE otherwise. this method should be 
   * invoked after 'process'
	 * @access public
	 * @return void
	 */
  function printResponse() {
    global $_utilAttrToXmlSoap;
    
    $_utilAttrToXmlSoap = $this->_isSoap;
    if (!$this->_format) $this->_format = $this->_isSoap ? SRA_WS_FORMAT_XML : SRA_WS_FORMAT_JSON;
    if (!$this->_metaFormat) $this->_metaFormat = $this->_format == SRA_WS_FORMAT_RAW ? SRA_WS_META_FORMAT_NONE : $this->_format;
    
    $tpl =& SRA_Controller::getSysTemplate();
    if ($this->_id != SRA_WS_GATEWAY_NOOP && $this->_status == SRA_WS_REQUEST_STATUS_SUCCESS) {
      global $_utilDateFormat;
      global $_utilTimeFormat;
      $_utilDateFormat = $this->_dateFormat ? $this->_dateFormat : $this->_timeFormat;
      $_utilTimeFormat = $this->_timeFormat;
      if ($this->_entities && ($this->_service->_view || ($this->_format == SRA_WS_FORMAT_JSON && $this->_service->_viewJson) || ($this->_format == SRA_WS_FORMAT_XML && $this->_service->_viewXml))) {
        $tpl->assignByRef('resources', SRA_Controller::getAppResources());
        foreach(array_keys($this->_entities) as $key) {
          ob_start();
          $this->_entities[$key]->render(($this->_format == SRA_WS_FORMAT_JSON && $this->_service->_viewJson ? $this->_service->_viewJson : ($this->_format == SRA_WS_FORMAT_XML && $this->_service->_viewXml ? $this->_service->_viewXml : $this->_service->_view)), $this->_includeAttrs, $this->_excludeAttrs);
          $this->_entities[$key] = ob_get_contents();
          ob_end_clean();
        }
      }
      
      if ($this->_global) {
        $tpl->assignByRef('response', $this->_results);
      }
      else if (!$this->_global && isset($this->_entities[0]) && (isset($this->_primaryKey) || $this->_action == SRA_WS_REQUEST_CREATE) && $this->_action != SRA_WS_REQUEST_DELETE) {
        $this->_resultCount = 1;
        $tpl->assignByRef('response', $this->_entities[0]); 
      }
      else if (!$this->_global && $this->_entities && $this->_action != SRA_WS_REQUEST_DELETE) {
        $tpl->assignByRef('response', $this->_entities);
      }
      // add primary key to include attributes
      if ($this->_includeAttrs && $this->_results && ((is_object($this->_results) && method_exists($this->_results, 'getPrimaryKeyAttribute') && ($pkName = $this->_results->getPrimaryKeyAttribute())) || (is_array($this->_results) && ($keys = array_keys($this->_results)) && method_exists($this->_results[$keys[0]], 'getPrimaryKeyAttribute') && ($pkName = $this->_results[$keys[0]]->getPrimaryKeyAttribute())))) {
        if (in_array(SRA_WS_REQUEST_PK, $this->_includeAttrs)) {
          foreach(array_keys($this->_includeAttrs) as $ikey) {
            if ($this->_includeAttrs[$ikey] == SRA_WS_REQUEST_PK) { $this->_includeAttrs[$ikey] = $pkName; }
          }
        }
        if (!in_array($pkName , $this->_includeAttrs)) { $this->_includeAttrs[] = $pkName; }
      }
    }
    $tpl->assignByRef('request', $this);
    if ($this->_id != SRA_WS_GATEWAY_NOOP) { $tpl->assignByRef('service', $this->_service); }
    $output = $tpl->fetch($this->_metaFormat == SRA_WS_META_FORMAT_JSON ? 'model/sra-ws-response-json.tpl' : ($this->_metaFormat == SRA_WS_META_FORMAT_XML ? 'model/sra-ws-response-xml.tpl' : 'model/sra-ws-response-raw.tpl'));
    
    if ($this->_isSoap) {
      $tpl->assignByRef('soapBody', $output);
      $tpl->display('model/sra-soap-response.tpl');
    }
    else {
      echo $output;
    }
  }
  // }}}
  
  
	// {{{ validate
	/**
	 * returns TRUE if this request is valid, FALSE otherwise. if it is not valid, 
   * a corresponding SRA_WS_REQUEST_STATUS_* code will be set to $this->_status
	 * @access public
	 * @return boolean
	 */
	function validate() {
    if ($this->_status) { return $this->_status == SRA_WS_REQUEST_STATUS_SUCCESS; }
    
    // sessions
    if (!$this->_useSessions && ($this->_sessionId || $this->_asynchronous)) { $this->_useSessions = TRUE; }
    if ($this->_useSessions) {
      if ($this->_sessionId) { $_COOKIE[session_name()] = $this->_sessionId; }
      session_start();
      $this->_sessionId = session_id();
      if (!$this->_user && $_SESSION['ws-user']) { 
        $this->_user = $_SESSION['ws-user']; 
      }
      else if ($this->_user) {
        $_SESSION['ws-user'] = $this->_user;
      }
      if (!$this->_password && $_SESSION['ws-password']) { 
        $this->_password = $_SESSION['ws-password']; 
      }
      else if ($this->_password) {
        $_SESSION['ws-password'] = $this->_password;
      }
    }
    
    // constraint groups
    if ($this->_constraintGroups) {
      foreach (array_keys($this->_constraintGroups) as $gid) {
        if (!$this->_constraintGroups[$gid]->evaluateNonQueryConstraints()) {
          $msg = 'SRA_WSRequest: Failed - non query constraint group returned FALSE for group ' . $gid . ' and service ' . $this->_id;
          SRA_Error::logError($msg, __FILE__, __LINE__);
          $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
          break;
        }
      }
    }
    // invalid app
    if (!$this->_status && (!$this->_app || !SRA_Controller::appKeyIsValid($this->_app) || !SRA_Controller::init($this->_app, TRUE, FALSE, TRUE, TRUE))) {
      $this->_status = SRA_WS_REQUEST_STATUS_INVALID_APP;
    }
    
    if ($this->_password) { $_SERVER['PHP_AUTH_PW'] = $this->_password; }
    if ($this->_user) { $_SERVER['PHP_AUTH_USER'] = $this->_user; }
    
    // validate service
    if ($this->_id != SRA_WS_GATEWAY_NOOP && $this->_id && ($this->_service =& SRA_WSGateway::getService($this->_id)) && (SRA_WS::isValid($this->_service) || SRA_WSGlobal::isValid($this->_service))) {
      if (SRA_WS::isValid($this->_service)) {
        // merge constraint groups
        $keys = array_keys($this->_service->_constraintGroups);
        foreach($keys as $key) {
          $this->_constraintGroups[] =& $this->_service->_constraintGroups[$key];
        }
        
        // excludeAttrs
        if ($this->_service->_excludeAttrs) $this->_excludeAttrs = array_merge($this->_excludeAttrs, $this->_service->_excludeAttrs);
        
        // includeAttrs
        if (count($this->_service->_includeAttrs)) {
          $include = array();
          foreach($this->_service->_includeAttrs as $attr) {
            if (!$this->_includeAttrs || in_array($attr, $this->_includeAttrs)) {
              $include[] = $attr;
            }
          }
          if ($this->_includeAttrs && array_diff($this->_includeAttrs, $include) && !$this->_service->_view) $this->_status = SRA_WS_REQUEST_STATUS_INVALID_ATTRS;
          $this->_includeAttrs = $include;
        }
        
        // validators
        $this->_validators = array_merge($this->_validators, $this->_service->_validators);
        
      }
      else if (SRA_WSGlobal::isValid($this->_service)) {
        // merge params
        $keys = array_keys($this->_service->_params);
        foreach($keys as $key) {
          if (!isset($this->_params[$key]) || !$this->_service->_params[$key]->_allowOverride) {
            $this->_params[$key] =& $this->_service->_params[$key];
          }
        }
        $this->_global = TRUE;
      }
      
      // format
      $format = $this->_format && (!$this->_service->_formatFixed || $this->_format == $this->_service->_format) ? $this->_format : ($this->_soap ? SRA_WS_FORMAT_XML : $this->_service->_format);
      if (($this->_format && $format != $this->_format) || ($format != SRA_WS_FORMAT_JSON && $format != SRA_WS_FORMAT_RAW && $format != SRA_WS_FORMAT_XML) || ($this->_global && $this->_service->_type != SRA_WS_GLOBAL_TYPE_METHOD && $format == SRA_WS_FORMAT_RAW)) $this->_status = SRA_WS_REQUEST_STATUS_INVALID_FORMAT;
      $this->_format = $format;
      
      // limit 
      $limit = $this->_limit && (!$this->_service->_limitFixed || $this->_limit <= $this->_service->_limit) ? $this->_limit : $this->_service->_limit;
      if ($this->_limit && $limit != $this->_limit) $this->_status = SRA_WS_REQUEST_STATUS_INVALID_LIMIT;
      $this->_limit = $limit;
      
      // meta format
      $metaFormat = $this->_metaFormat && (!$this->_service->_metaFormatFixed || $this->_metaFormat == $this->_service->_metaFormat) ? $this->_metaFormat : $this->_service->_metaFormat;
      if (($this->_metaFormat && $metaFormat != $this->_metaFormat) || ($metaFormat != SRA_WS_META_FORMAT_JSON && $metaFormat != SRA_WS_META_FORMAT_NONE && $metaFormat != SRA_WS_META_FORMAT_XML)) $this->_status = SRA_WS_REQUEST_STATUS_INVALID_META_FORMAT;
      $this->_metaFormat = $metaFormat;
      
      if ($this->_service->_authenticate) {
        require_once('auth/SRA_Authenticator.php');
        if (!SRA_Authenticator::authenticate(SRA_Controller::getSysConf(), SRA_Controller::getAppConf())) {
          if (isset($_SERVER['PHP_AUTH_USER'])) {
            $this->_status = SRA_WS_REQUEST_STATUS_AUTH_FAILED;
          }
          else {
            global $_wsGateway;
            $oldGateway = $_wsGateway;
            $_wsGateway = NULL;
            SRA_Authenticator::authenticate(SRA_Controller::getSysConf(), SRA_Controller::getAppConf());
            $_wsGateway =& $oldGateway;
          }
        }
      }
    }
    else if ($this->_id != SRA_WS_GATEWAY_NOOP) {
      $this->_format = $this->_format ? $this->_format : ($this->_soap ? SRA_WS_FORMAT_XML : SRA_WS_FORMAT_JSON);
      $this->_metaFormat = $this->_metaFormat ? $this->_metaFormat : $this->_format;
      $this->_service = NULL;
      $this->_status = SRA_WS_REQUEST_STATUS_INVALID_SERVICE;
    }
    else if ($this->_id == SRA_WS_GATEWAY_NOOP) {
      require_once('auth/SRA_Authenticator.php');
      if (!SRA_Authenticator::authenticate(SRA_Controller::getSysConf(), SRA_Controller::getAppConf())) {
        if (isset($_SERVER['PHP_AUTH_USER'])) {
          $this->_status = SRA_WS_REQUEST_STATUS_AUTH_FAILED;
        }
        else {
          global $_wsGateway;
          $oldGateway = $_wsGateway;
          $_wsGateway = NULL;
          SRA_Authenticator::authenticate(SRA_Controller::getSysConf(), SRA_Controller::getAppConf());
          $_wsGateway =& $oldGateway;
        }
      }
    }
    // translate params to attributes
    if ($this->_params) {
      foreach(array_keys($this->_params) as $pkey) {
        if (isset($this->_attrs[$this->_params[$pkey]->_name])) {
          if (!is_array($this->_attrs[$this->_params[$pkey]->_name])) { $this->_attrs[$this->_params[$pkey]->_name] = array($this->_attrs[$this->_params[$pkey]->_name]); }
          $this->_attrs[$this->_params[$pkey]->_name][] = SRA_WS::findValue($this->_params[$pkey]->_value, $this->_params[$pkey]->_valueType);
        }
        else {
          $this->_attrs[$this->_params[$pkey]->_name] = SRA_WS::findValue($this->_params[$pkey]->_value, $this->_params[$pkey]->_valueType);
        }
      }
    }
    // missing primary key
    if (!$this->_status && !$this->_global && ($this->_action == SRA_WS_REQUEST_UPDATE || $this->_action == SRA_WS_REQUEST_DELETE) && !isset($this->_primaryKey)) {
      $msg = 'SRA_WSRequest: Failed - primary key was not specified for an update or delete service invocation for service ' . $this->_id;
      SRA_Error::logError($msg, __FILE__, __LINE__);
      $this->_status = SRA_WS_REQUEST_STATUS_INVALID_REQUEST;
    }
    // validate dao/entity
    if ($this->_id != SRA_WS_GATEWAY_NOOP && !$this->_status && !$this->_global && SRA_Error::isError($this->_dao =& SRA_DaoFactory::getDao($this->_service->_entity))) {
      $msg = 'SRA_WSRequest: Failed - unable to obtain a reference to the ' . $this->_service->_entity . ' dao for service ' . $this->_id;
      SRA_Error::logError($msg, __FILE__, __LINE__);
      $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
    }
    // lookup entity instance and validate access (if applicable)
    if ($this->_id != SRA_WS_GATEWAY_NOOP && !$this->_status && !$this->_global && isset($this->_primaryKey) && $this->_queryConstraintGroups && method_exists($this->_dao, 'getTableName')) {
      require_once('model/SRA_QueryBuilderConstraintGroup.php');
      $this->_queryConstraintGroups[] = new SRA_QueryBuilderConstraintGroup(array(new SRA_QueryBuilderConstraint($this->_dao->getPkName(), SRA_QUERY_BUILDER_CONSTRAINT_TYPE_EQUAL, $this->_primaryKey)));
      $queryBuilder = new SRA_QueryBuilder($this->_service->_entity, $this->_queryConstraintGroups, 1, 0);
      if (SRA_Error::isError($this->_entities =& $queryBuilder->getEntities())) {
        $msg = 'SRA_WSRequest: Failed - unable to get entities from query builder for service ' . $this->_id;
        SRA_Error::logError($msg, __FILE__, __LINE__);
        $this->_status = SRA_WS_REQUEST_STATUS_FAILED;
      }
      if ($queryBuilder->getResultCount() != 1) {
        $this->_status = SRA_WS_REQUEST_STATUS_INVALID_REQUEST;
      }
    }
    else if ($this->_id != SRA_WS_GATEWAY_NOOP && !$this->_status && !$this->_global && isset($this->_primaryKey) && !$this->_workflowId && !$this->_entities && (SRA_Error::isError($this->_entities[0] =& $this->_dao->findByPk($this->_primaryKey)) || !$this->_entities[0])) {
      $msg = 'SRA_WSRequest: Failed - unable to obtain a reference to entity instance ' . $this->_primaryKey . ' for entity ' . $this->_service->_entity;
      SRA_Error::logError($msg, __FILE__, __LINE__);
      $this->_status = SRA_WS_REQUEST_STATUS_INVALID_PK;
    }
    else if ($this->_action == SRA_WS_REQUEST_RETRIEVE && isset($this->_primaryKey) && $this->_workflowId) {
      require_once('workflow/SRA_WorkflowManager.php');
      if (SRA_Error::isError($wf =& SRA_WorkflowManager::resumeWorkflow($this->_workflowId)) || !$wf || SRA_Error::isError($this->_entities[0] =& $wf->getEntityObj($this->_primaryKey)) || !$this->_entities[0]) {
        $msg = 'SRA_WSRequest: Failed - Invalid workflow id ' . $this->_workflowId . ' or entity id ' . $this->_primaryKey . ' for web service ' . $this->_id;
        SRA_Error::logError($msg, __FILE__, __LINE__);
        $this->_status = SRA_WS_REQUEST_STATUS_INVALID_REQUEST;
      }
    }
    else if (!$this->_status && $this->_action == SRA_WS_REQUEST_CREATE) {
      $this->_entities[0] = $this->_dao->newInstance();
    }
    // validate action
    if ($this->_id != SRA_WS_GATEWAY_NOOP && !$this->_status && !$this->_global && (($this->_action == SRA_WS_REQUEST_CREATE && !$this->_service->_create) || ($this->_action == SRA_WS_REQUEST_DELETE && !$this->_service->_delete) || ($this->_action == SRA_WS_REQUEST_RETRIEVE && !$this->_service->_retrieve) || ($this->_action == SRA_WS_REQUEST_UPDATE && !$this->_service->_update))) {
      $msg = 'SRA_WSRequest: Failed - invalid action ' . $this->_action . ' request for service ' . $this->_id;
      SRA_Error::logError($msg, __FILE__, __LINE__);
      $this->_status = SRA_WS_REQUEST_STATUS_NOT_ALLOWED;
    }
    // substitute in includeAttrs
    if ($this->_dao && $this->_includeAttrs && method_exists($this->_dao, 'getPkName')) {
      if (!in_array(SRA_WS_REQUEST_PK, $this->_includeAttrs) && !in_array(SRA_WS_REQUEST_PK, $this->_dao->getPkName())) $this->_includeAttrs[] = SRA_WS_REQUEST_PK;
      foreach(array_keys($this->_includeAttrs) as $key) {
        if ($this->_includeAttrs[$key] == SRA_WS_REQUEST_PK) {
          $this->_includeAttrs[$key] = $this->_dao->getPkName();
        }
      }
    }
    // validate attrs
    if ($this->_id != SRA_WS_GATEWAY_NOOP && !$this->_status && $this->_attrs) {
      foreach(array_keys($this->_attrs) as $key) {
        $pieces = explode('_', $key);
        $attr = $pieces[0];
        if (!$this->_service->_view && (($this->_entities[0] && ($this->_entities[0]->isAttributeReadOnly($attr) || !$this->_entities[0]->isAttribute($attr))) || (count($this->_service->_includeAttrs) && !in_array($attr, $this->_service->_includeAttrs)) || (count($this->_service->_excludeAttrs) && in_array($attr, $this->_service->_excludeAttrs)))) {
          $this->_status = SRA_WS_REQUEST_STATUS_INVALID_ATTRS;
        }
      }
    }
    // set attributes and invoke validators
    if (!$this->_status && $this->_entities[0] && ($this->_action == SRA_WS_REQUEST_CREATE || $this->_action == SRA_WS_REQUEST_UPDATE || $this->_action == SRA_WS_REQUEST_DELETE)) {
      if ($this->_attrs) { $this->_entities[0]->setAttributes($this->_attrs); }
      if ($this->_validators) { $this->_entities[0]->validate($this->_validators); }
      $this->_action == SRA_WS_REQUEST_DELETE ? $this->_entities[0]->validateDelete() : $this->_entities[0]->validate();
      if ($this->_entities[0]->validateErrors) { $this->_status = SRA_WS_REQUEST_STATUS_INVALID_INPUT; }
      $tpl =& SRA_Controller::getSysTemplate();
      $tpl->assignByRef('entity', $this->_entities[0]);
    }
    // validate IP address (if applicable)
    if ($this->_id != SRA_WS_GATEWAY_NOOP && !$this->_status && $this->_service->_ipAuthenticator && !SRA_Util::invokeStaticMethodPath($this->_service->_ipAuthenticator, $params = array($_SERVER['REMOTE_ADDR']))) {
      $this->_status = SRA_WS_REQUEST_STATUS_IP_NOT_ALLOWED;
    }
    
    if (!$this->_status) { 
      $this->_status = SRA_WS_REQUEST_STATUS_SUCCESS;
      return TRUE;
    }
    else {
      return FALSE;
    }
	}
	// }}}
  
  
	// Static methods
	
	// {{{ isValid
	/**
	 * returns TRUE if $object is a SRA_WSRequest object
	 * @param mixed $object The object to validate
	 * @access public
	 * @return boolean
	 */
	function isValid( & $object ) {
		return (is_object($object) && (!isset($object->err) || !SRA_Error::isError($object->err)) && strtolower(get_class($object)) == 'sra_wsrequest');
	}
	// }}}
	
}
// }}}
?>
Return current item: Sierra-php PHP Application Framework