- First implementation of documents

- small cleanup to remove a global Config variable (and removed some deprecated utils:: functions)
- removed the 'DocumentVersion' object since previous versions are now tracked as normal change objects.

SVN:trunk[220]
This commit is contained in:
Denis Flaven
2009-12-31 09:08:09 +00:00
parent 9247b326c8
commit 966d4820ca
16 changed files with 403 additions and 132 deletions

View File

@@ -225,6 +225,21 @@ abstract class cmdbAbstractObject extends CMDBObject
}
}
$sHtml .= $oPage->GetDetails($aDetails);
// Documents displayed inline (when possible: images, html...)
foreach($aList as $sAttCode)
{
$oAttDef = Metamodel::GetAttributeDef($sClass, $sAttCode);
if ( $oAttDef->GetEditClass() == 'Document')
{
$oDoc = $this->Get($sAttCode);
if (is_object($oDoc) && !$oDoc->IsEmpty())
{
$sHtml .= "<p>Open in New Window: ".$oDoc->GetDisplayLink($sClass, $this->GetKey(), $sAttCode).", \n";
$sHtml .= "Download: ".$oDoc->GetDownloadLink($sClass, $this->GetKey(), $sAttCode)."</p>\n";
$sHtml .= "<div>".$oDoc->GetDisplayInline($sClass, $this->GetKey(), $sAttCode)."</div>\n";
}
}
}
return $sHtml;
}
@@ -269,8 +284,6 @@ abstract class cmdbAbstractObject extends CMDBObject
//public static function GetDisplaySet(web_page $oPage, CMDBObjectSet $oSet, $sLinkageAttribute = '', $bDisplayMenu = true, $bSelectMode = false)
public static function GetDisplaySet(web_page $oPage, CMDBObjectSet $oSet, $aExtraParams = array())
{
global $g_oConfig;
static $iListId = 0;
$iListId++;
@@ -347,9 +360,9 @@ abstract class cmdbAbstractObject extends CMDBObject
$iMaxObjects = -1;
if ($bDisplayLimit)
{
if ($oSet->Count() > $g_oConfig->GetMaxDisplayLimit())
if ($oSet->Count() > utils::GetConfig()->GetMaxDisplayLimit())
{
$iMaxObjects = $g_oConfig->GetMinDisplayLimit();
$iMaxObjects = utils::GetConfig()->GetMinDisplayLimit();
}
}
while (($oObj = $oSet->Fetch()) && ($iMaxObjects != 0))
@@ -379,14 +392,14 @@ abstract class cmdbAbstractObject extends CMDBObject
//$aMenuExtraParams['linkage'] = $sLinkageAttribute;
$aMenuExtraParams = $aExtraParams;
}
if ($bDisplayLimit && ($oSet->Count() > $g_oConfig->GetMaxDisplayLimit()))
if ($bDisplayLimit && ($oSet->Count() > utils::GetConfig()->GetMaxDisplayLimit()))
{
// list truncated
$divId = $aExtraParams['block_id'];
$sFilter = $oSet->GetFilter()->serialize();
$aExtraParams['display_limit'] = false; // To expand the full list
$sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
$sHtml .= '<tr class="containerHeader"><td>'.$g_oConfig->GetMinDisplayLimit().' object(s) displayed out of '.$oSet->Count().'&nbsp;&nbsp;<a href="Javascript:ReloadTruncatedList(\''.$divId.'\', \''.$sFilter.'\', \''.$sExtraParams.'\');">Display All</a></td><td>';
$sHtml .= '<tr class="containerHeader"><td>'.utils::GetConfig()->GetMinDisplayLimit().' object(s) displayed out of '.$oSet->Count().'&nbsp;&nbsp;<a href="Javascript:ReloadTruncatedList(\''.$divId.'\', \''.$sFilter.'\', \''.$sExtraParams.'\');">Display All</a></td><td>';
$oPage->add_ready_script("$('#{$divId} table.listResults').addClass('truncated');");
$oPage->add_ready_script("$('#{$divId} table.listResults tr:last td').addClass('truncated');");
}
@@ -434,14 +447,7 @@ abstract class cmdbAbstractObject extends CMDBObject
$aRow[] = $oObj->GetKey();
foreach($aList as $sAttCode)
{
if (strstr($oObj->Get($sAttCode), $sSeparator)) // Escape the text only when it contains the separator
{
$aRow[] = $sTextQualifier.$oObj->Get($sAttCode).$sTextQualifier;
}
else
{
$aRow[] = $oObj->Get($sAttCode);
}
$aRow[] = $oObj->GetAsCSV($sAttCode, $sSeparator, '\\');
}
$sHtml .= implode($sSeparator, $aRow)."\n";
}
@@ -674,6 +680,20 @@ abstract class cmdbAbstractObject extends CMDBObject
$sHTMLValue = $oWidget->Display($oPage, $value);
break;
case 'Document':
$oDocument = $value; // Value is an ormDocument object
$sFileName = '';
if (is_object($oDocument))
{
$sFileName = $oDocument->GetFileName();
}
$iMaxFileSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
$sHTMLValue = "<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"$iMaxFileSize\" />\n";
$sHTMLValue .= "<input name=\"attr_{$sAttCode}{$sNameSuffix}\" type=\"hidden\" id=\"$iInputId\" \" value=\"$sFileName\"/>\n";
$sHTMLValue .= "<span id=\"name_$iInputId\">$sFileName</span><br/>\n";
$sHTMLValue .= "<input name=\"file_{$sAttCode}{$sNameSuffix}\" type=\"file\" id=\"file_$iInputId\" onChange=\"UpdateFileName('$iInputId', this.value);\"/>\n";
break;
case 'String':
default:
// #@# todo - add context information (depending on dimensions)
@@ -728,7 +748,7 @@ abstract class cmdbAbstractObject extends CMDBObject
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
$iKey = $this->GetKey();
$aDetails = array();
$oPage->add("<form id=\"form_{$iFormId}\" method=\"post\" onSubmit=\"return CheckMandatoryFields('form_{$iFormId}')\">\n");
$oPage->add("<form id=\"form_{$iFormId}\" enctype=\"multipart/form-data\" method=\"post\" onSubmit=\"return CheckMandatoryFields('form_{$iFormId}')\">\n");
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if ('finalclass' == $sAttCode) // finalclass is a reserved word, hardcoded !

View File

@@ -2,8 +2,6 @@
require_once('../application/utils.inc.php');
$g_oConfig = new Config('../config-itop.php');
MetaModel::Startup('../config-itop.php');
MetaModel::Startup(ITOP_CONFIG_FILE);
?>

View File

@@ -27,6 +27,10 @@ class UIWizard
*/
public function DisplayWizardStep($aStep, $iStepIndex, &$iMaxInputId, &$aFieldsMap, $bFinishEnabled = false)
{
if ($iStepIndex == 1) // one big form that contains everything, to make sure that the uploaded files are posted too
{
$this->m_oPage->add("<form method=\"post\" enctype=\"multipart/form-data\" action=\"../pages/UI.php\">\n");
}
$this->m_oPage->add("<div class=\"wizContainer\" id=\"wizStep$iStepIndex\" style=\"display:none;\">\n");
$this->m_oPage->add("<a name=\"step$iStepIndex\" />\n");
$aStates = MetaModel::EnumStates($this->m_sClass);
@@ -34,7 +38,7 @@ class UIWizard
$sJSHandlerCode = ''; // Javascript code to be executed each time this step of the wizard is entered
foreach($aStep as $sAttCode)
{
if ($sAttCode != 'finalclass') // Do not displa the attribute that stores the actual class name
if ($sAttCode != 'finalclass') // Do not display the attribute that stores the actual class name
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
$sAttLabel = $oAttDef->GetLabel();
@@ -107,7 +111,6 @@ $sJSHandlerCode
$this->m_oPage->add("<div class=\"wizContainer\" id=\"wizStep$iStepIndex\" style=\"display:none;\">\n");
$this->m_oPage->add("<a name=\"step$iStepIndex\" />\n");
$this->m_oPage->P("Final step: confirmation");
$this->m_oPage->add("<form method=\"post\" action=\"../pages/UI.php\">\n");
$this->m_oPage->add("<input type=\"hidden\" name=\"operation\" value=\"wizard_apply_new\" />\n");
$this->m_oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\" />\n");
$this->m_oPage->add("<input type=\"hidden\" id=\"wizard_json_obj\" name=\"json_obj\" value=\"\" />\n");
@@ -124,8 +127,8 @@ $sJSHandlerCode
$this->m_oPage->add("<div id=\"object_preview\">\n");
$this->m_oPage->add("</div>\n");
$this->m_oPage->add("<input type=\"submit\" value=\"Create ".MetaModel::GetName($this->m_sClass)."\" />\n");
$this->m_oPage->add("</form>\n");
$this->m_oPage->add("</div>\n");
$this->m_oPage->add("</form>\n");
}
/**
* Compute the order of the fields & pages in the wizard

View File

@@ -1,10 +1,15 @@
<?php
require_once('../core/config.class.inc.php');
define('CONFIGFILE', '../config.txt');
define('ITOP_CONFIG_FILE', '../config-itop.php');
class FileUploadException extends Exception
{
}
class utils
{
private static $m_aConfig = null;
private static $m_oConfig = null;
public static function ReadParam($sName, $defaultValue = "")
{
@@ -16,6 +21,75 @@ class utils
return isset($_POST[$sName]) ? $_POST[$sName] : $defaultValue;
}
/**
* Reads an uploaded file and turns it into an ormDocument object - Triggers an exception in case of error
* @param string $sName Name of the input used from uploading the file
* @return ormDocument The uploaded file (can be 'empty' if nothing was uploaded)
*/
public static function ReadPostedDocument($sName)
{
$oDocument = new ormDocument(); // an empty document
if(isset($_FILES[$sName]))
{
switch($_FILES[$sName]['error'])
{
case UPLOAD_ERR_OK:
$doc_content = file_get_contents($_FILES[$sName]['tmp_name']);
$sMimeType = $_FILES[$sName]['type'];
if (function_exists('finfo_file'))
{
// as of PHP 5.3 the fileinfo extension is bundled within PHP
// in which case we don't trust the mime type provided by the browser
$rInfo = @finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
if ($rInfo !== false)
{
$sType = @finfo_file($rInfo, $file);
if ( ($sType !== false)
&& is_string($sType)
&& (strlen($sType)>0))
{
$sMimeType = $sType;
}
}
@finfo_close($finfo);
}
$oDocument = new ormDocument($doc_content, $sMimeType, $_FILES[$sName]['name']);
break;
case UPLOAD_ERR_NO_FILE:
// no file to load, it's a normal case, just return an empty document
break;
case UPLOAD_ERR_FORM_SIZE:
case UPLOAD_ERR_INI_SIZE:
throw new FileUploadException("Uploaded file is too big. (Max allowed size is ".ini_get('upload_max_filesize').". Check you PHP configuration for upload_max_filesize.");
break;
case UPLOAD_ERR_PARTIAL:
throw new FileUploadException("File upload failed, file has been truncated.");
break;
case UPLOAD_ERR_NO_TMP_DIR:
throw new FileUploadException("Missing a temporary folder.");
break;
case UPLOAD_ERR_CANT_WRITE:
throw new FileUploadException("Unable to write the temporary file to the disk (upload_tmp_dir = ".ini_get('upload_tmp_dir').")");
break;
case UPLOAD_ERR_EXTENSION:
throw new FileUploadException("File upload stopped by extension. (Original file name: ".$_FILES[$sName]['name'].")");
break;
default:
throw new FileUploadException("File upload failed, unknown cause (Error code = ".$_FILES[$sName]['error'].")");
break;
}
}
return $oDocument;
}
public static function GetNewTransactionId()
{
// TO DO implement the real mechanism here
@@ -34,47 +108,44 @@ class utils
return file_get_contents($sFileName);
}
public static function ReadConfig()
/**
* Get access to the application config file
* @param none
* @return Config The Config object initialized from the application config file
*/
public static function GetConfig()
{
self::$m_aConfig = array();
$sConfigContents = self::ReadFromFile(CONFIGFILE);
if (!$sConfigContents) throw new Exception("Could not load file ".CONFIGFILE);
foreach (explode("\n", $sConfigContents) as $sLine)
if (self::$m_oConfig == null)
{
$sLine = trim($sLine);
if (($iPos = strpos($sLine, '#')) !== false)
{
// strip out the end of the line right after the #
$sLine = substr($sLine, 0, $iPos);
}
$aMatches = array();
if (preg_match("@(\\S+.*)=\s*(\S+.*)@", $sLine, $aMatches))
{
$sParamName = trim($aMatches[1]);
$sParamValue = trim($aMatches[2]);
self::$m_aConfig[$sParamName] = $sParamValue;
}
self::$m_oConfig = new Config(ITOP_CONFIG_FILE);
}
return self::$m_oConfig;
}
public static function GetConfig($sParamName, $defaultValue = "")
/**
* Helper function to convert a value expressed in a 'user friendly format'
* as in php.ini, e.g. 256k, 2M, 1G etc. Into a number of bytes
* @param mixed $value The value as read from php.ini
* @return number
*/
public static function ConvertToBytes( $value )
{
if (is_null(self::$m_aConfig))
$iReturn = $value;
if ( !is_numeric( $value ) )
{
self::ReadConfig();
}
if (array_key_exists($sParamName, self::$m_aConfig))
{
return self::$m_aConfig[$sParamName];
}
else
{
return $defaultValue;
}
}
$iLength = strlen( $value );
$iReturn = substr( $value, 0, $iLength - 1 );
$sUnit = strtoupper( substr( $value, $iLength - 1 ) );
switch ( $sUnit )
{
case 'G':
$iReturn *= 1024;
case 'M':
$iReturn *= 1024;
case 'K':
$iReturn *= 1024;
}
}
return $iReturn;
}
}
?>

View File

@@ -8,8 +8,12 @@ class WizardHelper
public function __construct()
{
}
public function GetTargetObject()
/**
* Constructs the PHP target object from the parameters sent to the web page by the wizard
* @param boolean $bReadUploadedFiles True to also ready any uploaded file (for blob/document fields)
* @return object
*/
public function GetTargetObject($bReadUploadedFiles = false)
{
$oObj = MetaModel::NewObject($this->m_aData['m_sClass']);
foreach($this->m_aData['m_aCurrentValues'] as $iIndex => $value)
@@ -60,6 +64,20 @@ class WizardHelper
$oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray);
$oObj->Set($sAttCode, $oSet);
}
else if ( $oAttDef->GetEditClass() == 'Document' )
{
if ($bReadUploadedFiles)
{
$oDocument = utils::ReadPostedDocument('file_'.$sAttCode);
$oObj->Set($sAttCode, $oDocument);
}
else
{
// Create a new empty document, just for displaying the file name
$oDocument = new ormDocument(null, '', $value);
$oObj->Set($sAttCode, $oDocument);
}
}
else if (($oAttDef->IsExternalKey()) && (!empty($value)) )
{
// For external keys: load the target object so that external fields

View File

@@ -406,7 +406,7 @@ class bizDocument extends logRealObject
MetaModel::Init_AddFilterFromAttribute("description");
MetaModel::Init_SetZListItems('details', array('name', 'status', 'org_id', 'scope', 'description', 'contents')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('name', 'status', 'org_id', 'scope')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', array('name', 'status', 'org_id', 'scope', 'contents')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('name', 'status', 'scope')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('name', 'status', 'scope')); // Criteria of the advanced search form
@@ -415,55 +415,6 @@ class bizDocument extends logRealObject
}
////////////////////////////////////////////////////////////////////////////////////
/**
* A version of an electronic document
*/
////////////////////////////////////////////////////////////////////////////////////
class bizDocVersion extends cmdbAbstractObject
{
public static function Init()
{
global $oAllowedStatuses;
$aParams = array
(
"category" => "bizmodel,searchable",
"name" => "DocumentVersion",
"description" => "A version of a document",
"key_type" => "autoincrement",
"key_label" => "id",
"name_attcode" => "version_number",
"state_attcode" => "",
"reconc_keys" => array("document", "version_number"),
"db_table" => "document_versions",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "../business/templates/default.html",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_AddAttribute(new AttributeExternalKey("document", array("targetclass"=>"bizDocument", "label"=>"Document", "description"=>"The main document", "allowed_values"=>null, "sql"=>"document_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeExternalField("docname", array("label"=>"Document Name", "description"=>"name of the document", "allowed_values"=>null, "extkey_attcode"=> 'document', "target_attcode"=>"name")));
MetaModel::Init_AddAttribute(new AttributeString("version_number", array("label"=>"Version", "description"=>"Version identifier", "allowed_values"=>null, "sql"=>"version_number", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("label"=>"Status", "description"=>"Status", "allowed_values"=>$oAllowedStatuses, "sql"=>"status", "default_value"=>"implementation", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("type", array("label"=>"Type", "description"=>"Type", "allowed_values"=>new ValueSetEnum("local,draft"), "sql"=>"type", "default_value"=>"local", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeURL("url", array("label"=>"URL", "description"=>"Hyperlink to the version", "allowed_values"=>null, "target"=>"_blank", "sql"=>"url", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("label"=>"Description", "description"=>"Service Description", "allowed_values"=>null, "sql"=>"description", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddFilterFromAttribute("document");
MetaModel::Init_AddFilterFromAttribute("docname");
MetaModel::Init_AddFilterFromAttribute("version_number");
MetaModel::Init_AddFilterFromAttribute("status");
MetaModel::Init_AddFilterFromAttribute("type");
MetaModel::Init_AddFilterFromAttribute("description");
MetaModel::Init_SetZListItems('details', array('document', 'status', 'version_number', 'type','url','description')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('version_number', 'status', 'type', 'url')); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', array('docname', 'type')); // Criteria of the std search form
MetaModel::Init_SetZListItems('advanced_search', array('docname', 'type')); // Criteria o
}
}
////////////////////////////////////////////////////////////////////////////////////
/**
* n-n link between any Object and a Document

View File

@@ -5,9 +5,3 @@
</div>
<img src="../images/folder_documents.png" style="margin-top:-10px; margin-right:10px; float:right">
<itopblock blockclass="DisplayBlock" asynchronous="true" type="bare_details" encoding="text/oql">SELECT $class$ WHERE id = $pkey$</itopblock>
<itoptabs>
<itoptab name="Versions">
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT bizDocVersion WHERE document = $pkey$</itopblock>
</itoptab>
</itoptabs>

View File

@@ -1233,7 +1233,20 @@ class AttributeBlob extends AttributeDefinition
public function GetAsHTML($value)
{
return $value->GetAsHTML();
if (is_object($value))
{
return $value->GetAsHTML();
}
}
public function GetAsCSV($sValue, $sSeparator = ';', $sSepEscape = ',')
{
return ''; // Not exportable in CSV !
}
public function GetAsXML($value)
{
return ''; // Not exportable in XML, or as CDATA + some subtags ??
}
}

View File

@@ -347,7 +347,11 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
$sAttName = $oAttDef->GetLabel();
$oPrevDoc = $this->Get('prevdata');
$sDocView = $oPrevDoc->GetAsHtml();
$sResult = "$sAttName changed (previous value: $sDocView)";
$sDocView .= "<br/>Open in New Window: ".$oPrevDoc->GetDisplayLink(get_class($this), $this->GetKey(), 'prevdata').", \n";
$sDocView .= "Download: ".$oPrevDoc->GetDownloadLink(get_class($this), $this->GetKey(), 'prevdata')."\n";
//$sDocView = $oPrevDoc->GetDisplayInline(get_class($this), $this->GetKey(), 'prevdata');
$sResult = "$sAttName changed, previous value: $sDocView";
}
return $sResult;
}

View File

@@ -428,6 +428,23 @@ class CMDBSource
mysql_free_result($result);
return $aRows;
}
/**
* Returns the value of the specified server variable
* @param string $sVarName Name of the server variable
* @return mixed Current value of the variable
*/
public static function GetServerVariable($sVarName)
{
$result = '';
$sSql = "SELECT @@$sVarName as theVar";
$aRows = self::QueryToArray($sSql);
if (count($aRows) > 0)
{
$result = $aRows[0]['theVar'];
}
return $result;
}
}

View File

@@ -33,6 +33,11 @@ class ormDocument
return MyHelpers::beautifulstr($this->m_data, 100, true);
}
public function IsEmpty()
{
return ($this->m_data == null);
}
public function GetMimeType()
{
return $this->m_sMimeType;
@@ -59,20 +64,72 @@ class ormDocument
public function GetAsHTML()
{
$data = $this->GetData();
$sResult = '';
if ($this->IsEmpty())
{
// If the filename is not empty, display it, this is used
// by the creation wizard while the file has not yet been uploaded
$sResult = $this->GetFileName();
}
else
{
$data = $this->GetData();
$sResult = $this->GetFileName().' [ '.$this->GetMimeType().', size: '.strlen($data).' byte(s) ]';
}
return $sResult;
}
/**
* Returns an HTML fragment that will display the document *inline* (if possible)
* @return string
*/
public function GetDisplayInline($sClass, $Id, $sAttCode)
{
switch ($this->GetMainMimeType())
{
case 'text':
return "<pre>".htmlentities(MyHelpers::beautifulstr($data, 1000, true))."</pre>\n";
case 'text':
case 'html':
$data = $this->GetData();
switch($this->GetMimeType())
{
case 'text/html':
case 'text/xml':
return "<iframe src=\"../pages/ajax.render.php?operation=display_document&class=$sClass&id=$Id&field=$sAttCode\" width=\"100%\" height=\"400\">Loading...</iframe>\n";
default:
return "<pre>".htmlentities(MyHelpers::beautifulstr($data, 1000, true))."</pre>\n";
}
break; // Not really needed, but...
case 'application':
return "binary data for ".$this->GetMimeType().', size: '.strlen($data).' byte(s).';
case 'html':
default:
return "<div>".htmlentities(MyHelpers::beautifulstr($data, 1000, true))."</div>\n";
case 'application':
switch($this->GetMimeType())
{
case 'application/pdf':
return "<iframe src=\"../pages/ajax.render.php?operation=display_document&class=$sClass&id=$Id&field=$sAttCode\" width=\"100%\" height=\"400\">Loading...</iframe>\n";
}
break;
case 'image':
return "<img src=\"../pages/ajax.render.php?operation=display_document&class=$sClass&id=$Id&field=$sAttCode\" />\n";
}
}
/**
* Returns an hyperlink to display the document *inline*
* @return string
*/
public function GetDisplayLink($sClass, $Id, $sAttCode)
{
return "<a href=\"../pages/ajax.render.php?operation=display_document&class=$sClass&id=$Id&field=$sAttCode\" target=\"_blank\" >".$this->GetFileName()."</a>\n";
}
/**
* Returns an hyperlink to download the document (content-disposition: attachment)
* @return string
*/
public function GetDownloadLink($sClass, $Id, $sAttCode)
{
return "<a href=\"../pages/ajax.render.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode\">".$this->GetFileName()."</a>\n";
}
}
?>

View File

@@ -17,3 +17,15 @@ function ReloadTruncatedList(divId, sSerializedFilter, sExtraParams)
}
);
}
/**
* Update the display and value of a file input widget when the user picks a new file
*/
function UpdateFileName(id, sNewFileName)
{
var aPath = sNewFileName.split('\\');
var sNewFileName = aPath[aPath.length-1];
$('#'+id).val(sNewFileName);
$('#name_'+id).text(sNewFileName);
}

View File

@@ -18,6 +18,7 @@ function WizardHelper(sClass)
this.m_oData.m_oFieldsMap = oFieldsMap;
}
this.SetFieldsCount = function (count)
{
this.m_oData.m_iFieldsCount = count;

View File

@@ -459,6 +459,17 @@ switch($operation)
$bObjectModified = true;
}
}
else if ($oAttDef->GetEditClass() == 'Document')
{
// There should be an uploaded file with the named attr_<attCode>
$oDocument = utils::ReadPostedDocument('file_'.$sAttCode);
if (!$oDocument->IsEmpty())
{
// A new file has been uploaded
$oObj->Set($sAttCode, $oDocument);
$bObjectModified = true;
}
}
else if (!$oAttDef->IsExternalField())
{
$rawValue = utils::ReadPostedParam("attr_$sAttCode", null);
@@ -826,7 +837,7 @@ switch($operation)
}
else
{
$oObj = $oWizardHelper->GetTargetObject();
$oObj = $oWizardHelper->GetTargetObject(true /* read uploaded files */);
if (is_object($oObj))
{
$sClass = get_class($oObj);

View File

@@ -269,9 +269,60 @@ switch($operation)
$oPage->add('<option title="Here is more information..." value="'.$oObj->GetKey().'">'.$oObj->GetDisplayName().'</option>');
}
break;
case 'display_document':
$id = utils::ReadParam('id', '');
$sField = utils::ReadParam('field', '');
if (!empty($sClass) && !empty($id) && !empty($sField))
{
DownloadDocument($oPage, $oContext, $sClass, $id, $sField, 'inline');
}
break;
case 'download_document':
$id = utils::ReadParam('id', '');
$sField = utils::ReadParam('field', '');
if (!empty($sClass) && !empty($id) && !empty($sField))
{
DownloadDocument($oPage, $oContext, $sClass, $id, $sField, 'attachement');
}
break;
default:
$oPage->p("Invalid query.");
}
$oPage->output();
/**
* Downloads a document to the browser, either as 'inline' or 'attachment'
*
* @param web_page $oPage The web page for the output
* @param UserContext $oContext The current User/security context to retreive the objects
* @param string $sClass Class name of the object
* @param mixed $id Identifier of the object
* @param string $sAttCode Name of the attribute containing the document to download
* @param string $sContentDisposition Either 'inline' or 'attachment'
* @return none
*/
function DownloadDocument(web_page $oPage, UserContext $oContext, $sClass, $id, $sAttCode, $sContentDisposition = 'attachement')
{
try
{
$oObj = $oContext->GetObject($sClass, $id);
if (is_object($oObj))
{
$oDocument = $oObj->Get($sAttCode);
if (is_object($oDocument))
{
$oPage->add_header('Content-type: '.$oDocument->GetMimeType());
$oPage->add_header('Content-Disposition: '.$sContentDisposition.'; filename="'.$oDocument->GetFileName().'"');
$oPage->add($oDocument->GetData());
}
}
}
catch(Exception $e)
{
$oPage->p($e->getMessage());
}
}
?>

View File

@@ -23,6 +23,7 @@ $oP = new setup_web_page('iTop configuration wizard');
*/
function CheckPHPVersion(setup_web_page $oP)
{
$bResult = true;
$oP->log('Info - CheckPHPVersion');
if (version_compare(phpversion(), PHP_MIN_VERSION, '>='))
{
@@ -57,9 +58,38 @@ function CheckPHPVersion(setup_web_page $oP)
if (count($aMissingExtensions) > 0)
{
$oP->error("Missing PHP extension(s): ".implode(', ', $aMissingExtensionsLinks).".");
return false;
$bResult = false;
}
return true;
// Check some ini settings here
if (!ini_get('file_uploads'))
{
$oP->error("Files upload is not allowed on this server (file_uploads = ".ini_get('file_uploads').").");
$bResult = false;
}
$sUploadTmpDir = ini_get('upload_tmp_dir');
if (empty($sUploadTmpDir))
{
$oP->error("Temporary directory for files upload is not defined (upload_tmp_dir)");
$bResult = false;
}
if (!ini_get('upload_max_filesize'))
{
$oP->error("File upload is not allowed on this server (file_uploads = ".ini_get('file_uploads').").");
}
$iMaxFileUploads = ini_get('max_file_uploads');
if (!empty($iMaxFileUploads) && ($iMaxFileUploads < 1))
{
$oP->error("File upload is not allowed on this server (max_file_uploads = ".ini_get('max_file_uploads').").");
$bResult = false;
}
$oP->log("Info - upload_max_filesize: ".ini_get('upload_max_filesize'));
$oP->log("Info - upload_tmp_dir: $sUploadTmpDir");
$oP->log("Info - max_file_uploads: ".ini_get('max_file_uploads'));
return $bResult;
}
/**
@@ -80,6 +110,26 @@ function CheckServerConnection(setup_web_page $oP, $sDBServer, $sDBUser, $sDBPwd
if (version_compare($sDBVersion, MYSQL_MIN_VERSION, '>='))
{
$oP->ok("Current MySQL version ($sDBVersion), greater than minimum required version (".MYSQL_MIN_VERSION.")");
// Check some server variables
$iMaxAllowedPacket = $oDBSource->GetServerVariable('max_allowed_packet');
$iMaxUploadSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
if ($iMaxAllowedPacket >= (500 + $iMaxUploadSize)) // Allow some space for the query + the file to upload
{
$oP->ok("MySQL server's max_allowed_packet is big enough.");
}
else if($iMaxAllowedPacket < $iMaxUploadSize)
{
$oP->warning("MySQL server's max_allowed_packet ($iMaxAllowedPacket) is not big enough.");
$oP->warning("Consider setting it to at least ".(500 + $iMaxUploadSize).".");
}
$oP->log("Info - MySQL max_allowed_packet: $iMaxAllowedPacket");
$iMaxConnections = $oDBSource->GetServerVariable('max_connections');
if ($iMaxConnections < 5)
{
$oP->warning("MySQL server's max_connections ($iMaxConnections) is not enough.");
$oP->warning("Consider setting it to at least 5.");
}
$oP->log("Info - MySQL max_connections: ".($oDBSource->GetServerVariable('max_connections')));
}
else
{