Browse Source

Dynamisation des Types (peux causer des régressions)

idleman 6 years ago
parent
commit
1637e11a31

+ 57 - 27
action.php

@@ -1,4 +1,4 @@
-<?php
+<?php
 
 require_once __DIR__.DIRECTORY_SEPARATOR."common.php";
 
@@ -84,18 +84,24 @@ switch ($_['action']){
 			$response['sketch'] = $sketch->toArray();
 			$response['resources'] = array();
 			
-			foreach(Resource::loadAll(array('sketch'=>$_['id'])) as $resource)
-				$response['resources'][] = Type::toExport($resource);
+			$types = ResourceType::all();
+			foreach(Resource::loadAll(array('sketch'=>$_['id'])) as $resource){
+				$type = $types[$resource->type];
+				$response['resources'][] = $type['class']::toJson($resource);
+			}
 
 		
 		}catch(Exception $e){
 			$response['error'] = $e->getMessage();
 		}
-	
+		
+
 		$response = gzdeflate(json_encode($response));
 		
+		
 		if(!isset($_['api'])){
 			$filename = slugify($sketch->label).('.export.').date('d-m-Y_H-i').'.json';
+			ob_end_clean();
 			header("Content-Type: application/json");
 			header("Content-Length: " . strlen($response));
 			header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
@@ -130,6 +136,7 @@ switch ($_['action']){
 			$stream = false;
 			try{ $stream = @file_get_contents($contentPath); }catch(Exception $a){}
 			if($stream === false) throw new Exception("Impossible d'atteindre le contenu hackpoint : $contentPath ");
+			
 			$stream = gzinflate($stream);
 			if($stream === false) throw new Exception('Impossible de décompresser le sketch...');
 			$json = json_decode($stream,true);
@@ -147,9 +154,17 @@ switch ($_['action']){
 			$sketch->save();
 			
 			
-			
-			foreach($json['resources'] as $res)
-				Type::fromImport($res,$sketch);
+			$types = ResourceType::all();
+			foreach($json['resources'] as $res){
+				$resource = new Resource();
+				$resource->fromArray($res);
+				$resource->id = null;
+				$resource->sketch = $sketch->id;
+				$type = $types[$resource->type];
+				
+				$resource = $type['class']::fromJson($resource);
+				$resource->save();
+			}
 
 		});
 	break;
@@ -206,21 +221,25 @@ switch ($_['action']){
 
 	case 'download_sketch':
 
+
 		$sketch = Sketch::getByid($_['id']);
 		$resources = Resource::loadAll(array('sketch'=>$sketch->id),'sort');
 		
 		$filename = $sketch->slug.'-'.time().'.zip';
 		$filepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.$filename;
 		$zip = new ZipArchive;
+
 		$res = $zip->open($filepath, ZipArchive::CREATE);
 		if ($res === TRUE) {
 			foreach($resources as $resource){
-				$type = Type::get($resource->type);
-				$file = Type::toFileStream($resource);
-				$zip->addFromString($file->name, $file->content);
+				$type = ResourceType::all($resource->type);
+				$file = $type['class']::toFile($resource);
+
+				$zip->addFromString($file['name'], $file['content']);
 			}
 			$zip->close();
 		}
+		ob_end_clean();
 		header("Content-Type: application/zip");
 		header("Content-Length: " . filesize($filepath));
 		header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
@@ -250,12 +269,10 @@ switch ($_['action']){
 			
 			$resource->content = $name;
 			$resource->save();
-			$response = array_merge(Type::get($resource->type));
-			//$response['url'] = $path.'?v='.time();
-			
+
+			$response = array_merge(ResourceType::all($resource->type));
 			$response['url'] ="action.php?action=get_resource_image&id=".$resource->id."&v=".time();
-			
-			
+		
 		});
 	break;
 	
@@ -275,7 +292,7 @@ switch ($_['action']){
 			$path = $folder.'/'.$_FILES['file']['name'];
 			
 			move_uploaded_file($_FILES['file']['tmp_name'], $path);
-			$response = array_merge(Type::get($resource->type));
+			$response = array_merge(ResourceType::all($resource->type));
 			$response['url'] = $path.'?v='.time();
 		});
 	break;
@@ -302,16 +319,21 @@ switch ($_['action']){
 		if($myUser->id != $sketch->owner) return;
 		$ext = explode('.',$_FILES['file']['name']);
 		$ext = strtolower(array_pop($ext));
-		$types = Type::all();
-		$type = 'readme';
+		$types = ResourceType::all();
+		$type = ResourceType::all('readme');
 		foreach($types as $uid=>$tp){
-			if(!isset($tp['extension'])) continue;
-			foreach($tp['extension'] as $ext2){
-				if($ext == $ext2) $type = $uid;
-			}
-			
+			if(!isset($tp['fromExtension'])) continue;
+			if(in_array($ext, $tp['fromExtension'])) $type = $tp;
 		}
-		Type::fromFileImport($_FILES['file'],$sketch,$type);
+	
+		$resource = new Resource();
+		$resource->sketch = $sketch->id;
+		$stream = file_get_contents($_FILES['file']['tmp_name']);
+		$resource->label = $_FILES['file']['name'];
+		$resource->type = $type['uid'];
+		$resource->content = $stream;
+		$resource = $type['class']::fromFile($resource,$sketch);
+		$resource->save();
 		
 	break;
 
@@ -514,12 +536,20 @@ switch ($_['action']){
 	
 	case 'edit_resource':
 		Action::write(function($_,&$response){
-		
+			if(!isset($_['id']) ||  empty($_['id']) || $_['id']==0) return;
 			$resource = Resource::getById($_['id']);
+			if(!$resource) return;
 			global $myUser;
 			$sketch = Sketch::getById($resource->sketch);
 			$resource->label = html_entity_decode($resource->label);
-			$response = Type::toHtml($resource,$sketch);
+			$response = $resource->toArray();
+
+			$type = ResourceType::all($resource->type);
+			$response = array_merge($response,$type['class']::toHtml($resource,$sketch));
+			if(isset($response['codemirror'])) $response['code'] = $response['codemirror'];
+			if($myUser->id != $sketch->owner) $response['code']['readOnly'] = true;
+	
+			
 		});
 	break;
 	case 'delete_resource':
@@ -577,7 +607,7 @@ switch ($_['action']){
 				
 				$zip->close();
 			}
-		
+			ob_end_clean();
 			header("Content-Type: application/zip");
 			header("Content-Length: " . filesize($filepath));
 			header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');

+ 1 - 0
class/Action.class.php

@@ -45,6 +45,7 @@ class Action
         } catch (Exception $e) {
             $response['errors'][] = $e->getMessage();
         }
+        
         echo json_encode($response);
         restore_error_handler();
     }

+ 35 - 0
class/ResourceType.class.php

@@ -0,0 +1,35 @@
+<?php
+
+class ResourceType{
+	
+	public $user,$type;
+	protected $fields =
+    array(
+        'id' => 'key',
+        'user' => 'string',
+        'type' => 'string'
+    );
+
+	public static function all($target=null){
+		$rawtypes = array();
+		Plugin::callHook('resource_type',array(&$rawtypes));
+		$types = array();
+		foreach($rawtypes as $uid=>$file){
+			if(isset($target) && $uid!=$target) continue;
+			$class = str_replace('.class.php','',basename($file));
+			require_once($file);
+			if(!method_exists ( $class , 'toHtml' )) continue;
+			if(!method_exists ( $class , 'toJson' )) continue;
+			if(!method_exists ( $class , 'toFile' )) continue;
+			if(!method_exists ( $class , 'fromJson' )) continue;
+			if(!method_exists ( $class , 'fromFile' )) continue;
+        	$types[$uid] = $class::manifest();
+        	$types[$uid]['file'] =$file;
+        	$types[$uid]['class'] = $class;
+    	}
+		return isset($target) ? $types[$target] : $types;
+	}
+
+}
+
+?>

+ 20 - 0
common.php

@@ -27,3 +27,23 @@
         $myUser =unserialize($_SESSION['currentUser']);
     }
     Plugin::includeAll();
+
+    Plugin::addHook('resource_type',function(&$types){
+        $types['readme'] = __DIR__.SLASH.'type'.SLASH.'Readme.class.php';
+        $types['arduino'] = __DIR__.SLASH.'type'.SLASH.'Arduino.class.php';
+        $types['c'] = __DIR__.SLASH.'type'.SLASH.'Arduino.class.php';
+        $types['shell'] = __DIR__.SLASH.'type'.SLASH.'C.class.php';
+        $types['php'] = __DIR__.SLASH.'type'.SLASH.'Php.class.php';
+        $types['xml'] = __DIR__.SLASH.'type'.SLASH.'Xml.class.php';
+        $types['python'] = __DIR__.SLASH.'type'.SLASH.'Python.class.php';
+        $types['java'] = __DIR__.SLASH.'type'.SLASH.'Java.class.php';
+        $types['css'] = __DIR__.SLASH.'type'.SLASH.'Css.class.php';
+        $types['javascript'] = __DIR__.SLASH.'type'.SLASH.'Javascript.class.php';
+        $types['json'] = __DIR__.SLASH.'type'.SLASH.'Json.class.php';
+        $types['image'] = __DIR__.SLASH.'type'.SLASH.'Image.class.php';
+        $types['files'] = __DIR__.SLASH.'type'.SLASH.'File.class.php';
+        $types['part'] = __DIR__.SLASH.'type'.SLASH.'PartType.class.php';
+    });
+    
+
+?>

+ 4 - 5
function.php

@@ -4,7 +4,10 @@ function secondToTime($seconds) {
   return sprintf('%02d:%02d:%02d', ($t/3600),($t/60%60), $t%60);
 }
 function app_autoloader($class_name) {
-		require_once('class/'.$class_name.'.class.php');
+	if(file_exists(__DIR__.'/class/'.$class_name.'.class.php'))
+		require_once(__DIR__.'/class/'.$class_name.'.class.php');
+	if(file_exists(__DIR__.'/type/'.$class_name.'.class.php'))
+		require_once(__DIR__.'/type/'.$class_name.'.class.php');
 }
 function errorToException( $errno, $errstr, $errfile, $errline, $errcontext)
 {
@@ -180,8 +183,4 @@ function imageResize($image,$w,$h){
 	imagejpeg($thumbnail , $image, 100);
 }
 
-
-
-
-
 ?>

+ 15 - 0
header.php

@@ -106,6 +106,21 @@ Plugin::addHook("menu_main", function(&$menuItems){
                             <li ><a href="account.php">Profil</a></li>
                             
                             <li class="divider"></li>
+                            <?php 
+						$menuItems = array();
+						Plugin::callHook("menu_setting",array(&$menuItems)); 
+						
+						usort($menuItems, function($a, $b){
+							if ($a['sort'] == $b['sort']) {
+						        return 0;
+						    }
+						    return ($a['sort'] < $b['sort']) ? -1 : 1;
+						});
+
+						foreach($menuItems as $item): ?>
+								<li><a href="<?php echo $item['url'];?>"><?php echo $item['label'];?></a></li>
+							<?php endforeach;?>
+
                             <li><a href="action.php?action=logout">Déconnexion</a></li>
                           </ul>
                         </li>

+ 10 - 0
install.php

@@ -69,11 +69,21 @@ try {
 	//Class entities
 	Entity::install(__ROOT__.'class');
 
+
+
     $admin = new User();
     $admin->login = 'admin';
     $admin->password = User::password_encrypt('admin');
     $admin->rank = 'ADMIN';
     $admin->save();
+
+    foreach(array('readme','arduino') as $rt){
+       $resourceType = new ResourceType();
+       $resourceType->user = $admin->login;
+       $resourceType->type = $rt;
+       $resourceType->save();
+    }
+
     ?>
 
 <div class="alert alert-success alert-dismissable">

+ 21 - 0
plugin/modele/Arduino.class.php

@@ -0,0 +1,21 @@
+<?php 
+class Arduino extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'arduino',
+			'label' => 'Arduino',
+			'description' => 'Fichier contenant du langage arduino (proche du c++)',
+			'fromExtension' => array('ino'),
+			'toExtension' => 'ino',
+			'codemirror' => array(
+				'mode'=>'text/x-carduino',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 57 - 0
plugin/modele/Readme.class.php

@@ -0,0 +1,57 @@
+<?php
+class Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'readme',
+			'label' => 'README',
+			'description' => 'Fichier texte de type "lisez moi", utilise du markdown pour la mise en forme',
+			'fromExtension' => array('md'),
+			'toExtension' => 'md',
+			'codemirror' => array(
+				'mode'=>'markdown',
+				//'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+
+	//Import depuis un glisser déposé du fichier
+	public static function fromFile($resource){
+		$enc = mb_detect_encoding($resource->content,"UTF-8, ISO-8859-1, GBK");
+		if($enc!='UTF-8')
+			$resource->content = iconv($enc,"utf-8",$resource->content); 
+	
+		return $resource;
+	}
+
+	//Import depuis un flux json compressé de la ressource
+	public static function fromJson($resource){
+		return $resource;
+	}
+	
+	//export en fichier JSON compressé de la ressource
+	public static function toJson($resource){
+		$resource = $resource->toArray();
+		$resource['content'] = htmlspecialchars($resource['content']);
+		return $resource;
+	}
+
+	public static function toFile($resource){
+		$infos = self::manifest();
+		return array(
+			'name'=> slugify($resource->label).'.'.$infos['toExtension'],
+			'content' => html_entity_decode($resource->content)
+		);
+	}
+
+	public static function toHtml($resource){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => $infos['codemirror']
+		);
+	}
+}
+?>

+ 29 - 1
plugin/modele/modele.plugin.php

@@ -12,9 +12,23 @@ function test_plugin_menu(&$menuItems){
 	);
 }
 
+function test_plugin_menu_setting(&$menuItems){
+	global $_;
+	$menuItems[] = array(
+	'sort'=>10,
+	'url'=>'setting.php?module=modele',
+	'label'=>'Modele',
+	'icon'=>'codepen'
+	);
+}
+
+function test_plugin_add_type(&$types){
+	$types['readme'] = __DIR__.SLASH.'Readme.class.php';
+	$types['readme'] = __DIR__.SLASH.'Arduino.class.php';
+}
 
 
-//Cette fonction va generer une page quand on clique sur Modele dans menu
+//Cette fonction va generer une page quand on clique sur Modele dans menu général
 function test_plugin_page(){
 	global $_;
 	if(!isset($_['module']) || $_['module']!='modele') return;
@@ -25,6 +39,17 @@ function test_plugin_page(){
 <?php
 }
 
+//Cette fonction va generer une page quand on clique sur Modele dans menu setting
+function test_plugin_page_setting(){
+	global $_;
+	if(!isset($_['module']) || $_['module']!='modele') return;
+	?>
+	<h3>Réglages Mon plugin</h3>
+	<h5>Plugins d'exemple</h5>
+	
+<?php
+}
+
 function test_plugin_install($id){
 	if($id != 'fr.idleman.modele') return;
 	// en cas d'erreur : throw new Exception('Mon erreur');
@@ -53,6 +78,9 @@ Plugin::addHook("uninstall", "test_plugin_uninstall");
 Plugin::addHook("section", "test_plugin_section");
 Plugin::addHook("menu_main", "test_plugin_menu"); 
 Plugin::addHook("page", "test_plugin_page");  
+Plugin::addHook("menu_setting", "test_plugin_menu_setting"); 
+Plugin::addHook("page_setting", "test_plugin_page_setting");  
 Plugin::addHook("action", "test_plugin_action");    
+Plugin::addHook("resource_type", "test_plugin_add_type");    
 
 ?>

+ 5 - 0
setting.php

@@ -0,0 +1,5 @@
+<?php 
+require_once __DIR__.DIRECTORY_SEPARATOR.'header.php'; 
+Plugin::callHook("page_setting"); 
+require_once __ROOT__.'footer.php' 
+?>

+ 9 - 4
sketch.php

@@ -12,6 +12,8 @@ try {
         throw new Exception("Sketch privé, demandez à son propriétaire de le rendre publique");
     }
 
+    $types = ResourceType::all();
+    
     ?>
 <div class="row" id="sketch" data-id="<?php echo $sketch->id;
     ?>">
@@ -46,9 +48,11 @@ try {
 					<span class="sr-only">Toggle Dropdown</span>
 				  </button>
 				  <ul class="dropdown-menu" role="menu">
-					<?php foreach (Type::all() as $uid=>$type): ?>
+					<?php foreach ($types as $uid=>$type): ?>
 					<li><a onclick="add_resource('<?php echo $uid;
-    ?>');"><?php echo $type['label'];
+    ?>');"><?php 
+          require_once($type['file']);
+          echo $type['label'];
     ?></a></li>
 					<?php endforeach;
     ?>
@@ -97,7 +101,7 @@ try {
       <div class="modal-body">
 	  <label for="type">Type</label>
        <select class="form-control" id="type">
-       	<?php foreach (Type::all() as $uid=>$type): ?>
+       	<?php foreach ($types as $uid=>$type): ?>
        	<option value="<?php echo $uid;
     ?>"><?php echo $type['label'];
     ?></option>
@@ -144,7 +148,8 @@ try {
 
 <?php 
 } catch (Exception $e) {
+
     $_SESSION['error'] = $e->getMessage();
-    header('location: index.php');
+    echo $_SESSION['error'];
 }
 require_once __ROOT__.'footer.php' ?>

+ 28 - 0
type/Arduino.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Arduino extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'arduino',
+			'label' => 'Arduino',
+			'description' => 'Fichier contenant du langage arduino (proche du c++)',
+			'fromExtension' => array('ino'),
+			'toExtension' => 'ino'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'text/x-carduino',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 28 - 0
type/C.class.php

@@ -0,0 +1,28 @@
+<?php 
+class C extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'clike',
+			'label' => 'Source C++/C',
+			'description' => 'Fichier contenant du langage c,c++ ou proche (clike)',
+			'fromExtension' => array('c','cpp','h','hpp'),
+			'toExtension' => 'cpp'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'clike',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 28 - 0
type/Css.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Css extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'css',
+			'label' => 'Css',
+			'description' => 'Feuille de style CSS',
+			'fromExtension' => array('css','scss'),
+			'toExtension' => 'css'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'css',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 129 - 0
type/File.class.php

@@ -0,0 +1,129 @@
+<?php
+class File {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'files',
+			'label' => 'Set de fichiers',
+			'description' => 'Ensemble de fichiers attachés',
+			'fromExtension' => array('zip','7z'),
+			'toExtension' => 'zip',
+			'upload' => array(
+				'url'=>'action.php?action=upload_resource_file',
+				'element' => '#dropZoneFiles',
+				'callback' => "search_file();",
+			)
+		);
+	}
+
+	//Import depuis un glisser déposé du fichier
+	public static function fromFile($resource){
+		$resource->save();
+		
+		$path = SKETCH_PATH.'/'.$resource->id;
+		if(!file_exists($path)) mkdir($path);
+
+
+		$filepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.$resource->label.'-'.time();
+		if(file_exists($filepath))unlink($filepath); 
+		file_put_contents($filepath, $resource->content);
+
+		$zip = new ZipArchive;
+		$res = $zip->open($filepath);
+		if ($res === TRUE) {
+		  $zip->extractTo($path);
+		  $zip->close();
+		}
+		$resource->content = '';
+
+		return $resource;
+	}
+
+	//Import depuis un flux json compressé de la ressource
+	public static function fromJson($resource){
+		
+		$files = $resource->content;
+		$resource->content = '';
+		$resource->save();
+		$folder = SKETCH_PATH.'/'.$resource->id;
+		if(!file_exists($folder)) mkdir($folder);
+		foreach($files as $file):
+			$stream = base64_decode($file['stream']);
+			file_put_contents($folder.'/'.$file['label'],$stream);
+		endforeach;
+
+		return $resource;
+	}
+	
+	//export en fichier JSON compressé de la ressource
+	public static function toJson($resource){
+		$resource = $resource->toArray();
+
+
+
+		$resource->content = array();
+		$folder = SKETCH_PATH.'/'.$resource->id;
+		foreach(glob($folder.'/*') as $file):
+			$resource->content[] = array('label'=>basename($file),'stream'=>base64_encode(file_get_contents($file)));
+		endforeach;
+
+		return $resource;
+	}
+
+	public static function toFile($resource){
+		global $myUser;
+		$infos = self::manifest();
+		$path = SKETCH_PATH.'/'.$resource->id;
+
+		$filename = $resource->label.'-'.time().'.'.$infos['toExtension'];
+		$filepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.$filename;
+		$zip = new ZipArchive;
+		if(file_exists($filepath))unlink($filepath); 
+		$res = $zip->open($filepath, ZipArchive::CREATE);
+		if ($res === TRUE) {
+			foreach(glob($path.'/*') as $f)
+				$zip->addFile($f,basename($f));
+			
+			$zip->close();
+		}
+	
+		
+		return array(
+			'name'=> slugify($resource->label).'.'.$infos['toExtension'],
+			'content' => file_get_contents($filepath)
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		global $myUser;
+		$infos = self::manifest();
+
+		if($myUser->id == $sketch->owner){
+			$response['upload'] = $infos['upload'];
+			$response['content'] = '<div id="dropZoneFiles"><i class="fa fa-file-text-o"></i> Faites glisser vos fichiers ici</div>';
+}
+		$response['callback'] = 'init_file();';
+		$response['content'] .= '<table class="table table-stripped table-bordered" id="files"><thead>
+			<tr>
+				<th>Fichiers disponibles <a class="btn btn-primary" href="action.php?action=download_file&resource='.$resource->id.'" style="float:right;" title="Télécharger les fichiers"><i class="fa fa-file-zip-o"></i> Télécharger</a></th>';
+		
+		$response['content'] .= '<th style="width:50px;"></th>';
+				
+		$response['content'] .= '</tr></thead><tbody>';
+		
+		$response['content'] .= '<tr style="display:none" data-id="{{id}}">
+				<td ><a href="action.php?action=get_resource_file&id={{resource}}&file={{label}}"><i class="fa {{icon}}"></i> {{label}}</a></td>';
+		
+		
+			$response['content'] .= '<td>';
+			if($myUser->id == $sketch->owner)
+			$response['content'] .= '<div class="btn btn-danger btn-mini btn-rounded pulse" onclick="delete_file(this);"><i class="fa fa-times" ></i></div>';
+			$response['content'] .= '</td>';
+		
+		$response['content'] .= '</tr>';
+		$response['content'] .='</tbody></table>';
+		
+		return $response;
+	}
+}
+?>

+ 66 - 0
type/Image.class.php

@@ -0,0 +1,66 @@
+<?php
+class Image {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'image',
+			'label' => 'Image',
+			'description' => 'Fichier image de type jpg/jpeg/png/bmp/gif/svg',
+			'fromExtension' => array('jpg','jpeg','png','bmp','gif','svg'),
+			'upload' => array(
+				'url'     => 'action.php?action=upload_resource',
+				'element' => '#resource p img:eq(0)',
+				'callback' => '$(\'#resource img:eq(0)\').attr(\'src\',r.url);'
+			)
+		);
+	}
+
+	//Import depuis un glisser déposé du fichier
+	public static function fromFile($resource){
+		$resource->save();
+		$ext = getExt($resource->label);
+		$name = $resource->id.'.'.$ext;
+		file_put_contents(SKETCH_PATH.$name,$resource->content);
+		$resource->content = $name;
+		return $resource;
+	}
+
+	//Import depuis un flux json compressé de la ressource
+	public static function fromJson($resource){
+		$resource->save();
+		$stream = base64_decode($resource->content);
+		$resource->content = $resource->id.'.png';
+		file_put_contents(SKETCH_PATH.$resource->content,$stream);
+		return $resource;
+	}
+	
+	//export en fichier JSON compressé de la ressource
+	public static function toJson($resource){
+		$resource = $resource->toArray();
+		$resource['content'] = base64_encode(file_get_contents(SKETCH_PATH.$resource['content']));
+		return $resource;
+	}
+
+	public static function toFile($resource){
+
+		$ext = getExt($resource->content);
+		$infos = self::manifest();
+		return array(
+			'name'=> slugify($resource->label).'.'.$ext,
+			'content' => file_exists(SKETCH_PATH.$resource->content) ? file_get_contents(SKETCH_PATH.$resource->content) : ''
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		global $myUser;
+		$infos = self::manifest();
+
+		$image = $resource->content ==''?'img/default_image.png':'action.php?action=get_resource_image&id='.$resource->id;
+		$response['content'] = '<img style="width:100%;height:auto;" class="dropzone" src="'.$image.'" />';
+		if($myUser->id == $sketch->owner)
+			$response['upload'] = $infos['upload'];
+		
+		return $response;
+	}
+}
+?>

+ 28 - 0
type/Java.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Java extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'java',
+			'label' => 'Java',
+			'description' => 'Langage JAVA (il faut de tout pour faire un monde...)',
+			'fromExtension' => array('java','jsp','jar'),
+			'toExtension' => 'java'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'java',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 28 - 0
type/Javascript.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Javascript extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'javascript',
+			'label' => 'Javascript',
+			'description' => 'Langage javascript client/serveur',
+			'fromExtension' => array('js'),
+			'toExtension' => 'js'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'javascript',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 28 - 0
type/Json.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Json extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'json',
+			'label' => 'Json',
+			'description' => 'Structure JSON (notation objet javascript)',
+			'fromExtension' => array('json'),
+			'toExtension' => 'json'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'javascript',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 130 - 0
type/PartType.class.php

@@ -0,0 +1,130 @@
+<?php
+class PartType {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'part',
+			'label' => 'Set de composants',
+			'description' => 'Ensemble de composants éléctroniques (ou autres)',
+			'fromExtension' => array('part'),
+			'toExtension' => 'txt'
+		);
+	}
+
+	//Import depuis un glisser déposé du fichier
+	public static function fromFile($resource){
+		
+		//TODO
+		
+		return $resource;
+	}
+
+	//Import depuis un flux json compressé de la ressource
+	public static function fromJson($resource){
+		global $myUser;
+		$parts = $resource->content;
+		$resource->content = '';
+		foreach($parts as $p):
+				
+			$part = new Part();
+			$part->fromArray($p['part']);
+			$part->id = null;
+			$stream = base64_decode($part->image);
+			$part->owner = $myUser->id;
+			$part->save();
+			$name = $part->id.'.png';
+			file_put_contents(PART_PATH.$name,$stream);
+			$part->image = $name;
+			$part->save();
+			
+					
+			$resourcePart = new ResourcePart();
+			$resourcePart->fromArray($p['resourcePart']);
+			$resourcePart->id = null;
+			$resourcePart->part = $part->id;
+			$resourcePart->resource = $resource->id;
+			$resourcePart->save();
+			
+		endforeach;
+		$resource->content = '';
+
+		return $resource;
+	}
+	
+	//export en fichier JSON compressé de la ressource
+	public static function toJson($resource){
+		$resource = $resource->toArray();
+
+		$resource['content'] = array();
+		foreach(ResourcePart::loadAll(array('resource'=>$resource['id'])) as $resourcePart):
+			$part = $resourcePart->part_object;
+			$part = $part->toArray();
+			$resourcePart = $resourcePart->toArray();
+			if($part['image']!='') $part['image'] = base64_encode(file_get_contents(PART_PATH.$part['image']));
+			$resource['content'][] = array('resourcePart'=>$resourcePart,'part'=>$part);
+		endforeach;
+
+		return $resource;
+	}
+
+	public static function toFile($resource){
+		global $myUser;
+		$infos = self::manifest();
+		
+		$content = '> '.strtoupper($resource->label).PHP_EOL;
+		$content .= str_repeat('=',strlen($resource->label)+2).PHP_EOL;
+		foreach(ResourcePart::loadAll(array('resource'=>$resource->id)) as $resourcePart):
+			$part = $resourcePart->part_object;
+			$content .= $part->label."\t";
+			if(isset($part->link) && !empty($part->link)) $content .= $part->link."\t";
+			if(isset($part->brand) && !empty($part->brand)) $content .= '('.$part->brand.")\t";
+			if(isset($part->price) && !empty($part->price)) $content .= $part->price.'€';
+			$content .= PHP_EOL;
+		endforeach;
+	
+		
+		return array(
+			'name'=> slugify($resource->label).'.'.$infos['toExtension'],
+			'content' => $content
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		global $myUser;
+		
+
+		$response['callback'] = 'init_part();';
+		$response['content'] = '<table class="table table-stripped table-bordered" id="parts"><thead>
+			<tr>
+				<th>Libellé</th>
+				<!--<th>Lien</th>
+				<th>Prix</th>-->';
+		if($myUser->id == $sketch->owner)
+				$response['content'] .= '<th></th>';
+				
+		$response['content'] .= '</tr>';
+			
+		if($myUser->id == $sketch->owner){
+			$response['content'] .= '<tr id="partForm" data-action="save_part" data-id="">
+				<td><input type="text" id="label" class="form-control"></td>
+				<!--<td><input type="url" id="link"  class="form-control"></td>
+				<td><input type="text" id="price"  class="form-control input-mini"></td>-->
+				<td><div class="btn btn-success" onclick="save_part();"><i class="fa fa-plus"></i></div></td>
+			</tr>';
+		}
+			
+		$response['content'] .= '</thead><tbody>';
+		
+		$response['content'] .= '<tr style="display:none" data-id="{{id}}">
+				<td ><a href="{{link}}"><div class="componentImage"><img src="{{image}}"/></div> {{label}}</a> {{#price}}<code>{{price}} €</code>{{/price}}{{#brand}} <small>{{brand}}</small>{{/brand}}</td>';
+		
+		if($myUser->id == $sketch->owner)
+			$response['content'] .= '<td><div class="btn btn-danger btn-mini btn-rounded pulse" onclick="delete_part(this);"><i class="fa fa-times" ></i></div></td>';
+		
+		$response['content'] .= '</tr>';
+		$response['content'] .='</tbody></table>';
+		
+		return $response;
+	}
+}
+?>

+ 28 - 0
type/Php.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Php extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'php',
+			'label' => 'PHP',
+			'description' => 'Fichier PHP',
+			'fromExtension' => array('php','phar'),
+			'toExtension' => 'php'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'php',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 28 - 0
type/Python.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Python extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'python',
+			'label' => 'Python',
+			'description' => 'Fichier python',
+			'fromExtension' => array('py'),
+			'toExtension' => 'py'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'python',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 56 - 0
type/Readme.class.php

@@ -0,0 +1,56 @@
+<?php
+class Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'readme',
+			'label' => 'README',
+			'description' => 'Fichier texte de type "lisez moi", utilise du markdown pour la mise en forme',
+			'fromExtension' => array('md'),
+			'toExtension' => 'md'
+		);
+	}
+
+	//Import depuis un glisser déposé du fichier
+	public static function fromFile($resource,$sketch){
+		$enc = mb_detect_encoding($resource->content,"UTF-8, ISO-8859-1, GBK");
+		if($enc!='UTF-8')
+			$resource->content = iconv($enc,"utf-8",$resource->content); 
+	
+		return $resource;
+	}
+
+	//Import depuis un flux json compressé de la ressource
+	public static function fromJson($resource){
+		return $resource;
+	}
+	
+	//export en fichier JSON compressé de la ressource
+	public static function toJson($resource){
+		$resource = $resource->toArray();
+		$resource['content'] = htmlspecialchars($resource['content']);
+		return $resource;
+	}
+
+	public static function toFile($resource){
+		$infos = self::manifest();
+		return array(
+			'name'=> slugify($resource->label).'.'.$infos['toExtension'],
+			'content' => html_entity_decode($resource->content)
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'markdown',
+				//'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+}
+?>

+ 28 - 0
type/Shell.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Shell extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'shell',
+			'label' => 'Shell',
+			'description' => 'Script shell (linux, windows...)',
+			'fromExtension' => array('sh','bat'),
+			'toExtension' => 'sh'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'shell',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>

+ 28 - 0
type/Xml.class.php

@@ -0,0 +1,28 @@
+<?php 
+class Xml extends Readme {
+
+	public static function manifest(){
+		return array(
+			'uid' => 'xml',
+			'label' => 'Html & XML',
+			'description' => 'Fichier contenant du html',
+			'fromExtension' => array('html','xml'),
+			'toExtension' => 'html'
+		);
+	}
+
+	public static function toHtml($resource,$sketch){
+		$infos = self::manifest();
+		return array(
+			'content'=>'<textarea>'.$resource->content.'</textarea>',
+			'codemirror' => array(
+				'mode'=>'htmlmixed',
+				'theme'=>'monokai',
+				'lineNumbers' => true,
+				'readOnly' =>  false
+			)
+		);
+	}
+	
+}
+?>