更新到 5.2 正式版后第一次 SVN 提交。

yuchenghu@hawebs.net


git-svn-id: https://svn.code.sf.net/p/hawebs/svn@625 a2543c7e-f6e9-4f8a-8bff-1ffc34733512
This commit is contained in:
YuCheng Hu
2010-11-16 14:51:21 +00:00
parent 861a61e7ac
commit f97dbf1782
48 changed files with 3452 additions and 0 deletions
@@ -0,0 +1,8 @@
CHANGES TO CORE PRODUCT
=======================
Support for ORDER BY ... DESC was missing in 5.1.0, you will need to apply the patch available at:
* http://trac.vtiger.com/cgi-bin/trac.cgi/ticket/6635 - Should be available in 5.2.0
Support for overriding GetRelatedList global API
* http://trac.vtiger.com/cgi-bin/trac.cgi/ticket/6768 - Should be available in 5.2.0
@@ -0,0 +1,16 @@
Project URL: http://code.google.com/p/iui
Modified version: http://www.k10design.net//iui/iui.js
Further Customization:
iui.js
+ Avoided re-fetching link each time by re-writing href after first fetch
+ To get back default behavior use 'nocache' for the link's class attribute
iui.css
+ Added -moz- specific rules
*******************************************************************************
Project URL: http://code.google.com/p/qcal/
GNU Library or Lesser General Public License (LGPL)
@@ -0,0 +1,21 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
$Module_Mobile_Configuration = array(
'Default.Skin' => 'default.css', // Available in resources/skins
'Navigation.Limit' => 25,
// Control number of records sent out through API (SyncModuleRecords, Query...) which supports paging.
'API_RECORD_FETCH_LIMIT' => 99, // NOTE: vtws_query internally limits fetch to 100 and give room to perform 1 extra fetch to determine paging
);
?>
+60
View File
@@ -0,0 +1,60 @@
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
if(typeof($) == 'undefined') {
$ = function(id) {
var node = document.getElementById(id);
if(typeof(node) == 'undefined') node = false;
return node;
}
$fnT = function(id1, id2) {
var node1 = $(id1);
var node2 = $(id2);
if(node1) node1.style.display = 'none';
if(node2) node2.style.display = 'block';
}
$fnFocus = function(id) {
try {
var node = $(id);
node.focus();
} catch(error) {
}
}
$fnAddClass = function(node, toadd) {
var classValue = node.className;
var regex = new RegExp(toadd, "g");
if(classValue.match(regex) == null) {
classValue += " " + toadd;
node.className = classValue;
}
}
$fnRemoveClass = function(node, toremove) {
var classValue = node.className;
var regex = new RegExp(toremove, "g");
classValue = classValue.replace(regex, '');
node.className = classValue;
}
$fnCheckboxOn = function(idprefix) {
//$fnT((idprefix+'_on'), (idprefix+'_off'));
var nodeon = $(idprefix+'_on');
var nodeoff = $(idprefix+'_off');
if(nodeon) $fnAddClass(nodeon.parentNode, 'hide');
if(nodeoff) $fnRemoveClass(nodeoff.parentNode, 'hide');
}
$fnCheckboxOff = function(idprefix) {
//$fnT((idprefix+'_off'), (idprefix+'_on'));
var nodeon = $(idprefix+'_on');
var nodeoff = $(idprefix+'_off');
if(nodeon) $fnRemoveClass(nodeon.parentNode, 'hide');
if(nodeoff) $fnAddClass(nodeoff.parentNode, 'hide');
}
}
+229
View File
@@ -0,0 +1,229 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/Mobile.Config.php';
class Mobile {
/**
* Detect if request is from IPhone
*/
static function isSafari() {
if(isset($_SERVER['HTTP_USER_AGENT'])) {
$ua = $_SERVER['HTTP_USER_AGENT'];
if(preg_match("/safari/i", $ua)) return true;
}
return false;
}
static function templatePath($filename) {
return vtlib_getModuleTemplate('Mobile',"generic/$filename");
}
static function config($key, $defvalue = false) {
// Defined in the configuration file
global $Module_Mobile_Configuration;
if(isset($Module_Mobile_Configuration) && isset($Module_Mobile_Configuration[$key])) {
return $Module_Mobile_Configuration[$key];
}
return $defvalue;
}
/**
* Alert management
*/
static function alert_lookup($handlerPath, $handlerClass) {
global $adb;
$check = $adb->pquery("SELECT id FROM vtiger_mobile_alerts WHERE handler_path=? and handler_class=?", array($handlerPath, $handlerClass));
if ($adb->num_rows($check)) {
return $adb->query_result($check, 0, 'id');
}
return false;
}
static function alert_register($handlerPath, $handlerClass) {
global $adb;
if (self::alert_lookup($handlerPath, $handlerClass) === false) {
Vtiger_Utils::Log("Registered alert {$handlerClass} [$handlerPath]");
$adb->pquery("INSERT INTO vtiger_mobile_alerts (handler_path, handler_class, deleted) VALUES(?,?,?)", array($handlerPath, $handlerClass, 0));
}
}
static function alert_deregister($handlerPath, $handlerClass) {
global $adb;
Vtiger_Utils::Log("De-registered alert {$handlerClass} [$handlerPath]");
$adb->pquery("DELETE FROM vtiger_mobile_alerts WHERE handler_path=? AND handler_class=?", array($handlerPath, $handlerClass));
}
static function alert_markdeleted($handlerPath, $handlerClass, $flag) {
global $adb;
$adb->pquery("UPDATE vtiger_mobile_alerts SET deleted=? WHERE handler_path=? AND handler_class=?", array($flag, $handlerPath, $handlerClass));
}
/**
* Invoked when special actions are performed on the module.
* @param String Module name
* @param String Event Type (module.postinstall, module.disabled, module.enabled, module.preuninstall)
*/
function vtlib_handler($modulename, $event_type) {
$registerWSAPI = false;
$registerAlerts = false;
if($event_type == 'module.postinstall') {
$registerWSAPI = true;
$registerAlerts= true;
} else if($event_type == 'module.disabled') {
// TODO Handle actions when this module is disabled.
} else if($event_type == 'module.enabled') {
// TODO Handle actions when this module is enabled.
} else if($event_type == 'module.preuninstall') {
// TODO Handle actions when this module is about to be deleted.
} else if($event_type == 'module.preupdate') {
// TODO Handle actions before this module is updated.
} else if($event_type == 'module.postupdate') {
$registerWSAPI = true;
$registerAlerts= true;
}
// Register alerts
if ($registerAlerts) {
self::alert_register('modules/Mobile/api/ws/models/alerts/IdleTicketsOfMine.php', 'Mobile_WS_AlertModel_IdleTicketsOfMine');
self::alert_register('modules/Mobile/api/ws/models/alerts/NewTicketOfMine.php', 'Mobile_WS_AlertModel_NewTicketOfMine');
self::alert_register('modules/Mobile/api/ws/models/alerts/PendingTicketsOfMine.php', 'Mobile_WS_AlertModel_PendingTicketsOfMine');
self::alert_register('modules/Mobile/api/ws/models/alerts/PotentialsDueIn5Days.php', 'Mobile_WS_AlertModel_PotentialsDueIn5Days');
self::alert_register('modules/Mobile/api/ws/models/alerts/EventsOfMineToday.php', 'Mobile_WS_AlertModel_EventsOfMineToday');
}
// Register webservice API
if($registerWSAPI) {
$operations = array();
$operations[] = array (
'name' => 'mobile.fetchallalerts',
'handler' => 'mobile_ws_fetchAllAlerts',
);
$operations[] = array (
'name' => 'mobile.alertdetailswithmessage',
'handler' => 'mobile_ws_alertDetailsWithMessage',
'parameters' => array( array( 'name' => 'alertid', 'type' => 'string' ) )
);
$operations[] = array (
'name' => 'mobile.fetchmodulefilters',
'handler' => 'mobile_ws_fetchModuleFilters',
'parameters' => array( array( 'name' => 'module', 'type' => 'string' ) )
);
$operations[] = array (
'name' => 'mobile.fetchrecord',
'handler' => 'mobile_ws_fetchRecord',
'parameters' => array( array( 'name' => 'record', 'type' => 'string' ) )
);
$operations[] = array (
'name' => 'mobile.fetchrecordwithgrouping',
'handler' => 'mobile_ws_fetchRecordWithGrouping',
'parameters' => array( array( 'name' => 'record', 'type' => 'string' ) )
);
$operations[] = array (
'name' => 'mobile.filterdetailswithcount',
'handler' => 'mobile_ws_filterDetailsWithCount',
'parameters' => array( array( 'name' => 'filterid', 'type' => 'string' ) )
);
$operations[] = array (
'name' => 'mobile.listmodulerecords',
'handler' => 'mobile_ws_listModuleRecords',
'parameters' => array( array( 'name' => 'elements', 'type' => 'encoded' ) )
);
$operations[] = array (
'name' => 'mobile.saverecord',
'handler' => 'mobile_ws_saveRecord',
'parameters' => array( array( 'name' => 'module', 'type' => 'string' ),
array( 'name' => 'record', 'type' => 'string' ),
array( 'name' => 'values', 'type' => 'encoded' ),
)
);
$operations[] = array (
'name' => 'mobile.syncModuleRecords',
'handler' => 'mobile_ws_syncModuleRecords',
'parameters' => array( array( 'name' => 'module', 'type' => 'string' ),
array( 'name' => 'syncToken', 'type' => 'string' ),
array( 'name' => 'page', 'type' => 'string' ),
)
);
$operations[] = array (
'name' => 'mobile.query',
'handler' => 'mobile_ws_query',
'parameters' => array( array( 'name' => 'module', 'type' => 'string' ),
array( 'name' => 'query', 'type' => 'string' ),
array( 'name' => 'page', 'type' => 'string' ),
)
);
$operations[] = array (
'name' => 'mobile.querywithgrouping',
'handler' => 'mobile_ws_queryWithGrouping',
'parameters' => array( array( 'name' => 'module', 'type' => 'string' ),
array( 'name' => 'query', 'type' => 'string' ),
array( 'name' => 'page', 'type' => 'string' ),
)
);
foreach($operations as $o) {
$operation = new Mobile_WS_Operation($o['name'], $o['handler'], 'modules/Mobile/api/wsapi.php', 'POST');
if(!empty($o['parameters'])) {
foreach($o['parameters'] as $p) {
$operation->addParameter($p['name'], $p['type']);
}
}
$operation->register();
}
}
}
}
/* Helper functions */
class Mobile_WS_Operation {
var $opName, $opClass, $opFile, $opType;
var $parameters = array();
function __construct($apiName, $className, $handlerFile, $reqType) {
$this->opName = $apiName;
$this->opClass= $className;
$this->opFile = $handlerFile;
$this->opType = $reqType;
}
function addParameter($name, $type) {
$this->parameters[] = array('name' => $name, 'type' => $type);
return $this;
}
function register() {
global $adb;
$checkresult = $adb->pquery("SELECT 1 FROM vtiger_ws_operation WHERE name = ?", array($this->opName));
if($adb->num_rows($checkresult)) {
return;
}
Vtiger_Utils::Log("Enabling webservice operation {$this->opName}", true);
$operationid = vtws_addWebserviceOperation($this->opName, $this->opFile, $this->opClass, $this->opType);
for($index = 0; $index < count($this->parameters); ++$index) {
vtws_addWebserviceOperationParam($operationid, $this->parameters[$index]['name'], $this->parameters[$index]['type'], ($index+1));
}
}
}
?>
@@ -0,0 +1,13 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
//require_once('include/Ajax/CommonAjax.php'); // DO NOTHING
?>
@@ -0,0 +1,24 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
class MobileHandler extends VTEventHandler {
function handleEvent($eventName, $data) {
if($eventName == 'vtiger.entity.beforesave') {
// Entity is about to be saved, take required action
}
if($eventName == 'vtiger.entity.aftersave') {
// Entity has been saved, take next action
}
}
}
?>
+124
View File
@@ -0,0 +1,124 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
header('Content-Type: text/json');
chdir (dirname(__FILE__) . '/../../');
// Define GetRelatedList API before including the core files
// NOTE: Make sure GetRelatedList function_exists check is made in include/utils/RelatedListView.php
include_once dirname(__FILE__) . '/api/Relation.php';
include_once dirname(__FILE__) . '/api/Request.php';
include_once dirname(__FILE__) . '/api/Response.php';
include_once dirname(__FILE__) . '/api/Session.php';
include_once dirname(__FILE__) . '/api/ws/Controller.php';
class Mobile_API_Controller {
static $opControllers = array(
'login' => array('file' => '/api/ws/Login.php', 'class' => 'Mobile_WS_Login'),
'loginAndFetchModules' => array('file' => '/api/ws/LoginAndFetchModules.php', 'class' => 'Mobile_WS_LoginAndFetchModules'),
'fetchModuleFilters' => array('file' => '/api/ws/FetchModuleFilters.php' , 'class' => 'Mobile_WS_FetchModuleFilters'),
'filterDetailsWithCount' => array('file' => '/api/ws/FilterDetailsWithCount.php', 'class' => 'Mobile_WS_FilterDetailsWithCount'),
'fetchAllAlerts' => array('file' => '/api/ws/FetchAllAlerts.php', 'class' => 'Mobile_WS_FetchAllAlerts'),
'alertDetailsWithMessage' => array('file' => '/api/ws/AlertDetailsWithMessage.php', 'class' => 'Mobile_WS_AlertDetailsWithMessage'),
'listModuleRecords' => array('file' => '/api/ws/ListModuleRecords.php', 'class' => 'Mobile_WS_ListModuleRecords'),
'fetchRecord' => array('file' => '/api/ws/FetchRecord.php', 'class' => 'Mobile_WS_FetchRecord'),
'fetchRecordWithGrouping' => array('file' => '/api/ws/FetchRecordWithGrouping.php', 'class' => 'Mobile_WS_FetchRecordWithGrouping'),
'fetchRecordsWithGrouping' => array('file' => '/api/ws/FetchRecordsWithGrouping.php', 'class' => 'Mobile_WS_FetchRecordsWithGrouping'),
'describe' => array('file' => '/api/ws/Describe.php', 'class' => 'Mobile_WS_Describe'),
'saveRecord' => array('file' => '/api/ws/SaveRecord.php', 'class' => 'Mobile_WS_SaveRecord'),
'syncModuleRecords' => array('file' => '/api/ws/SyncModuleRecords.php', 'class' => 'Mobile_WS_SyncModuleRecords'),
'query' => array('file' => '/api/ws/Query.php', 'class' => 'Mobile_WS_Query'),
'queryWithGrouping' => array('file' => '/api/ws/QueryWithGrouping.php', 'class' => 'Mobile_WS_QueryWithGrouping'),
'relatedRecordsWithGrouping' => array('file' => '/api/ws/RelatedRecordsWithGrouping.php', 'class' => 'Mobile_WS_RelatedRecordsWithGrouping'),
'deleteRecords' => array('file' => '/api/ws/DeleteRecords.php', 'class' => 'Mobile_WS_DeleteRecords'),
'addRecordComment' => array('file' => '/api/ws/AddRecordComment.php', 'class' => 'Mobile_WS_AddRecordComment'),
);
static function process(Mobile_API_Request $request) {
$operation = $request->getOperation();
$sessionid = $request->getSession();
$response = false;
if(isset(self::$opControllers[$operation])) {
$operationFile = self::$opControllers[$operation]['file'];
$operationClass= self::$opControllers[$operation]['class'];
include_once dirname(__FILE__) . $operationFile;
$operationController = new $operationClass;
$operationSession = false;
if($operationController->requireLogin()) {
$operationSession = Mobile_API_Session::init($sessionid);
if($operationController->hasActiveUser() === false) {
$operationSession = false;
}
//Mobile_WS_Utils::initAppGlobals();
} else {
// By-pass login
$operationSession = true;
}
if($operationSession === false) {
$response = new Mobile_API_Response();
$response->setError(1501, 'Login required');
} else {
try {
$response = $operationController->process($request);
} catch(Exception $e) {
$response = new Mobile_API_Response();
$response->setError($e->getCode(), $e->getMessage());
}
}
} else {
$response = new Mobile_API_Response();
$response->setError(1404, 'Operation not found: ' . $operation);
}
if($response !== false) {
echo $response->emitJSON();
}
}
}
/** Take care of stripping the slashes */
function stripslashes_recursive($value) {
$value = is_array($value) ? array_map('stripslashes_recursive', $value) : stripslashes($value);
return $value;
}
/** END **/
if(!defined('MOBILE_API_CONTROLLER_AVOID_TRIGGER')) {
$clientRequestValues = $_POST; // $_REQUEST or $_GET
$clientRequestValuesRaw = array();
// Set of request key few controllers are interested in raw values (example, SaveRecord)
/*$rawValueHeaders = array('values');
foreach($rawValueHeaders as $rawValueHeader) {
if(isset($clientRequestValues[$rawValueHeader])) {
$clientRequestValuesRaw[$rawValueHeader] = $clientRequestValues[$rawValueHeader];
}
}*/
// END
if (get_magic_quotes_gpc()) {
$clientRequestValues = stripslashes_recursive($clientRequestValues);
}
Mobile_API_Controller::process(new Mobile_API_Request($clientRequestValues, $clientRequestValuesRaw));
}
@@ -0,0 +1,13 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
function GetRelatedList($module,$relatedmodule,$focus,$query,$button,$returnset,$id='',$edit_val='',$del_val='') {
return array( 'query' => $query );
}
@@ -0,0 +1,56 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
class Mobile_API_Request {
private $valuemap;
private $rawvaluemap;
private $defaultmap = array();
function __construct($values, $rawvalues = array()) {
$this->valuemap = $values;
$this->rawvaluemap = $rawvalues;
}
function get($key, $defvalue = '') {
if(isset($this->valuemap[$key])) {
return $this->valuemap[$key];
}
if($defvalue === '' && isset($this->defaultmap[$key])) {
$defvalue = $this->defaultmap[$key];
}
return $defvalue;
}
function has($key) {
return isset($this->valuemap[$key]);
}
function getRaw($key, $defvalue = '') {
if (isset($this->rawvaluemap[$key])) {
return $this->rawvaluemap[$key];
}
return $this->get($key, $defvalue);
}
function set($key, $newvalue) {
$this->valuemap[$key]= $newvalue;
}
function setDefault($key, $defvalue) {
$this->defaultmap[$key] = $defvalue;
}
function getOperation() {
return $this->get('_operation');
}
function getSession() {
return $this->get('_session');
}
}
@@ -0,0 +1,62 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/../../../include/Zend/Json.php';
class Mobile_API_Response {
private $error = NULL;
private $result = NULL;
function setError($code, $message) {
$error = array('code' => $code, 'message' => $message);
$this->error = $error;
}
function getError() {
return $this->error;
}
function hasError() {
return !is_null($this->error);
}
function setResult($result) {
$this->result = $result;
}
function getResult() {
return $this->result;
}
function addToResult($key, $value) {
$this->result[$key] = $value;
}
function prepareResponse() {
$response = array();
if($this->result === NULL) {
$response['success'] = false;
$response['error'] = $this->error;
} else {
$response['success'] = true;
$response['result'] = $this->result;
}
return $response;
}
function emitJSON() {
return Zend_Json::encode($this->prepareResponse());
}
function emitHTML() {
if($this->result === NULL) return (is_string($this->error))? $this->error : var_export($this->error, true);
return $this->result;
}
}
@@ -0,0 +1,43 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/../../../include/HTTP_Session/Session.php';
class Mobile_API_Session {
function __construct() {
}
static function destroy($sessionid = false) {
HTTP_Session_Destroy($sessionid);
}
static function init($sessionid = false) {
if(empty($sessionid)) {
HTTP_Session::start(null, null);
$sessionid = HTTP_Session::id();
} else {
HTTP_Session::start(null, $sessionid);
}
if(HTTP_Session::isIdle() || HTTP_Session::isExpired()) {
return false;
}
return $sessionid;
}
static function get($key, $defvalue = '') {
return HTTP_Session::get($key, $defvalue);
}
static function set($key, $value) {
HTTP_Session::set($key, $value);
}
}
@@ -0,0 +1,59 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/SaveRecord.php';
class Mobile_WS_AddRecordComment extends Mobile_WS_SaveRecord {
function saveCommentToHelpDesk($commentcontent, $record, $user) {
global $current_user;
$current_user = $user;
$targetModule = 'HelpDesk';
$recordComponents = vtws_getIdComponents($record);
$focus = CRMEntity::getInstance('HelpDesk');
$focus->retrieve_entity_info($recordComponents[1], $targetModule);
$focus->id = $recordComponents[1];
$focus->mode = 'edit';
$focus->column_fields['comments'] = $commentcontent;
$focus->save($targetModule);
return false;
}
function process(Mobile_API_Request $request) {
$values = Zend_Json::decode($request->get('values'));
$relatedTo = $values['related_to'];
$commentContent = $values['commentcontent'];
$user = $this->getActiveUser();
$targetModule = '';
if (!empty($relatedTo) && Mobile_WS_Utils::detectModulenameFromRecordId($relatedTo) == 'HelpDesk') {
$targetModule = 'HelpDesk';
} else {
$targetModule = 'ModComments';
}
$response = false;
if ($targetModule == 'HelpDesk') {
$response = $this->saveCommentToHelpDesk($commentContent, $relatedTo, $user);
} else {
if (vtlib_isModuleActive($targetModule)) {
$request->set('module', $targetModule);
$values['assigned_user_id'] = sprintf('%sx%s', Mobile_WS_Utils::getEntityModuleWSId('Users'), $user->id);
$request->set('values', Zend_Json::encode($values) );
$response = parent::process($request);
}
}
return $response;
}
}
@@ -0,0 +1,50 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/Query.php';
include_once dirname(__FILE__) . '/FetchAllAlerts.php';
class Mobile_WS_AlertDetailsWithMessage extends Mobile_WS_FetchAllAlerts {
function process(Mobile_API_Request $request) {
global $current_user;
$response = new Mobile_API_Response();
$alertid = $request->get('alertid');
$current_user = $this->getActiveUser();
$alert = $this->getAlertDetails($alertid);
if(empty($alert)) {
$response->setError(1401, 'Alert not found');
} else {
$result = array();
$result['alert'] = $this->getAlertDetails($alertid);
$response->setResult($result);
}
return $response;
}
function getAlertDetails($alertid) {
$alertModel = Mobile_WS_AlertModel::modelWithId($alertid);
$alert = false;
if($alertModel) {
$alert = $alertModel->serializeToSend();
$alertModel->setUser($this->getActiveUser());
$alert['message'] = $alertModel->message();
}
return $alert;
}
}
@@ -0,0 +1,52 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/Utils.php';
include_once 'modules/Mobile/Mobile.php';
include_once dirname(__FILE__) . '/Utils.php';
class Mobile_WS_Controller {
function requireLogin() {
return true;
}
private $activeUser = false;
public function initActiveUser($user) {
$this->activeUser = $user;
}
protected function setActiveUser($user) {
$this->sessionSet('_authenticated_user_id', $user->id);
$this->initActiveUser($user);
}
protected function getActiveUser() {
if($this->activeUser === false) {
$userid = $this->sessionGet('_authenticated_user_id');
if(!empty($userid)) {
$this->activeUser = CRMEntity::getInstance('Users');
$this->activeUser->retrieveCurrentUserInfoFromFile($userid);
}
}
return $this->activeUser;
}
function hasActiveUser() {
$user = $this->getActiveUser();
return ($user !== false);
}
function sessionGet($key, $defvaule = '') {
return Mobile_API_Session::get($key, $defvalue);
}
function sessionSet($key, $value) {
Mobile_API_Session::set($key, $value);
}
}
@@ -0,0 +1,42 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/Delete.php';
class Mobile_WS_DeleteRecords extends Mobile_WS_Controller {
function process(Mobile_API_Request $request) {
global $current_user;
$current_user = $this->getActiveUser();
$records = $request->get('records');
if (empty($records)) {
$records = array($request->get('record'));
} else {
$records = Zend_Json::decode($records);
}
$deleted = array();
foreach($records as $record) {
try {
vtws_delete($record, $current_user);
$result = true;
} catch(Exception $e) {
$result = false;
}
$deleted[$record] = $result;
}
$response = new Mobile_API_Response();
$response->setResult(array('deleted' => $deleted));
return $response;
}
}
@@ -0,0 +1,26 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/DescribeObject.php';
class Mobile_WS_Describe extends Mobile_WS_Controller {
function process(Mobile_API_Request $request) {
$current_user = $this->getActiveUser();
$module = $request->get('module');
$describeInfo = vtws_describe($module, $current_user);
Mobile_WS_Utils::fixDescribeFieldInfo($module, $describeInfo);
$response = new Mobile_API_Response();
$response->setResult(array('describe' => $describeInfo));
return $response;
}
}
@@ -0,0 +1,35 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/models/Alert.php';
class Mobile_WS_FetchAllAlerts extends Mobile_WS_Controller {
function process(Mobile_API_Request $request) {
$response = new Mobile_API_Response();
$current_user = $this->getActiveUser();
$result = array();
$result['alerts'] = $this->getAlertDetails();
$response->setResult($result);
return $response;
}
function getAlertDetails() {
$alertModels = Mobile_WS_AlertModel::models();
$alerts = array();
foreach($alertModels as $alertModel) {
$alerts[] = $alertModel->serializeToSend();;
}
return $alerts;
}
}
@@ -0,0 +1,79 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
class Mobile_WS_FetchModuleFilters extends Mobile_WS_Controller {
function process(Mobile_API_Request $request) {
$response = new Mobile_API_Response();
$module = $request->get('module');
$current_user = $this->getActiveUser();
$result = array();
$filters = $this->getModuleFilters($module, $current_user);
$yours = array();
$others= array();
if(!empty($filters)) {
foreach($filters as $filter) {
if($filter['userName'] == $current_user->column_fields['user_name']) {
$yours[] = $filter;
} else {
$others[]= $filter;
}
}
}
$result['filters'] = array('yours' => $yours, 'others' => $others);
$response->setResult($result);
return $response;
}
protected function getModuleFilters($moduleName, $user) {
$filters = array();
global $adb;
$sql = "SELECT vtiger_customview.*, vtiger_users.user_name FROM vtiger_customview
INNER JOIN vtiger_users ON vtiger_customview.userid = vtiger_users.id WHERE vtiger_customview.entitytype=?";
$parameters = array($moduleName);
if(!is_admin($user)) {
require('user_privileges/user_privileges_'.$user->id.'.php');
$sql .= " AND (vtiger_customview.status=0 or vtiger_customview.userid = ? or vtiger_customview.status = 3 or vtiger_customview.userid IN
(SELECT vtiger_user2role.userid FROM vtiger_user2role INNER JOIN vtiger_users on vtiger_users.id=vtiger_user2role.userid
INNER JOIN vtiger_role on vtiger_role.roleid=vtiger_user2role.roleid WHERE vtiger_role.parentrole LIKE '".$current_user_parent_role_seq."::%'))";
array_push($parameters, $current_user->id);
}
$result = $adb->pquery($sql, $parameters);
if($result && $adb->num_rows($result)) {
while($resultrow = $adb->fetch_array($result)) {
$filters[] = $this->prepareFilterDetailUsingResultRow($resultrow);
}
}
return $filters;
}
protected function prepareFilterDetailUsingResultRow($resultrow) {
$filter = array();
$filter['cvid'] = $resultrow['cvid'];
$filter['viewname'] = decode_html($resultrow['viewname']);
$filter['setdefault'] = $resultrow['setdefault'];
$filter['setmetrics'] = $resultrow['setmetrics'];
$filter['moduleName'] = decode_html($resultrow['entitytype']);
$filter['status'] = decode_html($resultrow['status']);
$filter['userName'] = decode_html($resultrow['user_name']);
return $filter;
}
}
@@ -0,0 +1,76 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/Retrieve.php';
class Mobile_WS_FetchRecord extends Mobile_WS_Controller {
private $module = false;
protected $resolvedValueCache = array();
protected function detectModuleName($recordid) {
if($this->module === false) {
$this->module = Mobile_WS_Utils::detectModulenameFromRecordId($recordid);
}
return $this->module;
}
protected function processRetrieve(Mobile_API_Request $request) {
$current_user = $this->getActiveUser();
$recordid = $request->get('record');
$record = vtws_retrieve($recordid, $current_user);
return $record;
}
function process(Mobile_API_Request $request) {
$current_user = $this->getActiveUser();
$record = $this->processRetrieve($request);
$this->resolveRecordValues($record, $current_user);
$response = new Mobile_API_Response();
$response->setResult(array('record' => $record));
return $response;
}
function resolveRecordValues(&$record, $user, $ignoreUnsetFields=false) {
if(empty($record)) return $record;
$fieldnamesToResolve = Mobile_WS_Utils::detectFieldnamesToResolve(
$this->detectModuleName($record['id']) );
if(!empty($fieldnamesToResolve)) {
foreach($fieldnamesToResolve as $resolveFieldname) {
if ($ignoreUnsetFields === false || isset($record[$resolveFieldname])) {
$fieldvalueid = $record[$resolveFieldname];
$fieldvalue = $this->fetchRecordLabelForId($fieldvalueid, $user);
$record[$resolveFieldname] = array('value' => $fieldvalueid, 'label'=>$fieldvalue);
}
}
}
}
function fetchRecordLabelForId($id, $user) {
$value = null;
if (isset($this->resolvedValueCache[$id])) {
$value = $this->resolvedValueCache[$id];
} else if(!empty($id)) {
$value = trim(vtws_getName($id, $user));
$this->resolvedValueCache[$id] = $value;
} else {
$value = $id;
}
return $value;
}
}
@@ -0,0 +1,169 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/Retrieve.php';
include_once dirname(__FILE__) . '/FetchRecord.php';
include_once 'include/Webservices/DescribeObject.php';
class Mobile_WS_FetchRecordWithGrouping extends Mobile_WS_FetchRecord {
private $_cachedDescribeInfo = false;
private $_cachedDescribeFieldInfo = false;
protected function cacheDescribeInfo($describeInfo) {
$this->_cachedDescribeInfo = $describeInfo;
$this->_cachedDescribeFieldInfo = array();
if(!empty($describeInfo['fields'])) {
foreach($describeInfo['fields'] as $describeFieldInfo) {
$this->_cachedDescribeFieldInfo[$describeFieldInfo['name']] = $describeFieldInfo;
}
}
}
protected function cachedDescribeInfo() {
return $this->_cachedDescribeInfo;
}
protected function cachedDescribeFieldInfo($fieldname) {
if ($this->_cachedDescribeFieldInfo !== false) {
if(isset($this->_cachedDescribeFieldInfo[$fieldname])) {
return $this->_cachedDescribeFieldInfo[$fieldname];
}
}
return false;
}
protected function cachedEntityFieldnames($module) {
$describeInfo = $this->cachedDescribeInfo();
$labelFields = $describeInfo['labelFields'];
switch($module) {
case 'HelpDesk': $labelFields = 'ticket_title'; break;
case 'Documents': $labelFields = 'notes_title'; break;
}
return explode(',', $labelFields);
}
protected function isTemplateRecordRequest(Mobile_API_Request $request) {
$recordid = $request->get('record');
return (preg_match("/([0-9]+)x0/", $recordid));
}
protected function processRetrieve(Mobile_API_Request $request) {
$recordid = $request->get('record');
// Create a template record for use
if ($this->isTemplateRecordRequest($request)) {
$current_user = $this->getActiveUser();
$module = $this->detectModuleName($recordid);
$describeInfo = vtws_describe($module, $current_user);
Mobile_WS_Utils::fixDescribeFieldInfo($module, $describeInfo);
$this->cacheDescribeInfo($describeInfo);
$templateRecord = array();
foreach($describeInfo['fields'] as $describeField) {
$templateFieldValue = '';
if (isset($describeField['type']) && isset($describeField['type']['defaultValue'])) {
$templateFieldValue = $describeField['type']['defaultValue'];
} else if (isset($describeField['default'])) {
$templateFieldValue = $describeField['default'];
}
$templateRecord[$describeField['name']] = $templateFieldValue;
}
if (isset($templateRecord['assigned_user_id'])) {
$templateRecord['assigned_user_id'] = sprintf("%sx%s", Mobile_WS_Utils::getEntityModuleWSId('Users'), $current_user->id);
}
// Reset the record id
$templateRecord['id'] = $recordid;
return $templateRecord;
}
// Or else delgate the action to parent
return parent::processRetrieve($request);
}
function process(Mobile_API_Request $request) {
$response = parent::process($request);
return $this->processWithGrouping($request, $response);
}
protected function processWithGrouping(Mobile_API_Request $request, $response) {
$isTemplateRecord = $this->isTemplateRecordRequest($request);
$result = $response->getResult();
$resultRecord = $result['record'];
$module = $this->detectModuleName($resultRecord['id']);
$modifiedRecord = $this->transformRecordWithGrouping($resultRecord, $module, $isTemplateRecord);
$response->setResult(array('record' => $modifiedRecord));
return $response;
}
protected function transformRecordWithGrouping($resultRecord, $module, $isTemplateRecord=false) {
$current_user = $this->getActiveUser();
$moduleFieldGroups = Mobile_WS_Utils::gatherModuleFieldGroupInfo($module);
$modifiedResult = array();
$blocks = array(); $labelFields = false;
foreach($moduleFieldGroups as $blocklabel => $fieldgroups) {
$fields = array();
foreach($fieldgroups as $fieldname => $fieldinfo) {
// Pickup field if its part of the result
if(isset($resultRecord[$fieldname])) {
$field = array(
'name' => $fieldname,
'value' => $resultRecord[$fieldname],
'label' => $fieldinfo['label'],
'uitype'=> $fieldinfo['uitype']
);
// Template record requested send more details if available
if ($isTemplateRecord) {
$describeFieldInfo = $this->cachedDescribeFieldInfo($fieldname);
foreach($describeFieldInfo as $k=>$v) {
if (isset($field[$k])) continue;
$field[$k] = $v;
}
// Entity fieldnames
$labelFields = $this->cachedEntityFieldnames($module);
}
// Fix the assigned to uitype
if ($field['uitype'] == '53') {
$field['type']['defaultValue'] = array('value' => "19x{$current_user->id}", 'label' => $current_user->column_fields['last_name']);
} else if($field['uitype'] == '117') {
$field['type']['defaultValue'] = $field['value'];
}
// END
$fields[] = $field;
}
}
$blocks[] = array( 'label' => $blocklabel, 'fields' => $fields );
}
$sections = array();
$moduleFieldGroupKeys = array_keys($moduleFieldGroups);
foreach($moduleFieldGroupKeys as $blocklabel) {
// Eliminate empty blocks
if(isset($groups[$blocklabel]) && !empty($groups[$blocklabel])) {
$sections[] = array( 'label' => $blocklabel, 'count' => count($groups[$blocklabel]) );
}
}
$modifiedResult = array('blocks' => $blocks, 'id' => $resultRecord['id']);
if($labelFields) $modifiedResult['labelFields'] = $labelFields;
return $modifiedResult;
}
}
@@ -0,0 +1,110 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/Query.php';
include_once dirname(__FILE__) . '/FetchRecordWithGrouping.php';
include_once dirname(__FILE__) . '/models/Alert.php';
class Mobile_WS_FetchRecordsWithGrouping extends Mobile_WS_FetchRecordWithGrouping {
function process(Mobile_API_Request $request) {
$response = new Mobile_API_Response();
$current_user = $this->getActiveUser();
$module = $request->get('module');
$moduleWSID = Mobile_WS_Utils::getEntityModuleWSId($module);
if (empty($module)) {
$response->setError(1501, "Module not specified.");
return $response;
}
$records = array();
// Fetch the request parameters
$idlist = $request->get('ids');
$alertid = $request->get('alertid');
// List of ids specified?
if (!empty($idlist)) {
$idlist = Zend_Json::decode($idlist);
$records = $this->fetchRecordsWithId($module, $idlist, $current_user);
}
// Alert id specified?
else if (!empty($alertid)) {
$alert = Mobile_WS_AlertModel::modelWithId($alertid);
if ($alert === false) {
$response->setError(1404, "Alert not found.");
$records = false;
}
$alert->setUser($current_user);
$records = $this->fetchAlertRecords($module, $alert);
}
if ($records !== false) {
$response->setResult(array('records' => $records));
}
return $response;
}
function fetchRecordsWithId($module, $idlist, $user) {
if (empty($idlist)) return array();
$wsresult = vtws_query(sprintf("SELECT * FROM {$module} WHERE id IN ('%s');", implode("','", $idlist)), $user);
if (!empty($wsresult)) {
$resolvedRecords = array();
foreach($wsresult as $record) {
$this->resolveRecordValues($record, $user);
$resolvedRecords[] = $this->transformRecordWithGrouping($record, $module, false);
}
}
return $resolvedRecords;
}
function fetchAlertRecords($module, $alert) {
global $adb;
// Initialize global variable: ($alert->query() could indirectly depend if its using Module API as its base)
global $current_user;
if (!isset($current_user)) $current_user = $alert->getUser();
$moduleWSID = Mobile_WS_Utils::getEntityModuleWSId($module);
$alertResult = $adb->pquery($alert->query(), $alert->queryParameters());
$alertRecords = array();
// For Calendar module there is a need for merging Todo's
if ($module == 'Calendar') {
$eventsWSID = Mobile_WS_Utils::getEntityModuleWSId('Events');
$eventIds = array(); $taskIds = array();
while($resultrow = $adb->fetch_array($alertResult)) {
if (isset($resultrow['activitytype']) && $resultrow['activitytype'] == 'Task') {
$taskIds[] = "{$moduleWSID}x". $resultrow['crmid'];
} else {
$eventIds[] = "{$eventsWSID}x". $resultrow['crmid'];
}
}
$alertRecords = $this->fetchRecordsWithId($module, $taskIds, $alert->getUser());
if (!empty($eventIds)) {
$alertRecords = array_merge($alertRecords, $this->fetchRecordsWithId('Events', $eventIds, $alert->getUser()));
}
} else {
$fetchIds = array();
while($resultrow = $adb->fetch_array($alertResult)) {
$fetchIds[] = "{$moduleWSID}x" . $resultrow['crmid'];
}
$alertRecords = $this->fetchRecordsWithId($module, $fetchIds, $alert->getUser());
}
return $alertRecords;
}
}
@@ -0,0 +1,57 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/FetchModuleFilters.php';
include_once 'modules/CustomView/CustomView.php';
class Mobile_WS_FilterDetailsWithCount extends Mobile_WS_FetchModuleFilters {
function process(Mobile_API_Request $request) {
global $current_user;
$response = new Mobile_API_Response();
$filterid = $request->get('filterid');
$current_user = $this->getActiveUser();
$result = array();
$result['filter'] = $this->getModuleFilterDetails($filterid);
$response->setResult($result);
return $response;
}
protected function getModuleFilterDetails($filterid) {
global $adb;
$result = $adb->pquery("SELECT * FROM vtiger_customview WHERE cvid=?", array($filterid));
if ($result && $adb->num_rows($result)) {
$resultrow = $adb->fetch_array($result);
$module = $resultrow['entitytype'];
$view = new CustomView($module);
$viewid = $resultrow['cvid'];
$view->getCustomViewByCvid($viewid);
$viewQuery = $view->getModifiedCvListQuery($viewid, getListQuery($module), $module);
$countResult = $adb->pquery(mkCountQuery($viewQuery), array());
$count = 0;
if($countResult && $adb->num_rows($countResult)) {
$count = $adb->query_result($countResult, 0, 'count');
}
$filter = $this->prepareFilterDetailUsingResultRow($resultrow);
$filter['userName'] = getUserName($resultrow['userid']);
$filter['count'] = $count;
return $filter;
}
}
}
@@ -0,0 +1,188 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/models/Alert.php';
include_once dirname(__FILE__) . '/models/SearchFilter.php';
include_once dirname(__FILE__) . '/models/Paging.php';
class Mobile_WS_ListModuleRecords extends Mobile_WS_Controller {
function isCalendarModule($module) {
return ($module == 'Events' || $module == 'Calendar');
}
function getSearchFilterModel($module, $search) {
return Mobile_WS_SearchFilterModel::modelWithCriterias($module, Zend_JSON::decode($search));
}
function getPagingModel(Mobile_API_Request $request) {
$page = $request->get('page', 0);
return Mobile_WS_PagingModel::modelWithPageStart($page);
}
function process(Mobile_API_Request $request) {
return $this->processSearchRecordLabel($request);
}
function processSearchRecordLabel(Mobile_API_Request $request) {
global $current_user; // Few core API assumes this variable availability
$current_user = $this->getActiveUser();
$module = $request->get('module');
$alertid = $request->get('alertid');
$filterid = $request->get('filterid');
$search = $request->get('search');
$filterOrAlertInstance = false;
if(!empty($alertid)) {
$filterOrAlertInstance = Mobile_WS_AlertModel::modelWithId($alertid);
}
else if(!empty($filterid)) {
$filterOrAlertInstance = Mobile_WS_FilterModel::modelWithId($module, $filterid);
}
else if(!empty($search)) {
$filterOrAlertInstance = $this->getSearchFilterModel($module, $search);
}
if($filterOrAlertInstance && strcmp($module, $filterOrAlertInstance->moduleName)) {
$response = new Mobile_API_Response();
$response->setError(1001, 'Mistached module information.');
return $response;
}
// Initialize with more information
if($filterOrAlertInstance) {
$filterOrAlertInstance->setUser($current_user);
}
// Paging model
$pagingModel = $this->getPagingModel($request);
if($this->isCalendarModule($module)) {
return $this->processSearchRecordLabelForCalendar($request, $pagingModel);
}
$records = $this->fetchRecordLabelsForModule($module, $current_user, array(), $filterOrAlertInstance, $pagingModel);
$modifiedRecords = array();
foreach($records as $record) {
if ($record instanceof SqlResultIteratorRow) {
$record = $record->data;
// Remove all integer indexed mappings
for($index = count($record); $index > -1; --$index) {
if(isset($record[$index])) {
unset($record[$index]);
}
}
}
$recordid = $record['id'];
unset($record['id']);
$eventstart = '';
if($this->isCalendarModule($module)) {
$eventstart = $record['date_start'];
unset($record['date_start']);
}
$values = array_values($record);
$label = implode(' ', $values);
$modifiedRecord = array('id' => $recordid, 'label'=>$label);
if(!empty($eventstart)) {
$modifiedRecord['eventstart'] = $eventstart;
}
$modifiedRecords[] = $modifiedRecord;
}
$response = new Mobile_API_Response();
$response->setResult(array('records'=>$modifiedRecords, 'module'=>$module));
return $response;
}
function processSearchRecordLabelForCalendar(Mobile_API_Request $request, $pagingModel = false) {
$current_user = $this->getActiveUser();
// Fetch both Calendar (Todo) and Event information
$moreMetaFields = array('date_start', 'time_start', 'activitytype', 'location');
$eventsRecords = $this->fetchRecordLabelsForModule('Events', $current_user, $moreMetaFields, false, $pagingModel);
$calendarRecords=$this->fetchRecordLabelsForModule('Calendar', $current_user, $moreMetaFields, false, $pagingModel);
// Merge the Calendar & Events information
$records = array_merge($eventsRecords, $calendarRecords);
$modifiedRecords = array();
foreach($records as $record) {
$modifiedRecord = array();
$modifiedRecord['id'] = $record['id']; unset($record['id']);
$modifiedRecord['eventstartdate'] = $record['date_start']; unset($record['date_start']);
$modifiedRecord['eventstarttime'] = $record['time_start']; unset($record['time_start']);
$modifiedRecord['eventtype'] = $record['activitytype']; unset($record['activitytype']);
$modifiedRecord['eventlocation'] = $record['location']; unset($record['location']);
$modifiedRecord['label'] = implode(' ',array_values($record));
$modifiedRecords[] = $modifiedRecord;
}
$response = new Mobile_API_Response();
$response->setResult(array('records' =>$modifiedRecords, 'module'=>'Calendar'));
return $response;
}
function fetchRecordLabelsForModule($module, $user, $morefields=array(), $filterOrAlertInstance=false, $pagingModel = false) {
if($this->isCalendarModule($module)) {
$fieldnames = Mobile_WS_Utils::getEntityFieldnames('Calendar');
} else {
$fieldnames = Mobile_WS_Utils::getEntityFieldnames($module);
}
if(!empty($morefields)) {
foreach($morefields as $fieldname) $fieldnames[] = $fieldname;
}
if($filterOrAlertInstance === false) {
$filterOrAlertInstance = Mobile_WS_SearchFilterModel::modelWithCriterias($module);
$filterOrAlertInstance->setUser($user);
}
return $this->queryToSelectFilteredRecords($module, $fieldnames, $filterOrAlertInstance, $pagingModel);
}
function queryToSelectFilteredRecords($module, $fieldnames, $filterOrAlertInstance, $pagingModel) {
if ($filterOrAlertInstance instanceof Mobile_WS_SearchFilterModel) {
return $filterOrAlertInstance->execute($fieldnames, $pagingModel);
}
global $adb;
$moduleWSId = Mobile_WS_Utils::getEntityModuleWSId($module);
$columnByFieldNames = Mobile_WS_Utils::getModuleColumnTableByFieldNames($module, $fieldnames);
// Build select clause similar to Webservice query
$selectColumnClause = "CONCAT('{$moduleWSId}','x',vtiger_crmentity.crmid) as id,";
foreach($columnByFieldNames as $fieldname=>$fieldinfo) {
$selectColumnClause .= sprintf("%s.%s as %s,", $fieldinfo['table'],$fieldinfo['column'],$fieldname);
}
$selectColumnClause = rtrim($selectColumnClause, ',');
$query = $filterOrAlertInstance->query();
$query = preg_replace("/SELECT.*FROM(.*)/i", "SELECT $selectColumnClause FROM $1", $query);
if ($pagingModel !== false) {
$query .= sprintf(" LIMIT %s, %s", $pagingModel->currentCount(), $pagingModel->limit());
}
$prequeryResult = $adb->pquery($query, $filterOrAlertInstance->queryParameters());
return new SqlResultIterator($adb, $prequeryResult);
}
}
@@ -0,0 +1,62 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
class Mobile_WS_Login extends Mobile_WS_Controller {
function requireLogin() {
return false;
}
function process(Mobile_API_Request $request) {
$response = new Mobile_API_Response();
$username = $request->get('username');
$password = $request->get('password');
$current_user = CRMEntity::getInstance('Users');
$current_user->column_fields['user_name'] = $username;
if(vtlib_isModuleActive('Mobile') === false) {
$response->setError(1501, 'Service not available');
return $response;
}
if(!$current_user->doLogin($password)) {
$response->setError(1210, 'Authentication Failed');
} else {
// Start session now
$sessionid = Mobile_API_Session::init();
if($sessionid === false) {
echo "Session init failed $sessionid\n";
}
$current_user->id = $current_user->retrieve_user_id($username);
$this->setActiveUser($current_user);
$result = array();
$result['login'] = array(
'userid' => $current_user->id,
'session'=> $sessionid,
'vtiger_version' => Mobile_WS_Utils::getVtigerVersion(),
'mobile_module_version' => Mobile_WS_Utils::getVersion()
);
$response->setResult($result);
$this->postProcess($response);
}
return $response;
}
function postProcess(Mobile_API_Response $response) {
return $response;
}
}
@@ -0,0 +1,50 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/Login.php';
class Mobile_WS_LoginAndFetchModules extends Mobile_WS_Login {
function postProcess(Mobile_API_Response $response) {
$current_user = $this->getActiveUser();
if ($current_user) {
$result = $response->getResult();
$result['modules'] = $this->getListing($current_user);
$response->setResult($result);
}
}
function getListing($user) {
$modulewsids = Mobile_WS_Utils::getEntityModuleWSIds();
// Disallow modules
unset($modulewsids['Users']);
// Calendar & Events module will be merged
unset($modulewsids['Events']);
$listresult = vtws_listtypes($user);
$listing = array();
foreach($listresult['types'] as $index => $modulename) {
if(!isset($modulewsids[$modulename])) continue;
$listing[] = array(
'id' => $modulewsids[$modulename],
'name' => $modulename,
'isEntity' => $listresult['information'][$modulename]['isEntity'],
'label' => $listresult['information'][$modulename]['label'],
'singular' => $listresult['information'][$modulename]['singular'],
);
}
return $listing;
}
}
@@ -0,0 +1,61 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/FetchRecordWithGrouping.php';
include_once 'include/Webservices/Query.php';
class Mobile_WS_Query extends Mobile_WS_FetchRecordWithGrouping {
function processQueryResultRecord(&$record, $user) {
$this->resolveRecordValues($record, $user);
return $record;
}
function process(Mobile_API_Request $request) {
$current_user = $this->getActiveUser();
$query = $request->get('query');
$nextPage = 0;
$queryResult = false;
if (preg_match("/(.*) LIMIT[^;]+;/i", $query)) {
$queryResult = vtws_query($query, $current_user);
} else {
// Implicit limit and paging
$query = rtrim($query, ";");
$currentPage = intval($request->get('page', 0));
$FETCH_LIMIT = Mobile::config('API_RECORD_FETCH_LIMIT');
$startLimit = $currentPage * $FETCH_LIMIT;
$queryWithLimit = sprintf("%s LIMIT %u,%u;", $query, $startLimit, ($FETCH_LIMIT+1));
$queryResult = vtws_query($queryWithLimit, $current_user);
// Determine paging
$hasNextPage = (count($queryResult) > $FETCH_LIMIT);
if ($hasNextPage) {
array_pop($queryResult); // Avoid sending next page record now
$nextPage = $currentPage + 1;
}
}
$records = array();
if (!empty($queryResult)) {
foreach($queryResult as $recordValues) {
$records[] = $this->processQueryResultRecord($recordValues, $current_user);
}
}
$result = array('records' => $records, 'nextPage' => $nextPage );
$response = new Mobile_API_Response();
$response->setResult($result);
return $response;
}
}
@@ -0,0 +1,35 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/Query.php';
include_once 'include/Webservices/Query.php';
class Mobile_WS_QueryWithGrouping extends Mobile_WS_Query {
private $queryModule;
function processQueryResultRecord($record, $user) {
parent::processQueryResultRecord($record, $user);
if ($this->cachedDescribeInfo() === false) {
$describeInfo = vtws_describe($this->queryModule, $user);
$this->cacheDescribeInfo($describeInfo);
}
$transformedRecord = $this->transformRecordWithGrouping($record, $this->queryModule);
// Update entity fieldnames
$transformedRecord['labelFields'] = $this->cachedEntityFieldnames($this->queryModule);
return $transformedRecord;
}
function process(Mobile_API_Request $request) {
$this->queryModule = $request->get('module');
return parent::process($request);
}
}
@@ -0,0 +1,79 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/QueryWithGrouping.php';
class Mobile_WS_RelatedRecordsWithGrouping extends Mobile_WS_QueryWithGrouping {
function process(Mobile_API_Request $request) {
global $current_user, $adb, $currentModule;
$current_user = $this->getActiveUser();
$response = new Mobile_API_Response();
$record = $request->get('record');
$relatedmodule = $request->get('relatedmodule');
$currentPage = $request->get('page', 0);
// Input validation
if (empty($record)) {
$response->setError(1001, 'Record id is empty');
return $response;
}
$recordid = vtws_getIdComponents($record);
$recordid = $recordid[1];
$module = Mobile_WS_Utils::detectModulenameFromRecordId($record);
// Initialize global variable
$currentModule = $module;
$functionHandler = Mobile_WS_Utils::getRelatedFunctionHandler($module, $relatedmodule);
if ($functionHandler) {
$sourceFocus = CRMEntity::getInstance($module);
$relationResult = call_user_func_array( array($sourceFocus, $functionHandler), array($recordid, getTabid($module), getTabid($relatedmodule)) );
$query = $relationResult['query'];
$querySEtype = "vtiger_crmentity.setype as setype";
if ($relatedmodule == 'Calendar') {
$querySEtype = "vtiger_activity.activitytype as setype";
}
$query = sprintf("SELECT vtiger_crmentity.crmid, $querySEtype %s", substr($query, stripos($query, 'FROM')));
$queryResult = $adb->query($query);
// Gather resolved record id's
$relatedRecords = array();
while($row = $adb->fetch_array($queryResult)) {
$targetSEtype = $row['setype'];
if ($relatedmodule == 'Calendar') {
if ($row['setype'] != 'Task' && $row['setype'] != 'Emails') {
$targetSEtype = 'Events';
} else {
$targetSEtype = $relatedmodule;
}
}
$relatedRecords[] = sprintf("%sx%s", Mobile_WS_Utils::getEntityModuleWSId($targetSEtype), $row['crmid']);
}
// Perform query to get record information with grouping
$wsquery = sprintf("SELECT * FROM %s WHERE id IN ('%s');", $relatedmodule, implode("','", $relatedRecords));
$newRequest = new Mobile_API_Request();
$newRequest->set('module', $relatedmodule);
$newRequest->set('query', $wsquery);
$newRequest->set('page', $currentPage);
$response = parent::process($newRequest);
}
return $response;
}
}
@@ -0,0 +1,84 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/FetchRecordWithGrouping.php';
include_once 'include/Webservices/Create.php';
include_once 'include/Webservices/Update.php';
class Mobile_WS_SaveRecord extends Mobile_WS_FetchRecordWithGrouping {
protected $recordValues = false;
// Avoid retrieve and return the value obtained after Create or Update
protected function processRetrieve(Mobile_API_Request $request) {
return $this->recordValues;
}
function process(Mobile_API_Request $request) {
global $current_user; // Required for vtws_update API
$current_user = $this->getActiveUser();
$module = $request->get('module');
$recordid = $request->get('record');
$valuesJSONString = $request->get('values');
$values = "";
if(!empty($valuesJSONString) && is_string($valuesJSONString)) {
$values = Zend_Json::decode($valuesJSONString);
} else {
$values = $valuesJSONString; // Either empty or already decoded.
}
$response = new Mobile_API_Response();
if (empty($values)) {
$response->setError(1501, "Values cannot be empty!");
return $response;
}
try {
// Retrieve or Initalize
if (!empty($recordid) && !$this->isTemplateRecordRequest($request)) {
$this->recordValues = vtws_retrieve($recordid, $current_user);
} else {
$this->recordValues = array();
}
// Set the modified values
foreach($values as $name => $value) {
$this->recordValues[$name] = $value;
}
// Update or Create
if (isset($this->recordValues['id'])) {
$this->recordValues = vtws_update($this->recordValues, $current_user);
} else {
// Set right target module name for Calendar/Event record
if ($module == 'Calendar') {
if (!empty($this->recordValues['eventstatus'])) {
$module = 'Events';
}
}
$this->recordValues = vtws_create($module, $this->recordValues, $current_user);
}
// Update the record id
$request->set('record', $this->recordValues['id']);
// Gather response with full details
$response = parent::process($request);
} catch(Exception $e) {
$response->setError($e->getCode(), $e->getMessage());
}
return $response;
}
}
@@ -0,0 +1,172 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/SaveRecord.php';
include_once 'include/Webservices/Query.php';
class Mobile_WS_SyncModuleRecords extends Mobile_WS_SaveRecord {
static $SYNC_MODE_PUBLIC = "PUBLIC";
static $SYNC_MODE_PRIVATE = "PRIVATE";
function isModePrivate(Mobile_API_Request $request, $defmode="PRIVATE") {
return (strcasecmp($request->get('mode', $defmode), self::$SYNC_MODE_PRIVATE) === 0);
}
function process(Mobile_API_Request $request) {
$current_user = $this->getActiveUser();
$current_user_wsid = sprintf("%sx%s", Mobile_WS_Utils::getEntityModuleWSId("Users"), $current_user->id);
$module = $request->get('module');
$lastSyncTime = $request->get('syncToken', 0);
$currentPage = intval($request->get('page', 0));
$isPrivateMode = $this->isModePrivate($request);
$FETCH_LIMIT = Mobile::config('API_RECORD_FETCH_LIMIT');
$startLimit = $currentPage * $FETCH_LIMIT;
// Keep track of sync-token for futher reference
$maxSyncTime = $lastSyncTime;
$describeInfo = vtws_describe($module, $current_user);
$this->cacheDescribeInfo($describeInfo);
$hasAssignedToField = false;
foreach ($describeInfo['fields'] as $fieldinfo) {
if ($fieldinfo['name'] == 'assigned_user_id') {
$hasAssignedToField = true;
break;
}
}
/////////////////////////////
// MODIFIED RECORDS TRACKING
/////////////////////////////
if (empty($lastSyncTime)) {
// No previous state information available? Lookup records recently modified
if ($hasAssignedToField && $isPrivateMode) {
$queryActive = sprintf("SELECT * FROM %s WHERE assigned_user_id = '%s' ORDER BY modifiedtime DESC", $module, $current_user_wsid);
} else {
$queryActive = sprintf("SELECT * FROM %s ORDER BY modifiedtime DESC", $module);
}
} else {
// Attempt to lookup records from previous state
if ($hasAssignedToField && $isPrivateMode) {
$queryActive = sprintf("SELECT * FROM %s WHERE assigned_user_id = '%s' AND modifiedtime > '%s'", $module, $current_user_wsid, date("Y-m-d H:i:s", $lastSyncTime));
} else {
$queryActive = sprintf("SELECT * FROM %s WHERE modifiedtime > '%s'", $module, date("Y-m-d H:i:s", $lastSyncTime));
}
}
// Try to fetch record with paging (one extra record fetch is attempted to determine presence of next page)
$activeQuery = sprintf("%s LIMIT %u,%u;", $queryActive, $startLimit, ($FETCH_LIMIT+1));
$activeResult = vtws_query( $activeQuery, $current_user );
// Special case handling merge Events records
if ($module == 'Calendar') {
$activeResult2 = vtws_query(str_replace('Calendar', 'Events', $activeQuery), $current_user);
if (!empty($activeResult2)) $activeResult = array_merge($activeResult, $activeResult2);
$FETCH_LIMIT *= 2;
}
// Determine paging
$hasNextPage = (count($activeResult) > $FETCH_LIMIT);
$nextPage = 0;
if ($hasNextPage) {
array_pop($activeResult); // Avoid sending next page record now
$nextPage = $currentPage + 1;
}
// Resolved record details
$resolvedModifiedRecords = array();
$resolvedDeletedRecords = array();
if (!empty($activeResult)) {
foreach($activeResult as $recordValues) {
$this->resolveRecordValues($recordValues, $current_user);
$transformedRecord = $this->transformRecordWithGrouping($recordValues, $module);
// Update entity fieldnames
$transformedRecord['labelFields'] = $this->cachedEntityFieldnames($module);
$resolvedModifiedRecords[] = $transformedRecord;
$modifiedTimeInSeconds = strtotime($recordValues['modifiedtime']);
if ($maxSyncTime < $modifiedTimeInSeconds) {
$maxSyncTime = $modifiedTimeInSeconds;
}
}
}
////////////////////////////
// DELETED RECORDS TRACKING
////////////////////////////
// Only when there is previous state information and is first page
if (!empty($lastSyncTime) && $currentPage === 0) {
global $adb;
$queryDeletedParameters = array($module, date('Y-m-d H:i:s', $lastSyncTime));
$andsmowneridequal = "";
if ($hasAssignedToField) {
if ($isPrivateMode) {
$queryDeletedParameters[] = $current_user->id;
$andsmowneridequal = " AND vtiger_crmentity.smownerid=?";
} else {
$andsmowneridequal = Mobile_WS_Utils::querySecurityFromSuffix($module, $current_user);
}
}
// Since Calendar and Events are merged
if ($module == 'Calendar') {
$queryDeleted = $adb->pquery("SELECT activityid as crmid, activitytype as setype FROM vtiger_activity
INNER JOIN vtiger_crmentity ON vtiger_activity.activityid=vtiger_crmentity.crmid
AND vtiger_crmentity.deleted=1 AND vtiger_crmentity.setype=? AND vtiger_crmentity.modifiedtime > ?
LEFT JOIN vtiger_users ON vtiger_users.id = vtiger_crmentity.smownerid
LEFT JOIN vtiger_groups ON vtiger_groups.groupid = vtiger_crmentity.smownerid WHERE 1=1 $andsmowneridequal ",
$queryDeletedParameters);
} else {
$queryDeleted = $adb->pquery("SELECT crmid, modifiedtime, setype FROM vtiger_crmentity
LEFT JOIN vtiger_users ON vtiger_users.id = vtiger_crmentity.smownerid
LEFT JOIN vtiger_groups ON vtiger_groups.groupid = vtiger_crmentity.smownerid
WHERE vtiger_crmentity.deleted=1 AND vtiger_crmentity.setype=? AND vtiger_crmentity.modifiedtime > ? $andsmowneridequal", $queryDeletedParameters);
}
while($row = $adb->fetch_array($queryDeleted)) {
$recordModule = $row['setype'];
if ($module == 'Calendar') {
if ($row['setype'] != 'Task' && $row['setype'] != 'Emails') {
$recordModule = 'Events';
} else {
$recordModule = $module;
}
}
$resolvedDeletedRecords[] = sprintf("%sx%s", Mobile_WS_Utils::getEntityModuleWSId($recordModule), $row['crmid']);
$modifiedTimeInSeconds = strtotime($row['modifiedtime']);
if ($maxSyncTime < $modifiedTimeInSeconds) {
$maxSyncTime = $modifiedTimeInSeconds;
}
}
}
$result = array(
'nextSyncToken' => $maxSyncTime,
'deleted' => $resolvedDeletedRecords,
'updated' => $resolvedModifiedRecords,
'nextPage'=> $nextPage, // Applies only to retrieve updated record details
);
$response = new Mobile_API_Response();
$response->setResult( array( 'sync' => $result) );
return $response;
}
}
@@ -0,0 +1,305 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
class Mobile_WS_Utils {
/*
static function initAppGlobals() {
global $current_language, $app_strings, $app_list_strings, $app_currency_strings;
$current_language = 'en_us';
$app_currency_strings = return_app_currency_strings_language($current_language);
$app_strings = return_application_language($current_language);
$app_list_strings = return_app_list_strings_language($current_language);
}
static function initModuleGlobals($module) {
global $mod_strings, $current_language;
if(isset($current_language)) {
$mod_strings = return_module_language($current_language, $module);
}
}*/
static function getVtigerVersion() {
global $vtiger_current_version;
return $vtiger_current_version;
}
static function getVersion() {
global $adb;
$versionResult = $adb->pquery("SELECT version FROM vtiger_tab WHERE name='Mobile'", array());
return $adb->query_result($versionResult, 0, 'version');
}
static function array_replace($search, $replace, $array) {
$index = array_search($search, $array);
if($index !== false) {
$array[$index] = $replace;
}
return $array;
}
static function getModuleListQuery($moduleName, $where = '1=1') {
$module = CRMEntity::getInstance($moduleName);
return $module->create_list_query('', $where);
}
static $moduleWSIdCache = array();
static function getEntityModuleWSId($moduleName) {
if (!isset(self::$moduleWSIdCache[$moduleName])) {
global $adb;
$result = $adb->pquery("SELECT id FROM vtiger_ws_entity WHERE name=?", array($moduleName));
if ($result && $adb->num_rows($result)) {
self::$moduleWSIdCache[$moduleName] = $adb->query_result($result, 0, 'id');
}
}
return self::$moduleWSIdCache[$moduleName];
}
static function getEntityModuleWSIds($ignoreNonModule = true) {
global $adb;
$modulewsids = array();
$result = false;
if($ignoreNonModule) {
$result = $adb->pquery("SELECT id, name FROM vtiger_ws_entity WHERE ismodule=1", array());
} else {
$result = $adb->pquery("SELECT id, name FROM vtiger_ws_entity", array());
}
while($resultrow = $adb->fetch_array($result)) {
$modulewsids[$resultrow['name']] = $resultrow['id'];
}
return $modulewsids;
}
static function getEntityFieldnames($module) {
global $adb;
$result = $adb->pquery("SELECT fieldname FROM vtiger_entityname WHERE modulename=?", array($module));
$fieldnames = array();
if($result && $adb->num_rows($result)) {
$fieldnames = explode(',', $adb->query_result($result, 0, 'fieldname'));
}
switch($module) {
case 'HelpDesk': $fieldnames = self::array_replace('title', 'ticket_title', $fieldnames); break;
case 'Document': $fieldnames = self::array_replace('title', 'notes_title', $fieldnames); break;
}
return $fieldnames;
}
static function getModuleColumnTableByFieldNames($module, $fieldnames) {
global $adb;
$result = $adb->pquery("SELECT fieldname,columnname,tablename FROM vtiger_field WHERE tabid=? AND fieldname IN (".
generateQuestionMarks($fieldnames) . ")", array(getTabid($module), $fieldnames)
);
$columnnames = array();
if ($result && $adb->num_rows($result)) {
while($resultrow = $adb->fetch_array($result)) {
$columnnames[$resultrow['fieldname']] = array('column' => $resultrow['columnname'], 'table' => $resultrow['tablename']);
}
}
return $columnnames;
}
static function detectModulenameFromRecordId($wsrecordid) {
global $adb;
$idComponents = vtws_getIdComponents($wsrecordid);
$result = $adb->pquery("SELECT name FROM vtiger_ws_entity WHERE id=?", array($idComponents[0]));
if($result && $adb->num_rows($result)) {
return $adb->query_result($result, 0, 'name');
}
return false;
}
static $detectFieldnamesToResolveCache = array();
static function detectFieldnamesToResolve($module) {
global $adb;
// Cache hit?
if(isset(self::$detectFieldnamesToResolveCache[$module])) {
return self::$detectFieldnamesToResolveCache[$module];
}
$resolveUITypes = array(10, 101, 116, 117, 26, 357, 50, 51, 52, 53, 57, 58, 59, 66, 68, 73, 75, 76, 77, 78, 80, 81);
$result = $adb->pquery(
"SELECT fieldname FROM vtiger_field WHERE uitype IN(".
generateQuestionMarks($resolveUITypes) .") AND tabid=?", array($resolveUITypes, getTabid($module))
);
$fieldnames = array();
while($resultrow = $adb->fetch_array($result)) {
$fieldnames[] = $resultrow['fieldname'];
}
// Cache information
self::$detectFieldnamesToResolveCache[$module] = $fieldnames;
return $fieldnames;
}
static $gatherModuleFieldGroupInfoCache = array();
static function gatherModuleFieldGroupInfo($module) {
global $adb;
if($module == 'Events') $module = 'Calendar';
// Cache hit?
if(isset(self::$gatherModuleFieldGroupInfoCache[$module])) {
return self::$gatherModuleFieldGroupInfoCache[$module];
}
$result = $adb->pquery(
"SELECT fieldname, fieldlabel, blocklabel, uitype FROM vtiger_field INNER JOIN
vtiger_blocks ON vtiger_blocks.tabid=vtiger_field.tabid AND vtiger_blocks.blockid=vtiger_field.block
WHERE vtiger_field.tabid=? AND vtiger_field.presence != 1 ORDER BY vtiger_blocks.sequence, vtiger_field.sequence", array(getTabid($module))
);
$fieldgroups = array();
while($resultrow = $adb->fetch_array($result)) {
$blocklabel = getTranslatedString($resultrow['blocklabel'], $module);
if(!isset($fieldgroups[$blocklabel])) {
$fieldgroups[$blocklabel] = array();
}
$fieldgroups[$blocklabel][$resultrow['fieldname']] =
array(
'label' => getTranslatedString($resultrow['fieldlabel'], $module),
'uitype'=> self::fixUIType($module, $resultrow['fieldname'], $resultrow['uitype'])
);
}
// Cache information
self::$gatherModuleFieldGroupInfoCache[$module] = $fieldgroups;
return $fieldgroups;
}
static function documentFoldersInfo() {
global $adb;
$folders = $adb->pquery("SELECT folderid, foldername FROM vtiger_attachmentsfolder", array());
$folderOptions = array();
while( $folderrow = $adb->fetch_array($folders) ) {
$folderwsid = sprintf("%sx%s", self::getEntityModuleWSId('DocumentFolders'), $folderrow['folderid']);
$folderOptions[] = array( 'value' => $folderwsid, 'label' => $folderrow['foldername'] );
}
return $folderOptions;
}
static function salutationValues() {
$values = vtlib_getPicklistValues('salutationtype');
$options = array();
foreach($values as $value) {
$options[] = array( 'value' => $value, 'label' => $value);
}
return $options;
}
static function fixUIType($module, $fieldname, $uitype) {
if ($module == 'Contacts' || $module == 'Leads') {
if ($fieldname == 'salutationtype') {
return 16;
}
}
else if ($module == 'Calendar' || $module == 'Events') {
if ($fieldname == 'time_start' || $fieldname == 'time_end') {
// Special type for mandatory time type (not defined in product)
return 252;
}
}
return $uitype;
}
static function fixDescribeFieldInfo($module, &$describeInfo) {
if ($module == 'Leads' || $module == 'Contacts') {
foreach($describeInfo['fields'] as $index => $fieldInfo) {
if ($fieldInfo['name'] == 'salutationtype') {
$picklistValues = self::salutationValues();
$fieldInfo['uitype'] = self::fixUIType($module, $fieldInfo['name'], $fieldInfo['uitype']) ;
$fieldInfo['type']['name'] = 'picklist';
$fieldInfo['type']['picklistValues'] = $picklistValues;
//$fieldInfo['type']['defaultValue'] = $picklistValues[0];
$describeInfo['fields'][$index] = $fieldInfo;
}
}
}
else if ($module == 'Documents') {
foreach($describeInfo['fields'] as $index => $fieldInfo) {
if ($fieldInfo['name'] == 'folderid') {
$picklistValues = self::documentFoldersInfo();
$fieldInfo['type']['picklistValues'] = $picklistValues;
//$fieldInfo['type']['defaultValue'] = $picklistValues[0];
$describeInfo['fields'][$index] = $fieldInfo;
}
}
}
else if($module == 'Calendar' || $module == 'Events') {
foreach($describeInfo['fields'] as $index => $fieldInfo) {
$fieldInfo['uitype'] = self::fixUIType($module, $fieldInfo['name'], $fieldInfo['uitype']);
$describeInfo['fields'][$index] = $fieldInfo;
}
}
}
static function getRelatedFunctionHandler($sourceModule, $targetModule) {
global $adb;
$relationResult = $adb->pquery("SELECT name FROM vtiger_relatedlists WHERE tabid=? and related_tabid=? and presence=0", array(getTabid($sourceModule), getTabid($targetModule)));
$functionName = false;
if ($adb->num_rows($relationResult)) $functionName = $adb->query_result($relationResult, 0, 'name');
return $functionName;
}
/**
* Security restriction (sharing privilege) query part
*/
static function querySecurityFromSuffix($module, $current_user) {
require('user_privileges/user_privileges_'.$current_user->id.'.php');
require('user_privileges/sharing_privileges_'.$current_user->id.'.php');
$querySuffix = '';
$tabid = getTabid($module);
if($is_admin==false && $profileGlobalPermission[1] == 1 && $profileGlobalPermission[2] == 1
&& $defaultOrgSharingPermission[$tabid] == 3) {
$querySuffix .= " AND (vtiger_crmentity.smownerid in($current_user->id) OR vtiger_crmentity.smownerid IN
(
SELECT vtiger_user2role.userid FROM vtiger_user2role
INNER JOIN vtiger_users ON vtiger_users.id=vtiger_user2role.userid
INNER JOIN vtiger_role ON vtiger_role.roleid=vtiger_user2role.roleid
WHERE vtiger_role.parentrole LIKE '".$current_user_parent_role_seq."::%'
)
OR vtiger_crmentity.smownerid IN
(
SELECT shareduserid FROM vtiger_tmp_read_user_sharing_per
WHERE userid=".$current_user->id." AND tabid=".$tabid."
)
OR
(";
// Build the query based on the group association of current user.
if(sizeof($current_user_groups) > 0) {
$querySuffix .= " vtiger_groups.groupid IN (". implode(",", $current_user_groups) .") OR ";
}
$querySuffix .= " vtiger_groups.groupid IN
(
SELECT vtiger_tmp_read_group_sharing_per.sharedgroupid
FROM vtiger_tmp_read_group_sharing_per
WHERE userid=".$current_user->id." and tabid=".$tabid."
)";
$querySuffix .= ")
)";
}
return $querySuffix;
}
}
@@ -0,0 +1,100 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
abstract class Mobile_WS_AlertModel {
var $alertid; // Unique id refering the instance
var $name; // Name of the alert - should be unique to make it easy on client side
var $moduleName; // If alert is targeting module record count, this should be set along with $recordsLinked
var $refreshRate;// Recommended lookup rate in SECONDS
var $description;// Describe the purpose of alert to client
var $recordsLinked;// TRUE if message is based on records of module, FALSE otherwise
protected $user;
function __construct() {
$this->recordsLinked = true;
}
function setUser($userInstance) {
$this->user = $userInstance;
}
function getUser() {
return $this->user;
}
function serializeToSend() {
$category = $this->moduleName;
if (empty($category)) {
$category = "General";
}
return array(
'alertid' => (string)$this->alertid,
'name' => $this->name,
'category' => $category,
'refreshRate'=> $this->refreshRate,
'description'=> $this->description,
'recordsLinked'=> $this->recordsLinked
);
}
abstract function query();
abstract function queryParameters();
function message() {
return (string) $this->executeCount();
}
/*function execute() {
global $adb;
$result = $adb->pquery($this->query(), $this->queryParameters());
return $result;
}*/
function executeCount() {
global $adb;
$result = $adb->pquery($this->countQuery(), $this->queryParameters());
return $adb->query_result($result, 0, 'count');
}
// Function provided to enable sub-classes to over-ride in case required
protected function countQuery() {
return mkCountQuery($this->query());
}
static function models() {
global $adb;
$models = array();
$handlerResult = $adb->pquery("SELECT * FROM vtiger_mobile_alerts WHERE deleted = 0", array());
if ($adb->num_rows($handlerResult)) {
while ($handlerRow = $adb->fetch_array($handlerResult)) {
$handlerPath = $handlerRow['handler_path'];
if (file_exists($handlerPath)) {
checkFileAccess($handlerPath);
include_once $handlerPath;
$alertModel = new $handlerRow['handler_class'];
$alertModel->alertid = $handlerRow['id'];
$models[] = $alertModel;
}
}
}
return $models;
}
static function modelWithId($alertid) {
$models = self::models();
foreach($models as $model) {
if ($model->alertid == $alertid) return $model;
}
return false;
}
}
@@ -0,0 +1,47 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'modules/CustomView/CustomView.php';
class Mobile_WS_FilterModel {
var $filterid, $moduleName;
var $user;
protected $customView;
function __construct($moduleName) {
$this->moduleName = $moduleName;
$this->customView = new CustomView($moduleName);
}
function setUser($userInstance) {
$this->user = $userInstance;
}
function getUser() {
return $this->user;
}
function query() {
$listquery = getListQuery($this->moduleName);
$query = $this->customView->getModifiedCvListQuery($this->filterid,$listquery,$this->moduleName);
return $query;
}
function queryParameters() {
return false;
}
static function modelWithId($moduleName, $filterid) {
$model = new Mobile_WS_FilterModel($moduleName);
$model->filterid = $filterid;
return $model;
}
}
@@ -0,0 +1,71 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
class Mobile_WS_PagingModel {
var $_start;
var $_limit;
var $_page;
function __construct() {
$this->_limit = Mobile::config('API_RECORD_FETCH_LIMIT', 20);
}
function start() {
return $this->_start;
}
function limit() {
return $this->_limit;
}
function currentCount() {
return ($this->current() * $this->limit());
}
function current() {
return $this->_page;
}
function next() {
return ($this->current()+1);
}
function previous() {
return ($this->current() < 1? 0 : ($this->current()-1));
}
function hasNext($countOnPage) {
return ($countOnPage >= $this->limit());
}
function hasPrevious() {
return ($this->start() != 0);
}
function initStart($page) {
if(empty($page)) $page = 0;
$this->_page = $page;
if($page < 1) $this->_start = 0;
else $this->_start = ($page * $this->_limit);
}
function setLimit($limit) {
$this->_limit = $limit;
}
static function modelWithPageStart($start) {
$instance = new self();
$instance->initStart($start);
return $instance;
}
}
?>
@@ -0,0 +1,58 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once 'include/Webservices/Query.php';
include_once dirname(__FILE__) . '/Filter.php';
class Mobile_WS_SearchFilterModel extends Mobile_WS_FilterModel {
protected $criterias;
function __construct($moduleName) {
$this->moduleName = $moduleName;
}
function query() {
return false;
}
function queryParameters() {
return false;
}
function setCriterias($criterias) {
$this->criterias = $criterias;
}
function execute($fieldnames, $pagingModel = false) {
$selectClause = sprintf("SELECT %s", implode(',', $fieldnames));
$fromClause = sprintf("FROM %s", $this->moduleName);
$whereClause = "";
$orderClause = "";
$groupClause = "";
$limitClause = $pagingModel? " LIMIT {$pagingModel->currentCount()},{$pagingModel->limit()}" : "" ;
if (!empty($this->criterias)) {
$_sortCriteria = $this->criterias['_sort'];
if(!empty($_sortCriteria)) {
$orderClause = $_sortCriteria;
}
}
$query = sprintf("%s %s %s %s %s %s;", $selectClause, $fromClause, $whereClause, $orderClause, $groupClause, $limitClause);
return vtws_query($query, $this->getUser());
}
static function modelWithCriterias($moduleName, $criterias = false) {
$model = new Mobile_WS_SearchFilterModel($moduleName);
$model->setCriterias($criterias);
return $model;
}
}
@@ -0,0 +1,35 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/../Alert.php';
/** Events for today alert */
class Mobile_WS_AlertModel_EventsOfMineToday extends Mobile_WS_AlertModel {
function __construct() {
parent::__construct();
$this->name = 'Your events for the day';
$this->moduleName = 'Calendar';
$this->refreshRate= 1 * (24* 60 * 60); // 1 day
$this->description='Alert sent when events are scheduled for the day';
}
function query() {
$today = date('Y-m-d');
$sql = "SELECT crmid, activitytype FROM vtiger_activity INNER JOIN
vtiger_crmentity ON vtiger_crmentity.crmid=vtiger_activity.activityid
WHERE vtiger_crmentity.deleted=0 AND vtiger_crmentity.smownerid=? AND
vtiger_activity.activitytype <> 'Emails' AND
(vtiger_activity.date_start = '{$today}' OR vtiger_activity.due_date = '{$today}')";
return $sql;
}
function queryParameters() {
return array($this->getUser()->id);
}
}
@@ -0,0 +1,27 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/PendingTicketsOfMine.php';
/** Idle Ticket Alert */
class Mobile_WS_AlertModel_IdleTicketsOfMine extends Mobile_WS_AlertModel_PendingTicketsOfMine {
function __construct() {
parent::__construct();
$this->name = 'Idle Ticket Alert';
$this->moduleName = 'HelpDesk';
$this->refreshRate= 1 * (60 * 60); // 1 hour
$this->description='Alert sent when ticket has not been updated in 24 hours';
}
function query() {
$sql = parent::query();
$sql .= " AND DATEDIFF(CURDATE(), vtiger_crmentity.modifiedtime) > 1";
return $sql;
}
}
@@ -0,0 +1,37 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/PendingTicketsOfMine.php';
/** New Ticket */
class Mobile_WS_AlertModel_NewTicketOfMine extends Mobile_WS_AlertModel_PendingTicketsOfMine {
function __construct() {
parent::__construct();
$this->name = 'New Ticket Alert';
$this->moduleName = 'HelpDesk';
$this->refreshRate= 1 * (60 * 60); // 1 hour
$this->description='Alert sent when a ticket is assigned to you';
}
function query() {
$sql = parent::query();
$sql .= " ORDER BY crmid DESC LIMIT 1";
return $sql;
}
function countQuery() {
return str_replace("ORDER BY crmid DESC", "", $this->query());
}
function executeCount() {
global $adb;
$result = $adb->pquery($this->countQuery(), $this->queryParameters());
return $adb->num_rows($result);
}
}
@@ -0,0 +1,33 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/../Alert.php';
/** Pending Ticket Alert */
class Mobile_WS_AlertModel_PendingTicketsOfMine extends Mobile_WS_AlertModel {
function __construct() {
parent::__construct();
$this->name = 'Pending Ticket Alert';
$this->moduleName = 'HelpDesk';
$this->refreshRate= 1 * (24* 60 * 60); // 1 day
$this->description='Alert sent when ticket assigned is not yet closed';
}
function query() {
$sql = "SELECT crmid FROM vtiger_troubletickets INNER JOIN
vtiger_crmentity ON vtiger_crmentity.crmid=vtiger_troubletickets.ticketid
WHERE vtiger_crmentity.deleted=0 AND vtiger_crmentity.smownerid=? AND
vtiger_troubletickets.status <> 'Closed'";
return $sql;
}
function queryParameters() {
return array($this->getUser()->id);
}
}
@@ -0,0 +1,33 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/../Alert.php';
/** Upcoming Opportunity */
class Mobile_WS_AlertModel_PotentialsDueIn5Days extends Mobile_WS_AlertModel {
function __construct() {
parent::__construct();
$this->name = 'Upcoming Opportunity';
$this->moduleName = 'Potentials';
$this->refreshRate= 1 * (24 * 60 * 60); // 1 day
$this->description='Alert sent when Potential Close Date is due before 5 days or less';
}
function query() {
$sql = Mobile_WS_Utils::getModuleListQuery('Potentials',
"vtiger_potential.sales_stage not like 'Closed%' AND
DATEDIFF(vtiger_potential.closingdate, CURDATE()) <= 5"
);
return preg_replace("/^SELECT count\(\*\) as count(.*)/i", "SELECT crmid $1", mkCountQuery($sql));
}
function queryParameters() {
return array();
}
}
@@ -0,0 +1,38 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
include_once dirname(__FILE__) . '/../Alert.php';
/** Server time sample alert */
class Mobile_WS_AlertModel_ServerTimeSampleAlert extends Mobile_WS_AlertModel {
function __construct() {
// Mandatory call to parent constructor
parent::__construct();
$this->name = 'Server Time Alert';
$this->description='Alert to get server time information';
$this->refreshRate= 1; // 1 second
$this->recordsLinked = FALSE;
// There is no module records linked with message.
// If set to true $this->moduleName needs to be set.
}
function message() {
return date('Y-m-d H:i:s');
}
/** Override base class methods */
function query() {
return false;
}
function queryParameters() {
return false;
}
}
@@ -0,0 +1,127 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
/**********************************************************************
* Expose the extensions added over webservice API
*/
function mobile_ws_fetchAllAlerts($user) {
$request = new Mobile_API_Request();
return Mobile_WS_API::process($request, $user, 'Mobile_WS_FetchAllAlerts', 'ws/FetchAllAlerts.php');
}
function mobile_ws_alertDetailsWithMessage($alertid, $user) {
$request = new Mobile_API_Request();
$request->set('alertid', $alertid);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_AlertDetailsWithMessage', 'ws/AlertDetailsWithMessage.php');
}
function mobile_ws_fetchModuleFilters($module, $user) {
$request = new Mobile_API_Request();
$request->set('module', $module);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_FetchModuleFilters', 'ws/FetchModuleFilters.php');
}
function mobile_ws_fetchRecord($record, $user) {
$request = new Mobile_API_Request();
$request->set('record', $record);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_FetchRecord', 'ws/FetchRecord.php');
}
function mobile_ws_fetchRecordWithGrouping($record, $user) {
$request = new Mobile_API_Request();
$request->set('record', $record);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_FetchRecordWithGrouping', 'ws/FetchRecordWithGrouping.php');
}
function mobile_ws_filterDetailsWithCount($filterid, $user) {
$request = new Mobile_API_Request();
$request->set('filterid', $filterid);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_FilterDetailsWithCount', 'ws/FilterDetailsWithCount.php');
}
function mobile_ws_listModuleRecords($elements, $user) {
$request = new Mobile_API_Request($elements); // elements can have key (module, alertid, filterid, search, page)
return Mobile_WS_API::process($request, $user, 'Mobile_WS_ListModuleRecords', 'ws/ListModuleRecords.php');
}
function mobile_ws_saveRecord($module, $record, $values, $user) {
$request = new Mobile_API_Request();
$request->set('module', $module);
$request->set('record', $record);
$request->set('values', $values);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_SaveRecord', 'ws/SaveRecord.php');
}
function mobile_ws_syncModuleRecords($module, $syncToken, $page, $user) {
$request = new Mobile_API_Request();
$request->set('module', $module);
$request->set('syncToken', $syncToken);
$request->set('page', $page);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_SyncModuleRecords', 'ws/SyncModuleRecords.php');
}
function mobile_ws_query($module, $query, $page, $user) {
$request = new Mobile_API_Request();
$request->set('module', $module);
$request->set('query', $query);
$request->set('page', $page);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_Query', 'ws/Query.php');
}
function mobile_ws_queryWithGrouping($module, $query, $page, $user) {
$request = new Mobile_API_Request();
$request->set('module', $module);
$request->set('query', $query);
$request->set('page', $page);
return Mobile_WS_API::process($request, $user, 'Mobile_WS_QueryWithGrouping', 'ws/QueryWithGrouping.php');
}
/**********************************************************************/
/**
* Mobile WS API Controller
*/
include_once dirname(__FILE__) . '/Request.php';
include_once dirname(__FILE__) . '/Response.php';
include_once dirname(__FILE__) . '/Session.php';
include_once dirname(__FILE__) . '/ws/Controller.php';
class Mobile_WS_API {
private $controller;
function initController($className, $handlerPath, $user) {
include_once dirname(__FILE__) . "/$handlerPath";
$this->controller = new $className();
Mobile_API_Session::init(session_id());
$this->controller->initActiveUser($user);
return $this->controller;
}
function getController() {
return $this->controller;
}
static function process(Mobile_API_Request $request, $user, $className, $handlerPath) {
if(vtlib_isModuleActive('Mobile') === false) {
throw new WebServiceException('1501', 'Service not available');
}
$wsapiController = new self();
$response = $wsapiController->initController($className, $handlerPath, $user)->process($request);
if($response->hasError()) {
$error = $response->getError();
throw new WebServiceException($error['code'], $error['message']);
}
return $response->getResult();
}
}
+214
View File
@@ -0,0 +1,214 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
error_reporting(E_ALL & ~E_NOTICE);
chdir( dirname(__FILE__). '/../../');
// Include ICAL library
set_include_path(dirname(__FILE__) . '/third-party/qCal' . PATH_SEPARATOR . get_include_path());
include_once dirname(__FILE__) . '/third-party/qCal/autoload.php';
include_once 'vtlib/Vtiger/Module.php';
/**
* Core class to process ICAL request
*/
class Mobile_ICAL {
// User context
private $userfocus;
// DB Connection
private $db;
/**
* Default constructor
*/
function __construct() {
$this->db = PearDatabase::getInstance();
}
/**
* Authenticate user
*
* @param String $username
* @param String $password
* @return True if authenticated, false otherwise
*/
function authenticate($username, $password) {
$this->userfocus = CRMEntity::getInstance('Users');
$this->userfocus->column_fields['user_name'] = $username;
$authsuccess = $this->userfocus->doLogin($password);
if($authsuccess) {
if(!isset($this->userfocus->id)) {
$this->userfocus->id = $this->userfocus->retrieve_user_id($username);
}
}
return $authsuccess;
}
/**
* Prepare date to useable icalendar format
*
* @param String $date yyyy-mm-dd format
* @return yyyymmdd
*/
function formatDate($date) {
if(empty($date)) $date = date('Y-m-d');
return str_replace('-', '', $date);
}
/**
* Prepare date-time to useable icalendar format
*
* @param String $date yyyy-mm-dd format
* @param String $time hh:ii:ss format
* @return yyyymmddThhiissZ
*/
function formatDateTime($date, $time) {
if(empty($date) || preg_match("/0000-00-00/", $date)) {
$date = date('Y-m-d');
}
if(empty($time)) $time = "00:00:00";
// Hous not padded?
if(preg_match("/([0-9]):([0-9][0-9])$/", $time, $m)) {
$time = sprintf("0%s:%s", $m[1], $m[2]);
}
// Minutes not padded?
if(preg_match("/([0-9][0-9]):([0-9])$/", $time, $m)) {
$time = sprintf("%s:0%s", $m[1], $m[2]);
}
if(strlen($time) == 5) $time = "{$time}:00";
return sprintf("%sT%sZ", $this->formatDate($date), str_replace(':','',$time));
}
/**
* Prepare date-timestamp to useable icalendar format
*
* @param String $value yyyy-mm-dd hh:ii:ss format
* @return yyyymmddThhiissZ
*/
function formatDateTimestamp($value) {
return str_replace(array('-', ':', ' '), array('','','T'), trim($value)) . 'Z';
}
/**
* Format value based on its current state.
*
* @param String $value
* @param String $defvalue
* @return unknown|unknown
*/
function formatValue($value, $defvalue='') {
if(is_null($value) || empty($value)) return $defvalue;
return $value;
}
/**
* Generate icalendar data output.
*
* @return String
*/
function generate() {
$properties = array();
$properties['prodid'] = '-//vtiger/Mobile/NONSGML 1.0//EN';
$ical = new qCal($properties);
// TODO Configure timezone information.
$fieldnames = array(
'activityid', 'subject', 'description', 'activitytype', 'location', 'reminder_time',
'date_start', 'time_start', 'due_date', 'time_end', 'modifiedtime'
);
$query = "SELECT " . implode(',', $fieldnames) . " FROM vtiger_activity
INNER JOIN vtiger_crmentity ON
(vtiger_activity.activityid=vtiger_crmentity.crmid AND vtiger_crmentity.deleted = 0 AND vtiger_crmentity.smownerid = ?)
LEFT JOIN vtiger_activity_reminder ON vtiger_activity_reminder.activity_id=vtiger_activity.activityid
WHERE vtiger_activity.activitytype != 'Emails'";
$result = $this->db->pquery($query, array($this->userfocus->id));
while($resultrow = $this->db->fetch_array($result)) {
$properties = array();
$properties['uid'] = $resultrow['activityid'];
$properties['summary'] = $this->formatValue(decode_html($resultrow['subject']));
$properties['description'] = $this->formatValue(decode_html($resultrow['description']));
$properties['class'] = 'PRIVATE';
$properties['dtstart'] = $this->formatDateTime( $resultrow['date_start'], $resultrow['time_start']);
$properties['dtend'] = $this->formatDateTime( $resultrow['due_date'], $resultrow['time_end']);
$properties['dtstamp'] = $this->formatDateTimestamp($resultrow['modifiedtime']);
$properties['location'] = $this->formatValue($resultrow['location']);
if($resultrow['activitytype'] == 'Task') {
// Tranform the parameter
$properties['due'] = $properties['dtend'];
unset($properties['dtend']);
$icalComponent = new qCal_Component_Vtodo($properties);
} else {
$icalComponent = new qCal_Component_Vevent($properties);
if(!empty($resultrow['reminder_time'])) {
$alarmProperties = array();
$alarmProperties['trigger'] = $resultrow['reminder_time'] * 60;
$icalComponent->attach(new qCal_Component_Valarm($alarmProperties));
}
}
$ical->attach($icalComponent);
}
return $ical->render();
}
/**
* Helper method to process the request and emit output
*
* @param String $username
* @param String $password
*/
static function process($username, $password) {
$mobileical = new Mobile_ICAL();
if(!$mobileical->authenticate($username, $password)) {
header('Content-type: text/plain');
echo "FAILED";
} else {
$icalContent = $mobileical->generate();
header('Content-Disposition: attachment; filename="icalendar.ics"');
header('Content-Length: '. strlen($icalContent));
echo $icalContent;
}
}
}
// To make it easier for subscribing to Calendar via applications we support the
// url format: http://localhost:81/modules/Mobile/ical.php/username@password
// Retrieve username and password from the URL
$pathinfo = $_SERVER['PATH_INFO'];
if(empty($pathinfo)) $pathinfo = "/ @ ";
preg_match("/\/([^@]+)@(.*)/", $pathinfo, $matches);
// Process the request
if (vtlib_isModuleActive('Mobile')) {
Mobile_ICAL::process($matches[1], $matches[2]);
}
+108
View File
@@ -0,0 +1,108 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
header('Content-Type: text/html;charset=utf-8');
chdir (dirname(__FILE__) . '/../../');
include_once dirname(__FILE__) . '/api/Request.php';
include_once dirname(__FILE__) . '/api/Response.php';
include_once dirname(__FILE__) . '/api/Session.php';
include_once dirname(__FILE__) . '/api/ws/Controller.php';
include_once dirname(__FILE__) . '/Mobile.php';
include_once dirname(__FILE__) . '/ui/Viewer.php';
include_once dirname(__FILE__) . '/ui/models/Module.php'; // Required for auto de-serializatio of session data
class Mobile_Index_Controller {
static $opControllers = array(
'logout' => array('file' => '/ui/Logout.php', 'class' => 'Mobile_UI_Logout'),
'login' => array('file' => '/ui/Login.php', 'class' => 'Mobile_UI_Login'),
'loginAndFetchModules' => array('file' => '/ui/LoginAndFetchModules.php', 'class' => 'Mobile_UI_LoginAndFetchModules'),
'listModuleRecords' => array('file' => '/ui/ListModuleRecords.php', 'class' => 'Mobile_UI_ListModuleRecords'),
'fetchRecordWithGrouping' => array('file' => '/ui/FetchRecordWithGrouping.php', 'class' => 'Mobile_UI_FetchRecordWithGrouping'),
'searchConfig' => array('file' => '/ui/SearchConfig.php', 'class' => 'Mobile_UI_SearchConfig' )
);
static function process(Mobile_API_Request $request) {
$operation = $request->getOperation();
$sessionid = HTTP_Session::detectId(); //$request->getSession();
if (empty($operation)) $operation = 'login';
$response = false;
if(isset(self::$opControllers[$operation])) {
$operationFile = self::$opControllers[$operation]['file'];
$operationClass= self::$opControllers[$operation]['class'];
include_once dirname(__FILE__) . $operationFile;
$operationController = new $operationClass;
$operationSession = false;
if($operationController->requireLogin()) {
$operationSession = Mobile_API_Session::init($sessionid);
if($operationController->hasActiveUser() === false) {
$operationSession = false;
}
//Mobile_WS_Utils::initAppGlobals();
} else {
// By-pass login
$operationSession = true;
}
if($operationSession === false) {
$response = new Mobile_API_Response();
$response->setError(1501, 'Login required');
} else {
try {
$response = $operationController->process($request);
} catch(Exception $e) {
$response = new Mobile_API_Response();
$response->setError($e->getCode(), $e->getMessage());
}
}
} else {
$response = new Mobile_API_Response();
$response->setError(1404, 'Operation not found: ' . $operation);
}
if($response !== false) {
if ($response->hasError()) {
include_once dirname(__FILE__) . '/ui/Error.php';
$errorController = new Mobile_UI_Error();
$errorController->setError($response->getError());
echo $errorController->process($request)->emitHTML();
} else {
echo $response->emitHTML();
}
}
}
}
/** Take care of stripping the slashes */
function stripslashes_recursive($value) {
$value = is_array($value) ? array_map('stripslashes_recursive', $value) : stripslashes($value);
return $value;
}
if (get_magic_quotes_gpc()) {
//$_GET = stripslashes_recursive($_GET );
//$_POST = stripslashes_recursive($_POST );
$_REQUEST = stripslashes_recursive($_REQUEST);
}
/** END **/
if(!defined('MOBILE_INDEX_CONTROLLER_AVOID_TRIGGER')) {
Mobile_Index_Controller::process(new Mobile_API_Request($_REQUEST));
}
@@ -0,0 +1,15 @@
<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
$mod_strings = Array (
'Mobile' => 'Mobile',
);
?>
@@ -0,0 +1,33 @@
<?php
/**
* Copyright (C) 2006-2010 YUCHENG HU
*
* ---------------------------------------------
* HA WEBSYSTEMS
* http://www.hawebs.net
* https://www.hawebs.org/forums/computer/
*
* CONTACT
* huyuchengus@gmail.com / yuchenghu@hawebs.net
*
* ---------------------------------------------
* [A] GNU GENERAL PUBLIC LICENSE GNU/LGPL
* [B] Apache License, Version 2.0
*
* ---------------------------------------------
* NOTE
* 1. 所有的语言配置文件请采用 UTF-8 编码
*
* ---------------------------------------------
*/
$mod_strings = Array(
'Mobile' => 'Mobile',
);
?>
@@ -0,0 +1,16 @@
<?xml version='1.0'?>
<schema>
<tables>
<table>
<name>vtiger_mobile_alerts</name>
<sql><![CDATA[CREATE TABLE `vtiger_mobile_alerts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`handler_path` varchar(500) DEFAULT NULL,
`handler_class` varchar(50) DEFAULT NULL,
`sequence` int(11) DEFAULT NULL,
`deleted` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8]]></sql>
</table>
</tables>
</schema>