Moving the datamodel to its new place
SVN:trunk[2240]
108
datamodels/1.x/itop-attachments/ajax.attachment.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Handles various ajax requests
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*/
|
||||
|
||||
require_once('../../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/application/webpage.class.inc.php');
|
||||
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
|
||||
|
||||
try
|
||||
{
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
// require_once(APPROOT.'/application/user.preferences.class.inc.php');
|
||||
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(false /* bMustBeAdmin */, true /* IsAllowedToPortalUsers */); // Check user rights and prompt if needed
|
||||
|
||||
$oPage = new ajax_page("");
|
||||
$oPage->no_cache();
|
||||
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
switch($sOperation)
|
||||
{
|
||||
case 'add':
|
||||
$aResult = array(
|
||||
'error' => '',
|
||||
'att_id' => 0,
|
||||
'msg' => ''
|
||||
);
|
||||
$sObjClass = stripslashes(utils::ReadParam('obj_class', '', false, 'class'));
|
||||
$sTempId = utils::ReadParam('temp_id', '');
|
||||
if (empty($sObjClass))
|
||||
{
|
||||
$aResult['error'] = "Missing argument 'obj_class'";
|
||||
}
|
||||
elseif (empty($sTempId))
|
||||
{
|
||||
$aResult['error'] = "Missing argument 'temp_id'";
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
$oDoc = utils::ReadPostedDocument('file');
|
||||
$oAttachment = MetaModel::NewObject('Attachment');
|
||||
$oAttachment->Set('expire', time() + 3600); // one hour...
|
||||
$oAttachment->Set('temp_id', $sTempId);
|
||||
$oAttachment->Set('item_class', $sObjClass);
|
||||
$oAttachment->SetDefaultOrgId();
|
||||
$oAttachment->Set('contents', $oDoc);
|
||||
$iAttId = $oAttachment->DBInsert();
|
||||
|
||||
$aResult['msg'] = $oDoc->GetFileName();
|
||||
$aResult['icon'] = utils::GetAbsoluteUrlAppRoot().AttachmentPlugIn::GetFileIcon($oDoc->GetFileName());
|
||||
$aResult['att_id'] = $iAttId;
|
||||
}
|
||||
catch (FileUploadException $e)
|
||||
{
|
||||
$aResult['error'] = $e->GetMessage();
|
||||
}
|
||||
}
|
||||
$oPage->add(json_encode($aResult));
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
$iAttachmentId = utils::ReadParam('att_id', '');
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id = :id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('id' => $iAttachmentId));
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oAttachment->DBDelete();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$oPage->p("Missing argument 'operation'");
|
||||
}
|
||||
|
||||
$oPage->output();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
echo $e->GetMessage();
|
||||
IssueLog::Error($e->getMessage());
|
||||
}
|
||||
?>
|
||||
191
datamodels/1.x/itop-attachments/ajaxfileupload.js
Normal file
@@ -0,0 +1,191 @@
|
||||
|
||||
jQuery.extend(
|
||||
{
|
||||
createUploadIframe: function(id, uri)
|
||||
{
|
||||
//create frame
|
||||
var frameId = 'jUploadFrame' + id;
|
||||
var iframeHtml = '<iframe id="' + frameId + '" name="' + frameId + '" style="position:absolute; top:-9999px; left:-9999px"';
|
||||
if(window.ActiveXObject)
|
||||
{
|
||||
if(typeof uri== 'boolean')
|
||||
{
|
||||
iframeHtml += ' src="' + 'javascript:false' + '"';
|
||||
}
|
||||
else if(typeof uri== 'string')
|
||||
{
|
||||
iframeHtml += ' src="' + uri + '"';
|
||||
}
|
||||
}
|
||||
iframeHtml += ' />';
|
||||
jQuery(iframeHtml).appendTo(document.body);
|
||||
|
||||
return jQuery('#' + frameId).get(0);
|
||||
},
|
||||
createUploadForm: function(id, fileElementId)
|
||||
{
|
||||
//create form
|
||||
var formId = 'jUploadForm' + id;
|
||||
var fileId = 'jUploadFile' + id;
|
||||
var form = jQuery('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
|
||||
var oldElement = jQuery('#' + fileElementId);
|
||||
var newElement = jQuery(oldElement).clone();
|
||||
jQuery(oldElement).attr('id', fileId);
|
||||
jQuery(oldElement).before(newElement);
|
||||
jQuery(oldElement).appendTo(form);
|
||||
//set attributes
|
||||
jQuery(form).css('position', 'absolute');
|
||||
jQuery(form).css('top', '-1200px');
|
||||
jQuery(form).css('left', '-1200px');
|
||||
jQuery(form).appendTo('body');
|
||||
return form;
|
||||
},
|
||||
|
||||
ajaxFileUpload: function(s) {
|
||||
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
|
||||
s = jQuery.extend({}, jQuery.ajaxSettings, s);
|
||||
var id = new Date().getTime();
|
||||
var form = jQuery.createUploadForm(id, s.fileElementId);
|
||||
var io = jQuery.createUploadIframe(id, s.secureuri);
|
||||
var frameId = 'jUploadFrame' + id;
|
||||
var formId = 'jUploadForm' + id;
|
||||
// Watch for a new set of requests
|
||||
if ( s.global && ! jQuery.active++ )
|
||||
{
|
||||
jQuery.event.trigger( "ajaxStart" );
|
||||
}
|
||||
var requestDone = false;
|
||||
// Create the request object
|
||||
var xml = {};
|
||||
if ( s.global )
|
||||
jQuery.event.trigger("ajaxSend", [xml, s]);
|
||||
// Wait for a response to come back
|
||||
var uploadCallback = function(isTimeout)
|
||||
{
|
||||
var io = document.getElementById(frameId);
|
||||
try
|
||||
{
|
||||
if(io.contentWindow)
|
||||
{
|
||||
xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
|
||||
xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
|
||||
|
||||
}else if(io.contentDocument)
|
||||
{
|
||||
xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
|
||||
xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
|
||||
}
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
jQuery.handleError(s, xml, null, e);
|
||||
}
|
||||
if ( xml || isTimeout == "timeout")
|
||||
{
|
||||
requestDone = true;
|
||||
var status;
|
||||
try {
|
||||
status = isTimeout != "timeout" ? "success" : "error";
|
||||
// Make sure that the request was successful or notmodified
|
||||
if ( status != "error" )
|
||||
{
|
||||
// process the data (runs the xml through httpData regardless of callback)
|
||||
var data = jQuery.uploadHttpData( xml, s.dataType );
|
||||
// If a local callback was specified, fire it and pass it the data
|
||||
if ( s.success )
|
||||
s.success( data, status );
|
||||
|
||||
// Fire the global callback
|
||||
if( s.global )
|
||||
jQuery.event.trigger( "ajaxSuccess", [xml, s] );
|
||||
} else
|
||||
jQuery.handleError(s, xml, status);
|
||||
} catch(e)
|
||||
{
|
||||
status = "error";
|
||||
jQuery.handleError(s, xml, status, e);
|
||||
}
|
||||
|
||||
// The request was completed
|
||||
if( s.global )
|
||||
jQuery.event.trigger( "ajaxComplete", [xml, s] );
|
||||
|
||||
// Handle the global AJAX counter
|
||||
if ( s.global && ! --jQuery.active )
|
||||
jQuery.event.trigger( "ajaxStop" );
|
||||
|
||||
// Process result
|
||||
if ( s.complete )
|
||||
s.complete(xml, status);
|
||||
|
||||
jQuery(io).unbind();
|
||||
|
||||
setTimeout(function()
|
||||
{ try
|
||||
{
|
||||
jQuery(io).remove();
|
||||
jQuery(form).remove();
|
||||
|
||||
} catch(e)
|
||||
{
|
||||
jQuery.handleError(s, xml, null, e);
|
||||
}
|
||||
|
||||
}, 100)
|
||||
|
||||
xml = null
|
||||
|
||||
}
|
||||
}
|
||||
// Timeout checker
|
||||
if ( s.timeout > 0 )
|
||||
{
|
||||
setTimeout(function(){
|
||||
// Check to see if the request is still happening
|
||||
if( !requestDone ) uploadCallback( "timeout" );
|
||||
}, s.timeout);
|
||||
}
|
||||
try
|
||||
{
|
||||
|
||||
var form = jQuery('#' + formId);
|
||||
jQuery(form).attr('action', s.url);
|
||||
jQuery(form).attr('method', 'POST');
|
||||
jQuery(form).attr('target', frameId);
|
||||
if(form.encoding)
|
||||
{
|
||||
jQuery(form).attr('encoding', 'multipart/form-data');
|
||||
}
|
||||
else
|
||||
{
|
||||
jQuery(form).attr('enctype', 'multipart/form-data');
|
||||
}
|
||||
jQuery(form).submit();
|
||||
|
||||
} catch(e)
|
||||
{
|
||||
jQuery.handleError(s, xml, null, e);
|
||||
}
|
||||
|
||||
jQuery('#' + frameId).load(uploadCallback );
|
||||
return {abort: function () {}};
|
||||
|
||||
},
|
||||
|
||||
uploadHttpData: function( r, type ) {
|
||||
var data = !type;
|
||||
data = type == "xml" || data ? r.responseXML : r.responseText;
|
||||
// If the type is "script", eval it in global context
|
||||
if ( type == "script" )
|
||||
jQuery.globalEval( data );
|
||||
// Get the JavaScript object, if JSON is used.
|
||||
if ( type == "json" )
|
||||
eval( "data = " + data );
|
||||
// evaluate scripts within html
|
||||
if ( type == "html" )
|
||||
jQuery("<div>").html(data).evalScripts();
|
||||
|
||||
return data;
|
||||
}
|
||||
})
|
||||
|
||||
200
datamodels/1.x/itop-attachments/datamodel.itop-attachments.xml
Normal file
@@ -0,0 +1,200 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<classes>
|
||||
<class id="Attachment" _delta="define">
|
||||
<parent>DBObject</parent>
|
||||
<properties>
|
||||
<comment><![CDATA[/**
|
||||
* Module attachments
|
||||
*
|
||||
* A quick and easy way to upload and attach files to *any* (see Configuration below) object in the CMBD in one click
|
||||
*
|
||||
* Configuration: the list of classes for which the "Attachments" tab is visible is defined via the module's 'allowed_classes'
|
||||
* configuration parameter. By default the tab is active for all kind of Tickets.
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*/]]></comment>
|
||||
<category>addon,bizmodel</category>
|
||||
<abstract>false</abstract>
|
||||
<key_type>autoincrement</key_type>
|
||||
<db_table>attachment</db_table>
|
||||
<db_key_field>id</db_key_field>
|
||||
<db_final_class_field></db_final_class_field>
|
||||
<naming>
|
||||
<format>%1$s %2$s</format>
|
||||
<attributes>
|
||||
<attribute id="item_class"/>
|
||||
<attribute id="temp_id"/>
|
||||
</attributes>
|
||||
</naming>
|
||||
<display_template></display_template>
|
||||
<icon></icon>
|
||||
<reconciliation>
|
||||
<attributes>
|
||||
<attribute id=""/>
|
||||
</attributes>
|
||||
</reconciliation>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="expire" xsi:type="AttributeDateTime">
|
||||
<sql>expire</sql>
|
||||
<default_value></default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="temp_id" xsi:type="AttributeString">
|
||||
<sql>temp_id</sql>
|
||||
<default_value></default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="item_class" xsi:type="AttributeString">
|
||||
<sql>item_class</sql>
|
||||
<default_value></default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="item_id" xsi:type="AttributeString">
|
||||
<sql>item_id</sql>
|
||||
<default_value></default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="item_org_id" xsi:type="AttributeInteger">
|
||||
<sql>item_org_id</sql>
|
||||
<default_value>0</default_value>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="contents" xsi:type="AttributeBlob"/>
|
||||
</fields>
|
||||
<methods>
|
||||
<method id="MapContextParam">
|
||||
<comment><![CDATA[/**
|
||||
* Maps the given context parameter name to the appropriate filter/search code for this class
|
||||
* @param string $sContextParam Name of the context parameter, e.g. 'org_id'
|
||||
* @return string Filter code, e.g. 'customer_id'
|
||||
*/]]></comment>
|
||||
<static>true</static>
|
||||
<access>public</access>
|
||||
<type>Overload-ExNihilo</type>
|
||||
<code><![CDATA[ public static function MapContextParam($sContextParam)
|
||||
{
|
||||
if ($sContextParam == 'org_id')
|
||||
{
|
||||
return 'item_org_id';
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="SetItem">
|
||||
<comment><![CDATA[/**
|
||||
* Set/Update all of the '_item' fields
|
||||
* @param object $oItem Container item
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-ExNihilo</type>
|
||||
<code><![CDATA[ public function SetItem($oItem, $bUpdateOnChange = false)
|
||||
{
|
||||
$sClass = get_class($oItem);
|
||||
$iItemId = $oItem->GetKey();
|
||||
|
||||
$this->Set('item_class', $sClass);
|
||||
$this->Set('item_id', $iItemId);
|
||||
|
||||
$aCallSpec = array($sClass, 'MapContextParam');
|
||||
if (is_callable($aCallSpec))
|
||||
{
|
||||
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
|
||||
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
$iOrgId = $oItem->Get($sAttCode);
|
||||
if ($iOrgId > 0)
|
||||
{
|
||||
if ($iOrgId != $this->Get('item_org_id'))
|
||||
{
|
||||
$this->Set('item_org_id', $iOrgId);
|
||||
if ($bUpdateOnChange)
|
||||
{
|
||||
$this->DBUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="SetDefaultOrgId">
|
||||
<comment>/**
|
||||
* Give a default value for item_org_id (if relevant...)
|
||||
* @return void
|
||||
*/</comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-ExNihilo</type>
|
||||
<code><![CDATA[ public function SetDefaultOrgId()
|
||||
{
|
||||
// First check that the organization CAN be fetched from the target class
|
||||
//
|
||||
$sClass = $this->Get('item_class');
|
||||
$aCallSpec = array($sClass, 'MapContextParam');
|
||||
if (is_callable($aCallSpec))
|
||||
{
|
||||
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
|
||||
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
// Second: check that the organization CAN be fetched from the current user
|
||||
//
|
||||
if (MetaModel::IsValidClass('Person'))
|
||||
{
|
||||
$aCallSpec = array($sClass, 'MapContextParam');
|
||||
if (is_callable($aCallSpec))
|
||||
{
|
||||
$sAttCode = call_user_func($aCallSpec, 'org_id'); // Returns null when there is no mapping for this parameter
|
||||
if (MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
// OK - try it
|
||||
//
|
||||
$oCurrentPerson = MetaModel::GetObject('Person', UserRights::GetContactId(), false);
|
||||
if ($oCurrentPerson)
|
||||
{
|
||||
$this->Set('item_org_id', $oCurrentPerson->Get($sAttCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item>temp_id</item>
|
||||
<item>item_class</item>
|
||||
<item>item_id</item>
|
||||
<item>item_org_id</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
<items>
|
||||
<item>temp_id</item>
|
||||
<item>item_class</item>
|
||||
<item>item_id</item>
|
||||
</items>
|
||||
</search>
|
||||
<list>
|
||||
<items>
|
||||
<item>temp_id</item>
|
||||
<item>item_class</item>
|
||||
<item>item_id</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
</classes>
|
||||
</itop_design>
|
||||
41
datamodels/1.x/itop-attachments/de.dict.attachments.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @author Stephan Rosenke <stephan.rosenke@itomig.de>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Attachments:TabTitle_Count' => 'Attachments (%1$d)',
|
||||
'Attachments:EmptyTabTitle' => 'Attachments',
|
||||
'Attachments:FieldsetTitle' => 'Attachments',
|
||||
'Attachments:DeleteBtn' => 'Löschen',
|
||||
'Attachments:History_File_Added' => 'Attachment %1$s hinzugefügt.',
|
||||
'Attachments:History_File_Removed' => 'Attachment %1$s entfernt.',
|
||||
'Attachments:AddAttachment' => 'Attachment hinzufügen: ',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'Datei-Upload auf diesem System NICHT erlaubt.',
|
||||
'Attachment:Max_Go' => '(Maximale Datei-Größe: %1$s Go)',
|
||||
'Attachment:Max_Mo' => '(Maximale Datei-Größe: %1$s Mo)',
|
||||
'Attachment:Max_Ko' => '(Maximale Datei-Größe: %1$s Ko)',
|
||||
'Attachments:NoAttachment' => 'Kein Attachment.',
|
||||
));
|
||||
?>
|
||||
40
datamodels/1.x/itop-attachments/en.dict.attachments.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Attachments:TabTitle_Count' => 'Attachments (%1$d)',
|
||||
'Attachments:EmptyTabTitle' => 'Attachments',
|
||||
'Attachments:FieldsetTitle' => 'Attachments',
|
||||
'Attachments:DeleteBtn' => 'Delete',
|
||||
'Attachments:History_File_Added' => 'Attachment %1$s added.',
|
||||
'Attachments:History_File_Removed' => 'Attachment %1$s removed.',
|
||||
'Attachments:AddAttachment' => 'Add attachment: ',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'File upload in NOT allowed on this system.',
|
||||
'Attachment:Max_Go' => '(Maximum file size: %1$s Go)',
|
||||
'Attachment:Max_Mo' => '(Maximum file size: %1$s Mo)',
|
||||
'Attachment:Max_Ko' => '(Maximum file size: %1$s Ko)',
|
||||
'Attachments:NoAttachment' => 'No attachment. ',
|
||||
));
|
||||
?>
|
||||
40
datamodels/1.x/itop-attachments/fr.dict.attachments.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||
*/
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Attachments:TabTitle_Count' => 'Pièces jointes (%1$d)',
|
||||
'Attachments:EmptyTabTitle' => 'Pièces jointes',
|
||||
'Attachments:FieldsetTitle' => 'Pièces jointes',
|
||||
'Attachments:DeleteBtn' => 'Supprimer',
|
||||
'Attachments:History_File_Added' => 'Ajout de la pièce jointe: %1$s.',
|
||||
'Attachments:History_File_Removed' => 'Suppression de la pièce jointe: %1$s.',
|
||||
'Attachments:AddAttachment' => 'Ajouter une pièce jointe: ',
|
||||
'Attachments:UploadNotAllowedOnThisSystem' => 'Le téléchargement de fichiers est interdit sur ce système.',
|
||||
'Attachment:Max_Go' => '(Taille de fichier max.: %1$s Gb)',
|
||||
'Attachment:Max_Mo' => '(Taille de fichier max.: %1$s Mb)',
|
||||
'Attachment:Max_Ko' => '(Taille de fichier max.: %1$s Kb)',
|
||||
'Attachments:NoAttachment' => 'Aucune pièce jointe.',
|
||||
));
|
||||
?>
|
||||
BIN
datamodels/1.x/itop-attachments/icons/doc.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
datamodels/1.x/itop-attachments/icons/document.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
datamodels/1.x/itop-attachments/icons/html.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
datamodels/1.x/itop-attachments/icons/image.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
datamodels/1.x/itop-attachments/icons/odp.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
datamodels/1.x/itop-attachments/icons/ods.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
datamodels/1.x/itop-attachments/icons/odt.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
datamodels/1.x/itop-attachments/icons/pdf.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
datamodels/1.x/itop-attachments/icons/ppt.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
datamodels/1.x/itop-attachments/icons/rtf.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
datamodels/1.x/itop-attachments/icons/txt.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
datamodels/1.x/itop-attachments/icons/xls.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
datamodels/1.x/itop-attachments/icons/zip.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
560
datamodels/1.x/itop-attachments/main.attachments.php
Normal file
@@ -0,0 +1,560 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
class AttachmentPlugIn implements iApplicationUIExtension, iApplicationObjectExtension
|
||||
{
|
||||
public function OnDisplayProperties($oObject, WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
if ($this->GetAttachmentsPosition() == 'properties')
|
||||
{
|
||||
$this->DisplayAttachments($oObject, $oPage, $bEditMode);
|
||||
}
|
||||
}
|
||||
|
||||
public function OnDisplayRelations($oObject, WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
if ($this->GetAttachmentsPosition() == 'relations')
|
||||
{
|
||||
$this->DisplayAttachments($oObject, $oPage, $bEditMode);
|
||||
}
|
||||
}
|
||||
|
||||
public function OnFormSubmit($oObject, $sFormPrefix = '')
|
||||
{
|
||||
if ($this->IsTargetObject($oObject))
|
||||
{
|
||||
// For new objects attachments are processed in OnDBInsert
|
||||
if (!$oObject->IsNew())
|
||||
{
|
||||
self::UpdateAttachments($oObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function GetMaxUpload()
|
||||
{
|
||||
$iMaxUpload = ini_get('upload_max_filesize');
|
||||
if (!$iMaxUpload)
|
||||
{
|
||||
$sRet = Dict::S('Attachments:UploadNotAllowedOnThisSystem');
|
||||
}
|
||||
else
|
||||
{
|
||||
$iMaxUpload = utils::ConvertToBytes($iMaxUpload);
|
||||
if ($iMaxUpload > 1024*1024*1024)
|
||||
{
|
||||
$sRet = Dict::Format('Attachment:Max_Go', sprintf('%0.2f', $iMaxUpload/(1024*1024*1024)));
|
||||
}
|
||||
else if ($iMaxUpload > 1024*1024)
|
||||
{
|
||||
$sRet = Dict::Format('Attachment:Max_Mo', sprintf('%0.2f', $iMaxUpload/(1024*1024)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sRet = Dict::Format('Attachment:Max_Ko', sprintf('%0.2f', $iMaxUpload/(1024)));
|
||||
}
|
||||
}
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
public function OnFormCancel($sTempId)
|
||||
{
|
||||
// Delete all "pending" attachments for this form
|
||||
$sOQL = 'SELECT Attachment WHERE temp_id = :temp_id';
|
||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
|
||||
while($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oAttachment->DBDelete();
|
||||
// Pending attachment, don't mention it in the history
|
||||
}
|
||||
}
|
||||
|
||||
public function EnumUsedAttributes($oObject)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function GetIcon($oObject)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function GetHilightClass($oObject)
|
||||
{
|
||||
// Possible return values are:
|
||||
// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE
|
||||
return HILIGHT_CLASS_NONE;
|
||||
}
|
||||
|
||||
public function EnumAllowedActions(DBObjectSet $oSet)
|
||||
{
|
||||
// No action
|
||||
return array();
|
||||
}
|
||||
|
||||
public function OnIsModified($oObject)
|
||||
{
|
||||
if ($this->IsTargetObject($oObject))
|
||||
{
|
||||
$aAttachmentIds = utils::ReadParam('attachments', array());
|
||||
$aRemovedAttachmentIds = utils::ReadParam('removed_attachments', array());
|
||||
if ( (count($aAttachmentIds) > 0) || (count($aRemovedAttachmentIds) > 0) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function OnCheckToWrite($oObject)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function OnCheckToDelete($oObject)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function OnDBUpdate($oObject, $oChange = null)
|
||||
{
|
||||
if ($this->IsTargetObject($oObject))
|
||||
{
|
||||
// Get all current attachments
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oAttachment->SetItem($oObject, true /*updateonchange*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function OnDBInsert($oObject, $oChange = null)
|
||||
{
|
||||
if ($this->IsTargetObject($oObject))
|
||||
{
|
||||
self::UpdateAttachments($oObject, $oChange);
|
||||
}
|
||||
}
|
||||
|
||||
public function OnDBDelete($oObject, $oChange = null)
|
||||
{
|
||||
if ($this->IsTargetObject($oObject))
|
||||
{
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oAttachment->DBDelete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Plug-ins specific functions
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected function IsTargetObject($oObject)
|
||||
{
|
||||
$aAllowedClasses = MetaModel::GetModuleSetting('itop-attachments', 'allowed_classes', array('Ticket'));
|
||||
foreach($aAllowedClasses as $sAllowedClass)
|
||||
{
|
||||
if ($oObject instanceof $sAllowedClass)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function GetAttachmentsPosition()
|
||||
{
|
||||
return MetaModel::GetModuleSetting('itop-attachments', 'position', 'relations');
|
||||
}
|
||||
|
||||
var $m_bDeleteEnabled = true;
|
||||
|
||||
public function EnableDelete($bEnabled)
|
||||
{
|
||||
$this->m_bDeleteEnabled = $bEnabled;
|
||||
}
|
||||
|
||||
public function DisplayAttachments($oObject, WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
// Exit here if the class is not allowed
|
||||
if (!$this->IsTargetObject($oObject)) return;
|
||||
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
|
||||
if ($this->GetAttachmentsPosition() == 'relations')
|
||||
{
|
||||
$sTitle = ($oSet->Count() > 0)? Dict::Format('Attachments:TabTitle_Count', $oSet->Count()) : Dict::S('Attachments:EmptyTabTitle');
|
||||
$oPage->SetCurrentTab($sTitle);
|
||||
}
|
||||
$oPage->add_style(
|
||||
<<<EOF
|
||||
.attachment {
|
||||
display: inline-block;
|
||||
text-align:center;
|
||||
float:left;
|
||||
padding:5px;
|
||||
}
|
||||
.attachment:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
.attachment img {
|
||||
border: 0;
|
||||
}
|
||||
.attachment a {
|
||||
text-decoration: none;
|
||||
color: #1C94C4;
|
||||
}
|
||||
.btn_hidden {
|
||||
display: none;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
$oPage->add('<fieldset>');
|
||||
$oPage->add('<legend>'.Dict::S('Attachments:FieldsetTitle').'</legend>');
|
||||
|
||||
if ($bEditMode)
|
||||
{
|
||||
$sIsDeleteEnabled = $this->m_bDeleteEnabled ? 'true' : 'false';
|
||||
$iTransactionId = $oPage->GetTransactionId();
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-attachments/ajaxfileupload.js');
|
||||
$sClass = get_class($oObject);
|
||||
$sTempId = session_id().'_'.$iTransactionId;
|
||||
$sDeleteBtn = Dict::S('Attachments:DeleteBtn');
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
function RemoveNewAttachment(att_id)
|
||||
{
|
||||
$('#attachment_'+att_id).attr('name', 'removed_attachments[]');
|
||||
$('#display_attachment_'+att_id).hide();
|
||||
$('#attachment_plugin').trigger('remove_attachment', [att_id]);
|
||||
return false; // Do not submit the form !
|
||||
}
|
||||
function ajaxFileUpload()
|
||||
{
|
||||
//starting setting some animation when the ajax starts and completes
|
||||
$("#attachment_loading").ajaxStart(function(){
|
||||
$(this).show();
|
||||
}).ajaxComplete(function(){
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
/*
|
||||
prepareing ajax file upload
|
||||
url: the url of script file handling the uploaded files
|
||||
fileElementId: the file type of input element id and it will be the index of \$_FILES Array()
|
||||
dataType: it support json, xml
|
||||
secureuri:use secure protocol
|
||||
success: call back function when the ajax complete
|
||||
error: callback function when the ajax failed
|
||||
|
||||
*/
|
||||
$.ajaxFileUpload
|
||||
(
|
||||
{
|
||||
url: GetAbsoluteUrlModulesRoot()+'itop-attachments/ajax.attachment.php?obj_class={$sClass}&temp_id={$sTempId}&operation=add',
|
||||
secureuri:false,
|
||||
fileElementId:'file',
|
||||
dataType: 'json',
|
||||
success: function (data, status)
|
||||
{
|
||||
if(typeof(data.error) != 'undefined')
|
||||
{
|
||||
if(data.error != '')
|
||||
{
|
||||
alert(data.error);
|
||||
}
|
||||
else
|
||||
{
|
||||
var sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php/?operation=download_document&class=Attachment&id='+data.att_id+'&field=contents';
|
||||
$('#attachments').append('<div class="attachment" id="display_attachment_'+data.att_id+'"><a href="'+sDownloadLink+'"><img src="'+data.icon+'"><br/>'+data.msg+'<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveNewAttachment('+data.att_id+');"/></div>');
|
||||
if($sIsDeleteEnabled)
|
||||
{
|
||||
$('#display_attachment_'+data.att_id).hover( function() { $(this).children(':button').toggleClass('btn_hidden'); } );
|
||||
}
|
||||
$('#attachment_plugin').trigger('add_attachment', [data.att_id, data.msg]);
|
||||
|
||||
//alert(data.msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function (data, status, e)
|
||||
{
|
||||
alert(e);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
EOF
|
||||
);
|
||||
$oPage->add('<span id="attachments">');
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$iAttId = $oAttachment->GetKey();
|
||||
$oDoc = $oAttachment->Get('contents');
|
||||
$sFileName = $oDoc->GetFileName();
|
||||
$sIcon = utils::GetAbsoluteUrlAppRoot().AttachmentPlugIn::GetFileIcon($sFileName);
|
||||
$sDownloadLink = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php/?operation=download_document&class=Attachment&id='.$iAttId.'&field=contents';
|
||||
$oPage->add('<div class="attachment" id="attachment_'.$iAttId.'"><a href="'.$sDownloadLink.'"><img src="'.$sIcon.'"><br/>'.$sFileName.'<input type="hidden" name="attachments[]" value="'.$iAttId.'"/></a><br/> <input id="btn_remove_'.$iAttId.'" type="button" class="btn_hidden" value="Delete" onClick="$(\'#attachment_'.$iAttId.'\').remove();"/> </div>');
|
||||
}
|
||||
|
||||
// Suggested attachments are listed here but treated as temporary
|
||||
$aDefault = utils::ReadParam('default', array(), false, 'raw_data');
|
||||
if (array_key_exists('suggested_attachments', $aDefault))
|
||||
{
|
||||
$sSuggestedAttachements = $aDefault['suggested_attachments'];
|
||||
if (is_array($sSuggestedAttachements))
|
||||
{
|
||||
$sSuggestedAttachements = implode(',', $sSuggestedAttachements);
|
||||
}
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id IN($sSuggestedAttachements)");
|
||||
$oSet = new DBObjectSet($oSearch, array());
|
||||
if ($oSet->Count() > 0)
|
||||
{
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
// Mark the attachments as temporary attachments for the current object/form
|
||||
$oAttachment->Set('temp_id', $sTempId);
|
||||
$oAttachment->DBUpdate();
|
||||
// Display them
|
||||
$iAttId = $oAttachment->GetKey();
|
||||
$oDoc = $oAttachment->Get('contents');
|
||||
$sFileName = $oDoc->GetFileName();
|
||||
$sIcon = utils::GetAbsoluteUrlAppRoot().AttachmentPlugIn::GetFileIcon($sFileName);
|
||||
$sDownloadLink = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php/?operation=download_document&class=Attachment&id='.$iAttId.'&field=contents';
|
||||
$oPage->add('<div class="attachment" id="display_attachment_'.$iAttId.'"><a href="'.$sDownloadLink.'"><img src="'.$sIcon.'"><br/>'.$sFileName.'<input type="hidden" name="attachments[]" value="'.$iAttId.'"/></a><br/> <input id="btn_remove_'.$iAttId.'" type="button" class="btn_hidden" value="Delete" onClick="RemoveNewAttachment('.$iAttId.');"/> </div>');
|
||||
$oPage->add_ready_script("$('#attachment_plugin').trigger('add_attachment', [$iAttId, '".addslashes($sFileName)."']);");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oPage->add('</span>');
|
||||
$oPage->add('<div style="clear:both"></div>');
|
||||
$sMaxUpload = $this->GetMaxUpload();
|
||||
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading"> <img src="../images/indicator.gif"></span> '.$sMaxUpload);
|
||||
$oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
|
||||
$oPage->p('<input type="hidden" id="attachment_plugin"/>');
|
||||
$oPage->add('</fieldset>');
|
||||
if ($this->m_bDeleteEnabled)
|
||||
{
|
||||
$oPage->add_ready_script('$(".attachment").hover( function() {$(this).children(":button").toggleClass("btn_hidden"); } );');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add('<span id="attachments">');
|
||||
if ($oSet->Count() == 0)
|
||||
{
|
||||
$oPage->add(Dict::S('Attachments:NoAttachment'));
|
||||
}
|
||||
else
|
||||
{
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$iAttId = $oAttachment->GetKey();
|
||||
$oDoc = $oAttachment->Get('contents');
|
||||
$sFileName = $oDoc->GetFileName();
|
||||
$sIcon = utils::GetAbsoluteUrlAppRoot().AttachmentPlugIn::GetFileIcon($sFileName);
|
||||
$sDownloadLink = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php/?operation=download_document&class=Attachment&id='.$iAttId.'&field=contents';
|
||||
$oPage->add('<div class="attachment" id="attachment_'.$iAttId.'"><a href="'.$sDownloadLink.'"><img src="'.$sIcon.'"><br/>'.$sFileName.'</a><input type="hidden" name="attachments[]" value="'.$iAttId.'"/><br/> </div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static function UpdateAttachments($oObject, $oChange = null)
|
||||
{
|
||||
$iTransactionId = utils::ReadParam('transaction_id', null);
|
||||
if (!is_null($iTransactionId))
|
||||
{
|
||||
$aActions = array();
|
||||
$aAttachmentIds = utils::ReadParam('attachments', array());
|
||||
|
||||
// Get all current attachments
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_class = :class AND item_id = :item_id");
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('class' => get_class($oObject), 'item_id' => $oObject->GetKey()));
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
// Remove attachments that are no longer attached to the current object
|
||||
if (!in_array($oAttachment->GetKey(), $aAttachmentIds))
|
||||
{
|
||||
$oAttachment->DBDelete();
|
||||
$aActions[] = self::GetActionDescription($oAttachment, false /* false => deletion */);
|
||||
}
|
||||
}
|
||||
|
||||
// Attach new (temporary) attachements
|
||||
$sTempId = session_id().'_'.$iTransactionId;
|
||||
// The object is being created from a form, check if there are pending attachments
|
||||
// for this object, but deleting the "new" ones that were already removed from the form
|
||||
$aRemovedAttachmentIds = utils::ReadParam('removed_attachments', array());
|
||||
$sOQL = 'SELECT Attachment WHERE temp_id = :temp_id';
|
||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||
foreach($aAttachmentIds as $iAttachmentId)
|
||||
{
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('temp_id' => $sTempId));
|
||||
while($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
if (in_array($oAttachment->GetKey(),$aRemovedAttachmentIds))
|
||||
{
|
||||
$oAttachment->DBDelete();
|
||||
// temporary attachment removed, don't even mention it in the history
|
||||
}
|
||||
else
|
||||
{
|
||||
$oAttachment->SetItem($oObject);
|
||||
$oAttachment->Set('temp_id', '');
|
||||
$oAttachment->DBUpdate();
|
||||
// temporary attachment confirmed, list it in the history
|
||||
$aActions[] = self::GetActionDescription($oAttachment, true /* true => creation */);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count($aActions) > 0)
|
||||
{
|
||||
if ($oChange == null)
|
||||
{
|
||||
// Let's create a change if non is supplied
|
||||
$oChange = MetaModel::NewObject("CMDBChange");
|
||||
$oChange->Set("date", time());
|
||||
$sUserString = CMDBChange::GetCurrentUserName();
|
||||
$oChange->Set("userinfo", $sUserString);
|
||||
$iChangeId = $oChange->DBInsert();
|
||||
}
|
||||
foreach($aActions as $sActionDescription)
|
||||
{
|
||||
self::RecordHistory($oChange, $oObject, $sActionDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
public static function GetFileIcon($sFileName)
|
||||
{
|
||||
$aPathParts = pathinfo($sFileName);
|
||||
switch($aPathParts['extension'])
|
||||
{
|
||||
case 'doc':
|
||||
case 'docx':
|
||||
$sIcon = 'doc.png';
|
||||
break;
|
||||
|
||||
case 'xls':
|
||||
case 'xlsx':
|
||||
$sIcon = 'xls.png';
|
||||
break;
|
||||
|
||||
case 'ppt':
|
||||
case 'pptx':
|
||||
$sIcon = 'ppt.png';
|
||||
break;
|
||||
|
||||
case 'pdf':
|
||||
$sIcon = 'pdf.png';
|
||||
break;
|
||||
|
||||
case 'txt':
|
||||
case 'text':
|
||||
$sIcon = 'txt.png';
|
||||
break;
|
||||
|
||||
case 'rtf':
|
||||
$sIcon = 'rtf.png';
|
||||
break;
|
||||
|
||||
case 'odt':
|
||||
$sIcon = 'odt.png';
|
||||
break;
|
||||
|
||||
case 'ods':
|
||||
$sIcon = 'ods.png';
|
||||
break;
|
||||
|
||||
case 'odp':
|
||||
$sIcon = 'odp.png';
|
||||
break;
|
||||
|
||||
case 'html':
|
||||
case 'htm':
|
||||
$sIcon = 'html.png';
|
||||
break;
|
||||
|
||||
case 'png':
|
||||
case 'gif':
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
case 'tiff':
|
||||
case 'tif':
|
||||
case 'bmp':
|
||||
$sIcon = 'image.png';
|
||||
|
||||
break;
|
||||
case 'zip':
|
||||
case 'gz':
|
||||
case 'tgz':
|
||||
case 'rar':
|
||||
$sIcon = 'zip.png';
|
||||
break;
|
||||
|
||||
default:
|
||||
$sIcon = 'document.png';
|
||||
break;
|
||||
}
|
||||
|
||||
return 'env-'.utils::GetCurrentEnvironment()."/itop-attachments/icons/$sIcon";
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
private static function RecordHistory(CMDBChange $oChange, $oTargetObject, $sDescription)
|
||||
{
|
||||
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpPlugin");
|
||||
$oMyChangeOp->Set("change", $oChange->GetKey());
|
||||
$oMyChangeOp->Set("objclass", get_class($oTargetObject));
|
||||
$oMyChangeOp->Set("objkey", $oTargetObject->GetKey());
|
||||
$oMyChangeOp->Set("description", $sDescription);
|
||||
$iId = $oMyChangeOp->DBInsertNoReload();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
private static function GetActionDescription($oAttachment, $bCreate = true)
|
||||
{
|
||||
$oBlob = $oAttachment->Get('contents');
|
||||
$sFileName = $oBlob->GetFileName();
|
||||
if ($bCreate)
|
||||
{
|
||||
$sDescription = Dict::Format('Attachments:History_File_Added', $sFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sDescription = Dict::Format('Attachments:History_File_Removed', $sFileName);
|
||||
}
|
||||
return $sDescription;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
128
datamodels/1.x/itop-attachments/module.attachments.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-attachments/1.0.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Tickets attachments',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
|
||||
),
|
||||
'mandatory' => false,
|
||||
'visible' => true,
|
||||
'installer' => 'AttachmentInstaller',
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
'model.itop-attachments.php',
|
||||
'main.attachments.php',
|
||||
),
|
||||
'webservice' => array(
|
||||
|
||||
),
|
||||
'dictionary' => array(
|
||||
'en.dict.attachments.php',
|
||||
'fr.dict.attachments.php',
|
||||
),
|
||||
'data.struct' => array(
|
||||
// add your 'structure' definition XML files here,
|
||||
),
|
||||
'data.sample' => array(
|
||||
// add your sample data XML files here,
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
'allowed_classes' => array('Ticket'), // List of classes for which to manage "Attachments"
|
||||
'position' => 'relations', // Where to display the attachments: relations | properties
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if (!class_exists('AttachmentInstaller'))
|
||||
{
|
||||
// Module installation handler
|
||||
//
|
||||
class AttachmentInstaller extends ModuleInstallerAPI
|
||||
{
|
||||
public static function BeforeWritingConfig(Config $oConfiguration)
|
||||
{
|
||||
// If you want to override/force some configuration values, do it here
|
||||
return $oConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler called before creating or upgrading the database schema
|
||||
* @param $oConfiguration Config The new configuration of the application
|
||||
* @param $sPreviousVersion string PRevious version number of the module (empty string in case of first install)
|
||||
* @param $sCurrentVersion string Current version number of the module
|
||||
*/
|
||||
public static function BeforeDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
// If you want to migrate data from one format to another, do it here
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler called after the creation/update of the database schema
|
||||
* @param $oConfiguration Config The new configuration of the application
|
||||
* @param $sPreviousVersion string PRevious version number of the module (empty string in case of first install)
|
||||
* @param $sCurrentVersion string Current version number of the module
|
||||
*/
|
||||
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
// For each record having item_org_id unset,
|
||||
// get the org_id from the container object
|
||||
//
|
||||
// Prerequisite: change null into 0 (workaround to the fact that we cannot use IS NULL in OQL)
|
||||
SetupPage::log_info("Initializing attachment/item_org_id - null to zero");
|
||||
$sTableName = MetaModel::DBGetTable('Attachment');
|
||||
$sRepair = "UPDATE `$sTableName` SET `item_org_id` = 0 WHERE `item_org_id` IS NULL";
|
||||
CMDBSource::Query($sRepair);
|
||||
|
||||
SetupPage::log_info("Initializing attachment/item_org_id - zero to the container");
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_org_id = 0");
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$iUpdated = 0;
|
||||
while ($oAttachment = $oSet->Fetch())
|
||||
{
|
||||
$oContainer = MetaModel::GetObject($oAttachment->Get('item_class'), $oAttachment->Get('item_id'), false /* must be found */, true /* allow all data */);
|
||||
if ($oContainer)
|
||||
{
|
||||
$oAttachment->SetItem($oContainer, true /*updateonchange*/);
|
||||
$iUpdated++;
|
||||
}
|
||||
}
|
||||
|
||||
SetupPage::log_info("Initializing attachment/item_org_id - $iUpdated records have been adjusted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||