From f9c8b272c6badfa4731e9c3e9e257e1348a93e60 Mon Sep 17 00:00:00 2001
From: elena <ebudnik@irap.omp.eu>
Date: Fri, 25 Sep 2015 15:26:17 +0200
Subject: [PATCH] edit catalog

---
 js/app/controllers/CatalogModule.js     |  16 ++++++++++++++--
 js/app/controllers/InteractiveModule.js |  99 +++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------
 js/app/views/CatalogUI.js               | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------
 php/classes/AmdaAction.php              |  19 ++++++++++++++-----
 php/classes/CatalogCacheMgr.php         |  91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 php/classes/CatalogMgr.php              |  33 ++++++++++++++++++++++++++++++++-
 6 files changed, 362 insertions(+), 146 deletions(-)

diff --git a/js/app/controllers/CatalogModule.js b/js/app/controllers/CatalogModule.js
index 046a5ad..2605d70 100644
--- a/js/app/controllers/CatalogModule.js
+++ b/js/app/controllers/CatalogModule.js
@@ -15,6 +15,7 @@ Ext.define('amdaDesktop.CatalogModule', {
      ],
      
       contentId : 'catalogUI',
+      isOperationOnShow : true,
       
     /**
      * @cfg {String} data models
@@ -30,6 +31,17 @@ Ext.define('amdaDesktop.CatalogModule', {
 	height: 700,
 	uiType : 'panelCatalog',
 	helpTitle : 'Help on Catalog Module',
-	helpFile : 'catalogHelp'
-		
+	helpFile : 'catalogHelp',
+	
+	operationOnShow: function() {				
+		var obj = this.linkedNode.get('object');
+		if (obj && obj.get('id') == '' && !obj.get('fromPlugin')) {
+			Ext.Msg.prompt('Define Parameters', 'Please enter parameters number:', function(btn, text){
+			if (btn == 'ok'){
+				AmdaAction.initTTCache(this.getUiContent().isCatalog, text, this.getUiContent().onAfterInit, this.getUiContent()); 
+			}
+		}, this);
+		}
+								  
+	}		
 });
diff --git a/js/app/controllers/InteractiveModule.js b/js/app/controllers/InteractiveModule.js
index e6ba79e..fd41a1a 100644
--- a/js/app/controllers/InteractiveModule.js
+++ b/js/app/controllers/InteractiveModule.js
@@ -5,13 +5,7 @@
  * @extends amdaDesktop.AmdaModule
  * @brief   Generic Interactive Module controller definition
  * @author  CDA
- * @version $Id: InteractiveModule.js 2109 2014-02-19 17:47:37Z elena $
- *******************************************************************************
- *    FT Id     :   Date   : Name - Description
- *******************************************************************************
- *  :           :08/06/2011: CDA - Migration extjs4 
- *  :           :09/06/2011: elena - generic Interactive modules methods: init(), createWindow(), 
- *                                   createLinkedNode(), createObject() now are defined here 
+ * @version $Id: InteractiveModule.js 2109 2014-02-19 17:47:37Z elena $ 
  */
 
 Ext.define('amdaDesktop.InteractiveModule', {
@@ -82,65 +76,70 @@ Ext.define('amdaDesktop.InteractiveModule', {
 				],
 				items : [ 
 				 {
-				 	    xtype :  this.uiType,
-					    object : this.linkedNode.get('object'),
-					    id : this.contentId
+					xtype :  this.uiType,
+					object : this.linkedNode.get('object'),
+					id : this.contentId
 				  }	
 				]
 			});
 			
 			this.closed = false;
 			win.on({
-                                scope: this,
-                                // on window activation event
-                                activate: function(){
-                                    // order to pin this Module with WsExplorer
-                                    this.pin();
-                                },
-                                // on window closing event
-                                beforeclose: function (win, eOpts) {
-                                    
-                                   this.saveState();
-                                        
-                                    var isDirty = this.getUiContent().fclose();
-                                    
-                                    if (!this.closed && isDirty) {
-                                        Ext.Msg.confirm('Close', 'Current window has been modified.\nDo you want to close the window ?' , function (btn, text){  
-                                            if (btn == 'yes'){ 
-                                                // mark this.closed as true before the call to close() as that will fire the beforeclose event again
-                                                this.closed = true; 
-                                                win.close();
-                                            } 
+				scope: this,
+				// on window activation event
+				activate: function(){
+					// order to pin this Module with WsExplorer
+					this.pin();
+				},
+				// on window closing event
+				beforeclose: function (win, eOpts) {
+					
+					this.saveState();
+					
+					var isDirty = this.getUiContent().fclose();
+					
+					if (!this.closed && isDirty) {
+					Ext.Msg.confirm('Close', 'Current window has been modified.\nDo you want to close the window ?' , function (btn, text){  
+						if (btn == 'yes'){ 
+						// mark this.closed as true before the call to close() as that will fire the beforeclose event again
+						this.closed = true; 
+						win.close();
+						} 
                                         },this); 
-	                } else if (!isDirty) {
-	                	this.closed = true;
-	                }
+					} else if (!isDirty) {
+						this.closed = true;
+					}
 									
-	                if (this.closed) {
-                            //remove object from linkedNode in order to minimize used memory
-                            this.linkedNode.set('object','');
-                            // unlink Node
-                            this.setLinkedNode(null);
-                                // order to unpin this Module from WsExplorer
-                            this.unpin();
-	                }
+					if (this.closed) {
+						//remove object from linkedNode in order to minimize used memory
+						this.linkedNode.set('object','');
+						// unlink Node
+						this.setLinkedNode(null);
+							// order to unpin this Module from WsExplorer
+						this.unpin();
+					}
 	 
-	                // Don't automatically close if the form is dirty, let the call to this.close() within the confirm box close the window.
-	                return this.closed;
-	            },	   
-	            minimize: function (win, eOpts) {
+				// Don't automatically close if the form is dirty, let the call to this.close() within the confirm box close the window.
+				return this.closed;
+				},	   
+				minimize: function (win, eOpts) {
 					// Save form
 					if (this.getUiContent().formPanel)
-					    this.getUiContent().formPanel.getForm().updateRecord(this.linkedNode.get('object'));
+						this.getUiContent().formPanel.getForm().updateRecord(this.linkedNode.get('object'));
 					else 
-					   this.getUiContent().items.getAt(0).getForm().updateRecord(this.linkedNode.get('object'));
+						this.getUiContent().items.getAt(0).getForm().updateRecord(this.linkedNode.get('object'));
 					// Save grids
 					this.getUiContent().updateObject();
-	            }
+				},
+				show: function() {
+					// configuration of empty catalog
+					if (this.isOperationOnShow)
+						 this.operationOnShow();
+				}	 
 			});
-
 		} else {
-			this.getUiContent().setObject(this.linkedNode.get('object'));
+			// second arg 'true' is used in CatalogUI to mark if Grid Reconfiguration is needed
+			this.getUiContent().setObject(this.linkedNode.get('object'), true);
 		}
 		win.show();
 	},
diff --git a/js/app/views/CatalogUI.js b/js/app/views/CatalogUI.js
index 1f3da5c..51c4384 100644
--- a/js/app/views/CatalogUI.js
+++ b/js/app/views/CatalogUI.js
@@ -10,21 +10,28 @@
 Ext.define('amdaUI.CatalogUI', {
 	extend: 'Ext.container.Container',
 	alias: 'widget.panelCatalog',
-
+	
+	requires: [
+		'Ext.grid.plugin.BufferedRenderer'
+	],
+	
 	isCatalog : true,
 	
+	
 	constructor: function(config) 
 	{
 		this.init(config);
-		this.callParent(arguments);;
+		this.callParent(arguments);
+		this.toReconfigure = true;
 		if (this.object) this.loadObject();	         
 	},
 	
-	setObject : function (object) 
-	{
-		// set object
-		this.object = object;
-		
+	setObject : function (object, toReconfigure) 
+	{	
+		if (toReconfigure) 
+			this.toReconfigure = true;
+		// set object	        
+		this.object = object;		 
 		// load object into view
 		this.loadObject();
 	},
@@ -77,44 +84,38 @@ Ext.define('amdaUI.CatalogUI', {
 		this.formPanel.getForm().findField('nbIntervals').setValue(this.object.get('nbIntervals'));
 	},
 	
-	/**
-	 * load object catalog into this view
-	 */
-	loadObject : function()
-	{ 	  
-		// load object into form
-		this.formPanel.getForm().loadRecord(this.object);
+	 
+	
+	onAfterInit:   function(result, e) {
 		
-		this.status = null;
-			
 		var me = this;
 		
-		var onAfterInit = function(result, e) 
-		{		
-			if (!result || !result.success)
-			{
-				if (result.message)
-					myDesktopApp.errorMsg(result.message);
-				else
-					myDesktopApp.errorMsg('Unknown error during catalog cache initialisation');
-				return;
-			}
-			          	
+		if (!result || !result.success)
+		{
+			if (result.message)
+				myDesktopApp.errorMsg(result.message);
+			else
+				myDesktopApp.errorMsg('Unknown error during catalog cache initialisation');
+			return;
+		}
+			 
+		if (me.toReconfigure) 
+		{          	
 			var fields = [], columns = [], i = 3, width, index;
 
 			var fieldsConfig =  [{ name : 'start' },{ name : 'stop' },{ name: 'cacheId', type : 'int'},
 				{ name: 'isNew', type : 'boolean', defaultValue: false },
-			       { name: 'isModified', type : 'boolean', defaultValue: false}
+				{ name: 'isModified', type : 'boolean', defaultValue: false}
 			];
 			
 			for (var j = 0; j < 5; j++) fields[j] =  Ext.create('Ext.data.Field', fieldsConfig[j]);
 				
-			columns[0] =  Ext.create('Ext.grid.column.RowNumberer');
+			columns[0] = Ext.create('Ext.grid.column.RowNumberer');
 
 			columns[1] = Ext.create('Ext.grid.column.Column', { text: 'Start Time', sortable : false,  dataIndex: 'start',  
-						width : 120, menuDisabled: true });
+						width : 120, menuDisabled: true, editor : { xtype:'datefield', allowBlank:false, hideTrigger: true,  format : 'Y-m-d\\TH:i:s'}});
 			columns[2] = Ext.create('Ext.grid.column.Column', { text: 'Stop Time', sortable : false,  dataIndex: 'stop',  
-						width : 120, menuDisabled: true });
+						width : 120, menuDisabled: true, editor : { xtype:'datefield', allowBlank:false, hideTrigger: true,  format : 'Y-m-d\\TH:i:s'}});
 		
 			Ext.Array.each(result.parameters, function(obj) 
 			{
@@ -122,12 +123,12 @@ Ext.define('amdaUI.CatalogUI', {
 				fields[i+2] = Ext.create('Ext.data.Field',{ name : index });
 				width = 50. *  parseInt(obj.size);
 				columns[i] = Ext.create('Ext.grid.column.Column', { text: obj.name, sortable : false,  dataIndex: index,  
-						width : width, menuDisabled: true });
+						width : width, menuDisabled: true, editor: 'textfield' });
 				i++;
 			});
-			
-			
-         
+				
+				
+		
 			var store = Ext.create('Ext.data.Store', {
 				fields: fields,
 				autoDestroy: false,
@@ -161,11 +162,11 @@ Ext.define('amdaUI.CatalogUI', {
 						//   	this.fireEvent("refresh");
 					}
 				}
-			});
-	   
+			});			
+			
 			me.TTGrid.reconfigure(store, columns);
-					
-			me.TTGrid.getSelectionModel().deselectAll();
+		}		
+		me.TTGrid.getSelectionModel().deselectAll();
 	//         	        	
 	//         	// clear filters
 	//         	me.TTGrid.getStore().clearFilter(true);
@@ -173,41 +174,50 @@ Ext.define('amdaUI.CatalogUI', {
 	//     		//clear sort
 	//         	me.TTGrid.getStore().sorters.clear();
 	//         	//me.TTGrid.getStore().sorters = new Ext.util.MixedCollection();
-	//         	
+	         	
 			//set cache token to the Catalog object
-			me.object.set('cacheToken', result.token);
-			me.setParamInfo(result.parameters);
-			
-			me.TTGrid.getStore().load();
+		me.object.set('cacheToken', result.token);
+		me.setParamInfo(result.parameters);
+		
+		me.TTGrid.getStore().load();
 			
-			me.status = result.status;
-		};
-	  
+		me.status = result.status;
+	},
+	
+	/**
+	 * load object catalog into this view
+	 */
+	loadObject : function()
+	{ 	  
+		// load object into form
+		this.formPanel.getForm().loadRecord(this.object);
+	
+		this.status = null;
+		
 		if (this.object.get('fromPlugin'))
 		{
 			if (this.object.get('objFormat') && this.object.get('objFormat') != '')
 			{
 				//From uploaded file
-				//AmdaAction.initTTCacheFromUploadedFile(this.object.get('objName'), this.object.get('objFormat'), onAfterInit);
+				//AmdaAction.initTTCacheFromUploadedFile(this.object.get('objName'), this.object.get('objFormat'), this.onAfterInit, this);
 			}
 			else
 			{
-				//From tmp object (ie Search result)		    
-				AmdaAction.initTTCacheFromTmpObject(this.object.get('folderId'), this.object.get('objName'), this.isCatalog, onAfterInit);
+				//From tmp object (ie Statistics result)		    
+				AmdaAction.initTTCacheFromTmpObject(this.object.get('folderId'), this.object.get('objName'), this.isCatalog, this.onAfterInit, this);
 			}
 		}
 		else
 		{
-			var typeTT = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.catalog.id).linkedNode.data.nodeType;
+			// var typeTT = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.catalog.id).linkedNode.data.nodeType;
 			if (this.object.get('id') == '')
-			{
-				//Init empty cache
-				AmdaAction.initTTCache(this.isCatalog, onAfterInit);
+			{														  				
+				  
 			}	
 			else
 			{
 				//From existing TT file
-				AmdaAction.initTTCacheFromTT(this.object.get('id'), 'catalog', onAfterInit);
+				AmdaAction.initTTCacheFromTT(this.object.get('id'), 'catalog', this.onAfterInit, this);
 			}
 		}
 	},
@@ -221,8 +231,9 @@ Ext.define('amdaUI.CatalogUI', {
 	 */
 	saveProcess : function(toRename)
 	{
-		var module = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.catalog.id); 
-	      
+		var module = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.catalog.id);
+		//  store / columns are the same - not needed to reconfigure grid
+		this.toReconfigure = false;
             // if the name has been modified this is a creation
 		if (this.fclose()) 
 	      {         
@@ -245,13 +256,26 @@ Ext.define('amdaUI.CatalogUI', {
 				} 
 				module.linkedNode.create({callback : function() {module.linkedNode.update();}, scope : this});
 			} else {
-				//update
+				//update				
 				module.linkedNode.update();
 			}
+		   	
 		}
 	},
 	
 	/**
+	 * overwrite metod called by Save button
+	 */
+	overwriteProcess : function(btn)
+	{	
+		if (btn == 'cancel') return;
+               
+		this.fieldName.clearInvalid();
+		this.saveProcess(true);		
+		
+	},
+	
+	/**
 	 * Check if changes were made before closing window 
 	 * @return true if changes
 	 */	
@@ -263,8 +287,7 @@ Ext.define('amdaUI.CatalogUI', {
 		var isDirty = this.formPanel.getForm().isDirty() || (this.status.isModified) || (this.status.nbModified > 0) || (this.status.nbNew > 0);
 	return isDirty;
 	},
-
-		    
+ 	    
 	init : function (config) 
 	{	  
 		this.object =   config.object;
@@ -282,39 +305,97 @@ Ext.define('amdaUI.CatalogUI', {
 					return this.validFlag;
 				}
 		});
-	  
+		
+		var cellEditing = Ext.create('Ext.grid.plugin.CellEditing',{
+//			clicksToEdit: 2,
+			onEditComplete : function(ed, value, startValue) {
+				var me = this,
+				activeColumn = me.getActiveColumn(),
+				context = me.context,
+				record;
+
+				if (activeColumn) {
+					record = context.record;
+
+					me.setActiveEditor(null);
+					me.setActiveColumn(null);
+					me.setActiveRecord(null);
+				
+					context.value = value;
+					if (!me.validateEdit()) {
+						me.editing = false;
+						return;
+					}
+
+					// Only update the record if the new value is different than the
+					// startValue. When the view refreshes its el will gain focus
+					if (!record.isEqual(value, startValue)) {
+					var obj = {};					
+					 
+					obj['cacheId']  = record.get('cacheId');
+					obj['isCatalog'] = true;
+					obj[activeColumn.dataIndex] = value;								  
+					
+					//Interval is modified on the server side
+					me.editing = true;
+					
+					AmdaAction.modifyTTCacheInterval(obj, function (result, e) {
+						
+						var module = myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.catalog.id);
+						if (module)
+							module.getUiContent().status = result.status;
+						context.grid.getSelectionModel().deselectAll();
+						context.store.reload({
+							callback : function(records, options, success) {
+								context.view.bufferedRenderer.scrollTo(context.rowIdx, true, function() {
+									me.fireEvent('edit', me, context);
+									me.editing = false;
+								}, me);	    	            
+							}
+						});
+						}, this);
+					}
+					else
+					me.editing = false;
+				}
+			}	
+		});
 
 		this.TTGrid =  Ext.create('Ext.grid.Panel', { 
 			height: 530,
 			columns: [ ],
 			frame: true,
+			columnLines: true,
+		//	selType: 'cellmodel',
+			plugins: [ cellEditing, { ptype : 'bufferedrenderer'} ],
 			dockedItems: [{
 				xtype: 'toolbar', 
 				items: [{
 				iconCls: 'icon-add',
 				scope: this,
 				handler: function(){
-				      alert('NOT IMPLEMENTED YET');
-	//                         cellEditing.cancelEdit();
-	//                         
-	//                         var selection = this.TTGrid.getView().getSelectionModel().getSelection()[0];
-	//                         var row = 0;
-	//                         if (selection)
-	//                         	row = store.indexOf(selection) + 1;
-	//                         this.TTGrid.getSelectionModel().deselectAll();
-	//                         
-	//                         var me = this;
-	//                         AmdaAction.addTTCacheInterval({'index' : row}, function (result, e) {
-	//                         	this.status = result.status;
-	//                         	this.TTGrid.getStore().reload({
-	//                         		callback : function(records, options, success) {
-	//                         			me.TTGrid.getView().bufferedRenderer.scrollTo(row, false, function() {
-	//                         				me.TTGrid.getView().select(row);
-	//                         				cellEditing.startEditByPosition({row: row, column: 1});	
-	//                         			}, me);	
-	//                         		}
-	//                         	});
-	//                         }, this);
+					 
+					cellEditing.cancelEdit();
+					var store = this.TTGrid.getStore();
+					 
+					var selection = this.TTGrid.getView().getSelectionModel().getSelection()[0];
+					var row = 0;
+					if (selection)
+						row = store.indexOf(selection) + 1;
+					this.TTGrid.getSelectionModel().deselectAll();
+                        
+					var me = this;
+					AmdaAction.addTTCacheInterval({'index' : row, 'isCatalog' : true}, function (result, e) {
+	                        	this.status = result.status;
+	                        	this.TTGrid.getStore().reload({
+	                        		callback : function(records, options, success) {
+	                        			me.TTGrid.getView().bufferedRenderer.scrollTo(row, false, function() {
+	                        				me.TTGrid.getView().select(row);
+	                        				cellEditing.startEditByPosition({row: row, column: 1});	
+	                        			}, me);	
+	                        		}
+	                        	});
+	                        }, this);
 				}
 				},{
 				iconCls: 'icon-delete',
@@ -325,8 +406,7 @@ Ext.define('amdaUI.CatalogUI', {
 					var selection = this.TTGrid.getView().getSelectionModel().getSelection()[0];
 					if (selection) 
 					{
-						var rowId = selection.get('cacheId');
-						console.log(selection);
+						var rowId = selection.get('cacheId');						
 						this.TTGrid.getSelectionModel().deselectAll();
 						AmdaAction.removeTTCacheIntervalFromId(rowId, this.isCatalog, function (result, e) {
 							this.status = result.status;
@@ -458,7 +538,7 @@ Ext.define('amdaUI.CatalogUI', {
 	 
 				 myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.visu.id, true, function (module) {	 	 
 					
-					//temporary linked node - as  Visu module is 'pseud' intercative - no 'save', no 'execute'
+					//temporary linked node - as  Visu module is 'pseudo' interactive - no 'save', no 'execute'
 					var temporaryNode = Ext.create('amdaModel.CatalogNode', {
 						leaf : true 
 					}); 
diff --git a/php/classes/AmdaAction.php b/php/classes/AmdaAction.php
index 5fd734c..11b8c04 100644
--- a/php/classes/AmdaAction.php
+++ b/php/classes/AmdaAction.php
@@ -937,12 +937,12 @@ class AmdaAction {
             return  $result;
         }
         
-        public function initTTCache($isCatalog = false)
+        public function initTTCache($isCatalog = false, $nparams)
         {
         	if (!$isCatalog) $cacheMgr = new TimeTableCacheMgr();
         	else              $cacheMgr = new CatalogCacheMgr();
         	
-        	return $cacheMgr->initTTCache();
+        	return $cacheMgr->initTTCache($nparams);
         }
         
         
@@ -1002,7 +1002,9 @@ class AmdaAction {
         
         public function addTTCacheInterval($o)
         {
-        	$cacheMgr = new TimeTableCacheMgr();
+          	if ($o->isCatalog) $cacheMgr = new CatalogCacheMgr();
+          	else $cacheMgr = new TimeTableCacheMgr();
+    	
             return $cacheMgr->addInterval($o->index, $o->start, $o->stop);
         }
         
@@ -1010,13 +1012,20 @@ class AmdaAction {
         {
         	if ($isCatalog) $cacheMgr = new CatalogCacheMgr();
         	else $cacheMgr = new TimeTableCacheMgr();
-        	
+  	
         	return $cacheMgr->removeIntervalFromId($id);
         }
         
         public function modifyTTCacheInterval($o)
         {
-        	$cacheMgr = new TimeTableCacheMgr();
+        	if ($o->isCatalog) {
+        	
+			$cacheMgr = new CatalogCacheMgr();
+		return $cacheMgr->modifyIntervalFromId($o);
+		
+		}
+          	else $cacheMgr = new TimeTableCacheMgr();
+          	
         	return $cacheMgr->modifyIntervalFromId($o->cacheId, $o->start, $o->stop);
         }
         
diff --git a/php/classes/CatalogCacheMgr.php b/php/classes/CatalogCacheMgr.php
index 765d441..d482cbb 100644
--- a/php/classes/CatalogCacheMgr.php
+++ b/php/classes/CatalogCacheMgr.php
@@ -226,12 +226,42 @@ class CatalogCacheObject extends TimeTableCacheObject
 		
 		return true;
 	}
+	
+	public function modifyIntervalFromId($obj) {	
+		
+		foreach ($this->intervals as $interval)
+		{
+			if ($interval->getId() == $obj->cacheId)
+			{				
+				foreach((array)$obj as $key => $val) {				
+				 					
+					if ($key == 'start')
+						$interval->setStartFromISO($val);
+					else if ($key == 'stop')
+						$interval->setStopFromISO($val); 	
+					else {
+					       if (strpos($key, 'param') === false)
+							continue;
+						$params = $interval->getParams();
+						$paramIndex = (int)substr($key,5);
+						$params[$paramIndex-2] = $val;
+						$interval->setParams($params);						 
+					}
+				}
+				$interval->setIsModified(true);
+				$this->isModified = true;
+				return true;
+			}
+		}
+		
+		return false;
+	}
 }
 
 class CatalogCacheMgr extends TimeTableCacheMgr 
 {
 		
-	protected static $cache_file                = "cacheCat";
+	protected static $cache_file = "cacheCat";
 	
 	protected $ttMgr = null;
 	protected $cache = null;
@@ -298,7 +328,7 @@ class CatalogCacheMgr extends TimeTableCacheMgr
 		}
 		
 		$paramHeaders = $intervals_res['parameters'];
-	
+	 
 		$this->cache->setParamsNumber(count($paramHeaders));
 		$this->cache->setParamsSizes($paramHeaders);
 		unset($intervals_res);
@@ -350,6 +380,61 @@ class CatalogCacheMgr extends TimeTableCacheMgr
 		$this->cache->reset();
 
 	return $this->ttMgr->saveIntervals($id, $intervals, $action);
-	}		
+	}
+	
+	public function addInterval($index, $start, $stop, $params) {
+		if (!$this->loadFromFile())
+			return array('success' => false, 'message' => 'Cannot load cache file');
+
+		if (!isset($index))
+			$index = 0;
+
+		if (!isset($start))
+			$start = date('Y-m-d\TH:i:s');
+
+		if (!isset($stop))
+			$stop = date('Y-m-d\TH:i:s');
+			
+		if (!isset($params))
+			$params = [];		 		
+		
+		$this->cache->addInterval($start, $stop, $params, true, $index);
+		
+		//$this->cache->updateIndexes();
+		
+		$this->saveToFile();
+		
+		return array('success' => true, 'index' => $index, 'status' => $this->cache->getStatus());
+	}
+	
+	public function modifyIntervalFromId($obj) {
+		if (!$this->loadFromFile())
+			return array('success' => false, 'message' => 'Cannot load cache file');
+
+		$this->cache->modifyIntervalFromId($obj);
+		
+		$this->saveToFile();
+		
+		return array('success' => true, 'status' => $this->cache->getStatus());
+	}
+	
+	public function initTTCache($nparams) {
+		//Create new cache
+		$this->cache = new CatalogCacheObject();
+		$this->cache->setParamsNumber((int)$nparams);
+		$paramHeaders = array();
+		
+		for ($i = 0; $i < (int)$nparams; $i++) {
+			$paramHeaders[$i]['id'] = 'id_'.(string)($i+1);
+			$paramHeaders[$i]['name'] = 'param_'.(string)($i+1);
+			$paramHeaders[$i]['size'] = 1;
+			$paramHeaders[$i]['type'] = 'Float';
+			
+		}
+		$this->cache->setParamsSizes($paramHeaders);
+		//Save cache file
+		return array('success' => $this->saveToFile(), 'token' => $this->cache->getToken(),
+			     'status' => $this->cache->getStatus(), 'parameters' => $paramHeaders);
+	}
    }
 ?>
\ No newline at end of file
diff --git a/php/classes/CatalogMgr.php b/php/classes/CatalogMgr.php
index f422f12..8de4a17 100644
--- a/php/classes/CatalogMgr.php
+++ b/php/classes/CatalogMgr.php
@@ -379,6 +379,37 @@ class CatalogMgr extends TimeTableMgr {
 	      );
 	  
       }
-
+      
+// 	public function modifyObject($p) {
+// 		$folder = $this->getObjectFolder($p->id);
+// 		
+// 		//Copy TT in a tempory file
+// 		$ttFilePath = USERTTDIR.$p->id.'.xml';
+// 		$tmpFileExist = FALSE;
+// 		if (file_exists($ttFilePath))
+// 			$tmpFileExist = copy($ttFilePath,$ttFilePath.".tmp");
+// 		
+// 		//Delete TT
+// 		$this->deleteObject($p);
+// 		
+// 		//Save modifications
+// 		try {
+// 			$result = $this->createObject($p, $folder);
+// 			if ($result['error'])
+// 				throw new Exception($result['error']);
+// 			if ($tmpFileExist)
+// 				unlink($ttFilePath.".tmp");
+// 			return array('id' => $p->id, 'info' => $result['nbIntervals'].' intervals' );
+// 		}
+// 		catch (Exception $e) {
+// 			//Restore TT file
+// 			if ($tmpFileExist)
+// 			{
+// 				copy($ttFilePath.".tmp", $ttFilePath);
+// 				unlink($ttFilePath.".tmp");
+// 			}
+// 			return array ('error' => $e->getMessage());
+// 		}
+// 	}
 }
 ?>
--
libgit2 0.21.2