include 文件夹。
This commit is contained in:
parent
e18b890f8e
commit
0b5ff56be0
|
@ -0,0 +1,23 @@
|
|||
<?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.
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
$moduleFilepath = 'modules/'.$_REQUEST['module'].'/'.$_REQUEST['file'].'.php';
|
||||
|
||||
if(file_exists($moduleFilepath) == false) {
|
||||
|
||||
$moduleFilepath = 'modules/Vtiger/'.$_REQUEST['file'].'.php';
|
||||
|
||||
}
|
||||
|
||||
checkFileAccessForInclusion($moduleFilepath);
|
||||
|
||||
require_once $moduleFilepath;
|
||||
?>
|
|
@ -0,0 +1,67 @@
|
|||
<?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.
|
||||
*
|
||||
********************************************************************************/
|
||||
$ajaxaction = $_REQUEST["ajxaction"];
|
||||
global $current_user;
|
||||
global $default_charset;
|
||||
|
||||
$crmid = vtlib_purify($_REQUEST["recordid"]);
|
||||
$module = vtlib_purify($_REQUEST["module"]);
|
||||
$userid = $current_user->id;
|
||||
if($ajaxaction == "SAVETAG")
|
||||
{
|
||||
|
||||
require_once('include/freetag/freetag.class.php');
|
||||
$tagfields=function_exists(iconv) ? @iconv("UTF-8",$default_charset,$_REQUEST['tagfields']) : $_REQUEST['tagfields'];
|
||||
$tagfields =str_replace(array("'",'"'),'',$tagfields);
|
||||
if($tagfields != "")
|
||||
{
|
||||
$freetag = new freetag();
|
||||
if (isset($_REQUEST["tagfields"]) && trim($_REQUEST["tagfields"]) != "")
|
||||
{
|
||||
$freetag->tag_object($userid,$crmid,$tagfields,$module);
|
||||
$tagcloud = $freetag->get_tag_cloud_html($module,$userid,$crmid);
|
||||
echo $tagcloud;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo ":#:FAILURE";
|
||||
}
|
||||
}
|
||||
elseif($ajaxaction == 'GETTAGCLOUD')
|
||||
{
|
||||
require_once('include/freetag/freetag.class.php');
|
||||
$freetag = new freetag();
|
||||
if(trim($module) != "")
|
||||
{
|
||||
$tagcloud = $freetag->get_tag_cloud_html($module,$userid,$crmid);
|
||||
echo $tagcloud;
|
||||
}else
|
||||
{
|
||||
$tagcloud = $freetag->get_tag_cloud_html("",$userid);
|
||||
echo $tagcloud;
|
||||
}
|
||||
}elseif($ajaxaction == 'DELETETAG')
|
||||
{
|
||||
if(is_numeric($_REQUEST['tagid']))
|
||||
{
|
||||
$tagid = $_REQUEST['tagid'];
|
||||
global $adb;
|
||||
$query="delete from vtiger_freetagged_objects where tag_id=? and object_id=?";
|
||||
$result=$adb->pquery($query, array($tagid, $crmid));
|
||||
echo 'SUCCESS';
|
||||
}else
|
||||
{
|
||||
die("An invalid tagid to delete.");
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,523 @@
|
|||
<?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/utils/utils.php');
|
||||
require_once 'include/utils/CommonUtils.php';
|
||||
|
||||
Class ChartUtils {
|
||||
|
||||
// Function to generate Bar Chart
|
||||
public static function getBarChart($xaxisData, $yaxisData, $title='', $width='', $height='', $charttype='vertical', $cachedFileName=false, $target=false, $color='') {
|
||||
|
||||
global $log, $lang_crm, $default_charset;
|
||||
|
||||
require_once('include/utils/utils.php');
|
||||
require_once('include/utils/GraphUtils.php');
|
||||
include_once ('Image/Graph.php');
|
||||
include_once ('Image/Canvas.php');
|
||||
|
||||
$barwidth = '70';
|
||||
if ($cachedFileName === false) {
|
||||
$cache_file_name = 'cache/images/bar_chart_' . time() . '.png';
|
||||
} else {
|
||||
$cache_file_name = $cachedFileName;
|
||||
}
|
||||
if (empty($width))
|
||||
$width = '400';
|
||||
if (empty($height))
|
||||
$height = '300';
|
||||
if ($target === false)
|
||||
$target = array();
|
||||
if (empty($color))
|
||||
$color = 'black';
|
||||
|
||||
$alts = array();
|
||||
$temp = array();
|
||||
for ($i = 0; $i < count($xaxisData); $i++) {
|
||||
$name = html_entity_decode($xaxisData[$i], ENT_QUOTES, $default_charset);
|
||||
$pos = substr_count($name, " ");
|
||||
$alts[] = $name;
|
||||
//If the daatx value of a string is greater, adding '\n' to it so that it'll cme inh 2nd line
|
||||
if (strlen($name) >= 14)
|
||||
$name = substr($name, 0, 44);
|
||||
if ($pos >= 2) {
|
||||
$val = explode(" ", $name);
|
||||
$n = count($val) - 1;
|
||||
$x = "";
|
||||
for ($j = 0; $j < count($val); $j++) {
|
||||
if ($j != $n) {
|
||||
$x .=" " . $val[$j];
|
||||
} else {
|
||||
$x .= "@#" . $val[$j];
|
||||
}
|
||||
}
|
||||
$name = $x;
|
||||
}
|
||||
$name = str_replace("@#", " ", $name);
|
||||
$temp[] = html_entity_decode($name, ENT_QUOTES, $default_charset);
|
||||
}
|
||||
$xaxisData = $temp;
|
||||
|
||||
// Set the basic parameters of the graph
|
||||
$canvas = & Image_Canvas::factory('png', array('width' => $width, 'height' => $height, 'usemap' => true));
|
||||
$imagemap = $canvas->getImageMap();
|
||||
$graph = & Image_Graph::factory('graph', $canvas);
|
||||
|
||||
$font = & $graph->addNew('font', calculate_font_name($lang_crm));
|
||||
$font->setSize(8);
|
||||
$font_color = "#000000";
|
||||
$font->setColor($font_color);
|
||||
$graph->setFont($font);
|
||||
|
||||
$titlestr = & Image_Graph::factory('title', array($title, 8));
|
||||
$plotarea = & Image_Graph::factory('plotarea', array(
|
||||
'axis',
|
||||
'axis',
|
||||
$charttype
|
||||
));
|
||||
$graph->add(Image_Graph::vertical($titlestr, $plotarea, 5));
|
||||
|
||||
// Now create a bar plot
|
||||
$max = 0;
|
||||
// To create unique lables we need to keep track of lable name and its count
|
||||
$uniquex = array();
|
||||
|
||||
$xlabels = array();
|
||||
$dataset = & Image_Graph::factory('dataset');
|
||||
if ($charttype == 'horizontal') {
|
||||
$fill = & Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED, $color, 'white'));
|
||||
} else {
|
||||
$fill = & Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED, $color, 'white'));
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($yaxisData); $i++) {
|
||||
$x = 1 + $i;
|
||||
if ($yaxisData[$i] >= $max)
|
||||
$max = $yaxisData[$i];
|
||||
$dataset->addPoint(
|
||||
$x,
|
||||
$yaxisData[$i],
|
||||
array(
|
||||
'url' => $target[$i],
|
||||
'alt' => $alts[$i] . '=' . $yaxisData[$i]
|
||||
)
|
||||
);
|
||||
$xlabels[$x] = $xaxisData[$i];
|
||||
|
||||
// To have unique names even in case of duplicates let us add the id
|
||||
$xaxisData_appearance = $uniquex[$xaxisData[$i]];
|
||||
if ($xaxisData_appearance == null) {
|
||||
$uniquex[$xaxisData[$i]] = 1;
|
||||
} else {
|
||||
$xlabels[$x] = $xaxisData[$i] . ' [' . $xaxisData_appearance . ']';
|
||||
$uniquex[$xaxisData[$i]] = $xaxisData_appearance + 1;
|
||||
}
|
||||
}
|
||||
$bplot = & $plotarea->addNew('bar', $dataset);
|
||||
$bplot->setFillStyle($fill);
|
||||
|
||||
//You can change the width of the bars if you like
|
||||
if (!empty($xaxisData))
|
||||
$bplot->setBarWidth($barwidth / count($xaxisData), "%");
|
||||
//$bplot->setPadding(array('top'=>10));
|
||||
$bplot->setBackground(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL, 'white', 'white')));
|
||||
$xaxis = & $plotarea->getAxis(IMAGE_GRAPH_AXIS_X);
|
||||
$yaxis = & $plotarea->getAxis(IMAGE_GRAPH_AXIS_Y);
|
||||
$yaxis->setFontSize(8);
|
||||
$xaxis->setFontSize(8);
|
||||
|
||||
if ($charttype == 'horizontal') { // Invert X-axis and put Y-axis at bottom
|
||||
$xaxis->setInverted(false);
|
||||
$yaxis->setAxisIntersection('max');
|
||||
}
|
||||
|
||||
// set grid
|
||||
$gridY = & $plotarea->addNew('line_grid', IMAGE_GRAPH_AXIS_Y);
|
||||
$gridY->setLineColor('#FFFFFF@0.5');
|
||||
$gridY2 = & $plotarea->addNew('bar_grid', null, IMAGE_GRAPH_AXIS_Y);
|
||||
$gridY2->setFillColor('#FFFFFF@0.2');
|
||||
|
||||
|
||||
// Add some grace to y-axis so the bars doesn't go all the way to the end of the plot area
|
||||
$yaxis->forceMaximum(round(($max * 1.1) + 0.5));
|
||||
$ticks = get_tickspacing(round(($max * 1.1) + 0.5));
|
||||
|
||||
// First make the labels look right
|
||||
if ($charttype == 'horizontal')
|
||||
$yaxis->setFontAngle('vertical');
|
||||
$yaxis->setLabelInterval($ticks[0]);
|
||||
$yaxis->setTickOptions(-5, 0);
|
||||
$yaxis->setLabelInterval($ticks[1], 2);
|
||||
$yaxis->setTickOptions(-2, 0, 2);
|
||||
|
||||
// Create the xaxis labels
|
||||
$array_data = & Image_Graph::factory('Image_Graph_DataPreprocessor_Array',
|
||||
array($xlabels)
|
||||
);
|
||||
|
||||
// The fix the tick marks
|
||||
$xaxis->setDataPreprocessor($array_data);
|
||||
$xaxis->forceMinimum(0.5);
|
||||
$xaxis->forceMaximum(0.5 + count($yaxisData));
|
||||
if ($charttype == 'vertical')
|
||||
$xaxis->setFontAngle('vertical');
|
||||
$xaxis->setLabelInterval(1);
|
||||
$xaxis->setTickOptions(0, 0);
|
||||
$xaxis->setLabelInterval(2, 2);
|
||||
|
||||
// set markers
|
||||
if ($width > 400 && $height > 400) {
|
||||
$marker = & $graph->addNew('value_marker', IMAGE_GRAPH_VALUE_Y);
|
||||
$marker->setFillColor('000000@0.0');
|
||||
$marker->setBorderColor('000000@0.0');
|
||||
$marker->setFontSize(8);
|
||||
// shift markers 20 pix right
|
||||
if ($charttype == 'horizontal') {
|
||||
$marker_pointing = & $graph->addNew('Image_Graph_Marker_Pointing', array(10, 0, & $marker));
|
||||
} else {
|
||||
$marker_pointing = & $graph->addNew('Image_Graph_Marker_Pointing', array(0, -10, & $marker));
|
||||
}
|
||||
$marker_pointing->setLineColor('000000@0.0');
|
||||
$bplot->setMarker($marker_pointing);
|
||||
}
|
||||
|
||||
//Getting the graph in the form of html page
|
||||
$img = $graph->done(
|
||||
array(
|
||||
'tohtml' => true,
|
||||
'border' => 0,
|
||||
'filename' => $cache_file_name,
|
||||
'filepath' => '',
|
||||
'urlpath' => ''
|
||||
));
|
||||
|
||||
return $img;
|
||||
}
|
||||
|
||||
// Function to generate Pie Chart
|
||||
public static function getPieChart($xaxisData, $yaxisData, $title='', $width='', $height='', $charttype='vertical', $cachedFileName=false, $target=false, $color='') {
|
||||
|
||||
global $log, $lang_crm, $default_charset;
|
||||
|
||||
require_once('include/utils/utils.php');
|
||||
require_once('include/utils/GraphUtils.php');
|
||||
include_once ('Image/Graph.php');
|
||||
include_once ('Image/Canvas.php');
|
||||
|
||||
if ($cachedFileName === false) {
|
||||
$cache_file_name = 'cache/images/pie_chart_' . time() . '.png';
|
||||
} else {
|
||||
$cache_file_name = $cachedFileName;
|
||||
}
|
||||
|
||||
if (empty($width))
|
||||
$width = '500';
|
||||
if (empty($height))
|
||||
$height = '400';
|
||||
if ($target === false)
|
||||
$target = array();
|
||||
|
||||
$alts = array();
|
||||
$temp = array();
|
||||
for ($i = 0; $i < count($xaxisData); $i++) {
|
||||
$name = html_entity_decode($xaxisData[$i], ENT_QUOTES, $default_charset);
|
||||
$pos = substr_count($name, " ");
|
||||
$alts[] = $name;
|
||||
//If the datax value of a string is greater, adding '\n' to it so that it'll come in 2nd line
|
||||
if (strlen($name) >= 14)
|
||||
$name = substr($name, 0, 34);
|
||||
if ($pos >= 2) {
|
||||
$val = explode(" ", $name);
|
||||
$n = count($val) - 1;
|
||||
$x = "";
|
||||
for ($j = 0; $j < count($val); $j++) {
|
||||
if ($j != $n) {
|
||||
$x .=" " . $val[$j];
|
||||
} else {
|
||||
$x .= "@#" . $val[$j];
|
||||
}
|
||||
}
|
||||
$name = $x;
|
||||
}
|
||||
$name = str_replace("@#", "\n", $name);
|
||||
$temp[] = $name;
|
||||
}
|
||||
$xaxisData = $temp;
|
||||
$width = $width + ($width / 5);
|
||||
|
||||
$canvas = & Image_Canvas::factory('png', array('width' => $width, 'height' => $height, 'usemap' => true));
|
||||
$imagemap = $canvas->getImageMap();
|
||||
$graph = & Image_Graph::factory('graph', $canvas);
|
||||
$font = & $graph->addNew('font', calculate_font_name($lang_crm));
|
||||
$font->setSize(8);
|
||||
$font->setColor($color);
|
||||
$graph->setFont($font);
|
||||
// create the plotarea layout
|
||||
$title = & Image_Graph::factory('title', array($title, 10));
|
||||
$plotarea = & Image_Graph::factory('plotarea', array(
|
||||
'category',
|
||||
'axis'
|
||||
));
|
||||
$graph->add(Image_Graph::vertical($title, $plotarea, 5));
|
||||
// To create unique lables we need to keep track of lable name and its count
|
||||
$uniquex = array();
|
||||
// Generate colours
|
||||
$colors = color_generator(count($yaxisData), '#33DDFF', '#3322FF');
|
||||
$dataset = & Image_Graph::factory('dataset');
|
||||
$fills = & Image_Graph::factory('Image_Graph_Fill_Array');
|
||||
$sum = 0;
|
||||
$pcvalues = array();
|
||||
for ($i = 0; $i < count($yaxisData); $i++) {
|
||||
$sum += $yaxisData[$i];
|
||||
}
|
||||
for ($i = 0; $i < count($yaxisData); $i++) {
|
||||
// To have unique names even in case of duplicates let us add the id
|
||||
$datalabel = $xaxisData[$i];
|
||||
$xaxisData_appearance = $uniquex[$xaxisData[$i]];
|
||||
if ($xaxisData_appearance == null) {
|
||||
$uniquex[$xaxisData[$i]] = 1;
|
||||
} else {
|
||||
$datalabel = $xaxisData[$i] . ' [' . $xaxisData_appearance . ']';
|
||||
$uniquex[$xaxisData[$i]] = $xaxisData_appearance + 1;
|
||||
}
|
||||
$dataset->addPoint(
|
||||
$datalabel,
|
||||
$yaxisData[$i],
|
||||
array(
|
||||
'url' => $target[$i],
|
||||
'alt' => $alts[$i] . '=' . sprintf('%0.1f%%', 100 * $yaxisData[$i] / $sum)
|
||||
)
|
||||
);
|
||||
$pcvalues[$yaxisData[$i]] = sprintf('%0.1f%%', 100 * $yaxisData[$i] / $sum);
|
||||
$fills->addColor($colors[$i]);
|
||||
}
|
||||
if ($sum == 0)
|
||||
return null;
|
||||
// create the pie chart and associate the filling colours
|
||||
$gbplot = & $plotarea->addNew('pie', $dataset);
|
||||
$plotarea->setPadding(array('top' => 0, 'bottom' => 0, 'left' => 0, 'right' => ($width / 20)));
|
||||
$plotarea->hideAxis();
|
||||
$gbplot->setFillStyle($fills);
|
||||
// format the data values
|
||||
$marker_array = & Image_Graph::factory('Image_Graph_DataPreprocessor_Array', array($pcvalues));
|
||||
// set markers
|
||||
$marker = & $graph->addNew('value_marker', IMAGE_GRAPH_VALUE_Y);
|
||||
$marker->setDataPreprocessor($marker_array);
|
||||
$marker->setFillColor('#FFFFFF');
|
||||
$marker->setBorderColor($color);
|
||||
$marker->setFontColor($color);
|
||||
$marker->setFontSize(8);
|
||||
$pointingMarker = & $graph->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$marker));
|
||||
$gbplot->setMarker($pointingMarker);
|
||||
$legend_box = & $plotarea->addNew('legend');
|
||||
$legend_box->setPadding(array('top' => 20, 'bottom' => 0, 'left' => 0, 'right' => 0));
|
||||
$legend_box->setFillColor('#F5F5F5');
|
||||
$legend_box->showShadow();
|
||||
|
||||
$img = $graph->done(array(
|
||||
'tohtml' => true,
|
||||
'border' => 0,
|
||||
'filename' => $cache_file_name,
|
||||
'filepath' => '',
|
||||
'urlpath' => ''
|
||||
));
|
||||
return $img;
|
||||
}
|
||||
|
||||
//Generates Chart Data in form of an array from the Query Result of reports
|
||||
public static function generateChartDataFromReports($queryResult, $groupbyField, $fieldDetails='', $reportid='') {
|
||||
require_once 'modules/Reports/CustomReportUtils.php';
|
||||
require_once('include/Webservices/Utils.php');
|
||||
require_once('include/Webservices/Query.php');
|
||||
global $adb, $current_user, $theme, $default_charset;
|
||||
$inventorymodules = array('Quotes', 'SalesOrder', 'PurchaseOrder', 'Invoice', 'Products', 'PriceBooks', 'Vendors', 'Services');
|
||||
$rows = $adb->num_rows($queryResult);
|
||||
$condition = "is";
|
||||
$current_theme = $theme;
|
||||
$groupByFields = array();
|
||||
$yaxisArray = array();
|
||||
$ChartDataArray = array();
|
||||
$target_val = array();
|
||||
|
||||
$report = new ReportRun($reportid);
|
||||
$restrictedModules = array();
|
||||
if($report->secondarymodule!='') {
|
||||
$reportModules = explode(":",$report->secondarymodule);
|
||||
} else {
|
||||
$reportModules = array();
|
||||
}
|
||||
array_push($reportModules,$report->primarymodule);
|
||||
|
||||
$restrictedModules = false;
|
||||
foreach($reportModules as $mod) {
|
||||
if(isPermitted($mod,'index') != "yes" || vtlib_isModuleActive($mod) == false) {
|
||||
if(!is_array($restrictedModules)) $restrictedModules = array();
|
||||
$restrictedModules[] = $mod;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_array($restrictedModules) && count($restrictedModules) > 0) {
|
||||
$ChartDataArray['error'] = "<h4>".getTranslatedString('LBL_NO_ACCESS', 'Reports').' - '.implode(',', $restrictedModules)."</h4>";
|
||||
return $ChartDataArray;
|
||||
}
|
||||
|
||||
if ($fieldDetails != '') {
|
||||
list($tablename, $colname, $module_field, $fieldname, $single) = explode(":", $fieldDetails);
|
||||
list($module, $field) = split("_", $module_field);
|
||||
$dateField = false;
|
||||
if ($single == 'D') {
|
||||
$dateField = true;
|
||||
$query = "SELECT * FROM vtiger_reportgroupbycolumn WHERE reportid=? ORDER BY sortid";
|
||||
$result = $adb->pquery($query, array($reportid));
|
||||
$criteria = $adb->query_result($result, 0, 'dategroupbycriteria');
|
||||
}
|
||||
}
|
||||
preg_match('/&/', $groupbyField, $matches);
|
||||
if (!empty($matches)) {
|
||||
$groupfield = str_replace('&', '&', $groupbyField);
|
||||
$groupbyField = $report->replaceSpecialChar($groupfield);
|
||||
}
|
||||
$handler = vtws_getModuleHandlerFromName($module, $current_user);
|
||||
$meta = $handler->getMeta();
|
||||
$meta->retrieveMeta();
|
||||
$referenceFields = $meta->getReferenceFieldDetails();
|
||||
|
||||
if($rows > 0) {
|
||||
$resultRow = $adb->query_result_rowdata($queryResult, 0);
|
||||
if(!array_key_exists($groupbyField, $resultRow)) {
|
||||
$ChartDataArray['error'] = "<h4>".getTranslatedString('LBL_NO_PERMISSION_FIELD', 'Dashboard')."</h4>";
|
||||
return $ChartDataArray;
|
||||
}
|
||||
}
|
||||
for ($i = 0; $i < $rows; $i++) {
|
||||
$groupFieldValue = $adb->query_result($queryResult, $i, strtolower($groupbyField));
|
||||
$decodedGroupFieldValue = html_entity_decode($groupFieldValue, ENT_QUOTES, $default_charset);
|
||||
if (!empty($groupFieldValue)) {
|
||||
if (in_array($module_field, $report->append_currency_symbol_to_value)) {
|
||||
$valueComp = explode('::', $groupFieldValue);
|
||||
$groupFieldValue = $valueComp[1];
|
||||
}
|
||||
if ($dateField) {
|
||||
if (!empty($groupFieldValue))
|
||||
$groupByFields[] = CustomReportUtils::getXAxisDateFieldValue($groupFieldValue, $criteria);
|
||||
else
|
||||
$groupByFields[] = "Null";
|
||||
}
|
||||
else if (in_array($fieldname, array_keys($referenceFields))) {
|
||||
if (count($referenceFields[$fieldname]) > 1) {
|
||||
$refenceModule = CustomReportUtils::getEntityTypeFromName($decodedGroupFieldValue, $referenceFields[$fieldname]);
|
||||
}
|
||||
else {
|
||||
$refenceModule = $referenceFields[$fieldname][0];
|
||||
}
|
||||
$groupByFields[] = $groupFieldValue;
|
||||
|
||||
if ($fieldname == 'currency_id' && in_array($module, $inventorymodules)) {
|
||||
$tablename = 'vtiger_currency_info';
|
||||
} elseif ($refenceModule == 'DocumentFolders' && $fieldname == 'folderid') {
|
||||
$tablename = 'vtiger_attachmentsfolder';
|
||||
$colname = 'foldername';
|
||||
} else {
|
||||
require_once "modules/$refenceModule/$refenceModule.php";
|
||||
$focus = new $refenceModule();
|
||||
$tablename = $focus->table_name;
|
||||
$colname = $focus->list_link_field;
|
||||
$condition = "c";
|
||||
}
|
||||
} else {
|
||||
$groupByFields[] = $groupFieldValue;
|
||||
}
|
||||
$yaxisArray[] = $adb->query_result($queryResult, $i, 'groupby_count');
|
||||
if ($fieldDetails != '') {
|
||||
if ($dateField) {
|
||||
$advanceSearchCondition = CustomReportUtils::getAdvanceSearchCondition($fieldDetails, $criteria, $groupFieldValue);
|
||||
if ($module == 'Calendar') {
|
||||
$link_val = "index.php?module=" . $module . "&query=true&action=ListView&" . $advanceSearchCondition;
|
||||
}else
|
||||
$link_val = "index.php?module=" . $module . "&query=true&action=index&" . $advanceSearchCondition;
|
||||
}
|
||||
else {
|
||||
$cvid = getCvIdOfAll($module);
|
||||
$esc_search_str = urlencode($decodedGroupFieldValue);
|
||||
if ($single == 'DT') {
|
||||
$esc_search_str = urlencode($groupFieldValue);
|
||||
if (strtolower($fieldname) == 'modifiedtime' || strtolower($fieldname) == 'createdtime') {
|
||||
$tablename = 'vtiger_crmentity';
|
||||
$colname = $fieldname;
|
||||
}
|
||||
}
|
||||
if ($fieldname == 'assigned_user_id') {
|
||||
$tablename = 'vtiger_crmentity';
|
||||
$colname = 'smownerid';
|
||||
}
|
||||
|
||||
if ($module == 'Calendar') {
|
||||
$link_val = "index.php?module=" . $module . "&action=ListView&search_text=" . $esc_search_str . "&search_field=" . $fieldname . "&searchtype=BasicSearch&query=true&operator=e&viewname=" . $cvid;
|
||||
} else {
|
||||
$link_val = "index.php?module=" . $module . "&action=index&search_text=" . $esc_search_str . "&search_field=" . $fieldname . "&searchtype=BasicSearch&query=true&operator=e&viewname=" . $cvid;
|
||||
}
|
||||
}
|
||||
|
||||
$target_val[] = $link_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(count($groupByFields) == 0) {
|
||||
$ChartDataArray['error'] = "<div class='componentName'>".getTranslatedString('LBL_NO_DATA', 'Reports')."</div";
|
||||
}
|
||||
$ChartDataArray['xaxisData'] = $groupByFields;
|
||||
$ChartDataArray['yaxisData'] = $yaxisArray;
|
||||
$ChartDataArray['targetLink'] = $target_val;
|
||||
$theme = $current_theme;
|
||||
return $ChartDataArray;
|
||||
}
|
||||
|
||||
public static function getReportBarChart($queryResult, $groupbyField, $fieldDetails, $reportid, $charttype='horizontal') {
|
||||
global $theme;
|
||||
$BarChartDetails = self::generateChartDataFromReports($queryResult, $groupbyField, $fieldDetails, $reportid);
|
||||
$groupbyFields = $BarChartDetails['xaxisData'];
|
||||
$yaxisArray = $BarChartDetails['yaxisData'];
|
||||
$targerLinks = $BarChartDetails['targetLink'];
|
||||
if ($theme == "softed") {
|
||||
$font_color = "#212473";
|
||||
} else {
|
||||
$font_color = "#000000";
|
||||
}
|
||||
if(!empty($BarChartDetails['error'])) {
|
||||
return $BarChartDetails['error'];
|
||||
} else {
|
||||
$barChart = ChartUtils::getBarChart($groupbyFields, $yaxisArray, '', '350', '300', $charttype, false, $targerLinks, $font_color);
|
||||
return $barChart;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getReportPieChart($queryResult, $groupbyField, $fieldDetails, $reportid) {
|
||||
global $theme;
|
||||
$PieChartDetails = self::generateChartDataFromReports($queryResult, $groupbyField, $fieldDetails, $reportid);
|
||||
$groupbyFields = $PieChartDetails['xaxisData'];
|
||||
$yaxisArray = $PieChartDetails['yaxisData'];
|
||||
$targerLinks = $PieChartDetails['targetLink'];
|
||||
$charttype = 'vertical';
|
||||
if ($theme == "softed") {
|
||||
$font_color = "#212473";
|
||||
} else {
|
||||
$font_color = "#000000";
|
||||
}
|
||||
if(!empty($PieChartDetails['error'])) {
|
||||
return $PieChartDetails['error'];
|
||||
} else {
|
||||
$pieChart = ChartUtils::getPieChart($groupbyFields, $yaxisArray, '', '350', '300', $charttype, false, $targerLinks, $font_color);
|
||||
return $pieChart;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,364 @@
|
|||
<?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.
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
global $combo_strings;
|
||||
|
||||
$combo_strings = Array(
|
||||
'accounttype_dom' => Array(''=>''
|
||||
, 'Analyst'=>'Analyst'
|
||||
, 'Competitor'=>'Competitor'
|
||||
, 'Customer'=>'Customer'
|
||||
, 'Integrator'=>'Integrator'
|
||||
, 'Investor'=>'Investor'
|
||||
, 'Partner'=>'Partner'
|
||||
, 'Press'=>'Press'
|
||||
, 'Prospect'=>'Prospect'
|
||||
, 'Reseller'=>'Reseller'
|
||||
, 'Other'=>'Other'
|
||||
),
|
||||
'industry_dom' => Array(''=>''
|
||||
, 'Apparel'=>'Apparel'
|
||||
, 'Banking'=>'Banking'
|
||||
, 'Biotechnology'=>'Biotechnology'
|
||||
, 'Chemicals'=>'Chemicals'
|
||||
, 'Communications'=>'Communications'
|
||||
, 'Construction'=>'Construction'
|
||||
, 'Consulting'=>'Consulting'
|
||||
, 'Education'=>'Education'
|
||||
, 'Electronics'=>'Electronics'
|
||||
, 'Energy'=>'Energy'
|
||||
, 'Engineering'=>'Engineering'
|
||||
, 'Entertainment'=>'Entertainment'
|
||||
, 'Environmental'=>'Environmental'
|
||||
, 'Finance'=>'Finance'
|
||||
, 'Food & Beverage'=>'Food & Beverage'
|
||||
, 'Government'=>'Government'
|
||||
, 'Healthcare'=>'Healthcare'
|
||||
, 'Hospitality'=>'Hospitality'
|
||||
, 'Insurance'=>'Insurance'
|
||||
, 'Machinery'=>'Machinery'
|
||||
, 'Manufacturing'=>'Manufacturing'
|
||||
, 'Media'=>'Media'
|
||||
, 'Not For Profit'=>'Not For Profit'
|
||||
, 'Recreation'=>'Recreation'
|
||||
, 'Retail'=>'Retail'
|
||||
, 'Shipping'=>'Shipping'
|
||||
, 'Technology'=>'Technology'
|
||||
, 'Telecommunications'=>'Telecommunications'
|
||||
, 'Transportation'=>'Transportation'
|
||||
, 'Utilities'=>'Utilities'
|
||||
, 'Other'=>'Other'
|
||||
),
|
||||
'leadsource_dom' => Array(''=>''
|
||||
, 'Cold Call'=>'Cold Call'
|
||||
, 'Existing Customer'=>'Existing Customer'
|
||||
, 'Self Generated'=>'Self Generated'
|
||||
, 'Employee'=>'Employee'
|
||||
, 'Partner'=>'Partner'
|
||||
, 'Public Relations'=>'Public Relations'
|
||||
, 'Direct Mail'=>'Direct Mail'
|
||||
, 'Conference'=>'Conference'
|
||||
, 'Trade Show'=>'Trade Show'
|
||||
, 'Web Site'=>'Web Site'
|
||||
, 'Word of mouth'=>'Word of mouth'
|
||||
, 'Other'=>'Other'
|
||||
),
|
||||
'leadstatus_dom' => Array(''=>''
|
||||
, 'Attempted to Contact'=>'Attempted to Contact'
|
||||
, 'Cold'=>'Cold'
|
||||
, 'Contact in Future'=>'Contact in Future'
|
||||
, 'Contacted'=>'Contacted'
|
||||
, 'Hot'=>'Hot'
|
||||
, 'Junk Lead'=>'Junk Lead'
|
||||
, 'Lost Lead'=>'Lost Lead'
|
||||
, 'Not Contacted'=>'Not Contacted'
|
||||
, 'Pre Qualified'=>'Pre Qualified'
|
||||
, 'Qualified'=>'Qualified'
|
||||
, 'Warm'=>'Warm'
|
||||
),
|
||||
'rating_dom' => Array(''=>''
|
||||
, 'Acquired'=>'Acquired'
|
||||
, 'Active'=>'Active'
|
||||
, 'Market Failed'=>'Market Failed'
|
||||
, 'Project Cancelled'=>'Project Cancelled'
|
||||
, 'Shutdown'=>'Shutdown'
|
||||
),
|
||||
'opportunity_type_dom' => Array(''=>''
|
||||
, 'Existing Business'=>'Existing Business'
|
||||
, 'New Business'=>'New Business'
|
||||
),
|
||||
'sales_stage_dom' => Array('Prospecting'=>'Prospecting'
|
||||
, 'Qualification'=>'Qualification'
|
||||
, 'Needs Analysis'=>'Needs Analysis'
|
||||
, 'Value Proposition'=>'Value Proposition'
|
||||
, 'Id. Decision Makers'=>'Id. Decision Makers'
|
||||
, 'Perception Analysis'=>'Perception Analysis'
|
||||
, 'Proposal/Price Quote'=>'Proposal/Price Quote'
|
||||
, 'Negotiation/Review'=>'Negotiation/Review'
|
||||
, 'Closed Won'=>'Closed Won'
|
||||
, 'Closed Lost'=>'Closed Lost'
|
||||
),
|
||||
'salutationtype_dom' => Array(''=>''
|
||||
, 'Mr.'=>'Mr.'
|
||||
, 'Ms.'=>'Ms.'
|
||||
, 'Mrs.'=>'Mrs.'
|
||||
, 'Dr.'=>'Dr.'
|
||||
, 'Prof.'=>'Prof.'
|
||||
),
|
||||
'eventstatus_dom' => Array('Planned'=>'Planned'
|
||||
, 'Held'=>'Held'
|
||||
, 'Not Held'=>'Not Held'
|
||||
),
|
||||
'taskstatus_dom' => Array('Not Started'=>'Not Started'
|
||||
, 'In Progress'=>'In Progress'
|
||||
, 'Completed'=>'Completed'
|
||||
, 'Pending Input'=>'Pending Input'
|
||||
, 'Deferred'=>'Deferred'
|
||||
, 'Planned'=>'Planned'
|
||||
),
|
||||
'taskpriority_dom' => Array('High'=>'High'
|
||||
,'Medium'=>'Medium'
|
||||
,'Low'=>'Low'
|
||||
),
|
||||
'duration_minutes_dom' => Array('00'=>'00'
|
||||
, '15'=>'15'
|
||||
, '30'=>'30'
|
||||
, '45'=>'45'
|
||||
),
|
||||
'productcategory_dom' => Array(''=>''
|
||||
, 'Hardware'=>'Hardware'
|
||||
, 'Software'=>'Software'
|
||||
, 'CRM Applications'=>'CRM Applications'
|
||||
),
|
||||
'manufacturer_dom' => Array(''=>''
|
||||
, 'AltvetPet Inc.'=>'AltvetPet Inc.'
|
||||
, 'LexPon Inc.'=>'LexPon Inc.'
|
||||
, 'MetBeat Corp'=>'MetBeat Corp'
|
||||
),
|
||||
'ticketcategories_dom' => Array('Big Problem'=>'Big Problem'
|
||||
,'Small Problem'=>'Small Problem'
|
||||
,'Other Problem'=>'Other Problem'
|
||||
),
|
||||
'ticketpriorities_dom' => Array('Low'=>'Low'
|
||||
,'Normal'=>'Normal'
|
||||
,'High'=>'High'
|
||||
,'Urgent'=>'Urgent'
|
||||
),
|
||||
'ticketseverities_dom' => Array('Minor'=>'Minor'
|
||||
,'Major'=>'Major'
|
||||
,'Feature'=>'Feature'
|
||||
,'Critical'=>'Critical'
|
||||
),
|
||||
|
||||
'ticketstatus_dom' => Array('Open'=>'Open'
|
||||
,'In Progress'=>'In Progress'
|
||||
,'Wait For Response'=>'Wait For Response'
|
||||
,'Closed'=>'Closed'
|
||||
),
|
||||
|
||||
'activitytype_dom' => Array('Call'=>'Call'
|
||||
, 'Meeting'=>'Meeting'
|
||||
),
|
||||
|
||||
'faqcategories_dom' => Array('General'=>'General'
|
||||
),
|
||||
|
||||
'faqstatus_dom' => Array('Draft'=>'Draft'
|
||||
,'Reviewed'=>'Reviewed'
|
||||
,'Published'=>'Published'
|
||||
,'Obsolete'=>'Obsolete'
|
||||
),
|
||||
|
||||
|
||||
'currency_dom' => Array('Rupees'=>'Rupees',
|
||||
'Dollar'=>'Dollar',
|
||||
'Euro'=>'Euro'
|
||||
),
|
||||
|
||||
'visibility_dom' => Array('Private'=>'Private',
|
||||
'Public'=>'Public'
|
||||
),
|
||||
|
||||
'usageunit_dom' => Array('Box'=>'Box',
|
||||
'Carton'=>'Carton',
|
||||
'Dozen'=>'Dozen',
|
||||
'Each'=>'Each',
|
||||
'Hours'=>'Hours',
|
||||
'Impressions'=>'Impressions',
|
||||
'Lb'=>'Lb',
|
||||
'M'=>'M',
|
||||
'Pack'=>'Pack',
|
||||
'Pages'=>'Pages',
|
||||
'Pieces'=>'Pieces',
|
||||
'Quantity'=>'Quantity',
|
||||
'Reams'=>'Reams',
|
||||
'Sheet'=>'Sheet',
|
||||
'Spiral Binder'=>'Spiral Binder',
|
||||
'Sq Ft'=>'Sq Ft'
|
||||
),
|
||||
|
||||
'glacct_dom' => Array('300-Sales-Software'=>'300-Sales-Software',
|
||||
'301-Sales-Hardware'=>'301-Sales-Hardware',
|
||||
'302-Rental-Income'=>'302-Rental-Income',
|
||||
'303-Interest-Income'=>'303-Interest-Income',
|
||||
'304-Sales-Software-Support'=>'304-Sales-Software-Support',
|
||||
'305-Sales Other'=>'305-Sales Other',
|
||||
'306-Internet Sales'=>'306-Internet Sales',
|
||||
'307-Service-Hardware Labor'=>'307-Service-Hardware Labor',
|
||||
'308-Sales-Books'=>'308-Sales-Books'
|
||||
),
|
||||
|
||||
'quotestage_dom' => Array('Created'=>'Created',
|
||||
'Delivered'=>'Delivered',
|
||||
'Reviewed'=>'Reviewed',
|
||||
'Accepted'=>'Accepted',
|
||||
'Rejected'=>'Rejected'
|
||||
),
|
||||
|
||||
'carrier_dom' => Array('FedEx'=>'FedEx',
|
||||
'UPS'=>'UPS',
|
||||
'USPS'=>'USPS',
|
||||
'DHL'=>'DHL',
|
||||
'BlueDart'=>'BlueDart'
|
||||
),
|
||||
|
||||
'taxclass_dom' => Array('SalesTax'=>'SalesTax',
|
||||
'Vat'=>'Vat'
|
||||
),
|
||||
|
||||
'recurringtype_dom' => Array(''=>'',
|
||||
'Daily'=>'Daily',
|
||||
'Weekly'=>'Weekly',
|
||||
'Monthly'=>'Monthly',
|
||||
'Yearly'=>'Yearly'
|
||||
),
|
||||
|
||||
'invoicestatus_dom' => Array('AutoCreated'=>'AutoCreated',
|
||||
'Created'=>'Created',
|
||||
'Approved'=>'Approved',
|
||||
'Sent'=>'Sent',
|
||||
'Credit Invoice'=>'Credit Invoice',
|
||||
'Paid'=>'Paid'
|
||||
),
|
||||
|
||||
'postatus_dom' => Array('Created'=>'Created',
|
||||
'Approved'=>'Approved',
|
||||
'Delivered'=>'Delivered',
|
||||
'Cancelled'=>'Cancelled',
|
||||
'Received Shipment'=>'Received Shipment'
|
||||
),
|
||||
|
||||
'sostatus_dom' => Array('Created'=>'Created',
|
||||
'Approved'=>'Approved',
|
||||
'Delivered'=>'Delivered',
|
||||
'Cancelled'=>'Cancelled'
|
||||
),
|
||||
|
||||
'campaignstatus_dom' => Array(''=>'',
|
||||
'Planning'=>'Planning',
|
||||
'Active'=>'Active',
|
||||
'Inactive'=>'Inactive',
|
||||
'Completed'=>'Completed',
|
||||
'Cancelled'=>'Cancelled', ),
|
||||
|
||||
|
||||
'campaigntype_dom' => Array(''=>'',
|
||||
'Conference'=>'Conference',
|
||||
'Webinar'=>'Webinar',
|
||||
'Trade Show'=>'Trade Show', 'Public Relations'=>'Public Relations', 'Partners'=>'Partners',
|
||||
'Referral Program'=>'Referral Program',
|
||||
'Advertisement'=>'Advertisement',
|
||||
'Banner Ads'=>'Banner Ads',
|
||||
'Direct Mail'=>'Direct Mail',
|
||||
'Email'=>'Email',
|
||||
'Telemarketing'=>'Telemarketing',
|
||||
'Others'=>'Others'
|
||||
),
|
||||
|
||||
'expectedresponse_dom' => Array(''=>'',
|
||||
'Excellent'=>'Excellent',
|
||||
'Good'=>'Good',
|
||||
'Average'=>'Average',
|
||||
'Poor'=>'Poor'
|
||||
),
|
||||
'status_dom' => Array('Active'=>'Active',
|
||||
'Inactive'=>'Inactive'
|
||||
),
|
||||
'activity_view_dom' => Array('Today'=>'Today',
|
||||
'This Week'=>'This Week',
|
||||
'This Month'=>'This Month',
|
||||
'This Year'=>'This Year'
|
||||
),
|
||||
'lead_view_dom' => Array('Today'=>'Today',
|
||||
'Last 2 Days'=>'Last 2 Days',
|
||||
'Last Week'=>'Last Week'
|
||||
),
|
||||
'date_format_dom' => Array('dd-mm-yyyy'=>'dd-mm-yyyy',
|
||||
'mm-dd-yyyy'=>'mm-dd-yyyy',
|
||||
'yyyy-mm-dd'=>'yyyy-mm-dd'
|
||||
),
|
||||
'reminder_interval_dom' => Array('None'=>'None',
|
||||
'1 Minute'=>'1 Minute',
|
||||
'5 Minutes'=>'5 Minutes',
|
||||
'15 Minutes'=>'15 Minutes',
|
||||
'30 Minutes'=>'30 Minutes',
|
||||
'45 Minutes'=>'45 Minutes',
|
||||
'1 Hour'=>'1 Hour',
|
||||
'1 Day'=>'1 Day'
|
||||
),
|
||||
|
||||
'recurring_frequency_dom' => Array('--None--'=>'--None--',
|
||||
'Daily' => 'Daily',
|
||||
'Weekly' => 'Weekly',
|
||||
'Monthly' => 'Monthly',
|
||||
'Quarterly' => 'Quarterly',
|
||||
'Yearly' => 'Yearly'
|
||||
),
|
||||
'payment_duration_dom' => Array('Net 30 days'=>'Net 30 days',
|
||||
'Net 45 days'=>'Net 45 days',
|
||||
'Net 60 days'=>'Net 60 days'
|
||||
),
|
||||
'campaignrelstatus_dom' => Array('--None--'=>'--None--',
|
||||
'Contacted - Successful' => 'Contacted - Successful',
|
||||
'Contacted - Unsuccessful' => 'Contacted - Unsuccessful',
|
||||
'Contacted - Never Contact Again' => 'Contacted - Never Contact Again'
|
||||
),
|
||||
'currency_grouping_pattern_dom' => Array('123,456,789' => '123,456,789',
|
||||
'123456789' => '123456789',
|
||||
'123456,789' => '123456,789',
|
||||
'12,34,56,789' => '12,34,56,789'
|
||||
),
|
||||
'currency_decimal_separator_dom' => Array("." => ".",
|
||||
"," => ",",
|
||||
"'" => "'",
|
||||
" " => " ",
|
||||
"$" => "$"
|
||||
),
|
||||
'currency_grouping_separator_dom' => Array("." => ".",
|
||||
"," => ",",
|
||||
"'" => "'",
|
||||
" " => " ",
|
||||
"$" => "$"
|
||||
),
|
||||
'currency_symbol_placement_dom' => Array("$1.0" => "$1.0",
|
||||
"1.0$" => "1.0$"
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
require_once('modules/Users/UserTimeZonesArray.php');
|
||||
$usertimezonesClass = new UserTimeZones();
|
||||
$arrayOfSupportedTimeZones = $usertimezonesClass->userTimeZones();
|
||||
$combo_strings['time_zone_dom'] = array_combine($arrayOfSupportedTimeZones,$arrayOfSupportedTimeZones);
|
||||
|
||||
?>
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?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/utils/CommonUtils.php');
|
||||
require_once('include/database/PearDatabase.php');
|
||||
/** Function to returns the combo field values in array format
|
||||
* @param $combofieldNames -- combofieldNames:: Type string array
|
||||
* @returns $comboFieldArray -- comboFieldArray:: Type string array
|
||||
*/
|
||||
function getComboArray($combofieldNames)
|
||||
{
|
||||
global $log,$mod_strings;
|
||||
$log->debug("Entering getComboArray(".$combofieldNames.") method ...");
|
||||
global $adb,$current_user;
|
||||
$roleid=$current_user->roleid;
|
||||
$comboFieldArray = Array();
|
||||
foreach ($combofieldNames as $tableName => $arrayName)
|
||||
{
|
||||
$fldArrName= $arrayName;
|
||||
$arrayName = Array();
|
||||
|
||||
$sql = "select $tableName from vtiger_$tableName";
|
||||
$params = array();
|
||||
if(!is_admin($current_user))
|
||||
{
|
||||
$subrole = getRoleSubordinates($roleid);
|
||||
if(count($subrole)> 0)
|
||||
{
|
||||
$roleids = $subrole;
|
||||
array_push($roleids, $roleid);
|
||||
}
|
||||
else
|
||||
{
|
||||
$roleids = $roleid;
|
||||
}
|
||||
$sql = "select distinct $tableName from vtiger_$tableName inner join vtiger_role2picklist on vtiger_role2picklist.picklistvalueid = vtiger_$tableName.picklist_valueid where roleid in(". generateQuestionMarks($roleids) .") order by sortid";
|
||||
$params = array($roleids);
|
||||
}
|
||||
$result = $adb->pquery($sql, $params);
|
||||
while($row = $adb->fetch_array($result))
|
||||
{
|
||||
$val = $row[$tableName];
|
||||
$arrayName[$val] = getTranslatedString($val);
|
||||
}
|
||||
$comboFieldArray[$fldArrName] = $arrayName;
|
||||
}
|
||||
$log->debug("Exiting getComboArray method ...");
|
||||
return $comboFieldArray;
|
||||
}
|
||||
function getUniquePicklistID()
|
||||
{
|
||||
global $adb;
|
||||
/*$sql="select id from vtiger_picklistvalues_seq";
|
||||
$picklistvalue_id = $adb->query_result($adb->pquery($sql, array()),0,'id');
|
||||
|
||||
$qry = "update vtiger_picklistvalues_seq set id =?";
|
||||
$adb->pquery($qry, array(++$picklistvalue_id));*/
|
||||
return $adb->getUniqueID('vtiger_picklistvalues');
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,285 @@
|
|||
<?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/database/PearDatabase.php');
|
||||
require_once('include/utils/utils.php');
|
||||
|
||||
/**
|
||||
* Function to get vtiger_field typename
|
||||
* @param $uitype :: uitype -- Type integer
|
||||
* returns the vtiger_field type name -- Type string
|
||||
*/
|
||||
function getCustomFieldTypeName($uitype)
|
||||
{
|
||||
|
||||
global $mod_strings,$app_strings;
|
||||
global $log;
|
||||
$log->debug("Entering getCustomFieldTypeName(".$uitype.") method ...");
|
||||
global $log;
|
||||
$log->info("uitype is ".$uitype);
|
||||
$fldname = '';
|
||||
|
||||
/*
|
||||
* salutation type is an exception where the uitype 55 is considered to be as text.
|
||||
*/
|
||||
|
||||
if($uitype == 1 || $uitype == 55 || $uitype == 255)
|
||||
{
|
||||
$fldname = $mod_strings['Text'];
|
||||
}
|
||||
elseif($uitype == 7)
|
||||
{
|
||||
$fldname = $mod_strings['Number'];
|
||||
}
|
||||
elseif($uitype == 9)
|
||||
{
|
||||
$fldname = $mod_strings['Percent'];
|
||||
}
|
||||
elseif($uitype == 5 || $uitype == 23)
|
||||
{
|
||||
$fldname = $mod_strings['Date'];
|
||||
}
|
||||
elseif($uitype == 13)
|
||||
{
|
||||
$fldname = $mod_strings['Email'];
|
||||
}
|
||||
elseif($uitype == 11)
|
||||
{
|
||||
$fldname = $mod_strings['Phone'];
|
||||
}
|
||||
elseif($uitype == 15 )
|
||||
{
|
||||
$fldname = $mod_strings['PickList'];
|
||||
}
|
||||
elseif($uitype == 17)
|
||||
{
|
||||
$fldname = $mod_strings['LBL_URL'];
|
||||
}
|
||||
elseif($uitype == 56)
|
||||
{
|
||||
$fldname = $mod_strings['LBL_CHECK_BOX'];
|
||||
}
|
||||
elseif($uitype == 71)
|
||||
{
|
||||
$fldname = $mod_strings['Currency'];
|
||||
}
|
||||
elseif($uitype == 21 || $uitype == 19)
|
||||
{
|
||||
$fldname = $mod_strings['LBL_TEXT_AREA'];
|
||||
}
|
||||
elseif($uitype == 33)
|
||||
{
|
||||
$fldname = $mod_strings['LBL_MULTISELECT_COMBO'];
|
||||
}
|
||||
elseif($uitype == 85)
|
||||
{
|
||||
$fldname = $mod_strings['Skype'];
|
||||
}
|
||||
$log->debug("Exiting getCustomFieldTypeName method ...");
|
||||
return $fldname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get custom vtiger_fields
|
||||
* @param $module :: vtiger_table name -- Type string
|
||||
* returns customfields in key-value pair array format
|
||||
*/
|
||||
function getCustomFieldArray($module)
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering getCustomFieldArray(".$module.") method ...");
|
||||
global $adb;
|
||||
$custquery = "select tablename,fieldname from vtiger_field where tablename=? and vtiger_field.presence in (0,2) order by tablename";
|
||||
$custresult = $adb->pquery($custquery, array('vtiger_'.strtolower($module).'cf'));
|
||||
$custFldArray = Array();
|
||||
$noofrows = $adb->num_rows($custresult);
|
||||
for($i=0; $i<$noofrows; $i++)
|
||||
{
|
||||
$colName=$adb->query_result($custresult,$i,"fieldname");
|
||||
$custFldArray[$colName] = $i;
|
||||
}
|
||||
$log->debug("Exiting getCustomFieldArray method ...");
|
||||
return $custFldArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get columnname and vtiger_fieldlabel from vtiger_field vtiger_table
|
||||
* @param $module :: module name -- Type string
|
||||
* @param $trans_array :: translated column vtiger_fields -- Type array
|
||||
* returns trans_array in key-value pair array format
|
||||
*/
|
||||
function getCustomFieldTrans($module, $trans_array)
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering getCustomFieldTrans(".$module.",". $trans_array.") method ...");
|
||||
global $adb;
|
||||
$tab_id = getTabid($module);
|
||||
$custquery = "select columnname,fieldlabel from vtiger_field where generatedtype=2 and vtiger_field.presence in (0,2) and tabid=?";
|
||||
$custresult = $adb->pquery($custquery, array($tab_id));
|
||||
$custFldArray = Array();
|
||||
$noofrows = $adb->num_rows($custresult);
|
||||
for($i=0; $i<$noofrows; $i++)
|
||||
{
|
||||
$colName=$adb->query_result($custresult,$i,"columnname");
|
||||
$fldLbl = $adb->query_result($custresult,$i,"fieldlabel");
|
||||
$trans_array[$colName] = $fldLbl;
|
||||
}
|
||||
$log->debug("Exiting getCustomFieldTrans method ...");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to get customfield record from vtiger_field vtiger_table
|
||||
* @param $tab :: Tab ID -- Type integer
|
||||
* @param $datatype :: vtiger_field name -- Type string
|
||||
* @param $id :: vtiger_field Id -- Type integer
|
||||
* returns the data result in string format
|
||||
*/
|
||||
function getCustomFieldData($tab,$id,$datatype)
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering getCustomFieldData(".$tab.",".$id.",".$datatype.") method ...");
|
||||
global $adb;
|
||||
$query = "select * from vtiger_field where tabid=? and fieldid=? and vtiger_field.presence in (0,2)";
|
||||
$result = $adb->pquery($query, array($tab, $id));
|
||||
$return_data=$adb->fetch_array($result);
|
||||
$log->debug("Exiting getCustomFieldData method ...");
|
||||
return $return_data[$datatype];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to get customfield type,length value,decimal value and picklist value
|
||||
* @param $label :: vtiger_field typename -- Type string
|
||||
* @param $typeofdata :: datatype -- Type string
|
||||
* returns the vtiger_field type,length,decimal
|
||||
* and picklist value in ';' separated array format
|
||||
*/
|
||||
function getFldTypeandLengthValue($label,$typeofdata)
|
||||
{
|
||||
global $log;
|
||||
global $mod_strings,$app_strings;
|
||||
$log->debug("Entering getFldTypeandLengthValue(".$label.",".$typeofdata.") method ...");
|
||||
if($label == $mod_strings['Text'])
|
||||
{
|
||||
$types = explode("~",$typeofdata);
|
||||
$data_array=array('0',$types[3]);
|
||||
$fieldtype = implode(";",$data_array);
|
||||
}
|
||||
elseif($label == $mod_strings['Number'])
|
||||
{
|
||||
$types = explode("~",$typeofdata);
|
||||
$data_decimal = explode(",",$types[2]);
|
||||
$data_array=array('1',$data_decimal[0],$data_decimal[1]);
|
||||
$fieldtype = implode(";",$data_array);
|
||||
}
|
||||
elseif($label == $mod_strings['Percent'])
|
||||
{
|
||||
$types = explode("~",$typeofdata);
|
||||
$data_array=array('2','5',$types[3]);
|
||||
$fieldtype = implode(";",$data_array);
|
||||
}
|
||||
elseif($label == $mod_strings['Currency'])
|
||||
{
|
||||
$types = explode("~",$typeofdata);
|
||||
$data_decimal = explode(",",$types[2]);
|
||||
$data_array=array('3',$data_decimal[0],$data_decimal[1]);
|
||||
$fieldtype = implode(";",$data_array);
|
||||
}
|
||||
elseif($label == $mod_strings['Date'])
|
||||
{
|
||||
$fieldtype = '4';
|
||||
}
|
||||
elseif($label == $mod_strings['Email'])
|
||||
{
|
||||
$fieldtype = '5';
|
||||
}
|
||||
elseif($label == $mod_strings['Phone'])
|
||||
{
|
||||
$fieldtype = '6';
|
||||
}
|
||||
elseif($label == $mod_strings['PickList'])
|
||||
{
|
||||
$fieldtype = '7';
|
||||
}
|
||||
elseif($label == $mod_strings['LBL_URL'])
|
||||
{
|
||||
$fieldtype = '8';
|
||||
}
|
||||
elseif($label == $mod_strings['LBL_CHECK_BOX'])
|
||||
{
|
||||
$fieldtype = '9';
|
||||
}
|
||||
elseif($label == $mod_strings['LBL_TEXT_AREA'])
|
||||
{
|
||||
$fieldtype = '10';
|
||||
}
|
||||
elseif($label == $mod_strings['LBL_MULTISELECT_COMBO'])
|
||||
{
|
||||
$fieldtype = '11';
|
||||
}
|
||||
elseif($label == $mod_strings['Skype'])
|
||||
{
|
||||
$fieldtype = '12';
|
||||
}
|
||||
$log->debug("Exiting getFldTypeandLengthValue method ...");
|
||||
return $fieldtype;
|
||||
}
|
||||
|
||||
function getCalendarCustomFields($tabid,$mode='edit',$col_fields='') {
|
||||
global $adb, $log, $current_user;
|
||||
$log->debug("Entering getCalendarCustomFields($tabid, $mode, $col_fields)");
|
||||
|
||||
require('user_privileges/user_privileges_'.$current_user->id.'.php');
|
||||
|
||||
$block = getBlockId($tabid,"LBL_CUSTOM_INFORMATION");
|
||||
$custparams = array($block, $tabid);
|
||||
|
||||
if($is_admin == true || $profileGlobalPermission[1] == 0 || $profileGlobalPermission[2] == 0) {
|
||||
$custquery = "select * from vtiger_field where block=? AND vtiger_field.tabid=? ORDER BY fieldid";
|
||||
} else {
|
||||
$profileList = getCurrentUserProfileList();
|
||||
$custquery = "SELECT vtiger_field.* FROM vtiger_field" .
|
||||
" INNER JOIN vtiger_profile2field ON vtiger_profile2field.fieldid=vtiger_field.fieldid" .
|
||||
" INNER JOIN vtiger_def_org_field ON vtiger_def_org_field.fieldid=vtiger_field.fieldid" .
|
||||
" WHERE vtiger_field.block=? AND vtiger_field.tabid=? AND vtiger_profile2field.visible=0" .
|
||||
" AND vtiger_def_org_field.visible=0 AND vtiger_profile2field.profileid IN (". generateQuestionMarks($profileList) .")";
|
||||
|
||||
if ($mode == 'edit') {
|
||||
$custquery .= " AND vtiger_profile2field.readonly = 0";
|
||||
}
|
||||
$custquery .= " ORDER BY vtiger_field.fieldid";
|
||||
array_push($custparams, $profileList);
|
||||
}
|
||||
$custresult = $adb->pquery($custquery, $custparams);
|
||||
|
||||
$custFldArray = Array();
|
||||
$noofrows = $adb->num_rows($custresult);
|
||||
for($i=0; $i<$noofrows; $i++)
|
||||
{
|
||||
$fieldname=$adb->query_result($custresult,$i,"fieldname");
|
||||
$fieldlabel=$adb->query_result($custresult,$i,"fieldlabel");
|
||||
$columnName=$adb->query_result($custresult,$i,"columnname");
|
||||
$uitype=$adb->query_result($custresult,$i,"uitype");
|
||||
$maxlength = $adb->query_result($custresult,$i,"maximumlength");
|
||||
$generatedtype = $adb->query_result($custresult,$i,"generatedtype");
|
||||
$typeofdata = $adb->query_result($custresult,$i,"typeofdata");
|
||||
|
||||
if ($mode == 'edit')
|
||||
$custfld = getOutputHtml($uitype, $fieldname, $fieldlabel, $maxlength, $col_fields,$generatedtype,'Calendar',$mode, $typeofdata);
|
||||
if ($mode == 'detail_view')
|
||||
$custfld = getDetailViewOutputHtml($uitype, $fieldname, $fieldlabel, $col_fields,$generatedtype,$tabid);
|
||||
$custFldArray[] = $custfld;
|
||||
}
|
||||
$log->debug("Exiting getCalendarCustomFields()");
|
||||
return $custFldArray;
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
/*********************************************************************************
|
||||
* The contents of this file are subject to the SugarCRM Public License Version 1.1.2
|
||||
* ("License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at http://www.sugarcrm.com/SPL
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
* the specific language governing rights and limitations under the License.
|
||||
* The Original Code is: SugarCRM Open Source
|
||||
* The Initial Developer of the Original Code is SugarCRM, Inc.
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.;
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
********************************************************************************/
|
||||
|
||||
//Added to check database charset and $default_charset are set to UTF8.
|
||||
//If both are not set to be UTF-8, Then we will show an alert message.
|
||||
function check_db_utf8_support($conn) {
|
||||
global $db_type;
|
||||
if($db_type == 'pgsql')
|
||||
return true;
|
||||
$dbvarRS = &$conn->Execute("show variables like '%_database' ");
|
||||
$db_character_set = null;
|
||||
$db_collation_type = null;
|
||||
while(!$dbvarRS->EOF) {
|
||||
$arr = $dbvarRS->FetchRow();
|
||||
$arr = array_change_key_case($arr);
|
||||
switch($arr['variable_name']) {
|
||||
case 'character_set_database' : $db_character_set = $arr['value']; break;
|
||||
case 'collation_database' : $db_collation_type = $arr['value']; break;
|
||||
}
|
||||
// If we have all the required information break the loop.
|
||||
if($db_character_set != null && $db_collation_type != null) break;
|
||||
}
|
||||
return (stristr($db_character_set, 'utf8') && stristr($db_collation_type, 'utf8'));
|
||||
}
|
||||
|
||||
function get_db_charset($conn) {
|
||||
global $db_type;
|
||||
if($db_type == 'pgsql')
|
||||
return 'UTF8';
|
||||
$dbvarRS = &$conn->query("show variables like '%_database' ");
|
||||
$db_character_set = null;
|
||||
while(!$dbvarRS->EOF) {
|
||||
$arr = $dbvarRS->FetchRow();
|
||||
$arr = array_change_key_case($arr);
|
||||
if($arr['variable_name'] == 'character_set_database') {
|
||||
$db_character_set = $arr['value'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $db_character_set;
|
||||
}
|
||||
|
||||
//Make a count query
|
||||
function mkCountQuery($query)
|
||||
{
|
||||
// Remove all the \n, \r and white spaces to keep the space between the words consistent.
|
||||
// This is required for proper pattern matching for words like ' FROM ', 'ORDER BY', 'GROUP BY' as they depend on the spaces between the words.
|
||||
$query = preg_replace("/[\n\r\s]+/"," ",$query);
|
||||
|
||||
//Strip of the current SELECT fields and replace them by "select count(*) as count"
|
||||
// Space across FROM has to be retained here so that we do not have a clash with string "from" found in select clause
|
||||
$query = "SELECT count(*) AS count ".substr($query, stripos($query,' FROM '),strlen($query));
|
||||
|
||||
//Strip of any "GROUP BY" clause
|
||||
if(stripos($query,'GROUP BY') > 0)
|
||||
$query = substr($query, 0, stripos($query,'GROUP BY'));
|
||||
|
||||
//Strip of any "ORDER BY" clause
|
||||
if(stripos($query,'ORDER BY') > 0)
|
||||
$query = substr($query, 0, stripos($query,'ORDER BY'));
|
||||
|
||||
//That's it
|
||||
return( $query);
|
||||
}
|
||||
|
||||
//Added for PHP version less than 5
|
||||
if (!function_exists("stripos"))
|
||||
{
|
||||
function stripos($query,$needle)
|
||||
{
|
||||
return strpos(strtolower($query),strtolower($needle));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
/**
|
||||
* File created by SAKTI PRASAD MISHRA on 31 oct, 2007.
|
||||
* This file is included within "DetailView.tpl" to provide SESSION value to smarty template
|
||||
*/
|
||||
session_start();
|
||||
$aAllBlockStatus = $_SESSION['BLOCKINITIALSTATUS'];
|
||||
$this->assign("BLOCKINITIALSTATUS",$aAllBlockStatus);
|
||||
?>
|
|
@ -0,0 +1,114 @@
|
|||
<?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.
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* File containing methods to proceed with the ui validation for all the forms
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Get field validation information
|
||||
*/
|
||||
function getDBValidationData($tablearray, $tabid='') {
|
||||
if($tabid != '') {
|
||||
global $adb, $mod_strings;
|
||||
$fieldModuleName = getTabModuleName($tabid);
|
||||
$fieldres = $adb->pquery(
|
||||
"SELECT fieldlabel,fieldname,typeofdata FROM vtiger_field
|
||||
WHERE displaytype IN (1,3) AND presence in (0,2) AND tabid=?", Array($tabid));
|
||||
$fieldinfos = Array();
|
||||
while($fieldrow = $adb->fetch_array($fieldres)) {
|
||||
$fieldlabel = getTranslatedString($fieldrow['fieldlabel'], $fieldModuleName);
|
||||
$fieldname = $fieldrow['fieldname'];
|
||||
$typeofdata= $fieldrow['typeofdata'];
|
||||
$fieldinfos[$fieldname] = Array($fieldlabel => $typeofdata);
|
||||
}
|
||||
return $fieldinfos;
|
||||
} else {
|
||||
// TODO: Call the old API defined below in the file?
|
||||
return getDBValidationData_510($tablearray, $tabid);
|
||||
}
|
||||
}
|
||||
|
||||
/** Function to get the details for fieldlabels for a given table array
|
||||
* @param $tablearray -- tablearray:: Type string array (table names in array)
|
||||
* @param $tabid -- tabid:: Type integer
|
||||
* @returns $fieldName_array -- fieldName_array:: Type string array (field name details)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
function getDBValidationData_510($tablearray,$tabid='')
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering getDBValidationData(".$tablearray.",".$tabid.") method ...");
|
||||
$sql = '';
|
||||
$params = array();
|
||||
$tab_con = "";
|
||||
$numValues = count($tablearray);
|
||||
global $adb,$mod_strings;
|
||||
|
||||
if($tabid!='') $tab_con = ' and tabid='. $adb->sql_escape_string($tabid);
|
||||
|
||||
for($i=0;$i<$numValues;$i++)
|
||||
{
|
||||
|
||||
if(in_array("emails",$tablearray))
|
||||
{
|
||||
if($numValues > 1 && $i != $numValues-1)
|
||||
{
|
||||
$sql .= "select fieldlabel,fieldname,typeofdata from vtiger_field where tablename=? and tabid=10 and vtiger_field.presence in (0,2) and displaytype <> 2 union ";
|
||||
array_push($params, $tablearray[$i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql .= "select fieldlabel,fieldname,typeofdata from vtiger_field where tablename=? and tabid=10 and vtiger_field.presence in (0,2) and displaytype <> 2 ";
|
||||
array_push($params, $tablearray[$i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($numValues > 1 && $i != $numValues-1)
|
||||
{
|
||||
$sql .= "select fieldlabel,fieldname,typeofdata from vtiger_field where tablename=? $tab_con and displaytype in (1,3) and vtiger_field.presence in (0,2) union ";
|
||||
array_push($params, $tablearray[$i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql .= "select fieldlabel,fieldname,typeofdata from vtiger_field where tablename=? $tab_con and displaytype in (1,3) and vtiger_field.presence in (0,2)";
|
||||
array_push($params, $tablearray[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$result = $adb->pquery($sql, $params);
|
||||
$noofrows = $adb->num_rows($result);
|
||||
$fieldModuleName = empty($tabid)? false : getTabModuleName($tabid);
|
||||
$fieldName_array = Array();
|
||||
for($i=0;$i<$noofrows;$i++)
|
||||
{
|
||||
// Translate label with reference to module language string
|
||||
$fieldlabel = getTranslatedString($adb->query_result($result,$i,'fieldlabel'), $fieldModuleName);
|
||||
$fieldname = $adb->query_result($result,$i,'fieldname');
|
||||
$typeofdata = $adb->query_result($result,$i,'typeofdata');
|
||||
//echo '<br> '.$fieldlabel.'....'.$fieldname.'....'.$typeofdata;
|
||||
$fldLabel_array = Array();
|
||||
$fldLabel_array[$fieldlabel] = $typeofdata;
|
||||
$fieldName_array[$fieldname] = $fldLabel_array;
|
||||
|
||||
}
|
||||
|
||||
|
||||
$log->debug("Exiting getDBValidationData method ...");
|
||||
return $fieldName_array;
|
||||
|
||||
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,804 @@
|
|||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* Class for managing HTTP sessions
|
||||
*
|
||||
* Provides access to session-state values as well as session-level
|
||||
* settings and lifetime management methods.
|
||||
* Based on the standart PHP session handling mechanism
|
||||
* it provides for you more advanced features such as
|
||||
* database container, idle and expire timeouts, etc.
|
||||
*
|
||||
* PHP version 4
|
||||
*
|
||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
||||
* the PHP License and are unable to obtain it through the web, please
|
||||
* send a note to license@php.net so we can mail you a copy immediately.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version CVS: $Id: Session.php,v 1.15 2007/07/14 12:11:54 troehr Exp $
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since File available since Release 0.4.0
|
||||
*/
|
||||
|
||||
// @const HTTP_SESSION_STARTED - The session was started with the current request
|
||||
define("HTTP_SESSION_STARTED", 1);
|
||||
// @const HTTP_SESSION_STARTED - No new session was started with the current request
|
||||
define("HTTP_SESSION_CONTINUED", 2);
|
||||
|
||||
/**
|
||||
* Class for managing HTTP sessions
|
||||
*
|
||||
* Provides access to session-state values as well as session-level
|
||||
* settings and lifetime management methods.
|
||||
* Based on the standart PHP session handling mechanism
|
||||
* it provides for you more advanced features such as
|
||||
* database container, idle and expire timeouts, etc.
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* <code>
|
||||
* // Setting some options and detecting of a new session
|
||||
* HTTP_Session::setCookieless(false);
|
||||
* HTTP_Session::start('MySessionID');
|
||||
* HTTP_Session::set('variable', 'Tet string');
|
||||
* if (HTTP_Session::isNew()) {
|
||||
* echo('new session was created with the current request');
|
||||
* $visitors++; // Increase visitors count
|
||||
* }
|
||||
*
|
||||
* //HTTP_Session::regenerateId();
|
||||
* </code>
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* <code>
|
||||
* // Using database container
|
||||
* HTTP_Session::setContainer('DB');
|
||||
* HTTP_Session::start();
|
||||
* </code>
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* <code>
|
||||
* // Setting timeouts
|
||||
* HTTP_Session::start();
|
||||
* HTTP_Session::setExpire(time() + 60 * 60); // expires in one hour
|
||||
* HTTP_Session::setIdle(time()+ 10 * 60); // idles in ten minutes
|
||||
* if (HTTP_Session::isExpired()) {
|
||||
* // expired
|
||||
* echo('Your session is expired!');
|
||||
* HTTP_Session::destroy();
|
||||
* }
|
||||
* if (HTTP_Session::isIdle()) {
|
||||
* // idle
|
||||
* echo('You've been idle for too long!');
|
||||
* HTTP_Session::destroy();
|
||||
* }
|
||||
* HTTP_Session::updateIdle();
|
||||
* </code>
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since Class available since Release 0.4.0
|
||||
*/
|
||||
class HTTP_Session
|
||||
{
|
||||
/**
|
||||
* Sets user-defined session storage functions
|
||||
*
|
||||
* Sets the user-defined session storage functions which are used
|
||||
* for storing and retrieving data associated with a session.
|
||||
* This is most useful when a storage method other than
|
||||
* those supplied by PHP sessions is preferred.
|
||||
* i.e. Storing the session data in a local database.
|
||||
*
|
||||
* @param string $container Container name
|
||||
* @param array $container_options Container options
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
* @see session_set_save_handler()
|
||||
*/
|
||||
function setContainer($container, $container_options = null)
|
||||
{
|
||||
$container_class = 'HTTP_Session_Container_' . $container;
|
||||
$container_classfile = 'HTTP/Session/Container/' . $container . '.php';
|
||||
|
||||
include_once $container_classfile;
|
||||
$container = new $container_class($container_options);
|
||||
|
||||
$container->set();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes session data
|
||||
*
|
||||
* Creates a session (or resumes the current one
|
||||
* based on the session id being passed
|
||||
* via a GET variable or a cookie).
|
||||
* You can provide your own name and/or id for a session.
|
||||
*
|
||||
* @param string $name string Name of a session, default is 'SessionID'
|
||||
* @param string $id string Id of a session which will be used
|
||||
* only when the session is new
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
* @see session_name()
|
||||
* @see session_id()
|
||||
* @see session_start()
|
||||
*/
|
||||
function start($name = 'SessionID', $id = null)
|
||||
{
|
||||
HTTP_Session::name($name);
|
||||
if ($id) {
|
||||
HTTP_Session::id($id);
|
||||
} elseif (is_null(HTTP_Session::detectID())) {
|
||||
HTTP_Session::id($id ? $id : uniqid(dechex(rand())));
|
||||
}
|
||||
session_start();
|
||||
if (!isset($_SESSION['__HTTP_Session_Info'])) {
|
||||
$_SESSION['__HTTP_Session_Info'] = HTTP_SESSION_STARTED;
|
||||
} else {
|
||||
$_SESSION['__HTTP_Session_Info'] = HTTP_SESSION_CONTINUED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes session data and ends session
|
||||
*
|
||||
* Session data is usually stored after your script
|
||||
* terminated without the need to call HTTP_Session::stop(),
|
||||
* but as session data is locked to prevent concurrent
|
||||
* writes only one script may operate on a session at any time.
|
||||
* When using framesets together with sessions you will
|
||||
* experience the frames loading one by one due to this
|
||||
* locking. You can reduce the time needed to load all the
|
||||
* frames by ending the session as soon as all changes
|
||||
* to session variables are done.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
* @see session_write_close()
|
||||
*/
|
||||
function pause()
|
||||
{
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees all session variables and destroys all data
|
||||
* registered to a session
|
||||
*
|
||||
* This method resets the $_SESSION variable and
|
||||
* destroys all of the data associated
|
||||
* with the current session in its storage (file or DB).
|
||||
* It forces new session to be started after this method
|
||||
* is called. It does not unset the session cookie.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
* @see session_unset()
|
||||
* @see session_destroy()
|
||||
*/
|
||||
function destroy()
|
||||
{
|
||||
session_unset();
|
||||
session_destroy();
|
||||
|
||||
// set session handlers again to avoid fatal error in case
|
||||
// HTTP_Session::start() will be called afterwards
|
||||
if (isset($GLOBALS['HTTP_Session_Container']) &&
|
||||
is_a($GLOBALS['HTTP_Session_Container'], 'HTTP_Session_Container')) {
|
||||
$GLOBALS['HTTP_Session_Container']->set();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls session_regenerate_id() if available
|
||||
*
|
||||
* @param bool $deleteOldSessionData Whether to delete data of old session
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function regenerateId($deleteOldSessionData = false)
|
||||
{
|
||||
if (function_exists('session_regenerate_id')) {
|
||||
return session_regenerate_id($deleteOldSessionData);
|
||||
|
||||
// emulate session_regenerate_id()
|
||||
} else {
|
||||
|
||||
do {
|
||||
$newId = uniqid(dechex(rand()));
|
||||
} while ($newId === session_id());
|
||||
|
||||
if ($deleteOldSessionData) {
|
||||
session_unset();
|
||||
}
|
||||
|
||||
session_id($newId);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function copies session data of specified id to specified table
|
||||
*
|
||||
* @param string $targetTable Table to replicate data to
|
||||
* @param string $id ID of the session
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function replicate($targetTable, $id = null)
|
||||
{
|
||||
return $GLOBALS['HTTP_Session_Container']->replicate($targetTable, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all session variables
|
||||
*
|
||||
* @todo TODO Save expire and idle timestamps?
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function clear()
|
||||
{
|
||||
$info = $_SESSION['__HTTP_Session_Info'];
|
||||
session_unset();
|
||||
$_SESSION['__HTTP_Session_Info'] = $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find any session id in $_GET, $_POST or $_COOKIE
|
||||
*
|
||||
* @static
|
||||
* @access private
|
||||
* @return string Session ID (if exists) or null
|
||||
*/
|
||||
function detectID()
|
||||
{
|
||||
if (HTTP_Session::useCookies()) {
|
||||
if (isset($_COOKIE[HTTP_Session::name()])) {
|
||||
return $_COOKIE[HTTP_Session::name()];
|
||||
}
|
||||
} else {
|
||||
if (isset($_GET[HTTP_Session::name()])) {
|
||||
return $_GET[HTTP_Session::name()];
|
||||
}
|
||||
if (isset($_POST[HTTP_Session::name()])) {
|
||||
return $_POST[HTTP_Session::name()];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new name of a session
|
||||
*
|
||||
* @param string $name New name of a session
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return string Previous name of a session
|
||||
* @see session_name()
|
||||
*/
|
||||
function name($name = null)
|
||||
{
|
||||
return isset($name) ? session_name($name) : session_name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new ID of a session
|
||||
*
|
||||
* @param string $id New ID of a session
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return string Previous ID of a session
|
||||
* @see session_id()
|
||||
*/
|
||||
function id($id = null)
|
||||
{
|
||||
return isset($id) ? session_id($id) : session_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum expire time
|
||||
*
|
||||
* @param integer $time Time in seconds
|
||||
* @param bool $add Add time to current expire time or not
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setExpire($time, $add = false)
|
||||
{
|
||||
if ($add) {
|
||||
if (!isset($_SESSION['__HTTP_Session_Expire_TS'])) {
|
||||
$_SESSION['__HTTP_Session_Expire_TS'] = time() + $time;
|
||||
}
|
||||
|
||||
// update session.gc_maxlifetime
|
||||
$currentGcMaxLifetime = HTTP_Session::setGcMaxLifetime(null);
|
||||
HTTP_Session::setGcMaxLifetime($currentGcMaxLifetime + $time);
|
||||
|
||||
} elseif (!isset($_SESSION['__HTTP_Session_Expire_TS'])) {
|
||||
$_SESSION['__HTTP_Session_Expire_TS'] = $time;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum idle time
|
||||
*
|
||||
* Sets the time-out period allowed
|
||||
* between requests before the session-state
|
||||
* provider terminates the session.
|
||||
*
|
||||
* @param int $time Time in seconds
|
||||
* @param bool $add Add time to current maximum idle time or not
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setIdle($time, $add = false)
|
||||
{
|
||||
if ($add) {
|
||||
$_SESSION['__HTTP_Session_Idle'] = $time;
|
||||
} else {
|
||||
// substract time again because it doesn't make any sense to provide
|
||||
// the idle time as a timestamp
|
||||
// keep $add functionality to provide BC
|
||||
$_SESSION['__HTTP_Session_Idle'] = $time - time();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time up to the session is valid
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return integer Time when the session idles
|
||||
*/
|
||||
function sessionValidThru()
|
||||
{
|
||||
if (!isset($_SESSION['__HTTP_Session_Idle_TS']) ||
|
||||
!isset($_SESSION['__HTTP_Session_Idle'])) {
|
||||
return 0;
|
||||
} else {
|
||||
return $_SESSION['__HTTP_Session_Idle_TS'] +
|
||||
$_SESSION['__HTTP_Session_Idle'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if session is expired
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function isExpired()
|
||||
{
|
||||
if (isset($_SESSION['__HTTP_Session_Expire_TS']) &&
|
||||
$_SESSION['__HTTP_Session_Expire_TS'] < time()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if session is idle
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function isIdle()
|
||||
{
|
||||
if (isset($_SESSION['__HTTP_Session_Idle_TS']) &&
|
||||
(($_SESSION['__HTTP_Session_Idle_TS'] +
|
||||
$_SESSION['__HTTP_Session_Idle']) < time())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the idletime
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function updateIdle()
|
||||
{
|
||||
$_SESSION['__HTTP_Session_Idle_TS'] = time();
|
||||
}
|
||||
|
||||
/**
|
||||
* If optional parameter is specified it indicates
|
||||
* whether the module will use cookies to store
|
||||
* the session id on the client side
|
||||
*
|
||||
* It returns the previous value of this property
|
||||
*
|
||||
* @param bool $useCookies If specified it will replace the previous value
|
||||
* of this property
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
*
|
||||
* @return bool The previous value of the property
|
||||
*/
|
||||
function useCookies($useCookies = null)
|
||||
{
|
||||
$return = ini_get('session.use_cookies') ? true : false;
|
||||
if (isset($useCookies)) {
|
||||
ini_set('session.use_cookies', $useCookies ? 1 : 0);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the session
|
||||
* was created with the current request
|
||||
*
|
||||
* You MUST call this method only after you have started
|
||||
* the session with the HTTP_Session::start() method.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool True if the session was created
|
||||
* with the current request, false otherwise
|
||||
*/
|
||||
function isNew()
|
||||
{
|
||||
// The best way to check if a session is new is to check
|
||||
// for existence of a session data storage
|
||||
// with the current session id, but this is impossible
|
||||
// with the default PHP module wich is 'files'.
|
||||
// So we need to emulate it.
|
||||
return !isset($_SESSION['__HTTP_Session_Info']) ||
|
||||
$_SESSION['__HTTP_Session_Info'] == HTTP_SESSION_STARTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register variable with the current session
|
||||
*
|
||||
* @param string $name Name of a global variable
|
||||
*
|
||||
* @deprecated Use set()/setRef() instead
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
* @see session_register()
|
||||
*/
|
||||
function register($name)
|
||||
{
|
||||
return session_register($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a variable from the current session
|
||||
*
|
||||
* @param string $name Name of a global variable
|
||||
*
|
||||
* @deprecated Use get()/getRef() instead
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
* @see session_unregister()
|
||||
*/
|
||||
function unregister($name)
|
||||
{
|
||||
return session_unregister($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a session variable is registered
|
||||
*
|
||||
* @param string $name Variable name
|
||||
*
|
||||
* @deprecated Use is_set() instead
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function registered($name)
|
||||
{
|
||||
return session_is_registered($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns session variable
|
||||
*
|
||||
* @param string $name Name of a variable
|
||||
* @param mixed $default Default value of a variable if not set
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return mixed Value of a variable
|
||||
*/
|
||||
function get($name, $default = null)
|
||||
{
|
||||
if (!isset($_SESSION[$name]) && isset($default)) {
|
||||
$_SESSION[$name] = $default;
|
||||
}
|
||||
$return = (isset($_SESSION[$name])) ? $_SESSION[$name] : null;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns session variable by reference
|
||||
*
|
||||
* @param string $name Name of a variable
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return mixed Value of a variable
|
||||
*/
|
||||
function &getRef($name)
|
||||
{
|
||||
if (isset($_SESSION[$name])) {
|
||||
$return =& $_SESSION[$name];
|
||||
} else {
|
||||
$return = null;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets session variable
|
||||
*
|
||||
* @param string $name Name of a variable
|
||||
* @param mixed $value Value of a variable
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return mixed Old value of a variable
|
||||
*/
|
||||
function set($name, $value)
|
||||
{
|
||||
$return = (isset($_SESSION[$name])) ? $_SESSION[$name] : null;
|
||||
if (null === $value) {
|
||||
unset($_SESSION[$name]);
|
||||
} else {
|
||||
$_SESSION[$name] = $value;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets session variable by reference
|
||||
*
|
||||
* @param string $name Name of a variable
|
||||
* @param mixed $value Value of a variable
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return mixed Old value of a variable
|
||||
*/
|
||||
function setRef($name, &$value)
|
||||
{
|
||||
$return = (isset($_SESSION[$name])) ? $_SESSION[$name] : null;
|
||||
|
||||
$_SESSION[$name] =& $value;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a session variable is set
|
||||
*
|
||||
* @param string $name Variable name
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function is_set($name)
|
||||
{
|
||||
return isset($_SESSION[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns local variable of a script
|
||||
*
|
||||
* Two scripts can have local variables with the same names
|
||||
*
|
||||
* @param string $name Name of a variable
|
||||
* @param mixed $default Default value of a variable if not set
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return mixed Value of a local variable
|
||||
*/
|
||||
function &getLocal($name, $default = null)
|
||||
{
|
||||
$local = md5(HTTP_Session::localName());
|
||||
if (!isset($_SESSION[$local]) || !is_array($_SESSION[$local])) {
|
||||
$_SESSION[$local] = array();
|
||||
}
|
||||
if (!isset($_SESSION[$local][$name]) && isset($default)) {
|
||||
$_SESSION[$local][$name] = $default;
|
||||
}
|
||||
return $_SESSION[$local][$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets local variable of a script.
|
||||
* Two scripts can have local variables with the same names.
|
||||
*
|
||||
* @param string $name Name of a local variable
|
||||
* @param mixed $value Value of a local variable
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return mixed Old value of a local variable
|
||||
*/
|
||||
function setLocal($name, $value)
|
||||
{
|
||||
$local = md5(HTTP_Session::localName());
|
||||
if (!isset($_SESSION[$local]) || !is_array($_SESSION[$local])) {
|
||||
$_SESSION[$local] = array();
|
||||
}
|
||||
$return = (isset($_SESSION[$local][$name])) ? $_SESSION[$local][$name]
|
||||
: null;
|
||||
|
||||
if (null === $value) {
|
||||
unset($_SESSION[$local][$name]);
|
||||
} else {
|
||||
$_SESSION[$local][$name] = $value;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new local name
|
||||
*
|
||||
* @param string $name New local name
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return string Previous local name
|
||||
*/
|
||||
function localName($name = null)
|
||||
{
|
||||
$return = (isset($GLOBALS['__HTTP_Session_Localname'])) ? $GLOBALS['__HTTP_Session_Localname']
|
||||
: null;
|
||||
|
||||
if (!empty($name)) {
|
||||
$GLOBALS['__HTTP_Session_Localname'] = $name;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* @static
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function _init()
|
||||
{
|
||||
// Disable auto-start of a sesion
|
||||
ini_set('session.auto_start', 0);
|
||||
|
||||
// Set local name equal to the current script name
|
||||
HTTP_Session::localName($_SERVER['PHP_SELF']);
|
||||
}
|
||||
|
||||
/**
|
||||
* If optional parameter is specified it indicates
|
||||
* whether the session id will automatically be appended to
|
||||
* all links
|
||||
*
|
||||
* It returns the previous value of this property
|
||||
*
|
||||
* @param bool $useTransSID If specified it will replace the previous value
|
||||
* of this property
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool The previous value of the property
|
||||
*/
|
||||
function useTransSID($useTransSID = null)
|
||||
{
|
||||
$return = ini_get('session.use_trans_sid') ? true : false;
|
||||
if (isset($useTransSID)) {
|
||||
ini_set('session.use_trans_sid', $useTransSID ? 1 : 0);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If optional parameter is specified it determines the number of seconds
|
||||
* after which session data will be seen as 'garbage' and cleaned up
|
||||
*
|
||||
* It returns the previous value of this property
|
||||
*
|
||||
* @param bool $gcMaxLifetime If specified it will replace the previous value
|
||||
* of this property
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool The previous value of the property
|
||||
*/
|
||||
function setGcMaxLifetime($gcMaxLifetime = null)
|
||||
{
|
||||
$return = ini_get('session.gc_maxlifetime');
|
||||
if (isset($gcMaxLifetime) && is_int($gcMaxLifetime) && $gcMaxLifetime >= 1) {
|
||||
ini_set('session.gc_maxlifetime', $gcMaxLifetime);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If optional parameter is specified it determines the
|
||||
* probability that the gc (garbage collection) routine is started
|
||||
* and session data is cleaned up
|
||||
*
|
||||
* It returns the previous value of this property
|
||||
*
|
||||
* @param bool $gcProbability If specified it will replace the previous value
|
||||
* of this property
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool The previous value of the property
|
||||
*/
|
||||
function setGcProbability($gcProbability = null)
|
||||
{
|
||||
$return = ini_get('session.gc_probability');
|
||||
if (isset($gcProbability) &&
|
||||
is_int($gcProbability) &&
|
||||
$gcProbability >= 1 &&
|
||||
$gcProbability <= 100) {
|
||||
ini_set('session.gc_probability', $gcProbability);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
HTTP_Session::_init();
|
||||
?>
|
|
@ -0,0 +1,280 @@
|
|||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* Container class for storing session data
|
||||
*
|
||||
* PHP version 4
|
||||
*
|
||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
||||
* the PHP License and are unable to obtain it through the web, please
|
||||
* send a note to license@php.net so we can mail you a copy immediately.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author Alexander Radivanovich <info@wwwlab.net>
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version CVS: $Id: Container.php,v 1.8 2007/07/14 12:11:54 troehr Exp $
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since File available since Release 0.4.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Container class for storing session data
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since Class available since Release 0.4.0
|
||||
*/
|
||||
class HTTP_Session_Container
|
||||
{
|
||||
/**
|
||||
* Additional options for the container object
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $options = array();
|
||||
|
||||
/**
|
||||
* Constrtuctor method
|
||||
*
|
||||
* @param array $options Additional options for the container object
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
function HTTP_Session_Container($options = null)
|
||||
{
|
||||
$this->_setDefaults();
|
||||
if (is_array($options)) {
|
||||
$this->_parseOptions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some default options
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function _setDefaults()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse options passed to the container class
|
||||
*
|
||||
* @param array $options Options
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function _parseOptions($options)
|
||||
{
|
||||
foreach ($options as $option => $value) {
|
||||
if (in_array($option, array_keys($this->options))) {
|
||||
$this->options[$option] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by the session handler to initialize things
|
||||
*
|
||||
* @param string $save_path Save path
|
||||
* @param string $session_name Session name
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function open($save_path, $session_name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the page is finished
|
||||
* executing and the session handler needs to close things off
|
||||
*
|
||||
* Has to be overwritten by each container class
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by the session handler
|
||||
* to read the data associated with a given session ID.
|
||||
* This function must retrieve and return the session data
|
||||
* for the session identified by $id.
|
||||
*
|
||||
* Has to be overwritten by each container class
|
||||
*
|
||||
* @param string $id ID of the session
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the session handler
|
||||
* has session data to save, which usually happens
|
||||
* at the end of your script
|
||||
*
|
||||
* Has to be overwritten by each container class
|
||||
*
|
||||
* @param string $id ID of the session
|
||||
* @param mixed $data The data associated with a given session ID
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function write($id, $data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when a session is destroyed.
|
||||
* It is responsible for deleting the session and cleaning things up.
|
||||
*
|
||||
* Has to be overwritten by each container class
|
||||
*
|
||||
* @param string $id ID of the session
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function destroy($id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function copies session data of specified id to specified table
|
||||
*
|
||||
* Has to be overwritten by each container class
|
||||
*
|
||||
* @param string $targetTable Table to replicate data to
|
||||
* @param string $id ID of the session
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function replicate($targetTable, $id = null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is responsible for garbage collection.
|
||||
* In the case of session handling, it is responsible
|
||||
* for deleting old, stale sessions that are hanging around.
|
||||
* The session handler will call this every now and then.
|
||||
*
|
||||
* Has to be overwritten by each container class
|
||||
*
|
||||
* @param integer $maxlifetime Maximum lifetime
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set session save handler
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function set()
|
||||
{
|
||||
$GLOBALS['HTTP_Session_Container'] =& $this;
|
||||
session_module_name('user');
|
||||
session_set_save_handler('HTTP_Session_Open',
|
||||
'HTTP_Session_Close',
|
||||
'HTTP_Session_Read',
|
||||
'HTTP_Session_Write',
|
||||
'HTTP_Session_Destroy',
|
||||
'HTTP_Session_GC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor for compatibility with PHP >= 5.0.5
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function __destruct()
|
||||
{
|
||||
$GLOBALS['HTTP_Session_Container'] =& $this;
|
||||
session_write_close();
|
||||
}
|
||||
}
|
||||
|
||||
// Delegate function calls to the object's methods
|
||||
/** @ignore */
|
||||
function HTTP_Session_Open($save_path, $session_name)
|
||||
{
|
||||
return (isset($GLOBALS['HTTP_Session_Container'])) ? $GLOBALS['HTTP_Session_Container']->open($save_path, $session_name)
|
||||
: false;
|
||||
}
|
||||
/** @ignore */
|
||||
function HTTP_Session_Close()
|
||||
{
|
||||
return (isset($GLOBALS['HTTP_Session_Container'])) ? $GLOBALS['HTTP_Session_Container']->close()
|
||||
: false;
|
||||
}
|
||||
/** @ignore */
|
||||
function HTTP_Session_Read($id)
|
||||
{
|
||||
return (isset($GLOBALS['HTTP_Session_Container'])) ? $GLOBALS['HTTP_Session_Container']->read($id)
|
||||
: false;
|
||||
}
|
||||
/** @ignore */
|
||||
function HTTP_Session_Write($id, $data)
|
||||
{
|
||||
return (isset($GLOBALS['HTTP_Session_Container'])) ? $GLOBALS['HTTP_Session_Container']->write($id, $data)
|
||||
: false;
|
||||
}
|
||||
/** @ignore */
|
||||
function HTTP_Session_Destroy($id)
|
||||
{
|
||||
return (isset($GLOBALS['HTTP_Session_Container'])) ? $GLOBALS['HTTP_Session_Container']->destroy($id)
|
||||
: false;
|
||||
}
|
||||
/** @ignore */
|
||||
function HTTP_Session_GC($maxlifetime)
|
||||
{
|
||||
return (isset($GLOBALS['HTTP_Session_Container'])) ? $GLOBALS['HTTP_Session_Container']->gc($maxlifetime)
|
||||
: false;
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,364 @@
|
|||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* PEAR::DB database container
|
||||
*
|
||||
* PHP version 4
|
||||
*
|
||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
||||
* the PHP License and are unable to obtain it through the web, please
|
||||
* send a note to license@php.net so we can mail you a copy immediately.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author Alexander Radivanovich <info@wwwlab.net>
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version CVS: $Id: DB.php,v 1.7 2007/07/14 12:11:54 troehr Exp $
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since File available since Release 0.4.0
|
||||
*/
|
||||
|
||||
require_once 'HTTP/Session/Container.php';
|
||||
require_once 'DB.php';
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* Create the following table to store session data
|
||||
* <code>
|
||||
* CREATE TABLE `sessiondata` (
|
||||
* `id` CHAR(32) NOT NULL,
|
||||
* `expiry` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
* `data` TEXT NOT NULL,
|
||||
* PRIMARY KEY (`id`)
|
||||
* );
|
||||
* </code>
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since Class available since Release 0.4.0
|
||||
*/
|
||||
class HTTP_Session_Container_DB extends HTTP_Session_Container
|
||||
{
|
||||
/**
|
||||
* DB connection object
|
||||
*
|
||||
* @var object DB
|
||||
* @access private
|
||||
*/
|
||||
var $db = null;
|
||||
|
||||
/**
|
||||
* Session data cache id
|
||||
*
|
||||
* @var mixed
|
||||
* @access private
|
||||
*/
|
||||
var $crc = false;
|
||||
|
||||
/**
|
||||
* Constrtuctor method
|
||||
*
|
||||
* $options is an array with the options.<br>
|
||||
* The options are:
|
||||
* <ul>
|
||||
* <li>'dsn' - The DSN string</li>
|
||||
* <li>'table' - Table with session data, default is 'sessiondata'</li>
|
||||
* <li>'autooptimize' - Boolean, 'true' to optimize
|
||||
* the table on garbage collection, default is 'false'.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param array $options Options
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
function HTTP_Session_Container_DB($options)
|
||||
{
|
||||
$this->_setDefaults();
|
||||
if (is_array($options)) {
|
||||
$this->_parseOptions($options);
|
||||
} else {
|
||||
$this->options['dsn'] = $options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to database by using the given DSN string
|
||||
*
|
||||
* @param string $dsn DSN string
|
||||
*
|
||||
* @access private
|
||||
* @return mixed Object on error, otherwise bool
|
||||
*/
|
||||
function _connect($dsn)
|
||||
{
|
||||
if (is_string($dsn) || is_array($dsn)) {
|
||||
$this->db = DB::connect($dsn);
|
||||
} else if (is_object($dsn) && is_a($dsn, "db_common")) {
|
||||
$this->db = $dsn;
|
||||
} else if (is_object($dsn) && DB::isError($dsn)) {
|
||||
return new DB_Error($dsn->code, PEAR_ERROR_DIE);
|
||||
} else {
|
||||
return new PEAR_Error("The given dsn was not valid in file " . __FILE__
|
||||
. " at line " . __LINE__,
|
||||
41,
|
||||
PEAR_ERROR_RETURN,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if (DB::isError($this->db)) {
|
||||
return new DB_Error($this->db->code, PEAR_ERROR_DIE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some default options
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function _setDefaults()
|
||||
{
|
||||
$this->options['dsn'] = null;
|
||||
$this->options['table'] = 'sessiondata';
|
||||
$this->options['autooptimize'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection to a database
|
||||
*
|
||||
* @param string $save_path Save path
|
||||
* @param string $session_name Session name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function open($save_path, $session_name)
|
||||
{
|
||||
if (DB::isError($this->_connect($this->options['dsn']))) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
$query = sprintf("SELECT data FROM %s WHERE id = %s AND expiry >= %d",
|
||||
$this->options['table'],
|
||||
$this->db->quoteSmart(md5($id)),
|
||||
time());
|
||||
$result = $this->db->getOne($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
$this->crc = strlen($result) . crc32($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
* @param mixed $data Data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function write($id, $data)
|
||||
{
|
||||
if ((false !== $this->crc) &&
|
||||
($this->crc === strlen($data) . crc32($data))) {
|
||||
// $_SESSION hasn't been touched, no need to update the blob column
|
||||
$query = sprintf("UPDATE %s SET expiry = %d WHERE id = %s",
|
||||
$this->options['table'],
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->quoteSmart(md5($id)));
|
||||
} else {
|
||||
// Check if table row already exists
|
||||
$query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
$this->db->quoteSmart(md5($id)));
|
||||
$result = $this->db->getOne($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
if (0 == intval($result)) {
|
||||
// Insert new row into table
|
||||
$query = sprintf("INSERT INTO %s (id, expiry, data) VALUES (%s, %d, %s)",
|
||||
$this->options['table'],
|
||||
$this->db->quoteSmart(md5($id)),
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->quoteSmart($data));
|
||||
} else {
|
||||
// Update existing row
|
||||
$query = sprintf("UPDATE %s SET expiry = %d, data = %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->quoteSmart($data),
|
||||
$this->db->quoteSmart(md5($id)));
|
||||
}
|
||||
}
|
||||
$result = $this->db->query($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function destroy($id)
|
||||
{
|
||||
$query = sprintf("DELETE FROM %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
$this->db->quoteSmart(md5($id)));
|
||||
$result = $this->db->query($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replicate session data to table specified in option 'replicateBeforeDestroy'
|
||||
*
|
||||
* @param string $targetTable Table to replicate to
|
||||
* @param string $id Id of record to replicate
|
||||
*
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
function replicate($targetTable, $id = null)
|
||||
{
|
||||
if (is_null($id)) {
|
||||
$id = HTTP_Session::id();
|
||||
}
|
||||
|
||||
// Check if table row already exists
|
||||
$query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
|
||||
$targetTable,
|
||||
$this->db->quoteSmart(md5($id)));
|
||||
$result = $this->db->getOne($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert new row into dest table
|
||||
if (0 == intval($result)) {
|
||||
$query = sprintf("INSERT INTO %s SELECT * FROM %s WHERE id = %s",
|
||||
$targetTable,
|
||||
$this->options['table'],
|
||||
$this->db->quoteSmart(md5($id)));
|
||||
|
||||
} else {
|
||||
// Update existing row
|
||||
$query = sprintf("UPDATE %s dst, %s src SET dst.expiry = src.expiry, dst.data = src.data WHERE dst.id = src.id AND src.id = %s",
|
||||
$targetTable,
|
||||
$this->options['table'],
|
||||
$this->db->quoteSmart(md5($id)));
|
||||
}
|
||||
|
||||
$result = $this->db->query($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection
|
||||
*
|
||||
* @param int $maxlifetime Maximum lifetime
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function gc($maxlifetime)
|
||||
{
|
||||
$query = sprintf("DELETE FROM %s WHERE expiry < %d",
|
||||
$this->options['table'],
|
||||
time());
|
||||
$result = $this->db->query($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
if ($this->options['autooptimize']) {
|
||||
switch($this->db->phptype) {
|
||||
case 'mysql':
|
||||
$query = sprintf("OPTIMIZE TABLE %s", $this->options['table']);
|
||||
break;
|
||||
case 'pgsql':
|
||||
$query = sprintf("VACUUM %s", $this->options['table']);
|
||||
break;
|
||||
default:
|
||||
$query = null;
|
||||
break;
|
||||
}
|
||||
if (isset($query)) {
|
||||
$result = $this->db->query($query);
|
||||
if (DB::isError($result)) {
|
||||
new DB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,364 @@
|
|||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* PEAR::MDB database container
|
||||
*
|
||||
* PHP version 4
|
||||
*
|
||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
||||
* the PHP License and are unable to obtain it through the web, please
|
||||
* send a note to license@php.net so we can mail you a copy immediately.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author Alexander Radivanovich <info@wwwlab.net>
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version CVS: $Id: MDB.php,v 1.5 2007/07/14 12:11:55 troehr Exp $
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since File available since Release 0.5.0
|
||||
*/
|
||||
|
||||
require_once 'HTTP/Session/Container.php';
|
||||
require_once 'MDB.php';
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* Create the following table to store session data
|
||||
* <code>
|
||||
* CREATE TABLE `sessiondata` (
|
||||
* `id` CHAR(32) NOT NULL,
|
||||
* `expiry` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
* `data` TEXT NOT NULL,
|
||||
* PRIMARY KEY (`id`)
|
||||
* );
|
||||
* </code>
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since Class available since Release 0.4.0
|
||||
*/
|
||||
class HTTP_Session_Container_MDB extends HTTP_Session_Container
|
||||
{
|
||||
|
||||
/**
|
||||
* MDB connection object
|
||||
*
|
||||
* @var object MDB
|
||||
* @access private
|
||||
*/
|
||||
var $db = null;
|
||||
|
||||
/**
|
||||
* Session data cache id
|
||||
*
|
||||
* @var mixed
|
||||
* @access private
|
||||
*/
|
||||
var $crc = false;
|
||||
|
||||
/**
|
||||
* Constructor method
|
||||
*
|
||||
* $options is an array with the options.<br>
|
||||
* The options are:
|
||||
* <ul>
|
||||
* <li>'dsn' - The DSN string</li>
|
||||
* <li>'table' - Table with session data, default is 'sessiondata'</li>
|
||||
* <li>'autooptimize' - Boolean, 'true' to optimize
|
||||
* the table on garbage collection, default is 'false'.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param array $options Options
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
function HTTP_Session_Container_MDB($options)
|
||||
{
|
||||
$this->_setDefaults();
|
||||
if (is_array($options)) {
|
||||
$this->_parseOptions($options);
|
||||
} else {
|
||||
$this->options['dsn'] = $options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to database by using the given DSN string
|
||||
*
|
||||
* @param string $dsn DSN string
|
||||
*
|
||||
* @access private
|
||||
* @return mixed Object on error, otherwise bool
|
||||
*/
|
||||
function _connect($dsn)
|
||||
{
|
||||
if (is_string($dsn) || is_array($dsn)) {
|
||||
$this->db = MDB::connect($dsn);
|
||||
} else if (is_object($dsn) && is_a($dsn, 'mdb_common')) {
|
||||
$this->db = $dsn;
|
||||
} else if (is_object($dsn) && MDB::isError($dsn)) {
|
||||
return new MDB_Error($dsn->code, PEAR_ERROR_DIE);
|
||||
} else {
|
||||
return new PEAR_Error("The given dsn was not valid in file " . __FILE__
|
||||
. " at line " . __LINE__,
|
||||
41,
|
||||
PEAR_ERROR_RETURN,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if (MDB::isError($this->db)) {
|
||||
return new MDB_Error($this->db->code, PEAR_ERROR_DIE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some default options
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function _setDefaults()
|
||||
{
|
||||
$this->options['dsn'] = null;
|
||||
$this->options['table'] = 'sessiondata';
|
||||
$this->options['autooptimize'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection to a database
|
||||
*
|
||||
* @param string $save_path Save path
|
||||
* @param string $session_name Session name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function open($save_path, $session_name)
|
||||
{
|
||||
if (MDB::isError($this->_connect($this->options['dsn']))) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
$query = sprintf("SELECT data FROM %s WHERE id = %s AND expiry >= %d",
|
||||
$this->options['table'],
|
||||
$this->db->getTextValue(md5($id)),
|
||||
time());
|
||||
$result = $this->db->getOne($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
$this->crc = strlen($result) . crc32($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
* @param mixed $data Data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function write($id, $data)
|
||||
{
|
||||
if ((false !== $this->crc) &&
|
||||
($this->crc === strlen($data) . crc32($data))) {
|
||||
// $_SESSION hasn't been touched, no need to update the blob column
|
||||
$query = sprintf("UPDATE %s SET expiry = %d WHERE id = %s",
|
||||
$this->options['table'],
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->getTextValue(md5($id)));
|
||||
} else {
|
||||
// Check if table row already exists
|
||||
$query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
$this->db->getTextValue(md5($id)));
|
||||
$result = $this->db->getOne($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
if (0 == intval($result)) {
|
||||
// Insert new row into table
|
||||
$query = sprintf("INSERT INTO %s (id, expiry, data) VALUES (%s, %d, %s)",
|
||||
$this->options['table'],
|
||||
$this->db->getTextValue(md5($id)),
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->getTextValue($data));
|
||||
} else {
|
||||
// Update existing row
|
||||
$query = sprintf("UPDATE %s SET expiry = %d, data = %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->getTextValue($data),
|
||||
$this->db->getTextValue(md5($id)));
|
||||
}
|
||||
}
|
||||
$result = $this->db->query($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function destroy($id)
|
||||
{
|
||||
$query = sprintf("DELETE FROM %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
$this->db->getTextValue(md5($id)));
|
||||
$result = $this->db->query($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replicate session data to table specified in option 'replicateBeforeDestroy'
|
||||
*
|
||||
* @param string $targetTable Table to replicate to
|
||||
* @param string $id Id of record to replicate
|
||||
*
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
function replicate($targetTable, $id = null)
|
||||
{
|
||||
if (is_null($id)) {
|
||||
$id = HTTP_Session::id();
|
||||
}
|
||||
|
||||
// Check if table row already exists
|
||||
$query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
|
||||
$targetTable,
|
||||
$this->db->getTextValue(md5($id)));
|
||||
$result = $this->db->getOne($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert new row into dest table
|
||||
if (0 == intval($result)) {
|
||||
$query = sprintf("INSERT INTO %s SELECT * FROM %s WHERE id = %s",
|
||||
$targetTable,
|
||||
$this->options['table'],
|
||||
$this->db->getTextValue(md5($id)));
|
||||
} else {
|
||||
// Update existing row
|
||||
$query = sprintf("UPDATE %s dst, %s src SET dst.expiry = src.expiry, dst.data = src.data WHERE dst.id = src.id AND src.id = %s",
|
||||
$targetTable,
|
||||
$this->options['table'],
|
||||
$this->db->getTextValue(md5($id)));
|
||||
}
|
||||
|
||||
$result = $this->db->query($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection
|
||||
*
|
||||
* @param int $maxlifetime Maximum lifetime
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function gc($maxlifetime)
|
||||
{
|
||||
$query = sprintf("DELETE FROM %s WHERE expiry < %d",
|
||||
$this->options['table'],
|
||||
time());
|
||||
$result = $this->db->query($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
if ($this->options['autooptimize']) {
|
||||
switch($this->db->phptype) {
|
||||
case 'mysql':
|
||||
$query = sprintf("OPTIMIZE TABLE %s", $this->options['table']);
|
||||
break;
|
||||
case 'pgsql':
|
||||
$query = sprintf("VACUUM %s", $this->options['table']);
|
||||
break;
|
||||
default:
|
||||
$query = null;
|
||||
break;
|
||||
}
|
||||
if (isset($query)) {
|
||||
$result = $this->db->query($query);
|
||||
if (MDB::isError($result)) {
|
||||
new MDB_Error($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,364 @@
|
|||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* PEAR::MDB2 database container
|
||||
*
|
||||
* PHP version 4
|
||||
*
|
||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
||||
* the PHP License and are unable to obtain it through the web, please
|
||||
* send a note to license@php.net so we can mail you a copy immediately.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author Alexander Radivanovich <info@wwwlab.net>
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version CVS: $Id: MDB2.php,v 1.5 2007/07/14 12:11:55 troehr Exp $
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since File available since Release 0.5.0
|
||||
*/
|
||||
|
||||
require_once 'HTTP/Session/Container.php';
|
||||
require_once 'MDB2.php';
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* Create the following table to store session data
|
||||
* <code>
|
||||
* CREATE TABLE `sessiondata` (
|
||||
* `id` CHAR(32) NOT NULL,
|
||||
* `expiry` INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
* `data` TEXT NOT NULL,
|
||||
* PRIMARY KEY (`id`)
|
||||
* );
|
||||
* </code>
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author David Costa <gurugeek@php.net>
|
||||
* @author Michael Metz <pear.metz@speedpartner.de>
|
||||
* @author Stefan Neufeind <pear.neufeind@speedpartner.de>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2005 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since Class available since Release 0.5.0
|
||||
*/
|
||||
class HTTP_Session_Container_MDB2 extends HTTP_Session_Container
|
||||
{
|
||||
/**
|
||||
* MDB2 connection object
|
||||
*
|
||||
* @var object MDB2
|
||||
* @access private
|
||||
*/
|
||||
var $db = null;
|
||||
|
||||
/**
|
||||
* Session data cache id
|
||||
*
|
||||
* @var mixed
|
||||
* @access private
|
||||
*/
|
||||
var $crc = false;
|
||||
|
||||
/**
|
||||
* Constructor method
|
||||
*
|
||||
* $options is an array with the options.<br>
|
||||
* The options are:
|
||||
* <ul>
|
||||
* <li>'dsn' - The DSN string</li>
|
||||
* <li>'table' - Table with session data, default is 'sessiondata'</li>
|
||||
* <li>'autooptimize' - Boolean, 'true' to optimize
|
||||
* the table on garbage collection, default is 'false'.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param array $options Options
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function HTTP_Session_Container_MDB2($options)
|
||||
{
|
||||
$this->_setDefaults();
|
||||
if (is_array($options)) {
|
||||
$this->_parseOptions($options);
|
||||
} else {
|
||||
$this->options['dsn'] = $options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to database by using the given DSN string
|
||||
*
|
||||
* @param string $dsn DSN string
|
||||
*
|
||||
* @access private
|
||||
* @return mixed Object on error, otherwise bool
|
||||
*/
|
||||
function _connect($dsn)
|
||||
{
|
||||
if (is_string($dsn) || is_array($dsn)) {
|
||||
$this->db = MDB2::connect($dsn);
|
||||
} else if (is_object($dsn) && is_a($dsn, 'MDB2_Driver_Common')) {
|
||||
$this->db = $dsn;
|
||||
} else if (is_object($dsn) && MDB2::isError($dsn)) {
|
||||
return $dsn;
|
||||
} else {
|
||||
return new PEAR_Error("The given dsn was not valid in file " . __FILE__
|
||||
. " at line " . __LINE__,
|
||||
41,
|
||||
PEAR_ERROR_RETURN,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if (MDB2::isError($this->db)) {
|
||||
return new MDB2_Error($this->db->code, PEAR_ERROR_DIE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some default options
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function _setDefaults()
|
||||
{
|
||||
$this->options['dsn'] = null;
|
||||
$this->options['table'] = 'sessiondata';
|
||||
$this->options['autooptimize'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection to a database
|
||||
*
|
||||
* @param string $save_path Save path
|
||||
* @param string $session_name Session name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function open($save_path, $session_name)
|
||||
{
|
||||
if (MDB2::isError($this->_connect($this->options['dsn']))) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
$query = sprintf("SELECT data FROM %s WHERE id = %s AND expiry >= %d",
|
||||
$this->options['table'],
|
||||
$this->db->quote(md5($id), 'text'),
|
||||
time());
|
||||
$result = $this->db->queryOne($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
$this->crc = strlen($result) . crc32($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
* @param mixed $data Data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function write($id, $data)
|
||||
{
|
||||
if ((false !== $this->crc) &&
|
||||
($this->crc === strlen($data) . crc32($data))) {
|
||||
// $_SESSION hasn't been touched, no need to update the blob column
|
||||
$query = sprintf("UPDATE %s SET expiry = %d WHERE id = %s",
|
||||
$this->options['table'],
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->quote(md5($id), 'text'));
|
||||
} else {
|
||||
// Check if table row already exists
|
||||
$query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
$this->db->quote(md5($id), 'text'));
|
||||
$result = $this->db->queryOne($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
if (0 == intval($result)) {
|
||||
// Insert new row into table
|
||||
$query = sprintf("INSERT INTO %s (id, expiry, data) VALUES (%s, %d, %s)",
|
||||
$this->options['table'],
|
||||
$this->db->quote(md5($id), 'text'),
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->quote($data, 'text'));
|
||||
} else {
|
||||
// Update existing row
|
||||
$query = sprintf("UPDATE %s SET expiry = %d, data = %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
time() + ini_get('session.gc_maxlifetime'),
|
||||
$this->db->quote($data, 'text'),
|
||||
$this->db->quote(md5($id), 'text'));
|
||||
}
|
||||
}
|
||||
$result = $this->db->query($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function destroy($id)
|
||||
{
|
||||
$query = sprintf("DELETE FROM %s WHERE id = %s",
|
||||
$this->options['table'],
|
||||
$this->db->quote(md5($id), 'text'));
|
||||
$result = $this->db->query($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replicate session data to table specified in option 'replicateBeforeDestroy'
|
||||
*
|
||||
* @param string $targetTable Table to replicate to
|
||||
* @param string $id Id of record to replicate
|
||||
*
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
function replicate($targetTable, $id = null)
|
||||
{
|
||||
if (is_null($id)) {
|
||||
$id = HTTP_Session::id();
|
||||
}
|
||||
|
||||
// Check if table row already exists
|
||||
$query = sprintf("SELECT COUNT(id) FROM %s WHERE id = %s",
|
||||
$targetTable,
|
||||
$this->db->quote(md5($id), 'text'));
|
||||
$result = $this->db->queryOne($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert new row into dest table
|
||||
if (0 == intval($result)) {
|
||||
$query = sprintf("INSERT INTO %s SELECT * FROM %s WHERE id = %s",
|
||||
$targetTable,
|
||||
$this->options['table'],
|
||||
$this->db->quote(md5($id), 'text'));
|
||||
|
||||
} else {
|
||||
// Update existing row
|
||||
$query = sprintf("UPDATE %s dst, %s src SET dst.expiry = src.expiry, dst.data = src.data WHERE dst.id = src.id AND src.id = %s",
|
||||
$targetTable,
|
||||
$this->options['table'],
|
||||
$this->db->quote(md5($id), 'text'));
|
||||
}
|
||||
|
||||
$result = $this->db->query($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection
|
||||
*
|
||||
* @param int $maxlifetime Maximum lifetime
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function gc($maxlifetime)
|
||||
{
|
||||
$query = sprintf("DELETE FROM %s WHERE expiry < %d",
|
||||
$this->options['table'],
|
||||
time());
|
||||
$result = $this->db->query($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
if ($this->options['autooptimize']) {
|
||||
switch($this->db->phptype) {
|
||||
case 'mysql':
|
||||
$query = sprintf("OPTIMIZE TABLE %s", $this->options['table']);
|
||||
break;
|
||||
case 'pgsql':
|
||||
$query = sprintf("VACUUM %s", $this->options['table']);
|
||||
break;
|
||||
default:
|
||||
$query = null;
|
||||
break;
|
||||
}
|
||||
if (isset($query)) {
|
||||
$result = $this->db->query($query);
|
||||
if (MDB2::isError($result)) {
|
||||
$this->db->raiseError($result->code, PEAR_ERROR_DIE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,202 @@
|
|||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* Memcache database container
|
||||
*
|
||||
* PHP version 4
|
||||
*
|
||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
||||
* the PHP License and are unable to obtain it through the web, please
|
||||
* send a note to license@php.net so we can mail you a copy immediately.
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author Chad Wagner <chad.wagner@gmail.com>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2007 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version CVS: $Id: Memcache.php,v 1.3 2007/07/14 12:11:55 troehr Exp $
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since File available since Release 0.5.6
|
||||
*/
|
||||
|
||||
require_once 'HTTP/Session/Container.php';
|
||||
|
||||
/**
|
||||
* Database container for session data
|
||||
*
|
||||
* @category HTTP
|
||||
* @package HTTP_Session
|
||||
* @author Chad Wagner <chad.wagner@gmail.com>
|
||||
* @author Torsten Roehr <torsten.roehr@gmx.de>
|
||||
* @copyright 1997-2007 The PHP Group
|
||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
||||
* @version Release: @package_version@
|
||||
* @link http://pear.php.net/package/HTTP_Session
|
||||
* @since Class available since Release 0.5.6
|
||||
*/
|
||||
class HTTP_Session_Container_Memcache extends HTTP_Session_Container
|
||||
{
|
||||
/**
|
||||
* Memcache connection object
|
||||
*
|
||||
* @var object Memcache
|
||||
* @access private
|
||||
*/
|
||||
var $mc;
|
||||
|
||||
/**
|
||||
* Constructor method
|
||||
*
|
||||
* $options is an array with the options.<br>
|
||||
* The options are:
|
||||
* <ul>
|
||||
* <li>'memcache' - Memcache object
|
||||
* <li>'prefix' - Key prefix, default is 'sessiondata:'</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param array $options Options
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
function HTTP_Session_Container_Memcache($options)
|
||||
{
|
||||
$this->_setDefaults();
|
||||
|
||||
if (is_array($options)) {
|
||||
$this->_parseOptions($options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to database by using the given DSN string
|
||||
*
|
||||
* @param string $mc Memcache object
|
||||
*
|
||||
* @access private
|
||||
* @return mixed Object on error, otherwise bool
|
||||
*/
|
||||
function _connect($mc)
|
||||
{
|
||||
if (is_object($mc) && is_a($mc, 'Memcache')) {
|
||||
$this->mc = $mc;
|
||||
|
||||
} else {
|
||||
|
||||
return new PEAR_Error('The given memcache object was not valid in file '
|
||||
. __FILE__ . ' at line ' . __LINE__,
|
||||
41,
|
||||
PEAR_ERROR_RETURN,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some default options
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
function _setDefaults()
|
||||
{
|
||||
$this->options['prefix'] = 'sessiondata:';
|
||||
$this->options['memcache'] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection to a database
|
||||
*
|
||||
* @param string $save_path Save path
|
||||
* @param string $session_name Session name
|
||||
*
|
||||
* @access public
|
||||
* @return mixed Object on error, otherwise bool
|
||||
*/
|
||||
function open($save_path, $session_name)
|
||||
{
|
||||
return $this->_connect($this->options['memcache']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
function read($id)
|
||||
{
|
||||
$result = $this->mc->get($this->options['prefix'] . $id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
* @param mixed $data Session data
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function write($id, $data)
|
||||
{
|
||||
$this->mc->set($this->options['prefix'] . $id,
|
||||
$data,
|
||||
MEMCACHE_COMPRESSED,
|
||||
time() + ini_get('session.gc_maxlifetime'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy session data
|
||||
*
|
||||
* @param string $id Session id
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function destroy($id)
|
||||
{
|
||||
$this->mc->delete($this->options['prefix'] . $id);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection
|
||||
*
|
||||
* @param int $maxlifetime Maximum lifetime
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function gc($maxlifetime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,16 @@
|
|||
<?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 handleInventoryProductRel($entity){
|
||||
require_once("include/utils/InventoryUtils.php");
|
||||
updateInventoryProductRel($entity);
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,417 @@
|
|||
<?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 'vtlib/Vtiger/PDF/models/Model.php';
|
||||
include_once 'vtlib/Vtiger/PDF/inventory/HeaderViewer.php';
|
||||
include_once 'vtlib/Vtiger/PDF/inventory/FooterViewer.php';
|
||||
include_once 'vtlib/Vtiger/PDF/inventory/ContentViewer.php';
|
||||
include_once 'vtlib/Vtiger/PDF/inventory/ContentViewer2.php';
|
||||
include_once 'vtlib/Vtiger/PDF/viewers/PagerViewer.php';
|
||||
include_once 'vtlib/Vtiger/PDF/PDFGenerator.php';
|
||||
include_once 'data/CRMEntity.php';
|
||||
|
||||
class Vtiger_InventoryPDFController {
|
||||
|
||||
protected $module;
|
||||
protected $focus = null;
|
||||
|
||||
function __construct($module) {
|
||||
$this->moduleName = $module;
|
||||
}
|
||||
|
||||
function loadRecord($id) {
|
||||
global $current_user;
|
||||
$this->focus = $focus = CRMEntity::getInstance($this->moduleName);
|
||||
$focus->retrieve_entity_info($id,$this->moduleName);
|
||||
$focus->apply_field_security();
|
||||
$focus->id = $id;
|
||||
$this->associated_products = getAssociatedProducts($this->moduleName,$focus);
|
||||
}
|
||||
|
||||
function getPDFGenerator() {
|
||||
return new Vtiger_PDF_Generator();
|
||||
}
|
||||
|
||||
function getContentViewer() {
|
||||
if($this->focusColumnValue('hdnTaxType') == "individual") {
|
||||
$contentViewer = new Vtiger_PDF_InventoryContentViewer();
|
||||
} else {
|
||||
$contentViewer = new Vtiger_PDF_InventoryTaxGroupContentViewer();
|
||||
}
|
||||
$contentViewer->setContentModels($this->buildContentModels());
|
||||
$contentViewer->setSummaryModel($this->buildSummaryModel());
|
||||
$contentViewer->setLabelModel($this->buildContentLabelModel());
|
||||
$contentViewer->setWatermarkModel($this->buildWatermarkModel());
|
||||
return $contentViewer;
|
||||
}
|
||||
|
||||
function getHeaderViewer() {
|
||||
$headerViewer = new Vtiger_PDF_InventoryHeaderViewer();
|
||||
$headerViewer->setModel($this->buildHeaderModel());
|
||||
return $headerViewer;
|
||||
}
|
||||
|
||||
function getFooterViewer() {
|
||||
$footerViewer = new Vtiger_PDF_InventoryFooterViewer();
|
||||
$footerViewer->setModel($this->buildFooterModel());
|
||||
$footerViewer->setLabelModel($this->buildFooterLabelModel());
|
||||
$footerViewer->setOnLastPage();
|
||||
return $footerViewer;
|
||||
}
|
||||
|
||||
function getPagerViewer() {
|
||||
$pagerViewer = new Vtiger_PDF_PagerViewer();
|
||||
$pagerViewer->setModel($this->buildPagermodel());
|
||||
return $pagerViewer;
|
||||
}
|
||||
|
||||
function Output($filename, $type) {
|
||||
if(is_null($this->focus)) return;
|
||||
|
||||
$pdfgenerator = $this->getPDFGenerator();
|
||||
|
||||
$pdfgenerator->setPagerViewer($this->getPagerViewer());
|
||||
$pdfgenerator->setHeaderViewer($this->getHeaderViewer());
|
||||
$pdfgenerator->setFooterViewer($this->getFooterViewer());
|
||||
$pdfgenerator->setContentViewer($this->getContentViewer());
|
||||
|
||||
$pdfgenerator->generate($filename, $type);
|
||||
}
|
||||
|
||||
|
||||
// Helper methods
|
||||
|
||||
function buildContentModels() {
|
||||
$associated_products = $this->associated_products;
|
||||
$contentModels = array();
|
||||
$productLineItemIndex = 0;
|
||||
$totaltaxes = 0;
|
||||
foreach($associated_products as $productLineItem) {
|
||||
++$productLineItemIndex;
|
||||
|
||||
$contentModel = new Vtiger_PDF_Model();
|
||||
|
||||
$discountPercentage = 0.00;
|
||||
$total_tax_percent = 0.00;
|
||||
$producttotal_taxes = 0.00;
|
||||
$quantity = ''; $listPrice = ''; $discount = ''; $taxable_total = '';
|
||||
$tax_amount = ''; $producttotal = '';
|
||||
|
||||
|
||||
$quantity = $productLineItem["qty{$productLineItemIndex}"];
|
||||
$listPrice = $productLineItem["listPrice{$productLineItemIndex}"];
|
||||
$discount = $productLineItem["discountTotal{$productLineItemIndex}"];
|
||||
$taxable_total = $quantity * $listPrice - $discount;
|
||||
$taxable_total = number_format($taxable_total, 2,'.',''); //Convert to 2 decimals
|
||||
$producttotal = $taxable_total;
|
||||
if($this->focus->column_fields["hdnTaxType"] == "individual") {
|
||||
for($tax_count=0;$tax_count<count($productLineItem['taxes']);$tax_count++) {
|
||||
$tax_percent = $productLineItem['taxes'][$tax_count]['percentage'];
|
||||
$total_tax_percent += $tax_percent;
|
||||
$tax_amount = (($taxable_total*$tax_percent)/100);
|
||||
$producttotal_taxes += $tax_amount;
|
||||
}
|
||||
}
|
||||
|
||||
$producttotal_taxes = number_format($producttotal_taxes, 2,'.',''); //Convert to 2 decimals
|
||||
$producttotal = $taxable_total+$producttotal_taxes;
|
||||
$producttotal = number_format($producttotal, 2,'.',''); //Convert to 2 decimals
|
||||
$tax = $producttotal_taxes;
|
||||
$totaltaxes += $tax;
|
||||
$totaltaxes = number_format($totaltaxes, 2,'.',''); //Convert to 2 decimals
|
||||
$discountPercentage = $productLineItem["discount_percent{$productLineItemIndex}"];
|
||||
$productName = $productLineItem["productName{$productLineItemIndex}"];
|
||||
//get the sub product
|
||||
$subProducts = $productLineItem["subProductArray{$productLineItemIndex}"];
|
||||
if($subProducts != ''){
|
||||
foreach($subProducts as $subProduct) {
|
||||
$productName .="\n"." - ".decode_html($subProduct);
|
||||
}
|
||||
}
|
||||
$contentModel->set('Name', $productName);
|
||||
$contentModel->set('Code', $productLineItem["hdnProductcode{$productLineItemIndex}"]);
|
||||
$contentModel->set('Quantity', $quantity);
|
||||
$contentModel->set('Price', $this->formatPrice($listPrice));
|
||||
$contentModel->set('Discount', $this->formatPrice($discount)."\n ($discountPercentage%)");
|
||||
$contentModel->set('Tax', $this->formatPrice($tax)."\n ($total_tax_percent%)");
|
||||
$contentModel->set('Total', $this->formatPrice($producttotal));
|
||||
$contentModel->set('Comment', $productLineItem["comment{$productLineItemIndex}"]);
|
||||
|
||||
$contentModels[] = $contentModel;
|
||||
}
|
||||
$this->totaltaxes = $totaltaxes; //will be used to add it to the net total
|
||||
|
||||
return $contentModels;
|
||||
}
|
||||
|
||||
function buildContentLabelModel() {
|
||||
$labelModel = new Vtiger_PDF_Model();
|
||||
$labelModel->set('Code', getTranslatedString('Product Code',$this->moduleName));
|
||||
$labelModel->set('Name', getTranslatedString('Product Name',$this->moduleName));
|
||||
$labelModel->set('Quantity', getTranslatedString('Quantity',$this->moduleName));
|
||||
$labelModel->set('Price', getTranslatedString('Price',$this->moduleName));
|
||||
$labelModel->set('Discount', getTranslatedString('Discount',$this->moduleName));
|
||||
$labelModel->set('Tax', getTranslatedString('Tax',$this->moduleName));
|
||||
$labelModel->set('Total', getTranslatedString('Total',$this->moduleName));
|
||||
$labelModel->set('Comment', getTranslatedString('Comment'),$this->moduleName);
|
||||
return $labelModel;
|
||||
}
|
||||
|
||||
function buildSummaryModel() {
|
||||
$associated_products = $this->associated_products;
|
||||
$final_details = $associated_products[1]['final_details'];
|
||||
|
||||
$summaryModel = new Vtiger_PDF_Model();
|
||||
|
||||
$netTotal = $discount = $handlingCharges = $handlingTaxes = 0;
|
||||
$adjustment = $grandTotal = 0;
|
||||
|
||||
$productLineItemIndex = 0;
|
||||
$sh_tax_percent = 0;
|
||||
foreach($associated_products as $productLineItem) {
|
||||
++$productLineItemIndex;
|
||||
$netTotal += $productLineItem["netPrice{$productLineItemIndex}"];
|
||||
}
|
||||
$netTotal = number_format(($netTotal + $this->totaltaxes), 2,'.', '');
|
||||
$summaryModel->set(getTranslatedString("Net Total", $this->moduleName), $this->formatPrice($netTotal));
|
||||
|
||||
$discount_amount = $final_details["discount_amount_final"];
|
||||
$discount_percent = $final_details["discount_percentage_final"];
|
||||
|
||||
$discount = 0.0;
|
||||
if(!empty($discount_amount)) {
|
||||
$discount = $discount_amount;
|
||||
} else if(!empty($discount_percent)) {
|
||||
$discount = (($discount_percent*$final_details["hdnSubTotal"])/100);
|
||||
}
|
||||
$summaryModel->set(getTranslatedString("Discount", $this->moduleName), $this->formatPrice($discount));
|
||||
|
||||
$group_total_tax_percent = '0.00';
|
||||
//To calculate the group tax amount
|
||||
if($final_details['taxtype'] == 'group') {
|
||||
$group_tax_details = $final_details['taxes'];
|
||||
for($i=0;$i<count($group_tax_details);$i++) {
|
||||
$group_total_tax_percent += $group_tax_details[$i]['percentage'];
|
||||
}
|
||||
$summaryModel->set(getTranslatedString("Tax:", $this->moduleName)."($group_total_tax_percent%)", $this->formatPrice($final_details['tax_totalamount']));
|
||||
}
|
||||
//Shipping & Handling taxes
|
||||
$sh_tax_details = $final_details['sh_taxes'];
|
||||
for($i=0;$i<count($sh_tax_details);$i++) {
|
||||
$sh_tax_percent = $sh_tax_percent + $sh_tax_details[$i]['percentage'];
|
||||
}
|
||||
//obtain the Currency Symbol
|
||||
$currencySymbol = $this->buildCurrencySymbol();
|
||||
|
||||
$summaryModel->set(getTranslatedString("Shipping & Handling Charges", $this->moduleName), $this->formatPrice($final_details['shipping_handling_charge']));
|
||||
$summaryModel->set(getTranslatedString("Shipping & Handling Tax:", $this->moduleName)."($sh_tax_percent%)", $this->formatPrice($final_details['shtax_totalamount']));
|
||||
$summaryModel->set(getTranslatedString("Adjustment", $this->moduleName), $this->formatPrice($final_details['adjustment']));
|
||||
$summaryModel->set(getTranslatedString("Grand Total : (in $currencySymbol)", $this->moduleName), $this->formatPrice($final_details['grandTotal'])); // TODO add currency string
|
||||
|
||||
return $summaryModel;
|
||||
}
|
||||
|
||||
function buildHeaderModel() {
|
||||
$headerModel = new Vtiger_PDF_Model();
|
||||
$headerModel->set('title', $this->buildHeaderModelTitle());
|
||||
$modelColumns = array($this->buildHeaderModelColumnLeft(), $this->buildHeaderModelColumnCenter(), $this->buildHeaderModelColumnRight());
|
||||
$headerModel->set('columns', $modelColumns);
|
||||
|
||||
return $headerModel;
|
||||
}
|
||||
|
||||
function buildHeaderModelTitle() {
|
||||
return $this->moduleName;
|
||||
}
|
||||
|
||||
function buildHeaderModelColumnLeft() {
|
||||
global $adb;
|
||||
|
||||
// Company information
|
||||
$result = $adb->pquery("SELECT * FROM vtiger_organizationdetails", array());
|
||||
$num_rows = $adb->num_rows($result);
|
||||
if($num_rows) {
|
||||
$resultrow = $adb->fetch_array($result);
|
||||
|
||||
$addressValues = array();
|
||||
$addressValues[] = $resultrow['address'];
|
||||
if(!empty($resultrow['city'])) $addressValues[]= "\n".$resultrow['city'];
|
||||
if(!empty($resultrow['state'])) $addressValues[]= ",".$resultrow['state'];
|
||||
if(!empty($resultrow['code'])) $addressValues[]= $resultrow['code'];
|
||||
if(!empty($resultrow['country'])) $addressValues[]= "\n".$resultrow['country'];
|
||||
|
||||
|
||||
if(!empty($resultrow['phone'])) $additionalCompanyInfo[]= "\n".getTranslatedString("Phone: ", $this->moduleName). $resultrow['phone'];
|
||||
if(!empty($resultrow['fax'])) $additionalCompanyInfo[]= "\n".getTranslatedString("Fax: ", $this->moduleName). $resultrow['fax'];
|
||||
if(!empty($resultrow['website'])) $additionalCompanyInfo[]= "\n".getTranslatedString("Website: ", $this->moduleName). $resultrow['website'];
|
||||
|
||||
$modelColumnLeft = array(
|
||||
'logo' => "test/logo/".$resultrow['logoname'],
|
||||
'summary' => decode_html($resultrow['organizationname']),
|
||||
'content' => $this->joinValues($addressValues, ' '). $this->joinValues($additionalCompanyInfo, ' ')
|
||||
);
|
||||
}
|
||||
return $modelColumnLeft;
|
||||
}
|
||||
|
||||
|
||||
function buildHeaderModelColumnCenter() {
|
||||
$customerName = $this->resolveReferenceLabel($this->focusColumnValue('account_id'), 'Accounts');
|
||||
$contactName = $this->resolveReferenceLabel($this->focusColumnValue('contact_id'), 'Contacts');
|
||||
|
||||
$customerNameLabel = getTranslatedString('Customer Name', $this->moduleName);
|
||||
$contactNameLabel = getTranslatedString('Contact Name', $this->moduleName);
|
||||
$modelColumnCenter = array(
|
||||
$customerNameLabel => $customerName,
|
||||
$contactNameLabel => $contactName,
|
||||
);
|
||||
return $modelColumnCenter;
|
||||
}
|
||||
|
||||
function buildHeaderModelColumnRight() {
|
||||
$issueDateLabel = getTranslatedString('Issued Date', $this->moduleName);
|
||||
$validDateLabel = getTranslatedString('Valid Date', $this->moduleName);
|
||||
$billingAddressLabel = getTranslatedString('Billing Address', $this->moduleName);
|
||||
$shippingAddressLabel = getTranslatedString('Shipping Address', $this->moduleName);
|
||||
|
||||
$modelColumnRight = array(
|
||||
'dates' => array(
|
||||
$issueDateLabel => $this->formatDate(date("Y-m-d")),
|
||||
$validDateLabel => $this->formatDate($this->focusColumnValue('validtill')),
|
||||
),
|
||||
$billingAddressLabel => $this->buildHeaderBillingAddress(),
|
||||
$shippingAddressLabel => $this->buildHeaderShippingAddress()
|
||||
);
|
||||
return $modelColumnRight;
|
||||
}
|
||||
|
||||
function buildFooterModel() {
|
||||
$footerModel = new Vtiger_PDF_Model();
|
||||
$footerModel->set(Vtiger_PDF_InventoryFooterViewer::$DESCRIPTION_DATA_KEY, from_html($this->focusColumnValue('description')));
|
||||
$footerModel->set(Vtiger_PDF_InventoryFooterViewer::$TERMSANDCONDITION_DATA_KEY, from_html($this->focusColumnValue('terms_conditions')));
|
||||
return $footerModel;
|
||||
}
|
||||
|
||||
function buildFooterLabelModel() {
|
||||
$labelModel = new Vtiger_PDF_Model();
|
||||
$labelModel->set(Vtiger_PDF_InventoryFooterViewer::$DESCRIPTION_LABEL_KEY, getTranslatedString('Description',$this->moduleName));
|
||||
$labelModel->set(Vtiger_PDF_InventoryFooterViewer::$TERMSANDCONDITION_LABEL_KEY, getTranslatedString('Terms & Conditions',$this->moduleName));
|
||||
return $labelModel;
|
||||
}
|
||||
|
||||
function buildPagerModel() {
|
||||
$footerModel = new Vtiger_PDF_Model();
|
||||
$footerModel->set('format', '-%s-');
|
||||
return $footerModel;
|
||||
}
|
||||
|
||||
function getWatermarkContent() {
|
||||
return '';
|
||||
}
|
||||
|
||||
function buildWatermarkModel() {
|
||||
$watermarkModel = new Vtiger_PDF_Model();
|
||||
$watermarkModel->set('content', $this->getWatermarkContent());
|
||||
return $watermarkModel;
|
||||
}
|
||||
|
||||
function buildHeaderBillingAddress() {
|
||||
$billPoBox = $this->focusColumnValues(array('bill_pobox'));
|
||||
$billStreet = $this->focusColumnValues(array('bill_street'));
|
||||
$billCity = $this->focusColumnValues(array('bill_city'));
|
||||
$billState = $this->focusColumnValues(array('bill_state'));
|
||||
$billCountry = $this->focusColumnValues(array('bill_country'));
|
||||
$billCode = $this->focusColumnValues(array('bill_code'));
|
||||
$address = $this->joinValues(array($billPoBox, $billStreet), ' ');
|
||||
$address .= "\n".$this->joinValues(array($billCity, $billState), ',')." ".$billCode;
|
||||
$address .= "\n".$billCountry;
|
||||
return $address;
|
||||
}
|
||||
|
||||
function buildHeaderShippingAddress() {
|
||||
$shipPoBox = $this->focusColumnValues(array('ship_pobox'));
|
||||
$shipStreet = $this->focusColumnValues(array('ship_street'));
|
||||
$shipCity = $this->focusColumnValues(array('ship_city'));
|
||||
$shipState = $this->focusColumnValues(array('ship_state'));
|
||||
$shipCountry = $this->focusColumnValues(array('ship_country'));
|
||||
$shipCode = $this->focusColumnValues(array('ship_code'));
|
||||
$address = $this->joinValues(array($shipPoBox, $shipStreet), ' ');
|
||||
$address .= "\n".$this->joinValues(array($shipCity, $shipState), ',')." ".$shipCode;
|
||||
$address .= "\n".$shipCountry;
|
||||
return $address;
|
||||
}
|
||||
|
||||
function buildCurrencySymbol() {
|
||||
global $adb;
|
||||
$currencyId = $this->focus->column_fields['currency_id'];
|
||||
if(!empty($currencyId)) {
|
||||
$result = $adb->pquery("SELECT currency_symbol FROM vtiger_currency_info WHERE id=?", array($currencyId));
|
||||
return decode_html($adb->query_result($result,0,'currency_symbol'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function focusColumnValues($names, $delimeter="\n") {
|
||||
if(!is_array($names)) {
|
||||
$names = array($names);
|
||||
}
|
||||
$values = array();
|
||||
foreach($names as $name) {
|
||||
$value = $this->focusColumnValue($name, false);
|
||||
if($value !== false) {
|
||||
$values[] = $value;
|
||||
}
|
||||
}
|
||||
return $this->joinValues($values, $delimeter);
|
||||
}
|
||||
|
||||
function focusColumnValue($key, $defvalue='') {
|
||||
$focus = $this->focus;
|
||||
if(isset($focus->column_fields[$key])) {
|
||||
return $focus->column_fields[$key];
|
||||
}
|
||||
return $defvalue;
|
||||
}
|
||||
|
||||
function resolveReferenceLabel($id, $module=false) {
|
||||
if(empty($id)) {
|
||||
return '';
|
||||
}
|
||||
if($module === false) {
|
||||
$module = getSalesEntityType($id);
|
||||
}
|
||||
$label = getEntityName($module, array($id));
|
||||
return decode_html($label[$id]);
|
||||
}
|
||||
|
||||
function joinValues($values, $delimeter= "\n") {
|
||||
$valueString = '';
|
||||
foreach($values as $value) {
|
||||
if(empty($value)) continue;
|
||||
$valueString .= $value . $delimeter;
|
||||
}
|
||||
return rtrim($valueString, $delimeter);
|
||||
}
|
||||
|
||||
function formatNumber($value) {
|
||||
return number_format($value);
|
||||
}
|
||||
|
||||
function formatPrice($value, $decimal=2) {
|
||||
$currencyField = new CurrencyField($value);
|
||||
return $currencyField->getDisplayValue(null, true);
|
||||
}
|
||||
|
||||
function formatDate($value) {
|
||||
return DateTimeField::convertToUserFormat($value);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,288 @@
|
|||
<?php
|
||||
/*********************************************************************************
|
||||
* The contents of this file are subject to the SugarCRM Public License Version 1.1.2
|
||||
* ("License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at http://www.sugarcrm.com/SPL
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
* the specific language governing rights and limitations under the License.
|
||||
* The Original Code is: SugarCRM Open Source
|
||||
* The Initial Developer of the Original Code is SugarCRM, Inc.
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.;
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
********************************************************************************/
|
||||
/*********************************************************************************
|
||||
* $Header$
|
||||
* Description: generic list view class.
|
||||
********************************************************************************/
|
||||
require_once('include/logging.php');
|
||||
require_once('include/ListView/ListViewSession.php');
|
||||
|
||||
class ListView {
|
||||
|
||||
var $local_theme = null;
|
||||
var $local_app_strings= null;
|
||||
var $local_image_path = null;
|
||||
var $local_current_module = null;
|
||||
var $local_mod_strings = null;
|
||||
var $records_per_page = 20;
|
||||
var $xTemplate = null;
|
||||
var $xTemplatePath = null;
|
||||
var $seed_data = null;
|
||||
var $query_where = null;
|
||||
var $query_limit = -1;
|
||||
var $query_orderby = null;
|
||||
var $header_title = "";
|
||||
var $header_text = "";
|
||||
var $log = null;
|
||||
var $initialized = false;
|
||||
var $querey_where_has_changed = false;
|
||||
var $display_header_and_footer = true;
|
||||
|
||||
|
||||
/**initializes ListView
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function ListView(){
|
||||
global $log;
|
||||
$log->debug("Entering ListView() method ...");
|
||||
|
||||
|
||||
if(!$this->initialized){
|
||||
global $list_max_entries_per_page;
|
||||
$this->records_per_page = $list_max_entries_per_page + 0;
|
||||
$this->initialized = true;
|
||||
global $theme, $app_strings, $image_path, $currentModule;
|
||||
$this->local_theme = $theme;
|
||||
$this->local_app_strings = &$app_strings;
|
||||
$this->local_image_path = $image_path;
|
||||
$this->local_current_module = $currentModule;
|
||||
|
||||
if(empty($this->local_image_path)){
|
||||
$this->local_image_path = 'themes/'.$theme.'/images';
|
||||
}
|
||||
$this->log = LoggerManager::getLogger('listView_'.$this->local_current_module);
|
||||
$log->debug("Exiting ListView method ...");
|
||||
}
|
||||
}
|
||||
/**sets the header title */
|
||||
function setHeaderTitle($value){
|
||||
global $log;
|
||||
$log->debug("Entering setHeaderTitle(".$value.") method ...");
|
||||
$this->header_title = $value;
|
||||
$log->debug("Exiting setHeaderTitle method ...");
|
||||
}
|
||||
/**sets the header text this is text thats appended to the header vtiger_table and is usually used for the creation of buttons
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setHeaderText($value){
|
||||
global $log;
|
||||
$log->debug("Entering setHeaderText(".$value.") method ...");
|
||||
$this->header_text = $value;
|
||||
$log->debug("Exiting setHeaderText method ...");
|
||||
}
|
||||
/**sets the parameters dealing with the db
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setQuery($where, $limit, $orderBy, $varName, $allowOrderByOveride= true){
|
||||
global $log;
|
||||
$log->debug("Entering setQuery(".$where.",". $limit.",". $orderBy.",". $varName.",". $allowOrderByOveride.") method ...");
|
||||
$this->query_where = $where;
|
||||
if($this->getSessionVariable("query", "where") != $where){
|
||||
$this->querey_where_has_changed = true;
|
||||
$this->setSessionVariable("query", "where", $where);
|
||||
}
|
||||
|
||||
$this->query_limit = $limit;
|
||||
if(!$allowOrderByOveride){
|
||||
$this->query_orderby = $orderBy;
|
||||
$log->debug("Exiting setQuery method ...");
|
||||
return;
|
||||
}
|
||||
$sortBy = $this->getSessionVariable($varName, "ORDER_BY") ;
|
||||
|
||||
if(empty($sortBy)){
|
||||
$this->setUserVariable($varName, "ORDER_BY", $orderBy);
|
||||
$sortBy = $orderBy;
|
||||
}else{
|
||||
$this->setUserVariable($varName, "ORDER_BY", $sortBy);
|
||||
}
|
||||
if($sortBy == 'amount'){
|
||||
$sortBy = 'amount*1';
|
||||
}
|
||||
|
||||
$desc = false;
|
||||
$desc = $this->getSessionVariable($varName, $sortBy."_desc");
|
||||
|
||||
if(empty($desc))
|
||||
$desc = false;
|
||||
if(isset($_REQUEST[$this->getSessionVariableName($varName, "ORDER_BY")]))
|
||||
$last = $this->getSessionVariable($varName, "ORDER_BY_LAST");
|
||||
if(!empty($last) && $last == $sortBy){
|
||||
$desc = !$desc;
|
||||
}else {
|
||||
$this->setSessionVariable($varName, "ORDER_BY_LAST", $sortBy);
|
||||
}
|
||||
$this->setSessionVariable($varName, $sortBy."_desc", $desc);
|
||||
if(!empty($sortBy)){
|
||||
if(substr_count(strtolower($sortBy), ' desc') == 0 && substr_count(strtolower($sortBy), ' asc') == 0){
|
||||
if($desc){
|
||||
$this->query_orderby = $sortBy.' desc';
|
||||
}else{
|
||||
$this->query_orderby = $sortBy.' asc';
|
||||
}
|
||||
}
|
||||
else{
|
||||
$this->query_orderby = $sortBy;
|
||||
}
|
||||
}else {
|
||||
$this->query_orderby = "";
|
||||
}
|
||||
$log->debug("Exiting setQuery method ...");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**sets the theme used only use if it is different from the global
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setTheme($theme){
|
||||
global $log;
|
||||
$log->debug("Entering setTheme(".$theme.") method ...");
|
||||
$this->local_theme = $theme;
|
||||
if(isset($this->xTemplate))$this->xTemplate->assign("THEME", $this->local_theme );
|
||||
$log->debug("Exiting setTheme method ...");
|
||||
}
|
||||
|
||||
/**sets the AppStrings used only use if it is different from the global
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setAppStrings(&$app_strings){
|
||||
global $log;
|
||||
$log->debug("Entering setAppStrings(".$app_strings.") method ...");
|
||||
unset($this->local_app_strings);
|
||||
$this->local_app_strings = $app_strings;
|
||||
if(isset($this->xTemplate))$this->xTemplate->assign("APP", $this->local_app_strings );
|
||||
$log->debug("Exiting setAppStrings method ...");
|
||||
}
|
||||
|
||||
/**sets the ModStrings used
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setModStrings(&$mod_strings){
|
||||
global $log;
|
||||
$log->debug("Entering setModStrings(".$mod_strings.") method ...");
|
||||
unset($this->local_module_strings);
|
||||
$this->local_mod_strings = $mod_strings;
|
||||
if(isset($this->xTemplate))$this->xTemplate->assign("MOD", $this->local_mod_strings );
|
||||
$log->debug("Exiting setModStrings method ...");
|
||||
}
|
||||
|
||||
/**sets the ImagePath used
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setImagePath($image_path){
|
||||
global $log;
|
||||
$log->debug("Entering setImagePath(".$image_path.") method ...");
|
||||
$this->local_image_path = $image_path;
|
||||
if(empty($this->local_image_path)){
|
||||
$this->local_image_path = 'themes/'.$this->local_theme.'/images';
|
||||
}
|
||||
if(isset($this->xTemplate))$this->xTemplate->assign("IMAGE_PATH", $this->local_image_path );
|
||||
$log->debug("Exiting setImagePath method ...");
|
||||
}
|
||||
|
||||
/**sets the currentModule only use if this is different from the global
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setCurrentModule($currentModule){
|
||||
global $log;
|
||||
$log->debug("Entering setCurrentModule(".$currentModule.") method ...");
|
||||
unset($this->local_current_module);
|
||||
$this->local_current_module = $currentModule;
|
||||
$this->log = LoggerManager::getLogger('listView_'.$this->local_current_module);
|
||||
if(isset($this->xTemplate))$this->xTemplate->assign("MODULE_NAME", $this->local_current_module );
|
||||
$log->debug("Exiting setCurrentModule method ...");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**INTERNAL FUNCTION sets a session variable
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function setSessionVariable($localVarName,$varName, $value){
|
||||
global $log;
|
||||
$log->debug("Entering setSessionVariable(".$localVarName.",".$varName.",". $value.") method ...");
|
||||
$_SESSION[$this->local_current_module."_".$localVarName."_".$varName] = $value;
|
||||
$log->debug("Exiting setSessionVariable method ...");
|
||||
}
|
||||
|
||||
function setUserVariable($localVarName,$varName, $value){
|
||||
global $log;
|
||||
$log->debug("Entering setUserVariable(".$localVarName.",".$varName.",". $value.") method ...");
|
||||
global $current_user;
|
||||
$current_user->setPreference($this->local_current_module."_".$localVarName."_".$varName, $value);
|
||||
$log->debug("Exiting setUserVariable method ...");
|
||||
}
|
||||
|
||||
/**INTERNAL FUNCTION returns a session variable first checking the querey for it then checking the session
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
function getSessionVariable($localVarName,$varName){
|
||||
global $log;
|
||||
$log->debug("Entering getSessionVariable(".$localVarName.",".$varName.") method ...");
|
||||
if(isset($_REQUEST[$this->getSessionVariableName($localVarName, $varName)])){
|
||||
$this->setSessionVariable($localVarName,$varName,vtlib_purify($_REQUEST[$this->getSessionVariableName($localVarName, $varName)]));
|
||||
}
|
||||
if(isset($_SESSION[$this->getSessionVariableName($localVarName, $varName)])){
|
||||
$log->debug("Exiting getSessionVariable method ...");
|
||||
return $_SESSION[$this->getSessionVariableName($localVarName, $varName)];
|
||||
}
|
||||
$log->debug("Exiting getSessionVariable method ...");
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* @return void
|
||||
* @param unknown $localVarName
|
||||
* @param unknown $varName
|
||||
* @desc INTERNAL FUNCTION returns the session/query variable name
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________..
|
||||
*/
|
||||
function getSessionVariableName($localVarName,$varName){
|
||||
global $log;
|
||||
$log->debug("Entering getSessionVariableName(".$localVarName.",".$varName.") method ...");
|
||||
$log->debug("Exiting getSessionVariableName method ...");
|
||||
return $this->local_current_module."_".$localVarName."_".$varName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,717 @@
|
|||
<?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.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Description of ListViewController
|
||||
*
|
||||
* @author MAK
|
||||
*/
|
||||
class ListViewController {
|
||||
/**
|
||||
*
|
||||
* @var QueryGenerator
|
||||
*/
|
||||
private $queryGenerator;
|
||||
/**
|
||||
*
|
||||
* @var PearDatabase
|
||||
*/
|
||||
private $db;
|
||||
private $nameList;
|
||||
private $typeList;
|
||||
private $ownerNameList;
|
||||
private $user;
|
||||
private $picklistValueMap;
|
||||
private $picklistRoleMap;
|
||||
private $headerSortingEnabled;
|
||||
public function __construct($db, $user, $generator) {
|
||||
$this->queryGenerator = $generator;
|
||||
$this->db = $db;
|
||||
$this->user = $user;
|
||||
$this->nameList = array();
|
||||
$this->typeList = array();
|
||||
$this->ownerNameList = array();
|
||||
$this->picklistValueMap = array();
|
||||
$this->picklistRoleMap = array();
|
||||
$this->headerSortingEnabled = true;
|
||||
}
|
||||
|
||||
public function isHeaderSortingEnabled() {
|
||||
return $this->headerSortingEnabled;
|
||||
}
|
||||
|
||||
public function setHeaderSorting($enabled) {
|
||||
$this->headerSortingEnabled = $enabled;
|
||||
}
|
||||
|
||||
public function setupAccessiblePicklistValueList($name) {
|
||||
$isRoleBased = vtws_isRoleBasedPicklist($name);
|
||||
$this->picklistRoleMap[$name] = $isRoleBased;
|
||||
if ($this->picklistRoleMap[$name]) {
|
||||
$this->picklistValueMap[$name] = getAssignedPicklistValues($name,$this->user->roleid, $this->db);
|
||||
}
|
||||
}
|
||||
|
||||
public function fetchNameList($field, $result) {
|
||||
$referenceFieldInfoList = $this->queryGenerator->getReferenceFieldInfoList();
|
||||
$fieldName = $field->getFieldName();
|
||||
$rowCount = $this->db->num_rows($result);
|
||||
|
||||
$idList = array();
|
||||
for ($i = 0; $i < $rowCount; $i++) {
|
||||
$id = $this->db->query_result($result, $i, $field->getColumnName());
|
||||
if (!isset($this->nameList[$fieldName][$id])) {
|
||||
$idList[$id] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
$idList = array_keys($idList);
|
||||
if(count($idList) == 0) {
|
||||
return;
|
||||
}
|
||||
$moduleList = $referenceFieldInfoList[$fieldName];
|
||||
foreach ($moduleList as $module) {
|
||||
$meta = $this->queryGenerator->getMeta($module);
|
||||
if ($meta->isModuleEntity()) {
|
||||
if($module == 'Users') {
|
||||
$nameList = getOwnerNameList($idList);
|
||||
} else {
|
||||
//TODO handle multiple module names overriding each other.
|
||||
$nameList = getEntityName($module, $idList);
|
||||
}
|
||||
} else {
|
||||
$nameList = vtws_getActorEntityName($module, $idList);
|
||||
}
|
||||
$entityTypeList = array_intersect(array_keys($nameList), $idList);
|
||||
foreach ($entityTypeList as $id) {
|
||||
$this->typeList[$id] = $module;
|
||||
}
|
||||
if(empty($this->nameList[$fieldName])) {
|
||||
$this->nameList[$fieldName] = array();
|
||||
}
|
||||
foreach ($entityTypeList as $id) {
|
||||
$this->typeList[$id] = $module;
|
||||
$this->nameList[$fieldName][$id] = $nameList[$id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**This function generates the List view entries in a list view
|
||||
* Param $focus - module object
|
||||
* Param $result - resultset of a listview query
|
||||
* Param $navigation_array - navigation values in an array
|
||||
* Param $relatedlist - check for related list flag
|
||||
* Param $returnset - list query parameters in url string
|
||||
* Param $edit_action - Edit action value
|
||||
* Param $del_action - delete action value
|
||||
* Param $oCv - vtiger_customview object
|
||||
* Returns an array type
|
||||
*/
|
||||
function getListViewEntries($focus, $module,$result,$navigationInfo,$skipActions=false) {
|
||||
|
||||
require('user_privileges/user_privileges_'.$this->user->id.'.php');
|
||||
global $listview_max_textlength, $theme,$default_charset;
|
||||
$fields = $this->queryGenerator->getFields();
|
||||
$whereFields = $this->queryGenerator->getWhereFields();
|
||||
$meta = $this->queryGenerator->getMeta($this->queryGenerator->getModule());
|
||||
|
||||
$moduleFields = $meta->getModuleFields();
|
||||
$accessibleFieldList = array_keys($moduleFields);
|
||||
$listViewFields = array_intersect($fields, $accessibleFieldList);
|
||||
|
||||
$referenceFieldList = $this->queryGenerator->getReferenceFieldList();
|
||||
foreach ($referenceFieldList as $fieldName) {
|
||||
if (in_array($fieldName, $listViewFields)) {
|
||||
$field = $moduleFields[$fieldName];
|
||||
$this->fetchNameList($field, $result);
|
||||
}
|
||||
}
|
||||
|
||||
$db = PearDatabase::getInstance();
|
||||
$rowCount = $db->num_rows($result);
|
||||
$ownerFieldList = $this->queryGenerator->getOwnerFieldList();
|
||||
foreach ($ownerFieldList as $fieldName) {
|
||||
if (in_array($fieldName, $listViewFields)) {
|
||||
$field = $moduleFields[$fieldName];
|
||||
$idList = array();
|
||||
for ($i = 0; $i < $rowCount; $i++) {
|
||||
$id = $this->db->query_result($result, $i, $field->getColumnName());
|
||||
if (!isset($this->ownerNameList[$fieldName][$id])) {
|
||||
$idList[] = $id;
|
||||
}
|
||||
}
|
||||
if(count($idList) > 0) {
|
||||
if(!is_array($this->ownerNameList[$fieldName])) {
|
||||
$this->ownerNameList[$fieldName] = getOwnerNameList($idList);
|
||||
} else {
|
||||
//array_merge API loses key information so need to merge the arrays
|
||||
// manually.
|
||||
$newOwnerList = getOwnerNameList($idList);
|
||||
foreach ($newOwnerList as $id => $name) {
|
||||
$this->ownerNameList[$fieldName][$id] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($listViewFields as $fieldName) {
|
||||
$field = $moduleFields[$fieldName];
|
||||
if(!$is_admin && ($field->getFieldDataType() == 'picklist' ||
|
||||
$field->getFieldDataType() == 'multipicklist')) {
|
||||
$this->setupAccessiblePicklistValueList($fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
$useAsterisk = get_use_asterisk($this->user->id);
|
||||
|
||||
$data = array();
|
||||
for ($i = 0; $i < $rowCount; ++$i) {
|
||||
//Getting the recordId
|
||||
if($module != 'Users') {
|
||||
$baseTable = $meta->getEntityBaseTable();
|
||||
$moduleTableIndexList = $meta->getEntityTableIndexList();
|
||||
$baseTableIndex = $moduleTableIndexList[$baseTable];
|
||||
|
||||
$recordId = $db->query_result($result,$i,$baseTableIndex);
|
||||
$ownerId = $db->query_result($result,$i,"smownerid");
|
||||
}else {
|
||||
$recordId = $db->query_result($result,$i,"id");
|
||||
}
|
||||
$row = array();
|
||||
|
||||
foreach ($listViewFields as $fieldName) {
|
||||
$field = $moduleFields[$fieldName];
|
||||
$uitype = $field->getUIType();
|
||||
$rawValue = $this->db->query_result($result, $i, $field->getColumnName());
|
||||
if($module == 'Calendar') {
|
||||
$activityType = $this->db->query_result($result, $i, 'activitytype');
|
||||
}
|
||||
|
||||
if($uitype != 8){
|
||||
$value = html_entity_decode($rawValue,ENT_QUOTES,$default_charset);
|
||||
} else {
|
||||
$value = $rawValue;
|
||||
}
|
||||
|
||||
if($module == 'Documents' && $fieldName == 'filename') {
|
||||
$downloadtype = $db->query_result($result,$i,'filelocationtype');
|
||||
if($downloadtype == 'I') {
|
||||
$ext =substr($value, strrpos($value, ".") + 1);
|
||||
$ext = strtolower($ext);
|
||||
if($value != ''){
|
||||
if($ext == 'bin' || $ext == 'exe' || $ext == 'rpm') {
|
||||
$fileicon = "<img src='" . vtiger_imageurl('fExeBin.gif', $theme).
|
||||
"' hspace='3' align='absmiddle' border='0'>";
|
||||
} elseif($ext == 'jpg' || $ext == 'gif' || $ext == 'bmp') {
|
||||
$fileicon = "<img src='".vtiger_imageurl('fbImageFile.gif', $theme).
|
||||
"' hspace='3' align='absmiddle' border='0'>";
|
||||
} elseif($ext == 'txt' || $ext == 'doc' || $ext == 'xls') {
|
||||
$fileicon = "<img src='".vtiger_imageurl('fbTextFile.gif', $theme).
|
||||
"' hspace='3' align='absmiddle' border='0'>";
|
||||
} elseif($ext == 'zip' || $ext == 'gz' || $ext == 'rar') {
|
||||
$fileicon = "<img src='".vtiger_imageurl('fbZipFile.gif', $theme).
|
||||
"' hspace='3' align='absmiddle' border='0'>";
|
||||
} else {
|
||||
$fileicon = "<img src='".vtiger_imageurl('fbUnknownFile.gif',$theme)
|
||||
. "' hspace='3' align='absmiddle' border='0'>";
|
||||
}
|
||||
}
|
||||
} elseif($downloadtype == 'E') {
|
||||
if(trim($value) != '' ) {
|
||||
$fileicon = "<img src='" . vtiger_imageurl('fbLink.gif', $theme) .
|
||||
"' alt='".getTranslatedString('LBL_EXTERNAL_LNK',$module).
|
||||
"' title='".getTranslatedString('LBL_EXTERNAL_LNK',$module).
|
||||
"' hspace='3' align='absmiddle' border='0'>";
|
||||
} else {
|
||||
$value = '--';
|
||||
$fileicon = '';
|
||||
}
|
||||
} else {
|
||||
$value = ' --';
|
||||
$fileicon = '';
|
||||
}
|
||||
|
||||
$fileName = $db->query_result($result,$i,'filename');
|
||||
|
||||
$downloadType = $db->query_result($result,$i,'filelocationtype');
|
||||
$status = $db->query_result($result,$i,'filestatus');
|
||||
$fileIdQuery = "select attachmentsid from vtiger_seattachmentsrel where crmid=?";
|
||||
$fileIdRes = $db->pquery($fileIdQuery,array($recordId));
|
||||
$fileId = $db->query_result($fileIdRes,0,'attachmentsid');
|
||||
if($fileName != '' && $status == 1) {
|
||||
if($downloadType == 'I' ) {
|
||||
$value = "<a href='index.php?module=uploads&action=downloadfile&".
|
||||
"entityid=$recordId&fileid=$fileId' title='".
|
||||
getTranslatedString("LBL_DOWNLOAD_FILE",$module).
|
||||
"' onclick='javascript:dldCntIncrease($recordId);'>".textlength_check($value).
|
||||
"</a>";
|
||||
} elseif($downloadType == 'E') {
|
||||
$value = "<a target='_blank' href='$fileName' onclick='javascript:".
|
||||
"dldCntIncrease($recordId);' title='".
|
||||
getTranslatedString("LBL_DOWNLOAD_FILE",$module)."'>".textlength_check($value).
|
||||
"</a>";
|
||||
} else {
|
||||
$value = ' --';
|
||||
}
|
||||
}
|
||||
$value = $fileicon.$value;
|
||||
} elseif($module == 'Documents' && $fieldName == 'filesize') {
|
||||
$downloadType = $db->query_result($result,$i,'filelocationtype');
|
||||
if($downloadType == 'I') {
|
||||
$filesize = $value;
|
||||
if($filesize < 1024)
|
||||
$value=$filesize.' B';
|
||||
elseif($filesize > 1024 && $filesize < 1048576)
|
||||
$value=round($filesize/1024,2).' KB';
|
||||
else if($filesize > 1048576)
|
||||
$value=round($filesize/(1024*1024),2).' MB';
|
||||
} else {
|
||||
$value = ' --';
|
||||
}
|
||||
} elseif( $module == 'Documents' && $fieldName == 'filestatus') {
|
||||
if($value == 1)
|
||||
$value=getTranslatedString('yes',$module);
|
||||
elseif($value == 0)
|
||||
$value=getTranslatedString('no',$module);
|
||||
else
|
||||
$value='--';
|
||||
} elseif( $module == 'Documents' && $fieldName == 'filetype') {
|
||||
$downloadType = $db->query_result($result,$i,'filelocationtype');
|
||||
if($downloadType == 'E' || $downloadType != 'I') {
|
||||
$value = '--';
|
||||
}
|
||||
} elseif ($field->getUIType() == '27') {
|
||||
if ($value == 'I') {
|
||||
$value = getTranslatedString('LBL_INTERNAL',$module);
|
||||
}elseif ($value == 'E') {
|
||||
$value = getTranslatedString('LBL_EXTERNAL',$module);
|
||||
}else {
|
||||
$value = ' --';
|
||||
}
|
||||
}elseif ($field->getFieldDataType() == 'picklist') {
|
||||
if ($value != '' && !$is_admin && $this->picklistRoleMap[$fieldName] &&
|
||||
!in_array($value, $this->picklistValueMap[$fieldName])) {
|
||||
$value = "<font color='red'>".getTranslatedString('LBL_NOT_ACCESSIBLE',
|
||||
$module)."</font>";
|
||||
} else {
|
||||
$value = getTranslatedString($value,$module);
|
||||
$value = textlength_check($value);
|
||||
}
|
||||
}elseif($field->getFieldDataType() == 'date' ||
|
||||
$field->getFieldDataType() == 'datetime') {
|
||||
if($value != '' && $value != '0000-00-00') {
|
||||
$date = new DateTimeField($value);
|
||||
$value = $date->getDisplayDate();
|
||||
if($field->getFieldDataType() == 'datetime') {
|
||||
$value .= (' ' . $date->getDisplayTime());
|
||||
}
|
||||
} elseif ($value == '0000-00-00') {
|
||||
$value = '';
|
||||
}
|
||||
} elseif($field->getFieldDataType() == 'currency') {
|
||||
if($value != '') {
|
||||
if($field->getUIType() == 72) {
|
||||
if($fieldName == 'unit_price') {
|
||||
$currencyId = getProductBaseCurrency($recordId,$module);
|
||||
$cursym_convrate = getCurrencySymbolandCRate($currencyId);
|
||||
$currencySymbol = $cursym_convrate['symbol'];
|
||||
} else {
|
||||
$currencyInfo = getInventoryCurrencyInfo($module, $recordId);
|
||||
$currencySymbol = $currencyInfo['currency_symbol'];
|
||||
}
|
||||
$value = number_format($value, 2,'.','');
|
||||
$currencyValue = CurrencyField::convertToUserFormat($value, null, true);
|
||||
$value = CurrencyField::appendCurrencySymbol($currencyValue, $currencySymbol);
|
||||
} else {
|
||||
//changes made to remove vtiger_currency symbol infront of each
|
||||
//vtiger_potential amount
|
||||
if ($value != 0) {
|
||||
$value = CurrencyField::convertToUserFormat($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif($field->getFieldDataType() == 'url') {
|
||||
$matchPattern = "^[\w]+:\/\/^";
|
||||
preg_match($matchPattern, $rawValue, $matches);
|
||||
if(!empty ($matches[0])){
|
||||
$value = '<a href="'.$rawValue.'" target="_blank">'.textlength_check($value).'</a>';
|
||||
}else{
|
||||
$value = '<a href="http://'.$rawValue.'" target="_blank">'.textlength_check($value).'</a>';
|
||||
}
|
||||
} elseif ($field->getFieldDataType() == 'email') {
|
||||
if($_SESSION['internal_mailer'] == 1) {
|
||||
//check added for email link in user detailview
|
||||
$fieldId = $field->getFieldId();
|
||||
$value = "<a href=\"javascript:InternalMailer($recordId,$fieldId,".
|
||||
"'$fieldName','$module','record_id');\">".textlength_check($value)."</a>";
|
||||
}else {
|
||||
$value = '<a href="mailto:'.$rawValue.'">'.textlength_check($value).'</a>';
|
||||
}
|
||||
} elseif($field->getFieldDataType() == 'boolean') {
|
||||
if($value == 1) {
|
||||
$value = getTranslatedString('yes',$module);
|
||||
} elseif($value == 0) {
|
||||
$value = getTranslatedString('no',$module);
|
||||
} else {
|
||||
$value = '--';
|
||||
}
|
||||
} elseif($field->getUIType() == 98) {
|
||||
$value = '<a href="index.php?action=RoleDetailView&module=Settings&parenttab='.
|
||||
'Settings&roleid='.$value.'">'.textlength_check(getRoleName($value)).'</a>';
|
||||
} elseif($field->getFieldDataType() == 'multipicklist') {
|
||||
$value = ($value != "") ? str_replace(' |##| ',', ',$value) : "";
|
||||
if(!$is_admin && $value != '') {
|
||||
$valueArray = ($rawValue != "") ? explode(' |##| ',$rawValue) : array();
|
||||
$notaccess = '<font color="red">'.getTranslatedString('LBL_NOT_ACCESSIBLE',
|
||||
$module)."</font>";
|
||||
$tmp = '';
|
||||
$tmpArray = array();
|
||||
foreach($valueArray as $index => $val) {
|
||||
if(!$listview_max_textlength ||
|
||||
!(strlen(preg_replace("/(<\/?)(\w+)([^>]*>)/i","",$tmp)) >
|
||||
$listview_max_textlength)) {
|
||||
if (!$is_admin && $this->picklistRoleMap[$fieldName] &&
|
||||
!in_array(trim($val), $this->picklistValueMap[$fieldName])) {
|
||||
$tmpArray[] = $notaccess;
|
||||
$tmp .= ', '.$notaccess;
|
||||
} else {
|
||||
$tmpArray[] = $val;
|
||||
$tmp .= ', '.$val;
|
||||
}
|
||||
} else {
|
||||
$tmpArray[] = '...';
|
||||
$tmp .= '...';
|
||||
}
|
||||
}
|
||||
$value = implode(', ', $tmpArray);
|
||||
$value = textlength_check($value);
|
||||
}
|
||||
} elseif ($field->getFieldDataType() == 'skype') {
|
||||
$value = ($value != "") ? "<a href='skype:$value?call'>".textlength_check($value)."</a>" : "";
|
||||
} elseif ($field->getFieldDataType() == 'phone') {
|
||||
if($useAsterisk == 'true') {
|
||||
$value = "<a href='javascript:;' onclick='startCall("$value", ".
|
||||
""$recordId")'>".textlength_check($value)."</a>";
|
||||
} else {
|
||||
$value = textlength_check($value);
|
||||
}
|
||||
} elseif($field->getFieldDataType() == 'reference') {
|
||||
$referenceFieldInfoList = $this->queryGenerator->getReferenceFieldInfoList();
|
||||
$moduleList = $referenceFieldInfoList[$fieldName];
|
||||
if(count($moduleList) == 1) {
|
||||
$parentModule = $moduleList[0];
|
||||
} else {
|
||||
$parentModule = $this->typeList[$value];
|
||||
}
|
||||
if(!empty($value) && !empty($this->nameList[$fieldName]) && !empty($parentModule)) {
|
||||
$parentMeta = $this->queryGenerator->getMeta($parentModule);
|
||||
$value = textlength_check($this->nameList[$fieldName][$value]);
|
||||
if ($parentMeta->isModuleEntity() && $parentModule != "Users") {
|
||||
$value = "<a href='index.php?module=$parentModule&action=DetailView&".
|
||||
"record=$rawValue' title='".getTranslatedString($parentModule, $parentModule)."'>$value</a>";
|
||||
}
|
||||
} else {
|
||||
$value = '--';
|
||||
}
|
||||
} elseif($field->getFieldDataType() == 'owner') {
|
||||
$value = textlength_check($this->ownerNameList[$fieldName][$value]);
|
||||
} elseif ($field->getUIType() == 25) {
|
||||
//TODO clean request object reference.
|
||||
$contactId=$_REQUEST['record'];
|
||||
$emailId=$this->db->query_result($result,$i,"activityid");
|
||||
$result1 = $this->db->pquery("SELECT access_count FROM vtiger_email_track WHERE ".
|
||||
"crmid=? AND mailid=?", array($contactId,$emailId));
|
||||
$value=$this->db->query_result($result1,0,"access_count");
|
||||
if(!$value) {
|
||||
$value = 0;
|
||||
}
|
||||
} elseif($field->getUIType() == 8){
|
||||
if(!empty($value)){
|
||||
$temp_val = html_entity_decode($value,ENT_QUOTES,$default_charset);
|
||||
$json = new Zend_Json();
|
||||
$value = vt_suppressHTMLTags(implode(',',$json->decode($temp_val)));
|
||||
}
|
||||
} elseif ( in_array($uitype,array(7,9,90)) ) {
|
||||
$value = "<span align='right'>".textlength_check($value)."</div>";
|
||||
} else {
|
||||
$value = textlength_check($value);
|
||||
}
|
||||
|
||||
$parenttab = getParentTab();
|
||||
$nameFields = $this->queryGenerator->getModuleNameFields($module);
|
||||
$nameFieldList = explode(',',$nameFields);
|
||||
if(in_array($fieldName, $nameFieldList) && $module != 'Emails' ) {
|
||||
$value = "<a href='index.php?module=$module&parenttab=$parenttab&action=DetailView&record=".
|
||||
"$recordId' title='".getTranslatedString($module, $module)."'>$value</a>";
|
||||
} elseif($fieldName == $focus->list_link_field && $module != 'Emails') {
|
||||
$value = "<a href='index.php?module=$module&parenttab=$parenttab&action=DetailView&record=".
|
||||
"$recordId' title='".getTranslatedString($module, $module)."'>$value</a>";
|
||||
}
|
||||
|
||||
// vtlib customization: For listview javascript triggers
|
||||
$value = "$value <span type='vtlib_metainfo' vtrecordid='{$recordId}' vtfieldname=".
|
||||
"'{$fieldName}' vtmodule='$module' style='display:none;'></span>";
|
||||
// END
|
||||
$row[] = $value;
|
||||
}
|
||||
|
||||
//Added for Actions ie., edit and delete links in listview
|
||||
$actionLinkInfo = "";
|
||||
if(isPermitted($module,"EditView","") == 'yes'){
|
||||
$edit_link = $this->getListViewEditLink($module,$recordId);
|
||||
if(isset($navigationInfo['start']) && $navigationInfo['start'] > 1 && $module != 'Emails') {
|
||||
$actionLinkInfo .= "<a href=\"$edit_link&start=".
|
||||
$navigationInfo['start']."\">".getTranslatedString("LNK_EDIT",
|
||||
$module)."</a> ";
|
||||
} else {
|
||||
$actionLinkInfo .= "<a href=\"$edit_link\">".getTranslatedString("LNK_EDIT",
|
||||
$module)."</a> ";
|
||||
}
|
||||
}
|
||||
|
||||
if(isPermitted($module,"Delete","") == 'yes'){
|
||||
$del_link = $this->getListViewDeleteLink($module,$recordId);
|
||||
if($actionLinkInfo != "" && $del_link != "")
|
||||
$actionLinkInfo .= " | ";
|
||||
if($del_link != "")
|
||||
$actionLinkInfo .= "<a href='javascript:confirmdelete(\"".
|
||||
addslashes(urlencode($del_link))."\")'>".getTranslatedString("LNK_DELETE",
|
||||
$module)."</a>";
|
||||
}
|
||||
// Record Change Notification
|
||||
if(method_exists($focus, 'isViewed') &&
|
||||
PerformancePrefs::getBoolean('LISTVIEW_RECORD_CHANGE_INDICATOR', true)) {
|
||||
if(!$focus->isViewed($recordId)) {
|
||||
$actionLinkInfo .= " | <img src='" . vtiger_imageurl('important1.gif',
|
||||
$theme) . "' border=0>";
|
||||
}
|
||||
}
|
||||
// END
|
||||
if($actionLinkInfo != "" && !$skipActions) {
|
||||
$row[] = $actionLinkInfo;
|
||||
}
|
||||
$data[$recordId] = $row;
|
||||
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getListViewEditLink($module,$recordId, $activityType='') {
|
||||
if($module == 'Emails')
|
||||
return 'javascript:;" onclick="OpenCompose(\''.$recordId.'\',\'edit\');';
|
||||
if($module != 'Calendar') {
|
||||
$return_action = "index";
|
||||
} else {
|
||||
$return_action = 'ListView';
|
||||
}
|
||||
//Added to fix 4600
|
||||
$url = getBasic_Advance_SearchURL();
|
||||
$parent = getParentTab();
|
||||
//Appending view name while editing from ListView
|
||||
$link = "index.php?module=$module&action=EditView&record=$recordId&return_module=$module".
|
||||
"&return_action=$return_action&parenttab=$parent".$url."&return_viewname=".
|
||||
$_SESSION['lvs'][$module]["viewname"];
|
||||
|
||||
if($module == 'Calendar') {
|
||||
if($activityType == 'Task') {
|
||||
$link .= '&activity_mode=Task';
|
||||
} else {
|
||||
$link .= '&activity_mode=Events';
|
||||
}
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
|
||||
public function getListViewDeleteLink($module,$recordId) {
|
||||
$parenttab = getParentTab();
|
||||
$viewname = $_SESSION['lvs'][$module]['viewname'];
|
||||
//Added to fix 4600
|
||||
$url = getBasic_Advance_SearchURL();
|
||||
if($module == "Calendar")
|
||||
$return_action = "ListView";
|
||||
else
|
||||
$return_action = "index";
|
||||
//This is added to avoid the del link in Product related list for the following modules
|
||||
$link = "index.php?module=$module&action=Delete&record=$recordId".
|
||||
"&return_module=$module&return_action=$return_action".
|
||||
"&parenttab=$parenttab&return_viewname=".$viewname.$url;
|
||||
|
||||
// vtlib customization: override default delete link for custom modules
|
||||
$requestModule = vtlib_purify($_REQUEST['module']);
|
||||
$requestRecord = vtlib_purify($_REQUEST['record']);
|
||||
$requestAction = vtlib_purify($_REQUEST['action']);
|
||||
$requestFile = vtlib_purify($_REQUEST['file']);
|
||||
$isCustomModule = vtlib_isCustomModule($requestModule);
|
||||
|
||||
if($isCustomModule && (!in_array($requestAction, Array('index','ListView')) &&
|
||||
($requestAction == $requestModule.'Ajax' && !in_array($requestFile, Array('index','ListView'))))) {
|
||||
|
||||
$link = "index.php?module=$requestModule&action=updateRelations&parentid=$requestRecord";
|
||||
$link .= "&destination_module=$module&idlist=$entity_id&mode=delete&parenttab=$parenttab";
|
||||
}
|
||||
// END
|
||||
return $link;
|
||||
}
|
||||
|
||||
public function getListViewHeader($focus, $module,$sort_qry='',$sorder='',$orderBy='',
|
||||
$skipActions=false) {
|
||||
global $log, $singlepane_view;
|
||||
global $theme;
|
||||
|
||||
$arrow='';
|
||||
$qry = getURLstring($focus);
|
||||
$theme_path="themes/".$theme."/";
|
||||
$image_path=$theme_path."images/";
|
||||
$header = Array();
|
||||
|
||||
//Get the vtiger_tabid of the module
|
||||
$tabid = getTabid($module);
|
||||
$tabname = getParentTab();
|
||||
global $current_user;
|
||||
|
||||
require('user_privileges/user_privileges_'.$current_user->id.'.php');
|
||||
$fields = $this->queryGenerator->getFields();
|
||||
$whereFields = $this->queryGenerator->getWhereFields();
|
||||
$meta = $this->queryGenerator->getMeta($this->queryGenerator->getModule());
|
||||
|
||||
$moduleFields = $meta->getModuleFields();
|
||||
$accessibleFieldList = array_keys($moduleFields);
|
||||
$listViewFields = array_intersect($fields, $accessibleFieldList);
|
||||
//Added on 14-12-2005 to avoid if and else check for every list
|
||||
//vtiger_field for arrow image and change order
|
||||
$change_sorder = array('ASC'=>'DESC','DESC'=>'ASC');
|
||||
$arrow_gif = array('ASC'=>'arrow_down.gif','DESC'=>'arrow_up.gif');
|
||||
foreach($listViewFields as $fieldName) {
|
||||
$field = $moduleFields[$fieldName];
|
||||
|
||||
if(in_array($field->getColumnName(),$focus->sortby_fields)) {
|
||||
if($orderBy == $field->getColumnName()) {
|
||||
$temp_sorder = $change_sorder[$sorder];
|
||||
$arrow = " <img src ='".vtiger_imageurl($arrow_gif[$sorder], $theme)."' border='0'>";
|
||||
} else {
|
||||
$temp_sorder = 'ASC';
|
||||
}
|
||||
$label = getTranslatedString($field->getFieldLabelKey(), $module);
|
||||
//added to display vtiger_currency symbol in listview header
|
||||
if($label =='Amount') {
|
||||
$label .=' ('.getTranslatedString('LBL_IN', $module).' '.
|
||||
$user_info['currency_symbol'].')';
|
||||
}
|
||||
if($field->getUIType() == '9') {
|
||||
$label .=' (%)';
|
||||
}
|
||||
if($module == 'Users' && $fieldName == 'User Name') {
|
||||
$name = "<a href='javascript:;' onClick='getListViewEntries_js(\"".$module.
|
||||
"\",\"parenttab=".$tabname."&order_by=".$field->getColumnName()."&sorder=".
|
||||
$temp_sorder.$sort_qry."\");' class='listFormHeaderLinks'>".
|
||||
getTranslatedString('LBL_LIST_USER_NAME_ROLE',$module)."".$arrow."</a>";
|
||||
} else {
|
||||
if($this->isHeaderSortingEnabled()) {
|
||||
$name = "<a href='javascript:;' onClick='getListViewEntries_js(\"".$module.
|
||||
"\",\"parenttab=".$tabname."&foldername=Default&order_by=".$field->getColumnName()."&start=".
|
||||
$_SESSION["lvs"][$module]["start"]."&sorder=".$temp_sorder."".
|
||||
$sort_qry."\");' class='listFormHeaderLinks'>".$label."".$arrow."</a>";
|
||||
|
||||
} else {
|
||||
$name = $label;
|
||||
}
|
||||
}
|
||||
$arrow = '';
|
||||
} else {
|
||||
$name = getTranslatedString($field->getFieldLabelKey(), $module);
|
||||
}
|
||||
//added to display vtiger_currency symbol in related listview header
|
||||
if($name =='Amount') {
|
||||
$name .=' ('.getTranslatedString('LBL_IN').' '.$user_info['currency_symbol'].')';
|
||||
}
|
||||
|
||||
$header[]=$name;
|
||||
}
|
||||
|
||||
//Added for Action - edit and delete link header in listview
|
||||
if(!$skipActions && (isPermitted($module,"EditView","") == 'yes' ||
|
||||
isPermitted($module,"Delete","") == 'yes'))
|
||||
$header[] = getTranslatedString("LBL_ACTION", $module);
|
||||
return $header;
|
||||
}
|
||||
|
||||
public function getBasicSearchFieldInfoList() {
|
||||
$fields = $this->queryGenerator->getFields();
|
||||
$whereFields = $this->queryGenerator->getWhereFields();
|
||||
$meta = $this->queryGenerator->getMeta($this->queryGenerator->getModule());
|
||||
|
||||
$moduleFields = $meta->getModuleFields();
|
||||
$accessibleFieldList = array_keys($moduleFields);
|
||||
$listViewFields = array_intersect($fields, $accessibleFieldList);
|
||||
$basicSearchFieldInfoList = array();
|
||||
foreach ($listViewFields as $fieldName) {
|
||||
$field = $moduleFields[$fieldName];
|
||||
$basicSearchFieldInfoList[$fieldName] = getTranslatedString($field->getFieldLabelKey(),
|
||||
$this->queryGenerator->getModule());
|
||||
}
|
||||
return $basicSearchFieldInfoList;
|
||||
}
|
||||
|
||||
public function getAdvancedSearchOptionString() {
|
||||
$module = $this->queryGenerator->getModule();
|
||||
$meta = $this->queryGenerator->getMeta($module);
|
||||
|
||||
$moduleFields = $meta->getModuleFields();
|
||||
$i =0;
|
||||
foreach ($moduleFields as $fieldName=>$field) {
|
||||
if($field->getFieldDataType() == 'reference') {
|
||||
$typeOfData = 'V';
|
||||
} else if($field->getFieldDataType() == 'boolean') {
|
||||
$typeOfData = 'C';
|
||||
} else {
|
||||
$typeOfData = $field->getTypeOfData();
|
||||
$typeOfData = explode("~",$typeOfData);
|
||||
$typeOfData = $typeOfData[0];
|
||||
}
|
||||
$label = getTranslatedString($field->getFieldLabelKey(), $module);
|
||||
if(empty($label)) {
|
||||
$label = $field->getFieldLabelKey();
|
||||
}
|
||||
if($label == "Start Date & Time") {
|
||||
$fieldlabel = "Start Date";
|
||||
}
|
||||
$selected = '';
|
||||
if($i++ == 0) {
|
||||
$selected = "selected";
|
||||
}
|
||||
|
||||
// place option in array for sorting later
|
||||
//$blockName = getTranslatedString(getBlockName($field->getBlockId()), $module);
|
||||
$blockName = getTranslatedString($field->getBlockName(), $module);
|
||||
|
||||
$fieldLabelEscaped = str_replace(" ","_",$field->getFieldLabelKey());
|
||||
$optionvalue = $field->getTableName().":".$field->getColumnName().":".$fieldName.":".$module."_".$fieldLabelEscaped.":".$typeOfData;
|
||||
|
||||
$OPTION_SET[$blockName][$label] = "<option value=\'$optionvalue\' $selected>$label</option>";
|
||||
|
||||
}
|
||||
// sort array on block label
|
||||
ksort($OPTION_SET, SORT_STRING);
|
||||
|
||||
foreach ($OPTION_SET as $key=>$value) {
|
||||
$shtml .= "<optgroup label='$key' class='select' style='border:none'>";
|
||||
// sort array on field labels
|
||||
ksort($value, SORT_STRING);
|
||||
$shtml .= implode('',$value);
|
||||
}
|
||||
|
||||
return $shtml;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,86 @@
|
|||
<?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.
|
||||
*********************************************************************************/
|
||||
global $app_strings, $mod_strings, $current_language, $currentModule, $theme;
|
||||
global $list_max_entries_per_page;
|
||||
|
||||
require_once('Smarty_setup.php');
|
||||
require_once('include/ListView/ListView.php');
|
||||
require_once('modules/CustomView/CustomView.php');
|
||||
require_once('include/DatabaseUtil.php');
|
||||
|
||||
checkFileAccessForInclusion("modules/$currentModule/$currentModule.php");
|
||||
require_once("modules/$currentModule/$currentModule.php");
|
||||
if(!is_string($_SESSION[$currentModule.'_listquery']) || !empty($_REQUEST['globalSearch'])){
|
||||
// Custom View
|
||||
$customView = new CustomView($currentModule);
|
||||
$viewid = $customView->getViewId($currentModule);
|
||||
$customview_html = $customView->getCustomViewCombo($viewid);
|
||||
$viewinfo = $customView->getCustomViewByCvid($viewid);
|
||||
|
||||
if($viewid != "0"&& $viewid != 0){
|
||||
$listquery = getListQuery($currentModule);
|
||||
$list_query= $customView->getModifiedCvListQuery($viewid, $listquery, $currentModule);
|
||||
}else{
|
||||
$list_query = getListQuery($currentModule);
|
||||
}
|
||||
// Enabling Module Search
|
||||
$url_string = '';
|
||||
if($_REQUEST['query'] == 'true') {
|
||||
if(!empty($_REQUEST['tagSearchText'])){
|
||||
$searchValue = vtlib_purify($_REQUEST['globalSearchText']);
|
||||
$where = '(' . getTagWhere($searchValue, $current_user->id) . ')';
|
||||
} else if(!empty($_REQUEST['globalSearch'])){
|
||||
$searchValue = vtlib_purify($_REQUEST['globalSearchText']);
|
||||
$where = '(' . getUnifiedWhere($list_query,$currentModule,$searchValue) . ')';
|
||||
$url_string .= '&query=true&globalSearch=true&globalSearchText='.$searchValue;
|
||||
}else{
|
||||
list($where, $ustring) = split('#@@#', getWhereCondition($currentModule));
|
||||
$url_string .= "&query=true$ustring";
|
||||
}
|
||||
}
|
||||
//print_r($where);
|
||||
if($where != '') {
|
||||
$list_query = "$list_query AND $where";
|
||||
$_SESSION['export_where'] = $where;
|
||||
}else{
|
||||
unset($_SESSION['export_where']);
|
||||
}
|
||||
// Sorting
|
||||
if($order_by) {
|
||||
if($order_by == 'smownerid'){
|
||||
if( $adb->dbType == "pgsql"){
|
||||
$list_query .= ' GROUP BY user_name';
|
||||
}
|
||||
$list_query .= ' ORDER BY user_name '.$sorder;
|
||||
}else {
|
||||
$tablename = getTableNameForField($currentModule, $order_by);
|
||||
$tablename = ($tablename != '')? ($tablename . '.') : '';
|
||||
if( $adb->dbType == "pgsql"){
|
||||
$list_query .= ' GROUP BY '. $tablename . $order_by;
|
||||
}
|
||||
$list_query .= ' ORDER BY ' . $tablename . $order_by . ' ' . $sorder;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//TODO: remove after calendar module listview cleanup.
|
||||
//its failing for calendar module.
|
||||
$dummyQuery = getListQuery($currentModule);
|
||||
$list_query = $_SESSION[$currentModule.'_listquery'];
|
||||
}
|
||||
|
||||
$count_result = $adb->query(mkCountQuery($list_query));
|
||||
$noofrows = $adb->query_result($count_result,0,"count");
|
||||
|
||||
$pageNumber = ceil($noofrows/$list_max_entries_per_page);
|
||||
if($pageNumber == 0){
|
||||
$pageNumber = 1;
|
||||
}
|
||||
echo $app_strings['LBL_LIST_OF'].' '.$pageNumber;
|
||||
?>
|
|
@ -0,0 +1,218 @@
|
|||
<?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/logging.php');
|
||||
require_once('modules/CustomView/CustomView.php');
|
||||
|
||||
class ListViewSession {
|
||||
|
||||
var $module = null;
|
||||
var $viewname = null;
|
||||
var $start = null;
|
||||
var $sorder = null;
|
||||
var $sortby = null;
|
||||
var $page_view = null;
|
||||
|
||||
/**initializes ListViewSession
|
||||
* Portions created by vtigerCRM are Copyright (C) vtigerCRM.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
function ListViewSession()
|
||||
{
|
||||
global $log,$currentModule;
|
||||
$log->debug("Entering ListViewSession() method ...");
|
||||
|
||||
$this->module = $currentModule;
|
||||
$this->sortby = 'ASC';
|
||||
$this->start =1;
|
||||
}
|
||||
|
||||
function getCurrentPage($currentModule,$viewId){
|
||||
if(!empty($_SESSION['lvs'][$currentModule][$viewId]['start'])){
|
||||
return $_SESSION['lvs'][$currentModule][$viewId]['start'];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
function getRequestStartPage(){
|
||||
$start = $_REQUEST['start'];
|
||||
if(!is_numeric($start)){
|
||||
$start = 1;
|
||||
}
|
||||
if($start < 1){
|
||||
$start = 1;
|
||||
}
|
||||
$start = ceil($start);
|
||||
return $start;
|
||||
}
|
||||
|
||||
function getListViewNavigation($currentRecordId){
|
||||
global $currentModule,$current_user,$adb,$log,$list_max_entries_per_page;
|
||||
Zend_Json::$useBuiltinEncoderDecoder = true;
|
||||
$reUseData = false;
|
||||
$displayBufferRecordCount = 10;
|
||||
$bufferRecordCount = 15;
|
||||
if($currentModule == 'Documents'){
|
||||
$sql = "select folderid from vtiger_notes where notesid=?";
|
||||
$params = array($currentRecordId);
|
||||
$result = $adb->pquery($sql,$params);
|
||||
$folderId = $adb->query_result($result,0,'folderid');
|
||||
}
|
||||
$cv = new CustomView();
|
||||
$viewId = $cv->getViewId($currentModule);
|
||||
if(!empty($_SESSION[$currentModule.'_DetailView_Navigation'.$viewId])){
|
||||
$recordNavigationInfo = Zend_Json::decode($_SESSION[$currentModule.'_DetailView_Navigation'.$viewId]);
|
||||
$pageNumber =0;
|
||||
if(count($recordNavigationInfo) == 1){
|
||||
foreach ($recordNavigationInfo as $recordIdList) {
|
||||
if(in_array($currentRecordId,$recordIdList)){
|
||||
$reUseData = true;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$recordList = array();
|
||||
$recordPageMapping = array();
|
||||
foreach ($recordNavigationInfo as $start=>$recordIdList){
|
||||
foreach ($recordIdList as $index=>$recordId) {
|
||||
$recordList[] = $recordId;
|
||||
$recordPageMapping[$recordId] = $start;
|
||||
if($recordId == $currentRecordId){
|
||||
$searchKey = count($recordList)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($searchKey > $displayBufferRecordCount -1 && $searchKey < count($recordList)-$displayBufferRecordCount){
|
||||
$reUseData= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($reUseData === false){
|
||||
$recordNavigationInfo = array();
|
||||
if(!empty($_REQUEST['start'])){
|
||||
$start = ListViewSession::getRequestStartPage();
|
||||
}else{
|
||||
$start = ListViewSession::getCurrentPage($currentModule,$viewId);
|
||||
}
|
||||
$startRecord = (($start - 1) * $list_max_entries_per_page) - $bufferRecordCount;
|
||||
if($startRecord < 0){
|
||||
$startRecord = 0;
|
||||
}
|
||||
|
||||
$list_query = $_SESSION[$currentModule.'_listquery'];
|
||||
$instance = CRMEntity::getInstance($currentModule);
|
||||
$instance->getNonAdminAccessControlQuery($currentModule, $current_user);
|
||||
vtlib_setup_modulevars($currentModule, $instance);
|
||||
if($currentModule=='Documents' && !empty($folderId)){
|
||||
$list_query = preg_replace("/[\n\r\s]+/"," ",$list_query);
|
||||
$list_query .= " AND vtiger_notes.folderid=$folderId";
|
||||
$order_by = $instance->getOrderByForFolder($folderId);
|
||||
$sorder = $instance->getSortOrderForFolder($folderId);
|
||||
$tablename = getTableNameForField($currentModule,$order_by);
|
||||
$tablename = (($tablename != '')?($tablename."."):'');
|
||||
if(!empty($order_by)){
|
||||
$list_query .= ' ORDER BY '.$tablename.$order_by.' '.$sorder;
|
||||
}
|
||||
}
|
||||
if($start !=1){
|
||||
$recordCount = ($list_max_entries_per_page+2 * $bufferRecordCount);
|
||||
}else{
|
||||
$recordCount = ($list_max_entries_per_page+ $bufferRecordCount);
|
||||
}
|
||||
if( $adb->dbType == "pgsql"){
|
||||
$list_query .= " OFFSET $startRecord LIMIT $recordCount";
|
||||
}else{
|
||||
$list_query .= " LIMIT $startRecord, $recordCount";
|
||||
}
|
||||
|
||||
$resultAllCRMIDlist_query=$adb->pquery($list_query,array());
|
||||
$navigationRecordList = array();
|
||||
while($forAllCRMID = $adb->fetch_array($resultAllCRMIDlist_query)) {
|
||||
$navigationRecordList[] = $forAllCRMID[$instance->table_index];
|
||||
}
|
||||
|
||||
$pageCount = 0;
|
||||
$current = $start;
|
||||
if($start ==1){
|
||||
$firstPageRecordCount = $list_max_entries_per_page;
|
||||
}else{
|
||||
$firstPageRecordCount = $bufferRecordCount;
|
||||
$current -=1;
|
||||
}
|
||||
|
||||
$searchKey = array_search($currentRecordId,$navigationRecordList);
|
||||
$recordNavigationInfo = array();
|
||||
if($searchKey !== false){
|
||||
foreach ($navigationRecordList as $index => $recordId) {
|
||||
if(!is_array($recordNavigationInfo[$current])){
|
||||
$recordNavigationInfo[$current] = array();
|
||||
}
|
||||
if($index == $firstPageRecordCount || $index == ($firstPageRecordCount+$pageCount * $list_max_entries_per_page)){
|
||||
$current++;
|
||||
$pageCount++;
|
||||
}
|
||||
$recordNavigationInfo[$current][] = $recordId;
|
||||
}
|
||||
}
|
||||
$_SESSION[$currentModule.'_DetailView_Navigation'.$viewId] =
|
||||
Zend_Json::encode($recordNavigationInfo);
|
||||
}
|
||||
return $recordNavigationInfo;
|
||||
}
|
||||
|
||||
function getRequestCurrentPage($currentModule, $query, $viewid, $queryMode = false) {
|
||||
global $list_max_entries_per_page, $adb;
|
||||
$start = 1;
|
||||
if(isset($_REQUEST['query']) && $_REQUEST['query'] == 'true'&& $_REQUEST['start']!="last"){
|
||||
return ListViewSession::getRequestStartPage();
|
||||
}
|
||||
if(!empty($_REQUEST['start'])){
|
||||
$start = $_REQUEST['start'];
|
||||
if($start == 'last'){
|
||||
$count_result = $adb->query( mkCountQuery( $query));
|
||||
$noofrows = $adb->query_result($count_result,0,"count");
|
||||
if($noofrows > 0){
|
||||
$start = ceil($noofrows/$list_max_entries_per_page);
|
||||
}
|
||||
}
|
||||
if(!is_numeric($start)){
|
||||
$start = 1;
|
||||
}elseif($start < 1){
|
||||
$start = 1;
|
||||
}
|
||||
$start = ceil($start);
|
||||
}else if(!empty($_SESSION['lvs'][$currentModule][$viewid]['start'])){
|
||||
$start = $_SESSION['lvs'][$currentModule][$viewid]['start'];
|
||||
}
|
||||
if(!$queryMode) {
|
||||
$_SESSION['lvs'][$currentModule][$viewid]['start'] = intval($start);
|
||||
}
|
||||
return $start;
|
||||
}
|
||||
|
||||
function setSessionQuery($currentModule,$query,$viewid){
|
||||
if(isset($_SESSION[$currentModule.'_listquery'])){
|
||||
if($_SESSION[$currentModule.'_listquery'] != $query){
|
||||
unset($_SESSION[$currentModule.'_DetailView_Navigation'.$viewid]);
|
||||
}
|
||||
}
|
||||
$_SESSION[$currentModule.'_listquery'] = $query;
|
||||
}
|
||||
|
||||
function hasViewChanged($currentModule) {
|
||||
if(empty($_SESSION['lvs'][$currentModule]['viewname'])) return true;
|
||||
if(empty($_REQUEST['viewname'])) return false;
|
||||
if($_REQUEST['viewname'] != $_SESSION['lvs'][$currentModule]['viewname']) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,93 @@
|
|||
<?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.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
/**
|
||||
* @author MAK
|
||||
*/
|
||||
|
||||
if($ajaxaction == "LOADRELATEDLIST") {
|
||||
global $relationId;
|
||||
$relationId = vtlib_purify($_REQUEST['relation_id']);
|
||||
if(!empty($relationId) && ((int)$relationId) > 0) {
|
||||
$recordid = vtlib_purify($_REQUEST['record']);
|
||||
if($_SESSION['rlvs'][$currentModule][$relationId]['currentRecord'] != $recordid) {
|
||||
$resetCookie = true;
|
||||
} else {
|
||||
$resetCookie = false;
|
||||
}
|
||||
$_SESSION['rlvs'][$currentModule][$relationId]['currentRecord'] = $recordid;
|
||||
$actions = vtlib_purify($_REQUEST['actions']);
|
||||
$header = vtlib_purify($_REQUEST['header']);
|
||||
$modObj->id = $recordid;
|
||||
$relationInfo = getRelatedListInfoById($relationId);
|
||||
$relatedModule = getTabModuleName($relationInfo['relatedTabId']);
|
||||
$function_name = $relationInfo['functionName'];
|
||||
|
||||
$relatedListData = $modObj->$function_name($recordid, getTabid($currentModule),
|
||||
$relationInfo['relatedTabId'], $actions);
|
||||
require_once('Smarty_setup.php');
|
||||
global $theme, $mod_strings, $app_strings;
|
||||
$theme_path="themes/".$theme."/";
|
||||
$image_path=$theme_path."images/";
|
||||
|
||||
$smarty = new vtigerCRM_Smarty;
|
||||
// vtlib customization: Related module could be disabled, check it
|
||||
if(is_array($relatedListData)) {
|
||||
if( ($relatedModule == "Contacts" || $relatedModule == "Leads" ||
|
||||
$relatedModule == "Accounts") && $currentModule == 'Campaigns' &&
|
||||
!$resetCookie) {
|
||||
//TODO for 5.3 this should be COOKIE not REQUEST, change here else where
|
||||
// this logic is used for listview checkbox selection propogation.
|
||||
$checkedRecordIdString = $_REQUEST[$relatedModule.'_all'];
|
||||
$checkedRecordIdString = rtrim($checkedRecordIdString);
|
||||
$checkedRecordIdList = explode(';', $checkedRecordIdString);
|
||||
$relatedListData["checked"]=array();
|
||||
if (isset($relatedListData['entries'])) {
|
||||
foreach($relatedListData['entries'] as $key=>$val) {
|
||||
if(in_array($key,$checkedRecordIdList)) {
|
||||
$relatedListData["checked"][$key] = 'checked';
|
||||
} else {
|
||||
$relatedListData["checked"][$key] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
$smarty->assign("SELECTED_RECORD_LIST", $checkedRecordIdString);
|
||||
} else {
|
||||
$smarty->assign('RESET_COOKIE', $resetCookie);
|
||||
}
|
||||
}
|
||||
// END
|
||||
require_once('include/ListView/RelatedListViewSession.php');
|
||||
RelatedListViewSession::addRelatedModuleToSession($relationId,$header);
|
||||
|
||||
$smarty->assign("MOD", $mod_strings);
|
||||
$smarty->assign("APP", $app_strings);
|
||||
$smarty->assign("THEME", $theme);
|
||||
$smarty->assign("IMAGE_PATH", $image_path);
|
||||
$smarty->assign("ID",$recordid);
|
||||
$smarty->assign("MODULE",$currentModule);
|
||||
$smarty->assign("RELATED_MODULE",$relatedModule);
|
||||
$smarty->assign("HEADER",$header);
|
||||
$smarty->assign("RELATEDLISTDATA", $relatedListData);
|
||||
|
||||
$smarty->display("RelatedListDataContents.tpl");
|
||||
}
|
||||
}else if($ajaxaction == "DISABLEMODULE"){
|
||||
$relationId = vtlib_purify($_REQUEST['relation_id']);
|
||||
if(!empty($relationId) && ((int)$relationId) > 0) {
|
||||
$header = vtlib_purify($_REQUEST['header']);
|
||||
require_once('include/ListView/RelatedListViewSession.php');
|
||||
RelatedListViewSession::removeRelatedModuleFromSession($relationId,$header);
|
||||
}
|
||||
echo "SUCCESS";
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,116 @@
|
|||
<?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/logging.php');
|
||||
require_once('include/ListView/ListViewSession.php');
|
||||
|
||||
/**initializes Related ListViewSession
|
||||
* Portions created by vtigerCRM are Copyright (C) vtigerCRM.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
class RelatedListViewSession {
|
||||
|
||||
var $module = null;
|
||||
var $start = null;
|
||||
var $sorder = null;
|
||||
var $sortby = null;
|
||||
var $page_view = null;
|
||||
|
||||
function RelatedListViewSession() {
|
||||
global $log,$currentModule;
|
||||
$log->debug("Entering RelatedListViewSession() method ...");
|
||||
|
||||
$this->module = $currentModule;
|
||||
$this->start =1;
|
||||
}
|
||||
|
||||
public static function addRelatedModuleToSession($relationId, $header) {
|
||||
global $currentModule;
|
||||
$_SESSION['relatedlist'][$currentModule][$relationId] = $header;
|
||||
$start = RelatedListViewSession::getRequestStartPage();
|
||||
RelatedListViewSession::saveRelatedModuleStartPage($relationId, $start);
|
||||
}
|
||||
|
||||
public static function removeRelatedModuleFromSession($relationId, $header) {
|
||||
global $currentModule;
|
||||
|
||||
unset($_SESSION['relatedlist'][$currentModule][$relationId]);
|
||||
}
|
||||
|
||||
public static function getRelatedModulesFromSession() {
|
||||
global $currentModule;
|
||||
|
||||
$allRelatedModuleList = isPresentRelatedLists($currentModule);
|
||||
$moduleList = array();
|
||||
if(is_array($_SESSION['relatedlist'][$currentModule])){
|
||||
foreach ($allRelatedModuleList as $relationId=>$label) {
|
||||
if(array_key_exists($relationId, $_SESSION['relatedlist'][$currentModule])){
|
||||
$moduleList[] = $_SESSION['relatedlist'][$currentModule][$relationId];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $moduleList;
|
||||
}
|
||||
|
||||
public static function saveRelatedModuleStartPage($relationId, $start) {
|
||||
global $currentModule;
|
||||
|
||||
$_SESSION['rlvs'][$currentModule][$relationId]['start'] = $start;
|
||||
}
|
||||
|
||||
public static function getCurrentPage($relationId) {
|
||||
global $currentModule;
|
||||
|
||||
if(!empty($_SESSION['rlvs'][$currentModule][$relationId]['start'])){
|
||||
return $_SESSION['rlvs'][$currentModule][$relationId]['start'];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static function getRequestStartPage(){
|
||||
$start = $_REQUEST['start'];
|
||||
if(!is_numeric($start)){
|
||||
$start = 1;
|
||||
}
|
||||
if($start < 1){
|
||||
$start = 1;
|
||||
}
|
||||
$start = ceil($start);
|
||||
return $start;
|
||||
}
|
||||
|
||||
public static function getRequestCurrentPage($relationId, $query) {
|
||||
global $list_max_entries_per_page, $adb;
|
||||
|
||||
$start = 1;
|
||||
if(!empty($_REQUEST['start'])){
|
||||
$start = $_REQUEST['start'];
|
||||
if($start == 'last'){
|
||||
$count_result = $adb->query( mkCountQuery( $query));
|
||||
$noofrows = $adb->query_result($count_result,0,"count");
|
||||
if($noofrows > 0){
|
||||
$start = ceil($noofrows/$list_max_entries_per_page);
|
||||
}
|
||||
}
|
||||
if(!is_numeric($start)){
|
||||
$start = 1;
|
||||
}elseif($start < 1){
|
||||
$start = 1;
|
||||
}
|
||||
$start = ceil($start);
|
||||
}else {
|
||||
$start = RelatedListViewSession::getCurrentPage($relationId);
|
||||
}
|
||||
return $start;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
/*********************************************************************************
|
||||
* The contents of this file are subject to the SugarCRM Public License Version 1.1.2
|
||||
* ("License"); You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at http://www.sugarcrm.com/SPL
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
* the specific language governing rights and limitations under the License.
|
||||
* The Original Code is: SugarCRM Open Source
|
||||
* The Initial Developer of the Original Code is SugarCRM, Inc.
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.;
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
********************************************************************************/
|
||||
/*********************************************************************************
|
||||
* $Header$
|
||||
* Description: TODO To be written.
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________..
|
||||
********************************************************************************/
|
||||
|
||||
global $mod_strings;
|
||||
global $app_strings;
|
||||
global $moduleList;
|
||||
|
||||
require_once('include/utils/utils.php');
|
||||
require_once('include/utils/UserInfoUtil.php');
|
||||
|
||||
|
||||
$module_menu_array = Array('Contacts' => $app_strings['LNK_NEW_CONTACT'],
|
||||
'Leads'=> $app_strings['LNK_NEW_LEAD'],
|
||||
'Accounts' => $app_strings['LNK_NEW_ACCOUNT'],
|
||||
'Potentials' => $app_strings['LNK_NEW_OPPORTUNITY'],
|
||||
'HelpDesk' => $app_strings['LNK_NEW_HDESK'],
|
||||
'Faq' => $app_strings['LNK_NEW_FAQ'],
|
||||
'Products' => $app_strings['LNK_NEW_PRODUCT'],
|
||||
'Documents' => $app_strings['LNK_NEW_NOTE'],
|
||||
'Emails' => $app_strings['LNK_NEW_EMAIL'],
|
||||
'Events' => $app_strings['LNK_NEW_EVENT'],
|
||||
'Tasks' => $app_strings['LNK_NEW_TASK'],
|
||||
'Vendor' => $app_strings['LNK_NEW_VENDOR'],
|
||||
'PriceBook' => $app_strings['LNK_NEW_PRICEBOOK'],
|
||||
'Quotes' => $app_strings['LNK_NEW_QUOTE'],
|
||||
'PurchaseOrder' => $app_strings['LNK_NEW_PO'],
|
||||
'SalesOrder' => $app_strings['LNK_NEW_SO'],
|
||||
'Invoice' => $app_strings['LNK_NEW_INVOICE']
|
||||
);
|
||||
$module_menu = Array();
|
||||
$i= 0;
|
||||
$add_url = "";
|
||||
foreach($module_menu_array as $module1 => $label)
|
||||
{
|
||||
$add_url='';
|
||||
$curr_action = 'EditView';
|
||||
$ret_action = 'DetailView';
|
||||
if($module1 == 'Events')
|
||||
{
|
||||
$module_display = 'Activities';
|
||||
$add_url = "&activity_mode=Events";
|
||||
$tabid = getTabid($module1);
|
||||
}
|
||||
elseif($module1 == 'Tasks')
|
||||
{
|
||||
$module_display = 'Activities';
|
||||
$add_url = "&activity_mode=Task";
|
||||
$tabid = getTabid("Activities");
|
||||
}
|
||||
else
|
||||
{
|
||||
$module_display = $module1;
|
||||
$tabid = getTabid($module1);
|
||||
}
|
||||
|
||||
if(in_array($module_display, $moduleList))
|
||||
{
|
||||
|
||||
if(isPermitted($module_display,'EditView') == 'yes')
|
||||
{
|
||||
$tempArray = Array("index.php?module=".$module_display."&action=".$curr_action."&return_module=".$module_display."&return_action=".$ret_action.$add_url, $label);
|
||||
$module_menu[$i] = $tempArray;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
elseif($module_display == 'Faq')
|
||||
{
|
||||
$tempArray = Array("index.php?module=".$module_display."&action=".$curr_action."&return_module=".$module_display."&return_action=".$ret_action.$add_url, $label);
|
||||
$module_menu[$i] = $tempArray;
|
||||
$i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,161 @@
|
|||
<?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('config.php');
|
||||
require_once('include/logging.php');
|
||||
require_once('include/language/en_us.lang.php');
|
||||
require_once('include/database/PearDatabase.php');
|
||||
require_once('include/ComboStrings.php');
|
||||
require_once('include/ComboUtil.php');
|
||||
/**
|
||||
* Class which handles the population of the combo values
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PopulateComboValues
|
||||
{
|
||||
var $app_list_strings;
|
||||
|
||||
|
||||
/**
|
||||
* To populate the default combo values for the combo vtiger_tables
|
||||
* @param $values -- values:: Type string array
|
||||
* @param $tableName -- tablename:: Type string
|
||||
*/
|
||||
function insertComboValues($values, $tableName,$picklistid)
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering insertComboValues(".$values.", ".$tableName.") method ...");
|
||||
global $adb;
|
||||
//inserting the value in the vtiger_picklistvalues_seq for the getting uniqueID for each picklist values...
|
||||
$i=0;
|
||||
foreach ($values as $val => $cal)
|
||||
{
|
||||
$picklist_valueid = getUniquePicklistID();
|
||||
$id = $adb->getUniqueID('vtiger_'.$tableName);
|
||||
if($val != '')
|
||||
{
|
||||
$params = array($id, $val, 1, $picklist_valueid);
|
||||
$adb->pquery("insert into vtiger_$tableName values(?,?,?,?)", $params);
|
||||
}
|
||||
else
|
||||
{
|
||||
$params = array($id, '--None--', 1, $picklist_valueid);
|
||||
$adb->pquery("insert into vtiger_$tableName values(?,?,?,?)", $params);
|
||||
}
|
||||
|
||||
//Default entries for role2picklist relation has been inserted..
|
||||
|
||||
$sql="select roleid from vtiger_role";
|
||||
$role_result = $adb->pquery($sql, array());
|
||||
$numrow = $adb->num_rows($role_result);
|
||||
for($k=0; $k < $numrow; $k ++)
|
||||
{
|
||||
$roleid = $adb->query_result($role_result,$k,'roleid');
|
||||
$params = array($roleid, $picklist_valueid, $picklistid, $i);
|
||||
$adb->pquery("insert into vtiger_role2picklist values(?,?,?,?)", $params);
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
|
||||
$log->debug("Exiting insertComboValues method ...");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* To populate the combo vtiger_tables at startup time
|
||||
*/
|
||||
|
||||
function create_tables ()
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering create_tables () method ...");
|
||||
|
||||
global $app_list_strings,$adb;
|
||||
global $combo_strings;
|
||||
$comboRes = $adb->query("SELECT distinct fieldname FROM vtiger_field WHERE uitype IN ('15') OR fieldname = 'salutationtype' and vtiger_field.presence in (0,2)");
|
||||
$noOfCombos = $adb->num_rows($comboRes);
|
||||
for($i=0; $i<$noOfCombos; $i++)
|
||||
{
|
||||
$comTab = $adb->query_result($comboRes, $i, 'fieldname');
|
||||
$picklistid = $adb->getUniqueID("vtiger_picklist");
|
||||
$params = array($picklistid, $comTab);
|
||||
$picklist_qry = "insert into vtiger_picklist values(?,?)";
|
||||
$adb->pquery($picklist_qry, $params);
|
||||
|
||||
$this->insertComboValues($combo_strings[$comTab."_dom"],$comTab,$picklistid);
|
||||
}
|
||||
|
||||
//we have to decide what are all the picklist and picklist values are non editable
|
||||
//presence = 0 means you cannot edit the picklist value
|
||||
//presence = 1 means you can edit the picklist value
|
||||
$noneditable_tables = Array("ticketstatus","taskstatus","eventstatus","faqstatus","quotestage","postatus","sostatus","invoicestatus","activitytype");
|
||||
$noneditable_values = Array(
|
||||
"Closed Won"=>"sales_stage",
|
||||
"Closed Lost"=>"sales_stage",
|
||||
);
|
||||
foreach($noneditable_tables as $picklistname)
|
||||
{
|
||||
$adb->pquery("update vtiger_".$picklistname." set PRESENCE=0", array());
|
||||
}
|
||||
foreach($noneditable_values as $picklistname => $value)
|
||||
{
|
||||
$adb->pquery("update vtiger_$value set PRESENCE=0 where $value=?", array($picklistname));
|
||||
}
|
||||
|
||||
$log->debug("Exiting create_tables () method ...");
|
||||
|
||||
}
|
||||
|
||||
|
||||
function create_nonpicklist_tables ()
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering create_nonpicklist_tables () method ...");
|
||||
|
||||
global $app_list_strings,$adb;
|
||||
global $combo_strings;
|
||||
// uitype -> 16 - Non standard picklist, 115 - User status, 83 - Tax Class
|
||||
$comboRes = $adb->query("SELECT distinct fieldname FROM vtiger_field WHERE uitype IN ('16','115','83') AND fieldname NOT IN ('hdnTaxType','email_flag') and vtiger_field.presence in (0,2)");
|
||||
$noOfCombos = $adb->num_rows($comboRes);
|
||||
for($i=0; $i<$noOfCombos; $i++)
|
||||
{
|
||||
$comTab = $adb->query_result($comboRes, $i, 'fieldname');
|
||||
$this->insertNonPicklistValues($combo_strings[$comTab."_dom"],$comTab);
|
||||
}
|
||||
$log->debug("Exiting create_tables () method ...");
|
||||
}
|
||||
function insertNonPicklistValues($values, $tableName)
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering insertNonPicklistValues(".$values.", ".$tableName.") method ...");
|
||||
global $adb;
|
||||
$i=0;
|
||||
foreach ($values as $val => $cal)
|
||||
{
|
||||
$id = $adb->getUniqueID('vtiger_'.$tableName);
|
||||
if($val != '')
|
||||
{
|
||||
$params = array($id, $val, $i ,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$params = array($id, '--None--', $i ,1);
|
||||
}
|
||||
$adb->pquery("insert into vtiger_$tableName values(?,?,?,?)", $params);
|
||||
$i++;
|
||||
}
|
||||
$log->debug("Exiting insertNonPicklistValues method ...");
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,660 @@
|
|||
<?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/utils/UserInfoUtil.php');
|
||||
require_once("include/utils/utils.php");
|
||||
require_once("include/ListView/ListViewSession.php");
|
||||
require_once("include/ListView/RelatedListViewSession.php");
|
||||
require_once("include/DatabaseUtil.php");
|
||||
|
||||
if(!function_exists('GetRelatedList')) {
|
||||
function GetRelatedList($module,$relatedmodule,$focus,$query,$button,$returnset,$id='',
|
||||
$edit_val='',$del_val='',$skipActions=false) {
|
||||
return GetRelatedListBase($module, $relatedmodule, $focus, $query, $button, $returnset, $id, $edit_val, $del_val, $skipActions);
|
||||
}
|
||||
}
|
||||
|
||||
/** Function to get related list entries in detailed array format
|
||||
* @param $module -- modulename:: Type string
|
||||
* @param $relatedmodule -- relatedmodule:: Type string
|
||||
* @param $focus -- focus:: Type object
|
||||
* @param $query -- query:: Type string
|
||||
* @param $button -- buttons:: Type string
|
||||
* @param $returnset -- returnset:: Type string
|
||||
* @param $id -- id:: Type string
|
||||
* @param $edit_val -- edit value:: Type string
|
||||
* @param $del_val -- delete value:: Type string
|
||||
* @returns $related_entries -- related entires:: Type string array
|
||||
*
|
||||
*/
|
||||
|
||||
function GetRelatedListBase($module,$relatedmodule,$focus,$query,$button,$returnset,$id='',$edit_val='',$del_val='',$skipActions=false)
|
||||
{
|
||||
$log = LoggerManager::getLogger('account_list');
|
||||
$log->debug("Entering GetRelatedList(".$module.",".$relatedmodule.",".get_class($focus).",".$query.",".$button.",".$returnset.",".$edit_val.",".$del_val.") method ...");
|
||||
|
||||
require_once('Smarty_setup.php');
|
||||
require_once("data/Tracker.php");
|
||||
require_once('include/database/PearDatabase.php');
|
||||
|
||||
global $adb;
|
||||
global $app_strings;
|
||||
global $current_language;
|
||||
|
||||
$current_module_strings = return_module_language($current_language, $module);
|
||||
|
||||
global $list_max_entries_per_page;
|
||||
global $urlPrefix;
|
||||
|
||||
|
||||
global $currentModule;
|
||||
global $theme;
|
||||
global $theme_path;
|
||||
global $theme_path;
|
||||
global $mod_strings;
|
||||
// focus_list is the means of passing data to a ListView.
|
||||
global $focus_list;
|
||||
$smarty = new vtigerCRM_Smarty;
|
||||
if (!isset($where)) $where = "";
|
||||
|
||||
|
||||
$button = '<table cellspacing=0 cellpadding=2><tr><td>'.$button.'</td></tr></table>';
|
||||
|
||||
// Added to have Purchase Order as form Title
|
||||
$theme_path="themes/".$theme."/";
|
||||
$image_path=$theme_path."images/";
|
||||
$smarty->assign("MOD", $mod_strings);
|
||||
$smarty->assign("APP", $app_strings);
|
||||
$smarty->assign("THEME", $theme);
|
||||
$smarty->assign("IMAGE_PATH",$image_path);
|
||||
$smarty->assign("MODULE",$relatedmodule);
|
||||
|
||||
// We do not have RelatedListView in Detail View mode of Calendar module. So need to skip it.
|
||||
if ($module!= 'Calendar') {
|
||||
$focus->initSortByField($relatedmodule);
|
||||
}
|
||||
//Retreive the list from Database
|
||||
//Appending the security parameter Security fix by Don
|
||||
if($relatedmodule != 'Faq' && $relatedmodule != 'PriceBook'
|
||||
&& $relatedmodule != 'Vendors' && $relatedmodule != 'Users') {
|
||||
global $current_user;
|
||||
$secQuery = getNonAdminAccessControlQuery($relatedmodule, $current_user);
|
||||
if(strlen($secQuery) > 1) {
|
||||
$query = appendFromClauseToQuery($query, $secQuery);
|
||||
}
|
||||
}
|
||||
if($relatedmodule == 'Leads') {
|
||||
$query .= " AND vtiger_leaddetails.converted = 0";
|
||||
}
|
||||
|
||||
|
||||
if(isset($where) && $where != '')
|
||||
{
|
||||
$query .= ' and '.$where;
|
||||
}
|
||||
|
||||
if(!$_SESSION['rlvs'][$module][$relatedmodule])
|
||||
{
|
||||
$modObj = new ListViewSession();
|
||||
$modObj->sortby = $focus->default_order_by;
|
||||
$modObj->sorder = $focus->default_sort_order;
|
||||
$_SESSION['rlvs'][$module][$relatedmodule] = get_object_vars($modObj);
|
||||
}
|
||||
|
||||
if(!empty($_REQUEST['order_by'])) {
|
||||
if(method_exists($focus,getSortOrder))
|
||||
$sorder = $focus->getSortOrder();
|
||||
if(method_exists($focus,getOrderBy))
|
||||
$order_by = $focus->getOrderBy();
|
||||
|
||||
if(isset($order_by) && $order_by != '') {
|
||||
$_SESSION['rlvs'][$module][$relatedmodule]['sorder'] = $sorder;
|
||||
$_SESSION['rlvs'][$module][$relatedmodule]['sortby'] = $order_by;
|
||||
}
|
||||
|
||||
} elseif($_SESSION['rlvs'][$module][$relatedmodule]) {
|
||||
$sorder = $_SESSION['rlvs'][$module][$relatedmodule]['sorder'];
|
||||
$order_by = $_SESSION['rlvs'][$module][$relatedmodule]['sortby'];
|
||||
} else {
|
||||
$order_by = $focus->default_order_by;
|
||||
$sorder = $focus->default_sort_order;
|
||||
}
|
||||
|
||||
//Added by Don for AssignedTo ordering issue in Related Lists
|
||||
$query_order_by = $order_by;
|
||||
if($order_by == 'smownerid') {
|
||||
$userNameSql = getSqlForNameInDisplayFormat(array('first_name'=>'vtiger_users.first_name',
|
||||
'last_name' => 'vtiger_users.last_name'), 'Users');
|
||||
$query_order_by = "case when (vtiger_users.user_name not like '') then $userNameSql else vtiger_groups.groupname end ";
|
||||
} elseif($order_by != 'crmid' && !empty($order_by)) {
|
||||
$tabname = getTableNameForField($relatedmodule, $order_by);
|
||||
if($tabname !== '' and $tabname != NULL)
|
||||
$query_order_by = $tabname.".".$query_order_by;
|
||||
}
|
||||
if(!empty($query_order_by)){
|
||||
$query .= ' ORDER BY '.$query_order_by.' '.$sorder;
|
||||
}
|
||||
|
||||
if($relatedmodule == 'Calendar')
|
||||
$mod_listquery = "activity_listquery";
|
||||
else
|
||||
$mod_listquery = strtolower($relatedmodule)."_listquery";
|
||||
$_SESSION[$mod_listquery] = $query;
|
||||
|
||||
$url_qry .="&order_by=".$order_by."&sorder=".$sorder;
|
||||
$computeCount = $_REQUEST['withCount'];
|
||||
if(PerformancePrefs::getBoolean('LISTVIEW_COMPUTE_PAGE_COUNT', false) === true ||
|
||||
(boolean) $computeCount == true){
|
||||
//Retreiving the no of rows
|
||||
if($relatedmodule == "Calendar") {
|
||||
//for calendar related list, count will increase when we have multiple contacts
|
||||
//relationship for single activity
|
||||
$count_query = mkCountQuery($query);
|
||||
$count_result = $adb->query($count_query);
|
||||
$noofrows =$adb->query_result($count_result,0,"count");
|
||||
} else {
|
||||
$count_query = mkCountQuery($query);
|
||||
$count_result = $adb->query($count_query);
|
||||
|
||||
if($adb->num_rows($count_result) > 0)
|
||||
$noofrows =$adb->query_result($count_result,0,"count");
|
||||
else
|
||||
$noofrows = $adb->num_rows($count_result);
|
||||
}
|
||||
}else{
|
||||
$noofrows = null;
|
||||
}
|
||||
|
||||
//Setting Listview session object while sorting/pagination
|
||||
if(isset($_REQUEST['relmodule']) && $_REQUEST['relmodule']!='' && $_REQUEST['relmodule'] == $relatedmodule)
|
||||
{
|
||||
$relmodule = vtlib_purify($_REQUEST['relmodule']);
|
||||
if($_SESSION['rlvs'][$module][$relmodule])
|
||||
{
|
||||
setSessionVar($_SESSION['rlvs'][$module][$relmodule],$noofrows,$list_max_entries_per_page,$module,$relmodule);
|
||||
}
|
||||
}
|
||||
global $relationId;
|
||||
$start = RelatedListViewSession::getRequestCurrentPage($relationId, $query);
|
||||
$navigation_array = VT_getSimpleNavigationValues($start, $list_max_entries_per_page,
|
||||
$noofrows);
|
||||
|
||||
$limit_start_rec = ($start-1) * $list_max_entries_per_page;
|
||||
|
||||
if( $adb->dbType == "pgsql")
|
||||
$list_result = $adb->pquery($query.
|
||||
" OFFSET $limit_start_rec LIMIT $list_max_entries_per_page", array());
|
||||
else
|
||||
$list_result = $adb->pquery($query.
|
||||
" LIMIT $limit_start_rec, $list_max_entries_per_page", array());
|
||||
|
||||
//Retreive the List View Table Header
|
||||
$id = vtlib_purify($_REQUEST['record']);
|
||||
$listview_header = getListViewHeader($focus,$relatedmodule,'',$sorder,$order_by,$id,'',$module,$skipActions);//"Accounts");
|
||||
if ($noofrows > 15) {
|
||||
$smarty->assign('SCROLLSTART','<div style="overflow:auto;height:315px;width:100%;">');
|
||||
$smarty->assign('SCROLLSTOP','</div>');
|
||||
}
|
||||
$smarty->assign("LISTHEADER", $listview_header);
|
||||
|
||||
if($module == 'PriceBook' && $relatedmodule == 'Products') {
|
||||
$listview_entries = getListViewEntries($focus,$relatedmodule,$list_result,$navigation_array,'relatedlist',$returnset,$edit_val,$del_val,'','','','',$skipActions);
|
||||
}
|
||||
if($module == 'Products' && $relatedmodule == 'PriceBook') {
|
||||
$listview_entries = getListViewEntries($focus,$relatedmodule,$list_result,$navigation_array,'relatedlist',$returnset,'EditListPrice','DeletePriceBookProductRel','','','','',$skipActions);
|
||||
} elseif($relatedmodule == 'SalesOrder') {
|
||||
$listview_entries = getListViewEntries($focus,$relatedmodule,$list_result,$navigation_array,'relatedlist',$returnset,'SalesOrderEditView','DeleteSalesOrder','','','','',$skipActions);
|
||||
}else {
|
||||
$listview_entries = getListViewEntries($focus,$relatedmodule,$list_result,$navigation_array,'relatedlist',$returnset,$edit_val,$del_val,'','','','',$skipActions);
|
||||
}
|
||||
|
||||
$navigationOutput = Array();
|
||||
$navigationOutput[] = getRecordRangeMessage($list_result, $limit_start_rec,$noofrows);
|
||||
if(empty($id) && !empty($_REQUEST['record'])) $id = vtlib_purify($_REQUEST['record']);
|
||||
$navigationOutput[] = getRelatedTableHeaderNavigation($navigation_array, $url_qry,$module,$relatedmodule,$id);
|
||||
|
||||
$related_entries = array('header'=>$listview_header,'entries'=>$listview_entries,'navigation'=>$navigationOutput);
|
||||
|
||||
$log->debug("Exiting GetRelatedList method ...");
|
||||
return $related_entries;
|
||||
}
|
||||
|
||||
/** Function to get related list entries in detailed array format
|
||||
* @param $parentmodule -- parentmodulename:: Type string
|
||||
* @param $query -- query:: Type string
|
||||
* @param $id -- id:: Type string
|
||||
* @returns $entries_list -- entries list:: Type string array
|
||||
*
|
||||
*/
|
||||
|
||||
function getAttachmentsAndNotes($parentmodule,$query,$id,$sid='')
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering getAttachmentsAndNotes(".$parentmodule.",".$query.",".$id.",".$sid.") method ...");
|
||||
global $theme;
|
||||
|
||||
$list = '<script>
|
||||
function confirmdelete(url)
|
||||
{
|
||||
if(confirm("'.$app_strings['ARE_YOU_SURE'].'"))
|
||||
{
|
||||
document.location.href=url;
|
||||
}
|
||||
}
|
||||
</script>';
|
||||
|
||||
$theme_path="themes/".$theme."/";
|
||||
$image_path=$theme_path."images/";
|
||||
|
||||
global $adb,$current_user;
|
||||
global $mod_strings;
|
||||
global $app_strings, $listview_max_textlength;
|
||||
|
||||
$result=$adb->query($query);
|
||||
$noofrows = $adb->num_rows($result);
|
||||
|
||||
$_SESSION['Documents_listquery'] = $query;
|
||||
$header[] = $app_strings['LBL_TITLE'];
|
||||
$header[] = $app_strings['LBL_DESCRIPTION'];
|
||||
$header[] = $app_strings['LBL_ATTACHMENTS'];
|
||||
$header[] = $app_strings['LBL_ASSIGNED_TO'];
|
||||
$header[] = $app_strings['LBL_ACTION'];
|
||||
|
||||
if($result)
|
||||
{
|
||||
while($row = $adb->fetch_array($result))
|
||||
{
|
||||
if($row['activitytype'] == 'Attachments') {
|
||||
$query1="select setype,createdtime from vtiger_crmentity where crmid=?";
|
||||
$params1 = array($row['attachmentsid']);
|
||||
} else {
|
||||
$query1="select setype,createdtime from vtiger_crmentity where crmid=?";
|
||||
$params1 = array($row['crmid']);
|
||||
}
|
||||
|
||||
$query1 .=" order by createdtime desc";
|
||||
$res=$adb->pquery($query1, $params1);
|
||||
$num_rows = $adb->num_rows($res);
|
||||
for($i=0; $i<$num_rows; $i++)
|
||||
{
|
||||
$setype = $adb->query_result($res,$i,'setype');
|
||||
$createdtime = $adb->query_result($res,$i,'createdtime');
|
||||
}
|
||||
|
||||
if(($setype != "Products Image") && ($setype != "Contacts Image"))
|
||||
{
|
||||
$entries = Array();
|
||||
if(trim($row['activitytype']) == 'Documents')
|
||||
{
|
||||
$module = 'Documents';
|
||||
$editaction = 'EditView';
|
||||
$deleteaction = 'Delete';
|
||||
}
|
||||
elseif($row['activitytype'] == 'Attachments')
|
||||
{
|
||||
$module = 'uploads';
|
||||
$editaction = 'upload';
|
||||
$deleteaction = 'deleteattachments';
|
||||
}
|
||||
if($module == 'Documents')
|
||||
{
|
||||
$entries[] = '<a href="index.php?module='.$module.'&action=DetailView&return_module='.$parentmodule.'&return_action='.$return_action.'&record='.$row["crmid"].'&filename='.$row['filename'].'&fileid='.$row['attachmentsid'].'&return_id='.vtlib_purify($_REQUEST["record"]).'&parenttab='.vtlib_purify($_REQUEST["parenttab"]).'">'.textlength_check($row['title']).'</a>';
|
||||
}
|
||||
elseif($module == 'uploads')
|
||||
{
|
||||
$entries[] = $row['title'];
|
||||
}
|
||||
if((getFieldVisibilityPermission('Documents', $current_user->id, 'notecontent') == '0') || $row['activitytype'] == 'Documents')
|
||||
{
|
||||
$row['description'] = preg_replace("/(<\/?)(\w+)([^>]*>)/i","",$row['description']);
|
||||
if($listview_max_textlength && (strlen($row['description']) > $listview_max_textlength))
|
||||
{
|
||||
$row['description'] = substr($row['description'],0,$listview_max_textlength).'...';
|
||||
}
|
||||
$entries[] = nl2br($row['description']);
|
||||
}
|
||||
else
|
||||
$entries[] = " <font color ='red' >" .$app_strings['LBL_NOT_ACCESSIBLE']."</font>";
|
||||
|
||||
$attachmentname = $row['filename'];//explode('_',$row['filename'],2);
|
||||
|
||||
if((getFieldVisibilityPermission('Documents', $current_user->id, 'filename') == 0))
|
||||
{
|
||||
global $adb;
|
||||
|
||||
$prof_id = fetchUserProfileId($current_user->id);
|
||||
$modulepermissionQuery = "select permissions from vtiger_profile2tab where tabid=8 and profileid= ?";
|
||||
$modulepermissionresult = $adb->pquery($modulepermissionQuery,array($prof_id));
|
||||
$moduleviewpermission = $adb->query_result($modulepermissionresult,0,'permissions');
|
||||
|
||||
$folderQuery = 'select folderid,filelocationtype,filestatus,filename from vtiger_notes where notesid = ?';
|
||||
$folderresult = $adb->pquery($folderQuery,array($row["crmid"]));
|
||||
$folder_id = $adb->query_result($folderresult,0,'folderid');
|
||||
$download_type = $adb->query_result($folderresult,0,'filelocationtype');
|
||||
$filestatus = $adb->query_result($folderresult,0,'filestatus');
|
||||
$filename = $adb->query_result($folderresult,0,'filename');
|
||||
|
||||
$fileQuery = $adb->pquery("select attachmentsid from vtiger_seattachmentsrel where crmid = ?",array($row['crmid']));
|
||||
$fileid = $adb->query_result($fileQuery,0,'attachmentsid');
|
||||
if($moduleviewpermission == 0)
|
||||
{
|
||||
if($download_type == 'I' )
|
||||
{
|
||||
if($filestatus == 1 )
|
||||
$entries[] = '<a href="index.php?module=Documents&action=DownloadFile&fileid='.$fileid.'&folderid='.$folder_id.'">'.textlength_check($attachmentname).'</a>';
|
||||
elseif(isset($attachmentname) && $attachmentname != '')
|
||||
$entries[] = textlength_check($attachmentname);
|
||||
else
|
||||
$entries[] = ' --';
|
||||
}
|
||||
elseif($download_type == 'E' )
|
||||
{
|
||||
if($filestatus == 1)
|
||||
$entries[] = '<a target="_blank" href="'.$filename.'" onClick="javascript:dldCntIncrease('.$row['crmid'].');">'.textlength_check($attachmentname).'</a>';
|
||||
elseif(isset($attachmentname) && $attachmentname != '')
|
||||
$entries[] = textlength_check($attachmentname);
|
||||
else
|
||||
$entries[] = ' --';
|
||||
}
|
||||
else{
|
||||
$entries[] = ' --';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isset($attachmentname))
|
||||
$entries[] = textlength_check($attachmentname);
|
||||
else
|
||||
$entries[] = ' --';
|
||||
}
|
||||
}
|
||||
else
|
||||
$entries[]='';
|
||||
|
||||
$assignedToQuery = $adb->pquery('SELECT smownerid FROM vtiger_crmentity WHERE crmid = ?',array($row['crmid']));
|
||||
$assignedTo = $adb->query_result($assignedToQuery,0,'smownerid');
|
||||
if($assignedTo != '' ){
|
||||
$entries[] = $assignedTo;
|
||||
}
|
||||
$del_param = 'index.php?module='.$module.'&action='.$deleteaction.'&return_module='.$parentmodule.'&return_action='.vtlib_purify($_REQUEST['action']).'&record='.$row["crmid"].'&return_id='.vtlib_purify($_REQUEST["record"]).'&parenttab='.vtlib_purify($_REQUEST["parenttab"]);
|
||||
|
||||
if($module == 'Documents')
|
||||
{
|
||||
$edit_param = 'index.php?module='.$module.'&action='.$editaction.'&return_module='.$parentmodule.'&return_action='.vtlib_purify($_REQUEST['action']).'&record='.$row["crmid"].'&filename='.$row['filename'].'&fileid='.$row['attachmentsid'].'&return_id='.vtlib_purify($_REQUEST["record"]).'&parenttab='.vtlib_purify($_REQUEST["parenttab"]);
|
||||
|
||||
$entries[] .= '<a href="'.$edit_param.'">'.$app_strings['LNK_EDIT'].'</a> | <a href=\'javascript:confirmdelete("'.$del_param.'")\'>'.$app_strings['LNK_DELETE'].'</a>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$entries[] = '<a href=\'javascript:confirmdelete("'.$del_param.'")\'>'.$app_strings['LNK_DELETE'].'</a>';
|
||||
}
|
||||
$entries_list[] = $entries;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($entries_list != '')
|
||||
$return_data = array('header'=>$header,'entries'=>$entries_list);
|
||||
$log->debug("Exiting getAttachmentsAndNotes method ...");
|
||||
return $return_data;
|
||||
|
||||
}
|
||||
|
||||
/** Function to get related list entries in detailed array format
|
||||
* @param $parentmodule -- parentmodulename:: Type string
|
||||
* @param $query -- query:: Type string
|
||||
* @param $id -- id:: Type string
|
||||
* @returns $return_data -- return data:: Type string array
|
||||
*
|
||||
*/
|
||||
|
||||
function getHistory($parentmodule,$query,$id)
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering getHistory(".$parentmodule.",".$query.",".$id.") method ...");
|
||||
$parentaction = vtlib_purify($_REQUEST['action']);
|
||||
global $theme;
|
||||
$theme_path="themes/".$theme."/";
|
||||
$image_path=$theme_path."images/";
|
||||
|
||||
global $adb;
|
||||
global $mod_strings;
|
||||
global $app_strings;
|
||||
|
||||
//Appending the security parameter
|
||||
global $current_user;
|
||||
$rel_tab_id = getTabid("Calendar");
|
||||
|
||||
global $current_user;
|
||||
require('user_privileges/user_privileges_'.$current_user->id.'.php');
|
||||
require('user_privileges/sharing_privileges_'.$current_user->id.'.php');
|
||||
$tab_id = getTabid('Calendar');
|
||||
if($is_admin == false && $profileGlobalPermission[1] == 1 && $profileGlobalPermission[2] == 1 && $defaultOrgSharingPermission[$tab_id] == 3)
|
||||
{
|
||||
$sec_parameter=getListViewSecurityParameter('Calendar');
|
||||
$query .= ' '.$sec_parameter;
|
||||
}
|
||||
$query.= ' '."ORDER BY vtiger_activity.date_start DESC,vtiger_activity.time_start DESC";
|
||||
$result=$adb->query($query);
|
||||
$noofrows = $adb->num_rows($result);
|
||||
|
||||
if($noofrows == 0)
|
||||
{
|
||||
//There is no entries for history
|
||||
}
|
||||
else
|
||||
{
|
||||
//Form the header columns
|
||||
$header[] = $app_strings['LBL_TYPE'];
|
||||
$header[] = $app_strings['LBL_SUBJECT'];
|
||||
$header[] = $app_strings['LBL_RELATED_TO'];
|
||||
$header[] = $app_strings['LBL_START_DATE']." & ".$app_strings['LBL_TIME'];
|
||||
$header[] = $app_strings['LBL_END_DATE']." & ".$app_strings['LBL_TIME'];
|
||||
//$header[] = $app_strings['LBL_DESCRIPTION'];
|
||||
$header[] = $app_strings['LBL_STATUS'];
|
||||
$header[] = $app_strings['LBL_ASSIGNED_TO'];
|
||||
|
||||
$i = 1;
|
||||
while($row = $adb->fetch_array($result))
|
||||
{
|
||||
$entries = Array();
|
||||
if($row['activitytype'] == 'Task')
|
||||
{
|
||||
$activitymode = 'Task';
|
||||
$icon = 'Tasks.gif';
|
||||
$status = $row['status'];
|
||||
$status = $app_strings[$status];
|
||||
}
|
||||
else
|
||||
{
|
||||
$activitymode = 'Events';
|
||||
$icon = 'Activities.gif';
|
||||
$status = $row['eventstatus'];
|
||||
$status = $app_strings[$status];
|
||||
}
|
||||
|
||||
$typeofactivity = $row['activitytype'];
|
||||
$typeofactivity = getTranslatedString($typeofactivity, 'Calendar');
|
||||
$entries[] = $typeofactivity;
|
||||
|
||||
$activity = '<a href="index.php?module=Calendar&action=DetailView&return_module='.$parentmodule.'&return_action=DetailView&record='.$row["activityid"] .'&activity_mode='.$activitymode.'&return_id='.vtlib_purify($_REQUEST['record']).'&parenttab='.vtlib_purify($_REQUEST['parenttab']).'">'.$row['subject'].'</a></td>';
|
||||
$entries[] = $activity;
|
||||
|
||||
$parentname = getRelatedTo('Calendar',$result,$i-1);
|
||||
$entries[] = $parentname;
|
||||
|
||||
$date = new DateTimeField($row['date_start']." ".$row['time_start']);
|
||||
$entries[] = $date->getDisplayDateTimeValue();
|
||||
$date = new DateTimeField($row['due_date']." ".$row['time_end']);
|
||||
$entries[] = $date->getDisplayDate();
|
||||
|
||||
$entries[] = $status;
|
||||
|
||||
if($row['user_name'] == null && $row['groupname'] != null)
|
||||
{
|
||||
$entries[] = $row['groupname'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$entries[] = $row['user_name'];
|
||||
}
|
||||
|
||||
$i++;
|
||||
$entries_list[] = $entries;
|
||||
}
|
||||
|
||||
$return_data = array('header'=>$header,'entries'=>$entries_list);
|
||||
$log->debug("Exiting getHistory method ...");
|
||||
return $return_data;
|
||||
}
|
||||
}
|
||||
|
||||
/** Function to display the Products which are related to the PriceBook
|
||||
* @param string $query - query to get the list of products which are related to the current PriceBook
|
||||
* @param object $focus - PriceBook object which contains all the information of the current PriceBook
|
||||
* @param string $returnset - return_module, return_action and return_id which are sequenced with & to pass to the URL which is optional
|
||||
* return array $return_data which will be formed like array('header'=>$header,'entries'=>$entries_list) where as $header contains all the header columns and $entries_list will contain all the Product entries
|
||||
*/
|
||||
function getPriceBookRelatedProducts($query,$focus,$returnset='')
|
||||
{
|
||||
global $log;
|
||||
$log->debug("Entering getPriceBookRelatedProducts(".$query.",".get_class($focus).",".$returnset.") method ...");
|
||||
|
||||
global $adb;
|
||||
global $app_strings;
|
||||
global $mod_strings;
|
||||
global $current_language,$current_user;
|
||||
$current_module_strings = return_module_language($current_language, 'PriceBook');
|
||||
|
||||
global $list_max_entries_per_page;
|
||||
global $urlPrefix;
|
||||
|
||||
global $theme;
|
||||
$pricebook_id = vtlib_purify($_REQUEST['record']);
|
||||
$theme_path="themes/".$theme."/";
|
||||
$image_path=$theme_path."images/";
|
||||
|
||||
$computeCount = $_REQUEST['withCount'];
|
||||
if(PerformancePrefs::getBoolean('LISTVIEW_COMPUTE_PAGE_COUNT', false) === true ||
|
||||
((boolean) $computeCount) == true){
|
||||
$noofrows = $adb->query_result($adb->query(mkCountQuery($query)),0,'count');
|
||||
}else{
|
||||
$noofrows = null;
|
||||
}
|
||||
|
||||
$module = 'PriceBooks';
|
||||
$relatedmodule = 'Products';
|
||||
if(!$_SESSION['rlvs'][$module][$relatedmodule])
|
||||
{
|
||||
$modObj = new ListViewSession();
|
||||
$modObj->sortby = $focus->default_order_by;
|
||||
$modObj->sorder = $focus->default_sort_order;
|
||||
$_SESSION['rlvs'][$module][$relatedmodule] = get_object_vars($modObj);
|
||||
}
|
||||
|
||||
|
||||
if(isset($_REQUEST['relmodule']) && $_REQUEST['relmodule']!='' && $_REQUEST['relmodule'] == $relatedmodule) {
|
||||
$relmodule = vtlib_purify($_REQUEST['relmodule']);
|
||||
if($_SESSION['rlvs'][$module][$relmodule]) {
|
||||
setSessionVar($_SESSION['rlvs'][$module][$relmodule],$noofrows,$list_max_entries_per_page,$module,$relmodule);
|
||||
}
|
||||
}
|
||||
global $relationId;
|
||||
$start = RelatedListViewSession::getRequestCurrentPage($relationId, $query);
|
||||
$navigation_array = VT_getSimpleNavigationValues($start, $list_max_entries_per_page,
|
||||
$noofrows);
|
||||
|
||||
$limit_start_rec = ($start-1) * $list_max_entries_per_page;
|
||||
|
||||
if( $adb->dbType == "pgsql")
|
||||
$list_result = $adb->pquery($query.
|
||||
" OFFSET $limit_start_rec LIMIT $list_max_entries_per_page", array());
|
||||
else
|
||||
$list_result = $adb->pquery($query.
|
||||
" LIMIT $limit_start_rec, $list_max_entries_per_page", array());
|
||||
|
||||
$header=array();
|
||||
$header[]=$mod_strings['LBL_LIST_PRODUCT_NAME'];
|
||||
if(getFieldVisibilityPermission('Products', $current_user->id, 'productcode') == '0')
|
||||
$header[]=$mod_strings['LBL_PRODUCT_CODE'];
|
||||
if(getFieldVisibilityPermission('Products', $current_user->id, 'unit_price') == '0')
|
||||
$header[]=$mod_strings['LBL_PRODUCT_UNIT_PRICE'];
|
||||
$header[]=$mod_strings['LBL_PB_LIST_PRICE'];
|
||||
if(isPermitted("PriceBooks","EditView","") == 'yes' || isPermitted("PriceBooks","Delete","") == 'yes')
|
||||
$header[]=$mod_strings['LBL_ACTION'];
|
||||
|
||||
$currency_id = $focus->column_fields['currency_id'];
|
||||
$numRows = $adb->num_rows($list_result);
|
||||
for($i=0; $i<$numRows; $i++) {
|
||||
$entity_id = $adb->query_result($list_result,$i,"crmid");
|
||||
$unit_price = $adb->query_result($list_result,$i,"unit_price");
|
||||
if($currency_id != null) {
|
||||
$prod_prices = getPricesForProducts($currency_id, array($entity_id));
|
||||
$unit_price = $prod_prices[$entity_id];
|
||||
}
|
||||
$listprice = $adb->query_result($list_result,$i,"listprice");
|
||||
$field_name=$entity_id."_listprice";
|
||||
|
||||
$entries = Array();
|
||||
$entries[] = textlength_check($adb->query_result($list_result,$i,"productname"));
|
||||
if(getFieldVisibilityPermission('Products', $current_user->id, 'productcode') == '0')
|
||||
$entries[] = $adb->query_result($list_result,$i,"productcode");
|
||||
if(getFieldVisibilityPermission('Products', $current_user->id, 'unit_price') == '0')
|
||||
$entries[] = CurrencyField::convertToUserFormat($unit_price, null, true);
|
||||
|
||||
$entries[] = CurrencyField::convertToUserFormat($listprice, null, true);
|
||||
$action = "";
|
||||
if(isPermitted("PriceBooks","EditView","") == 'yes' && isPermitted('Products', 'EditView', $entity_id) == 'yes') {
|
||||
$action .= '<img style="cursor:pointer;" src="'. vtiger_imageurl('editfield.gif', $theme).'" border="0" onClick="fnvshobj(this,\'editlistprice\'),editProductListPrice(\''.$entity_id.'\',\''.$pricebook_id.'\',\''.$listprice.'\')" alt="'.$app_strings["LBL_EDIT_BUTTON"].'" title="'.$app_strings["LBL_EDIT_BUTTON"].'"/>';
|
||||
} else {
|
||||
$action .= '<img src="'. vtiger_imageurl('blank.gif', $theme).'" border="0" />';
|
||||
}
|
||||
if(isPermitted("PriceBooks","Delete","") == 'yes' && isPermitted('Products', 'Delete', $entity_id) == 'yes') {
|
||||
if($action != "")
|
||||
$action .= ' | ';
|
||||
$action .= '<img src="'. vtiger_imageurl('delete.gif', $theme).'" onclick="if(confirm(\''.$app_strings['ARE_YOU_SURE'].'\')) deletePriceBookProductRel('.$entity_id.','.$pricebook_id.');" alt="'.$app_strings["LBL_DELETE"].'" title="'.$app_strings["LBL_DELETE"].'" style="cursor:pointer;" border="0">';
|
||||
}
|
||||
if($action != "")
|
||||
$entries[] = $action;
|
||||
$entries_list[] = $entries;
|
||||
}
|
||||
$navigationOutput[] = getRecordRangeMessage($list_result, $limit_start_rec,$noofrows);
|
||||
$navigationOutput[] = getRelatedTableHeaderNavigation($navigation_array, '',$module,
|
||||
$relatedmodule,$focus->id);
|
||||
$return_data = array('header'=>$header,'entries'=>$entries_list,'navigation'=>$navigationOutput);
|
||||
|
||||
$log->debug("Exiting getPriceBookRelatedProducts method ...");
|
||||
return $return_data;
|
||||
}
|
||||
|
||||
function CheckFieldPermission($fieldname,$module) {
|
||||
global $current_user,$adb;
|
||||
require('user_privileges/user_privileges_'.$current_user->id.'.php');
|
||||
if($fieldname == '' || $module == '') {
|
||||
return "false";
|
||||
}
|
||||
|
||||
if(getFieldVisibilityPermission($module, $current_user->id, $fieldname) == '0') {
|
||||
return "true";
|
||||
}
|
||||
return "false";
|
||||
}
|
||||
|
||||
function CheckColumnPermission($tablename, $columnname, $module)
|
||||
{
|
||||
global $adb;
|
||||
|
||||
$res = $adb->pquery("select fieldname from vtiger_field where tablename=? and columnname=? and vtiger_field.presence in (0,2)", array($tablename, $columnname));
|
||||
$fieldname = $adb->query_result($res, 0, 'fieldname');
|
||||
return CheckFieldPermission($fieldname, $module);
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,31 @@
|
|||
<?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 vtws_getchallenge($username){
|
||||
|
||||
global $adb;
|
||||
|
||||
$user = new Users();
|
||||
$userid = $user->retrieve_user_id($username);
|
||||
$authToken = uniqid();
|
||||
|
||||
$servertime = time();
|
||||
$expireTime = time()+(60*5);
|
||||
|
||||
$sql = "delete from vtiger_ws_userauthtoken where userid=?";
|
||||
$adb->pquery($sql,array($userid));
|
||||
|
||||
$sql = "insert into vtiger_ws_userauthtoken(userid,token,expireTime) values (?,?,?)";
|
||||
$adb->pquery($sql,array($userid,$authToken,$expireTime));
|
||||
|
||||
return array("token"=>$authToken,"serverTime"=>$servertime,"expireTime"=>$expireTime);
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,70 @@
|
|||
<?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.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
/**
|
||||
* @author Musavir Ahmed Khan<musavir at vtiger.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param WebserviceId $id
|
||||
* @param String $oldPassword
|
||||
* @param String $newPassword
|
||||
* @param String $confirmPassword
|
||||
* @param Users $user
|
||||
*
|
||||
*/
|
||||
function vtws_changePassword($id, $oldPassword, $newPassword, $confirmPassword, $user) {
|
||||
vtws_preserveGlobal('current_user',$user);
|
||||
$idComponents = vtws_getIdComponents($id);
|
||||
if($idComponents[1] == $user->id || is_admin($user)) {
|
||||
$newUser = new Users();
|
||||
$newUser->retrieveCurrentUserInfoFromFile($idComponents[1]);
|
||||
if(!is_admin($user)) {
|
||||
if(empty($oldPassword)) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDOLDPASSWORD,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$INVALIDOLDPASSWORD));
|
||||
}
|
||||
if(!$user->verifyPassword($oldPassword)) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDOLDPASSWORD,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$INVALIDOLDPASSWORD));
|
||||
}
|
||||
}
|
||||
if(strcmp($newPassword, $confirmPassword) === 0) {
|
||||
$db = PearDatabase::getInstance();
|
||||
$db->dieOnError = true;
|
||||
$db->startTransaction();
|
||||
$success = $newUser->change_password($oldPassword, $newPassword, false);
|
||||
$error = $db->hasFailedTransaction();
|
||||
$db->completeTransaction();
|
||||
if($error) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
if(!$success) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$CHANGEPASSWORDFAILURE,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$CHANGEPASSWORDFAILURE));
|
||||
}
|
||||
} else {
|
||||
throw new WebServiceException(WebServiceErrorCode::$CHANGEPASSWORDFAILURE,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$CHANGEPASSWORDFAILURE));
|
||||
}
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return array('message' => 'Changed password successfully');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,266 @@
|
|||
<?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/Webservices/Retrieve.php';
|
||||
require_once 'include/Webservices/Create.php';
|
||||
require_once 'include/Webservices/Delete.php';
|
||||
require_once 'include/Webservices/DescribeObject.php';
|
||||
|
||||
function vtws_convertlead($entityvalues, $user) {
|
||||
|
||||
global $adb, $log;
|
||||
if (empty($entityvalues['assignedTo'])) {
|
||||
$entityvalues['assignedTo'] = vtws_getWebserviceEntityId('Users', $user->id);
|
||||
}
|
||||
if (empty($entityvalues['transferRelatedRecordsTo'])) {
|
||||
$entityvalues['transferRelatedRecordsTo'] = 'Contacts';
|
||||
}
|
||||
|
||||
|
||||
$leadObject = VtigerWebserviceObject::fromName($adb, 'Leads');
|
||||
$handlerPath = $leadObject->getHandlerPath();
|
||||
$handlerClass = $leadObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$leadHandler = new $handlerClass($leadObject, $user, $adb, $log);
|
||||
|
||||
|
||||
$leadInfo = vtws_retrieve($entityvalues['leadId'], $user);
|
||||
$sql = "select converted from vtiger_leaddetails where converted = 1 and leadid=?";
|
||||
$leadIdComponents = vtws_getIdComponents($entityvalues['leadId']);
|
||||
$result = $adb->pquery($sql, array($leadIdComponents[1]));
|
||||
if ($result === false) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_' .
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
if ($rowCount > 0) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$LEAD_ALREADY_CONVERTED,
|
||||
"Lead is already converted");
|
||||
}
|
||||
|
||||
$entityIds = array();
|
||||
|
||||
$availableModules = array('Accounts', 'Contacts', 'Potentials');
|
||||
|
||||
if (!(($entityvalues['entities']['Accounts']['create']) || ($entityvalues['entities']['Contacts']['create']))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($availableModules as $entityName) {
|
||||
if ($entityvalues['entities'][$entityName]['create']) {
|
||||
$entityvalue = $entityvalues['entities'][$entityName];
|
||||
$entityObject = VtigerWebserviceObject::fromName($adb, $entityvalue['name']);
|
||||
$handlerPath = $entityObject->getHandlerPath();
|
||||
$handlerClass = $entityObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$entityHandler = new $handlerClass($entityObject, $user, $adb, $log);
|
||||
|
||||
$entityObjectValues = array();
|
||||
$entityObjectValues['assigned_user_id'] = $entityvalues['assignedTo'];
|
||||
$entityObjectValues = vtws_populateConvertLeadEntities($entityvalue, $entityObjectValues, $entityHandler, $leadHandler, $leadInfo);
|
||||
|
||||
//update potential related to property
|
||||
if ($entityvalue['name'] == 'Potentials') {
|
||||
if (!empty($entityIds['Accounts'])) {
|
||||
$entityObjectValues['related_to'] = $entityIds['Accounts'];
|
||||
} else {
|
||||
$entityObjectValues['related_to'] = $entityIds['Contacts'];
|
||||
}
|
||||
}
|
||||
|
||||
//update the contacts relation
|
||||
if ($entityvalue['name'] == 'Contacts') {
|
||||
if (!empty($entityIds['Accounts'])) {
|
||||
$entityObjectValues['account_id'] = $entityIds['Accounts'];
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$create = true;
|
||||
if ($entityvalue['name'] == 'Accounts') {
|
||||
$sql = "SELECT vtiger_account.accountid FROM vtiger_account,vtiger_crmentity WHERE vtiger_crmentity.crmid=vtiger_account.accountid AND vtiger_account.accountname=? AND vtiger_crmentity.deleted=0";
|
||||
$result = $adb->pquery($sql, array($entityvalue['accountname']));
|
||||
if ($adb->num_rows($result) > 0) {
|
||||
$entityIds[$entityName] = vtws_getWebserviceEntityId('Accounts', $adb->query_result($result, 0, 'accountid'));
|
||||
$create = false;
|
||||
}
|
||||
}
|
||||
if ($create) {
|
||||
$entityRecord = vtws_create($entityvalue['name'], $entityObjectValues, $user);
|
||||
$entityIds[$entityName] = $entityRecord['id'];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$accountIdComponents = vtws_getIdComponents($entityIds['Accounts']);
|
||||
$accountId = $accountIdComponents[1];
|
||||
|
||||
$contactIdComponents = vtws_getIdComponents($entityIds['Contacts']);
|
||||
$contactId = $contactIdComponents[1];
|
||||
|
||||
if (!empty($accountId) && !empty($contactId) && !empty($entityIds['Potentials'])) {
|
||||
$potentialIdComponents = vtws_getIdComponents($entityIds['Potentials']);
|
||||
$potentialId = $potentialIdComponents[1];
|
||||
$sql = "insert into vtiger_contpotentialrel values(?,?)";
|
||||
$result = $adb->pquery($sql, array($contactId, $potentialIdComponents[1]));
|
||||
if ($result === false) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$FAILED_TO_CREATE_RELATION,
|
||||
"Failed to related Contact with the Potential");
|
||||
}
|
||||
}
|
||||
|
||||
$transfered = vtws_convertLeadTransferHandler($leadIdComponents, $entityIds, $entityvalues);
|
||||
|
||||
$relatedIdComponents = vtws_getIdComponents($entityIds[$entityvalues['transferRelatedRecordsTo']]);
|
||||
vtws_getRelatedActivities($leadIdComponents[1], $accountId, $contactId, $relatedIdComponents[1]);
|
||||
vtws_updateConvertLeadStatus($entityIds, $entityvalues['leadId'], $user);
|
||||
} catch (Exception $e) {
|
||||
foreach ($entityIds as $entity => $id) {
|
||||
vtws_delete($id, $user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return $entityIds;
|
||||
}
|
||||
|
||||
/*
|
||||
* populate the entity fields with the lead info.
|
||||
* if mandatory field is not provided populate with '????'
|
||||
* returns the entity array.
|
||||
*/
|
||||
|
||||
function vtws_populateConvertLeadEntities($entityvalue, $entity, $entityHandler, $leadHandler, $leadinfo) {
|
||||
global $adb, $log;
|
||||
$column;
|
||||
$entityName = $entityvalue['name'];
|
||||
$sql = "SELECT * FROM vtiger_convertleadmapping";
|
||||
$result = $adb->pquery($sql, array());
|
||||
if ($adb->num_rows($result)) {
|
||||
switch ($entityName) {
|
||||
case 'Accounts':$column = 'accountfid';
|
||||
break;
|
||||
case 'Contacts':$column = 'contactfid';
|
||||
break;
|
||||
case 'Potentials':$column = 'potentialfid';
|
||||
break;
|
||||
default:$column = 'leadfid';
|
||||
break;
|
||||
}
|
||||
|
||||
$leadFields = $leadHandler->getMeta()->getModuleFields();
|
||||
$entityFields = $entityHandler->getMeta()->getModuleFields();
|
||||
$row = $adb->fetch_array($result);
|
||||
$count = 1;
|
||||
do {
|
||||
$entityField = vtws_getFieldfromFieldId($row[$column], $entityFields);
|
||||
if ($entityField == null) {
|
||||
//user doesn't have access so continue.TODO update even if user doesn't have access
|
||||
continue;
|
||||
}
|
||||
$leadField = vtws_getFieldfromFieldId($row['leadfid'], $leadFields);
|
||||
if ($leadField == null) {
|
||||
//user doesn't have access so continue.TODO update even if user doesn't have access
|
||||
continue;
|
||||
}
|
||||
$leadFieldName = $leadField->getFieldName();
|
||||
$entityFieldName = $entityField->getFieldName();
|
||||
$entity[$entityFieldName] = $leadinfo[$leadFieldName];
|
||||
$count++;
|
||||
} while ($row = $adb->fetch_array($result));
|
||||
|
||||
foreach ($entityvalue as $fieldname => $fieldvalue) {
|
||||
if (!empty($fieldvalue)) {
|
||||
$entity[$fieldname] = $fieldvalue;
|
||||
}
|
||||
}
|
||||
|
||||
$entity = vtws_validateConvertLeadEntityMandatoryValues($entity, $entityHandler, $leadinfo, $entityName);
|
||||
}
|
||||
return $entity;
|
||||
}
|
||||
|
||||
function vtws_validateConvertLeadEntityMandatoryValues($entity, $entityHandler, $leadinfo, $module) {
|
||||
|
||||
$mandatoryFields = $entityHandler->getMeta()->getMandatoryFields();
|
||||
foreach ($mandatoryFields as $field) {
|
||||
if (empty($entity[$field])) {
|
||||
$fieldInfo = vtws_getConvertLeadFieldInfo($module, $field);
|
||||
if (($fieldInfo['type']['name'] == 'picklist' || $fieldInfo['type']['name'] == 'multipicklist'
|
||||
|| $fieldInfo['type']['name'] == 'date' || $fieldInfo['type']['name'] == 'datetime')
|
||||
&& ($fieldInfo['editable'] == true)) {
|
||||
$entity[$field] = $fieldInfo['default'];
|
||||
} else {
|
||||
$entity[$field] = '????';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $entity;
|
||||
}
|
||||
|
||||
function vtws_getConvertLeadFieldInfo($module, $fieldname) {
|
||||
global $adb, $log, $current_user;
|
||||
$describe = vtws_describe($module, $current_user);
|
||||
foreach ($describe['fields'] as $index => $fieldInfo) {
|
||||
if ($fieldInfo['name'] == $fieldname) {
|
||||
return $fieldInfo;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//function to handle the transferring of related records for lead
|
||||
function vtws_convertLeadTransferHandler($leadIdComponents, $entityIds, $entityvalues) {
|
||||
|
||||
try {
|
||||
$entityidComponents = vtws_getIdComponents($entityIds[$entityvalues['transferRelatedRecordsTo']]);
|
||||
vtws_transferLeadRelatedRecords($leadIdComponents[1], $entityidComponents[1], $entityvalues['transferRelatedRecordsTo']);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function vtws_updateConvertLeadStatus($entityIds, $leadId, $user) {
|
||||
global $adb, $log;
|
||||
$leadIdComponents = vtws_getIdComponents($leadId);
|
||||
if ($entityIds['Accounts'] != '' || $entityIds['Contacts'] != '') {
|
||||
$sql = "UPDATE vtiger_leaddetails SET converted = 1 where leadid=?";
|
||||
$result = $adb->pquery($sql, array($leadIdComponents[1]));
|
||||
if ($result === false) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$FAILED_TO_MARK_CONVERTED,
|
||||
"Failed mark lead converted");
|
||||
}
|
||||
//updating the campaign-lead relation --Minnie
|
||||
$sql = "DELETE FROM vtiger_campaignleadrel WHERE leadid=?";
|
||||
$adb->pquery($sql, array($leadIdComponents[1]));
|
||||
|
||||
$sql = "DELETE FROM vtiger_tracker WHERE item_id=?";
|
||||
$adb->pquery($sql, array($leadIdComponents[1]));
|
||||
|
||||
//update the modifiedtime and modified by information for the record
|
||||
$leadModifiedTime = $adb->formatDate(date('Y-m-d H:i:s'), true);
|
||||
$crmentityUpdateSql = "UPDATE vtiger_crmentity SET modifiedtime=?, modifiedby=? WHERE crmid=?";
|
||||
$adb->pquery($crmentityUpdateSql, array($leadModifiedTime, $user->id, $leadIdComponents[1]));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,85 @@
|
|||
<?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 vtws_create($elementType, $element, $user) {
|
||||
|
||||
$types = vtws_listtypes(null, $user);
|
||||
if (!in_array($elementType, $types['types'])) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Permission to perform the operation is denied");
|
||||
}
|
||||
|
||||
global $log, $adb;
|
||||
|
||||
// Cache the instance for re-use
|
||||
if(!isset($vtws_create_cache[$elementType]['webserviceobject'])) {
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,$elementType);
|
||||
$vtws_create_cache[$elementType]['webserviceobject'] = $webserviceObject;
|
||||
} else {
|
||||
$webserviceObject = $vtws_create_cache[$elementType]['webserviceobject'];
|
||||
}
|
||||
// END
|
||||
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject, $user, $adb, $log);
|
||||
$meta = $handler->getMeta();
|
||||
if ($meta->hasWriteAccess() !== true) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Permission to write is denied");
|
||||
}
|
||||
|
||||
$referenceFields = $meta->getReferenceFieldDetails();
|
||||
foreach ($referenceFields as $fieldName => $details) {
|
||||
if (isset($element[$fieldName]) && strlen($element[$fieldName]) > 0) {
|
||||
$ids = vtws_getIdComponents($element[$fieldName]);
|
||||
$elemTypeId = $ids[0];
|
||||
$elemId = $ids[1];
|
||||
$referenceObject = VtigerWebserviceObject::fromId($adb, $elemTypeId);
|
||||
if (!in_array($referenceObject->getEntityName(), $details)) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$REFERENCEINVALID,
|
||||
"Invalid reference specified for $fieldName");
|
||||
}
|
||||
if ($referenceObject->getEntityName() == 'Users') {
|
||||
if(!$meta->hasAssignPrivilege($element[$fieldName])) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Cannot assign record to the given user");
|
||||
}
|
||||
}
|
||||
if (!in_array($referenceObject->getEntityName(), $types['types']) && $referenceObject->getEntityName() != 'Users') {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,
|
||||
"Permission to access reference type is denied" . $referenceObject->getEntityName());
|
||||
}
|
||||
} else if ($element[$fieldName] !== NULL) {
|
||||
unset($element[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($meta->hasMandatoryFields($element)) {
|
||||
|
||||
$ownerFields = $meta->getOwnerFields();
|
||||
if (is_array($ownerFields) && sizeof($ownerFields) > 0) {
|
||||
foreach ($ownerFields as $ownerField) {
|
||||
if (isset($element[$ownerField]) && $element[$ownerField] !== null &&
|
||||
!$meta->hasAssignPrivilege($element[$ownerField])) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Cannot assign record to the given user");
|
||||
}
|
||||
}
|
||||
}
|
||||
$entity = $handler->create($elementType, $element);
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $entity;
|
||||
} else {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,277 @@
|
|||
<?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 DataTransform{
|
||||
|
||||
public static $recordString = "record_id";
|
||||
public static $recordModuleString = 'record_module';
|
||||
|
||||
function sanitizeDataWithColumn($row,$meta){
|
||||
|
||||
$newRow = array();
|
||||
if(isset($row['count(*)'])){
|
||||
return DataTransform::sanitizeDataWithCountColumn($row,$meta);
|
||||
}
|
||||
$fieldColumnMapping = $meta->getFieldColumnMapping();
|
||||
$columnFieldMapping = array_flip($fieldColumnMapping);
|
||||
foreach($row as $col=>$val){
|
||||
if(array_key_exists($col,$columnFieldMapping))
|
||||
$newRow[$columnFieldMapping[$col]] = $val;
|
||||
}
|
||||
$newRow = DataTransform::sanitizeData($newRow,$meta,true);
|
||||
return $newRow;
|
||||
}
|
||||
|
||||
function sanitizeDataWithCountColumn($row,$meta){
|
||||
$newRow = array();
|
||||
foreach($row as $col=>$val){
|
||||
$newRow['count'] = $val;
|
||||
}
|
||||
return $newRow;
|
||||
}
|
||||
|
||||
function filterAndSanitize($row,$meta){
|
||||
|
||||
$row = DataTransform::filterAllColumns($row,$meta);
|
||||
$row = DataTransform::sanitizeData($row,$meta);
|
||||
return $row;
|
||||
}
|
||||
|
||||
function sanitizeData($newRow,$meta,$t=null){
|
||||
|
||||
$newRow = DataTransform::sanitizeReferences($newRow,$meta);
|
||||
$newRow = DataTransform::sanitizeOwnerFields($newRow,$meta,$t);
|
||||
$newRow = DataTransform::sanitizeFields($newRow,$meta);
|
||||
return $newRow;
|
||||
}
|
||||
|
||||
function sanitizeForInsert($row,$meta){
|
||||
global $adb;
|
||||
$associatedToUser = false;
|
||||
$parentTypeId = null;
|
||||
if(strtolower($meta->getEntityName()) == "emails"){
|
||||
if(isset($row['parent_id'])){
|
||||
$components = vtws_getIdComponents($row['parent_id']);
|
||||
$userObj = VtigerWebserviceObject::fromName($adb,'Users');
|
||||
$parentTypeId = $components[0];
|
||||
if($components[0] == $userObj->getEntityId()){
|
||||
$associatedToUser = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// added to handle the setting reminder time
|
||||
if(strtolower($meta->getEntityName()) == "events"){
|
||||
if(isset($row['reminder_time'])&& $row['reminder_time']!= null && $row['reminder_time'] != 0){
|
||||
$_REQUEST['set_reminder'] = "Yes";
|
||||
$_REQUEST['mode'] = 'edit';
|
||||
|
||||
$reminder = $row['reminder_time'];
|
||||
$seconds = (int)$reminder%60;
|
||||
$minutes = (int)($reminder/60)%60;
|
||||
$hours = (int)($reminder/(60*60))%24;
|
||||
$days = (int)($reminder/(60*60*24));
|
||||
|
||||
//at vtiger there cant be 0 minutes reminder so we are setting to 1
|
||||
if($minutes == 0){
|
||||
$minutes = 1;
|
||||
}
|
||||
|
||||
$_REQUEST['remmin'] = $minutes;
|
||||
$_REQUEST['remhrs'] = $hours;
|
||||
$_REQUEST['remdays'] = $days;
|
||||
} else {
|
||||
$_REQUEST['set_reminder'] = "No";
|
||||
}
|
||||
} elseif(strtolower($meta->getEntityName()) == "calendar") {
|
||||
if(empty($row['sendnotification']) || strtolower($row['sendnotificaiton'])=='no'
|
||||
|| $row['sendnotificaiton'] == '0' || $row['sendnotificaiton'] == 'false'
|
||||
|| strtolower($row['sendnotificaiton']) == 'n') {
|
||||
unset($row['sendnotification']);
|
||||
}
|
||||
}
|
||||
$references = $meta->getReferenceFieldDetails();
|
||||
foreach($references as $field=>$typeList){
|
||||
if(strpos($row[$field],'x')!==false){
|
||||
$row[$field] = vtws_getIdComponents($row[$field]);
|
||||
$row[$field] = $row[$field][1];
|
||||
}
|
||||
}
|
||||
$ownerFields = $meta->getOwnerFields();
|
||||
foreach($ownerFields as $index=>$field){
|
||||
if(isset($row[$field]) && $row[$field]!=null){
|
||||
$ownerDetails = vtws_getIdComponents($row[$field]);
|
||||
$row[$field] = $ownerDetails[1];
|
||||
}
|
||||
}
|
||||
if(strtolower($meta->getEntityName()) == "emails"){
|
||||
if(isset($row['parent_id'])){
|
||||
if($associatedToUser === true){
|
||||
$_REQUEST['module'] = 'Emails';
|
||||
$row['parent_id'] = $row['parent_id']."@-1|";
|
||||
$_REQUEST['parent_id'] = $row['parent_id'];
|
||||
}else{
|
||||
$referenceHandler = vtws_getModuleHandlerFromId($parentTypeId,
|
||||
$meta->getUser());
|
||||
$referenceMeta = $referenceHandler->getMeta();
|
||||
$fieldId = getEmailFieldId($referenceMeta, $row['parent_id']);
|
||||
$row['parent_id'] .= "@$fieldId|";
|
||||
}
|
||||
}
|
||||
}
|
||||
if($row["id"]){
|
||||
unset($row["id"]);
|
||||
}
|
||||
if(isset($row[$meta->getObectIndexColumn()])){
|
||||
unset($row[$meta->getObectIndexColumn()]);
|
||||
}
|
||||
|
||||
$row = DataTransform::sanitizeDateFieldsForInsert($row,$meta);
|
||||
$row = DataTransform::sanitizeCurrencyFieldsForInsert($row,$meta);
|
||||
|
||||
return $row;
|
||||
|
||||
}
|
||||
|
||||
function filterAllColumns($row,$meta){
|
||||
|
||||
$recordString = DataTransform::$recordString;
|
||||
|
||||
$allFields = $meta->getFieldColumnMapping();
|
||||
$newRow = array();
|
||||
foreach($allFields as $field=>$col){
|
||||
$newRow[$field] = $row[$field];
|
||||
}
|
||||
if(isset($row[$recordString])){
|
||||
$newRow[$recordString] = $row[$recordString];
|
||||
}
|
||||
return $newRow;
|
||||
|
||||
}
|
||||
|
||||
function sanitizeFields($row,$meta){
|
||||
$default_charset = VTWS_PreserveGlobal::getGlobal('default_charset');
|
||||
$recordString = DataTransform::$recordString;
|
||||
|
||||
$recordModuleString = DataTransform::$recordModuleString;
|
||||
|
||||
if(isset($row[$recordModuleString])){
|
||||
unset($row[$recordModuleString]);
|
||||
}
|
||||
|
||||
if(isset($row['id'])){
|
||||
if(strpos($row['id'],'x')===false){
|
||||
$row['id'] = vtws_getId($meta->getEntityId(),$row['id']);
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($row[$recordString])){
|
||||
$row['id'] = vtws_getId($meta->getEntityId(),$row[$recordString]);
|
||||
unset($row[$recordString]);
|
||||
}
|
||||
|
||||
if(!isset($row['id'])){
|
||||
if($row[$meta->getObectIndexColumn()] ){
|
||||
$row['id'] = vtws_getId($meta->getEntityId(),$row[$meta->getObectIndexColumn()]);
|
||||
}else{
|
||||
//TODO Handle this.
|
||||
//echo 'error id noy set' ;
|
||||
}
|
||||
}else if(isset($row[$meta->getObectIndexColumn()]) && strcmp($meta->getObectIndexColumn(),"id")!==0){
|
||||
unset($row[$meta->getObectIndexColumn()]);
|
||||
}
|
||||
|
||||
foreach ($row as $field => $value) {
|
||||
$row[$field] = html_entity_decode($value, ENT_QUOTES, $default_charset);
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
function sanitizeReferences($row,$meta){
|
||||
global $adb,$log;
|
||||
$references = $meta->getReferenceFieldDetails();
|
||||
foreach($references as $field=>$typeList){
|
||||
if(strtolower($meta->getEntityName()) == "emails"){
|
||||
if(isset($row['parent_id'])){
|
||||
list($row['parent_id'], $fieldId) = explode('@',
|
||||
$row['parent_id']);
|
||||
}
|
||||
}
|
||||
if($row[$field]){
|
||||
$found = false;
|
||||
foreach ($typeList as $entity) {
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,$entity);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$meta->getUser(),$adb,$log);
|
||||
$entityMeta = $handler->getMeta();
|
||||
if($entityMeta->exists($row[$field])){
|
||||
$row[$field] = vtws_getId($webserviceObject->getEntityId(),$row[$field]);
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($found !== true){
|
||||
//This is needed as for query operation of the related record is deleted.
|
||||
$row[$field] = null;
|
||||
}
|
||||
//0 is the default for most of the reference fields, so handle the case and return null instead as its the
|
||||
//only valid value, which is not a reference Id.
|
||||
}elseif(isset($row[$field]) && $row[$field]==0){
|
||||
$row[$field] = null;
|
||||
}
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
function sanitizeOwnerFields($row,$meta,$t=null){
|
||||
global $adb;
|
||||
$ownerFields = $meta->getOwnerFields();
|
||||
foreach($ownerFields as $index=>$field){
|
||||
if(isset($row[$field]) && $row[$field]!=null){
|
||||
$ownerType = vtws_getOwnerType($row[$field]);
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,$ownerType);
|
||||
$row[$field] = vtws_getId($webserviceObject->getEntityId(),$row[$field]);
|
||||
}
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
function sanitizeDateFieldsForInsert($row,$meta){
|
||||
global $current_user;
|
||||
$moduleFields = $meta->getModuleFields();
|
||||
foreach($moduleFields as $fieldName=>$fieldObj){
|
||||
if($fieldObj->getFieldDataType()=="date"){
|
||||
if(!empty($row[$fieldName])){
|
||||
$dateFieldObj = new DateTimeField($row[$fieldName]);
|
||||
$row[$fieldName] = $dateFieldObj->getDisplayDate($current_user);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
function sanitizeCurrencyFieldsForInsert($row,$meta){
|
||||
global $current_user;
|
||||
$moduleFields = $meta->getModuleFields();
|
||||
foreach($moduleFields as $fieldName=>$fieldObj){
|
||||
if($fieldObj->getFieldDataType()=="currency"){
|
||||
if(!empty($row[$fieldName])){
|
||||
$row[$fieldName] = CurrencyField::convertToUserFormat($row[$fieldName],$current_user,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,49 @@
|
|||
<?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 vtws_delete($id,$user){
|
||||
global $log,$adb;
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$id);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$meta = $handler->getMeta();
|
||||
$entityName = $meta->getObjectEntityName($id);
|
||||
|
||||
$types = vtws_listtypes(null, $user);
|
||||
if(!in_array($entityName,$types['types'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
|
||||
}
|
||||
|
||||
if($entityName !== $webserviceObject->getEntityName()){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDID,"Id specified is incorrect");
|
||||
}
|
||||
|
||||
if(!$meta->hasPermission(EntityMeta::$DELETE,$id)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to read given object is denied");
|
||||
}
|
||||
|
||||
$idComponents = vtws_getIdComponents($id);
|
||||
if(!$meta->exists($idComponents[1])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND,"Record you are trying to access is not found");
|
||||
}
|
||||
|
||||
if($meta->hasDeleteAccess()!==true){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to delete is denied");
|
||||
}
|
||||
$entity = $handler->delete($id);
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $entity;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,70 @@
|
|||
<?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.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
/**
|
||||
* @author MAK
|
||||
*/
|
||||
|
||||
function vtws_deleteUser($id, $newOwnerId,$user){
|
||||
global $log,$adb;
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$id);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$meta = $handler->getMeta();
|
||||
$entityName = $meta->getObjectEntityName($id);
|
||||
|
||||
$types = vtws_listtypes($user);
|
||||
if(!in_array($entityName,$types['types'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,
|
||||
"Permission to perform the operation is denied, EntityName = ".$entityName);
|
||||
}
|
||||
|
||||
if($entityName !== $webserviceObject->getEntityName()){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDID,
|
||||
"Id specified is incorrect");
|
||||
}
|
||||
|
||||
if(!$meta->hasPermission(EntityMeta::$DELETE,$id)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,
|
||||
"Permission to read given object is denied");
|
||||
}
|
||||
|
||||
$idComponents = vtws_getIdComponents($id);
|
||||
if(!$meta->exists($idComponents[1])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND,
|
||||
"Record you are trying to access is not found, idComponent = ".$idComponents);
|
||||
}
|
||||
|
||||
if($meta->hasWriteAccess()!==true){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,
|
||||
"Permission to write is denied");
|
||||
}
|
||||
|
||||
$newIdComponents = vtws_getIdComponents($newOwnerId);
|
||||
if(empty($newIdComponents[1])) {
|
||||
//force the default user to be the default admin user.
|
||||
//added cause eazybusiness team is sending this value empty
|
||||
$newIdComponents[1] = 1;
|
||||
}
|
||||
vtws_transferOwnership($idComponents[1], $newIdComponents[1]);
|
||||
//delete from user vtiger_table;
|
||||
$sql = "delete from vtiger_users where id=?";
|
||||
vtws_runQueryAsTransaction($sql, array($idComponents[1]), $result);
|
||||
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return array("status"=>"successful");
|
||||
}
|
||||
|
||||
?>
|
|
@ -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.
|
||||
*************************************************************************************/
|
||||
|
||||
function vtws_describe($elementType,$user){
|
||||
|
||||
global $log,$adb;
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,$elementType);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$meta = $handler->getMeta();
|
||||
|
||||
$types = vtws_listtypes(null, $user);
|
||||
if(!in_array($elementType,$types['types'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
|
||||
}
|
||||
|
||||
$entity = $handler->describe($elementType);
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $entity;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,258 @@
|
|||
<?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 EntityMeta{
|
||||
|
||||
public static $RETRIEVE = "DetailView";
|
||||
public static $CREATE = "Save";
|
||||
public static $UPDATE = "EditView";
|
||||
public static $DELETE = "Delete";
|
||||
|
||||
protected $webserviceObject;
|
||||
protected $objectName;
|
||||
protected $objectId;
|
||||
protected $user;
|
||||
protected $baseTable;
|
||||
protected $tableList;
|
||||
protected $tableIndexList;
|
||||
protected $defaultTableList;
|
||||
protected $idColumn;
|
||||
|
||||
protected $userAccessibleColumns;
|
||||
protected $columnTableMapping;
|
||||
protected $fieldColumnMapping;
|
||||
protected $mandatoryFields;
|
||||
protected $referenceFieldDetails;
|
||||
protected $emailFields;
|
||||
protected $ownerFields;
|
||||
protected $moduleFields;
|
||||
|
||||
protected function EntityMeta($webserviceObject,$user){
|
||||
$this->webserviceObject = $webserviceObject;
|
||||
$this->objectName = $this->webserviceObject->getEntityName();
|
||||
$this->objectId = $this->webserviceObject->getEntityId();
|
||||
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function getEmailFields(){
|
||||
if($this->emailFields === null){
|
||||
$this->emailFields = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
if(strcasecmp($webserviceField->getFieldType(),'e') === 0){
|
||||
array_push($this->emailFields, $fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->emailFields;
|
||||
}
|
||||
|
||||
public function getFieldColumnMapping(){
|
||||
if($this->fieldColumnMapping === null){
|
||||
$this->fieldColumnMapping = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
$this->fieldColumnMapping[$fieldName] = $webserviceField->getColumnName();
|
||||
}
|
||||
$this->fieldColumnMapping['id'] = $this->idColumn;
|
||||
}
|
||||
return $this->fieldColumnMapping;
|
||||
}
|
||||
|
||||
public function getMandatoryFields(){
|
||||
if($this->mandatoryFields === null){
|
||||
$this->mandatoryFields = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
if($webserviceField->isMandatory() === true){
|
||||
array_push($this->mandatoryFields,$fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->mandatoryFields;
|
||||
}
|
||||
|
||||
public function getReferenceFieldDetails(){
|
||||
if($this->referenceFieldDetails === null){
|
||||
$this->referenceFieldDetails = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
if(strcasecmp($webserviceField->getFieldDataType(),'reference') === 0){
|
||||
$this->referenceFieldDetails[$fieldName] = $webserviceField->getReferenceList();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->referenceFieldDetails;
|
||||
}
|
||||
|
||||
public function getOwnerFields(){
|
||||
if($this->ownerFields === null){
|
||||
$this->ownerFields = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
if(strcasecmp($webserviceField->getFieldDataType(),'owner') === 0){
|
||||
array_push($this->ownerFields, $fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->ownerFields;
|
||||
}
|
||||
|
||||
public function getObectIndexColumn(){
|
||||
return $this->idColumn;
|
||||
}
|
||||
|
||||
public function getUserAccessibleColumns(){
|
||||
if($this->userAccessibleColumns === null){
|
||||
$this->userAccessibleColumns = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
array_push($this->userAccessibleColumns,$webserviceField->getColumnName());
|
||||
}
|
||||
array_push($this->userAccessibleColumns,$this->idColumn);
|
||||
}
|
||||
return $this->userAccessibleColumns;
|
||||
}
|
||||
|
||||
public function getFieldByColumnName($column){
|
||||
$fields = $this->getModuleFields();
|
||||
foreach ($fields as $fieldName=>$webserviceField) {
|
||||
if($column == $webserviceField->getColumnName()) {
|
||||
return $webserviceField;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getColumnTableMapping(){
|
||||
if($this->columnTableMapping === null){
|
||||
$this->columnTableMapping = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
$this->columnTableMapping[$webserviceField->getColumnName()] = $webserviceField->getTableName();
|
||||
}
|
||||
$this->columnTableMapping[$this->idColumn] = $this->baseTable;
|
||||
}
|
||||
return $this->columnTableMapping;
|
||||
}
|
||||
|
||||
function getUser(){
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
function hasMandatoryFields($row){
|
||||
|
||||
$mandatoryFields = $this->getMandatoryFields();
|
||||
$hasMandatory = true;
|
||||
foreach($mandatoryFields as $ind=>$field){
|
||||
// dont use empty API as '0'(zero) is a valid value.
|
||||
if( !isset($row[$field]) || $row[$field] === "" || $row[$field] === null ){
|
||||
throw new WebServiceException(WebServiceErrorCode::$MANDFIELDSMISSING,
|
||||
"$field does not have a value");
|
||||
}
|
||||
}
|
||||
return $hasMandatory;
|
||||
|
||||
}
|
||||
public function isUpdateMandatoryFields($element){
|
||||
if(!is_array($element)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$MANDFIELDSMISSING,
|
||||
"Mandatory field does not have a value");
|
||||
}
|
||||
$mandatoryFields = $this->getMandatoryFields();
|
||||
$updateFields = array_keys($element);
|
||||
$hasMandatory = true;
|
||||
$updateMandatoryFields = array_intersect($updateFields, $mandatoryFields);
|
||||
if(!empty($updateMandatoryFields)){
|
||||
foreach($updateMandatoryFields as $ind=>$field){
|
||||
// dont use empty API as '0'(zero) is a valid value.
|
||||
if( !isset($element[$field]) || $element[$field] === "" || $element[$field] === null ){
|
||||
throw new WebServiceException(WebServiceErrorCode::$MANDFIELDSMISSING,
|
||||
"$field does not have a value");
|
||||
}
|
||||
}
|
||||
}
|
||||
return $hasMandatory;
|
||||
}
|
||||
|
||||
public function getModuleFields(){
|
||||
return $this->moduleFields;
|
||||
}
|
||||
|
||||
public function getFieldNameListByType($type) {
|
||||
$type = strtolower($type);
|
||||
$typeList = array();
|
||||
$moduleFields = $this->getModuleFields();
|
||||
foreach ($moduleFields as $fieldName=>$webserviceField) {
|
||||
if(strcmp($webserviceField->getFieldDataType(),$type) === 0){
|
||||
array_push($typeList, $fieldName);
|
||||
}
|
||||
}
|
||||
return $typeList;
|
||||
}
|
||||
|
||||
public function getFieldListByType($type) {
|
||||
$type = strtolower($type);
|
||||
$typeList = array();
|
||||
$moduleFields = $this->getModuleFields();
|
||||
foreach ($moduleFields as $fieldName=>$webserviceField) {
|
||||
if(strcmp($webserviceField->getFieldDataType(),$type) === 0){
|
||||
array_push($typeList, $webserviceField);
|
||||
}
|
||||
}
|
||||
return $typeList;
|
||||
}
|
||||
|
||||
public function getIdColumn(){
|
||||
return $this->idColumn;
|
||||
}
|
||||
|
||||
public function getEntityBaseTable() {
|
||||
return $this->baseTable;
|
||||
}
|
||||
|
||||
public function getEntityTableIndexList() {
|
||||
return $this->tableIndexList;
|
||||
}
|
||||
|
||||
public function getEntityDefaultTableList() {
|
||||
return $this->defaultTableList;
|
||||
}
|
||||
|
||||
public function getEntityTableList() {
|
||||
return $this->tableList;
|
||||
}
|
||||
|
||||
public function getEntityAccessControlQuery(){
|
||||
$accessControlQuery = '';
|
||||
return $accessControlQuery;
|
||||
}
|
||||
|
||||
public function getEntityDeletedQuery(){
|
||||
if($this->getEntityName() == 'Leads') {
|
||||
return "vtiger_crmentity.deleted=0 and vtiger_leaddetails.converted=0";
|
||||
}
|
||||
if($this->getEntityName() != "Users"){
|
||||
return "vtiger_crmentity.deleted=0";
|
||||
}
|
||||
// not sure whether inactive users should be considered deleted or not.
|
||||
return "vtiger_users.status='Active'";
|
||||
}
|
||||
|
||||
abstract function hasPermission($operation,$webserviceId);
|
||||
abstract function hasAssignPrivilege($ownerWebserviceId);
|
||||
abstract function hasDeleteAccess();
|
||||
abstract function hasAccess();
|
||||
abstract function hasReadAccess();
|
||||
abstract function hasWriteAccess();
|
||||
abstract function getEntityName();
|
||||
abstract function getEntityId();
|
||||
abstract function exists($recordId);
|
||||
abstract function getObjectEntityName($webserviceId);
|
||||
abstract public function getNameFields();
|
||||
abstract public function getName($webserviceId);
|
||||
abstract public function isModuleEntity();
|
||||
}
|
||||
?>
|
|
@ -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.
|
||||
*************************************************************************************/
|
||||
|
||||
function vtws_extendSession(){
|
||||
global $adb,$API_VERSION,$application_unique_key;
|
||||
if(isset($_SESSION["authenticated_user_id"]) && $_SESSION["app_unique_key"] == $application_unique_key){
|
||||
$userId = $_SESSION["authenticated_user_id"];
|
||||
$sessionManager = new SessionManager();
|
||||
$sessionManager->set("authenticatedUserId", $userId);
|
||||
$crmObject = VtigerWebserviceObject::fromName($adb,"Users");
|
||||
$userId = vtws_getId($crmObject->getEntityId(),$userId);
|
||||
$vtigerVersion = vtws_getVtigerVersion();
|
||||
$resp = array("sessionName"=>$sessionManager->getSessionId(),"userId"=>$userId,"version"=>$API_VERSION,"vtigerVersion"=>$vtigerVersion);
|
||||
return $resp;
|
||||
}else{
|
||||
throw new WebServiceException(WebServiceErrorCode::$AUTHFAILURE,"Authencation Failed");
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,282 @@
|
|||
<?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/Webservices/Utils.php';
|
||||
require_once 'include/Webservices/ModuleTypes.php';
|
||||
require_once 'include/utils/CommonUtils.php';
|
||||
|
||||
function vtws_sync($mtime,$elementType,$syncType,$user){
|
||||
global $adb, $recordString,$modifiedTimeString;
|
||||
|
||||
$numRecordsLimit = 100;
|
||||
$ignoreModules = array("Users");
|
||||
$typed = true;
|
||||
$dformat = "Y-m-d H:i:s";
|
||||
$datetime = date($dformat, $mtime);
|
||||
$setypeArray = array();
|
||||
$setypeData = array();
|
||||
$setypeHandler = array();
|
||||
$setypeNoAccessArray = array();
|
||||
|
||||
$output = array();
|
||||
$output["updated"] = array();
|
||||
$output["deleted"] = array();
|
||||
|
||||
$applicationSync = false;
|
||||
if(is_object($syncType) && ($syncType instanceof Users)){
|
||||
$user = $syncType;
|
||||
} else if($syncType == 'application'){
|
||||
$applicationSync = true;
|
||||
}
|
||||
|
||||
if($applicationSync && !is_admin($user)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Only admin users can perform application sync");
|
||||
}
|
||||
|
||||
$ownerIds = array($user->id);
|
||||
|
||||
if(!isset($elementType) || $elementType=='' || $elementType==null){
|
||||
$typed=false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$adb->startTransaction();
|
||||
|
||||
$accessableModules = array();
|
||||
$entityModules = array();
|
||||
$modulesDetails = vtws_listtypes(null,$user);
|
||||
$moduleTypes = $modulesDetails['types'];
|
||||
$modulesInformation = $modulesDetails["information"];
|
||||
|
||||
foreach($modulesInformation as $moduleName=>$entityInformation){
|
||||
if($entityInformation["isEntity"])
|
||||
$entityModules[] = $moduleName;
|
||||
}
|
||||
if(!$typed){
|
||||
$accessableModules = $entityModules;
|
||||
}
|
||||
else{
|
||||
if(!in_array($elementType,$entityModules))
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
|
||||
$accessableModules[] = $elementType;
|
||||
}
|
||||
|
||||
$accessableModules = array_diff($accessableModules,$ignoreModules);
|
||||
|
||||
if(count($accessableModules)<=0)
|
||||
{
|
||||
$output['lastModifiedTime'] = $mtime;
|
||||
$output['more'] = false;
|
||||
return $output;
|
||||
}
|
||||
|
||||
if($typed){
|
||||
$handler = vtws_getModuleHandlerFromName($elementType, $user);
|
||||
$moduleMeta = $handler->getMeta();
|
||||
$entityDefaultBaseTables = $moduleMeta->getEntityDefaultTableList();
|
||||
//since there will be only one base table for all entities
|
||||
$baseCRMTable = $entityDefaultBaseTables[0];
|
||||
if($elementType=="Calendar" || $elementType=="Events" ){
|
||||
$baseCRMTable = getSyncQueryBaseTable($elementType);
|
||||
}
|
||||
}
|
||||
else
|
||||
$baseCRMTable = " vtiger_crmentity ";
|
||||
|
||||
//modifiedtime - next token
|
||||
$q = "SELECT modifiedtime FROM $baseCRMTable WHERE modifiedtime>? and setype IN(".generateQuestionMarks($accessableModules).") ";
|
||||
$params = array($datetime);
|
||||
foreach($accessableModules as $entityModule){
|
||||
if($entityModule == "Events")
|
||||
$entityModule = "Calendar";
|
||||
$params[] = $entityModule;
|
||||
}
|
||||
if(!$applicationSync){
|
||||
$q .= ' and smownerid IN('.generateQuestionMarks($ownerIds).')';
|
||||
$params = array_merge($params,$ownerIds);
|
||||
}
|
||||
|
||||
$q .=" order by modifiedtime limit $numRecordsLimit";
|
||||
$result = $adb->pquery($q,$params);
|
||||
|
||||
$modTime = array();
|
||||
for($i=0;$i<$adb->num_rows($result);$i++){
|
||||
$modTime[] = $adb->query_result($result,$i,'modifiedtime');
|
||||
}
|
||||
if(!empty($modTime)){
|
||||
$maxModifiedTime = max($modTime);
|
||||
}
|
||||
if(!$maxModifiedTime){
|
||||
$maxModifiedTime = $datetime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach($accessableModules as $elementType){
|
||||
$handler = vtws_getModuleHandlerFromName($elementType, $user);
|
||||
$moduleMeta = $handler->getMeta();
|
||||
$deletedQueryCondition = $moduleMeta->getEntityDeletedQuery();
|
||||
preg_match_all("/(?:\s+\w+[ \t\n\r]+)?([^=]+)\s*=([^\s]+|'[^']+')/",$deletedQueryCondition,$deletedFieldDetails);
|
||||
$fieldNameDetails = $deletedFieldDetails[1];
|
||||
$deleteFieldValues = $deletedFieldDetails[2];
|
||||
$deleteColumnNames = array();
|
||||
foreach($fieldNameDetails as $tableName_fieldName){
|
||||
$fieldComp = explode(".",$tableName_fieldName);
|
||||
$deleteColumnNames[$tableName_fieldName] = $fieldComp[1];
|
||||
}
|
||||
$params = array($moduleMeta->getTabName(),$datetime,$maxModifiedTime);
|
||||
|
||||
|
||||
$queryGenerator = new QueryGenerator($elementType, $user);
|
||||
$fields = array();
|
||||
$moduleFeilds = $moduleMeta->getModuleFields();
|
||||
$moduleFeildNames = array_keys($moduleFeilds);
|
||||
$moduleFeildNames[]='id';
|
||||
$queryGenerator->setFields($moduleFeildNames);
|
||||
$selectClause = "SELECT ".$queryGenerator->getSelectClauseColumnSQL();
|
||||
// adding the fieldnames that are present in the delete condition to the select clause
|
||||
// since not all fields present in delete condition will be present in the fieldnames of the module
|
||||
foreach($deleteColumnNames as $table_fieldName=>$columnName){
|
||||
if(!in_array($columnName,$moduleFeildNames)){
|
||||
$selectClause .=", ".$table_fieldName;
|
||||
}
|
||||
}
|
||||
if($elementType=="Emails")
|
||||
$fromClause = vtws_getEmailFromClause();
|
||||
else
|
||||
$fromClause = $queryGenerator->getFromClause();
|
||||
$fromClause .= " INNER JOIN (select modifiedtime, crmid,deleted,setype FROM $baseCRMTable WHERE setype=? and modifiedtime >? and modifiedtime<=?";
|
||||
if(!$applicationSync){
|
||||
$fromClause.= 'and smownerid IN('.generateQuestionMarks($ownerIds).')';
|
||||
$params = array_merge($params,$ownerIds);
|
||||
}
|
||||
$fromClause.= ' ) vtiger_ws_sync ON (vtiger_crmentity.crmid = vtiger_ws_sync.crmid)';
|
||||
$q = $selectClause." ".$fromClause;
|
||||
$result = $adb->pquery($q, $params);
|
||||
$recordDetails = array();
|
||||
$deleteRecordDetails = array();
|
||||
while($arre = $adb->fetchByAssoc($result)){
|
||||
$key = $arre[$moduleMeta->getIdColumn()];
|
||||
if(vtws_isRecordDeleted($arre,$deleteColumnNames,$deleteFieldValues)){
|
||||
if(!$moduleMeta->hasAccess()){
|
||||
continue;
|
||||
}
|
||||
$output["deleted"][] = vtws_getId($moduleMeta->getEntityId(), $key);
|
||||
}
|
||||
else{
|
||||
if(!$moduleMeta->hasAccess() ||!$moduleMeta->hasPermission(EntityMeta::$RETRIEVE,$key)){
|
||||
continue;
|
||||
}
|
||||
try{
|
||||
$output["updated"][] = DataTransform::sanitizeDataWithColumn($arre,$moduleMeta);;
|
||||
}catch(WebServiceException $e){
|
||||
//ignore records the user doesn't have access to.
|
||||
continue;
|
||||
}catch(Exception $e){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INTERNALERROR,"Unknown Error while processing request");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$q = "SELECT crmid FROM $baseCRMTable WHERE modifiedtime>? and setype IN(".generateQuestionMarks($accessableModules).")";
|
||||
$params = array($maxModifiedTime);
|
||||
|
||||
foreach($accessableModules as $entityModule){
|
||||
if($entityModule == "Events")
|
||||
$entityModule = "Calendar";
|
||||
$params[] = $entityModule;
|
||||
}
|
||||
if(!$applicationSync){
|
||||
$q.='and smownerid IN('.generateQuestionMarks($ownerIds).')';
|
||||
$params = array_merge($params,$ownerIds);
|
||||
}
|
||||
|
||||
$result = $adb->pquery($q,$params);
|
||||
if($adb->num_rows($result)>0){
|
||||
$output['more'] = true;
|
||||
}
|
||||
else{
|
||||
$output['more'] = false;
|
||||
}
|
||||
if(!$maxModifiedTime){
|
||||
$modifiedtime = $mtime;
|
||||
}else{
|
||||
$modifiedtime = vtws_getSeconds($maxModifiedTime);
|
||||
}
|
||||
if(is_string($modifiedtime)){
|
||||
$modifiedtime = intval($modifiedtime);
|
||||
}
|
||||
$output['lastModifiedTime'] = $modifiedtime;
|
||||
|
||||
$error = $adb->hasFailedTransaction();
|
||||
$adb->completeTransaction();
|
||||
|
||||
if($error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $output;
|
||||
}
|
||||
|
||||
function vtws_getSeconds($mtimeString){
|
||||
//TODO handle timezone and change time to gmt.
|
||||
return strtotime($mtimeString);
|
||||
}
|
||||
|
||||
function vtws_isRecordDeleted($recordDetails,$deleteColumnDetails,$deletedValues){
|
||||
$deletedRecord = false;
|
||||
$i=0;
|
||||
foreach($deleteColumnDetails as $tableName_fieldName=>$columnName){
|
||||
if($recordDetails[$columnName]!=$deletedValues[$i++]){
|
||||
$deletedRecord = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $deletedRecord;
|
||||
}
|
||||
|
||||
function vtws_getEmailFromClause(){
|
||||
$q = "FROM vtiger_activity
|
||||
INNER JOIN vtiger_crmentity ON vtiger_activity.activityid = vtiger_crmentity.crmid
|
||||
LEFT JOIN vtiger_users ON vtiger_crmentity.smownerid = vtiger_users.id
|
||||
LEFT JOIN vtiger_groups ON vtiger_crmentity.smownerid = vtiger_groups.groupid
|
||||
LEFT JOIN vtiger_seattachmentsrel ON vtiger_activity.activityid = vtiger_seattachmentsrel.crmid
|
||||
LEFT JOIN vtiger_attachments ON vtiger_seattachmentsrel.attachmentsid = vtiger_attachments.attachmentsid
|
||||
LEFT JOIN vtiger_email_track ON vtiger_activity.activityid = vtiger_email_track.mailid
|
||||
INNER JOIN vtiger_emaildetails ON vtiger_activity.activityid = vtiger_emaildetails.emailid
|
||||
LEFT JOIN vtiger_users vtiger_users2 ON vtiger_emaildetails.idlists = vtiger_users2.id
|
||||
LEFT JOIN vtiger_groups vtiger_groups2 ON vtiger_emaildetails.idlists = vtiger_groups2.groupid";
|
||||
return $q;
|
||||
}
|
||||
|
||||
function getSyncQueryBaseTable($elementType){
|
||||
if($elementType!="Calendar" && $elementType!="Events"){
|
||||
return "vtiger_crmentity";
|
||||
}
|
||||
else{
|
||||
$activityCondition = getCalendarTypeCondition($elementType);
|
||||
$query = "vtiger_crmentity INNER JOIN vtiger_activity ON (vtiger_crmentity.crmid = vtiger_activity.activityid and $activityCondition)";
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
||||
function getCalendarTypeCondition($elementType){
|
||||
if($elementType == "Events")
|
||||
$activityCondition = "vtiger_activity.activitytype !='Task' and vtiger_activity.activitytype !='Emails'";
|
||||
else
|
||||
$activityCondition = "vtiger_activity.activitytype ='Task'";
|
||||
return $activityCondition;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,63 @@
|
|||
<?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 vtws_login($username,$pwd){
|
||||
|
||||
$user = new Users();
|
||||
$userId = $user->retrieve_user_id($username);
|
||||
|
||||
$token = vtws_getActiveToken($userId);
|
||||
if($token == null){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDTOKEN,"Specified token is invalid or expired");
|
||||
}
|
||||
|
||||
$accessKey = vtws_getUserAccessKey($userId);
|
||||
if($accessKey == null){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSKEYUNDEFINED,"Access key for the user is undefined");
|
||||
}
|
||||
|
||||
$accessCrypt = md5($token.$accessKey);
|
||||
if(strcmp($accessCrypt,$pwd)!==0){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDUSERPWD,"Invalid username or password");
|
||||
}
|
||||
$user = $user->retrieveCurrentUserInfoFromFile($userId);
|
||||
if($user->status != 'Inactive'){
|
||||
return $user;
|
||||
}
|
||||
throw new WebServiceException(WebServiceErrorCode::$AUTHREQUIRED,'Given user is inactive');
|
||||
}
|
||||
|
||||
function vtws_getActiveToken($userId){
|
||||
global $adb;
|
||||
|
||||
$sql = "select * from vtiger_ws_userauthtoken where userid=? and expiretime >= ?";
|
||||
$result = $adb->pquery($sql,array($userId,time()));
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
return $adb->query_result($result,0,"token");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function vtws_getUserAccessKey($userId){
|
||||
global $adb;
|
||||
|
||||
$sql = "select * from vtiger_users where id=?";
|
||||
$result = $adb->pquery($sql,array($userId));
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
return $adb->query_result($result,0,"accesskey");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
?>
|
|
@ -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.
|
||||
*************************************************************************************/
|
||||
|
||||
function vtws_logout($sessionId,$user){
|
||||
$sessionManager = new SessionManager();
|
||||
$sid = $sessionManager->startSession($sessionId);
|
||||
|
||||
if(!isset($sessionId) || !$sessionManager->isValid()){
|
||||
return $sessionManager->getError();
|
||||
}
|
||||
|
||||
$sessionManager->destroy();
|
||||
// $sessionManager->setExpire(1);
|
||||
return array("message"=>"successfull");
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,136 @@
|
|||
<?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 vtws_listtypes($fieldTypeList, $user){
|
||||
// Bulk Save Mode: For re-using information
|
||||
static $webserviceEntities = false;
|
||||
// END
|
||||
|
||||
static $types = array();
|
||||
if(!empty($fieldTypeList)) {
|
||||
$fieldTypeList = array_map(strtolower, $fieldTypeList);
|
||||
sort($fieldTypeList);
|
||||
$fieldTypeString = implode(',', $fieldTypeList);
|
||||
} else {
|
||||
$fieldTypeString = 'all';
|
||||
}
|
||||
if(!empty($types[$user->id][$fieldTypeString])) {
|
||||
return $types[$user->id][$fieldTypeString];
|
||||
}
|
||||
try{
|
||||
global $log;
|
||||
/**
|
||||
* @var PearDatabase
|
||||
*/
|
||||
$db = PearDatabase::getInstance();
|
||||
|
||||
vtws_preserveGlobal('current_user',$user);
|
||||
//get All the modules the current user is permitted to Access.
|
||||
$allModuleNames = getPermittedModuleNames();
|
||||
if(array_search('Calendar',$allModuleNames) !== false){
|
||||
array_push($allModuleNames,'Events');
|
||||
}
|
||||
|
||||
if(!empty($fieldTypeList)) {
|
||||
$sql = "SELECT distinct(vtiger_field.tabid) as tabid FROM vtiger_field LEFT JOIN vtiger_ws_fieldtype ON ".
|
||||
"vtiger_field.uitype=vtiger_ws_fieldtype.uitype
|
||||
INNER JOIN vtiger_profile2field ON vtiger_field.fieldid = vtiger_profile2field.fieldid
|
||||
INNER JOIN vtiger_def_org_field ON vtiger_def_org_field.fieldid = vtiger_field.fieldid
|
||||
INNER JOIN vtiger_role2profile ON vtiger_profile2field.profileid = vtiger_role2profile.profileid
|
||||
INNER JOIN vtiger_user2role ON vtiger_user2role.roleid = vtiger_role2profile.roleid
|
||||
where vtiger_profile2field.visible=0 and vtiger_def_org_field.visible = 0
|
||||
and vtiger_field.presence in (0,2)
|
||||
and vtiger_user2role.userid=? and fieldtype in (".
|
||||
generateQuestionMarks($fieldTypeList).')';
|
||||
$params = array();
|
||||
$params[] = $user->id;
|
||||
foreach($fieldTypeList as $fieldType)
|
||||
$params[] = $fieldType;
|
||||
$result = $db->pquery($sql, $params);
|
||||
$it = new SqlResultIterator($db, $result);
|
||||
$moduleList = array();
|
||||
foreach ($it as $row) {
|
||||
$moduleList[] = getTabModuleName($row->tabid);
|
||||
}
|
||||
$allModuleNames = array_intersect($moduleList, $allModuleNames);
|
||||
|
||||
$params = $fieldTypeList;
|
||||
|
||||
$sql = "select name from vtiger_ws_entity inner join vtiger_ws_entity_tables on ".
|
||||
"vtiger_ws_entity.id=vtiger_ws_entity_tables.webservice_entity_id inner join ".
|
||||
"vtiger_ws_entity_fieldtype on vtiger_ws_entity_fieldtype.table_name=".
|
||||
"vtiger_ws_entity_tables.table_name where fieldtype=(".
|
||||
generateQuestionMarks($fieldTypeList).')';
|
||||
$result = $db->pquery($sql, $params);
|
||||
$it = new SqlResultIterator($db, $result);
|
||||
$entityList = array();
|
||||
foreach ($it as $row) {
|
||||
$entityList[] = $row->name;
|
||||
}
|
||||
}
|
||||
//get All the CRM entity names.
|
||||
if($webserviceEntities === false || !CRMEntity::isBulkSaveMode()) {
|
||||
// Bulk Save Mode: For re-using information
|
||||
$webserviceEntities = vtws_getWebserviceEntities();
|
||||
}
|
||||
|
||||
$accessibleModules = array_values(array_intersect($webserviceEntities['module'],$allModuleNames));
|
||||
$entities = $webserviceEntities['entity'];
|
||||
$accessibleEntities = array();
|
||||
if(empty($fieldTypeList)) {
|
||||
foreach($entities as $entity){
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($db,$entity);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
$handler = new $handlerClass($webserviceObject,$user,$db,$log);
|
||||
$meta = $handler->getMeta();
|
||||
if($meta->hasAccess()===true){
|
||||
array_push($accessibleEntities,$entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(WebServiceException $exception){
|
||||
throw $exception;
|
||||
}catch(Exception $exception){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
"An Database error occured while performing the operation");
|
||||
}
|
||||
|
||||
$default_language = VTWS_PreserveGlobal::getGlobal('default_language');
|
||||
$current_language = vtws_preserveGlobal('current_language',$default_language);
|
||||
|
||||
$appStrings = return_application_language($current_language);
|
||||
$appListString = return_app_list_strings_language($current_language);
|
||||
vtws_preserveGlobal('app_strings',$appStrings);
|
||||
vtws_preserveGlobal('app_list_strings',$appListString);
|
||||
|
||||
$informationArray = array();
|
||||
foreach ($accessibleModules as $module) {
|
||||
$vtigerModule = ($module == 'Events')? 'Calendar':$module;
|
||||
$informationArray[$module] = array('isEntity'=>true,'label'=>getTranslatedString($module,$vtigerModule),
|
||||
'singular'=>getTranslatedString('SINGLE_'.$module,$vtigerModule));
|
||||
}
|
||||
|
||||
foreach ($accessibleEntities as $entity) {
|
||||
$label = (isset($appStrings[$entity]))? $appStrings[$entity]:$entity;
|
||||
$singular = (isset($appStrings['SINGLE_'.$entity]))? $appStrings['SINGLE_'.$entity]:$entity;
|
||||
$informationArray[$entity] = array('isEntity'=>false,'label'=>$label,
|
||||
'singular'=>$singular);
|
||||
}
|
||||
|
||||
VTWS_PreserveGlobal::flush();
|
||||
$types[$user->id][$fieldTypeString] = array("types"=>array_merge($accessibleModules,$accessibleEntities),
|
||||
'information'=>$informationArray);
|
||||
return $types[$user->id][$fieldTypeString];
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,181 @@
|
|||
<?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 setBuiltIn($json){
|
||||
$json->useBuiltinEncoderDecoder = true;
|
||||
}
|
||||
|
||||
class OperationManager{
|
||||
private $format;
|
||||
private $formatsData=array(
|
||||
"json"=>array(
|
||||
"includePath"=>"include/Zend/Json.php",
|
||||
"class"=>"Zend_Json",
|
||||
"encodeMethod"=>"encode",
|
||||
"decodeMethod"=>"decode",
|
||||
"postCreate"=>"setBuiltIn"
|
||||
)
|
||||
);
|
||||
private $operationMeta = null;
|
||||
private $formatObjects ;
|
||||
private $inParamProcess ;
|
||||
private $sessionManager;
|
||||
private $pearDB;
|
||||
private $operationName;
|
||||
private $type;
|
||||
private $handlerPath;
|
||||
private $handlerMethod;
|
||||
private $preLogin;
|
||||
private $operationId;
|
||||
private $operationParams;
|
||||
|
||||
function OperationManager($adb,$operationName,$format, $sessionManager){
|
||||
|
||||
$this->format = strtolower($format);
|
||||
$this->sessionManager = $sessionManager;
|
||||
$this->formatObjects = array();
|
||||
|
||||
foreach($this->formatsData as $frmt=>$frmtData){
|
||||
require_once($frmtData["includePath"]);
|
||||
$instance = new $frmtData["class"]();
|
||||
$this->formatObjects[$frmt]["encode"] = array(&$instance,$frmtData["encodeMethod"]);
|
||||
$this->formatObjects[$frmt]["decode"] = array(&$instance,$frmtData["decodeMethod"]);
|
||||
if($frmtData["postCreate"]){
|
||||
call_user_func($frmtData["postCreate"],$instance);
|
||||
}
|
||||
}
|
||||
|
||||
$this->pearDB = $adb;
|
||||
$this->operationName = $operationName;
|
||||
$this->inParamProcess = array();
|
||||
$this->inParamProcess["encoded"] = &$this->formatObjects[$this->format]["decode"];
|
||||
$this->fillOperationDetails($operationName);
|
||||
}
|
||||
|
||||
function isPreLoginOperation(){
|
||||
return $this->preLogin == 1;
|
||||
}
|
||||
|
||||
private function fillOperationDetails($operationName){
|
||||
$sql = "select * from vtiger_ws_operation where name=?";
|
||||
$result = $this->pearDB->pquery($sql,array($operationName));
|
||||
if($result){
|
||||
$rowCount = $this->pearDB->num_rows($result);
|
||||
if($rowCount > 0){
|
||||
$row = $this->pearDB->query_result_rowdata($result,0);
|
||||
$this->type = $row['type'];
|
||||
$this->handlerMethod = $row['handler_method'];
|
||||
$this->handlerPath = $row['handler_path'];
|
||||
$this->preLogin = $row['prelogin'];
|
||||
$this->operationName = $row['name'];
|
||||
$this->operationId = $row['operationid'];
|
||||
$this->fillOperationParameters();
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new WebServiceException(WebServiceErrorCode::$UNKNOWNOPERATION,"Unknown operation requested");
|
||||
}
|
||||
|
||||
private function fillOperationParameters(){
|
||||
$sql = "select * from vtiger_ws_operation_parameters where operationid=? order by sequence";
|
||||
$result = $this->pearDB->pquery($sql,array($this->operationId));
|
||||
$this->operationParams = array();
|
||||
if($result){
|
||||
$rowCount = $this->pearDB->num_rows($result);
|
||||
if($rowCount > 0){
|
||||
for ($i=0;$i<$rowCount;++$i){
|
||||
$row = $this->pearDB->query_result_rowdata($result,$i);
|
||||
array_push($this->operationParams,array($row['name']=>$row['type']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getOperationInput(){
|
||||
$type = strtolower($this->type);
|
||||
switch($type){
|
||||
case 'get': $input = &$_GET;
|
||||
return $input;
|
||||
case 'post': $input = &$_POST;
|
||||
return $input;
|
||||
default: $input = &$_REQUEST;
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
|
||||
function sanitizeOperation($input){
|
||||
return $this->sanitizeInputForType($input);
|
||||
}
|
||||
|
||||
function sanitizeInputForType($input){
|
||||
|
||||
$sanitizedInput = array();
|
||||
foreach($this->operationParams as $ind=>$columnDetails){
|
||||
foreach ($columnDetails as $columnName => $type) {
|
||||
$sanitizedInput[$columnName] = $this->handleType($type,vtws_getParameter($input,$columnName));;
|
||||
}
|
||||
}
|
||||
return $sanitizedInput;
|
||||
}
|
||||
|
||||
function handleType($type,$value){
|
||||
$result;
|
||||
$value = stripslashes($value);
|
||||
$type = strtolower($type);
|
||||
if($this->inParamProcess[$type]){
|
||||
$result = call_user_func($this->inParamProcess[$type],$value);
|
||||
}else{
|
||||
$result = $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function runOperation($params,$user){
|
||||
global $API_VERSION;
|
||||
try{
|
||||
$operation = strtolower($this->operationName);
|
||||
if(!$this->preLogin){
|
||||
$params[] = $user;
|
||||
return call_user_func_array($this->handlerMethod,$params);
|
||||
}else{
|
||||
$userDetails = call_user_func_array($this->handlerMethod,$params);
|
||||
if(is_array($userDetails)){
|
||||
return $userDetails;
|
||||
}else{
|
||||
$this->sessionManager->set("authenticatedUserId", $userDetails->id);
|
||||
global $adb;
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,"Users");
|
||||
$userId = vtws_getId($webserviceObject->getEntityId(),$userDetails->id);
|
||||
$vtigerVersion = vtws_getVtigerVersion();
|
||||
$resp = array("sessionName"=>$this->sessionManager->getSessionId(),"userId"=>$userId,"version"=>$API_VERSION,"vtigerVersion"=>$vtigerVersion);
|
||||
return $resp;
|
||||
}
|
||||
}
|
||||
}catch(WebServiceException $e){
|
||||
throw $e;
|
||||
}catch(Exception $e){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INTERNALERROR,"Unknown Error while processing request");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function encode($param){
|
||||
return call_user_func($this->formatObjects[$this->format]["encode"],$param);
|
||||
}
|
||||
|
||||
function getOperationIncludes(){
|
||||
$includes = array();
|
||||
array_push($includes,$this->handlerPath);
|
||||
return $includes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,54 @@
|
|||
<?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 VTWS_PreserveGlobal{
|
||||
|
||||
private static $globalData = array();
|
||||
|
||||
static function preserveGlobal($name,$value){
|
||||
//$name store the name of the global.
|
||||
global $$name;
|
||||
|
||||
if(!is_array(VTWS_PreserveGlobal::$globalData[$name])){
|
||||
VTWS_PreserveGlobal::$globalData[$name] = array();
|
||||
VTWS_PreserveGlobal::$globalData[$name][] = $$name;
|
||||
}
|
||||
$$name = $value;
|
||||
return $$name;
|
||||
}
|
||||
|
||||
static function restore($name){
|
||||
//$name store the name of the global.
|
||||
global $$name;
|
||||
|
||||
if(is_array(VTWS_PreserveGlobal::$globalData[$name]) && count(VTWS_PreserveGlobal::$globalData[$name]) > 0){
|
||||
$$name = array_pop(VTWS_PreserveGlobal::$globalData[$name]);
|
||||
}
|
||||
$$name;
|
||||
}
|
||||
|
||||
static function getGlobal($name){
|
||||
global $$name;
|
||||
return VTWS_PreserveGlobal::preserveGlobal($name,$$name);
|
||||
}
|
||||
|
||||
static function flush(){
|
||||
foreach (VTWS_PreserveGlobal::$globalData as $name => $detail) {
|
||||
//$name store the name of the global.
|
||||
global $$name;
|
||||
if(is_array(VTWS_PreserveGlobal::$globalData[$name]) && count(VTWS_PreserveGlobal::$globalData[$name]) > 0) {
|
||||
$$name = array_pop(VTWS_PreserveGlobal::$globalData[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,69 @@
|
|||
<?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/Webservices/QueryParser.php");
|
||||
|
||||
function vtws_query($q,$user){
|
||||
|
||||
static $vtws_query_cache = array();
|
||||
|
||||
global $log,$adb;
|
||||
|
||||
// Cache the instance for re-use
|
||||
$moduleRegex = "/[fF][rR][Oo][Mm]\s+([^\s;]+)/";
|
||||
$moduleName = '';
|
||||
if(preg_match($moduleRegex, $q, $m)) $moduleName = trim($m[1]);
|
||||
|
||||
if(!isset($vtws_create_cache[$moduleName]['webserviceobject'])) {
|
||||
$webserviceObject = VtigerWebserviceObject::fromQuery($adb,$q);
|
||||
$vtws_query_cache[$moduleName]['webserviceobject'] = $webserviceObject;
|
||||
} else {
|
||||
$webserviceObject = $vtws_query_cache[$moduleName]['webserviceobject'];
|
||||
}
|
||||
// END
|
||||
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
// Cache the instance for re-use
|
||||
if(!isset($vtws_query_cache[$moduleName]['handler'])) {
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$vtws_query_cache[$moduleName]['handler'] = $handler;
|
||||
} else {
|
||||
$handler = $vtws_query_cache[$moduleName]['handler'];
|
||||
}
|
||||
// END
|
||||
|
||||
// Cache the instance for re-use
|
||||
if(!isset($vtws_query_cache[$moduleName]['meta'])) {
|
||||
$meta = $handler->getMeta();
|
||||
$vtws_query_cache[$moduleName]['meta'] = $meta;
|
||||
} else {
|
||||
$meta = $vtws_query_cache[$moduleName]['meta'];
|
||||
}
|
||||
// END
|
||||
|
||||
$types = vtws_listtypes(null, $user);
|
||||
if(!in_array($webserviceObject->getEntityName(),$types['types'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
|
||||
}
|
||||
|
||||
if(!$meta->hasReadAccess()){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to read is denied");
|
||||
}
|
||||
|
||||
$result = $handler->query($q);
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $result;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,64 @@
|
|||
<?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/Webservices/VTQL_Lexer.php");
|
||||
require_once("include/Webservices/VTQL_Parser.php");
|
||||
|
||||
class Parser{
|
||||
|
||||
private $query = "";
|
||||
private $out;
|
||||
private $meta;
|
||||
private $hasError ;
|
||||
private $error ;
|
||||
private $user;
|
||||
function Parser($user, $q){
|
||||
$this->query = $q;
|
||||
$this->out = array();
|
||||
$this->hasError = false;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
function parse(){
|
||||
|
||||
$lex = new VTQL_Lexer($this->query);
|
||||
$parser = new VTQL_Parser($this->user, $lex,$this->out);
|
||||
while ($lex->yylex()) {
|
||||
$parser->doParse($lex->token, $lex->value);
|
||||
}
|
||||
$parser->doParse(0, 0);
|
||||
|
||||
if($parser->isSuccess()){
|
||||
$this->hasError = false;
|
||||
$this->query = $parser->getQuery();
|
||||
$this->meta = $parser->getObjectMetaData();
|
||||
}else{
|
||||
$this->hasError = true;
|
||||
$this->error = $parser->getErrorMsg();
|
||||
}
|
||||
|
||||
return $this->hasError;
|
||||
|
||||
}
|
||||
|
||||
function getSql(){
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
function getObjectMetaData(){
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
function getError(){
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,88 @@
|
|||
<?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.
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
/**
|
||||
* Description of RelatedModuleMeta
|
||||
* TODO to add and extend a way to track many-many and many-one relationships.
|
||||
* @author MAK
|
||||
*/
|
||||
class RelatedModuleMeta {
|
||||
private $module;
|
||||
private $relatedModule;
|
||||
private $CAMPAIGNCONTACTREL = 1;
|
||||
private $PRODUCTQUOTESREL = 2;
|
||||
private $PRODUCTINVOICEREL = 3;
|
||||
private $PRODUCTPURCHASEORDERREL = 4;
|
||||
|
||||
private function __construct($module, $relatedModule) {
|
||||
$this->module = $module;
|
||||
$this->relatedModule = $relatedModule;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <type> $module
|
||||
* @param <type> $relatedModule
|
||||
* @return RelatedModuleMeta
|
||||
*/
|
||||
public static function getInstance($module, $relatedModule) {
|
||||
return new RelatedModuleMeta($module, $relatedModule);
|
||||
}
|
||||
|
||||
public function getRelationMeta() {
|
||||
$campaignContactRel = array('Campaigns','Contacts');
|
||||
$productInvoiceRel = array('Products','Invoice');
|
||||
$productQuotesRel = array('Products','Quotes');
|
||||
$productPurchaseOrder = array('Products','PurchaseOrder');
|
||||
if(in_array($this->module, $campaignContactRel) && in_array($this->relatedModule,
|
||||
$campaignContactRel)) {
|
||||
return $this->getRelationMetaInfo($this->CAMPAIGNCONTACTREL);
|
||||
}
|
||||
if(in_array($this->module, $productInvoiceRel) && in_array($this->relatedModule,
|
||||
$productInvoiceRel)) {
|
||||
return $this->getRelationMetaInfo($this->PRODUCTINVOICEREL);
|
||||
}
|
||||
if(in_array($this->module, $productQuotesRel) && in_array($this->relatedModule,
|
||||
$productQuotesRel)) {
|
||||
return $this->getRelationMetaInfo($this->PRODUCTQUOTESREL);
|
||||
}
|
||||
if(in_array($this->module, $productPurchaseOrder) && in_array($this->relatedModule,
|
||||
$productPurchaseOrder)) {
|
||||
return $this->getRelationMetaInfo($this->PRODUCTPURCHASEORDERREL);
|
||||
}
|
||||
}
|
||||
|
||||
private function getRelationMetaInfo($relationId) {
|
||||
switch($relationId) {
|
||||
case $this->CAMPAIGNCONTACTREL: return array(
|
||||
'relationTable' => 'vtiger_campaigncontrel',
|
||||
'Campaigns' => 'campaignid',
|
||||
'Contacts' => 'contactid'
|
||||
);
|
||||
case $this->PRODUCTINVOICEREL: return array(
|
||||
'relationTable' => 'vtiger_inventoryproductrel',
|
||||
'Products' => 'productid',
|
||||
'Invoice' => 'id'
|
||||
);
|
||||
case $this->PRODUCTQUOTESREL: return array(
|
||||
'relationTable' => 'vtiger_inventoryproductrel',
|
||||
'Products' => 'productid',
|
||||
'Quotes' => 'id'
|
||||
);
|
||||
case $this->PRODUCTPURCHASEORDERREL: return array(
|
||||
'relationTable' => 'vtiger_inventoryproductrel',
|
||||
'Products' => 'productid',
|
||||
'PurchaseOrder' => 'id'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,49 @@
|
|||
<?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 vtws_retrieve($id, $user){
|
||||
|
||||
global $log,$adb;
|
||||
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$id);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$meta = $handler->getMeta();
|
||||
$entityName = $meta->getObjectEntityName($id);
|
||||
$types = vtws_listtypes(null, $user);
|
||||
if(!in_array($entityName,$types['types'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
|
||||
}
|
||||
if($meta->hasReadAccess()!==true){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to write is denied");
|
||||
}
|
||||
|
||||
if($entityName !== $webserviceObject->getEntityName()){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDID,"Id specified is incorrect");
|
||||
}
|
||||
|
||||
if(!$meta->hasPermission(EntityMeta::$RETRIEVE,$id)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to read given object is denied");
|
||||
}
|
||||
|
||||
$idComponents = vtws_getIdComponents($id);
|
||||
if(!$meta->exists($idComponents[1])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND,"Record you are trying to access is not found");
|
||||
}
|
||||
|
||||
$entity = $handler->retrieve($id);
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $entity;
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,87 @@
|
|||
<?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 vtws_revise($element,$user){
|
||||
|
||||
global $log,$adb;
|
||||
$idList = vtws_getIdComponents($element['id']);
|
||||
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$idList[0]);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$meta = $handler->getMeta();
|
||||
$entityName = $meta->getObjectEntityName($element['id']);
|
||||
|
||||
$types = vtws_listtypes(null, $user);
|
||||
if(!in_array($entityName,$types['types'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
|
||||
}
|
||||
|
||||
if($entityName !== $webserviceObject->getEntityName()){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDID,"Id specified is incorrect");
|
||||
}
|
||||
|
||||
if(!$meta->hasPermission(EntityMeta::$UPDATE,$element['id'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to read given object is denied");
|
||||
}
|
||||
|
||||
if(!$meta->exists($idList[1])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND,"Record you are trying to access is not found");
|
||||
}
|
||||
|
||||
if($meta->hasWriteAccess()!==true){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to write is denied");
|
||||
}
|
||||
|
||||
$referenceFields = $meta->getReferenceFieldDetails();
|
||||
foreach($referenceFields as $fieldName=>$details){
|
||||
if(isset($element[$fieldName]) && strlen($element[$fieldName]) > 0){
|
||||
$ids = vtws_getIdComponents($element[$fieldName]);
|
||||
$elemTypeId = $ids[0];
|
||||
$elemId = $ids[1];
|
||||
$referenceObject = VtigerWebserviceObject::fromId($adb,$elemTypeId);
|
||||
if (!in_array($referenceObject->getEntityName(),$details)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$REFERENCEINVALID,
|
||||
"Invalid reference specified for $fieldName");
|
||||
}
|
||||
if ($referenceObject->getEntityName() == 'Users') {
|
||||
if(!$meta->hasAssignPrivilege($element[$fieldName])) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Cannot assign record to the given user");
|
||||
}
|
||||
}
|
||||
if (!in_array($referenceObject->getEntityName(), $types['types']) && $referenceObject->getEntityName() != 'Users') {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,
|
||||
"Permission to access reference type is denied ".$referenceObject->getEntityName());
|
||||
}
|
||||
}
|
||||
}
|
||||
//check if the element has mandtory fields filled
|
||||
$meta->isUpdateMandatoryFields($element);
|
||||
|
||||
$ownerFields = $meta->getOwnerFields();
|
||||
if(is_array($ownerFields) && sizeof($ownerFields) >0){
|
||||
foreach($ownerFields as $ownerField){
|
||||
if(isset($element[$ownerField]) && $element[$ownerField]!==null &&
|
||||
!$meta->hasAssignPrivilege($element[$ownerField])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Cannot assign record to the given user");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$entity = $handler->revise($element);
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $entity;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,132 @@
|
|||
<?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/HTTP_Session/Session.php");
|
||||
// Later may we can move this to config file.
|
||||
|
||||
global $maxWebServiceSessionLifeSpan, $maxWebServiceSessionIdleTime;
|
||||
|
||||
$maxWebServiceSessionLifeSpan = 86400; //Max life span of a session is a day.
|
||||
$maxWebServiceSessionIdleTime = 1800; //Max life span session should be kept alive after the last transaction.
|
||||
|
||||
// Till Here.
|
||||
|
||||
class SessionManager{
|
||||
private $maxLife ;
|
||||
private $idleLife ;
|
||||
//Note: the url lookup part of http_session will have String null or this be used as id instead of ignoring it.
|
||||
//private $sessionName = "sessionName";
|
||||
private $sessionVar = "__SessionExists";
|
||||
private $error ;
|
||||
|
||||
function SessionManager(){
|
||||
|
||||
global $maxWebServiceSessionLifeSpan, $maxWebServiceSessionIdleTime;
|
||||
|
||||
$now = time();
|
||||
$this->maxLife = $now + $maxWebServiceSessionLifeSpan;
|
||||
$this->idleLife = $now + $maxWebServiceSessionIdleTime;
|
||||
|
||||
HTTP_Session::useCookies(false); //disable cookie usage. may this could be moved out constructor?
|
||||
// only first invocation of following method, which is setExpire
|
||||
//have an effect and any further invocation will be have no effect.
|
||||
HTTP_Session::setExpire($this->maxLife);
|
||||
// this method replaces the new with old time if second params is true
|
||||
//otherwise it subtracts the time from previous time
|
||||
HTTP_Session::setIdle($this->idleLife, true);
|
||||
}
|
||||
|
||||
function isValid(){
|
||||
|
||||
$valid = true;
|
||||
// expired
|
||||
if (HTTP_Session::isExpired()) {
|
||||
$valid = false;
|
||||
HTTP_Session::destroy();
|
||||
throw new WebServiceException(WebServiceErrorCode::$SESSLIFEOVER,"Session has life span over please login again");
|
||||
}
|
||||
|
||||
// idled
|
||||
if (HTTP_Session::isIdle()) {
|
||||
$valid = false;
|
||||
HTTP_Session::destroy();
|
||||
throw new WebServiceException(WebServiceErrorCode::$SESSIONIDLE,"Session has been invalidated to due lack activity");
|
||||
}
|
||||
//echo "<br>is new: ", HTTP_Session::isNew();
|
||||
//invalid sessionId provided.
|
||||
//echo "<br>get: ",$this->get($this->sessionVar);
|
||||
if(!$this->get($this->sessionVar) && !HTTP_Session::isNew()){
|
||||
$valid = false;
|
||||
HTTP_Session::destroy();
|
||||
throw new WebServiceException(WebServiceErrorCode::$SESSIONIDINVALID,"Session Identifier provided is Invalid");
|
||||
}
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
function startSession($sid = null,$adoptSession=false){
|
||||
|
||||
// if($sid){
|
||||
// HTTP_Session::id($sid);
|
||||
// }
|
||||
|
||||
if(!$sid || strlen($sid) ===0){
|
||||
$sid = null;
|
||||
}
|
||||
|
||||
//session name is used for guessing the session id by http_session so pass null.
|
||||
HTTP_Session::start(null, $sid);
|
||||
|
||||
$newSID = HTTP_Session::id();
|
||||
|
||||
if(!$sid || $adoptSession==true){
|
||||
$this->set($this->sessionVar,"true");
|
||||
}else{
|
||||
if(!$this->get($this->sessionVar)){
|
||||
HTTP_Session::destroy();
|
||||
throw new WebServiceException(WebServiceErrorCode::$SESSIONIDINVALID,"Session Identifier provided is Invalid");
|
||||
$newSID = null;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->isValid()){
|
||||
$newSID = null;
|
||||
}
|
||||
$sid = $newSID;
|
||||
return $sid;
|
||||
|
||||
}
|
||||
|
||||
function getSessionId(){
|
||||
return HTTP_Session::id();
|
||||
}
|
||||
|
||||
function set($var_name, $var_value){
|
||||
//TODO test setRef and getRef combination
|
||||
//echo "<br>setting name: ",$var_name," :value: ",$var_value;
|
||||
HTTP_Session::set($var_name, $var_value);
|
||||
}
|
||||
|
||||
function get($name){
|
||||
//echo "<br> getting for: ",$name," :value: ",HTTP_Session::get($name);
|
||||
return HTTP_Session::get($name);
|
||||
}
|
||||
|
||||
FUNCTION getError(){
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
function destroy(){
|
||||
HTTP_Session::destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,25 @@
|
|||
<?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 State{
|
||||
|
||||
var $success ;
|
||||
var $result ;
|
||||
var $error;
|
||||
|
||||
function State(){
|
||||
$this->success = false;
|
||||
$this->result = array();
|
||||
$this->error = array();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,88 @@
|
|||
<?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 vtws_update($element,$user){
|
||||
|
||||
global $log,$adb;
|
||||
$idList = vtws_getIdComponents($element['id']);
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$idList[0]);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$meta = $handler->getMeta();
|
||||
$entityName = $meta->getObjectEntityName($element['id']);
|
||||
|
||||
$types = vtws_listtypes(null, $user);
|
||||
if(!in_array($entityName,$types['types'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
|
||||
}
|
||||
|
||||
if($entityName !== $webserviceObject->getEntityName()){
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDID,"Id specified is incorrect");
|
||||
}
|
||||
|
||||
if(!$meta->hasPermission(EntityMeta::$UPDATE,$element['id'])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to read given object is denied");
|
||||
}
|
||||
|
||||
if(!$meta->exists($idList[1])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND,"Record you are trying to access is not found");
|
||||
}
|
||||
|
||||
if($meta->hasWriteAccess()!==true){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to write is denied");
|
||||
}
|
||||
|
||||
$referenceFields = $meta->getReferenceFieldDetails();
|
||||
foreach($referenceFields as $fieldName=>$details){
|
||||
if(isset($element[$fieldName]) && strlen($element[$fieldName]) > 0){
|
||||
$ids = vtws_getIdComponents($element[$fieldName]);
|
||||
$elemTypeId = $ids[0];
|
||||
$elemId = $ids[1];
|
||||
$referenceObject = VtigerWebserviceObject::fromId($adb,$elemTypeId);
|
||||
if (!in_array($referenceObject->getEntityName(),$details)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$REFERENCEINVALID,
|
||||
"Invalid reference specified for $fieldName");
|
||||
}
|
||||
if ($referenceObject->getEntityName() == 'Users') {
|
||||
if(!$meta->hasAssignPrivilege($element[$fieldName])) {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Cannot assign record to the given user");
|
||||
}
|
||||
}
|
||||
if (!in_array($referenceObject->getEntityName(), $types['types']) && $referenceObject->getEntityName() != 'Users') {
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,
|
||||
"Permission to access reference type is denied ".$referenceObject->getEntityName());
|
||||
}
|
||||
}else if($element[$fieldName] !== NULL){
|
||||
unset($element[$fieldName]);
|
||||
}
|
||||
}
|
||||
|
||||
$meta->hasMandatoryFields($element);
|
||||
|
||||
$ownerFields = $meta->getOwnerFields();
|
||||
if(is_array($ownerFields) && sizeof($ownerFields) >0){
|
||||
foreach($ownerFields as $ownerField){
|
||||
if(isset($element[$ownerField]) && $element[$ownerField]!==null &&
|
||||
!$meta->hasAssignPrivilege($element[$ownerField])){
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Cannot assign record to the given user");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$entity = $handler->update($element);
|
||||
VTWS_PreserveGlobal::flush();
|
||||
return $entity;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,919 @@
|
|||
<?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/database/PearDatabase.php');
|
||||
require_once("modules/Users/Users.php");
|
||||
require_once 'include/Webservices/WebserviceField.php';
|
||||
require_once 'include/Webservices/EntityMeta.php';
|
||||
require_once 'include/Webservices/VtigerWebserviceObject.php';
|
||||
require_once("include/Webservices/VtigerCRMObject.php");
|
||||
require_once("include/Webservices/VtigerCRMObjectMeta.php");
|
||||
require_once("include/Webservices/DataTransform.php");
|
||||
require_once("include/Webservices/WebServiceError.php");
|
||||
require_once 'include/utils/utils.php';
|
||||
require_once 'include/utils/UserInfoUtil.php';
|
||||
require_once 'include/Webservices/ModuleTypes.php';
|
||||
require_once 'include/utils/VtlibUtils.php';
|
||||
require_once 'include/Webservices/WebserviceEntityOperation.php';
|
||||
require_once 'include/Webservices/PreserveGlobal.php';
|
||||
|
||||
/* Function to return all the users in the groups that this user is part of.
|
||||
* @param $id - id of the user
|
||||
* returns Array:UserIds userid of all the users in the groups that this user is part of.
|
||||
*/
|
||||
function vtws_getUsersInTheSameGroup($id){
|
||||
require_once('include/utils/GetGroupUsers.php');
|
||||
require_once('include/utils/GetUserGroups.php');
|
||||
|
||||
$groupUsers = new GetGroupUsers();
|
||||
$userGroups = new GetUserGroups();
|
||||
$allUsers = Array();
|
||||
$userGroups->getAllUserGroups($id);
|
||||
$groups = $userGroups->user_groups;
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$groupUsers->getAllUsersInGroup($group);
|
||||
$usersInGroup = $groupUsers->group_users;
|
||||
foreach ($usersInGroup as $user) {
|
||||
if($user != $id){
|
||||
$allUsers[$user] = getUserFullName($user);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $allUsers;
|
||||
}
|
||||
|
||||
function vtws_generateRandomAccessKey($length=10){
|
||||
$source = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
$accesskey = "";
|
||||
$maxIndex = strlen($source);
|
||||
for($i=0;$i<$length;++$i){
|
||||
$accesskey = $accesskey.substr($source,rand(null,$maxIndex),1);
|
||||
}
|
||||
return $accesskey;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current vtiger version from the database.
|
||||
*/
|
||||
function vtws_getVtigerVersion(){
|
||||
global $adb;
|
||||
$query = 'select * from vtiger_version';
|
||||
$result = $adb->pquery($query, array());
|
||||
$version = '';
|
||||
while($row = $adb->fetch_array($result))
|
||||
{
|
||||
$version = $row['current_version'];
|
||||
}
|
||||
return $version;
|
||||
}
|
||||
|
||||
function vtws_getUserAccessibleGroups($moduleId, $user){
|
||||
global $adb;
|
||||
require('user_privileges/user_privileges_'.$user->id.'.php');
|
||||
require('user_privileges/sharing_privileges_'.$user->id.'.php');
|
||||
$tabName = getTabname($moduleId);
|
||||
if($is_admin==false && $profileGlobalPermission[2] == 1 &&
|
||||
($defaultOrgSharingPermission[$moduleId] == 3 or $defaultOrgSharingPermission[$moduleId] == 0)){
|
||||
$result=get_current_user_access_groups($tabName);
|
||||
}else{
|
||||
$result = get_group_options();
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
if($result != null && $result != '' && is_object($result)){
|
||||
$rowCount = $adb->num_rows($result);
|
||||
for ($i = 0; $i < $rowCount; $i++) {
|
||||
$nameArray = $adb->query_result_rowdata($result,$i);
|
||||
$groupId=$nameArray["groupid"];
|
||||
$groupName=$nameArray["groupname"];
|
||||
$groups[] = array('id'=>$groupId,'name'=>$groupName);
|
||||
}
|
||||
}
|
||||
return $groups;
|
||||
}
|
||||
|
||||
function vtws_getWebserviceGroupFromGroups($groups){
|
||||
global $adb;
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,'Groups');
|
||||
foreach($groups as $index=>$group){
|
||||
$groups[$index]['id'] = vtws_getId($webserviceObject->getEntityId(),$group['id']);
|
||||
}
|
||||
return $groups;
|
||||
}
|
||||
|
||||
function vtws_getUserWebservicesGroups($tabId,$user){
|
||||
$groups = vtws_getUserAccessibleGroups($tabId,$user);
|
||||
return vtws_getWebserviceGroupFromGroups($groups);
|
||||
}
|
||||
|
||||
function vtws_getIdComponents($elementid){
|
||||
return explode("x",$elementid);
|
||||
}
|
||||
|
||||
function vtws_getId($objId, $elemId){
|
||||
return $objId."x".$elemId;
|
||||
}
|
||||
|
||||
function getEmailFieldId($meta, $entityId){
|
||||
global $adb;
|
||||
//no email field accessible in the module. since its only association pick up the field any way.
|
||||
$query="SELECT fieldid,fieldlabel,columnname FROM vtiger_field WHERE tabid=?
|
||||
and uitype=13 and presence in (0,2)";
|
||||
$result = $adb->pquery($query, array($meta->getTabId()));
|
||||
|
||||
//pick up the first field.
|
||||
$fieldId = $adb->query_result($result,0,'fieldid');
|
||||
return $fieldId;
|
||||
}
|
||||
|
||||
function vtws_getParameter($parameterArray, $paramName,$default=null){
|
||||
|
||||
if (!get_magic_quotes_gpc()) {
|
||||
if(is_array($parameterArray[$paramName])) {
|
||||
$param = array_map('addslashes', $parameterArray[$paramName]);
|
||||
} else {
|
||||
$param = addslashes($parameterArray[$paramName]);
|
||||
}
|
||||
} else {
|
||||
$param = $parameterArray[$paramName];
|
||||
}
|
||||
if(!$param){
|
||||
$param = $default;
|
||||
}
|
||||
return $param;
|
||||
}
|
||||
|
||||
function vtws_getEntityNameFields($moduleName){
|
||||
|
||||
global $adb;
|
||||
$query = "select fieldname,tablename,entityidfield from vtiger_entityname where modulename = ?";
|
||||
$result = $adb->pquery($query, array($moduleName));
|
||||
$rowCount = $adb->num_rows($result);
|
||||
$nameFields = array();
|
||||
if($rowCount > 0){
|
||||
$fieldsname = $adb->query_result($result,0,'fieldname');
|
||||
if(!(strpos($fieldsname,',') === false)){
|
||||
$nameFields = explode(',',$fieldsname);
|
||||
}else{
|
||||
array_push($nameFields,$fieldsname);
|
||||
}
|
||||
}
|
||||
return $nameFields;
|
||||
}
|
||||
|
||||
/** function to get the module List to which are crm entities.
|
||||
* @return Array modules list as array
|
||||
*/
|
||||
function vtws_getModuleNameList(){
|
||||
global $adb;
|
||||
|
||||
$sql = "select name from vtiger_tab where isentitytype=1 and name not in ('Rss','Webmails',".
|
||||
"'Recyclebin','Events') order by tabsequence";
|
||||
$res = $adb->pquery($sql, array());
|
||||
$mod_array = Array();
|
||||
while($row = $adb->fetchByAssoc($res)){
|
||||
array_push($mod_array,$row['name']);
|
||||
}
|
||||
return $mod_array;
|
||||
}
|
||||
|
||||
function vtws_getWebserviceEntities(){
|
||||
global $adb;
|
||||
|
||||
$sql = "select name,id,ismodule from vtiger_ws_entity";
|
||||
$res = $adb->pquery($sql, array());
|
||||
$moduleArray = Array();
|
||||
$entityArray = Array();
|
||||
while($row = $adb->fetchByAssoc($res)){
|
||||
if($row['ismodule'] == '1'){
|
||||
array_push($moduleArray,$row['name']);
|
||||
}else{
|
||||
array_push($entityArray,$row['name']);
|
||||
}
|
||||
}
|
||||
return array('module'=>$moduleArray,'entity'=>$entityArray);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param VtigerWebserviceObject $webserviceObject
|
||||
* @return CRMEntity
|
||||
*/
|
||||
function vtws_getModuleInstance($webserviceObject){
|
||||
$moduleName = $webserviceObject->getEntityName();
|
||||
return CRMEntity::getInstance($moduleName);
|
||||
}
|
||||
|
||||
function vtws_isRecordOwnerUser($ownerId){
|
||||
global $adb;
|
||||
$result = $adb->pquery("select first_name from vtiger_users where id = ?",array($ownerId));
|
||||
$rowCount = $adb->num_rows($result);
|
||||
$ownedByUser = ($rowCount > 0);
|
||||
return $ownedByUser;
|
||||
}
|
||||
|
||||
function vtws_isRecordOwnerGroup($ownerId){
|
||||
global $adb;
|
||||
$result = $adb->pquery("select groupname from vtiger_groups where groupid = ?",array($ownerId));
|
||||
$rowCount = $adb->num_rows($result);
|
||||
$ownedByGroup = ($rowCount > 0);
|
||||
return $ownedByGroup;
|
||||
}
|
||||
|
||||
function vtws_getOwnerType($ownerId){
|
||||
if(vtws_isRecordOwnerGroup($ownerId) == true){
|
||||
return 'Groups';
|
||||
}
|
||||
if(vtws_isRecordOwnerUser($ownerId) == true){
|
||||
return 'Users';
|
||||
}
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDID,"Invalid owner of the record");
|
||||
}
|
||||
|
||||
function vtws_runQueryAsTransaction($query,$params,&$result){
|
||||
global $adb;
|
||||
|
||||
$adb->startTransaction();
|
||||
$result = $adb->pquery($query,$params);
|
||||
$error = $adb->hasFailedTransaction();
|
||||
$adb->completeTransaction();
|
||||
return !$error;
|
||||
}
|
||||
|
||||
function vtws_getCalendarEntityType($id){
|
||||
global $adb;
|
||||
|
||||
$sql = "select activitytype from vtiger_activity where activityid=?";
|
||||
$result = $adb->pquery($sql,array($id));
|
||||
$seType = 'Calendar';
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
$activityType = $adb->query_result($result,0,"activitytype");
|
||||
if($activityType !== "Task"){
|
||||
$seType = "Events";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $seType;
|
||||
}
|
||||
|
||||
/***
|
||||
* Get the webservice reference Id given the entity's id and it's type name
|
||||
*/
|
||||
function vtws_getWebserviceEntityId($entityName, $id){
|
||||
global $adb;
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,$entityName);
|
||||
return $webserviceObject->getEntityId().'x'.$id;
|
||||
}
|
||||
|
||||
function vtws_addDefaultModuleTypeEntity($moduleName){
|
||||
global $adb;
|
||||
$isModule = 1;
|
||||
$moduleHandler = array('file'=>'include/Webservices/VtigerModuleOperation.php',
|
||||
'class'=>'VtigerModuleOperation');
|
||||
return vtws_addModuleTypeWebserviceEntity($moduleName,$moduleHandler['file'],$moduleHandler['class'],$isModule);
|
||||
}
|
||||
|
||||
function vtws_addModuleTypeWebserviceEntity($moduleName,$filePath,$className){
|
||||
global $adb;
|
||||
$checkres = $adb->pquery('SELECT id FROM vtiger_ws_entity WHERE name=? AND handler_path=? AND handler_class=?',
|
||||
array($moduleName, $filePath, $className));
|
||||
if($checkres && $adb->num_rows($checkres) == 0) {
|
||||
$isModule=1;
|
||||
$entityId = $adb->getUniqueID("vtiger_ws_entity");
|
||||
$adb->pquery('insert into vtiger_ws_entity(id,name,handler_path,handler_class,ismodule) values (?,?,?,?,?)',
|
||||
array($entityId,$moduleName,$filePath,$className,$isModule));
|
||||
}
|
||||
}
|
||||
|
||||
function vtws_deleteWebserviceEntity($moduleName) {
|
||||
global $adb;
|
||||
$adb->pquery('DELETE FROM vtiger_ws_entity WHERE name=?',array($moduleName));
|
||||
}
|
||||
|
||||
function vtws_addDefaultActorTypeEntity($actorName,$actorNameDetails,$withName = true){
|
||||
$actorHandler = array('file'=>'include/Webservices/VtigerActorOperation.php',
|
||||
'class'=>'VtigerActorOperation');
|
||||
if($withName == true){
|
||||
vtws_addActorTypeWebserviceEntityWithName($actorName,$actorHandler['file'],$actorHandler['class'],
|
||||
$actorNameDetails);
|
||||
}else{
|
||||
vtws_addActorTypeWebserviceEntityWithoutName($actorName,$actorHandler['file'],$actorHandler['class'],
|
||||
$actorNameDetails);
|
||||
}
|
||||
}
|
||||
|
||||
function vtws_addActorTypeWebserviceEntityWithName($moduleName,$filePath,$className,$actorNameDetails){
|
||||
global $adb;
|
||||
$isModule=0;
|
||||
$entityId = $adb->getUniqueID("vtiger_ws_entity");
|
||||
$adb->pquery('insert into vtiger_ws_entity(id,name,handler_path,handler_class,ismodule) values (?,?,?,?,?)',
|
||||
array($entityId,$moduleName,$filePath,$className,$isModule));
|
||||
vtws_addActorTypeName($entityId,$actorNameDetails['fieldNames'],$actorNameDetails['indexField'],
|
||||
$actorNameDetails['tableName']);
|
||||
}
|
||||
|
||||
function vtws_addActorTypeWebserviceEntityWithoutName($moduleName,$filePath,$className,$actorNameDetails){
|
||||
global $adb;
|
||||
$isModule=0;
|
||||
$entityId = $adb->getUniqueID("vtiger_ws_entity");
|
||||
$adb->pquery('insert into vtiger_ws_entity(id,name,handler_path,handler_class,ismodule) values (?,?,?,?,?)',
|
||||
array($entityId,$moduleName,$filePath,$className,$isModule));
|
||||
}
|
||||
|
||||
function vtws_addActorTypeName($entityId,$fieldNames,$indexColumn,$tableName){
|
||||
global $adb;
|
||||
$adb->pquery('insert into vtiger_ws_entity_name(entity_id,name_fields,index_field,table_name) values (?,?,?,?)',
|
||||
array($entityId,$fieldNames,$indexColumn,$tableName));
|
||||
}
|
||||
|
||||
function vtws_getName($id,$user){
|
||||
global $log,$adb;
|
||||
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$id);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
$meta = $handler->getMeta();
|
||||
return $meta->getName($id);
|
||||
}
|
||||
|
||||
function vtws_preserveGlobal($name,$value){
|
||||
return VTWS_PreserveGlobal::preserveGlobal($name,$value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the details of a webservices and exposes it over http.
|
||||
* @param $name name of the webservice to be added with namespace.
|
||||
* @param $handlerFilePath file to be include which provides the handler method for the given webservice.
|
||||
* @param $handlerMethodName name of the function to the called when this webservice is invoked.
|
||||
* @param $requestType type of request that this operation should be, if in doubt give it as GET,
|
||||
* general rule of thumb is that, if the operation is adding/updating data on server then it must be POST
|
||||
* otherwise it should be GET.
|
||||
* @param $preLogin 0 if the operation need the user to authorised to access the webservice and
|
||||
* 1 if the operation is called before login operation hence the there will be no user authorisation happening
|
||||
* for the operation.
|
||||
* @return Integer operationId of successful or null upon failure.
|
||||
*/
|
||||
function vtws_addWebserviceOperation($name,$handlerFilePath,$handlerMethodName,$requestType,$preLogin = 0){
|
||||
global $adb;
|
||||
$createOperationQuery = "insert into vtiger_ws_operation(operationid,name,handler_path,handler_method,type,prelogin)
|
||||
values (?,?,?,?,?,?);";
|
||||
if(strtolower($requestType) != 'get' && strtolower($requestType) != 'post'){
|
||||
return null;
|
||||
}
|
||||
$requestType = strtoupper($requestType);
|
||||
if(empty($preLogin)){
|
||||
$preLogin = 0;
|
||||
}else{
|
||||
$preLogin = 1;
|
||||
}
|
||||
$operationId = $adb->getUniqueID("vtiger_ws_operation");
|
||||
$result = $adb->pquery($createOperationQuery,array($operationId,$name,$handlerFilePath,$handlerMethodName,
|
||||
$requestType,$preLogin));
|
||||
if($result !== false){
|
||||
return $operationId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a parameter to a webservice.
|
||||
* @param $operationId Id of the operation for which a webservice needs to be added.
|
||||
* @param $paramName name of the parameter used to pickup value from request(POST/GET) object.
|
||||
* @param $paramType type of the parameter, it can either 'string','datetime' or 'encoded'
|
||||
* encoded type is used for input which will be encoded in JSON or XML(NOT SUPPORTED).
|
||||
* @param $sequence sequence of the parameter in the definition in the handler method.
|
||||
* @return Boolean true if the parameter was added successfully, false otherwise
|
||||
*/
|
||||
function vtws_addWebserviceOperationParam($operationId,$paramName,$paramType,$sequence){
|
||||
global $adb;
|
||||
$supportedTypes = array('string','encoded','datetime','double','boolean');
|
||||
if(!is_numeric($sequence)){
|
||||
$sequence = 1;
|
||||
}if($sequence <=1){
|
||||
$sequence = 1;
|
||||
}
|
||||
if(!in_array(strtolower($paramType),$supportedTypes)){
|
||||
return false;
|
||||
}
|
||||
$createOperationParamsQuery = "insert into vtiger_ws_operation_parameters(operationid,name,type,sequence)
|
||||
values (?,?,?,?);";
|
||||
$result = $adb->pquery($createOperationParamsQuery,array($operationId,$paramName,$paramType,$sequence));
|
||||
return ($result !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @global PearDatabase $adb
|
||||
* @global <type> $log
|
||||
* @param <type> $name
|
||||
* @param <type> $user
|
||||
* @return WebserviceEntityOperation
|
||||
*/
|
||||
function vtws_getModuleHandlerFromName($name,$user){
|
||||
global $adb, $log;
|
||||
$webserviceObject = VtigerWebserviceObject::fromName($adb,$name);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
return $handler;
|
||||
}
|
||||
|
||||
function vtws_getModuleHandlerFromId($id,$user){
|
||||
global $adb, $log;
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$id);
|
||||
$handlerPath = $webserviceObject->getHandlerPath();
|
||||
$handlerClass = $webserviceObject->getHandlerClass();
|
||||
|
||||
require_once $handlerPath;
|
||||
|
||||
$handler = new $handlerClass($webserviceObject,$user,$adb,$log);
|
||||
return $handler;
|
||||
}
|
||||
|
||||
function vtws_CreateCompanyLogoFile($fieldname) {
|
||||
global $root_directory;
|
||||
$uploaddir = $root_directory ."/test/logo/";
|
||||
$allowedFileTypes = array("jpeg", "png", "jpg", "pjpeg" ,"x-png");
|
||||
$binFile = $_FILES[$fieldname]['name'];
|
||||
$fileType = $_FILES[$fieldname]['type'];
|
||||
$fileSize = $_FILES[$fieldname]['size'];
|
||||
$fileTypeArray = explode("/",$fileType);
|
||||
$fileTypeValue = strtolower($fileTypeArray[1]);
|
||||
if($fileTypeValue == '') {
|
||||
$fileTypeValue = substr($binFile,strrpos($binFile, '.')+1);
|
||||
}
|
||||
if($fileSize != 0) {
|
||||
if(in_array($fileTypeValue, $allowedFileTypes)) {
|
||||
move_uploaded_file($_FILES[$fieldname]["tmp_name"],
|
||||
$uploaddir.$_FILES[$fieldname]["name"]);
|
||||
return $binFile;
|
||||
}
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDTOKEN,
|
||||
"$fieldname wrong file type given for upload");
|
||||
}
|
||||
throw new WebServiceException(WebServiceErrorCode::$INVALIDTOKEN,
|
||||
"$fieldname file upload failed");
|
||||
}
|
||||
|
||||
function vtws_getActorEntityName ($name, $idList) {
|
||||
$db = PearDatabase::getInstance();
|
||||
if (!is_array($idList) && count($idList) == 0) {
|
||||
return array();
|
||||
}
|
||||
$entity = VtigerWebserviceObject::fromName($db, $name);
|
||||
return vtws_getActorEntityNameById($entity->getEntityId(), $idList);
|
||||
}
|
||||
|
||||
function vtws_getActorEntityNameById ($entityId, $idList) {
|
||||
$db = PearDatabase::getInstance();
|
||||
if (!is_array($idList) && count($idList) == 0) {
|
||||
return array();
|
||||
}
|
||||
$nameList = array();
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($db, $entityId);
|
||||
$query = "select * from vtiger_ws_entity_name where entity_id = ?";
|
||||
$result = $db->pquery($query, array($entityId));
|
||||
if (is_object($result)) {
|
||||
$rowCount = $db->num_rows($result);
|
||||
if ($rowCount > 0) {
|
||||
$nameFields = $db->query_result($result,0,'name_fields');
|
||||
$tableName = $db->query_result($result,0,'table_name');
|
||||
$indexField = $db->query_result($result,0,'index_field');
|
||||
if (!(strpos($nameFields,',') === false)) {
|
||||
$fieldList = explode(',',$nameFields);
|
||||
$nameFields = "concat(";
|
||||
$nameFields = $nameFields.implode(",' ',",$fieldList);
|
||||
$nameFields = $nameFields.")";
|
||||
}
|
||||
|
||||
$query1 = "select $nameFields as entityname, $indexField from $tableName where ".
|
||||
"$indexField in (".generateQuestionMarks($idList).")";
|
||||
$params1 = array($idList);
|
||||
$result = $db->pquery($query1, $params1);
|
||||
if (is_object($result)) {
|
||||
$rowCount = $db->num_rows($result);
|
||||
for ($i = 0; $i < $rowCount; $i++) {
|
||||
$id = $db->query_result($result,$i, $indexField);
|
||||
$nameList[$id] = $db->query_result($result,$i,'entityname');
|
||||
}
|
||||
return $nameList;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
function vtws_isRoleBasedPicklist($name) {
|
||||
$db = PearDatabase::getInstance();
|
||||
$sql = "select picklistid from vtiger_picklist where name = ?";
|
||||
$result = $db->pquery($sql, array($name));
|
||||
return ($db->num_rows($result) > 0);
|
||||
}
|
||||
|
||||
function vtws_getConvertLeadFieldMapping(){
|
||||
global $adb;
|
||||
$sql = "select * from vtiger_convertleadmapping";
|
||||
$result = $adb->pquery($sql,array());
|
||||
if($result === false){
|
||||
return null;
|
||||
}
|
||||
$mapping = array();
|
||||
$rowCount = $adb->num_rows($result);
|
||||
for($i=0;$i<$rowCount;++$i){
|
||||
$row = $adb->query_result_rowdata($result,$i);
|
||||
$mapping[$row['leadfid']] = array('Accounts'=>$row['accountfid'],
|
||||
'Potentials'=>$row['potentialfid'],'Contacts'=>$row['contactfid']);
|
||||
}
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/** Function used to get the lead related Notes and Attachments with other entities Account, Contact and Potential
|
||||
* @param integer $id - leadid
|
||||
* @param integer $relatedId - related entity id (accountid / contactid)
|
||||
*/
|
||||
function vtws_getRelatedNotesAttachments($id,$relatedId) {
|
||||
global $adb,$log;
|
||||
|
||||
$sql = "select * from vtiger_senotesrel where crmid=?";
|
||||
$result = $adb->pquery($sql, array($id));
|
||||
if($result === false){
|
||||
return false;
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
|
||||
$sql="insert into vtiger_senotesrel(crmid,notesid) values (?,?)";
|
||||
for($i=0; $i<$rowCount;++$i ) {
|
||||
$noteId=$adb->query_result($result,$i,"notesid");
|
||||
$resultNew = $adb->pquery($sql, array($relatedId, $noteId));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "select * from vtiger_seattachmentsrel where crmid=?";
|
||||
$result = $adb->pquery($sql, array($id));
|
||||
if($result === false){
|
||||
return false;
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
|
||||
$sql = "insert into vtiger_seattachmentsrel(crmid,attachmentsid) values (?,?)";
|
||||
for($i=0;$i<$rowCount;++$i) {
|
||||
$attachmentId=$adb->query_result($result,$i,"attachmentsid");
|
||||
$resultNew = $adb->pquery($sql, array($relatedId, $attachmentId));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Function used to save the lead related products with other entities Account, Contact and Potential
|
||||
* $leadid - leadid
|
||||
* $relatedid - related entity id (accountid/contactid/potentialid)
|
||||
* $setype - related module(Accounts/Contacts/Potentials)
|
||||
*/
|
||||
function vtws_saveLeadRelatedProducts($leadId, $relatedId, $setype) {
|
||||
global $adb;
|
||||
|
||||
$result = $adb->pquery("select * from vtiger_seproductsrel where crmid=?", array($leadId));
|
||||
if($result === false){
|
||||
return false;
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
for($i = 0; $i < $rowCount; ++$i) {
|
||||
$productId = $adb->query_result($result,$i,'productid');
|
||||
$resultNew = $adb->pquery("insert into vtiger_seproductsrel values(?,?,?)", array($relatedId, $productId, $setype));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Function used to save the lead related services with other entities Account, Contact and Potential
|
||||
* $leadid - leadid
|
||||
* $relatedid - related entity id (accountid/contactid/potentialid)
|
||||
* $setype - related module(Accounts/Contacts/Potentials)
|
||||
*/
|
||||
function vtws_saveLeadRelations($leadId, $relatedId, $setype) {
|
||||
global $adb;
|
||||
|
||||
$result = $adb->pquery("select * from vtiger_crmentityrel where crmid=?", array($leadId));
|
||||
if($result === false){
|
||||
return false;
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
for($i = 0; $i < $rowCount; ++$i) {
|
||||
$recordId = $adb->query_result($result,$i,'relcrmid');
|
||||
$recordModule = $adb->query_result($result,$i,'relmodule');
|
||||
$adb->pquery("insert into vtiger_crmentityrel values(?,?,?,?)",
|
||||
array($relatedId, $setype, $recordId, $recordModule));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$result = $adb->pquery("select * from vtiger_crmentityrel where relcrmid=?", array($leadId));
|
||||
if($result === false){
|
||||
return false;
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
for($i = 0; $i < $rowCount; ++$i) {
|
||||
$recordId = $adb->query_result($result,$i,'crmid');
|
||||
$recordModule = $adb->query_result($result,$i,'module');
|
||||
$adb->pquery("insert into vtiger_crmentityrel values(?,?,?,?)",
|
||||
array($relatedId, $setype, $recordId, $recordModule));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function vtws_getFieldfromFieldId($fieldId, $fieldObjectList){
|
||||
foreach ($fieldObjectList as $field) {
|
||||
if($fieldId == $field->getFieldId()){
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Function used to get the lead related activities with other entities Account and Contact
|
||||
* @param integer $leadId - lead entity id
|
||||
* @param integer $accountId - related account id
|
||||
* @param integer $contactId - related contact id
|
||||
* @param integer $relatedId - related entity id to which the records need to be transferred
|
||||
*/
|
||||
function vtws_getRelatedActivities($leadId,$accountId,$contactId,$relatedId) {
|
||||
|
||||
if(empty($leadId) || empty($relatedId) || (empty($accountId) && empty($contactId))){
|
||||
throw new WebServiceException(WebServiceErrorCode::$LEAD_RELATED_UPDATE_FAILED,
|
||||
"Failed to move related Activities/Emails");
|
||||
}
|
||||
global $adb;
|
||||
$sql = "select * from vtiger_seactivityrel where crmid=?";
|
||||
$result = $adb->pquery($sql, array($leadId));
|
||||
if($result === false){
|
||||
return false;
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
for($i=0;$i<$rowCount;++$i) {
|
||||
$activityId=$adb->query_result($result,$i,"activityid");
|
||||
|
||||
$sql ="select setype from vtiger_crmentity where crmid=?";
|
||||
$resultNew = $adb->pquery($sql, array($activityId));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
$type=$adb->query_result($resultNew,0,"setype");
|
||||
|
||||
$sql="delete from vtiger_seactivityrel where crmid=?";
|
||||
$resultNew = $adb->pquery($sql, array($leadId));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
if($type != "Emails") {
|
||||
if(!empty($accountId)){
|
||||
$sql = "insert into vtiger_seactivityrel(crmid,activityid) values (?,?)";
|
||||
$resultNew = $adb->pquery($sql, array($accountId, $activityId));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!empty($contactId)){
|
||||
$sql="insert into vtiger_cntactivityrel(contactid,activityid) values (?,?)";
|
||||
$resultNew = $adb->pquery($sql, array($contactId, $activityId));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sql = "insert into vtiger_seactivityrel(crmid,activityid) values (?,?)";
|
||||
$resultNew = $adb->pquery($sql, array($relatedId, $activityId));
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to save the lead related Campaigns with Contact
|
||||
* @param $leadid - leadid
|
||||
* @param $relatedid - related entity id (contactid/accountid)
|
||||
* @param $setype - related module(Accounts/Contacts)
|
||||
* @return Boolean true on success, false otherwise.
|
||||
*/
|
||||
function vtws_saveLeadRelatedCampaigns($leadId, $relatedId, $seType) {
|
||||
global $adb;
|
||||
|
||||
$result = $adb->pquery("select * from vtiger_campaignleadrel where leadid=?", array($leadId));
|
||||
if($result === false){
|
||||
return false;
|
||||
}
|
||||
$rowCount = $adb->num_rows($result);
|
||||
for($i = 0; $i < $rowCount; ++$i) {
|
||||
$campaignId = $adb->query_result($result,$i,'campaignid');
|
||||
if($seType == 'Accounts') {
|
||||
$resultNew = $adb->pquery("insert into vtiger_campaignaccountrel (campaignid, accountid) values(?,?)",
|
||||
array($campaignId, $relatedId));
|
||||
} elseif ($seType == 'Contacts') {
|
||||
$resultNew = $adb->pquery("insert into vtiger_campaigncontrel (campaignid, contactid) values(?,?)",
|
||||
array($campaignId, $relatedId));
|
||||
}
|
||||
if($resultNew === false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to transfer all the lead related records to given Entity(Contact/Account) record
|
||||
* @param $leadid - leadid
|
||||
* @param $relatedid - related entity id (contactid/accountid)
|
||||
* @param $setype - related module(Accounts/Contacts)
|
||||
*/
|
||||
function vtws_transferLeadRelatedRecords($leadId, $relatedId, $seType) {
|
||||
|
||||
if(empty($leadId) || empty($relatedId) || empty($seType)){
|
||||
throw new WebServiceException(WebServiceErrorCode::$LEAD_RELATED_UPDATE_FAILED,
|
||||
"Failed to move related Records");
|
||||
}
|
||||
$status = vtws_getRelatedNotesAttachments($leadId, $relatedId);
|
||||
if($status === false){
|
||||
throw new WebServiceException(WebServiceErrorCode::$LEAD_RELATED_UPDATE_FAILED,
|
||||
"Failed to move related Documents to the ".$seType);
|
||||
}
|
||||
//Retrieve the lead related products and relate them with this new account
|
||||
$status = vtws_saveLeadRelatedProducts($leadId, $relatedId, $seType);
|
||||
if($status === false){
|
||||
throw new WebServiceException(WebServiceErrorCode::$LEAD_RELATED_UPDATE_FAILED,
|
||||
"Failed to move related Products to the ".$seType);
|
||||
}
|
||||
$status = vtws_saveLeadRelations($leadId, $relatedId, $seType);
|
||||
if($status === false){
|
||||
throw new WebServiceException(WebServiceErrorCode::$LEAD_RELATED_UPDATE_FAILED,
|
||||
"Failed to move Records to the ".$seType);
|
||||
}
|
||||
$status = vtws_saveLeadRelatedCampaigns($leadId, $relatedId, $seType);
|
||||
if($status === false){
|
||||
throw new WebServiceException(WebServiceErrorCode::$LEAD_RELATED_UPDATE_FAILED,
|
||||
"Failed to move Records to the ".$seType);
|
||||
}
|
||||
vtws_transferComments($leadId, $relatedId);
|
||||
}
|
||||
|
||||
function vtws_transferComments($sourceRecordId, $destinationRecordId) {
|
||||
if(vtlib_isModuleActive('ModComments')) {
|
||||
CRMEntity::getInstance('ModComments'); ModComments::transferRecords($sourceRecordId, $destinationRecordId);
|
||||
}
|
||||
}
|
||||
|
||||
function vtws_transferOwnership($ownerId, $newOwnerId, $delete=true) {
|
||||
$db = PearDatabase::getInstance();
|
||||
//Updating the smcreatorid,smownerid, modifiedby in vtiger_crmentity
|
||||
$sql = "update vtiger_crmentity set smcreatorid=? where smcreatorid=?";
|
||||
$db->pquery($sql, array($newOwnerId, $ownerId));
|
||||
|
||||
$sql = "update vtiger_crmentity set smownerid=? where smownerid=?";
|
||||
$db->pquery($sql, array($newOwnerId, $ownerId));
|
||||
|
||||
$sql = "update vtiger_crmentity set modifiedby=? where modifiedby=?";
|
||||
$db->pquery($sql, array($newOwnerId, $ownerId));
|
||||
|
||||
//deleting from vtiger_tracker
|
||||
if ($delete) {
|
||||
$sql = "delete from vtiger_tracker where user_id=?";
|
||||
$db->pquery($sql, array($ownerId));
|
||||
}
|
||||
|
||||
//updating created by in vtiger_lar
|
||||
$sql = "update vtiger_lar set createdby=? where createdby=?";
|
||||
$db->pquery($sql, array($newOwnerId, $ownerId));
|
||||
|
||||
//updating the vtiger_import_maps
|
||||
$sql ="update vtiger_import_maps set assigned_user_id=? where assigned_user_id=?";
|
||||
$db->pquery($sql, array($newOwnerId, $ownerId));
|
||||
|
||||
//update assigned_user_id in vtiger_files
|
||||
$sql ="update vtiger_files set assigned_user_id=? where assigned_user_id=?";
|
||||
$db->pquery($sql, array($newOwnerId, $ownerId));
|
||||
|
||||
if(Vtiger_Utils::CheckTable('vtiger_customerportal_prefs')) {
|
||||
$query = 'UPDATE vtiger_customerportal_prefs SET prefvalue = ? WHERE prefkey = ? AND prefvalue = ?';
|
||||
$params = array($newOwnerId, 'defaultassignee', $ownerId);
|
||||
$db->pquery($query, $params);
|
||||
|
||||
$query = 'UPDATE vtiger_customerportal_prefs SET prefvalue = ? WHERE prefkey = ? AND prefvalue = ?';
|
||||
$params = array($newOwnerId, 'userid', $ownerId);
|
||||
$db->pquery($query, $params);
|
||||
}
|
||||
|
||||
//delete from vtiger_homestuff
|
||||
if ($delete) {
|
||||
$sql = "delete from vtiger_homestuff where userid=?";
|
||||
$db->pquery($sql, array($ownerId));
|
||||
}
|
||||
|
||||
//delete from vtiger_users to group vtiger_table
|
||||
if ($delete) {
|
||||
$sql = "delete from vtiger_user2role where userid=?";
|
||||
$db->pquery($sql, array($ownerId));
|
||||
}
|
||||
|
||||
//delete from vtiger_users to vtiger_role vtiger_table
|
||||
if ($delete) {
|
||||
$sql = "delete from vtiger_users2group where userid=?";
|
||||
$db->pquery($sql, array($ownerId));
|
||||
}
|
||||
|
||||
$sql = "select tabid,fieldname,tablename,columnname from vtiger_field left join ".
|
||||
"vtiger_fieldmodulerel on vtiger_field.fieldid=vtiger_fieldmodulerel.fieldid where uitype ".
|
||||
"in (52,53,77,101) or (uitype=10 and relmodule='Users')";
|
||||
$result = $db->pquery($sql, array());
|
||||
$it = new SqlResultIterator($db, $result);
|
||||
$columnList = array();
|
||||
foreach ($it as $row) {
|
||||
$column = $row->tablename.'.'.$row->columnname;
|
||||
if(!in_array($column, $columnList)) {
|
||||
$columnList[] = $column;
|
||||
$sql = "update $row->tablename set $row->columnname=? where $row->columnname=?";
|
||||
$db->pquery($sql, array($newOwnerId, $ownerId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function vtws_getWebserviceTranslatedStringForLanguage($label, $currentLanguage) {
|
||||
static $translations = array();
|
||||
$currentLanguage = vtws_getWebserviceCurrentLanguage();
|
||||
if(empty($translations[$currentLanguage])) {
|
||||
include 'include/Webservices/language/'.$currentLanguage.'.lang.php';
|
||||
$translations[$currentLanguage] = $webservice_strings;
|
||||
}
|
||||
if(isset($translations[$currentLanguage][$label])) {
|
||||
return $translations[$currentLanguage][$label];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function vtws_getWebserviceTranslatedString($label) {
|
||||
$currentLanguage = vtws_getWebserviceCurrentLanguage();
|
||||
$translation = vtws_getWebserviceTranslatedStringForLanguage($label, $currentLanguage);
|
||||
if(!empty($translation)) {
|
||||
return $translation;
|
||||
}
|
||||
|
||||
//current language doesn't have translation, return translation in default language
|
||||
//if default language is english then LBL_ will not shown to the user.
|
||||
$defaultLanguage = vtws_getWebserviceDefaultLanguage();
|
||||
$translation = vtws_getWebserviceTranslatedStringForLanguage($label, $defaultLanguage);
|
||||
if(!empty($translation)) {
|
||||
return $translation;
|
||||
}
|
||||
|
||||
//if default language is not en_us then do the translation in en_us to eliminate the LBL_ bit
|
||||
//of label.
|
||||
if('en_us' != $defaultLanguage) {
|
||||
$translation = vtws_getWebserviceTranslatedStringForLanguage($label, 'en_us');
|
||||
if(!empty($translation)) {
|
||||
return $translation;
|
||||
}
|
||||
}
|
||||
return $label;
|
||||
}
|
||||
|
||||
function vtws_getWebserviceCurrentLanguage() {
|
||||
global $default_language, $current_language;
|
||||
if(empty($current_language)) {
|
||||
return $default_language;
|
||||
}
|
||||
return $current_language;
|
||||
}
|
||||
|
||||
function vtws_getWebserviceDefaultLanguage() {
|
||||
global $default_language;
|
||||
return $default_language;
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,316 @@
|
|||
<?php
|
||||
global $where_col,$orderby,$in_started,$count;
|
||||
$where_col = false;
|
||||
$orderby = false;
|
||||
$in_started = false;
|
||||
$count = false;
|
||||
function incrementN($lexer, $count){
|
||||
$i = 0;
|
||||
for(;$i<$count;$i++){
|
||||
incState($lexer);
|
||||
}
|
||||
}
|
||||
function incState($lexer){
|
||||
$lexer->current_state++;
|
||||
if($lexer->current_state === sizeof($lexer->mandatory_states)){
|
||||
$lexer->mandatory = false;
|
||||
}
|
||||
}
|
||||
function handleselect($lexer, $val){
|
||||
if($lexer->mandatory){
|
||||
if(strcasecmp($val, $lexer->mandatory_states[$lexer->current_state])===0){
|
||||
incState($lexer);
|
||||
return VTQL_Parser::SELECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
function handlecolumn_list($lexer, $val){
|
||||
global $count;
|
||||
if($lexer->mandatory){
|
||||
if(!(strcasecmp($val, $lexer->mandatory_states[2])===0)){
|
||||
if(strcmp($val, "*")===0){
|
||||
if(!$count){
|
||||
incrementN($lexer, 1);
|
||||
}
|
||||
return VTQL_Parser::ASTERISK;
|
||||
}else if((strcmp($val, "(")===0)){
|
||||
return VTQL_Parser::PARENOPEN;
|
||||
}else if(strcmp($val, ")")===0){
|
||||
return VTQL_Parser::PARENCLOSE;
|
||||
}else if((strcasecmp($val, "count")===0)){
|
||||
$count = true;
|
||||
return VTQL_Parser::COUNT;
|
||||
}else if(strcmp($val, ",")===0){
|
||||
return VTQL_Parser::COMMA;
|
||||
}else{
|
||||
return VTQL_Parser::COLUMNNAME;
|
||||
}
|
||||
}else{
|
||||
incrementN($lexer, 2);
|
||||
return VTQL_Parser::FRM;
|
||||
}
|
||||
}
|
||||
}
|
||||
function handlefrom($lexer, $val){
|
||||
if((strcasecmp($val, $lexer->mandatory_states[$lexer->current_state])===0)){
|
||||
incState($lexer);
|
||||
return VTQL_Parser::FRM;
|
||||
}
|
||||
}
|
||||
function handletable($lexer, $val){
|
||||
if($lexer->mandatory){
|
||||
$lexer->current_state =0;
|
||||
$lexer->mandatory = false;
|
||||
if(!(strcasecmp($val, $lexer->optional_states[$lexer->current_state])===0)){
|
||||
return VTQL_Parser::TABLENAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
function handlewhere($lexer, $val){
|
||||
global $where_col,$in_started;
|
||||
$val = trim($val);
|
||||
if((strcmp($val, "=")===0)){
|
||||
return VTQL_Parser::EQ;
|
||||
}else if((strcasecmp($val, $lexer->optional_states[$lexer->current_state])===0)){
|
||||
return VTQL_Parser::WHERE;
|
||||
}else if((strcmp($val, "<")===0)){
|
||||
return VTQL_Parser::LT;
|
||||
}else if((strcmp($val, "<=")===0)){
|
||||
return VTQL_Parser::LTE;
|
||||
}else if((strcmp($val, ">=")===0)){
|
||||
return VTQL_Parser::GTE;
|
||||
}else if((strcmp($val, "!=")===0)){
|
||||
return VTQL_Parser::NE;
|
||||
}else if((strcmp($val, ">")===0)){
|
||||
return VTQL_Parser::GT;
|
||||
}else if((strcmp($val, "(")===0)){
|
||||
return VTQL_Parser::PARENOPEN;
|
||||
}else if((strcmp($val, ")")===0)){
|
||||
if($in_started){
|
||||
$in_started = false;
|
||||
$where_col = false;
|
||||
}
|
||||
return VTQL_Parser::PARENCLOSE;
|
||||
}else if((strcasecmp($val, "and")===0)){
|
||||
return VTQL_Parser::LOGICAL_AND;
|
||||
}else if((strcasecmp($val, "or")===0)){
|
||||
return VTQL_Parser::LOGICAL_OR;
|
||||
}else if(!$where_col){
|
||||
$where_col = true;
|
||||
return VTQL_Parser::COLUMNNAME;
|
||||
}else if((strcasecmp($val, "in")===0)){
|
||||
$in_started = true;
|
||||
return VTQL_Parser::IN;
|
||||
}else if(strcmp($val, ",")===0){
|
||||
return VTQL_Parser::COMMA;
|
||||
}else if(strcasecmp($val, "like")===0){
|
||||
return VTQL_Parser::LIKE;
|
||||
}else if($where_col){
|
||||
if(!$in_started){
|
||||
$where_col = false;
|
||||
}
|
||||
return VTQL_Parser::VALUE;
|
||||
}
|
||||
}
|
||||
function handleorderby($lexer, $val){
|
||||
global $orderby;
|
||||
if(!$orderby){
|
||||
$orderby = true;
|
||||
return VTQL_Parser::ORDERBY;
|
||||
}
|
||||
if(strcmp($val, ",")===0){
|
||||
return VTQL_Parser::COMMA;
|
||||
}else if(strcasecmp($val, "asc")===0){
|
||||
return VTQL_Parser::ASC;
|
||||
}else if(strcasecmp($val, "desc")===0){
|
||||
return VTQL_Parser::DESC;
|
||||
}else{
|
||||
return VTQL_Parser::COLUMNNAME;
|
||||
}
|
||||
}
|
||||
function handlelimit($lexer, $val){
|
||||
if((strcasecmp($val, "limit")===0)){
|
||||
return VTQL_Parser::LIMIT;
|
||||
}else if((strcmp($val, "(")===0)){
|
||||
return VTQL_Parser::PARENOPEN;
|
||||
}else if((strcmp($val, ")")===0)){
|
||||
return VTQL_Parser::PARENCLOSE;
|
||||
}else if(strcmp($val, ",")===0){
|
||||
return VTQL_Parser::COMMA;
|
||||
}else{
|
||||
return VTQL_Parser::VALUE;
|
||||
}
|
||||
}
|
||||
function handleend($lexer, $val){
|
||||
return VTQL_Parser::SEMICOLON;
|
||||
}
|
||||
class VTQL_Lexer{
|
||||
private $index;
|
||||
public $token;
|
||||
public $value;
|
||||
public $linenum;
|
||||
public $state = 1;
|
||||
private $data;
|
||||
public $mandatory_states = array('select','column_list','from','table');
|
||||
public $optional_states = array('where', 'orderby', 'limit');
|
||||
public $mandatory ;
|
||||
public $current_state ;
|
||||
function __construct($data)
|
||||
{
|
||||
$this->index = 0;
|
||||
$this->data = $data;
|
||||
$this->linenum = 1;
|
||||
$this->mandatory = true;
|
||||
$this->current_state = 0;
|
||||
}
|
||||
function __toString(){
|
||||
return $this->token."";
|
||||
}
|
||||
|
||||
private $_yy_state = 1;
|
||||
private $_yy_stack = array();
|
||||
|
||||
function yylex()
|
||||
{
|
||||
return $this->{'yylex' . $this->_yy_state}();
|
||||
}
|
||||
|
||||
function yypushstate($state)
|
||||
{
|
||||
array_push($this->_yy_stack, $this->_yy_state);
|
||||
$this->_yy_state = $state;
|
||||
}
|
||||
|
||||
function yypopstate()
|
||||
{
|
||||
$this->_yy_state = array_pop($this->_yy_stack);
|
||||
}
|
||||
|
||||
function yybegin($state)
|
||||
{
|
||||
$this->_yy_state = $state;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function yylex1()
|
||||
{
|
||||
$tokenMap = array (
|
||||
1 => 2,
|
||||
4 => 0,
|
||||
);
|
||||
if ($this->index >= strlen($this->data)) {
|
||||
return false; // end of input
|
||||
}
|
||||
$yy_global_pattern = "/^((\\w+|'(?:[^']|'')+'|\\(|\\)|(\\+|-)?\\d+|,|\\*|(?!<|>)=|<(?!=)|>(?!=)|<=|>=|!=|;))|^([ \t\r\n]+)/";
|
||||
|
||||
do {
|
||||
if (preg_match($yy_global_pattern, substr($this->data, $this->index), $yymatches)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if (!count($yymatches)) {
|
||||
throw new Exception('Error: lexing failed because a rule matched' .
|
||||
'an empty string. Input "' . substr($this->data,
|
||||
$this->index, 5) . '... state INITR');
|
||||
}
|
||||
next($yymatches); // skip global match
|
||||
$this->token = key($yymatches); // token number
|
||||
if ($tokenMap[$this->token]) {
|
||||
// extract sub-patterns for passing to lex function
|
||||
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
|
||||
$tokenMap[$this->token]);
|
||||
} else {
|
||||
$yysubmatches = array();
|
||||
}
|
||||
$this->value = current($yymatches); // token value
|
||||
$r = $this->{'yy_r1_' . $this->token}($yysubmatches);
|
||||
if ($r === null) {
|
||||
$this->index += strlen($this->value);
|
||||
$this->linenum += substr_count("\n", $this->value);
|
||||
// accept this token
|
||||
return true;
|
||||
} elseif ($r === true) {
|
||||
// we have changed state
|
||||
// process this token in the new state
|
||||
return $this->yylex();
|
||||
} elseif ($r === false) {
|
||||
$this->index += strlen($this->value);
|
||||
$this->linenum += substr_count("\n", $this->value);
|
||||
if ($this->index >= strlen($this->data)) {
|
||||
return false; // end of input
|
||||
}
|
||||
// skip this token
|
||||
continue;
|
||||
} else { $yy_yymore_patterns = array(
|
||||
1 => "^([ \t\r\n]+)",
|
||||
4 => "",
|
||||
);
|
||||
|
||||
// yymore is needed
|
||||
do {
|
||||
if (!strlen($yy_yymore_patterns[$this->token])) {
|
||||
throw new Exception('cannot do yymore for the last token');
|
||||
}
|
||||
if (preg_match($yy_yymore_patterns[$this->token],
|
||||
substr($this->data, $this->index), $yymatches)) {
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
$this->token = key($yymatches); // token number
|
||||
$this->value = current($yymatches); // token value
|
||||
$this->linenum = substr_count("\n", $this->value);
|
||||
}
|
||||
} while ($this->{'yy_r1_' . $this->token}() !== null);
|
||||
// accept
|
||||
$this->index += strlen($this->value);
|
||||
$this->linenum += substr_count("\n", $this->value);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
throw new Exception('Unexpected input at line' . $this->linenum .
|
||||
': ' . $this->data[$this->index]);
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
} // end function
|
||||
|
||||
|
||||
const INITR = 1;
|
||||
function yy_r1_1($yy_subpatterns)
|
||||
{
|
||||
|
||||
global $orderby;
|
||||
//echo "<br> ql state: ",$this->current_state," ",$this->value,"<br>";
|
||||
if($this->mandatory){
|
||||
//echo "<br> ql state: ",$this->current_state," ",$this->value,"<br>";
|
||||
$handler = 'handle'.$this->mandatory_states[$this->current_state];
|
||||
$this->token = $handler($this, $this->value);
|
||||
}else{
|
||||
$str = $this->value;
|
||||
if(strcmp($this->value, ";")===0){
|
||||
$this->token = handleend($this, $this->value);
|
||||
return;
|
||||
}
|
||||
if(strcasecmp($this->value, "order")===0){
|
||||
$orderby = true;
|
||||
return false;
|
||||
}else if(strcasecmp($this->value, "by") ===0 && $orderby ===true){
|
||||
$orderby = false;
|
||||
$this->current_state = 1;
|
||||
}
|
||||
$index = array_search(strtolower($str), $this->optional_states, true);
|
||||
if($index !== false){
|
||||
$this->current_state = $index;
|
||||
}
|
||||
$handler = 'handle'.$this->optional_states[$this->current_state];
|
||||
$this->token = $handler($this, $this->value);
|
||||
}//$this->yypushstate($this->value);
|
||||
}
|
||||
function yy_r1_4($yy_subpatterns)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,337 @@
|
|||
<?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/Webservices/VtigerCRMActorMeta.php';
|
||||
class VtigerActorOperation extends WebserviceEntityOperation {
|
||||
protected $entityTableName;
|
||||
protected $moduleFields;
|
||||
protected $isEntity = false;
|
||||
protected $element;
|
||||
protected $id;
|
||||
|
||||
public function __construct($webserviceObject,$user,$adb,$log){
|
||||
parent::__construct($webserviceObject,$user,$adb,$log);
|
||||
$this->entityTableName = $this->getActorTables();
|
||||
if($this->entityTableName === null){
|
||||
throw new WebServiceException(WebServiceErrorCode::$UNKOWNENTITY,"Entity is not associated with any tables");
|
||||
}
|
||||
$this->meta = $this->getMetaInstance();
|
||||
$this->moduleFields = null;
|
||||
$this->element = null;
|
||||
$this->id = null;
|
||||
}
|
||||
|
||||
protected function getMetaInstance(){
|
||||
if(empty(WebserviceEntityOperation::$metaCache[$this->webserviceObject->getEntityName()][$this->user->id])){
|
||||
WebserviceEntityOperation::$metaCache[$this->webserviceObject->getEntityName()][$this->user->id]
|
||||
= new VtigerCRMActorMeta($this->entityTableName,$this->webserviceObject,$this->pearDB,$this->user);
|
||||
}
|
||||
return WebserviceEntityOperation::$metaCache[$this->webserviceObject->getEntityName()][$this->user->id];
|
||||
}
|
||||
|
||||
protected function getActorTables(){
|
||||
static $actorTables = array();
|
||||
|
||||
if(isset($actorTables[$this->webserviceObject->getEntityName()])){
|
||||
return $actorTables[$this->webserviceObject->getEntityName()];
|
||||
}
|
||||
$sql = 'select table_name from vtiger_ws_entity_tables where webservice_entity_id=?';
|
||||
$result = $this->pearDB->pquery($sql,array($this->webserviceObject->getEntityId()));
|
||||
$tableName = null;
|
||||
if($result){
|
||||
$rowCount = $this->pearDB->num_rows($result);
|
||||
for($i=0;$i<$rowCount;++$i){
|
||||
$row = $this->pearDB->query_result_rowdata($result,$i);
|
||||
$tableName = $row['table_name'];
|
||||
}
|
||||
// Cache the result for further re-use
|
||||
$actorTables[$this->webserviceObject->getEntityName()] = $tableName;
|
||||
}
|
||||
return $tableName;
|
||||
}
|
||||
|
||||
public function getMeta(){
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
protected function getNextId($elementType,$element){
|
||||
if(strcasecmp($elementType,'Groups') === 0){
|
||||
$tableName="vtiger_users";
|
||||
}else{
|
||||
$tableName = $this->entityTableName;
|
||||
|
||||
}
|
||||
$meta = $this->getMeta();
|
||||
if(strcasecmp($elementType,'Groups') !== 0 && strcasecmp($elementType,'Users') !== 0) {
|
||||
$sql = "update $tableName"."_seq set id=(select max(".$meta->getIdColumn().")
|
||||
from $tableName)";
|
||||
$this->pearDB->pquery($sql,array());
|
||||
}
|
||||
$id = $this->pearDB->getUniqueId($tableName);
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function __create($elementType,$element){
|
||||
require_once 'include/utils/utils.php';
|
||||
$db = PearDatabase::getInstance();
|
||||
|
||||
$this->id=$this->getNextId($elementType, $element);
|
||||
|
||||
$element[$this->meta->getObectIndexColumn()] = $this->id;
|
||||
|
||||
//Insert into group vtiger_table
|
||||
$query = "insert into {$this->entityTableName}(".implode(',',array_keys($element)).
|
||||
") values(".generateQuestionMarks(array_keys($element)).")";
|
||||
$result = null;
|
||||
$transactionSuccessful = vtws_runQueryAsTransaction($query, array_values($element),
|
||||
$result);
|
||||
return $transactionSuccessful;
|
||||
}
|
||||
|
||||
public function create($elementType,$element){
|
||||
$element = DataTransform::sanitizeForInsert($element,$this->meta);
|
||||
|
||||
$element = $this->restrictFields($element);
|
||||
|
||||
$success = $this->__create($elementType,$element);
|
||||
if(!$success){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
return $this->retrieve(vtws_getId($this->meta->getEntityId(),$this->id));
|
||||
}
|
||||
|
||||
protected function restrictFields($element, $selectedOnly = false){
|
||||
$fields = $this->getModuleFields();
|
||||
$newElement = array();
|
||||
foreach ($fields as $field) {
|
||||
if(isset($element[$field['name']])){
|
||||
$newElement[$field['name']] = $element[$field['name']];
|
||||
}else if($field['name'] != 'id' && $selectedOnly == false){
|
||||
$newElement[$field['name']] = '';
|
||||
}
|
||||
}
|
||||
return $newElement;
|
||||
}
|
||||
|
||||
public function __retrieve($id){
|
||||
$query = "select * from {$this->entityTableName} where {$this->meta->getObectIndexColumn()}=?";
|
||||
$transactionSuccessful = vtws_runQueryAsTransaction($query,array($id),$result);
|
||||
if(!$transactionSuccessful){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
$db = $this->pearDB;
|
||||
if($result){
|
||||
$rowCount = $db->num_rows($result);
|
||||
if($rowCount >0){
|
||||
$this->element = $db->query_result_rowdata($result,0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function retrieve($id){
|
||||
|
||||
$ids = vtws_getIdComponents($id);
|
||||
$elemId = $ids[1];
|
||||
$success = $this->__retrieve($elemId);
|
||||
if(!$success){
|
||||
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND,
|
||||
"Record not found");
|
||||
}
|
||||
$element = $this->getElement();
|
||||
|
||||
return DataTransform::filterAndSanitize($element,$this->meta);
|
||||
}
|
||||
|
||||
public function __update($element,$id){
|
||||
$columnStr = 'set '.implode('=?,',array_keys($element)).' =? ';
|
||||
$query = 'update '.$this->entityTableName.' '.$columnStr.'where '.
|
||||
$this->meta->getObectIndexColumn().'=?';
|
||||
$params = array_values($element);
|
||||
array_push($params,$id);
|
||||
$result = null;
|
||||
$transactionSuccessful = vtws_runQueryAsTransaction($query,$params,$result);
|
||||
return $transactionSuccessful;
|
||||
}
|
||||
|
||||
public function update($element){
|
||||
$ids = vtws_getIdComponents($element["id"]);
|
||||
$element = DataTransform::sanitizeForInsert($element,$this->meta);
|
||||
$element = $this->restrictFields($element);
|
||||
|
||||
$success = $this->__update($element,$ids[1]);
|
||||
if(!$success){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
return $this->retrieve(vtws_getId($this->meta->getEntityId(),$ids[1]));
|
||||
}
|
||||
|
||||
public function __revise($element,$id){
|
||||
$columnStr = 'set '.implode('=?,',array_keys($element)).' =? ';
|
||||
$query = 'update '.$this->entityTableName.' '.$columnStr.'where '.
|
||||
$this->meta->getObectIndexColumn().'=?';
|
||||
$params = array_values($element);
|
||||
array_push($params,$id);
|
||||
$result = null;
|
||||
$transactionSuccessful = vtws_runQueryAsTransaction($query,$params,$result);
|
||||
return $transactionSuccessful;
|
||||
}
|
||||
|
||||
public function revise($element){
|
||||
$ids = vtws_getIdComponents($element["id"]);
|
||||
|
||||
$element = DataTransform::sanitizeForInsert($element,$this->meta);
|
||||
$element = $this->restrictFields($element, true);
|
||||
|
||||
$success = $this->__retrieve($ids[1]);
|
||||
if(!$success){
|
||||
throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND,
|
||||
"Record not found");
|
||||
}
|
||||
|
||||
$allDetails = $this->getElement();
|
||||
foreach ($allDetails as $index=>$value) {
|
||||
if(!isset($element)){
|
||||
$element[$index] = $value;
|
||||
}
|
||||
}
|
||||
$success = $this->__revise($element,$ids[1]);
|
||||
if(!$success){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
return $this->retrieve(vtws_getId($this->meta->getEntityId(),$ids[1]));
|
||||
}
|
||||
|
||||
public function __delete($elemId){
|
||||
$result = null;
|
||||
$query = 'delete from '.$this->entityTableName.' where '.
|
||||
$this->meta->getObectIndexColumn().'=?';
|
||||
$transactionSuccessful = vtws_runQueryAsTransaction($query,array($elemId),$result);
|
||||
return $transactionSuccessful;
|
||||
}
|
||||
|
||||
public function delete($id){
|
||||
$ids = vtws_getIdComponents($id);
|
||||
$elemId = $ids[1];
|
||||
|
||||
$success = $this->__delete($elemId);
|
||||
if(!$success){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
return array("status"=>"successful");
|
||||
}
|
||||
|
||||
public function describe($elementType){
|
||||
|
||||
$app_strings = VTWS_PreserveGlobal::getGlobal('app_strings');
|
||||
$current_user = vtws_preserveGlobal('current_user',$this->user);;
|
||||
$label = (isset($app_strings[$elementType]))? $app_strings[$elementType]:$elementType;
|
||||
$createable = $this->meta->hasWriteAccess();
|
||||
$updateable = $this->meta->hasWriteAccess();
|
||||
$deleteable = $this->meta->hasDeleteAccess();
|
||||
$retrieveable = $this->meta->hasReadAccess();
|
||||
$fields = $this->getModuleFields();
|
||||
return array("label"=>$label,"name"=>$elementType,"createable"=>$createable,"updateable"=>$updateable,
|
||||
"deleteable"=>$deleteable,"retrieveable"=>$retrieveable,"fields"=>$fields,
|
||||
"idPrefix"=>$this->meta->getEntityId(),'isEntity'=>$this->isEntity,'labelFields'=>$this->meta->getNameFields());
|
||||
}
|
||||
|
||||
function getModuleFields(){
|
||||
$app_strings = VTWS_PreserveGlobal::getGlobal('app_strings');
|
||||
if($this->moduleFields === null){
|
||||
$fields = array();
|
||||
$moduleFields = $this->meta->getModuleFields();
|
||||
foreach ($moduleFields as $fieldName=>$webserviceField) {
|
||||
array_push($fields,$this->getDescribeFieldArray($webserviceField));
|
||||
}
|
||||
$label = ($app_strings[$this->meta->getObectIndexColumn()])? $app_strings[$this->meta->getObectIndexColumn()]:
|
||||
$this->meta->getObectIndexColumn();
|
||||
$this->moduleFields = $fields;
|
||||
}
|
||||
return $this->moduleFields;
|
||||
}
|
||||
|
||||
function getDescribeFieldArray($webserviceField){
|
||||
$app_strings = VTWS_PreserveGlobal::getGlobal('app_strings');
|
||||
$fieldLabel = $webserviceField->getFieldLabelKey();
|
||||
if(isset($app_strings[$fieldLabel])){
|
||||
$fieldLabel = $app_strings[$fieldLabel];
|
||||
}
|
||||
if(strcasecmp($webserviceField->getFieldName(),$this->meta->getObectIndexColumn()) === 0){
|
||||
return $this->getIdField($fieldLabel);
|
||||
}
|
||||
|
||||
$typeDetails = $this->getFieldTypeDetails($webserviceField);
|
||||
|
||||
//set type name, in the type details array.
|
||||
$typeDetails['name'] = $webserviceField->getFieldDataType();
|
||||
$editable = $this->isEditable($webserviceField);
|
||||
|
||||
$describeArray = array('name'=>$webserviceField->getFieldName(),'label'=>$fieldLabel,'mandatory'=>
|
||||
$webserviceField->isMandatory(),'type'=>$typeDetails,'nullable'=>$webserviceField->isNullable(),
|
||||
"editable"=>$editable);
|
||||
if($webserviceField->hasDefault()){
|
||||
$describeArray['default'] = $webserviceField->getDefault();
|
||||
}
|
||||
return $describeArray;
|
||||
}
|
||||
public function query($q){
|
||||
|
||||
$parser = new Parser($this->user, $q);
|
||||
$error = $parser->parse();
|
||||
|
||||
if($error){
|
||||
return $parser->getError();
|
||||
}
|
||||
|
||||
$mysql_query = $parser->getSql();
|
||||
$meta = $parser->getObjectMetaData();
|
||||
$this->pearDB->startTransaction();
|
||||
$result = $this->pearDB->pquery($mysql_query, array());
|
||||
$error = $this->pearDB->hasFailedTransaction();
|
||||
$this->pearDB->completeTransaction();
|
||||
|
||||
if($error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
$noofrows = $this->pearDB->num_rows($result);
|
||||
$output = array();
|
||||
for($i=0; $i<$noofrows; $i++){
|
||||
$row = $this->pearDB->fetchByAssoc($result,$i);
|
||||
if(!$meta->hasPermission(EntityMeta::$RETRIEVE,$row["crmid"])){
|
||||
continue;
|
||||
}
|
||||
$output[] = DataTransform::sanitizeDataWithColumn($row,$meta);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected function getElement(){
|
||||
return $this->element;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,282 @@
|
|||
<?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 VtigerCRMActorMeta extends EntityMeta {
|
||||
protected $pearDB;
|
||||
protected static $fieldTypeMapping = array();
|
||||
|
||||
function VtigerCRMActorMeta($tableName,$webserviceObject,$adb,$user){
|
||||
parent::__construct($webserviceObject,$user);
|
||||
$this->baseTable = $tableName;
|
||||
$this->idColumn = null;
|
||||
$this->pearDB = $adb;
|
||||
|
||||
$fieldList = $this->getTableFieldList($tableName);
|
||||
$this->moduleFields = array();
|
||||
foreach ($fieldList as $field) {
|
||||
$this->moduleFields[$field->getFieldName()] = $field;
|
||||
}
|
||||
|
||||
$this->pearDB = $adb;
|
||||
$this->tableList = array($this->baseTable);
|
||||
$this->tableIndexList = array($this->baseTable=>$this->idColumn);
|
||||
$this->defaultTableList = array();
|
||||
}
|
||||
|
||||
protected function getTableFieldList($tableName){
|
||||
$tableFieldList = array();
|
||||
|
||||
$factory = WebserviceField::fromArray($this->pearDB,array('tablename'=>$tableName));
|
||||
$dbTableFields = $factory->getTableFields();
|
||||
foreach ($dbTableFields as $dbField) {
|
||||
if($dbField->primary_key){
|
||||
if($this->idColumn === null){
|
||||
$this->idColumn = $dbField->name;
|
||||
}else{
|
||||
throw new WebServiceException(WebServiceErrorCode::$UNKOWNENTITY,
|
||||
"Entity table with multi column primary key is not supported");
|
||||
}
|
||||
}
|
||||
$field = $this->getFieldArrayFromDBField($dbField,$tableName);
|
||||
$webserviceField = WebserviceField::fromArray($this->pearDB,$field);
|
||||
$fieldDataType = $this->getFieldType($dbField,$tableName);
|
||||
if($fieldDataType === null){
|
||||
$fieldDataType = $this->getFieldDataTypeFromDBType($dbField->type);
|
||||
}
|
||||
$webserviceField->setFieldDataType($fieldDataType);
|
||||
if(strcasecmp($fieldDataType,'reference') === 0){
|
||||
$webserviceField->setReferenceList($this->getReferenceList($dbField,$tableName));
|
||||
}
|
||||
array_push($tableFieldList,$webserviceField);
|
||||
}
|
||||
return $tableFieldList;
|
||||
}
|
||||
|
||||
protected function getFieldArrayFromDBField($dbField,$tableName){
|
||||
$field = array();
|
||||
$field['fieldname'] = $dbField->name;
|
||||
$field['columnname'] = $dbField->name;
|
||||
$field['tablename'] = $tableName;
|
||||
$field['fieldlabel'] = str_replace('_', ' ',$dbField->name);
|
||||
$field['displaytype'] = 1;
|
||||
$field['uitype'] = 1;
|
||||
$fieldDataType = $this->getFieldType($dbField,$tableName);
|
||||
if($fieldDataType !== null){
|
||||
$fieldType = $this->getTypeOfDataForType($fieldDataType);
|
||||
}else{
|
||||
$fieldType = $this->getTypeOfDataForType($dbField->type);
|
||||
}
|
||||
$typeOfData = null;
|
||||
if(($dbField->not_null && !$dbField->primary_key) || $dbField->unique_key == 1){
|
||||
$typeOfData = $fieldType.'~M';
|
||||
}else{
|
||||
$typeOfData = $fieldType.'~O';
|
||||
}
|
||||
$field['typeofdata'] = $typeOfData;
|
||||
$field['tabid'] = null;
|
||||
$field['fieldid'] = null;
|
||||
$field['masseditable'] = 0;
|
||||
$field['presence'] = '0';
|
||||
return $field;
|
||||
}
|
||||
|
||||
protected function getReferenceList($dbField, $tableName){
|
||||
static $referenceList = array();
|
||||
if(isset($referenceList[$dbField->name])){
|
||||
return $referenceList[$dbField->name];
|
||||
}
|
||||
if(!isset(VtigerCRMActorMeta::$fieldTypeMapping[$tableName][$dbField->name])){
|
||||
$this->getFieldType($dbField, $tableName);
|
||||
}
|
||||
$fieldTypeData = VtigerCRMActorMeta::$fieldTypeMapping[$tableName][$dbField->name];
|
||||
$referenceTypes = array();
|
||||
$sql = "select * from vtiger_ws_entity_referencetype where fieldtypeid=?";
|
||||
$result = $this->pearDB->pquery($sql,array($fieldTypeData['fieldtypeid']));
|
||||
$numRows = $this->pearDB->num_rows($result);
|
||||
for($i=0;$i<$numRows;++$i){
|
||||
array_push($referenceTypes,$this->pearDB->query_result($result,$i,"type"));
|
||||
}
|
||||
$referenceList[$dbField->name] = $referenceTypes;
|
||||
return $referenceTypes;
|
||||
}
|
||||
|
||||
protected function getFieldType($dbField,$tableName){
|
||||
|
||||
if(isset(VtigerCRMActorMeta::$fieldTypeMapping[$tableName][$dbField->name])){
|
||||
if(VtigerCRMActorMeta::$fieldTypeMapping[$tableName][$dbField->name] === 'null'){
|
||||
return null;
|
||||
}
|
||||
$row = VtigerCRMActorMeta::$fieldTypeMapping[$tableName][$dbField->name];
|
||||
return $row['fieldtype'];
|
||||
}
|
||||
$sql = "select * from vtiger_ws_entity_fieldtype where table_name=? and field_name=?;";
|
||||
$result = $this->pearDB->pquery($sql,array($tableName,$dbField->name));
|
||||
$rowCount = $this->pearDB->num_rows($result);
|
||||
if($rowCount > 0){
|
||||
$row = $this->pearDB->query_result_rowdata($result,0);
|
||||
VtigerCRMActorMeta::$fieldTypeMapping[$tableName][$dbField->name] = $row;
|
||||
return $row['fieldtype'];
|
||||
}else{
|
||||
VtigerCRMActorMeta::$fieldTypeMapping[$tableName][$dbField->name] = 'null';
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getTypeOfDataForType($type){
|
||||
switch($type){
|
||||
case 'email': return 'E';
|
||||
case 'password': return 'P';
|
||||
case 'date': return 'D';
|
||||
case 'datetime': return 'DT';
|
||||
case 'timestamp': return 'T';
|
||||
case 'int':
|
||||
case 'integer': return 'I';
|
||||
case 'decimal':
|
||||
case 'numeric': return 'N';
|
||||
case 'varchar':
|
||||
case 'text':
|
||||
default: return 'V';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFieldDataTypeFromDBType($type){
|
||||
switch($type){
|
||||
case 'date': return 'date';
|
||||
case 'datetime': return 'datetime';
|
||||
case 'timestamp': return 'time';
|
||||
case 'int':
|
||||
case 'integer': return 'integer';
|
||||
case 'real':
|
||||
case 'decimal':
|
||||
case 'numeric': return 'double';
|
||||
case 'text': return 'text';
|
||||
case 'varchar': return 'string';
|
||||
default: return $type;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasPermission($operation,$webserviceId){
|
||||
if(is_admin($this->user)){
|
||||
return true;
|
||||
}else{
|
||||
if(strcmp($operation,EntityMeta::$RETRIEVE)===0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAssignPrivilege($ownerWebserviceId){
|
||||
if(is_admin($this->user)){
|
||||
return true;
|
||||
}else{
|
||||
$idComponents = vtws_getIdComponents($webserviceId);
|
||||
$userId=$idComponents[1];
|
||||
if($this->user->id === $userId){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasDeleteAccess(){
|
||||
if(is_admin($this->user)){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAccess(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasReadAccess(){
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasWriteAccess(){
|
||||
if(is_admin($this->user)){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getEntityName(){
|
||||
return $this->webserviceObject->getEntityName();
|
||||
}
|
||||
public function getEntityId(){
|
||||
return $this->webserviceObject->getEntityId();
|
||||
}
|
||||
|
||||
function getObjectEntityName($webserviceId){
|
||||
|
||||
$idComponents = vtws_getIdComponents($webserviceId);
|
||||
$id=$idComponents[1];
|
||||
|
||||
if($this->exists($id)){
|
||||
return $this->webserviceObject->getEntityName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function exists($recordId){
|
||||
$exists = false;
|
||||
$sql = 'select * from '.$this->baseTable.' where '.$this->getObectIndexColumn().'=?';
|
||||
$result = $this->pearDB->pquery($sql , array($recordId));
|
||||
if($result != null && isset($result)){
|
||||
if($this->pearDB->num_rows($result)>0){
|
||||
$exists = true;
|
||||
}
|
||||
}
|
||||
return $exists;
|
||||
}
|
||||
|
||||
public function getNameFields(){
|
||||
$query = "select name_fields from vtiger_ws_entity_name where entity_id = ?";
|
||||
$result = $this->pearDB->pquery($query, array($this->objectId));
|
||||
$fieldNames = '';
|
||||
if($result){
|
||||
$rowCount = $this->pearDB->num_rows($result);
|
||||
if($rowCount > 0){
|
||||
$fieldNames = $this->pearDB->query_result($result,0,'name_fields');
|
||||
}
|
||||
}
|
||||
return $fieldNames;
|
||||
}
|
||||
|
||||
public function getName($webserviceId){
|
||||
|
||||
$idComponents = vtws_getIdComponents($webserviceId);
|
||||
$entityId = $idComponents[0];
|
||||
$id=$idComponents[1];
|
||||
|
||||
$nameList = vtws_getActorEntityNameById($entityId, array($id));
|
||||
return $nameList[$id];
|
||||
}
|
||||
|
||||
public function getEntityAccessControlQuery() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getEntityDeletedQuery() {
|
||||
if($this->getEntityName() == 'Currency'){
|
||||
return 'vtiger_currency_info.deleted=0';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function isModuleEntity() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,215 @@
|
|||
<?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 VtigerCRMObject{
|
||||
|
||||
private $moduleName ;
|
||||
private $moduleId ;
|
||||
private $instance ;
|
||||
|
||||
function VtigerCRMObject($moduleCredential, $isId=false){
|
||||
|
||||
if($isId){
|
||||
$this->moduleId = $moduleCredential;
|
||||
$this->moduleName = $this->getObjectTypeName($this->moduleId);
|
||||
}else{
|
||||
$this->moduleName = $moduleCredential;
|
||||
$this->moduleId = $this->getObjectTypeId($this->moduleName);
|
||||
}
|
||||
$this->instance = null;
|
||||
$this->getInstance();
|
||||
}
|
||||
|
||||
public function getModuleName(){
|
||||
return $this->moduleName;
|
||||
}
|
||||
|
||||
public function getModuleId(){
|
||||
return $this->moduleId;
|
||||
}
|
||||
|
||||
public function getInstance(){
|
||||
if($this->instance == null){
|
||||
$this->instance = $this->getModuleClassInstance($this->moduleName);
|
||||
}
|
||||
return $this->instance;
|
||||
}
|
||||
|
||||
public function getObjectId(){
|
||||
if($this->instance==null){
|
||||
$this->getInstance();
|
||||
}
|
||||
return $this->instance->id;
|
||||
}
|
||||
|
||||
public function setObjectId($id){
|
||||
if($this->instance==null){
|
||||
$this->getInstance();
|
||||
}
|
||||
$this->instance->id = $id;
|
||||
}
|
||||
|
||||
private function titleCase($str){
|
||||
$first = substr($str, 0, 1);
|
||||
return strtoupper($first).substr($str,1);
|
||||
}
|
||||
|
||||
private function getObjectTypeId($objectName){
|
||||
|
||||
// Use getTabid API
|
||||
$tid = getTabid($objectName);
|
||||
|
||||
if($tid === false) {
|
||||
global $adb;
|
||||
|
||||
$sql = "select * from vtiger_tab where name=?;";
|
||||
$params = array($objectName);
|
||||
$result = $adb->pquery($sql, $params);
|
||||
$data1 = $adb->fetchByAssoc($result,1,false);
|
||||
|
||||
$tid = $data1["tabid"];
|
||||
}
|
||||
// END
|
||||
|
||||
return $tid;
|
||||
|
||||
}
|
||||
|
||||
private function getModuleClassInstance($moduleName){
|
||||
return CRMEntity::getInstance($moduleName);
|
||||
}
|
||||
|
||||
private function getObjectTypeName($moduleId){
|
||||
|
||||
return getTabModuleName($moduleId);
|
||||
|
||||
}
|
||||
|
||||
private function getTabName(){
|
||||
if($this->moduleName == 'Events'){
|
||||
return 'Calendar';
|
||||
}
|
||||
return $this->moduleName;
|
||||
}
|
||||
|
||||
public function read($id){
|
||||
global $adb;
|
||||
|
||||
$error = false;
|
||||
$adb->startTransaction();
|
||||
$this->instance->retrieve_entity_info($id,$this->getTabName());
|
||||
$error = $adb->hasFailedTransaction();
|
||||
$adb->completeTransaction();
|
||||
return !$error;
|
||||
}
|
||||
|
||||
public function create($element){
|
||||
global $adb;
|
||||
|
||||
$error = false;
|
||||
foreach($element as $k=>$v){
|
||||
$this->instance->column_fields[$k] = $v;
|
||||
}
|
||||
|
||||
$adb->startTransaction();
|
||||
$this->instance->Save($this->getTabName());
|
||||
$error = $adb->hasFailedTransaction();
|
||||
$adb->completeTransaction();
|
||||
return !$error;
|
||||
}
|
||||
|
||||
public function update($element){
|
||||
|
||||
global $adb;
|
||||
$error = false;
|
||||
|
||||
foreach($element as $k=>$v){
|
||||
$this->instance->column_fields[$k] = $v;
|
||||
}
|
||||
|
||||
$adb->startTransaction();
|
||||
$this->instance->mode = "edit";
|
||||
$this->instance->Save($this->getTabName());
|
||||
$error = $adb->hasFailedTransaction();
|
||||
$adb->completeTransaction();
|
||||
return !$error;
|
||||
}
|
||||
|
||||
public function revise($element){
|
||||
global $adb;
|
||||
$error = false;
|
||||
|
||||
$error = $this->read($this->getObjectId());
|
||||
if($error == false){
|
||||
return $error;
|
||||
}
|
||||
|
||||
foreach($element as $k=>$v){
|
||||
$this->instance->column_fields[$k] = $v;
|
||||
}
|
||||
|
||||
//added to fix the issue of utf8 characters
|
||||
foreach($this->instance->column_fields as $key=>$value){
|
||||
$this->instance->column_fields[$key] = decode_html($value);
|
||||
}
|
||||
|
||||
$adb->startTransaction();
|
||||
$this->instance->mode = "edit";
|
||||
$this->instance->Save($this->getTabName());
|
||||
$error = $adb->hasFailedTransaction();
|
||||
$adb->completeTransaction();
|
||||
return !$error;
|
||||
}
|
||||
|
||||
public function delete($id){
|
||||
global $adb;
|
||||
$error = false;
|
||||
$adb->startTransaction();
|
||||
DeleteEntity($this->getTabName(), $this->getTabName(), $this->instance, $id,$returnid);
|
||||
$error = $adb->hasFailedTransaction();
|
||||
$adb->completeTransaction();
|
||||
return !$error;
|
||||
}
|
||||
|
||||
public function getFields(){
|
||||
return $this->instance->column_fields;
|
||||
}
|
||||
|
||||
function exists($id){
|
||||
global $adb;
|
||||
|
||||
$exists = false;
|
||||
$sql = "select * from vtiger_crmentity where crmid=? and deleted=0";
|
||||
$result = $adb->pquery($sql , array($id));
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
$exists = true;
|
||||
}
|
||||
}
|
||||
return $exists;
|
||||
}
|
||||
|
||||
function getSEType($id){
|
||||
global $adb;
|
||||
|
||||
$seType = null;
|
||||
$sql = "select * from vtiger_crmentity where crmid=? and deleted=0";
|
||||
$result = $adb->pquery($sql , array($id));
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
$seType = $adb->query_result($result,0,"setype");
|
||||
}
|
||||
}
|
||||
return $seType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,521 @@
|
|||
<?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 VtigerCRMObjectMeta extends EntityMeta {
|
||||
|
||||
private $tabId;
|
||||
|
||||
private $meta;
|
||||
private $assign;
|
||||
private $hasAccess;
|
||||
private $hasReadAccess;
|
||||
private $hasWriteAccess;
|
||||
private $hasDeleteAccess;
|
||||
private $assignUsers;
|
||||
|
||||
function VtigerCRMObjectMeta($webserviceObject,$user){
|
||||
|
||||
parent::__construct($webserviceObject,$user);
|
||||
|
||||
$this->columnTableMapping = null;
|
||||
$this->fieldColumnMapping = null;
|
||||
$this->userAccessibleColumns = null;
|
||||
$this->mandatoryFields = null;
|
||||
$this->emailFields = null;
|
||||
$this->referenceFieldDetails = null;
|
||||
$this->ownerFields = null;
|
||||
$this->moduleFields = array();
|
||||
$this->hasAccess = false;
|
||||
$this->hasReadAccess = false;
|
||||
$this->hasWriteAccess = false;
|
||||
$this->hasDeleteAccess = false;
|
||||
$instance = vtws_getModuleInstance($this->webserviceObject);
|
||||
$this->idColumn = $instance->tab_name_index[$instance->table_name];
|
||||
$this->baseTable = $instance->table_name;
|
||||
$this->tableList = $instance->tab_name;
|
||||
$this->tableIndexList = $instance->tab_name_index;
|
||||
if(in_array('vtiger_crmentity',$instance->tab_name)){
|
||||
$this->defaultTableList = array('vtiger_crmentity');
|
||||
}else{
|
||||
$this->defaultTableList = array();
|
||||
}
|
||||
$this->tabId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns tabid of the current object.
|
||||
* @return Integer
|
||||
*/
|
||||
public function getTabId(){
|
||||
if($this->tabId == null){
|
||||
$this->tabId = getTabid($this->objectName);
|
||||
}
|
||||
return $this->tabId;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns tabid that can be consumed for database lookup purpose generally, events and
|
||||
* calendar are treated as the same module
|
||||
* @return Integer
|
||||
*/
|
||||
public function getEffectiveTabId() {
|
||||
return getTabid($this->getTabName());
|
||||
}
|
||||
|
||||
public function getTabName(){
|
||||
if($this->objectName == 'Events'){
|
||||
return 'Calendar';
|
||||
}
|
||||
return $this->objectName;
|
||||
}
|
||||
|
||||
private function computeAccess(){
|
||||
|
||||
global $adb;
|
||||
|
||||
$active = vtlib_isModuleActive($this->getTabName());
|
||||
if($active == false){
|
||||
$this->hasAccess = false;
|
||||
$this->hasReadAccess = false;
|
||||
$this->hasWriteAccess = false;
|
||||
$this->hasDeleteAccess = false;
|
||||
return;
|
||||
}
|
||||
|
||||
require('user_privileges/user_privileges_'.$this->user->id.'.php');
|
||||
if($is_admin == true || $profileGlobalPermission[1] == 0 || $profileGlobalPermission[2] == 0){
|
||||
$this->hasAccess = true;
|
||||
$this->hasReadAccess = true;
|
||||
$this->hasWriteAccess = true;
|
||||
$this->hasDeleteAccess = true;
|
||||
}else{
|
||||
|
||||
//TODO get oer sort out the preference among profile2tab and profile2globalpermissions.
|
||||
//TODO check whether create/edit seperate controls required for web sevices?
|
||||
$profileList = getCurrentUserProfileList();
|
||||
|
||||
$sql = "select * from vtiger_profile2globalpermissions where profileid in (".generateQuestionMarks($profileList).");";
|
||||
$result = $adb->pquery($sql,array($profileList));
|
||||
|
||||
$noofrows = $adb->num_rows($result);
|
||||
//globalactionid=1 is view all action.
|
||||
//globalactionid=2 is edit all action.
|
||||
for($i=0; $i<$noofrows; $i++){
|
||||
$permission = $adb->query_result($result,$i,"globalactionpermission");
|
||||
$globalactionid = $adb->query_result($result,$i,"globalactionid");
|
||||
if($permission != 1 || $permission != "1"){
|
||||
$this->hasAccess = true;
|
||||
if($globalactionid == 2 || $globalactionid == "2"){
|
||||
$this->hasWriteAccess = true;
|
||||
$this->hasDeleteAccess = true;
|
||||
}else{
|
||||
$this->hasReadAccess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sql = 'select * from vtiger_profile2tab where profileid in ('.generateQuestionMarks($profileList).') and tabid = ?;';
|
||||
$result = $adb->pquery($sql,array($profileList,$this->getTabId()));
|
||||
$standardDefined = false;
|
||||
$permission = $adb->query_result($result,1,"permissions");
|
||||
if($permission == 1 || $permission == "1"){
|
||||
$this->hasAccess = false;
|
||||
return;
|
||||
}else{
|
||||
$this->hasAccess = true;
|
||||
}
|
||||
|
||||
//operation=2 is delete operation.
|
||||
//operation=0 or 1 is create/edit operation. precise 0 create and 1 edit.
|
||||
//operation=3 index or popup. //ignored for websevices.
|
||||
//operation=4 is view operation.
|
||||
$sql = "select * from vtiger_profile2standardpermissions where profileid in (".generateQuestionMarks($profileList).") and tabid=?";
|
||||
$result = $adb->pquery($sql,array($profileList,$this->getTabId()));
|
||||
|
||||
$noofrows = $adb->num_rows($result);
|
||||
for($i=0; $i<$noofrows; $i++){
|
||||
$standardDefined = true;
|
||||
$permission = $adb->query_result($result,$i,"permissions");
|
||||
$operation = $adb->query_result($result,$i,"Operation");
|
||||
if(!$operation){
|
||||
$operation = $adb->query_result($result,$i,"operation");
|
||||
}
|
||||
|
||||
if($permission != 1 || $permission != "1"){
|
||||
$this->hasAccess = true;
|
||||
if($operation == 0 || $operation == "0"){
|
||||
$this->hasWriteAccess = true;
|
||||
}else if($operation == 1 || $operation == "1"){
|
||||
$this->hasWriteAccess = true;
|
||||
}else if($operation == 2 || $operation == "2"){
|
||||
$this->hasDeleteAccess = true;
|
||||
}else if($operation == 4 || $operation == "4"){
|
||||
$this->hasReadAccess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!$standardDefined){
|
||||
$this->hasReadAccess = true;
|
||||
$this->hasWriteAccess = true;
|
||||
$this->hasDeleteAccess = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function hasAccess(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return $this->hasAccess;
|
||||
}
|
||||
|
||||
function hasWriteAccess(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return $this->hasWriteAccess;
|
||||
}
|
||||
|
||||
function hasReadAccess(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return $this->hasReadAccess;
|
||||
}
|
||||
|
||||
function hasDeleteAccess(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return $this->hasDeleteAccess;
|
||||
}
|
||||
|
||||
function hasPermission($operation,$webserviceId){
|
||||
|
||||
$idComponents = vtws_getIdComponents($webserviceId);
|
||||
$id=$idComponents[1];
|
||||
|
||||
$permitted = isPermitted($this->getTabName(),$operation,$id);
|
||||
if(strcmp($permitted,"yes")===0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasAssignPrivilege($webserviceId){
|
||||
global $adb;
|
||||
|
||||
// administrator's have assign privilege
|
||||
if(is_admin($this->user)) return true;
|
||||
|
||||
$idComponents = vtws_getIdComponents($webserviceId);
|
||||
$userId=$idComponents[1];
|
||||
$ownerTypeId = $idComponents[0];
|
||||
|
||||
if($userId == null || $userId =='' || $ownerTypeId == null || $ownerTypeId ==''){
|
||||
return false;
|
||||
}
|
||||
$webserviceObject = VtigerWebserviceObject::fromId($adb,$ownerTypeId);
|
||||
if(strcasecmp($webserviceObject->getEntityName(),"Users")===0){
|
||||
if($userId == $this->user->id){
|
||||
return true;
|
||||
}
|
||||
if(!$this->assign){
|
||||
$this->retrieveUserHierarchy();
|
||||
}
|
||||
if(in_array($userId,array_keys($this->assignUsers))){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}elseif(strcasecmp($webserviceObject->getEntityName(),"Groups") === 0){
|
||||
$tabId = $this->getTabId();
|
||||
$groups = vtws_getUserAccessibleGroups($tabId, $this->user);
|
||||
foreach ($groups as $group) {
|
||||
if($group['id'] == $userId){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getUserAccessibleColumns(){
|
||||
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return parent::getUserAccessibleColumns();
|
||||
}
|
||||
|
||||
public function getModuleFields() {
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return parent::getModuleFields();
|
||||
}
|
||||
|
||||
function getColumnTableMapping(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return parent::getColumnTableMapping();
|
||||
}
|
||||
|
||||
function getFieldColumnMapping(){
|
||||
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
if($this->fieldColumnMapping === null){
|
||||
$this->fieldColumnMapping = array();
|
||||
foreach ($this->moduleFields as $fieldName=>$webserviceField) {
|
||||
if(strcasecmp($webserviceField->getFieldDataType(),'file') !== 0){
|
||||
$this->fieldColumnMapping[$fieldName] = $webserviceField->getColumnName();
|
||||
}
|
||||
}
|
||||
$this->fieldColumnMapping['id'] = $this->idColumn;
|
||||
}
|
||||
return $this->fieldColumnMapping;
|
||||
}
|
||||
|
||||
function getMandatoryFields(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return parent::getMandatoryFields();
|
||||
}
|
||||
|
||||
function getReferenceFieldDetails(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return parent::getReferenceFieldDetails();
|
||||
}
|
||||
|
||||
function getOwnerFields(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return parent::getOwnerFields();
|
||||
}
|
||||
|
||||
function getEntityName(){
|
||||
return $this->objectName;
|
||||
}
|
||||
|
||||
function getEntityId(){
|
||||
return $this->objectId;
|
||||
}
|
||||
|
||||
function getEmailFields(){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
return parent::getEmailFields();
|
||||
}
|
||||
|
||||
function getFieldIdFromFieldName($fieldName){
|
||||
if(!$this->meta){
|
||||
$this->retrieveMeta();
|
||||
}
|
||||
|
||||
if(isset($this->moduleFields[$fieldName])){
|
||||
$webserviceField = $this->moduleFields[$fieldName];
|
||||
return $webserviceField->getFieldId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function retrieveMeta(){
|
||||
|
||||
require_once('modules/CustomView/CustomView.php');
|
||||
$current_user = vtws_preserveGlobal('current_user',$this->user);
|
||||
$theme = vtws_preserveGlobal('theme',$this->user->theme);
|
||||
$default_language = VTWS_PreserveGlobal::getGlobal('default_language');
|
||||
$current_language = vtws_preserveGlobal('current_language',$default_language);
|
||||
|
||||
$this->computeAccess();
|
||||
|
||||
$cv = new CustomView();
|
||||
$module_info = $cv->getCustomViewModuleInfo($this->getTabName());
|
||||
$blockArray = array();
|
||||
foreach($cv->module_list[$this->getTabName()] as $label=>$blockList){
|
||||
$blockArray = array_merge($blockArray,explode(',',$blockList));
|
||||
}
|
||||
$this->retrieveMetaForBlock($blockArray);
|
||||
|
||||
$this->meta = true;
|
||||
VTWS_PreserveGlobal::flush();
|
||||
}
|
||||
|
||||
private function retrieveUserHierarchy(){
|
||||
|
||||
$heirarchyUsers = get_user_array(false,"ACTIVE",$this->user->id);
|
||||
$groupUsers = vtws_getUsersInTheSameGroup($this->user->id);
|
||||
$this->assignUsers = $heirarchyUsers+$groupUsers;
|
||||
$this->assign = true;
|
||||
}
|
||||
|
||||
private function retrieveMetaForBlock($block){
|
||||
|
||||
global $adb;
|
||||
|
||||
$tabid = $this->getTabId();
|
||||
require('user_privileges/user_privileges_'.$this->user->id.'.php');
|
||||
if($is_admin == true || $profileGlobalPermission[1] == 0 || $profileGlobalPermission[2] ==0){
|
||||
$sql = "select *, '0' as readonly from vtiger_field where tabid =? and block in (".generateQuestionMarks($block).") and displaytype in (1,2,3,4)";
|
||||
$params = array($tabid, $block);
|
||||
}else{
|
||||
$profileList = getCurrentUserProfileList();
|
||||
|
||||
if (count($profileList) > 0) {
|
||||
$sql = "SELECT vtiger_field.*, vtiger_profile2field.readonly
|
||||
FROM vtiger_field
|
||||
INNER JOIN vtiger_profile2field
|
||||
ON vtiger_profile2field.fieldid = vtiger_field.fieldid
|
||||
INNER JOIN vtiger_def_org_field
|
||||
ON vtiger_def_org_field.fieldid = vtiger_field.fieldid
|
||||
WHERE vtiger_field.tabid =? AND vtiger_profile2field.visible = 0
|
||||
AND vtiger_profile2field.profileid IN (". generateQuestionMarks($profileList) .")
|
||||
AND vtiger_def_org_field.visible = 0 and vtiger_field.block in (".generateQuestionMarks($block).") and vtiger_field.displaytype in (1,2,3,4) and vtiger_field.presence in (0,2) group by columnname";
|
||||
$params = array($tabid, $profileList, $block);
|
||||
} else {
|
||||
$sql = "SELECT vtiger_field.*, vtiger_profile2field.readonly
|
||||
FROM vtiger_field
|
||||
INNER JOIN vtiger_profile2field
|
||||
ON vtiger_profile2field.fieldid = vtiger_field.fieldid
|
||||
INNER JOIN vtiger_def_org_field
|
||||
ON vtiger_def_org_field.fieldid = vtiger_field.fieldid
|
||||
WHERE vtiger_field.tabid=?
|
||||
AND vtiger_profile2field.visible = 0
|
||||
AND vtiger_def_org_field.visible = 0 and vtiger_field.block in (".generateQuestionMarks($block).") and vtiger_field.displaytype in (1,2,3,4) and vtiger_field.presence in (0,2) group by columnname";
|
||||
$params = array($tabid, $block);
|
||||
}
|
||||
}
|
||||
|
||||
// Bulk Save Mode: Group by is not required!?
|
||||
if(CRMEntity::isBulkSaveMode()) {
|
||||
$sql = preg_replace("/group by [^ ]*/", " ", $sql);
|
||||
}
|
||||
// END
|
||||
|
||||
$result = $adb->pquery($sql,$params);
|
||||
|
||||
$noofrows = $adb->num_rows($result);
|
||||
$referenceArray = array();
|
||||
$knownFieldArray = array();
|
||||
for($i=0; $i<$noofrows; $i++){
|
||||
$fieldname = $adb->query_result($result,$i,"fieldname");
|
||||
if(strcasecmp($fieldname,'imagename')===0){
|
||||
continue;
|
||||
}
|
||||
$webserviceField = WebserviceField::fromQueryResult($adb,$result,$i);
|
||||
$this->moduleFields[$webserviceField->getFieldName()] = $webserviceField;
|
||||
}
|
||||
}
|
||||
|
||||
function getObjectEntityName($webserviceId){
|
||||
global $adb;
|
||||
|
||||
$idComponents = vtws_getIdComponents($webserviceId);
|
||||
$id=$idComponents[1];
|
||||
|
||||
$seType = null;
|
||||
if($this->objectName == 'Users'){
|
||||
$sql = "select user_name from vtiger_users where id=? and deleted=0";
|
||||
$result = $adb->pquery($sql , array($id));
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
$seType = 'Users';
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$sql = "select * from vtiger_crmentity where crmid=? and deleted=0";
|
||||
$result = $adb->pquery($sql , array($id));
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
$seType = $adb->query_result($result,0,"setype");
|
||||
if($seType == "Calendar"){
|
||||
$seType = vtws_getCalendarEntityType($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $seType;
|
||||
}
|
||||
|
||||
function exists($recordId){
|
||||
global $adb;
|
||||
|
||||
$exists = false;
|
||||
$sql = '';
|
||||
if($this->objectName == 'Users'){
|
||||
$sql = "select * from vtiger_users where id=? and deleted=0 and status='Active'";
|
||||
}else{
|
||||
$sql = "select * from vtiger_crmentity where crmid=? and deleted=0 and setype='".
|
||||
$this->getTabName()."'";
|
||||
}
|
||||
$result = $adb->pquery($sql , array($recordId));
|
||||
if($result != null && isset($result)){
|
||||
if($adb->num_rows($result)>0){
|
||||
$exists = true;
|
||||
}
|
||||
}
|
||||
return $exists;
|
||||
}
|
||||
|
||||
public function getNameFields(){
|
||||
global $adb;
|
||||
|
||||
$query = "select fieldname,tablename,entityidfield from vtiger_entityname where tabid = ?";
|
||||
$result = $adb->pquery($query, array($this->getEffectiveTabId()));
|
||||
$fieldNames = '';
|
||||
if($result){
|
||||
$rowCount = $adb->num_rows($result);
|
||||
if($rowCount > 0){
|
||||
$fieldNames = $adb->query_result($result,0,'fieldname');
|
||||
}
|
||||
}
|
||||
return $fieldNames;
|
||||
}
|
||||
|
||||
public function getName($webserviceId){
|
||||
|
||||
$idComponents = vtws_getIdComponents($webserviceId);
|
||||
$id=$idComponents[1];
|
||||
|
||||
$nameList = getEntityName($this->getTabName(),array($id));
|
||||
return $nameList[$id];
|
||||
}
|
||||
|
||||
public function getEntityAccessControlQuery(){
|
||||
$accessControlQuery = '';
|
||||
$instance = vtws_getModuleInstance($this->webserviceObject);
|
||||
if($this->getTabName() != 'Users') {
|
||||
$accessControlQuery = $instance->getNonAdminAccessControlQuery($this->getTabName(),
|
||||
$this->user);
|
||||
}
|
||||
return $accessControlQuery;
|
||||
}
|
||||
|
||||
public function getJoinClause($tableName) {
|
||||
$instance = vtws_getModuleInstance($this->webserviceObject);
|
||||
return $instance->getJoinClause($tableName);
|
||||
}
|
||||
|
||||
public function isModuleEntity() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,51 @@
|
|||
<?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/Webservices/VtigerActorOperation.php';
|
||||
/**
|
||||
* Description of VtigerCompanyDetails
|
||||
*
|
||||
* @author MAK
|
||||
*/
|
||||
class VtigerCompanyDetails extends VtigerActorOperation {
|
||||
public function create($elementType, $element) {
|
||||
$db = PearDatabase::getInstance();
|
||||
$sql = 'select * from vtiger_organizationdetails';
|
||||
$result = $db->pquery($sql,$params);
|
||||
$rowCount = $db->num_rows($result);
|
||||
if($rowCount > 0) {
|
||||
$id = $db->query_result($result,0,'organization_id');
|
||||
$meta = $this->getMeta();
|
||||
$element['id'] = vtws_getId($meta->getEntityId(), $id);
|
||||
return $this->update($element);
|
||||
}else{
|
||||
$element = $this->handleFileUpload($element);
|
||||
return parent::create($elementType, $element);
|
||||
}
|
||||
}
|
||||
|
||||
function handleFileUpload($element) {
|
||||
$fileFieldList = $this->meta->getFieldListByType('file');
|
||||
foreach ($fileFieldList as $field) {
|
||||
$fieldname = $field->getFieldName();
|
||||
if(is_array($_FILES[$fieldname])) {
|
||||
$element[$fieldname] = vtws_CreateCompanyLogoFile($fieldname);
|
||||
}
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
public function update($element) {
|
||||
$element = $this->handleFileUpload($element);
|
||||
return parent::update($element);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,237 @@
|
|||
<?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 VtigerModuleOperation extends WebserviceEntityOperation {
|
||||
protected $tabId;
|
||||
protected $isEntity = true;
|
||||
|
||||
public function VtigerModuleOperation($webserviceObject,$user,$adb,$log){
|
||||
parent::__construct($webserviceObject,$user,$adb,$log);
|
||||
$this->meta = $this->getMetaInstance();
|
||||
$this->tabId = $this->meta->getTabId();
|
||||
}
|
||||
|
||||
protected function getMetaInstance(){
|
||||
if(empty(WebserviceEntityOperation::$metaCache[$this->webserviceObject->getEntityName()][$this->user->id])){
|
||||
WebserviceEntityOperation::$metaCache[$this->webserviceObject->getEntityName()][$this->user->id] = new VtigerCRMObjectMeta($this->webserviceObject,$this->user);
|
||||
}
|
||||
return WebserviceEntityOperation::$metaCache[$this->webserviceObject->getEntityName()][$this->user->id];
|
||||
}
|
||||
|
||||
public function create($elementType,$element){
|
||||
$crmObject = new VtigerCRMObject($elementType, false);
|
||||
|
||||
$element = DataTransform::sanitizeForInsert($element,$this->meta);
|
||||
|
||||
$error = $crmObject->create($element);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
$id = $crmObject->getObjectId();
|
||||
|
||||
// Bulk Save Mode
|
||||
if(CRMEntity::isBulkSaveMode()) {
|
||||
// Avoiding complete read, as during bulk save mode, $result['id'] is enough
|
||||
return array('id' => vtws_getId($this->meta->getEntityId(), $id) );
|
||||
}
|
||||
|
||||
$error = $crmObject->read($id);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
return DataTransform::filterAndSanitize($crmObject->getFields(),$this->meta);
|
||||
}
|
||||
|
||||
public function retrieve($id){
|
||||
|
||||
$ids = vtws_getIdComponents($id);
|
||||
$elemid = $ids[1];
|
||||
|
||||
$crmObject = new VtigerCRMObject($this->tabId, true);
|
||||
$error = $crmObject->read($elemid);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
return DataTransform::filterAndSanitize($crmObject->getFields(),$this->meta);
|
||||
}
|
||||
|
||||
public function update($element){
|
||||
$ids = vtws_getIdComponents($element["id"]);
|
||||
$element = DataTransform::sanitizeForInsert($element,$this->meta);
|
||||
|
||||
$crmObject = new VtigerCRMObject($this->tabId, true);
|
||||
$crmObject->setObjectId($ids[1]);
|
||||
$error = $crmObject->update($element);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
$id = $crmObject->getObjectId();
|
||||
|
||||
$error = $crmObject->read($id);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
return DataTransform::filterAndSanitize($crmObject->getFields(),$this->meta);
|
||||
}
|
||||
|
||||
public function revise($element){
|
||||
$ids = vtws_getIdComponents($element["id"]);
|
||||
$element = DataTransform::sanitizeForInsert($element,$this->meta);
|
||||
|
||||
$crmObject = new VtigerCRMObject($this->tabId, true);
|
||||
$crmObject->setObjectId($ids[1]);
|
||||
$error = $crmObject->revise($element);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
$id = $crmObject->getObjectId();
|
||||
|
||||
$error = $crmObject->read($id);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
return DataTransform::filterAndSanitize($crmObject->getFields(),$this->meta);
|
||||
}
|
||||
|
||||
public function delete($id){
|
||||
$ids = vtws_getIdComponents($id);
|
||||
$elemid = $ids[1];
|
||||
|
||||
$crmObject = new VtigerCRMObject($this->tabId, true);
|
||||
|
||||
$error = $crmObject->delete($elemid);
|
||||
if(!$error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
return array("status"=>"successful");
|
||||
}
|
||||
|
||||
public function query($q){
|
||||
|
||||
$parser = new Parser($this->user, $q);
|
||||
$error = $parser->parse();
|
||||
|
||||
if($error){
|
||||
return $parser->getError();
|
||||
}
|
||||
|
||||
$mysql_query = $parser->getSql();
|
||||
$meta = $parser->getObjectMetaData();
|
||||
$this->pearDB->startTransaction();
|
||||
$result = $this->pearDB->pquery($mysql_query, array());
|
||||
$error = $this->pearDB->hasFailedTransaction();
|
||||
$this->pearDB->completeTransaction();
|
||||
|
||||
if($error){
|
||||
throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR,
|
||||
vtws_getWebserviceTranslatedString('LBL_'.
|
||||
WebServiceErrorCode::$DATABASEQUERYERROR));
|
||||
}
|
||||
|
||||
$noofrows = $this->pearDB->num_rows($result);
|
||||
$output = array();
|
||||
for($i=0; $i<$noofrows; $i++){
|
||||
$row = $this->pearDB->fetchByAssoc($result,$i);
|
||||
if(!$meta->hasPermission(EntityMeta::$RETRIEVE,$row["crmid"])){
|
||||
continue;
|
||||
}
|
||||
$output[] = DataTransform::sanitizeDataWithColumn($row,$meta);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function describe($elementType){
|
||||
$app_strings = VTWS_PreserveGlobal::getGlobal('app_strings');
|
||||
$current_user = vtws_preserveGlobal('current_user',$this->user);;
|
||||
|
||||
$label = (isset($app_strings[$elementType]))? $app_strings[$elementType]:$elementType;
|
||||
$createable = (strcasecmp(isPermitted($elementType,EntityMeta::$CREATE),'yes')===0)? true:false;
|
||||
$updateable = (strcasecmp(isPermitted($elementType,EntityMeta::$UPDATE),'yes')===0)? true:false;
|
||||
$deleteable = $this->meta->hasDeleteAccess();
|
||||
$retrieveable = $this->meta->hasReadAccess();
|
||||
$fields = $this->getModuleFields();
|
||||
return array("label"=>$label,"name"=>$elementType,"createable"=>$createable,"updateable"=>$updateable,
|
||||
"deleteable"=>$deleteable,"retrieveable"=>$retrieveable,"fields"=>$fields,
|
||||
"idPrefix"=>$this->meta->getEntityId(),'isEntity'=>$this->isEntity,'labelFields'=>$this->meta->getNameFields());
|
||||
}
|
||||
|
||||
function getModuleFields(){
|
||||
|
||||
$fields = array();
|
||||
$moduleFields = $this->meta->getModuleFields();
|
||||
foreach ($moduleFields as $fieldName=>$webserviceField) {
|
||||
if(((int)$webserviceField->getPresence()) == 1) {
|
||||
continue;
|
||||
}
|
||||
array_push($fields,$this->getDescribeFieldArray($webserviceField));
|
||||
}
|
||||
array_push($fields,$this->getIdField($this->meta->getObectIndexColumn()));
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
function getDescribeFieldArray($webserviceField){
|
||||
$default_language = VTWS_PreserveGlobal::getGlobal('default_language');
|
||||
|
||||
require 'modules/'.$this->meta->getTabName()."/language/$default_language.lang.php";
|
||||
$fieldLabel = $webserviceField->getFieldLabelKey();
|
||||
if(isset($mod_strings[$fieldLabel])){
|
||||
$fieldLabel = $mod_strings[$fieldLabel];
|
||||
}
|
||||
$typeDetails = $this->getFieldTypeDetails($webserviceField);
|
||||
|
||||
//set type name, in the type details array.
|
||||
$typeDetails['name'] = $webserviceField->getFieldDataType();
|
||||
$editable = $this->isEditable($webserviceField);
|
||||
|
||||
$describeArray = array('name'=>$webserviceField->getFieldName(),'label'=>$fieldLabel,'mandatory'=>
|
||||
$webserviceField->isMandatory(),'type'=>$typeDetails,'nullable'=>$webserviceField->isNullable(),
|
||||
"editable"=>$editable);
|
||||
if($webserviceField->hasDefault()){
|
||||
$describeArray['default'] = $webserviceField->getDefault();
|
||||
}
|
||||
return $describeArray;
|
||||
}
|
||||
|
||||
function getMeta(){
|
||||
return $this->meta;
|
||||
}
|
||||
|
||||
function getField($fieldName){
|
||||
$moduleFields = $this->meta->getModuleFields();
|
||||
return $this->getDescribeFieldArray($moduleFields[$fieldName]);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -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.
|
||||
*************************************************************************************/
|
||||
|
||||
class VtigerWebserviceObject{
|
||||
|
||||
private $id;
|
||||
private $name;
|
||||
private $handlerPath;
|
||||
private $handlerClass;
|
||||
|
||||
private function VtigerWebserviceObject($entityId,$entityName,$handler_path,$handler_class){
|
||||
$this->id = $entityId;
|
||||
$this->name = $entityName;
|
||||
$this->handlerPath = $handler_path;
|
||||
$this->handlerClass = $handler_class;
|
||||
}
|
||||
|
||||
// Cache variables to enable result re-use
|
||||
private static $_fromNameCache = array();
|
||||
|
||||
static function fromName($adb,$entityName){
|
||||
|
||||
$rowData = false;
|
||||
|
||||
// If the information not available in cache?
|
||||
if(!isset(self::$_fromNameCache[$entityName])) {
|
||||
$result = $adb->pquery("select * from vtiger_ws_entity where name=?",array($entityName));
|
||||
if($result){
|
||||
$rowCount = $adb->num_rows($result);
|
||||
if($rowCount === 1){
|
||||
$rowData = $adb->query_result_rowdata($result,0);
|
||||
self::$_fromNameCache[$entityName] = $rowData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rowData = self::$_fromNameCache[$entityName];
|
||||
|
||||
if($rowData) {
|
||||
return new VtigerWebserviceObject($rowData['id'],$rowData['name'],
|
||||
$rowData['handler_path'],$rowData['handler_class']);
|
||||
}
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied for name");
|
||||
}
|
||||
|
||||
// Cache variables to enable result re-use
|
||||
private static $_fromIdCache = array();
|
||||
|
||||
static function fromId($adb,$entityId){
|
||||
$rowData = false;
|
||||
|
||||
// If the information not available in cache?
|
||||
if(!isset(self::$_fromIdCache[$entityId])) {
|
||||
$result = $adb->pquery("select * from vtiger_ws_entity where id=?",array($entityId));
|
||||
if($result){
|
||||
$rowCount = $adb->num_rows($result);
|
||||
if($rowCount === 1){
|
||||
$rowData = $adb->query_result_rowdata($result,0);
|
||||
self::$_fromIdCache[$entityId] = $rowData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rowData = self::$_fromIdCache[$entityId];
|
||||
|
||||
if($rowData) {
|
||||
return new VtigerWebserviceObject($rowData['id'],$rowData['name'],
|
||||
$rowData['handler_path'],$rowData['handler_class']);
|
||||
}
|
||||
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied for id");
|
||||
}
|
||||
|
||||
static function fromQuery($adb,$query){
|
||||
$moduleRegex = "/[fF][rR][Oo][Mm]\s+([^\s;]+)/";
|
||||
$matches = array();
|
||||
$found = preg_match($moduleRegex,$query,$matches);
|
||||
if($found === 1){
|
||||
return VtigerWebserviceObject::fromName($adb,trim($matches[1]));
|
||||
}
|
||||
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied for query");
|
||||
}
|
||||
|
||||
public function getEntityName(){
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getEntityId(){
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getHandlerPath(){
|
||||
return $this->handlerPath;
|
||||
}
|
||||
|
||||
public function getHandlerClass(){
|
||||
return $this->handlerClass;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
|
@ -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.
|
||||
*************************************************************************************/
|
||||
|
||||
require_once("include/Webservices/WebServiceErrorCode.php");
|
||||
class WebServiceException extends Exception {
|
||||
|
||||
public $code;
|
||||
public $message;
|
||||
|
||||
function WebServiceException($errCode,$msg){
|
||||
$this->code = $errCode;
|
||||
$this->message = $msg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -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.
|
||||
*************************************************************************************/
|
||||
|
||||
class WebServiceErrorCode {
|
||||
|
||||
public static $SESSLIFEOVER = "SESSION_EXPIRED";
|
||||
public static $REFERENCEINVALID = "REFERENCE_INVALID";
|
||||
public static $SESSIONIDLE = "SESSION_LEFT_IDLE";
|
||||
public static $SESSIONIDINVALID = "INVALID_SESSIONID";
|
||||
public static $INVALIDUSERPWD = "INVALID_USER_CREDENTIALS";
|
||||
public static $AUTHREQUIRED = "AUTHENTICATION_REQUIRED";
|
||||
public static $AUTHFAILURE = "AUTHENTICATION_FAILURE";
|
||||
public static $ACCESSDENIED = "ACCESS_DENIED";
|
||||
public static $DATABASEQUERYERROR = "DATABASE_QUERY_ERROR";
|
||||
public static $MANDFIELDSMISSING = "MANDATORY_FIELDS_MISSING";
|
||||
public static $INVALIDID = "INVALID_ID_ATTRIBUTE";
|
||||
public static $QUERYSYNTAX = "QUERY_SYNTAX_ERROR";
|
||||
public static $INVALIDTOKEN = "INVALID_AUTH_TOKEN";
|
||||
public static $ACCESSKEYUNDEFINED = "ACCESSKEY_UNDEFINED";
|
||||
public static $RECORDNOTFOUND = "RECORD_NOT_FOUND";
|
||||
public static $UNKNOWNOPERATION = "UNKNOWN_OPERATION";
|
||||
public static $INTERNALERROR = "INTERNAL_SERVER_ERROR";
|
||||
public static $OPERATIONNOTSUPPORTED = "OPERATION_NOT_SUPPORTED";
|
||||
public static $UNKOWNENTITY = "UNKOWN_ENTITY";
|
||||
public static $INVALID_POTENTIAL_FOR_CONVERT_LEAD = "INVALID_POTENTIAL_FOR_CONVERTLEAD";
|
||||
public static $LEAD_ALREADY_CONVERTED = "LEAD_ALREADY_CONVERTED";
|
||||
public static $LEAD_RELATED_UPDATE_FAILED = "LEAD_RELATEDLIST_UPDATE_FAILED";
|
||||
public static $FAILED_TO_CREATE_RELATION = "FAILED_TO_CREATE_RELATION";
|
||||
public static $FAILED_TO_MARK_CONVERTED = "FAILED_TO_MARK_LEAD_CONVERTED";
|
||||
public static $INVALIDOLDPASSWORD = "INVALID_OLD_PASSWORD";
|
||||
public static $NEWPASSWORDMISMATCH = "NEW_PASSWORD_MISMATCH";
|
||||
public static $CHANGEPASSWORDFAILURE = "CHANGE_PASSWORD_FAILURE";
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,122 @@
|
|||
<?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 WebserviceEntityOperation{
|
||||
protected $user;
|
||||
protected $log;
|
||||
protected $webserviceObject;
|
||||
protected $meta;
|
||||
/**
|
||||
*
|
||||
* @var PearDatabase
|
||||
*/
|
||||
protected $pearDB;
|
||||
|
||||
protected static $metaCache = array();
|
||||
|
||||
protected function WebserviceEntityOperation($webserviceObject,$user,$adb,$log){
|
||||
$this->user = $user;
|
||||
$this->log = $log;
|
||||
$this->webserviceObject = $webserviceObject;
|
||||
$this->pearDB = $adb;
|
||||
}
|
||||
|
||||
public function create($elementType,$element){
|
||||
throw new WebServiceException(WebServiceErrorCode::$OPERATIONNOTSUPPORTED,
|
||||
"Operation Create is not supported for this entity");
|
||||
}
|
||||
|
||||
public function retrieve($id){
|
||||
throw new WebServiceException(WebServiceErrorCode::$OPERATIONNOTSUPPORTED,
|
||||
"Operation Retrieve is not supported for this entity");
|
||||
}
|
||||
|
||||
public function update($element){
|
||||
throw new WebServiceException(WebServiceErrorCode::$OPERATIONNOTSUPPORTED,
|
||||
"Operation Update is not supported for this entity");
|
||||
}
|
||||
|
||||
public function revise($element){
|
||||
throw new WebServiceException(WebServiceErrorCode::$OPERATIONNOTSUPPORTED,
|
||||
"Operation Update is not supported for this entity");
|
||||
}
|
||||
|
||||
public function delete($id){
|
||||
throw new WebServiceException(WebServiceErrorCode::$OPERATIONNOTSUPPORTED,
|
||||
"Operation delete is not supported for this entity");
|
||||
}
|
||||
|
||||
public function query($q){
|
||||
throw new WebServiceException(WebServiceErrorCode::$OPERATIONNOTSUPPORTED,
|
||||
"Operation query is not supported for this entity");
|
||||
}
|
||||
|
||||
public function describe($elementType){
|
||||
throw new WebServiceException(WebServiceErrorCode::$OPERATIONNOTSUPPORTED,
|
||||
"Operation describe is not supported for this entity");
|
||||
}
|
||||
|
||||
function getFieldTypeDetails($webserviceField){
|
||||
global $upload_maxsize;
|
||||
$typeDetails = array();
|
||||
switch($webserviceField->getFieldDataType()){
|
||||
case 'reference': $typeDetails['refersTo'] = $webserviceField->getReferenceList();
|
||||
break;
|
||||
case 'multipicklist':
|
||||
case 'picklist': $typeDetails["picklistValues"] = $webserviceField->getPicklistDetails($webserviceField);
|
||||
$typeDetails['defaultValue'] = $typeDetails["picklistValues"][0]['value'];
|
||||
break;
|
||||
case 'file': $maxUploadSize = 0;
|
||||
$maxUploadSize = ini_get('upload_max_filesize');
|
||||
$maxUploadSize = strtolower($maxUploadSize);
|
||||
$maxUploadSize = explode('m',$maxUploadSize);
|
||||
$maxUploadSize = $maxUploadSize[0];
|
||||
if(!is_numeric($maxUploadSize)){
|
||||
$maxUploadSize = 0;
|
||||
}
|
||||
$maxUploadSize = $maxUploadSize * 1000000;
|
||||
if($upload_maxsize > $maxUploadSize){
|
||||
$maxUploadSize = $upload_maxsize;
|
||||
}
|
||||
$typeDetails['maxUploadFileSize'] = $maxUploadSize;
|
||||
break;
|
||||
case 'date': $typeDetails['format'] = $this->user->date_format;
|
||||
}
|
||||
return $typeDetails;
|
||||
}
|
||||
|
||||
function isEditable($webserviceField){
|
||||
if(((int)$webserviceField->getDisplayType()) === 2 || strcasecmp($webserviceField->getFieldDataType(),"autogenerated")
|
||||
===0 || strcasecmp($webserviceField->getFieldDataType(),"id")===0 || $webserviceField->isReadOnly() == true){
|
||||
return false;
|
||||
}
|
||||
//uitype 70 is vtiger generated fields, such as (of vtiger_crmentity table) createdtime
|
||||
//and modified time fields.
|
||||
if($webserviceField->getUIType() == 70 || $webserviceField->getUIType() == 4){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getIdField($label){
|
||||
return array('name'=>'id','label'=>$label,'mandatory'=>false,'type'=>'id','editable'=>false,'type'=>
|
||||
array('name'=>'autogenerated'),'nullable'=>false,'default'=>"");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Intance of EntityMeta class.
|
||||
*
|
||||
*/
|
||||
abstract public function getMeta();
|
||||
abstract protected function getMetaInstance();
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,397 @@
|
|||
<?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 WebserviceField{
|
||||
private $fieldId;
|
||||
private $uitype;
|
||||
private $blockId;
|
||||
private $blockName;
|
||||
private $nullable;
|
||||
private $default;
|
||||
private $tableName;
|
||||
private $columnName;
|
||||
private $fieldName;
|
||||
private $fieldLabel;
|
||||
private $editable;
|
||||
private $fieldType;
|
||||
private $displayType;
|
||||
private $mandatory;
|
||||
private $massEditable;
|
||||
private $tabid;
|
||||
private $presence;
|
||||
/**
|
||||
*
|
||||
* @var PearDatabase
|
||||
*/
|
||||
private $pearDB;
|
||||
private $typeOfData;
|
||||
private $fieldDataType;
|
||||
private $dataFromMeta;
|
||||
private static $tableMeta = array();
|
||||
private static $fieldTypeMapping = array();
|
||||
private $referenceList;
|
||||
private $defaultValuePresent;
|
||||
private $explicitDefaultValue;
|
||||
|
||||
private $genericUIType = 10;
|
||||
|
||||
private $readOnly = 0;
|
||||
|
||||
private function __construct($adb,$row){
|
||||
$this->uitype = $row['uitype'];
|
||||
$this->blockId = $row['block'];
|
||||
$this->blockName = null;
|
||||
$this->tableName = $row['tablename'];
|
||||
$this->columnName = $row['columnname'];
|
||||
$this->fieldName = $row['fieldname'];
|
||||
$this->fieldLabel = $row['fieldlabel'];
|
||||
$this->displayType = $row['displaytype'];
|
||||
$this->massEditable = ($row['masseditable'] === '1')? true: false;
|
||||
$typeOfData = $row['typeofdata'];
|
||||
$this->presence = $row['presence'];
|
||||
$this->typeOfData = $typeOfData;
|
||||
$typeOfData = explode("~",$typeOfData);
|
||||
$this->mandatory = ($typeOfData[1] == 'M')? true: false;
|
||||
if($this->uitype == 4){
|
||||
$this->mandatory = false;
|
||||
}
|
||||
$this->fieldType = $typeOfData[0];
|
||||
$this->tabid = $row['tabid'];
|
||||
$this->fieldId = $row['fieldid'];
|
||||
$this->pearDB = $adb;
|
||||
$this->fieldDataType = null;
|
||||
$this->dataFromMeta = false;
|
||||
$this->defaultValuePresent = false;
|
||||
$this->referenceList = null;
|
||||
$this->explicitDefaultValue = false;
|
||||
|
||||
$this->readOnly = (isset($row['readonly']))? $row['readonly'] : 0;
|
||||
|
||||
if(array_key_exists('defaultvalue', $row)) {
|
||||
$this->setDefault($row['defaultvalue']);
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromQueryResult($adb,$result,$rowNumber){
|
||||
return new WebserviceField($adb,$adb->query_result_rowdata($result,$rowNumber));
|
||||
}
|
||||
|
||||
public static function fromArray($adb,$row){
|
||||
return new WebserviceField($adb,$row);
|
||||
}
|
||||
|
||||
public function getTableName(){
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
public function getFieldName(){
|
||||
return $this->fieldName;
|
||||
}
|
||||
|
||||
public function getFieldLabelKey(){
|
||||
return $this->fieldLabel;
|
||||
}
|
||||
|
||||
public function getFieldType(){
|
||||
return $this->fieldType;
|
||||
}
|
||||
|
||||
public function isMandatory(){
|
||||
return $this->mandatory;
|
||||
}
|
||||
|
||||
public function getTypeOfData(){
|
||||
return $this->typeOfData;
|
||||
}
|
||||
|
||||
public function getDisplayType(){
|
||||
return $this->displayType;
|
||||
}
|
||||
|
||||
public function getMassEditable(){
|
||||
return $this->massEditable;
|
||||
}
|
||||
|
||||
public function getFieldId(){
|
||||
return $this->fieldId;
|
||||
}
|
||||
|
||||
public function getDefault(){
|
||||
if($this->dataFromMeta !== true && $this->explicitDefaultValue !== true){
|
||||
$this->fillColumnMeta();
|
||||
}
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
public function getColumnName(){
|
||||
return $this->columnName;
|
||||
}
|
||||
|
||||
public function getBlockId(){
|
||||
return $this->blockId;
|
||||
}
|
||||
|
||||
public function getBlockName(){
|
||||
if(empty($this->blockName)) {
|
||||
$this->blockName = getBlockName($this->blockId);
|
||||
}
|
||||
return $this->blockName;
|
||||
}
|
||||
|
||||
public function getTabId(){
|
||||
return $this->tabid;
|
||||
}
|
||||
|
||||
public function isNullable(){
|
||||
if($this->dataFromMeta !== true){
|
||||
$this->fillColumnMeta();
|
||||
}
|
||||
return $this->nullable;
|
||||
}
|
||||
|
||||
public function hasDefault(){
|
||||
if($this->dataFromMeta !== true && $this->explicitDefaultValue !== true){
|
||||
$this->fillColumnMeta();
|
||||
}
|
||||
return $this->defaultValuePresent;
|
||||
}
|
||||
|
||||
public function getUIType(){
|
||||
return $this->uitype;
|
||||
}
|
||||
|
||||
public function isReadOnly() {
|
||||
if($this->readOnly == 1) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private function setNullable($nullable){
|
||||
$this->nullable = $nullable;
|
||||
}
|
||||
|
||||
public function setDefault($value){
|
||||
$this->default = $value;
|
||||
$this->explicitDefaultValue = true;
|
||||
$this->defaultValuePresent = true;
|
||||
}
|
||||
|
||||
public function setFieldDataType($dataType){
|
||||
$this->fieldDataType = $dataType;
|
||||
}
|
||||
|
||||
public function setReferenceList($referenceList){
|
||||
$this->referenceList = $referenceList;
|
||||
}
|
||||
|
||||
public function getTableFields(){
|
||||
$tableFields = null;
|
||||
if(isset(WebserviceField::$tableMeta[$this->getTableName()])){
|
||||
$tableFields = WebserviceField::$tableMeta[$this->getTableName()];
|
||||
}else{
|
||||
$dbMetaColumns = $this->pearDB->database->MetaColumns($this->getTableName());
|
||||
$tableFields = array();
|
||||
foreach ($dbMetaColumns as $key => $dbField) {
|
||||
$tableFields[$dbField->name] = $dbField;
|
||||
}
|
||||
WebserviceField::$tableMeta[$this->getTableName()] = $tableFields;
|
||||
}
|
||||
return $tableFields;
|
||||
}
|
||||
public function fillColumnMeta(){
|
||||
$tableFields = $this->getTableFields();
|
||||
foreach ($tableFields as $fieldName => $dbField) {
|
||||
if(strcmp($fieldName,$this->getColumnName())===0){
|
||||
$this->setNullable(!$dbField->not_null);
|
||||
if($dbField->has_default === true && !$this->explicitDefaultValue){
|
||||
$this->defaultValuePresent = $dbField->has_default;
|
||||
$this->setDefault($dbField->default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->dataFromMeta = true;
|
||||
}
|
||||
|
||||
public function getFieldDataType(){
|
||||
if($this->fieldDataType === null){
|
||||
$fieldDataType = $this->getFieldTypeFromUIType();
|
||||
if($fieldDataType === null){
|
||||
$fieldDataType = $this->getFieldTypeFromTypeOfData();
|
||||
}
|
||||
if($fieldDataType == 'date' || $fieldDataType == 'datetime' || $fieldDataType == 'time') {
|
||||
$tableFieldDataType = $this->getFieldTypeFromTable();
|
||||
if($tableFieldDataType == 'datetime'){
|
||||
$fieldDataType = $tableFieldDataType;
|
||||
}
|
||||
}
|
||||
$this->fieldDataType = $fieldDataType;
|
||||
}
|
||||
return $this->fieldDataType;
|
||||
}
|
||||
|
||||
public function getReferenceList(){
|
||||
static $referenceList = array();
|
||||
if($this->referenceList === null){
|
||||
if(isset($referenceList[$this->getFieldId()])){
|
||||
$this->referenceList = $referenceList[$this->getFieldId()];
|
||||
return $referenceList[$this->getFieldId()];
|
||||
}
|
||||
if(!isset(WebserviceField::$fieldTypeMapping[$this->getUIType()])){
|
||||
$this->getFieldTypeFromUIType();
|
||||
}
|
||||
$fieldTypeData = WebserviceField::$fieldTypeMapping[$this->getUIType()];
|
||||
$referenceTypes = array();
|
||||
if($this->getUIType() != $this->genericUIType){
|
||||
$sql = "select * from vtiger_ws_referencetype where fieldtypeid=?";
|
||||
$params = array($fieldTypeData['fieldtypeid']);
|
||||
}else{
|
||||
$sql = 'select relmodule as type from vtiger_fieldmodulerel where fieldid=?';
|
||||
$params = array($this->getFieldId());
|
||||
}
|
||||
$result = $this->pearDB->pquery($sql,$params);
|
||||
$numRows = $this->pearDB->num_rows($result);
|
||||
for($i=0;$i<$numRows;++$i){
|
||||
array_push($referenceTypes,$this->pearDB->query_result($result,$i,"type"));
|
||||
}
|
||||
|
||||
//to handle hardcoding done for Calendar module todo activities.
|
||||
if($this->tabid == 9 && $this->fieldName =='parent_id'){
|
||||
$referenceTypes[] = 'Invoice';
|
||||
$referenceTypes[] = 'Quotes';
|
||||
$referenceTypes[] = 'PurchaseOrder';
|
||||
$referenceTypes[] = 'SalesOrder';
|
||||
$referenceTypes[] = 'Campaigns';
|
||||
}
|
||||
|
||||
global $current_user;
|
||||
$types = vtws_listtypes(null, $current_user);
|
||||
$accessibleTypes = $types['types'];
|
||||
if(!is_admin($current_user)) {
|
||||
array_push($accessibleTypes, 'Users');
|
||||
}
|
||||
$referenceTypes = array_values(array_intersect($accessibleTypes,$referenceTypes));
|
||||
$referenceList[$this->getFieldId()] = $referenceTypes;
|
||||
$this->referenceList = $referenceTypes;
|
||||
return $referenceTypes;
|
||||
}
|
||||
return $this->referenceList;
|
||||
}
|
||||
|
||||
private function getFieldTypeFromTable(){
|
||||
$tableFields = $this->getTableFields();
|
||||
foreach ($tableFields as $fieldName => $dbField) {
|
||||
if(strcmp($fieldName,$this->getColumnName())===0){
|
||||
return $dbField->type;
|
||||
}
|
||||
}
|
||||
//This should not be returned if entries in DB are correct.
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getFieldTypeFromTypeOfData(){
|
||||
switch($this->fieldType){
|
||||
case 'T': return "time";
|
||||
case 'D':
|
||||
case 'DT': return "date";
|
||||
case 'E': return "email";
|
||||
case 'N':
|
||||
case 'NN': return "double";
|
||||
case 'P': return "password";
|
||||
case 'I': return "integer";
|
||||
case 'V':
|
||||
default: return "string";
|
||||
}
|
||||
}
|
||||
|
||||
private function getFieldTypeFromUIType(){
|
||||
|
||||
// Cache all the information for futher re-use
|
||||
if(empty(self::$fieldTypeMapping)) {
|
||||
$result = $this->pearDB->pquery("select * from vtiger_ws_fieldtype", array());
|
||||
while($resultrow = $this->pearDB->fetch_array($result)) {
|
||||
self::$fieldTypeMapping[$resultrow['uitype']] = $resultrow;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset(WebserviceField::$fieldTypeMapping[$this->getUIType()])){
|
||||
if(WebserviceField::$fieldTypeMapping[$this->getUIType()] === false){
|
||||
return null;
|
||||
}
|
||||
$row = WebserviceField::$fieldTypeMapping[$this->getUIType()];
|
||||
return $row['fieldtype'];
|
||||
} else {
|
||||
WebserviceField::$fieldTypeMapping[$this->getUIType()] = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getPicklistDetails(){
|
||||
$hardCodedPickListNames = array("hdntaxtype","email_flag");
|
||||
$hardCodedPickListValues = array(
|
||||
"hdntaxtype"=>array(
|
||||
array("label"=>"Individual","value"=>"individual"),
|
||||
array("label"=>"Group","value"=>"group")
|
||||
),
|
||||
"email_flag" => array(
|
||||
array('label'=>'SAVED','value'=>'SAVED'),
|
||||
array('label'=>'SENT','value' => 'SENT'),
|
||||
array('label'=>'MAILSCANNER','value' => 'MAILSCANNER')
|
||||
)
|
||||
);
|
||||
if(in_array(strtolower($this->getFieldName()),$hardCodedPickListNames)){
|
||||
return $hardCodedPickListValues[strtolower($this->getFieldName())];
|
||||
}
|
||||
return $this->getPickListOptions($this->getFieldName());
|
||||
}
|
||||
|
||||
function getPickListOptions(){
|
||||
$fieldName = $this->getFieldName();
|
||||
|
||||
$default_charset = VTWS_PreserveGlobal::getGlobal('default_charset');
|
||||
$options = array();
|
||||
$sql = "select * from vtiger_picklist where name=?";
|
||||
$result = $this->pearDB->pquery($sql,array($fieldName));
|
||||
$numRows = $this->pearDB->num_rows($result);
|
||||
if($numRows == 0){
|
||||
$sql = "select * from vtiger_$fieldName";
|
||||
$result = $this->pearDB->pquery($sql,array());
|
||||
$numRows = $this->pearDB->num_rows($result);
|
||||
for($i=0;$i<$numRows;++$i){
|
||||
$elem = array();
|
||||
$picklistValue = $this->pearDB->query_result($result,$i,$fieldName);
|
||||
$picklistValue = decode_html($picklistValue);
|
||||
$moduleName = getTabModuleName($this->getTabId());
|
||||
if($moduleName == 'Events') $moduleName = 'Calendar';
|
||||
$elem["label"] = getTranslatedString($picklistValue,$moduleName);
|
||||
$elem["value"] = $picklistValue;
|
||||
array_push($options,$elem);
|
||||
}
|
||||
}else{
|
||||
$user = VTWS_PreserveGlobal::getGlobal('current_user');
|
||||
$details = getPickListValues($fieldName,$user->roleid);
|
||||
for($i=0;$i<sizeof($details);++$i){
|
||||
$elem = array();
|
||||
$picklistValue = decode_html($details[$i]);
|
||||
$moduleName = getTabModuleName($this->getTabId());
|
||||
if($moduleName == 'Events') $moduleName = 'Calendar';
|
||||
$elem["label"] = getTranslatedString($picklistValue,$moduleName);
|
||||
$elem["value"] = $picklistValue;
|
||||
array_push($options,$elem);
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
function getPresence() {
|
||||
return $this->presence;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,28 @@
|
|||
<?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.
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
$app_strings = array (
|
||||
'Groups'=>'Gruppen',
|
||||
'DocumentFolders'=>'Dokumentenverzeichnisse',
|
||||
'Currency'=>'Währung',
|
||||
'SINGLE_Groups'=>'Gruppe',
|
||||
'SINGLE_DocumentFolders'=>'Dokumentenverzeichnis',
|
||||
'SINGLE_Currency'=>'Währung',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Ungültige Angabe des alten Passwortes.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "Die beiden Passwörter stimmen nicht überein.",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Ihre Anfrage konnte aufgrund eines Datenbankfehlers nicht verarbeitet werden.',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'Passwort konnte nicht geändert werden.Failed to change password',
|
||||
);
|
||||
|
||||
?>
|
|
@ -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.
|
||||
*
|
||||
********************************************************************************/
|
||||
$app_strings = array (
|
||||
'Groups'=>'Groups',
|
||||
'DocumentFolders'=>'Document Folders',
|
||||
'Currency'=>'Currency',
|
||||
'SINGLE_Groups'=>'Group',
|
||||
'SINGLE_DocumentFolders'=>'Document Folder',
|
||||
'SINGLE_Currency'=>'Currency',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Invalid value given for old password.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "New password and confirm password don't match",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Database error while performing requested operation',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'Failed to change password',
|
||||
);
|
||||
?>
|
|
@ -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.
|
||||
*
|
||||
********************************************************************************/
|
||||
$app_strings = array (
|
||||
'Groups'=>'Groups',
|
||||
'DocumentFolders'=>'Document Folders',
|
||||
'Currency'=>'Currency',
|
||||
'SINGLE_Groups'=>'Group',
|
||||
'SINGLE_DocumentFolders'=>'Document Folder',
|
||||
'SINGLE_Currency'=>'Currency',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Invalid value given for old password.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "New Password and confirm password don't match",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Database error while performing requested operation',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'Failed to change password',
|
||||
);
|
||||
|
||||
?>
|
|
@ -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.
|
||||
*
|
||||
********************************************************************************/
|
||||
$app_strings = array (
|
||||
'Groups'=>'Grupos',
|
||||
'DocumentFolders'=>'Carpetas Documentos',
|
||||
'Currency'=>'Monedas',
|
||||
'SINGLE_Groups'=>'Grupo',
|
||||
'SINGLE_DocumentFolders'=>'Carpeta Documento',
|
||||
'SINGLE_Currency'=>'Moneda',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Contraseña anterior inválida.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "Nueva contraseña y confirmación no coinciden.",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Error de base de datos al procesar la operación',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'No se ha podido cambiar la contraseña',
|
||||
);
|
||||
|
||||
?>
|
|
@ -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.
|
||||
* Es_mx Author: Francisco Hernandez Odin Consultores www.odin.mx
|
||||
********************************************************************************/
|
||||
$app_strings = array (
|
||||
'Groups'=>'Grupos',
|
||||
'DocumentFolders'=>'Carpetas Documentos',
|
||||
'Currency'=>'Monedas',
|
||||
'SINGLE_Groups'=>'Grupo',
|
||||
'SINGLE_DocumentFolders'=>'Carpeta Documento',
|
||||
'SINGLE_Currency'=>'Moneda',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Contraseña anterior inválida.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "Nueva contraseña y confirmación no coinciden.",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Error de base de datos al procesar la operación',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'No se ha podido cambiar la contraseña',
|
||||
);
|
||||
|
||||
?>
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/*******************************************************************************
|
||||
* The contents of this file are subject to the following licences:
|
||||
* - SugarCRM Public License Version 1.1.2 http://www.sugarcrm.com/SPL
|
||||
* - vtiger CRM Public License Version 1.0
|
||||
* You may not use this file except in compliance with the License
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
* the specific language governing rights and limitations under the License.
|
||||
* The Original Code is: SugarCRM Open Source
|
||||
* The Initial Developer of the Original Code is SugarCRM, Inc.
|
||||
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.;
|
||||
* Portions created by vtiger are Copyright (C) vtiger.
|
||||
* Portions created by Vicus are Copyright (C) Vicus.
|
||||
* All Rights Reserved.
|
||||
* Feel free to use / redistribute these languagefiles under the VPL 1.0.
|
||||
* This translations is based on earlier work of:
|
||||
* - IT-Online.nl <www.it-online.nl>
|
||||
* - Weltevree.org <www.Weltevree.org>
|
||||
********************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Vicus eBusiness Solutions Version Control
|
||||
* @package NL-Dutch
|
||||
* Description Dutch language pack for vtiger CRM version 5.3.x
|
||||
* @author $Author: luuk $
|
||||
* @version $Revision: 1.2 $ $Date: 2011/11/14 17:07:26 $
|
||||
* @source $Source: /var/lib/cvs/vtiger530/Dutch/include/Webservices/language/nl_nl.lang.php,v $
|
||||
* @copyright Copyright (c)2005-2011 Vicus eBusiness Solutions bv <info@vicus.nl>
|
||||
* @license vtiger CRM Public License Version 1.0 (by definition)
|
||||
********************************************************************************/
|
||||
|
||||
$app_strings = array (
|
||||
'Groups'=>'Groepen',
|
||||
'DocumentFolders'=>'Documentmappen',
|
||||
'Currency'=>'Valuta',
|
||||
'SINGLE_Groups'=>'Groep',
|
||||
'SINGLE_DocumentFolders'=>'Documentmap',
|
||||
'SINGLE_Currency'=>'Valuta',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Ongeldige waarden gegeven voor het oude wachtwoord.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "Het nieuwe wachtwoord komt niet overeen met de bevestiging.",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Database fout tijdens uitvoeren van de gevraagde operatie',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'Wijzigen wachtwoord is mislukt',
|
||||
);
|
||||
|
||||
?>
|
|
@ -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.
|
||||
* Contributor(s): Valmir Carlos Trindade/Translate to Brazilian Portuguese|03/03/2012|Curitiba/Paraná/Brasil.|www.ttcasolucoes.com.br
|
||||
********************************************************************************/
|
||||
$app_strings = array (
|
||||
'Groups'=>'Grupos',
|
||||
'DocumentFolders'=>'Pastas Documentos',
|
||||
'Currency'=>'Moeda',
|
||||
'SINGLE_Groups'=>'Grupo',
|
||||
'SINGLE_DocumentFolders'=>'Pasta Documento',
|
||||
'SINGLE_Currency'=>'Moeda',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Senha antiga inválida.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "A nova Senha e a Senha de confirmação não são iguais",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Erro na base de dados ao executar a operação solicitada',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'Falha ao alterar a Senha',
|
||||
);
|
||||
|
||||
?>
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (C) 2006-2012 YUCHENG HU
|
||||
*
|
||||
* ---------------------------------------------------------
|
||||
* OSSEZ (中国) 信息技术有限公司
|
||||
* http://www.ossez.com
|
||||
* http://src.ossez.com
|
||||
*
|
||||
* CONTACT
|
||||
* huyuchengus@gmail.com / yucheng.hu@ossez.com
|
||||
*
|
||||
* ---------------------------------------------------------
|
||||
* [A] GNU GENERAL PUBLIC LICENSE GNU/LGPL
|
||||
* [B] Apache License, Version 2.0
|
||||
*
|
||||
* ---------------------------------------------------------
|
||||
* NOTE
|
||||
* 1. 所有的语言配置文件必须采用无 BOM 的 UTF-8 编码
|
||||
* 2. 本语言文件为 ossez-5.4.0 分支,适用于 vTiger 5.4.0
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
|
||||
$app_strings = array (
|
||||
'Groups'=>'Groups',
|
||||
'DocumentFolders'=>'Document Folders',
|
||||
'Currency'=>'Currency',
|
||||
'SINGLE_Groups'=>'Group',
|
||||
'SINGLE_DocumentFolders'=>'Document Folder',
|
||||
'SINGLE_Currency'=>'Currency',
|
||||
);
|
||||
|
||||
$webservice_strings = array(
|
||||
'LBL_INVALID_OLD_PASSWORD' => 'Invalid value given for old password.',
|
||||
'LBL_NEW_PASSWORD_MISMATCH' => "New Password and confirm password don't match",
|
||||
'LBL_DATABASE_QUERY_ERROR' => 'Database error while performing requested operation',
|
||||
'LBL_CHANGE_PASSWORD_FAILURE' => 'Failed to change password',
|
||||
);
|
||||
|
||||
?>
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Exception extends Exception
|
||||
{}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Class for encoding to and decoding from JSON.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Json
|
||||
{
|
||||
/**
|
||||
* How objects should be encoded -- arrays or as StdClass. TYPE_ARRAY is 1
|
||||
* so that it is a boolean true value, allowing it to be used with
|
||||
* ext/json's functions.
|
||||
*/
|
||||
const TYPE_ARRAY = 1;
|
||||
const TYPE_OBJECT = 0;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public static $useBuiltinEncoderDecoder = false;
|
||||
|
||||
/**
|
||||
* Decodes the given $encodedValue string which is
|
||||
* encoded in the JSON format
|
||||
*
|
||||
* Uses ext/json's json_decode if available.
|
||||
*
|
||||
* @param string $encodedValue Encoded in JSON format
|
||||
* @param int $objectDecodeType Optional; flag indicating how to decode
|
||||
* objects. See {@link ZJsonDecoder::decode()} for details.
|
||||
* @return mixed
|
||||
*/
|
||||
public static function decode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
|
||||
{
|
||||
if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
|
||||
return json_decode($encodedValue, $objectDecodeType);
|
||||
}
|
||||
|
||||
require_once 'include/Zend/Json/Decoder.php';
|
||||
return Zend_Json_Decoder::decode($encodedValue, $objectDecodeType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode the mixed $valueToEncode into the JSON format
|
||||
*
|
||||
* Encodes using ext/json's json_encode() if available.
|
||||
*
|
||||
* NOTE: Object should not contain cycles; the JSON format
|
||||
* does not allow object reference.
|
||||
*
|
||||
* NOTE: Only public variables will be encoded
|
||||
*
|
||||
* @param mixed $valueToEncode
|
||||
* @param boolean $cycleCheck Optional; whether or not to check for object recursion; off by default
|
||||
* @return string JSON encoded object
|
||||
*/
|
||||
public static function encode($valueToEncode, $cycleCheck = false)
|
||||
{
|
||||
if (function_exists('json_encode') && self::$useBuiltinEncoderDecoder !== true) {
|
||||
return json_encode($valueToEncode);
|
||||
}
|
||||
|
||||
require_once 'include/Zend/Json/Encoder.php';
|
||||
return Zend_Json_Encoder::encode($valueToEncode, $cycleCheck);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,457 @@
|
|||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Zend_Json
|
||||
*/
|
||||
require_once 'include/Zend/Json.php';
|
||||
|
||||
/**
|
||||
* Zend_Json_Exception
|
||||
*/
|
||||
require_once 'include/Zend/Json/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* Decode JSON encoded string to PHP variable constructs
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Json_Decoder
|
||||
{
|
||||
/**
|
||||
* Parse tokens used to decode the JSON object. These are not
|
||||
* for public consumption, they are just used internally to the
|
||||
* class.
|
||||
*/
|
||||
const EOF = 0;
|
||||
const DATUM = 1;
|
||||
const LBRACE = 2;
|
||||
const LBRACKET = 3;
|
||||
const RBRACE = 4;
|
||||
const RBRACKET = 5;
|
||||
const COMMA = 6;
|
||||
const COLON = 7;
|
||||
|
||||
/**
|
||||
* Use to maintain a "pointer" to the source being decoded
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_source;
|
||||
|
||||
/**
|
||||
* Caches the source length
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_sourceLength;
|
||||
|
||||
/**
|
||||
* The offset within the souce being decoded
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
*/
|
||||
protected $_offset;
|
||||
|
||||
/**
|
||||
* The current token being considered in the parser cycle
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_token;
|
||||
|
||||
/**
|
||||
* Flag indicating how objects should be decoded
|
||||
*
|
||||
* @var int
|
||||
* @access protected
|
||||
*/
|
||||
protected $_decodeType;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $source String source to decode
|
||||
* @param int $decodeType How objects should be decoded -- see
|
||||
* {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for
|
||||
* valid values
|
||||
* @return void
|
||||
*/
|
||||
protected function __construct($source, $decodeType)
|
||||
{
|
||||
// Set defaults
|
||||
$this->_source = $source;
|
||||
$this->_sourceLength = strlen($source);
|
||||
$this->_token = self::EOF;
|
||||
$this->_offset = 0;
|
||||
|
||||
// Normalize and set $decodeType
|
||||
if (!in_array($decodeType, array(Zend_Json::TYPE_ARRAY, Zend_Json::TYPE_OBJECT)))
|
||||
{
|
||||
$decodeType = Zend_Json::TYPE_ARRAY;
|
||||
}
|
||||
$this->_decodeType = $decodeType;
|
||||
|
||||
// Set pointer at first token
|
||||
$this->_getNextToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a JSON source string
|
||||
*
|
||||
* Decodes a JSON encoded string. The value returned will be one of the
|
||||
* following:
|
||||
* - integer
|
||||
* - float
|
||||
* - boolean
|
||||
* - null
|
||||
* - StdClass
|
||||
* - array
|
||||
* - array of one or more of the above types
|
||||
*
|
||||
* By default, decoded objects will be returned as associative arrays; to
|
||||
* return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to
|
||||
* the $objectDecodeType parameter.
|
||||
*
|
||||
* Throws a Zend_Json_Exception if the source string is null.
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $source String to be decoded
|
||||
* @param int $objectDecodeType How objects should be decoded; should be
|
||||
* either or {@link Zend_Json::TYPE_ARRAY} or
|
||||
* {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
|
||||
* @return mixed
|
||||
* @throws Zend_Json_Exception
|
||||
*/
|
||||
public static function decode($source = null, $objectDecodeType = Zend_Json::TYPE_ARRAY)
|
||||
{
|
||||
if (null === $source) {
|
||||
throw new Zend_Json_Exception('Must specify JSON encoded source for decoding');
|
||||
} elseif (!is_string($source)) {
|
||||
throw new Zend_Json_Exception('Can only decode JSON encoded strings');
|
||||
}
|
||||
|
||||
$decoder = new self($source, $objectDecodeType);
|
||||
|
||||
return $decoder->_decodeValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursive driving rountine for supported toplevel tops
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function _decodeValue()
|
||||
{
|
||||
switch ($this->_token) {
|
||||
case self::DATUM:
|
||||
$result = $this->_tokenValue;
|
||||
$this->_getNextToken();
|
||||
return($result);
|
||||
break;
|
||||
case self::LBRACE:
|
||||
return($this->_decodeObject());
|
||||
break;
|
||||
case self::LBRACKET:
|
||||
return($this->_decodeArray());
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an object of the form:
|
||||
* { "attribute: value, "attribute2" : value,...}
|
||||
*
|
||||
* If ZJsonEnoder or ZJAjax was used to encode the original object
|
||||
* then a special attribute called __className which specifies a class
|
||||
* name that should wrap the data contained within the encoded source.
|
||||
*
|
||||
* Decodes to either an array or StdClass object, based on the value of
|
||||
* {@link $_decodeType}. If invalid $_decodeType present, returns as an
|
||||
* array.
|
||||
*
|
||||
* @return array|StdClass
|
||||
*/
|
||||
protected function _decodeObject()
|
||||
{
|
||||
$members = array();
|
||||
$tok = $this->_getNextToken();
|
||||
|
||||
while ($tok && $tok != self::RBRACE) {
|
||||
if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
|
||||
throw new Zend_Json_Exception('Missing key in object encoding: ' . $this->_source);
|
||||
}
|
||||
|
||||
$key = $this->_tokenValue;
|
||||
$tok = $this->_getNextToken();
|
||||
|
||||
if ($tok != self::COLON) {
|
||||
throw new Zend_Json_Exception('Missing ":" in object encoding: ' . $this->_source);
|
||||
}
|
||||
|
||||
$tok = $this->_getNextToken();
|
||||
$members[$key] = $this->_decodeValue();
|
||||
$tok = $this->_token;
|
||||
|
||||
if ($tok == self::RBRACE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($tok != self::COMMA) {
|
||||
throw new Zend_Json_Exception('Missing "," in object encoding: ' . $this->_source);
|
||||
}
|
||||
|
||||
$tok = $this->_getNextToken();
|
||||
}
|
||||
|
||||
switch ($this->_decodeType) {
|
||||
case Zend_Json::TYPE_OBJECT:
|
||||
// Create new StdClass and populate with $members
|
||||
$result = new StdClass();
|
||||
foreach ($members as $key => $value) {
|
||||
$result->$key = $value;
|
||||
}
|
||||
break;
|
||||
case Zend_Json::TYPE_ARRAY:
|
||||
default:
|
||||
$result = $members;
|
||||
break;
|
||||
}
|
||||
|
||||
$this->_getNextToken();
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a JSON array format:
|
||||
* [element, element2,...,elementN]
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _decodeArray()
|
||||
{
|
||||
$result = array();
|
||||
$starttok = $tok = $this->_getNextToken(); // Move past the '['
|
||||
$index = 0;
|
||||
|
||||
while ($tok && $tok != self::RBRACKET) {
|
||||
$result[$index++] = $this->_decodeValue();
|
||||
|
||||
$tok = $this->_token;
|
||||
|
||||
if ($tok == self::RBRACKET || !$tok) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($tok != self::COMMA) {
|
||||
throw new Zend_Json_Exception('Missing "," in array encoding: ' . $this->_source);
|
||||
}
|
||||
|
||||
$tok = $this->_getNextToken();
|
||||
}
|
||||
|
||||
$this->_getNextToken();
|
||||
return($result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes whitepsace characters from the source input
|
||||
*/
|
||||
protected function _eatWhitespace()
|
||||
{
|
||||
if (preg_match(
|
||||
'/([\t\b\f\n\r ])*/s',
|
||||
$this->_source,
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE,
|
||||
$this->_offset)
|
||||
&& $matches[0][1] == $this->_offset)
|
||||
{
|
||||
$this->_offset += strlen($matches[0][0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the next token from the source stream
|
||||
*
|
||||
* @return int Token constant value specified in class definition
|
||||
*/
|
||||
protected function _getNextToken()
|
||||
{
|
||||
$this->_token = self::EOF;
|
||||
$this->_tokenValue = null;
|
||||
$this->_eatWhitespace();
|
||||
|
||||
if ($this->_offset >= $this->_sourceLength) {
|
||||
return(self::EOF);
|
||||
}
|
||||
|
||||
$str = $this->_source;
|
||||
$str_length = $this->_sourceLength;
|
||||
$i = $this->_offset;
|
||||
$start = $i;
|
||||
|
||||
switch ($str{$i}) {
|
||||
case '{':
|
||||
$this->_token = self::LBRACE;
|
||||
break;
|
||||
case '}':
|
||||
$this->_token = self::RBRACE;
|
||||
break;
|
||||
case '[':
|
||||
$this->_token = self::LBRACKET;
|
||||
break;
|
||||
case ']':
|
||||
$this->_token = self::RBRACKET;
|
||||
break;
|
||||
case ',':
|
||||
$this->_token = self::COMMA;
|
||||
break;
|
||||
case ':':
|
||||
$this->_token = self::COLON;
|
||||
break;
|
||||
case '"':
|
||||
$result = '';
|
||||
do {
|
||||
$i++;
|
||||
if ($i >= $str_length) {
|
||||
break;
|
||||
}
|
||||
|
||||
$chr = $str{$i};
|
||||
if ($chr == '\\') {
|
||||
$i++;
|
||||
if ($i >= $str_length) {
|
||||
break;
|
||||
}
|
||||
$chr = $str{$i};
|
||||
switch ($chr) {
|
||||
case '"' :
|
||||
$result .= '"';
|
||||
break;
|
||||
case '\\':
|
||||
$result .= '\\';
|
||||
break;
|
||||
case '/' :
|
||||
$result .= '/';
|
||||
break;
|
||||
case 'b' :
|
||||
$result .= chr(8);
|
||||
break;
|
||||
case 'f' :
|
||||
$result .= chr(12);
|
||||
break;
|
||||
case 'n' :
|
||||
$result .= chr(10);
|
||||
break;
|
||||
case 'r' :
|
||||
$result .= chr(13);
|
||||
break;
|
||||
case 't' :
|
||||
$result .= chr(9);
|
||||
break;
|
||||
case '\'' :
|
||||
$result .= '\'';
|
||||
break;
|
||||
default:
|
||||
throw new Zend_Json_Exception("Illegal escape "
|
||||
. "sequence '" . $chr . "'");
|
||||
}
|
||||
} elseif ($chr == '"') {
|
||||
break;
|
||||
} else {
|
||||
$result .= $chr;
|
||||
}
|
||||
} while ($i < $str_length);
|
||||
|
||||
$this->_token = self::DATUM;
|
||||
//$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
|
||||
$this->_tokenValue = $result;
|
||||
break;
|
||||
case 't':
|
||||
if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
|
||||
$this->_token = self::DATUM;
|
||||
}
|
||||
$this->_tokenValue = true;
|
||||
$i += 3;
|
||||
break;
|
||||
case 'f':
|
||||
if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
|
||||
$this->_token = self::DATUM;
|
||||
}
|
||||
$this->_tokenValue = false;
|
||||
$i += 4;
|
||||
break;
|
||||
case 'n':
|
||||
if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
|
||||
$this->_token = self::DATUM;
|
||||
}
|
||||
$this->_tokenValue = NULL;
|
||||
$i += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->_token != self::EOF) {
|
||||
$this->_offset = $i + 1; // Consume the last token character
|
||||
return($this->_token);
|
||||
}
|
||||
|
||||
$chr = $str{$i};
|
||||
if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
|
||||
if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
|
||||
$str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
|
||||
|
||||
$datum = $matches[0][0];
|
||||
|
||||
if (is_numeric($datum)) {
|
||||
if (preg_match('/^0\d+$/', $datum)) {
|
||||
throw new Zend_Json_Exception("Octal notation not supported by JSON (value: $datum)");
|
||||
} else {
|
||||
$val = intval($datum);
|
||||
$fVal = floatval($datum);
|
||||
$this->_tokenValue = ($val == $fVal ? $val : $fVal);
|
||||
}
|
||||
} else {
|
||||
throw new Zend_Json_Exception("Illegal number format: $datum");
|
||||
}
|
||||
|
||||
$this->_token = self::DATUM;
|
||||
$this->_offset = $start + strlen($datum);
|
||||
}
|
||||
} else {
|
||||
throw new Zend_Json_Exception('Illegal Token');
|
||||
}
|
||||
|
||||
return($this->_token);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Zend_Json_Exception
|
||||
*/
|
||||
require_once 'include/Zend/Json/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* Encode PHP constructs to JSON
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Json_Encoder
|
||||
{
|
||||
/**
|
||||
* Whether or not to check for possible cycling
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_cycleCheck;
|
||||
|
||||
/**
|
||||
* Array of visited objects; used to prevent cycling.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_visited = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param boolean $cycleCheck Whether or not to check for recursion when encoding
|
||||
* @return void
|
||||
*/
|
||||
protected function __construct($cycleCheck = false)
|
||||
{
|
||||
$this->_cycleCheck = $cycleCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the JSON encoding scheme for the value specified
|
||||
*
|
||||
* @param mixed $value The value to be encoded
|
||||
* @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
|
||||
* @return string The encoded value
|
||||
*/
|
||||
public static function encode($value, $cycleCheck = false)
|
||||
{
|
||||
$encoder = new Zend_Json_Encoder(($cycleCheck) ? true : false);
|
||||
|
||||
return $encoder->_encodeValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive driver which determines the type of value to be encoded
|
||||
* and then dispatches to the appropriate method. $values are either
|
||||
* - objects (returns from {@link _encodeObject()})
|
||||
* - arrays (returns from {@link _encodeArray()})
|
||||
* - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
|
||||
*
|
||||
* @param $value mixed The value to be encoded
|
||||
* @return string Encoded value
|
||||
*/
|
||||
protected function _encodeValue(&$value)
|
||||
{
|
||||
if (is_object($value)) {
|
||||
return $this->_encodeObject($value);
|
||||
} else if (is_array($value)) {
|
||||
return $this->_encodeArray($value);
|
||||
}
|
||||
|
||||
return $this->_encodeDatum($value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Encode an object to JSON by encoding each of the public properties
|
||||
*
|
||||
* A special property is added to the JSON object called '__className'
|
||||
* that contains the name of the class of $value. This is used to decode
|
||||
* the object on the client into a specific class.
|
||||
*
|
||||
* @param $value object
|
||||
* @return string
|
||||
* @throws Zend_Json_Exception If recursive checks are enabled and the object has been serialized previously
|
||||
*/
|
||||
protected function _encodeObject(&$value)
|
||||
{
|
||||
if ($this->_cycleCheck) {
|
||||
if ($this->_wasVisited($value)) {
|
||||
throw new Zend_Json_Exception(
|
||||
'Cycles not supported in JSON encoding, cycle introduced by '
|
||||
. 'class "' . get_class($value) . '"'
|
||||
);
|
||||
}
|
||||
|
||||
$this->_visited[] = $value;
|
||||
}
|
||||
|
||||
$props = '';
|
||||
foreach (get_object_vars($value) as $name => $propValue) {
|
||||
if (isset($propValue)) {
|
||||
$props .= ','
|
||||
. $this->_encodeValue($name)
|
||||
. ':'
|
||||
. $this->_encodeValue($propValue);
|
||||
}
|
||||
}
|
||||
|
||||
/*return '{"__className":"' . get_class($value) . '"'
|
||||
. $props . '}';*/
|
||||
return '{'.substr($props,1).'}';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if an object has been serialized already
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _wasVisited(&$value)
|
||||
{
|
||||
if (in_array($value, $this->_visited, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JSON encode an array value
|
||||
*
|
||||
* Recursively encodes each value of an array and returns a JSON encoded
|
||||
* array string.
|
||||
*
|
||||
* Arrays are defined as integer-indexed arrays starting at index 0, where
|
||||
* the last index is (count($array) -1); any deviation from that is
|
||||
* considered an associative array, and will be encoded as such.
|
||||
*
|
||||
* @param $array array
|
||||
* @return string
|
||||
*/
|
||||
protected function _encodeArray(&$array)
|
||||
{
|
||||
$tmpArray = array();
|
||||
|
||||
// Check for associative array
|
||||
if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
|
||||
// Associative array
|
||||
$result = '{';
|
||||
foreach ($array as $key => $value) {
|
||||
$key = (string) $key;
|
||||
$tmpArray[] = $this->_encodeString($key)
|
||||
. ':'
|
||||
. $this->_encodeValue($value);
|
||||
}
|
||||
$result .= implode(',', $tmpArray);
|
||||
$result .= '}';
|
||||
} else {
|
||||
// Indexed array
|
||||
$result = '[';
|
||||
$length = count($array);
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$tmpArray[] = $this->_encodeValue($array[$i]);
|
||||
}
|
||||
$result .= implode(',', $tmpArray);
|
||||
$result .= ']';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JSON encode a basic data type (string, number, boolean, null)
|
||||
*
|
||||
* If value type is not a string, number, boolean, or null, the string
|
||||
* 'null' is returned.
|
||||
*
|
||||
* @param $value mixed
|
||||
* @return string
|
||||
*/
|
||||
protected function _encodeDatum(&$value)
|
||||
{
|
||||
$result = 'null';
|
||||
|
||||
if (is_int($value) || is_float($value)) {
|
||||
$result = (string)$value;
|
||||
} elseif (is_string($value)) {
|
||||
$result = $this->_encodeString($value);
|
||||
} elseif (is_bool($value)) {
|
||||
$result = $value ? 'true' : 'false';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JSON encode a string value by escaping characters as necessary
|
||||
*
|
||||
* @param $value string
|
||||
* @return string
|
||||
*/
|
||||
protected function _encodeString(&$string)
|
||||
{
|
||||
// Escape these characters with a backslash:
|
||||
// " \ / \n \r \t \b \f
|
||||
$search = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
|
||||
$replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
|
||||
$string = str_replace($search, $replace, $string);
|
||||
|
||||
// Escape certain ASCII characters:
|
||||
// 0x08 => \b
|
||||
// 0x0c => \f
|
||||
$string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
|
||||
|
||||
return '"' . $string . '"';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode the constants associated with the ReflectionClass
|
||||
* parameter. The encoding format is based on the class2 format
|
||||
*
|
||||
* @param $cls ReflectionClass
|
||||
* @return string Encoded constant block in class2 format
|
||||
*/
|
||||
private static function _encodeConstants(ReflectionClass $cls)
|
||||
{
|
||||
$result = "constants : {";
|
||||
$constants = $cls->getConstants();
|
||||
|
||||
$tmpArray = array();
|
||||
if (!empty($constants)) {
|
||||
foreach ($constants as $key => $value) {
|
||||
$tmpArray[] = "$key: " . self::encode($value);
|
||||
}
|
||||
|
||||
$result .= implode(', ', $tmpArray);
|
||||
}
|
||||
|
||||
return $result . "}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode the public methods of the ReflectionClass in the
|
||||
* class2 format
|
||||
*
|
||||
* @param $cls ReflectionClass
|
||||
* @return string Encoded method fragment
|
||||
*
|
||||
*/
|
||||
private static function _encodeMethods(ReflectionClass $cls)
|
||||
{
|
||||
$methods = $cls->getMethods();
|
||||
$result = 'methods:{';
|
||||
|
||||
$started = false;
|
||||
foreach ($methods as $method) {
|
||||
if (! $method->isPublic() || !$method->isUserDefined()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($started) {
|
||||
$result .= ',';
|
||||
}
|
||||
$started = true;
|
||||
|
||||
$result .= '' . $method->getName(). ':function(';
|
||||
|
||||
if ('__construct' != $method->getName()) {
|
||||
$parameters = $method->getParameters();
|
||||
$paramCount = count($parameters);
|
||||
$argsStarted = false;
|
||||
|
||||
$argNames = "var argNames=[";
|
||||
foreach ($parameters as $param) {
|
||||
if ($argsStarted) {
|
||||
$result .= ',';
|
||||
}
|
||||
|
||||
$result .= $param->getName();
|
||||
|
||||
if ($argsStarted) {
|
||||
$argNames .= ',';
|
||||
}
|
||||
|
||||
$argNames .= '"' . $param->getName() . '"';
|
||||
|
||||
$argsStarted = true;
|
||||
}
|
||||
$argNames .= "];";
|
||||
|
||||
$result .= "){"
|
||||
. $argNames
|
||||
. 'var result = ZAjaxEngine.invokeRemoteMethod('
|
||||
. "this, '" . $method->getName()
|
||||
. "',argNames,arguments);"
|
||||
. 'return(result);}';
|
||||
} else {
|
||||
$result .= "){}";
|
||||
}
|
||||
}
|
||||
|
||||
return $result . "}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode the public properties of the ReflectionClass in the class2
|
||||
* format.
|
||||
*
|
||||
* @param $cls ReflectionClass
|
||||
* @return string Encode properties list
|
||||
*
|
||||
*/
|
||||
private static function _encodeVariables(ReflectionClass $cls)
|
||||
{
|
||||
$properties = $cls->getProperties();
|
||||
$propValues = get_class_vars($cls->getName());
|
||||
$result = "variables:{";
|
||||
$cnt = 0;
|
||||
|
||||
$tmpArray = array();
|
||||
foreach ($properties as $prop) {
|
||||
if (! $prop->isPublic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tmpArray[] = $prop->getName()
|
||||
. ':'
|
||||
. self::encode($propValues[$prop->getName()]);
|
||||
}
|
||||
$result .= implode(',', $tmpArray);
|
||||
|
||||
return $result . "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given $className into the class2 model of encoding PHP
|
||||
* classes into JavaScript class2 classes.
|
||||
* NOTE: Currently only public methods and variables are proxied onto
|
||||
* the client machine
|
||||
*
|
||||
* @param $className string The name of the class, the class must be
|
||||
* instantiable using a null constructor
|
||||
* @param $package string Optional package name appended to JavaScript
|
||||
* proxy class name
|
||||
* @return string The class2 (JavaScript) encoding of the class
|
||||
* @throws Zend_Json_Exception
|
||||
*/
|
||||
public static function encodeClass($className, $package = '')
|
||||
{
|
||||
$cls = new ReflectionClass($className);
|
||||
if (! $cls->isInstantiable()) {
|
||||
throw new Zend_Json_Exception("$className must be instantiable");
|
||||
}
|
||||
|
||||
return "Class.create('$package$className',{"
|
||||
. self::_encodeConstants($cls) .","
|
||||
. self::_encodeMethods($cls) .","
|
||||
. self::_encodeVariables($cls) .'});';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode several classes at once
|
||||
*
|
||||
* Returns JSON encoded classes, using {@link encodeClass()}.
|
||||
*
|
||||
* @param array $classNames
|
||||
* @param string $package
|
||||
* @return string
|
||||
*/
|
||||
public static function encodeClasses(array $classNames, $package = '')
|
||||
{
|
||||
$result = '';
|
||||
foreach ($classNames as $className) {
|
||||
$result .= self::encodeClass($className, $package);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Zend_Exception
|
||||
*/
|
||||
require_once 'include/Zend/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend_Json
|
||||
* @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_Json_Exception extends Zend_Exception
|
||||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
* Unit tests
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
CharStreamConst::$EOF = -1;
|
||||
|
||||
class ANTLRStringStream implements CharStream {
|
||||
|
||||
/** Copy data in string to a local char array */
|
||||
public function __construct($input) {
|
||||
$this->p=0;
|
||||
$this->line = 1;
|
||||
$this->charPositionInLine = 0;
|
||||
$this->markDepth = 0;
|
||||
$this->markers = null;
|
||||
$this->lastMarker=0;
|
||||
$this->name=null;
|
||||
|
||||
$this->data = strToIntArray($input);
|
||||
$this->n = strlen($input);
|
||||
}
|
||||
|
||||
/** Reset the stream so that it's in the same state it was
|
||||
* when the object was created *except* the data array is not
|
||||
* touched.
|
||||
*/
|
||||
public function reset() {
|
||||
$this->p = 0;
|
||||
$this->line = 1;
|
||||
$this->charPositionInLine = 0;
|
||||
$this->markDepth = 0;
|
||||
}
|
||||
|
||||
public function consume() {
|
||||
if ( $this->p < $this->n ) {
|
||||
$this->charPositionInLine++;
|
||||
if ( $this->data[$this->p]==ord("\n") ) {
|
||||
$this->line++;
|
||||
$this->charPositionInLine=0;
|
||||
}
|
||||
$this->p++;
|
||||
}
|
||||
}
|
||||
|
||||
public function LA($i) {
|
||||
if ( $i==0 ) {
|
||||
return 0; // undefined
|
||||
}
|
||||
if ( $i<0 ) {
|
||||
$i++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1]
|
||||
if ( ($this->p+$i-1) < 0 ) {
|
||||
return CharStreamConst::$EOF; // invalid; no char before first char
|
||||
}
|
||||
}
|
||||
|
||||
if ( ($this->p+$i-1) >= $this->n ) {
|
||||
//System.out.println("char LA("+i+")=EOF; p="+p);
|
||||
return CharStreamConst::$EOF;
|
||||
}
|
||||
//System.out.println("char LA("+i+")="+(char)data[p+i-1]+"; p="+p);
|
||||
//System.out.println("LA("+i+"); p="+p+" n="+n+" data.length="+data.length);
|
||||
return $this->data[$this->p+$i-1];
|
||||
}
|
||||
|
||||
public function LT($i) {
|
||||
return $this->LA($i);
|
||||
}
|
||||
|
||||
/** Return the current input symbol index 0..n where n indicates the
|
||||
* last symbol has been read. The index is the index of char to
|
||||
* be returned from LA(1).
|
||||
*/
|
||||
public function index() {
|
||||
return $this->p;
|
||||
}
|
||||
|
||||
public function size() {
|
||||
return $this->n;
|
||||
}
|
||||
|
||||
public function mark() {
|
||||
if ( $this->markers == null) {
|
||||
$this->markers = array();
|
||||
$this->markers[] = null; // depth 0 means no backtracking, leave blank
|
||||
}
|
||||
$this->markDepth++;
|
||||
$state = null;
|
||||
if ($this->markDepth>=sizeof($this->markers)) {
|
||||
$state = new CharStreamState();
|
||||
$this->markers[] = $state;
|
||||
}
|
||||
else {
|
||||
$state = $this->markers[$this->markDepth];
|
||||
}
|
||||
$state->p = $this->p;
|
||||
$state->line = $this->line;
|
||||
$state->charPositionInLine = $this->charPositionInLine;
|
||||
$this->lastMarker = $this->markDepth;
|
||||
return $this->markDepth;
|
||||
}
|
||||
|
||||
public function rewind($m=null) {
|
||||
if($m===null){
|
||||
$this->rewind((int)$this->lastMarker);
|
||||
}else{
|
||||
$state = $this->markers[$m];
|
||||
// restore stream state
|
||||
$this->seek($state->p);
|
||||
$this->line = $state->line;
|
||||
$this->charPositionInLine = $state->charPositionInLine;
|
||||
$this->release($m);
|
||||
}
|
||||
}
|
||||
|
||||
public function release($marker) {
|
||||
// unwind any other markers made after m and release m
|
||||
$this->markDepth = $marker;
|
||||
// release this marker
|
||||
$this->markDepth--;
|
||||
}
|
||||
|
||||
/** consume() ahead until p==index; can't just set p=index as we must
|
||||
* update line and charPositionInLine.
|
||||
*/
|
||||
public function seek($index) {
|
||||
if ( $index<=$this->p ) {
|
||||
$this->p = $index; // just jump; don't update stream state (line, ...)
|
||||
return;
|
||||
}
|
||||
// seek forward, consume until p hits index
|
||||
while ( $this->p<$index ) {
|
||||
$this->consume();
|
||||
}
|
||||
}
|
||||
|
||||
public function substring($start, $stop) {
|
||||
return implode(array_map('chr', array_slice($this->data, $start, $stop-$start+1)));
|
||||
}
|
||||
|
||||
public function getLine() {
|
||||
return $this->line;
|
||||
}
|
||||
|
||||
public function getCharPositionInLine() {
|
||||
return $this->charPositionInLine;
|
||||
}
|
||||
|
||||
public function setLine($line) {
|
||||
$this->line = $line;
|
||||
}
|
||||
|
||||
public function setCharPositionInLine($pos) {
|
||||
$this->charPositionInLine = $pos;
|
||||
}
|
||||
|
||||
public function getSourceName() {
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,299 @@
|
|||
<?php
|
||||
/**
|
||||
* Base class for lexers
|
||||
*/
|
||||
abstract class AntlrLexer extends BaseRecognizer{
|
||||
public static $DEFAULT_TOKEN_CHANNEL = 0;
|
||||
protected $input;
|
||||
|
||||
public function __construct($input, $state=null) {
|
||||
if($state==null){
|
||||
$state = new RecognizerSharedState();
|
||||
}
|
||||
$this->state = $state;
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
public function reset() {
|
||||
parent::reset(); // reset all recognizer state variables
|
||||
// wack Lexer state variables
|
||||
if ( $this->input!=null ) {
|
||||
$this->input->seek(0); // rewind the input
|
||||
}
|
||||
if ( $this->state==null ) {
|
||||
return; // no shared state work to do
|
||||
}
|
||||
$this->state->token = null;
|
||||
$this->state->type = TokenConst::$INVALID_TOKEN_TYPE;
|
||||
$this->state->channel = TokenConst::$DEFAULT_CHANNEL;
|
||||
$this->state->tokenStartCharIndex = -1;
|
||||
$this->state->tokenStartCharPositionInLine = -1;
|
||||
$this->state->tokenStartLine = -1;
|
||||
$this->state->text = null;
|
||||
}
|
||||
|
||||
|
||||
/** Return a token from this source; i.e., match a token on the char
|
||||
* stream.
|
||||
*/
|
||||
public function nextToken() {
|
||||
while (true) {
|
||||
$this->state->token = null;
|
||||
$this->state->channel = 0;//Token::DEFAULT_CHANNEL;
|
||||
$this->state->tokenStartCharIndex = $this->input->index();
|
||||
$this->state->tokenStartCharPositionInLine = $this->input->getCharPositionInLine();
|
||||
$this->state->tokenStartLine = $this->input->getLine();
|
||||
$this->state->text = null;
|
||||
if ( $this->input->LA(1)==CharStreamConst::$EOF ) {
|
||||
return TokenConst::$EOF_TOKEN;
|
||||
}
|
||||
try {
|
||||
$this->mTokens();
|
||||
if ( $this->state->token==null ) {
|
||||
$this->emit();
|
||||
}
|
||||
else if ( $this->state->token==Token::$SKIP_TOKEN ) {
|
||||
continue;
|
||||
}
|
||||
return $this->state->token;
|
||||
}
|
||||
catch (NoViableAltException $nva) {
|
||||
$this->reportError($nva);
|
||||
$this->recover($nva); // throw out current char and try again
|
||||
}
|
||||
catch (RecognitionException $re) {
|
||||
$this->reportError($re);
|
||||
// match() routine has already called recover()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Instruct the lexer to skip creating a token for current lexer rule
|
||||
* and look for another token. nextToken() knows to keep looking when
|
||||
* a lexer rule finishes with token set to SKIP_TOKEN. Recall that
|
||||
* if token==null at end of any token rule, it creates one for you
|
||||
* and emits it.
|
||||
*/
|
||||
public function skip() {
|
||||
$this->state->token = TokenConst::$SKIP_TOKEN;
|
||||
}
|
||||
|
||||
/** This is the lexer entry point that sets instance var 'token' */
|
||||
public abstract function mTokens();
|
||||
|
||||
/** Set the char stream and reset the lexer */
|
||||
public function setCharStream($input) {
|
||||
$this->input = null;
|
||||
$this->reset();
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
public function getCharStream() {
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
public function getSourceName() {
|
||||
return $this->input->getSourceName();
|
||||
}
|
||||
|
||||
/** Currently does not support multiple emits per nextToken invocation
|
||||
* for efficiency reasons. Subclass and override this method and
|
||||
* nextToken (to push tokens into a list and pull from that list rather
|
||||
* than a single variable as this implementation does).
|
||||
*/
|
||||
/** The standard method called to automatically emit a token at the
|
||||
* outermost lexical rule. The token object should point into the
|
||||
* char buffer start..stop. If there is a text override in 'text',
|
||||
* use that to set the token's text. Override this method to emit
|
||||
* custom Token objects.
|
||||
*
|
||||
* If you are building trees, then you should also override
|
||||
* Parser or TreeParser.getMissingSymbol().
|
||||
*/
|
||||
public function emit($token=null) {
|
||||
if($token==null){
|
||||
$token = CommonToken::forInput($this->input, $this->state->type, $this->state->channel,
|
||||
$this->state->tokenStartCharIndex, $this->getCharIndex()-1);
|
||||
$token->setLine($this->state->tokenStartLine);
|
||||
$token->setText($this->state->text);
|
||||
$token->setCharPositionInLine($this->state->tokenStartCharPositionInLine);
|
||||
}
|
||||
$this->state->token = $token;
|
||||
return $token;
|
||||
}
|
||||
|
||||
function matchString($s){
|
||||
$i = 0;
|
||||
while ( $i<strlen($s)) {
|
||||
if ( $this->input->LA(1)!=charAt($s, $i) ) {
|
||||
if ( $this->state->backtracking>0 ) {
|
||||
$this->state->failed = true;
|
||||
return;
|
||||
}
|
||||
$mte = new MismatchedTokenException(charAt($s, $i), $this->input);
|
||||
$this->recover($mte);
|
||||
throw $mte;
|
||||
}
|
||||
$i++;
|
||||
$this->input->consume();
|
||||
$state->failed = false;
|
||||
}
|
||||
}
|
||||
|
||||
public function matchAny() {
|
||||
$this->input->consume();
|
||||
}
|
||||
|
||||
public function matchChar($c) {
|
||||
if ($this->input->LA(1)!=$c ) {
|
||||
if ( $this->state->backtracking>0 ) {
|
||||
$this->state->failed = true;
|
||||
return;
|
||||
}
|
||||
$mte = new MismatchedTokenException($c, $this->input);
|
||||
$this->recover($mte); // don't really recover; just consume in lexer
|
||||
throw $mte;
|
||||
}
|
||||
$this->input->consume();
|
||||
$this->state->failed = false;
|
||||
}
|
||||
|
||||
public function matchRange($a, $b) {
|
||||
if ( $this->input->LA(1)<$a || $this->input->LA(1)>$b ) {
|
||||
if ( $this->state->backtracking>0 ) {
|
||||
$this->state->failed = true;
|
||||
return;
|
||||
}
|
||||
$mre = new MismatchedRangeException($a, $b, $this->input);
|
||||
$this->recover($mre);
|
||||
throw $mre;
|
||||
}
|
||||
$this->input->consume();
|
||||
$this->state->failed = false;
|
||||
}
|
||||
|
||||
public function getLine() {
|
||||
return $this->input->getLine();
|
||||
}
|
||||
|
||||
public function getCharPositionInLine() {
|
||||
return $this->input->getCharPositionInLine();
|
||||
}
|
||||
|
||||
/** What is the index of the current character of lookahead? */
|
||||
public function getCharIndex() {
|
||||
return $this->input->index();
|
||||
}
|
||||
|
||||
|
||||
/** Return the text matched so far for the current token or any
|
||||
* text override.
|
||||
*/
|
||||
public function getText() {
|
||||
if ( $this->state->text!=null ) {
|
||||
return $this->state->text;
|
||||
}
|
||||
return $this->input->substring($this->state->tokenStartCharIndex,$this->getCharIndex()-1);
|
||||
}
|
||||
|
||||
/** Set the complete text of this token; it wipes any previous
|
||||
* changes to the text.
|
||||
*/
|
||||
public function setText($text) {
|
||||
$this->state->text = $text;
|
||||
}
|
||||
|
||||
public function reportError($e) {
|
||||
/** TODO: not thought about recovery in lexer yet.
|
||||
*
|
||||
// if we've already reported an error and have not matched a token
|
||||
// yet successfully, don't report any errors.
|
||||
if ( errorRecovery ) {
|
||||
//System.err.print("[SPURIOUS] ");
|
||||
return;
|
||||
}
|
||||
errorRecovery = true;
|
||||
*/
|
||||
|
||||
$this->displayRecognitionError($this->getTokenNames(), $e);
|
||||
}
|
||||
|
||||
public function getErrorMessage($e, $tokenNames) {
|
||||
$msg = null;
|
||||
if ( $e instanceof MismatchedTokenException ) {
|
||||
$mte = $e;
|
||||
$msg = "mismatched character ".$this->getCharErrorDisplay($e->c).
|
||||
" expecting ".$this->getCharErrorDisplay($mte->expecting);
|
||||
}
|
||||
else if ( $e instanceof NoViableAltException ) {
|
||||
$nvae = $e;
|
||||
// for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
|
||||
// and "(decision="+nvae.decisionNumber+") and
|
||||
// "state "+nvae.stateNumber
|
||||
$msg = "no viable alternative at character ".$this->getCharErrorDisplay($e->c);
|
||||
}
|
||||
else if ( $e instanceof EarlyExitException ) {
|
||||
$eee = $e;
|
||||
// for development, can add "(decision="+eee.decisionNumber+")"
|
||||
$msg = "required (...)+ loop did not match anything at character ".$this->getCharErrorDisplay($e->c);
|
||||
}
|
||||
else if ( $e instanceof MismatchedNotSetException ) {
|
||||
$mse = $e;
|
||||
$msg = "mismatched character ".$this->getCharErrorDisplay($e->c)." expecting set ".$mse->expecting;
|
||||
}
|
||||
else if ( $e instanceof MismatchedSetException ) {
|
||||
$mse = $e;
|
||||
$msg = "mismatched character ".$this->getCharErrorDisplay($e->c)." expecting set ".$mse->expecting;
|
||||
}
|
||||
else if ( $e instanceof MismatchedRangeException ) {
|
||||
$mre = $e;
|
||||
$msg = "mismatched character ".$this->getCharErrorDisplay($e->c)." expecting set ".
|
||||
$this->getCharErrorDisplay($mre->a)."..".$this->getCharErrorDisplay($mre->b);
|
||||
}
|
||||
else {
|
||||
$msg = parent::getErrorMessage($e, $tokenNames);
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
public function getCharErrorDisplay($c) {
|
||||
$s = chr($c);
|
||||
switch ( $s ) {
|
||||
case '\n' :
|
||||
$s = "\\n";
|
||||
break;
|
||||
case '\t' :
|
||||
$s = "\\t";
|
||||
break;
|
||||
case '\r' :
|
||||
$s = "\\r";
|
||||
break;
|
||||
}
|
||||
if ($c==TokenConst::$EOF){
|
||||
$s = "<EOF>";
|
||||
}
|
||||
return "'".$s."'";
|
||||
}
|
||||
|
||||
/** Lexers can normally match any char in it's vocabulary after matching
|
||||
* a token, so do the easy thing and just kill a character and hope
|
||||
* it all works out. You can instead use the rule invocation stack
|
||||
* to do sophisticated error recovery if you are in a fragment rule.
|
||||
*/
|
||||
public function recover($re) {
|
||||
$this->input->consume();
|
||||
}
|
||||
|
||||
|
||||
public function traceIn($ruleName, $ruleIndex) {
|
||||
$inputSymbol = $this->input->LT(1)." line=".$this->getLine().":".$this->getCharPositionInLine();
|
||||
parent::traceIn($ruleName, $ruleIndex, $inputSymbol);
|
||||
}
|
||||
|
||||
public function traceOut($ruleName, $ruleIndex) {
|
||||
$inputSymbol = $this->input->LT(1)." line=".$this->getLine().":".$this->getCharPositionInLine();
|
||||
parent::traceOut($ruleName, $ruleIndex, $inputSymbol);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** A parser for TokenStreams. "parser grammars" result in a subclass
|
||||
* of this.
|
||||
*/
|
||||
class AntlrParser extends BaseRecognizer {
|
||||
public $input;
|
||||
|
||||
|
||||
public function __construct($input, $state = null) {
|
||||
parent::__construct($state); // share the state object with another parser
|
||||
$this->setTokenStream($input);
|
||||
}
|
||||
|
||||
public function reset() {
|
||||
parent::reset(); // reset all recognizer state variables
|
||||
if ( $this->input!=null ) {
|
||||
$this->input->seek(0); // rewind the input
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCurrentInputSymbol($input) {
|
||||
return $this->input->LT(1);
|
||||
}
|
||||
|
||||
protected function getMissingSymbol($input, $e, $expectedTokenType, $follow)
|
||||
{
|
||||
$tokenText = null;
|
||||
if ( $expectedTokenType==TokenConst::$EOF ){
|
||||
$tokenText = "<missing EOF>";
|
||||
} else {
|
||||
$tokenNames = $this->getTokenNames();
|
||||
$tokenText = "<missing ".$tokenNames[$expectedTokenType].">";
|
||||
}
|
||||
$t = CommonToken::forTypeAndText($expectedTokenType, $tokenText);
|
||||
$current = $input->LT(1);
|
||||
if ( $current->getType() == TokenConst::$EOF ) {
|
||||
$current = $this->input->LT(-1);
|
||||
}
|
||||
$t->line = $current->getLine();
|
||||
$t->charPositionInLine = $current->getCharPositionInLine();
|
||||
$t->channel = $DEFAULT_TOKEN_CHANNEL;
|
||||
return $t;
|
||||
}
|
||||
|
||||
/** Set the token stream and reset the parser */
|
||||
public function setTokenStream($input) {
|
||||
$this->input = null;
|
||||
$this->reset();
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
public function getTokenStream() {
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
public function getSourceName() {
|
||||
return $this->input->getSourceName();
|
||||
}
|
||||
|
||||
public function traceIn($ruleName, $ruleIndex) {
|
||||
parent::traceIn($ruleName, $ruleIndex, $this->input->LT(1));
|
||||
}
|
||||
|
||||
public function traceOut($ruleName, $ruleIndex) {
|
||||
parent::traceOut($ruleName, $ruleIndex, $this->input->LT(1));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,851 @@
|
|||
<?php
|
||||
|
||||
abstract class BaseRecognizer{
|
||||
|
||||
public static $MEMO_RULE_FAILED = -2;
|
||||
public static $MEMO_RULE_UNKNOWN = -1;
|
||||
public static $INITIAL_FOLLOW_STACK_SIZE = 100;
|
||||
|
||||
// copies from Token object for convenience in actions
|
||||
public static $DEFAULT_TOKEN_CHANNEL; //= TokenConst::$DEFAULT_CHANNEL;
|
||||
public static $HIDDEN; //= TokenConst::$HIDDEN_CHANNEL;
|
||||
|
||||
public static $NEXT_TOKEN_RULE_NAME = "nextToken";
|
||||
|
||||
public function __construct($state = null) {
|
||||
if ( $state==null ) {
|
||||
$state = new RecognizerSharedState();
|
||||
}
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
/** reset the parser's state; subclasses must rewinds the input stream */
|
||||
public function reset() {
|
||||
// wack everything related to error recovery
|
||||
if ( $this->state==null ) {
|
||||
return; // no shared state work to do
|
||||
}
|
||||
$this->state->_fsp = -1;
|
||||
$this->state->errorRecovery = false;
|
||||
$this->state->lastErrorIndex = -1;
|
||||
$this->state->failed = false;
|
||||
$this->state->syntaxErrors = 0;
|
||||
// wack everything related to backtracking and memoization
|
||||
$this->state->backtracking = 0;
|
||||
for ($i = 0; $this->state->ruleMemo!=null && $i < $this->state->ruleMemo->length; $i++) { // wipe cache
|
||||
$this->state->ruleMemo[$i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Match current input symbol against ttype. Attempt
|
||||
* single token insertion or deletion error recovery. If
|
||||
* that fails, throw MismatchedTokenException.
|
||||
*
|
||||
* To turn off single token insertion or deletion error
|
||||
* recovery, override mismatchRecover() and have it call
|
||||
* plain mismatch(), which does not recover. Then any error
|
||||
* in a rule will cause an exception and immediate exit from
|
||||
* rule. Rule would recover by resynchronizing to the set of
|
||||
* symbols that can follow rule ref.
|
||||
*/
|
||||
public function match($input, $ttype, $follow)
|
||||
{
|
||||
//System.out.println("match "+((TokenStream)input).LT(1));
|
||||
$matchedSymbol = $this->getCurrentInputSymbol($input);
|
||||
if ( $input->LA(1)==$ttype ) {
|
||||
$input->consume();
|
||||
$this->state->errorRecovery = false;
|
||||
$this->state->failed = false;
|
||||
return $matchedSymbol;
|
||||
}
|
||||
if ( $this->state->backtracking>0 ) {
|
||||
$this->state->failed = true;
|
||||
return $matchedSymbol;
|
||||
}
|
||||
$matchedSymbol = $this->recoverFromMismatchedToken($input, $ttype, $follow);
|
||||
return $matchedSymbol;
|
||||
}
|
||||
|
||||
/** Match the wildcard: in a symbol */
|
||||
public function matchAny($input) {
|
||||
$this->state->errorRecovery = false;
|
||||
$this->state->failed = false;
|
||||
$input->consume();
|
||||
}
|
||||
|
||||
public function mismatchIsUnwantedToken($input, $ttype) {
|
||||
return $input->LA(2)==$ttype;
|
||||
}
|
||||
|
||||
public function mismatchIsMissingToken($input, $follow) {
|
||||
if ( $follow==null ) {
|
||||
// we have no information about the follow; we can only consume
|
||||
// a single token and hope for the best
|
||||
return $false;
|
||||
}
|
||||
// compute what can follow this grammar element reference
|
||||
if ( $follow->member(TokenConst::$EOR_TOKEN_TYPE) ) {
|
||||
$viableTokensFollowingThisRule = $this->computeContextSensitiveRuleFOLLOW();
|
||||
$follow = $follow->union($viableTokensFollowingThisRule);
|
||||
if ( $this->state->_fsp>=0 ) { // remove EOR if we're not the start symbol
|
||||
$follow->remove(TokenConst::$EOR_TOKEN_TYPE);
|
||||
}
|
||||
}
|
||||
// if current token is consistent with what could come after set
|
||||
// then we know we're missing a token; error recovery is free to
|
||||
// "insert" the missing token
|
||||
|
||||
//System.out.println("viable tokens="+follow.toString(getTokenNames()));
|
||||
//System.out.println("LT(1)="+((TokenStream)input).LT(1));
|
||||
|
||||
// BitSet cannot handle negative numbers like -1 (EOF) so I leave EOR
|
||||
// in follow set to indicate that the fall of the start symbol is
|
||||
// in the set (EOF can follow).
|
||||
if ( $follow->member($input->LA(1)) || $follow->member(TokenConst::$EOR_TOKEN_TYPE) ) {
|
||||
//System.out.println("LT(1)=="+((TokenStream)input).LT(1)+" is consistent with what follows; inserting...");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Factor out what to do upon token mismatch so tree parsers can behave
|
||||
* differently. Override and call mismatchRecover(input, ttype, follow)
|
||||
* to get single token insertion and deletion. Use this to turn of
|
||||
* single token insertion and deletion. Override mismatchRecover
|
||||
* to call this instead.
|
||||
*/
|
||||
protected function mismatch($input, $ttype, $follow)
|
||||
{
|
||||
if ( $this->mismatchIsUnwantedToken($input, $ttype) ) {
|
||||
throw new UnwantedTokenException($ttype, $input);
|
||||
}
|
||||
else if ( $this->mismatchIsMissingToken($input, $follow) ) {
|
||||
throw new MissingTokenException($ttype, $input, null);
|
||||
}
|
||||
throw new MismatchedTokenException($ttype, $input);
|
||||
}
|
||||
|
||||
/** Report a recognition problem.
|
||||
*
|
||||
* This method sets errorRecovery to indicate the parser is recovering
|
||||
* not parsing. Once in recovery mode, no errors are generated.
|
||||
* To get out of recovery mode, the parser must successfully match
|
||||
* a token (after a resync). So it will go:
|
||||
*
|
||||
* 1. error occurs
|
||||
* 2. enter recovery mode, report error
|
||||
* 3. consume until token found in resynch set
|
||||
* 4. try to resume parsing
|
||||
* 5. next match() will reset errorRecovery mode
|
||||
*
|
||||
* If you override, make sure to update syntaxErrors if you care about that.
|
||||
*/
|
||||
public function reportError($e) {
|
||||
// if we've already reported an error and have not matched a token
|
||||
// yet successfully, don't report any errors.
|
||||
if ( $this->state->errorRecovery ) {
|
||||
//System.err.print("[SPURIOUS] ");
|
||||
return;
|
||||
}
|
||||
$this->state->syntaxErrors++; // don't count spurious
|
||||
$this->state->errorRecovery = true;
|
||||
|
||||
$this->displayRecognitionError($this->getTokenNames(), $e);
|
||||
}
|
||||
|
||||
|
||||
public function displayRecognitionError($tokenNames, $e){
|
||||
$hdr = $this->getErrorHeader($e);
|
||||
$msg = $this->getErrorMessage($e, $tokenNames);
|
||||
$this->emitErrorMessage($hdr." ".$msg);
|
||||
}
|
||||
|
||||
/** What error message should be generated for the various
|
||||
* exception types?
|
||||
*
|
||||
* Not very object-oriented code, but I like having all error message
|
||||
* generation within one method rather than spread among all of the
|
||||
* exception classes. This also makes it much easier for the exception
|
||||
* handling because the exception classes do not have to have pointers back
|
||||
* to this object to access utility routines and so on. Also, changing
|
||||
* the message for an exception type would be difficult because you
|
||||
* would have to subclassing exception, but then somehow get ANTLR
|
||||
* to make those kinds of exception objects instead of the default.
|
||||
* This looks weird, but trust me--it makes the most sense in terms
|
||||
* of flexibility.
|
||||
*
|
||||
* For grammar debugging, you will want to override this to add
|
||||
* more information such as the stack frame with
|
||||
* getRuleInvocationStack(e, this.getClass().getName()) and,
|
||||
* for no viable alts, the decision description and state etc...
|
||||
*
|
||||
* Override this to change the message generated for one or more
|
||||
* exception types.
|
||||
*/
|
||||
public function getErrorMessage($e, $tokenNames) {
|
||||
$msg = $e->getMessage();
|
||||
if ( $e instanceof UnwantedTokenException ) {
|
||||
$ute = $e;
|
||||
$tokenName="<unknown>";
|
||||
if ( $ute->expecting== TokenConst::$EOF ) {
|
||||
$tokenName = "EOF";
|
||||
}
|
||||
else {
|
||||
$tokenName = $tokenNames[$ute->expecting];
|
||||
}
|
||||
$msg = "extraneous input ".$this->getTokenErrorDisplay($ute->getUnexpectedToken()).
|
||||
" expecting ".$tokenName;
|
||||
}
|
||||
else if ( $e instanceof MissingTokenException ) {
|
||||
$mte = $e;
|
||||
$tokenName="<unknown>";
|
||||
if ( $mte->expecting== TokenConst::$EOF ) {
|
||||
$tokenName = "EOF";
|
||||
}
|
||||
else {
|
||||
$tokenName = $tokenNames[$mte->expecting];
|
||||
}
|
||||
$msg = "missing ".$tokenName." at ".$this->getTokenErrorDisplay($e->token);
|
||||
}
|
||||
else if ( $e instanceof MismatchedTokenException ) {
|
||||
$mte = $e;
|
||||
$tokenName="<unknown>";
|
||||
if ( $mte->expecting== TokenConst::$EOF ) {
|
||||
$tokenName = "EOF";
|
||||
}
|
||||
else {
|
||||
$tokenName = $tokenNames[$mte->expecting];
|
||||
}
|
||||
$msg = "mismatched input ".$this->getTokenErrorDisplay($e->token).
|
||||
" expecting ".$tokenName;
|
||||
}
|
||||
else if ( $e instanceof MismatchedTreeNodeException ) {
|
||||
$mtne = $e;
|
||||
$tokenName="<unknown>";
|
||||
if ( $mtne->expecting==TokenConst::$EOF ) {
|
||||
$tokenName = "EOF";
|
||||
}
|
||||
else {
|
||||
$tokenName = $tokenNames[$mtne->expecting];
|
||||
}
|
||||
$msg = "mismatched tree node: ".$mtne->node.
|
||||
" expecting ".$tokenName;
|
||||
}
|
||||
else if ( $e instanceof NoViableAltException ) {
|
||||
$nvae = $e;
|
||||
// for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
|
||||
// and "(decision="+nvae.decisionNumber+") and
|
||||
// "state "+nvae.stateNumber
|
||||
$msg = "no viable alternative at input ".$this->getTokenErrorDisplay($e->token);
|
||||
}
|
||||
else if ( $e instanceof EarlyExitException ) {
|
||||
$eee = $e;
|
||||
// for development, can add "(decision="+eee.decisionNumber+")"
|
||||
$msg = "required (...)+ loop did not match anything at input ".
|
||||
getTokenErrorDisplay($e->token);
|
||||
}
|
||||
else if ( $e instanceof MismatchedSetException ) {
|
||||
$mse = $e;
|
||||
$msg = "mismatched input ".$this->getTokenErrorDisplay($e->token).
|
||||
" expecting set ".$mse->expecting;
|
||||
}
|
||||
else if ( $e instanceof MismatchedNotSetException ) {
|
||||
$mse = $e;
|
||||
$msg = "mismatched input ".$this->getTokenErrorDisplay($e->token).
|
||||
" expecting set ".$mse->expecting;
|
||||
}
|
||||
else if ( $e instanceof FailedPredicateException ) {
|
||||
$fpe = $e;
|
||||
$msg = "rule ".$fpe->ruleName." failed predicate: {".
|
||||
$fpe->predicateText."}?";
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/** Get number of recognition errors (lexer, parser, tree parser). Each
|
||||
* recognizer tracks its own number. So parser and lexer each have
|
||||
* separate count. Does not count the spurious errors found between
|
||||
* an error and next valid token match
|
||||
*
|
||||
* See also reportError()
|
||||
*/
|
||||
public function getNumberOfSyntaxErrors() {
|
||||
return $state->syntaxErrors;
|
||||
}
|
||||
|
||||
/** What is the error header, normally line/character position information? */
|
||||
public function getErrorHeader($e) {
|
||||
return "line ".$e->line.":".$e->charPositionInLine;
|
||||
}
|
||||
|
||||
|
||||
/** How should a token be displayed in an error message? The default
|
||||
* is to display just the text, but during development you might
|
||||
* want to have a lot of information spit out. Override in that case
|
||||
* to use t.toString() (which, for CommonToken, dumps everything about
|
||||
* the token). This is better than forcing you to override a method in
|
||||
* your token objects because you don't have to go modify your lexer
|
||||
* so that it creates a new Java type.
|
||||
*/
|
||||
public function getTokenErrorDisplay($t) {
|
||||
$s = $t->getText();
|
||||
if ( $s==null ) {
|
||||
if ( $t->getType()==TokenConst::$EOF ) {
|
||||
$s = "<EOF>";
|
||||
}
|
||||
else {
|
||||
$s = "<".$t->getType().">";
|
||||
}
|
||||
}
|
||||
$s = str_replace("\n", '\n', $s);
|
||||
$s = str_replace("\r",'\r', $s);
|
||||
$s = str_replace("\t",'\t', $s);
|
||||
return "'".$s."'";
|
||||
}
|
||||
|
||||
/** Override this method to change where error messages go */
|
||||
public function emitErrorMessage($msg) {
|
||||
echo $msg;
|
||||
}
|
||||
|
||||
/** Recover from an error found on the input stream. This is
|
||||
* for NoViableAlt and mismatched symbol exceptions. If you enable
|
||||
* single token insertion and deletion, this will usually not
|
||||
* handle mismatched symbol exceptions but there could be a mismatched
|
||||
* token that the match() routine could not recover from.
|
||||
*/
|
||||
public function recover($input, $re) {
|
||||
if ( $this->state->lastErrorIndex==$input->index() ) {
|
||||
// uh oh, another error at same token index; must be a case
|
||||
// where LT(1) is in the recovery token set so nothing is
|
||||
// consumed; consume a single token so at least to prevent
|
||||
// an infinite loop; this is a failsafe.
|
||||
$input->consume();
|
||||
}
|
||||
$this->state->lastErrorIndex = $input->index();
|
||||
$followSet = $this->computeErrorRecoverySet();
|
||||
$this->beginResync();
|
||||
$this->consumeUntilInSet($input, $followSet);
|
||||
$this->endResync();
|
||||
}
|
||||
|
||||
/** A hook to listen in on the token consumption during error recovery.
|
||||
* The DebugParser subclasses this to fire events to the listenter.
|
||||
*/
|
||||
public function beginResync() {
|
||||
}
|
||||
|
||||
public function endResync() {
|
||||
}
|
||||
|
||||
/* Compute the error recovery set for the current rule. During
|
||||
* rule invocation, the parser pushes the set of tokens that can
|
||||
* follow that rule reference on the stack; this amounts to
|
||||
* computing FIRST of what follows the rule reference in the
|
||||
* enclosing rule. This local follow set only includes tokens
|
||||
* from within the rule; i.e., the FIRST computation done by
|
||||
* ANTLR stops at the end of a rule.
|
||||
*
|
||||
* EXAMPLE
|
||||
*
|
||||
* When you find a "no viable alt exception", the input is not
|
||||
* consistent with any of the alternatives for rule r. The best
|
||||
* thing to do is to consume tokens until you see something that
|
||||
* can legally follow a call to r *or* any rule that called r.
|
||||
* You don't want the exact set of viable next tokens because the
|
||||
* input might just be missing a token--you might consume the
|
||||
* rest of the input looking for one of the missing tokens.
|
||||
*
|
||||
* Consider grammar:
|
||||
*
|
||||
* a : '[' b ']'
|
||||
* | '(' b ')'
|
||||
* ;
|
||||
* b : c '^' INT ;
|
||||
* c : ID
|
||||
* | INT
|
||||
* ;
|
||||
*
|
||||
* At each rule invocation, the set of tokens that could follow
|
||||
* that rule is pushed on a stack. Here are the various "local"
|
||||
* follow sets:
|
||||
*
|
||||
* FOLLOW(b1_in_a) = FIRST(']') = ']'
|
||||
* FOLLOW(b2_in_a) = FIRST(')') = ')'
|
||||
* FOLLOW(c_in_b) = FIRST('^') = '^'
|
||||
*
|
||||
* Upon erroneous input "[]", the call chain is
|
||||
*
|
||||
* a -> b -> c
|
||||
*
|
||||
* and, hence, the follow context stack is:
|
||||
*
|
||||
* depth local follow set after call to rule
|
||||
* 0 <EOF> a (from main())
|
||||
* 1 ']' b
|
||||
* 3 '^' c
|
||||
*
|
||||
* Notice that ')' is not included, because b would have to have
|
||||
* been called from a different context in rule a for ')' to be
|
||||
* included.
|
||||
*
|
||||
* For error recovery, we cannot consider FOLLOW(c)
|
||||
* (context-sensitive or otherwise). We need the combined set of
|
||||
* all context-sensitive FOLLOW sets--the set of all tokens that
|
||||
* could follow any reference in the call chain. We need to
|
||||
* resync to one of those tokens. Note that FOLLOW(c)='^' and if
|
||||
* we resync'd to that token, we'd consume until EOF. We need to
|
||||
* sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
|
||||
* In this case, for input "[]", LA(1) is in this set so we would
|
||||
* not consume anything and after printing an error rule c would
|
||||
* return normally. It would not find the required '^' though.
|
||||
* At this point, it gets a mismatched token error and throws an
|
||||
* exception (since LA(1) is not in the viable following token
|
||||
* set). The rule exception handler tries to recover, but finds
|
||||
* the same recovery set and doesn't consume anything. Rule b
|
||||
* exits normally returning to rule a. Now it finds the ']' (and
|
||||
* with the successful match exits errorRecovery mode).
|
||||
*
|
||||
* So, you cna see that the parser walks up call chain looking
|
||||
* for the token that was a member of the recovery set.
|
||||
*
|
||||
* Errors are not generated in errorRecovery mode.
|
||||
*
|
||||
* ANTLR's error recovery mechanism is based upon original ideas:
|
||||
*
|
||||
* "Algorithms + Data Structures = Programs" by Niklaus Wirth
|
||||
*
|
||||
* and
|
||||
*
|
||||
* "A note on error recovery in recursive descent parsers":
|
||||
* http://portal.acm.org/citation.cfm?id=947902.947905
|
||||
*
|
||||
* Later, Josef Grosch had some good ideas:
|
||||
*
|
||||
* "Efficient and Comfortable Error Recovery in Recursive Descent
|
||||
* Parsers":
|
||||
* ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
|
||||
*
|
||||
* Like Grosch I implemented local FOLLOW sets that are combined
|
||||
* at run-time upon error to avoid overhead during parsing.
|
||||
*/
|
||||
protected function computeErrorRecoverySet() {
|
||||
return $this->combineFollows(false);
|
||||
}
|
||||
|
||||
/** Compute the context-sensitive FOLLOW set for current rule.
|
||||
* This is set of token types that can follow a specific rule
|
||||
* reference given a specific call chain. You get the set of
|
||||
* viable tokens that can possibly come next (lookahead depth 1)
|
||||
* given the current call chain. Contrast this with the
|
||||
* definition of plain FOLLOW for rule r:
|
||||
*
|
||||
* FOLLOW(r)={x | S=>*alpha r beta in G and x in FIRST(beta)}
|
||||
*
|
||||
* where x in T* and alpha, beta in V*; T is set of terminals and
|
||||
* V is the set of terminals and nonterminals. In other words,
|
||||
* FOLLOW(r) is the set of all tokens that can possibly follow
|
||||
* references to r in *any* sentential form (context). At
|
||||
* runtime, however, we know precisely which context applies as
|
||||
* we have the call chain. We may compute the exact (rather
|
||||
* than covering superset) set of following tokens.
|
||||
*
|
||||
* For example, consider grammar:
|
||||
*
|
||||
* stat : ID '=' expr ';' // FOLLOW(stat)=={EOF}
|
||||
* | "return" expr '.'
|
||||
* ;
|
||||
* expr : atom ('+' atom)* ; // FOLLOW(expr)=={';','.',')'}
|
||||
* atom : INT // FOLLOW(atom)=={'+',')',';','.'}
|
||||
* | '(' expr ')'
|
||||
* ;
|
||||
*
|
||||
* The FOLLOW sets are all inclusive whereas context-sensitive
|
||||
* FOLLOW sets are precisely what could follow a rule reference.
|
||||
* For input input "i=(3);", here is the derivation:
|
||||
*
|
||||
* stat => ID '=' expr ';'
|
||||
* => ID '=' atom ('+' atom)* ';'
|
||||
* => ID '=' '(' expr ')' ('+' atom)* ';'
|
||||
* => ID '=' '(' atom ')' ('+' atom)* ';'
|
||||
* => ID '=' '(' INT ')' ('+' atom)* ';'
|
||||
* => ID '=' '(' INT ')' ';'
|
||||
*
|
||||
* At the "3" token, you'd have a call chain of
|
||||
*
|
||||
* stat -> expr -> atom -> expr -> atom
|
||||
*
|
||||
* What can follow that specific nested ref to atom? Exactly ')'
|
||||
* as you can see by looking at the derivation of this specific
|
||||
* input. Contrast this with the FOLLOW(atom)={'+',')',';','.'}.
|
||||
*
|
||||
* You want the exact viable token set when recovering from a
|
||||
* token mismatch. Upon token mismatch, if LA(1) is member of
|
||||
* the viable next token set, then you know there is most likely
|
||||
* a missing token in the input stream. "Insert" one by just not
|
||||
* throwing an exception.
|
||||
*/
|
||||
protected function computeContextSensitiveRuleFOLLOW() {
|
||||
return $this->combineFollows(true);
|
||||
}
|
||||
|
||||
protected function combineFollows($exact) {
|
||||
$top = $this->state->_fsp;
|
||||
$followSet = new Set(array());
|
||||
for ($i=$top; $i>=0; $i--) {
|
||||
$localFollowSet = $this->state->following[$i];
|
||||
/*
|
||||
System.out.println("local follow depth "+i+"="+
|
||||
localFollowSet.toString(getTokenNames())+")");
|
||||
*/
|
||||
$followSet->unionInPlace($localFollowSet);
|
||||
if ( $this->exact ) {
|
||||
// can we see end of rule?
|
||||
if ( $localFollowSet->member(TokenConst::$EOR_TOKEN_TYPE) ) {
|
||||
// Only leave EOR in set if at top (start rule); this lets
|
||||
// us know if have to include follow(start rule); i.e., EOF
|
||||
if ( $i>0 ) {
|
||||
$followSet->remove(TokenConst::$EOR_TOKEN_TYPE);
|
||||
}
|
||||
}
|
||||
else { // can't see end of rule, quit
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $followSet;
|
||||
}
|
||||
|
||||
/** Attempt to recover from a single missing or extra token.
|
||||
*
|
||||
* EXTRA TOKEN
|
||||
*
|
||||
* LA(1) is not what we are looking for. If LA(2) has the right token,
|
||||
* however, then assume LA(1) is some extra spurious token. Delete it
|
||||
* and LA(2) as if we were doing a normal match(), which advances the
|
||||
* input.
|
||||
*
|
||||
* MISSING TOKEN
|
||||
*
|
||||
* If current token is consistent with what could come after
|
||||
* ttype then it is ok to "insert" the missing token, else throw
|
||||
* exception For example, Input "i=(3;" is clearly missing the
|
||||
* ')'. When the parser returns from the nested call to expr, it
|
||||
* will have call chain:
|
||||
*
|
||||
* stat -> expr -> atom
|
||||
*
|
||||
* and it will be trying to match the ')' at this point in the
|
||||
* derivation:
|
||||
*
|
||||
* => ID '=' '(' INT ')' ('+' atom)* ';'
|
||||
* ^
|
||||
* match() will see that ';' doesn't match ')' and report a
|
||||
* mismatched token error. To recover, it sees that LA(1)==';'
|
||||
* is in the set of tokens that can follow the ')' token
|
||||
* reference in rule atom. It can assume that you forgot the ')'.
|
||||
*/
|
||||
protected function recoverFromMismatchedToken($input, $ttype, $follow)
|
||||
{
|
||||
$e = null;
|
||||
// if next token is what we are looking for then "delete" this token
|
||||
|
||||
if ( $this->mismatchIsUnwantedToken($input, $ttype) ) {
|
||||
$e = new UnwantedTokenException($ttype, $input);
|
||||
/*
|
||||
System.err.println("recoverFromMismatchedToken deleting "+
|
||||
((TokenStream)input).LT(1)+
|
||||
" since "+((TokenStream)input).LT(2)+" is what we want");
|
||||
*/
|
||||
$this->beginResync();
|
||||
$input->consume(); // simply delete extra token
|
||||
$this->endResync();
|
||||
$this->reportError($e); // report after consuming so AW sees the token in the exception
|
||||
// we want to return the token we're actually matching
|
||||
$matchedSymbol = $this->getCurrentInputSymbol($input);
|
||||
$input->consume(); // move past ttype token as if all were ok
|
||||
return $matchedSymbol;
|
||||
}
|
||||
// can't recover with single token deletion, try insertion
|
||||
if ( $this->mismatchIsMissingToken($input, $follow) ) {
|
||||
$inserted = $this->getMissingSymbol($input, $e, $ttype, $follow);
|
||||
$e = new MissingTokenException($ttype, $input, $inserted);
|
||||
$this->reportError($e); // report after inserting so AW sees the token in the exception
|
||||
return $inserted;
|
||||
}
|
||||
// even that didn't work; must throw the exception
|
||||
$e = new MismatchedTokenException($ttype, $input);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/** Not currently used */
|
||||
public function recoverFromMismatchedSet($input, $e, $follow) {
|
||||
if ( $this->mismatchIsMissingToken($input, $follow) ) {
|
||||
// System.out.println("missing token");
|
||||
reportError($e);
|
||||
// we don't know how to conjure up a token for sets yet
|
||||
return $this->getMissingSymbol($input, $e, TokenConst::$INVALID_TOKEN_TYPE, $follow);
|
||||
}
|
||||
// TODO do single token deletion like above for Token mismatch
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/** Match needs to return the current input symbol, which gets put
|
||||
* into the label for the associated token ref; e.g., x=ID. Token
|
||||
* and tree parsers need to return different objects. Rather than test
|
||||
* for input stream type or change the IntStream interface, I use
|
||||
* a simple method to ask the recognizer to tell me what the current
|
||||
* input symbol is.
|
||||
*
|
||||
* This is ignored for lexers.
|
||||
*/
|
||||
protected function getCurrentInputSymbol($input) { return null; }
|
||||
|
||||
/** Conjure up a missing token during error recovery.
|
||||
*
|
||||
* The recognizer attempts to recover from single missing
|
||||
* symbols. But, actions might refer to that missing symbol.
|
||||
* For example, x=ID {f($x);}. The action clearly assumes
|
||||
* that there has been an identifier matched previously and that
|
||||
* $x points at that token. If that token is missing, but
|
||||
* the next token in the stream is what we want we assume that
|
||||
* this token is missing and we keep going. Because we
|
||||
* have to return some token to replace the missing token,
|
||||
* we have to conjure one up. This method gives the user control
|
||||
* over the tokens returned for missing tokens. Mostly,
|
||||
* you will want to create something special for identifier
|
||||
* tokens. For literals such as '{' and ',', the default
|
||||
* action in the parser or tree parser works. It simply creates
|
||||
* a CommonToken of the appropriate type. The text will be the token.
|
||||
* If you change what tokens must be created by the lexer,
|
||||
* override this method to create the appropriate tokens.
|
||||
*/
|
||||
protected function getMissingSymbol($input, $e, $expectedTokenType, $follow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function consumeUntilMatchesType($input, $tokenType) {
|
||||
//System.out.println("consumeUntil "+tokenType);
|
||||
$ttype = $input->LA(1);
|
||||
while ($ttype != TokenConst::$EOF && $ttype != $tokenType) {
|
||||
$input->consume();
|
||||
$ttype = $input->LA(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Consume tokens until one matches the given token set */
|
||||
public function consumeUntilInSet($input, $set) {
|
||||
//System.out.println("consumeUntil("+set.toString(getTokenNames())+")");
|
||||
$ttype = $input->LA(1);
|
||||
while ($ttype != TokenConst::$EOF && !$set->member($ttype) ) {
|
||||
//System.out.println("consume during recover LA(1)="+getTokenNames()[input.LA(1)]);
|
||||
$input->consume();
|
||||
$ttype = $input->LA(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Push a rule's follow set using our own hardcoded stack */
|
||||
protected function pushFollow($fset) {
|
||||
// if ( ($this->state->_fsp +1)>=sizeof($this->state->following) ) {
|
||||
// $f = array();
|
||||
// System.arraycopy(state.following, 0, f, 0, state.following.length-1);
|
||||
// $this->state->following = f;
|
||||
// }
|
||||
$this->state->following[++$this->state->_fsp] = $fset;
|
||||
}
|
||||
|
||||
/** Return List<String> of the rules in your parser instance
|
||||
* leading up to a call to this method. You could override if
|
||||
* you want more details such as the file/line info of where
|
||||
* in the parser java code a rule is invoked.
|
||||
*
|
||||
* This is very useful for error messages and for context-sensitive
|
||||
* error recovery.
|
||||
*/
|
||||
|
||||
/** A more general version of getRuleInvocationStack where you can
|
||||
* pass in, for example, a RecognitionException to get it's rule
|
||||
* stack trace. This routine is shared with all recognizers, hence,
|
||||
* static.
|
||||
*
|
||||
* TODO: move to a utility class or something; weird having lexer call this
|
||||
*/
|
||||
public static function getRuleInvocationStack($e=null,
|
||||
$recognizerClassName=null)
|
||||
{
|
||||
if($e==null){
|
||||
$e = new Exception();
|
||||
}
|
||||
if($recognizerClassName==null){
|
||||
$recognizerClassName = get_class($this);
|
||||
}
|
||||
throw new Exception("Not implemented yet");
|
||||
// List rules = new ArrayList();
|
||||
// StackTraceElement[] stack = e.getStackTrace();
|
||||
// int i = 0;
|
||||
// for (i=stack.length-1; i>=0; i--) {
|
||||
// StackTraceElement t = stack[i];
|
||||
// if ( t.getClassName().startsWith("org.antlr.runtime.") ) {
|
||||
// continue; // skip support code such as this method
|
||||
// }
|
||||
// if ( t.getMethodName().equals(NEXT_TOKEN_RULE_NAME) ) {
|
||||
// continue;
|
||||
// }
|
||||
// if ( !t.getClassName().equals(recognizerClassName) ) {
|
||||
// continue; // must not be part of this parser
|
||||
// }
|
||||
// rules.add(t.getMethodName());
|
||||
// }
|
||||
// return rules;
|
||||
}
|
||||
|
||||
public function getBacktrackingLevel() {
|
||||
return $this->state->backtracking;
|
||||
}
|
||||
|
||||
/** Used to print out token names like ID during debugging and
|
||||
* error reporting. The generated parsers implement a method
|
||||
* that overrides this to point to their String[] tokenNames.
|
||||
*/
|
||||
public function getTokenNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** For debugging and other purposes, might want the grammar name.
|
||||
* Have ANTLR generate an implementation for this method.
|
||||
*/
|
||||
public function getGrammarFileName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract function getSourceName();
|
||||
|
||||
/** A convenience method for use most often with template rewrites.
|
||||
* Convert a List<Token> to List<String>
|
||||
*/
|
||||
public function toStrings($tokens) {
|
||||
if ( $tokens==null ) return null;
|
||||
$strings = array();
|
||||
for ($i=0; $i<$tokens->size(); $i++) {
|
||||
$strings[] = $tokens[$i]->getText();
|
||||
}
|
||||
return $strings;
|
||||
}
|
||||
|
||||
/** Given a rule number and a start token index number, return
|
||||
* MEMO_RULE_UNKNOWN if the rule has not parsed input starting from
|
||||
* start index. If this rule has parsed input starting from the
|
||||
* start index before, then return where the rule stopped parsing.
|
||||
* It returns the index of the last token matched by the rule.
|
||||
*
|
||||
* For now we use a hashtable and just the slow Object-based one.
|
||||
* Later, we can make a special one for ints and also one that
|
||||
* tosses out data after we commit past input position i.
|
||||
*/
|
||||
public function getRuleMemoization($ruleIndex, $ruleStartIndex) {
|
||||
if ( $this->state->ruleMemo[$ruleIndex]==null ) {
|
||||
$this->state->ruleMemo[$ruleIndex] = array();
|
||||
}
|
||||
$stopIndexI =
|
||||
$this->state->ruleMemo[$ruleIndex][$ruleStartIndex];
|
||||
if ( $stopIndexI==null ) {
|
||||
return self::$MEMO_RULE_UNKNOWN;
|
||||
}
|
||||
return $stopIndexI;
|
||||
}
|
||||
|
||||
/** Has this rule already parsed input at the current index in the
|
||||
* input stream? Return the stop token index or MEMO_RULE_UNKNOWN.
|
||||
* If we attempted but failed to parse properly before, return
|
||||
* MEMO_RULE_FAILED.
|
||||
*
|
||||
* This method has a side-effect: if we have seen this input for
|
||||
* this rule and successfully parsed before, then seek ahead to
|
||||
* 1 past the stop token matched for this rule last time.
|
||||
*/
|
||||
public function alreadyParsedRule($input, $ruleIndex) {
|
||||
$stopIndex = $this->getRuleMemoization($ruleIndex, $input->index());
|
||||
if ( $stopIndex==self::$MEMO_RULE_UNKNOWN ) {
|
||||
return false;
|
||||
}
|
||||
if ( $stopIndex==self::$MEMO_RULE_FAILED ) {
|
||||
//System.out.println("rule "+ruleIndex+" will never succeed");
|
||||
$this->state->failed=true;
|
||||
}
|
||||
else {
|
||||
//System.out.println("seen rule "+ruleIndex+" before; skipping ahead to @"+(stopIndex+1)+" failed="+state.failed);
|
||||
$input->seek($stopIndex+1); // jump to one past stop token
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Record whether or not this rule parsed the input at this position
|
||||
* successfully. Use a standard java hashtable for now.
|
||||
*/
|
||||
public function memoize($input, $ruleIndex, $ruleStartIndex){
|
||||
$stopTokenIndex = $this->state->failed?self::$MEMO_RULE_FAILED:$input->index()-1;
|
||||
if ( $this->state->ruleMemo==null ) {
|
||||
echo("!!!!!!!!! memo array is null for ". getGrammarFileName());
|
||||
}
|
||||
if ( $ruleIndex >= sizeof($this->state->ruleMemo) ) {
|
||||
echo("!!!!!!!!! memo size is ".sizeof($this->state->ruleMemo).", but rule index is ".$ruleIndex);
|
||||
}
|
||||
if ( $this->state->ruleMemo[$ruleIndex]!=null ) {
|
||||
$this->state->ruleMemo[$ruleIndex][$ruleStartIndex] = $stopTokenIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/** return how many rule/input-index pairs there are in total.
|
||||
* TODO: this includes synpreds. :(
|
||||
*/
|
||||
public function getRuleMemoizationCacheSize() {
|
||||
$n = 0;
|
||||
for ($i = 0; $this->state->ruleMemo!=null && $i < sizeof($this->state->ruleMemo); $i++) {
|
||||
$ruleMap = $this->state->ruleMemo[$i];
|
||||
if ( $ruleMap!=null ) {
|
||||
$n += sizeof($ruleMap); // how many input indexes are recorded?
|
||||
}
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
public function traceIn($ruleName, $ruleIndex, $inputSymbol) {
|
||||
echo("enter ".$ruleName." ".$inputSymbol);
|
||||
if ( $this->state->failed ) {
|
||||
echo(" failed=".$this->state->failed);
|
||||
}
|
||||
if ( $this->state->backtracking>0 ) {
|
||||
echo(" backtracking=".$this->state->backtracking);
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
public function traceOut($ruleName, $ruleIndex, $inputSymbol) {
|
||||
echo("exit ".$ruleName." ".$inputSymbol);
|
||||
if ( $this->state->failed ) {
|
||||
echo(" failed=".$this->state->failed);
|
||||
}
|
||||
if ( $this->state->backtracking>0 ) {
|
||||
echo(" backtracking="+$this->state->backtracking);
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
public function getToken($name){
|
||||
if(preg_match("/\d+/", $name)){
|
||||
return (integer)$name;
|
||||
}else{
|
||||
return $this->$name;
|
||||
}
|
||||
}
|
||||
|
||||
public function getTokenName($tokenId){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BaseRecognizer::$DEFAULT_TOKEN_CHANNEL = TokenConst::$DEFAULT_CHANNEL;
|
||||
BaseRecognizer::$HIDDEN = TokenConst::$HIDDEN_CHANNEL;
|
||||
?>
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
class CharStreamConst{
|
||||
public static $EOF = -1;
|
||||
}
|
||||
$CharStream_EOF = -1;
|
||||
|
||||
/** A source of characters for an ANTLR lexer */
|
||||
interface CharStream extends IntStream {
|
||||
|
||||
/** For infinite streams, you don't need this; primarily I'm providing
|
||||
* a useful interface for action code. Just make sure actions don't
|
||||
* use this on streams that don't support it.
|
||||
*/
|
||||
public function substring($start, $stop);
|
||||
|
||||
/** Get the ith character of lookahead. This is the same usually as
|
||||
* LA(i). This will be used for labels in the generated
|
||||
* lexer code. I'd prefer to return a char here type-wise, but it's
|
||||
* probably better to be 32-bit clean and be consistent with LA.
|
||||
*/
|
||||
public function LT($i);
|
||||
|
||||
/** ANTLR tracks the line information automatically */
|
||||
function getLine();
|
||||
|
||||
/** Because this stream can rewind, we need to be able to reset the line */
|
||||
function setLine($line);
|
||||
|
||||
function setCharPositionInLine($pos);
|
||||
|
||||
/** The index of the character relative to the beginning of the line 0..n-1 */
|
||||
function getCharPositionInLine();
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
class CharStreamState {
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,380 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** The most common stream of tokens is one where every token is buffered up
|
||||
* and tokens are prefiltered for a certain channel (the parser will only
|
||||
* see these tokens and cannot change the filter channel number during the
|
||||
* parse).
|
||||
*
|
||||
* TODO: how to access the full token stream? How to track all tokens matched per rule?
|
||||
*/
|
||||
class CommonTokenStream implements TokenStream {
|
||||
protected $tokenSource;
|
||||
|
||||
/** Record every single token pulled from the source so we can reproduce
|
||||
* chunks of it later.
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/** Map<tokentype, channel> to override some Tokens' channel numbers */
|
||||
protected $channelOverrideMap;
|
||||
|
||||
/** Set<tokentype>; discard any tokens with this type */
|
||||
protected $discardSet;
|
||||
|
||||
/** Skip tokens on any channel but this one; this is how we skip whitespace... */
|
||||
protected $channel;
|
||||
|
||||
/** By default, track all incoming tokens */
|
||||
protected $discardOffChannelTokens = false;
|
||||
|
||||
/** Track the last mark() call result value for use in rewind(). */
|
||||
protected $lastMarker = 0;
|
||||
|
||||
/** The index into the tokens list of the current token (next token
|
||||
* to consume). p==-1 indicates that the tokens list is empty
|
||||
*/
|
||||
protected $p = -1;
|
||||
|
||||
public function __construct($tokenSource, $channel=null) {
|
||||
$this->channel = TokenConst::$DEFAULT_CHANNEL;
|
||||
$this->tokens = array();
|
||||
$this->tokenSource = $tokenSource;
|
||||
if($channel != null){
|
||||
$this->channel = $channel;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset this token stream by setting its token source. */
|
||||
public function setTokenSource($tokenSource) {
|
||||
$this->tokenSource = $tokenSource;
|
||||
$this->tokens = array();
|
||||
$this->p = -1;
|
||||
$this->channel = TokenConst::$DEFAULT_CHANNEL;
|
||||
}
|
||||
|
||||
/** Load all tokens from the token source and put in tokens.
|
||||
* This is done upon first LT request because you might want to
|
||||
* set some token type / channel overrides before filling buffer.
|
||||
*/
|
||||
protected function fillBuffer() {
|
||||
$index = 0;
|
||||
$t = $this->tokenSource->nextToken();
|
||||
while ( $t!=null && $t->getType()!=CharStreamConst::$EOF ) {
|
||||
$discard = false;
|
||||
// is there a channel override for token type?
|
||||
if ( $this->channelOverrideMap!=null ) {
|
||||
$channelI = $this->channelOverrideMap[$t->getType()];
|
||||
if ( $channelI!=null ) {
|
||||
$t->setChannel($channelI);
|
||||
}
|
||||
}
|
||||
if ( $this->discardSet!=null &&
|
||||
$this->discardSet->contains($t->getType()))
|
||||
{
|
||||
$discard = true;
|
||||
}
|
||||
else if ( $this->discardOffChannelTokens && $t->getChannel()!=$this->channel ) {
|
||||
$discard = true;
|
||||
}
|
||||
if ( !$discard ) {
|
||||
$t->setTokenIndex($index);
|
||||
$this->tokens[] = $t;
|
||||
$index++;
|
||||
}
|
||||
$t = $this->tokenSource->nextToken();
|
||||
}
|
||||
// leave p pointing at first token on channel
|
||||
$this->p = 0;
|
||||
$this->p = $this->skipOffTokenChannels($this->p);
|
||||
}
|
||||
|
||||
/** Move the input pointer to the next incoming token. The stream
|
||||
* must become active with LT(1) available. consume() simply
|
||||
* moves the input pointer so that LT(1) points at the next
|
||||
* input symbol. Consume at least one token.
|
||||
*
|
||||
* Walk past any token not on the channel the parser is listening to.
|
||||
*/
|
||||
public function consume() {
|
||||
if ( $this->p<sizeof($this->tokens)) {
|
||||
$this->p++;
|
||||
$this->p = $this->skipOffTokenChannels($this->p); // leave p on valid token
|
||||
}
|
||||
}
|
||||
|
||||
/** Given a starting index, return the index of the first on-channel
|
||||
* token.
|
||||
*/
|
||||
protected function skipOffTokenChannels($i) {
|
||||
$n = sizeof($this->tokens);
|
||||
while ( $i<$n && $this->tokens[$i]->getChannel()!=$this->channel ) {
|
||||
$i++;
|
||||
}
|
||||
return $i;
|
||||
}
|
||||
|
||||
protected function skipOffTokenChannelsReverse($i) {
|
||||
while ( $i>=0 && $this->tokens[$i]->getChannel()!=$this->channel) {
|
||||
$i--;
|
||||
}
|
||||
return $i;
|
||||
}
|
||||
|
||||
/** A simple filter mechanism whereby you can tell this token stream
|
||||
* to force all tokens of type ttype to be on channel. For example,
|
||||
* when interpreting, we cannot exec actions so we need to tell
|
||||
* the stream to force all WS and NEWLINE to be a different, ignored
|
||||
* channel.
|
||||
*/
|
||||
public function setTokenTypeChannel($ttype, $channel) {
|
||||
if ( $this->channelOverrideMap==null ) {
|
||||
$this->channelOverrideMap = array();
|
||||
}
|
||||
$this->channelOverrideMap[$ttype] = $channel;
|
||||
}
|
||||
|
||||
public function discardTokenType($ttype) {
|
||||
if ( $this->discardSet==null ) {
|
||||
$this->discardSet = new Set();
|
||||
}
|
||||
$this->discardSet.add($ttype);
|
||||
}
|
||||
|
||||
public function discardOffChannelTokens($discardOffChannelTokens) {
|
||||
$this->discardOffChannelTokens = $discardOffChannelTokens;
|
||||
}
|
||||
|
||||
public function getTokens() {
|
||||
if ( $this->p == -1 ) {
|
||||
$this->fillBuffer();
|
||||
}
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
public function getTokensBetween($start, $stop) {
|
||||
return $this->getTokens($start, $stop, null);
|
||||
}
|
||||
|
||||
/** Given a start and stop index, return a List of all tokens in
|
||||
* the token type BitSet. Return null if no tokens were found. This
|
||||
* method looks at both on and off channel tokens.
|
||||
*/
|
||||
public function getTokensOfTypeInSet($start, $stop, $types) {
|
||||
if ( $p == -1 ) {
|
||||
fillBuffer();
|
||||
}
|
||||
if ( $stop>=sizeof($this->tokens)) {
|
||||
$stop=sizeof($this->tokens) - 1;
|
||||
}
|
||||
if ( $start<0 ) {
|
||||
$start=0;
|
||||
}
|
||||
if ( $start>$stop ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// list = tokens[start:stop]:{Token t, t.getType() in types}
|
||||
$filteredTokens = array();
|
||||
for ($i=$start; $i<=$stop; $i++) {
|
||||
$t = $this->tokens[$i];
|
||||
if ( $types==null || $types->member($t->getType())) {
|
||||
$filteredTokens->add($t);
|
||||
}
|
||||
}
|
||||
if ( sizeof($filteredTokens)==0 ) {
|
||||
$filteredTokens = null;
|
||||
}
|
||||
return $filteredTokens;
|
||||
}
|
||||
|
||||
public function getTokensOfTypeInArray($start, $stop, $types) {
|
||||
return $this->getTokens($start, $stop,new Set(types));
|
||||
}
|
||||
|
||||
public function getTokensofType($start, $stop, $ttype) {
|
||||
return $this->getTokens($start, $stop, new Set(array(ttype)));
|
||||
}
|
||||
|
||||
/** Get the ith token from the current position 1..n where k=1 is the
|
||||
* first symbol of lookahead.
|
||||
*/
|
||||
public function LT($k) {
|
||||
if ( $this->p == -1 ) {
|
||||
$this->fillBuffer();
|
||||
}
|
||||
if ( $k==0 ) {
|
||||
return null;
|
||||
}
|
||||
if ( $k<0 ) {
|
||||
return $this->LB(-$k);
|
||||
}
|
||||
//System.out.print("LT(p="+p+","+k+")=");
|
||||
if ( ($this->p+$k-1) >= sizeof($this->tokens)) {
|
||||
return TokenConst::$EOF_TOKEN;
|
||||
}
|
||||
//System.out.println(tokens.get(p+k-1));
|
||||
$i = $this->p;
|
||||
$n = 1;
|
||||
// find k good tokens
|
||||
while ( $n<$k ) {
|
||||
// skip off-channel tokens
|
||||
$i = $this->skipOffTokenChannels($i+1); // leave p on valid token
|
||||
$n++;
|
||||
}
|
||||
if ( $i>=sizeof($this->tokens)) {
|
||||
return TokenConst::$EOF_TOKEN;
|
||||
}
|
||||
return $this->tokens[$i];
|
||||
}
|
||||
|
||||
/** Look backwards k tokens on-channel tokens */
|
||||
protected function LB($k) {
|
||||
//System.out.print("LB(p="+p+","+k+") ");
|
||||
if ( $this->p == -1 ) {
|
||||
$this->fillBuffer();
|
||||
}
|
||||
if ( $k==0 ) {
|
||||
return null;
|
||||
}
|
||||
if ( ($this->p-$k)<0 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$i = $this->p;
|
||||
$n = 1;
|
||||
// find k good tokens looking backwards
|
||||
while ( $n<=$k ) {
|
||||
// skip off-channel tokens
|
||||
$i = $this->skipOffTokenChannelsReverse($i-1); // leave p on valid token
|
||||
$n++;
|
||||
}
|
||||
if ( $i<0 ) {
|
||||
return null;
|
||||
}
|
||||
return $this->tokens[$i];
|
||||
}
|
||||
|
||||
/** Return absolute token i; ignore which channel the tokens are on;
|
||||
* that is, count all tokens not just on-channel tokens.
|
||||
*/
|
||||
public function get($i) {
|
||||
return $this->tokens[$i];
|
||||
}
|
||||
|
||||
public function LA($i) {
|
||||
$lt = $this->LT($i);
|
||||
return $this->LT($i)->getType();
|
||||
}
|
||||
|
||||
public function mark() {
|
||||
if ( $this->p == -1 ) {
|
||||
$this->fillBuffer();
|
||||
}
|
||||
$this->lastMarker = $this->index();
|
||||
return $this->lastMarker;
|
||||
}
|
||||
|
||||
public function release($marker) {
|
||||
// no resources to release
|
||||
}
|
||||
|
||||
public function size() {
|
||||
return sizeof($this->tokens);
|
||||
}
|
||||
|
||||
public function index() {
|
||||
return $this->p;
|
||||
}
|
||||
|
||||
public function rewind($marker = null) {
|
||||
if($marker===null){
|
||||
$marker = $this->lastmarker;
|
||||
}
|
||||
$this->seek($marker);
|
||||
}
|
||||
|
||||
|
||||
public function reset() {
|
||||
$this->p = 0;
|
||||
$this->lastMarker = 0;
|
||||
}
|
||||
|
||||
public function seek($index) {
|
||||
$this->p = $index;
|
||||
}
|
||||
|
||||
public function getTokenSource() {
|
||||
return $this->tokenSource;
|
||||
}
|
||||
|
||||
public function getSourceName() {
|
||||
return $this->getTokenSource()->getSourceName();
|
||||
}
|
||||
|
||||
public function toString() {
|
||||
if ( $this->p == -1 ) {
|
||||
$this->fillBuffer();
|
||||
}
|
||||
return $this->toStringBetween(0, sizeof($this->tokens)-1);
|
||||
}
|
||||
|
||||
public function toStringBetween($start, $stop) {
|
||||
if ( $start<0 || $stop<0 ) {
|
||||
return null;
|
||||
}
|
||||
if ( $this->p == -1 ) {
|
||||
$this->fillBuffer();
|
||||
}
|
||||
if ( $stop>=sizeof($this->tokens)) {
|
||||
$stop = sizeof($this->tokens)-1;
|
||||
}
|
||||
$buf = "";
|
||||
for ($i = $start; $i <= $stop; $i++) {
|
||||
$t = $this->tokens[$i];
|
||||
$buf.=$t->getText();
|
||||
}
|
||||
return $buf;
|
||||
}
|
||||
|
||||
public function toStringBetweenTokens($start, $stop) {
|
||||
if ( $start!=null && $stop!=null ) {
|
||||
return toString($this->start->getTokenIndex(), $this->stop->getTokenIndex());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,215 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** A DFA implemented as a set of transition tables.
|
||||
*
|
||||
* Any state that has a semantic predicate edge is special; those states
|
||||
* are generated with if-then-else structures in a specialStateTransition()
|
||||
* which is generated by cyclicDFA template.
|
||||
*
|
||||
* There are at most 32767 states (16-bit signed short).
|
||||
* Could get away with byte sometimes but would have to generate different
|
||||
* types and the simulation code too. For a point of reference, the Java
|
||||
* lexer's Tokens rule DFA has 326 states roughly.
|
||||
*/
|
||||
class DFA {
|
||||
protected $eot;
|
||||
protected $eof;
|
||||
protected $min;
|
||||
protected $max;
|
||||
protected $accept;
|
||||
protected $special;
|
||||
protected $transition;
|
||||
|
||||
protected $decisionNumber;
|
||||
|
||||
/** Which recognizer encloses this DFA? Needed to check backtracking */
|
||||
protected $recognizer;
|
||||
|
||||
public $debug = false;
|
||||
|
||||
/** From the input stream, predict what alternative will succeed
|
||||
* using this DFA (representing the covering regular approximation
|
||||
* to the underlying CFL). Return an alternative number 1..n. Throw
|
||||
* an exception upon error.
|
||||
*/
|
||||
//TODO: This is a hackish way of doing a try finally, replace this by bunching up the returns.
|
||||
//Possibly rewrite predict. There is one more place i might need to fix, where i thought
|
||||
//try{}catch(ex){[work]; throw ex}; [work]; would be the same as a try finally;
|
||||
|
||||
public function predict($input){
|
||||
if ( $this->debug ) {
|
||||
echo ("Enter DFA.predict for decision ".$this->decisionNumber);
|
||||
}
|
||||
$mark = $input->mark(); // remember where decision started in input
|
||||
try {
|
||||
$ret = $this->_predict($input);
|
||||
|
||||
}
|
||||
catch(Exception $e) {
|
||||
$input->rewind($mark);
|
||||
throw $e;
|
||||
}
|
||||
$input->rewind($mark);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function _predict($input) {
|
||||
$s = 0; // we always start at s0
|
||||
while ( true ) {
|
||||
if ( $this->debug ) echo ("DFA ".$this->decisionNumber." state ".$s." LA(1)=".$input->LA(1)."(".$input->LA(1)."), index=".$input->index());
|
||||
$specialState = $this->special[$s];
|
||||
if ( $specialState>=0 ) {
|
||||
if ( $this->debug ) {
|
||||
echo ("DFA ".$this->decisionNumber.
|
||||
" state ".$s." is special state ".$specialState);
|
||||
}
|
||||
$s = $this->specialStateTransition($specialState, $input);
|
||||
if ( $this->debug ) {
|
||||
echo ("DFA ".$this->decisionNumber.
|
||||
" returns from special state ".$specialState." to ".s);
|
||||
}
|
||||
if ( $s==-1 ) {
|
||||
$this->noViableAlt($s, $input);
|
||||
return 0;
|
||||
}
|
||||
$input->consume();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $this->accept[$s] >= 1 ) {
|
||||
if ( $this->debug ) echo ("accept; predict "+$this->accept[$s]+" from state "+$this->s);
|
||||
return $this->accept[$s];
|
||||
}
|
||||
// look for a normal char transition
|
||||
$c = $input->LA(1); // -1 == \uFFFF, all tokens fit in 65000 space
|
||||
if ($c>=$this->min[$s] && $c<=$this->max[$s]) {
|
||||
$snext = $this->transition[$s][$c-$this->min[$s]]; // move to next state
|
||||
if ( $snext < 0 ) {
|
||||
// was in range but not a normal transition
|
||||
// must check EOT, which is like the else clause.
|
||||
// eot[s]>=0 indicates that an EOT edge goes to another
|
||||
// state.
|
||||
if ( $this->eot[$s]>=0 ) { // EOT Transition to accept state?
|
||||
if ( $this->debug ) echo("EOT transition");
|
||||
$s = $this->eot[$s];
|
||||
$input->consume();
|
||||
// TODO: I had this as return accept[eot[s]]
|
||||
// which assumed here that the EOT edge always
|
||||
// went to an accept...faster to do this, but
|
||||
// what about predicated edges coming from EOT
|
||||
// target?
|
||||
continue;
|
||||
}
|
||||
$this->noViableAlt($s,$input);
|
||||
return 0;
|
||||
}
|
||||
$s = $snext;
|
||||
$input->consume();
|
||||
continue;
|
||||
}
|
||||
if ( $eot[$s]>=0 ) { // EOT Transition?
|
||||
if ( $this->debug ) println("EOT transition");
|
||||
$s = $this->eot[$s];
|
||||
$input->consume();
|
||||
continue;
|
||||
}
|
||||
if ( $c==Token::$EOF && $eof[$s]>=0 ) { // EOF Transition to accept state?
|
||||
if ( $this->debug ) echo ("accept via EOF; predict "+$this->accept[$eof[$s]]+" from "+$eof[$s]);
|
||||
return $this->accept[$eof[$s]];
|
||||
}
|
||||
// not in range and not EOF/EOT, must be invalid symbol
|
||||
if ( $this->debug ) {
|
||||
echo("min[".$s."]=".$this->min[$s]);
|
||||
echo("max[".$s."]=".$this->max[$s]);
|
||||
echo("eot[".$s."]=".$this->eot[$s]);
|
||||
echo("eof[".$s."]=".$this->eof[$s]);
|
||||
for ($p=0; $p<$this->transition[$s]->length; $p++) {
|
||||
echo $this->transition[$s][$p]+" ";
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
$this->noViableAlt($s, $input);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function noViableAlt($s, $input){
|
||||
if ($this->recognizer->state->backtracking>0) {
|
||||
$this->recognizer->state->failed=true;
|
||||
return;
|
||||
}
|
||||
$nvae =
|
||||
new NoViableAltException($this->getDescription(),
|
||||
$decisionNumber,
|
||||
$s,
|
||||
$input);
|
||||
$this->error($nvae);
|
||||
throw $nvae;
|
||||
}
|
||||
|
||||
/** A hook for debugging interface */
|
||||
protected function error($nvae) { ; }
|
||||
|
||||
function specialStateTransition($s, $input)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getDescription() {
|
||||
return "n/a";
|
||||
}
|
||||
|
||||
/** Given a String that has a run-length-encoding of some unsigned shorts
|
||||
* like "\1\2\3\9", convert to short[] {2,9,9,9}. We do this to avoid
|
||||
* static short[] which generates so much init code that the class won't
|
||||
* compile. :(
|
||||
*/
|
||||
public static function unpackEncodedString($encodedString) {
|
||||
$data = array();
|
||||
$di = 0;
|
||||
for ($i=0,$len=strlen($encodedString); $i<$len; $i+=2) {
|
||||
$n = charAt($encodedString, $i);
|
||||
$v = charAt($encodedString, $i+1);
|
||||
// add v n times to data
|
||||
for ($j=1; $j<=$n; $j++) {
|
||||
if($v==0xff) $v=-1;
|
||||
$data[$di++] = $v;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
function __call($fn, $params){
|
||||
return call_user_func_array(array($this->recognizer, $fn), $params);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** The recognizer did not match anything for a (..)+ loop. */
|
||||
class EarlyExitException extends RecognitionException {
|
||||
public $decisionNumber;
|
||||
|
||||
public function __construct($decisionNumber, $input) {
|
||||
parent::__construct($input);
|
||||
$this->decisionNumber = $decisionNumber;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** A simple stream of integers used when all I care about is the char
|
||||
* or token type sequence (such as interpretation).
|
||||
*/
|
||||
interface IntStream {
|
||||
function consume();
|
||||
|
||||
/** Get int at current input pointer + i ahead where i=1 is next int.
|
||||
* Negative indexes are allowed. LA(-1) is previous token (token
|
||||
* just matched). LA(-i) where i is before first token should
|
||||
* yield -1, invalid char / EOF.
|
||||
*/
|
||||
function LA($i);
|
||||
|
||||
/** Tell the stream to start buffering if it hasn't already. Return
|
||||
* current input position, index(), or some other marker so that
|
||||
* when passed to rewind() you get back to the same spot.
|
||||
* rewind(mark()) should not affect the input cursor. The Lexer
|
||||
* track line/col info as well as input index so its markers are
|
||||
* not pure input indexes. Same for tree node streams.
|
||||
*/
|
||||
function mark();
|
||||
|
||||
/** Return the current input symbol index 0..n where n indicates the
|
||||
* last symbol has been read. The index is the symbol about to be
|
||||
* read not the most recently read symbol.
|
||||
*/
|
||||
function index();
|
||||
|
||||
/** Reset the stream so that next call to index would return marker.
|
||||
* The marker will usually be index() but it doesn't have to be. It's
|
||||
* just a marker to indicate what state the stream was in. This is
|
||||
* essentially calling release() and seek(). If there are markers
|
||||
* created after this marker argument, this routine must unroll them
|
||||
* like a stack. Assume the state the stream was in when this marker
|
||||
* was created.
|
||||
*/
|
||||
function rewind($marker=null);
|
||||
|
||||
/** You may want to commit to a backtrack but don't want to force the
|
||||
* stream to keep bookkeeping objects around for a marker that is
|
||||
* no longer necessary. This will have the same behavior as
|
||||
* rewind() except it releases resources without the backward seek.
|
||||
* This must throw away resources for all markers back to the marker
|
||||
* argument. So if you're nested 5 levels of mark(), and then release(2)
|
||||
* you have to release resources for depths 2..5.
|
||||
*/
|
||||
function release($marker);
|
||||
|
||||
/** Set the input cursor to the position indicated by index. This is
|
||||
* normally used to seek ahead in the input stream. No buffering is
|
||||
* required to do this unless you know your stream will use seek to
|
||||
* move backwards such as when backtracking.
|
||||
*
|
||||
* This is different from rewind in its multi-directional
|
||||
* requirement and in that its argument is strictly an input cursor (index).
|
||||
*
|
||||
* For char streams, seeking forward must update the stream state such
|
||||
* as line number. For seeking backwards, you will be presumably
|
||||
* backtracking using the mark/rewind mechanism that restores state and
|
||||
* so this method does not need to update state when seeking backwards.
|
||||
*
|
||||
* Currently, this method is only used for efficient backtracking using
|
||||
* memoization, but in the future it may be used for incremental parsing.
|
||||
*
|
||||
* The index is 0..n-1. A seek to position i means that LA(1) will
|
||||
* return the ith symbol. So, seeking to 0 means LA(1) will return the
|
||||
* first element in the stream.
|
||||
*/
|
||||
function seek($index);
|
||||
|
||||
/** Only makes sense for streams that buffer everything up probably, but
|
||||
* might be useful to display the entire stream or for testing. This
|
||||
* value includes a single EOF.
|
||||
*/
|
||||
function size();
|
||||
|
||||
/** Where are you getting symbols from? Normally, implementations will
|
||||
* pass the buck all the way to the lexer who can ask its input stream
|
||||
* for the file name or whatever.
|
||||
*/
|
||||
public function getSourceName();
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
class MismatchedRangeException extends RecognitionException {
|
||||
public $a;
|
||||
public $b;
|
||||
|
||||
public function __construct($a, $b, $input) {
|
||||
parent::__construct($input);
|
||||
$this->a = $a;
|
||||
$this->b = $b;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return "MismatchedNotSetException(".$this->getUnexpectedType()." not in [".a.",".b."])";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
class MismatchedSetException extends RecognitionException {
|
||||
public $expecting;
|
||||
|
||||
public function __construct($expecting, $input) {
|
||||
parent::__construct($input);
|
||||
$this->expecting = $expecting;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return "MismatchedSetException(".$this->getUnexpectedType()."!=".$this->expecting.")";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** A mismatched char or Token or tree node */
|
||||
class MismatchedTokenException extends RecognitionException {
|
||||
//$expecting = $Token_INVALID_TOKEN_TYPE
|
||||
public function __construct($expecting=0, $input=null) {
|
||||
parent::__construct($input);
|
||||
$this->expecting = $expecting;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return "MismatchedTokenException(".$this->getUnexpectedType()."!=".$this->expecting.")";
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/** We were expecting a token but it's not found. The current token
|
||||
* is actually what we wanted next. Used for tree node errors too.
|
||||
*/
|
||||
class MissingTokenException extends MismatchedTokenException {
|
||||
public $inserted;
|
||||
public function __construct($expecting, $input, $inserted) {
|
||||
parent::__construct($expecting, $input);
|
||||
$this->inserted = $inserted;
|
||||
}
|
||||
|
||||
public function getMissingType() {
|
||||
return $this->expecting;
|
||||
}
|
||||
|
||||
public function toString() {
|
||||
if ( $this->inserted!=null && $this->token!=null ) {
|
||||
return "MissingTokenException(inserted ".$this->inserted." at ".$this->token->getText()+")";
|
||||
}
|
||||
if ( $this->token!=null ) {
|
||||
return "MissingTokenException(at ".$token->getText().")";
|
||||
}
|
||||
return "MissingTokenException";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
class NoViableAltException extends RecognitionException {
|
||||
public $grammarDecisionDescription;
|
||||
public $decisionNumber;
|
||||
public $stateNumber;
|
||||
|
||||
public function __construct($grammarDecisionDescription,
|
||||
$decisionNumber,
|
||||
$stateNumber,
|
||||
$input)
|
||||
{
|
||||
parent::__construct($input);
|
||||
$this->grammarDecisionDescription = $grammarDecisionDescription;
|
||||
$this->decisionNumber = $decisionNumber;
|
||||
$this->stateNumber = $stateNumber;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
if ( $this->input instanceof CharStream ) {
|
||||
return "NoViableAltException('".$this->getUnexpectedType()."'@[".$this->grammarDecisionDescription."])";
|
||||
}
|
||||
else {
|
||||
return "NoViableAltException(".$this->getUnexpectedType()."@[".$this->grammarDecisionDescription."])";
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** The root of the ANTLR exception hierarchy.
|
||||
*
|
||||
* To avoid English-only error messages and to generally make things
|
||||
* as flexible as possible, these exceptions are not created with strings,
|
||||
* but rather the information necessary to generate an error. Then
|
||||
* the various reporting methods in Parser and Lexer can be overridden
|
||||
* to generate a localized error message. For example, MismatchedToken
|
||||
* exceptions are built with the expected token type.
|
||||
* So, don't expect getMessage() to return anything.
|
||||
*
|
||||
* Note that as of Java 1.4, you can access the stack trace, which means
|
||||
* that you can compute the complete trace of rules from the start symbol.
|
||||
* This gives you considerable context information with which to generate
|
||||
* useful error messages.
|
||||
*
|
||||
* ANTLR generates code that throws exceptions upon recognition error and
|
||||
* also generates code to catch these exceptions in each rule. If you
|
||||
* want to quit upon first error, you can turn off the automatic error
|
||||
* handling mechanism using rulecatch action, but you still need to
|
||||
* override methods mismatch and recoverFromMismatchSet.
|
||||
*
|
||||
* In general, the recognition exceptions can track where in a grammar a
|
||||
* problem occurred and/or what was the expected input. While the parser
|
||||
* knows its state (such as current input symbol and line info) that
|
||||
* state can change before the exception is reported so current token index
|
||||
* is computed and stored at exception time. From this info, you can
|
||||
* perhaps print an entire line of input not just a single token, for example.
|
||||
* Better to just say the recognizer had a problem and then let the parser
|
||||
* figure out a fancy report.
|
||||
*/
|
||||
class RecognitionException extends Exception {
|
||||
|
||||
public $line=0;
|
||||
|
||||
|
||||
public function __construct($input) {
|
||||
/** What input stream did the error occur in? */
|
||||
$this->input = $input;
|
||||
/** What is index of token/char were we looking at when the error occurred? */
|
||||
$this->index = $input->index();
|
||||
|
||||
/** The current Token when an error occurred. Since not all streams
|
||||
* can retrieve the ith Token, we have to track the Token object.
|
||||
* For parsers. Even when it's a tree parser, token might be set.
|
||||
*/
|
||||
$this->token=null;
|
||||
|
||||
/** If this is a tree parser exception, node is set to the node with
|
||||
* the problem.
|
||||
*/
|
||||
$this->node=null;
|
||||
|
||||
/** The current char when an error occurred. For lexers. */
|
||||
$this->c=0;
|
||||
|
||||
/** Track the line at which the error occurred in case this is
|
||||
* generated from a lexer. We need to track this since the
|
||||
* unexpected char doesn't carry the line info.
|
||||
*/
|
||||
$this->line=0;
|
||||
|
||||
$this->charPositionInLine=0;
|
||||
|
||||
/** If you are parsing a tree node stream, you will encounter som
|
||||
* imaginary nodes w/o line/col info. We now search backwards looking
|
||||
* for most recent token with line/col info, but notify getErrorHeader()
|
||||
* that info is approximate.
|
||||
*/
|
||||
$this->approximateLineInfo=false;
|
||||
|
||||
|
||||
if ( $this->input instanceof TokenStream ) {
|
||||
$this->token = $input->LT(1);
|
||||
$this->line = $this->token->getLine();
|
||||
$this->charPositionInLine = $this->token->getCharPositionInLine();
|
||||
}
|
||||
if ( $this->input instanceof TreeNodeStream ) {
|
||||
$this->extractInformationFromTreeNodeStream($input);
|
||||
}
|
||||
else if ( $input instanceof CharStream ) {
|
||||
$this->c = $input->LA(1);
|
||||
$this->line = $input->getLine();
|
||||
$this->charPositionInLine = $input->getCharPositionInLine();
|
||||
}
|
||||
else {
|
||||
$this->c = $input->LA(1);
|
||||
}
|
||||
}
|
||||
|
||||
protected function extractInformationFromTreeNodeStream($input) {
|
||||
$nodes = $input;
|
||||
$this->node = $nodes->LT(1);
|
||||
$adaptor = $nodes->getTreeAdaptor();
|
||||
$payload = $adaptor->getToken($this->node);
|
||||
if ( $payload!=null ) {
|
||||
$this->token = $payload;
|
||||
if ( $payload->getLine()<= 0 ) {
|
||||
// imaginary node; no line/pos info; scan backwards
|
||||
$i = -1;
|
||||
$priorNode = $nodes->LT($i);
|
||||
while ( $priorNode!=null ) {
|
||||
$priorPayload = $adaptor->getToken($priorNode);
|
||||
if ( $priorPayload!=null && $priorPayload->getLine()>0 ) {
|
||||
// we found the most recent real line / pos info
|
||||
$this->line = $priorPayload->getLine();
|
||||
$this->charPositionInLine = $priorPayload->getCharPositionInLine();
|
||||
$this->approximateLineInfo = true;
|
||||
break;
|
||||
}
|
||||
--$i;
|
||||
$priorNode = $nodes->LT($i);
|
||||
}
|
||||
}
|
||||
else { // node created from real token
|
||||
$this->line = $payload->getLine();
|
||||
$this->charPositionInLine = $payload->getCharPositionInLine();
|
||||
}
|
||||
}
|
||||
else if ( $this->node instanceof Tree) {
|
||||
$this->line = $this->node->getLine();
|
||||
$this->charPositionInLine = $this->node->getCharPositionInLine();
|
||||
if ( $this->node instanceof CommonTree) {
|
||||
$this->token = $this->node->token;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$type = $adaptor->getType($this->node);
|
||||
$text = $adaptor->getText($this->node);
|
||||
$this->token = CommonToken::forTypeAndText($type, $text);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the token type or char of the unexpected input element */
|
||||
public function getUnexpectedType() {
|
||||
if ( $this->input instanceof TokenStream ) {
|
||||
return $this->token->getType();
|
||||
}
|
||||
else if ( $this->input instanceof TreeNodeStream ) {
|
||||
$nodes = $this->input;
|
||||
$adaptor = $nodes->getTreeAdaptor();
|
||||
return $adaptor->getType($this->node);
|
||||
}
|
||||
else {
|
||||
return $this->c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
class RecognizerSharedState {
|
||||
public function __construct(){
|
||||
/** Track the set of token types that can follow any rule invocation.
|
||||
* Stack grows upwards. When it hits the max, it grows 2x in size
|
||||
* and keeps going.
|
||||
*/
|
||||
$this->following = array(); //Should be an array of bitsets
|
||||
$this->_fsp = -1;
|
||||
//public BitSet[] following = new BitSet[BaseRecognizer.INITIAL_FOLLOW_STACK_SIZE];
|
||||
|
||||
/** This is true when we see an error and before having successfully
|
||||
* matched a token. Prevents generation of more than one error message
|
||||
* per error.
|
||||
*/
|
||||
$this->errorRecovery = false;
|
||||
/** The index into the input stream where the last error occurred.
|
||||
* This is used to prevent infinite loops where an error is found
|
||||
* but no token is consumed during recovery...another error is found,
|
||||
* ad naseum. This is a failsafe mechanism to guarantee that at least
|
||||
* one token/tree node is consumed for two errors.
|
||||
*/
|
||||
$this->lastErrorIndex = -1;
|
||||
/** In lieu of a return value, this indicates that a rule or token
|
||||
* has failed to match. Reset to false upon valid token match.
|
||||
*/
|
||||
$this->failed=false;
|
||||
/** Did the recognizer encounter a syntax error? Track how many. */
|
||||
$this->syntaxErrors=0;
|
||||
|
||||
/** If 0, no backtracking is going on. Safe to exec actions etc...
|
||||
* If >0 then it's the level of backtracking.
|
||||
*/
|
||||
$this->backtracking = 0;
|
||||
|
||||
/** An array[size num rules] of Map<Integer,Integer> that tracks
|
||||
* the stop token index for each rule. ruleMemo[ruleIndex] is
|
||||
* the memoization table for ruleIndex. For key ruleStartIndex, you
|
||||
* get back the stop token for associated rule or MEMO_RULE_FAILED.
|
||||
*
|
||||
* This is only used if rule memoization is on (which it is by default).
|
||||
*/
|
||||
$this->ruleMemo = null;
|
||||
|
||||
|
||||
// LEXER FIELDS (must be in same state object to avoid casting
|
||||
// constantly in generated code and Lexer object) :(
|
||||
|
||||
|
||||
/** The goal of all lexer rules/methods is to create a token object.
|
||||
* This is an instance variable as multiple rules may collaborate to
|
||||
* create a single token. nextToken will return this object after
|
||||
* matching lexer rule(s). If you subclass to allow multiple token
|
||||
* emissions, then set this to the last token to be matched or
|
||||
* something nonnull so that the auto token emit mechanism will not
|
||||
* emit another token.
|
||||
*/
|
||||
$this->token = null;
|
||||
|
||||
/** What character index in the stream did the current token start at?
|
||||
* Needed, for example, to get the text for current token. Set at
|
||||
* the start of nextToken.
|
||||
*/
|
||||
$this->tokenStartCharIndex = -1;
|
||||
|
||||
/** The line on which the first character of the token resides */
|
||||
$this->tokenStartLine = 0;
|
||||
|
||||
/** The character position of first character within the line */
|
||||
$this->tokenStartCharPositionInLine = 0;
|
||||
|
||||
/** The channel number for the current token */
|
||||
$this->channel = 0;
|
||||
|
||||
/** The token type for the current token */
|
||||
$this->type = 0;
|
||||
|
||||
/** You can set the text for the current token to override what is in
|
||||
* the input char buffer. Use setText() or can set this instance var.
|
||||
*/
|
||||
$this->text=null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
//Todo: find a decent set implementation for php
|
||||
class Set{
|
||||
public function __construct($arr){
|
||||
$this->store = array();
|
||||
foreach($arr as $el){
|
||||
$this->store[$el] = $el;
|
||||
}
|
||||
}
|
||||
|
||||
public function add($value){
|
||||
$this->store[$value] = $value;
|
||||
}
|
||||
|
||||
public function member($value){
|
||||
return array_key_exists($value, $this->store);
|
||||
}
|
||||
|
||||
public function union($otherSet){
|
||||
return new Set(array_merge($this->store, $otherSet->store));
|
||||
}
|
||||
|
||||
public function unionInPlace($otherSet){
|
||||
$this->store = $this->union($otherSet)->store;
|
||||
}
|
||||
|
||||
public function remove($value){
|
||||
unset($this->store[$value]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,222 @@
|
|||
<?php
|
||||
|
||||
class TokenConst{
|
||||
public static $EOR_TOKEN_TYPE = 1;
|
||||
|
||||
/** imaginary tree navigation type; traverse "get child" link */
|
||||
public static $DOWN = 2;
|
||||
/** imaginary tree navigation type; finish with a child list */
|
||||
public static $UP = 3;
|
||||
|
||||
public static $MIN_TOKEN_TYPE;// = UP+1;
|
||||
|
||||
public static $EOF;// = CharStream.EOF;
|
||||
public static $EOF_TOKEN;// = new CommonToken(EOF);
|
||||
|
||||
public static $INVALID_TOKEN_TYPE = 0;
|
||||
public static $INVALID_TOKEN;// = new CommonToken(INVALID_TOKEN_TYPE);
|
||||
|
||||
/** In an action, a lexer rule can set token to this SKIP_TOKEN and ANTLR
|
||||
* will avoid creating a token for this symbol and try to fetch another.
|
||||
*/
|
||||
public static $SKIP_TOKEN;// = new CommonToken(INVALID_TOKEN_TYPE);
|
||||
|
||||
/** All tokens go to the parser (unless skip() is called in that rule)
|
||||
* on a particular "channel". The parser tunes to a particular channel
|
||||
* so that whitespace etc... can go to the parser on a "hidden" channel.
|
||||
*/
|
||||
public static $DEFAULT_CHANNEL = 0;
|
||||
|
||||
/** Anything on different channel than DEFAULT_CHANNEL is not parsed
|
||||
* by parser.
|
||||
*/
|
||||
public static $HIDDEN_CHANNEL = 99;
|
||||
}
|
||||
|
||||
|
||||
interface Token{
|
||||
}
|
||||
|
||||
|
||||
class CommonToken implements Token {
|
||||
|
||||
|
||||
function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public static function forInput($input=null, $type, $channel=0, $start=0, $stop=0) {
|
||||
$ct = new CommonToken();
|
||||
$ct->charPositionInLine=-1;
|
||||
$ct->input = $input;
|
||||
$ct->type = $type;
|
||||
$ct->channel = $channel;
|
||||
$ct->start = $start;
|
||||
$ct->stop = $stop;
|
||||
return $ct;
|
||||
}
|
||||
|
||||
public static function forType($type){
|
||||
return CommonToken::forInput($input=null, $type);
|
||||
}
|
||||
|
||||
public static function forTypeAndText($type, $text) {
|
||||
$ct = new CommonToken();
|
||||
$ct->type = $type;
|
||||
$ct->channel = TokenConst::$DEFAULT_CHANNEL;
|
||||
$ct->text = $text;
|
||||
return $ct;
|
||||
}
|
||||
/*
|
||||
public CommonToken(Token oldToken) {
|
||||
text = oldToken.getText();
|
||||
type = oldToken.getType();
|
||||
line = oldToken.getLine();
|
||||
index = oldToken.getTokenIndex();
|
||||
charPositionInLine = oldToken.getCharPositionInLine();
|
||||
channel = oldToken.getChannel();
|
||||
if ( oldToken instanceof CommonToken ) {
|
||||
start = ((CommonToken)oldToken).start;
|
||||
stop = ((CommonToken)oldToken).stop;
|
||||
}
|
||||
}
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setLine($line) {
|
||||
$this->line = $this->line;
|
||||
}
|
||||
|
||||
public function getText() {
|
||||
if ( $this->text!=null ) {
|
||||
return $this->text;
|
||||
}
|
||||
if ( $this->input==null ) {
|
||||
return null;
|
||||
}
|
||||
$this->text = $this->input->substring($this->start,$this->stop);
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/** Override the text for this token. getText() will return this text
|
||||
* rather than pulling from the buffer. Note that this does not mean
|
||||
* that start/stop indexes are not valid. It means that that input
|
||||
* was converted to a new string in the token object.
|
||||
*/
|
||||
public function setText($text) {
|
||||
$this->text = $this->text;
|
||||
}
|
||||
|
||||
public function getLine() {
|
||||
return $this->line;
|
||||
}
|
||||
|
||||
public function getCharPositionInLine() {
|
||||
return $this->charPositionInLine;
|
||||
}
|
||||
|
||||
public function setCharPositionInLine($charPositionInLine) {
|
||||
$this->charPositionInLine = $this->charPositionInLine;
|
||||
}
|
||||
|
||||
public function getChannel() {
|
||||
return $this->channel;
|
||||
}
|
||||
|
||||
public function setChannel($channel) {
|
||||
$this->channel = $this->channel;
|
||||
}
|
||||
|
||||
public function setType($type) {
|
||||
$this->type = $this->type;
|
||||
}
|
||||
|
||||
public function getStartIndex() {
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
public function setStartIndex($start) {
|
||||
$this->start = $this->start;
|
||||
}
|
||||
|
||||
public function getStopIndex() {
|
||||
return $this->stop;
|
||||
}
|
||||
|
||||
public function setStopIndex($stop) {
|
||||
$this->stop = $this->stop;
|
||||
}
|
||||
|
||||
public function getTokenIndex() {
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
public function setTokenIndex($index) {
|
||||
$this->index = $this->index;
|
||||
}
|
||||
|
||||
public function getInputStream() {
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
public function setInputStream($input) {
|
||||
$this->input = $this->input;
|
||||
}
|
||||
|
||||
public function toString() {
|
||||
$channelStr = "";
|
||||
if ( $this->channel>0 ) {
|
||||
$channelStr=",channel=".$this->channel;
|
||||
}
|
||||
$txt = $this->getText();
|
||||
if ( $txt!=null ) {
|
||||
$txt = str_replace("\n",'\n', $txt);
|
||||
$txt = str_replace("\r",'\r', $txt);
|
||||
$txt = str_replace("\t",'\t', $txt);
|
||||
}
|
||||
else {
|
||||
$txt = "<no text>";
|
||||
}
|
||||
return "[@".$this->getTokenIndex().",".$this->start.":".$this->stop."='".$txt."',<".$this->type.">".$channelStr.",".$this->line.":".$this->getCharPositionInLine()."]";
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
||||
TokenConst::$DEFAULT_CHANNEL=0;
|
||||
TokenConst::$INVALID_TOKEN_TYPE=0;
|
||||
|
||||
TokenConst::$EOF = CharStreamConst::$EOF;
|
||||
TokenConst::$EOF_TOKEN = CommonToken::forType(TokenConst::$EOF);
|
||||
|
||||
TokenConst::$INVALID_TOKEN_TYPE = 0;
|
||||
TokenConst::$INVALID_TOKEN = CommonToken::forType(TokenConst::$INVALID_TOKEN_TYPE);
|
||||
/** In an action, a lexer rule can set token to this SKIP_TOKEN and ANTLR
|
||||
* will avoid creating a token for this symbol and try to fetch another.
|
||||
*/
|
||||
TokenConst::$SKIP_TOKEN = CommonToken::forType(TokenConst::$INVALID_TOKEN_TYPE);
|
||||
|
||||
/** All tokens go to the parser (unless skip() is called in that rule)
|
||||
* on a particular "channel". The parser tunes to a particular channel
|
||||
* so that whitespace etc... can go to the parser on a "hidden" channel.
|
||||
*/
|
||||
TokenConst::$DEFAULT_CHANNEL = 0;
|
||||
|
||||
/** Anything on different channel than DEFAULT_CHANNEL is not parsed
|
||||
* by parser.
|
||||
*/
|
||||
TokenConst::$HIDDEN_CHANNEL = 99;
|
||||
|
||||
|
||||
|
||||
TokenConst::$MIN_TOKEN_TYPE = TokenConst::$UP+1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
/*
|
||||
[The "BSD licence"]
|
||||
Copyright (c) 2005-2008 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** A stream of tokens accessing tokens from a TokenSource */
|
||||
interface TokenStream extends IntStream {
|
||||
/** Get Token at current input pointer + i ahead where i=1 is next Token.
|
||||
* i<0 indicates tokens in the past. So -1 is previous token and -2 is
|
||||
* two tokens ago. LT(0) is undefined. For i>=n, return Token.EOFToken.
|
||||
* Return null for LT(0) and any index that results in an absolute address
|
||||
* that is negative.
|
||||
*/
|
||||
public function LT($k);
|
||||
|
||||
/** Get a token at an absolute index i; 0..n-1. This is really only
|
||||
* needed for profiling and debugging and token stream rewriting.
|
||||
* If you don't want to buffer up tokens, then this method makes no
|
||||
* sense for you. Naturally you can't use the rewrite stream feature.
|
||||
* I believe DebugTokenStream can easily be altered to not use
|
||||
* this method, removing the dependency.
|
||||
*/
|
||||
public function get($i);
|
||||
|
||||
/** Where is this stream pulling tokens from? This is not the name, but
|
||||
* the object that provides Token objects.
|
||||
*/
|
||||
public function getTokenSource();
|
||||
|
||||
/** Return the text of all tokens from start to stop, inclusive.
|
||||
* If the stream does not buffer all the tokens then it can just
|
||||
* return "" or null; Users should not access $ruleLabel.text in
|
||||
* an action of course in that case.
|
||||
*/
|
||||
public function toStringBetween($start, $stop);
|
||||
|
||||
|
||||
/** Because the user is not required to use a token with an index stored
|
||||
* in it, we must provide a means for two token objects themselves to
|
||||
* indicate the start/end location. Most often this will just delegate
|
||||
* to the other toString(int,int). This is also parallel with
|
||||
* the TreeNodeStream.toString(Object,Object).
|
||||
*/
|
||||
public function toStringBetweenTokens($start, $stop);
|
||||
}
|
||||
|
||||
?>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue