Browse Source

Enhance error notifications

Mathieu Moulin 3 years ago
parent
commit
16f070ca5c
8 changed files with 225 additions and 79 deletions
  1. 6 1
      src/db.inc.php
  2. 121 8
      src/functions.inc.php
  3. 1 1
      src/notify.inc.php
  4. 84 56
      src/sync/sync.inc.php
  5. BIN
      web/favicon.ico
  6. BIN
      web/favicon.png
  7. 6 6
      web/sync.php
  8. 7 7
      web/syncs.php

+ 6 - 1
src/db.inc.php

@@ -263,7 +263,12 @@ public static function d_update_row($tablename, $data, $params, $data_orig=[])
 	// Limit to updated data
 	if (!empty($data_orig)) {
 		foreach($data as $i=>$j) {
-			if($j===$data_orig[$i]) {
+			// Pas censé être là...
+			if (!array_key_exists($i, $data_orig)) {
+				Throw new Exception('DB field name '.$i.' does not exists in '.$tablename);
+				unset($data[$i]);
+			}
+			elseif($j===$data_orig[$i]) {
 				unset($data[$i]);
 				unset($data_orig[$i]);
 			}

+ 121 - 8
src/functions.inc.php

@@ -1,13 +1,125 @@
 <?php
 
-function sync_error($message, $e=NULL)
+/**
+ * Erreur de synchro
+ * 
+ * @param String $localisation fichier/ligne/méthode
+ * @param String $message Information/Explication courte
+ * @param [] $context Contexte objet
+ * @param Throwable $e Exception
+ * @param String $notif_ts Raison pour non resynchronisation, il faut le qualifier au maximum, afin de soulager le processus de resynchro, ça ne sert à rien de resynchroniser à l'infini un truc qui merdouille
+ */
+function sync_error($localisation, $message, $context=[], $e=NULL, $notif_ts=NULL)
 {
-	echo '<p>ERREUR :</p>';
-	echo '<p>'.$message.'</p>';
-	if ($e)
-		var_dump($e);
-	//die(json_encode(['message'=>$message]));
-	notify($message, $e);
+	static $nb = 0;
+	static $notified = false;
+	static $notify = [];
+	
+	$nb++;
+	if (DEBUG_AFF) {
+		echo '<hr /><p>ERROR '.$nb.' :</p>'
+			.'<p>WHERE : '.$localisation.'</p>'
+			.'<p>MESSAGE : '.$message.'</p>';
+	}
+	
+	// Si on a un contexte de mise à jour
+	if (!empty($context)) { // ['type'=>static::MODEL_NAME, 'sens'=>'pd', 'action'=>'osync', 'otype'=>$otype, 'oid'=>$oid]
+		// @todo if empty($contexte['required_field'])
+
+		if (in_array($context['action'], ['delete', 'odelete']))
+			$sql_action = '`action` IN ("delete", "odelete")';
+		elseif (in_array($context['action'], ['osync', 'create']))
+			$sql_action = '`action` IN ("osync", "create")';
+		else
+			$sql_action = "FALSE";
+		
+		// Dernière demande de synchro en BDD non traitée
+		$sql = 'SELECT id, sync_errors
+			FROM `_sync`
+			WHERE type="'.$context['type'].'" AND t_name="'.$context['otype'].'" AND t_oid='.$context['oid'].'
+				AND '.$sql_action.'
+				AND sync_ts IS NULL
+			ORDER BY id DESC
+			LIMIT 1';
+		
+		if($context['sens']=='pd')
+			$q = DB::p_select($sql);
+		elseif ($context['sens']=='dp')
+			$q = DB::d_select($sql);
+		//var_dump($q->num_rows);
+		
+		// Requête OK => contexte validé
+		if (!empty($q)) {
+			$context_hash = $context['type'].'-'.$context['otype'].'-'.$context['oid'];
+			if ($q->num_rows) {
+				// On incrémente le nbre d'erreurs de la dernière synchro non achevée
+				list($sync_id, $sync_errors) = $q->fetch_row();
+				$sql = 'UPDATE _sync
+					SET sync_errors=sync_errors+1
+					WHERE id='.$sync_id;
+				if($context['sens']=='pd')
+					DB::p_update($sql);
+				elseif ($context['sens']=='dp')
+					DB::d_update($sql);
+				
+				// Raison+ts => on note pourquoi on resynchronise pas
+				if (is_string($notif_ts)) {
+					// Dernier en date
+					$sql = 'UPDATE `_sync`
+						SET `sync_ts`=NOW(), `sync_result`="'.$notif_ts.'"
+						WHERE `type`="'.$context['type'].'" AND `t_name`="'.$context['otype'].'" AND `t_oid`="'.$context['oid'].'"
+							AND '.$sql_action.'
+							AND `sync_ts` IS NULL
+						ORDER BY id DESC
+						LIMIT 1';
+					if($context['sens']=='pd')
+						DB::p_update($sql);
+					elseif ($context['sens']=='dp')
+						DB::d_update($sql);
+					// Ce qui reste (avant)
+					$sql = 'UPDATE `_sync`
+						SET `sync_ts`=NOW(), `sync_result`="cascade"
+						WHERE `type`="'.$context['type'].'" AND `t_name`="'.$context['otype'].'" AND `t_oid`="'.$context['oid'].'"
+							AND '.$sql_action.'
+							AND `sync_ts` IS NULL';
+					if($context['sens']=='pd')
+						DB::p_update($sql);
+					elseif ($context['sens']=='dp')
+						DB::d_update($sql);
+				}
+				
+				// Notify l'ensemble des erreurs des objets pour lesquels on a une demande de synchro fraiche
+				// Demande fraiche
+				if ($sync_errors==0)
+					$notify[] = $context_hash;
+				// Demande pas fraiche
+				elseif (!in_array($context_hash, $notify)) {
+					echo '<p>'.$context_hash.' NOT IN NOTIFY TABLE => on zappe on va pas plus loin</p>';
+					return;
+				}
+			}
+			// Contexte sans résultat
+			// Si on a déjà traité et validé avec ts, on envoie l'erreur, sinon on affiche une anomalie
+			elseif (!in_array($context_hash, $notify)) {
+				notify('ATTENTION! ANOMALIE? Est-ce un test manuel ? Pas d\'enregistrement _sync de demande mise à jour trouvé pour la donnée... :<br />'.$sql.'<br />Context : '.json_encode($context));
+				//return;
+			}
+		}
+		// Contexte sans résultat
+		else {
+			notify('<b>ATTENTION! ANOMALIE! requête _sync de demande mise à jour en erreur pour la donnée... :</b><br />'.$sql.'<br />Context : '.json_encode($context));
+		}
+		// Une seule fois par objet
+		if (!isset($sync_errors) || $sync_errors==0) {
+			notify('<b>ERREUR SYNCHO '.$context['action'].' '.($context['sens']=='pd' ?'Presta=>Doli' :'Doli=>Presta').' : objet '.($context['sens']=='pd' ?'Presta' :'Doli').' de type '.$context['type'].'/'.$context['otype'].' ID: '.$context['oid'].' vers objet '.($context['sens']=='pd' ?'Dolia' :'Presta').'</b>'
+				.($e ?' :<br />'.$e->getmessage() :'')
+				.'<br /><b><a href="https://'.$_SERVER['SERVER_NAME'].'/sync.php?sens='.$context['sens'].'&type='.$context['type'].'&otype='.$context['otype'].'&oid='.$context['oid'].'&action='.$context['action'].'&password='.WS_PASSWORD.'">Relancer la synchro</a></b>');
+		}
+	}
+	// Envoi de la notification
+	//echo '<p>ENVOI NOTIF MAIL : '.$localisation.'<br />'.$message.'</p>';
+	notify($localisation.'<br />'.$message, $e);
+	$notified = true;
 }
 
 function notify($message, $e=NULL)
@@ -15,10 +127,11 @@ function notify($message, $e=NULL)
 	static $notify;
 	if (empty($notify))
 		$notify = new notify();
+	
 	$message = '<p>'.$message.'</p>';
 	if ($e) {
 		$dump = ob_var_dump($e);
-		$message .= '<br />'.$dump;
+		$message .= '<br /><div style="max-height: 400px;overflow: auto;">'.$dump.'</div>';
 	}
 
 	$notify->add($message);

+ 1 - 1
src/notify.inc.php

@@ -25,7 +25,7 @@ class notify
         	$message .= '<p>GET : '.json_encode($_GET).'</p>';
         	$message .= '<p>POST : '.json_encode($_POST).'</p>';
 		$message .= '<hr style="border-top: 1px solid rgb(0,0,0);" />';
-		$message .= implode('<hr style="border-top: 1px solid rgb(0,0,0); />', $this->list);
+		$message .= implode('<hr style="border-top: 1px solid rgb(0,0,0);" />', $this->list);
         	mail(DEBUG_EMAIL_TO, 'Erreur Synchro DoliPresta', $message, 'From: '.DEBUG_EMAIL_FROM."\r\n".'Content-Type: text/html; charset="UTF-8"');
 	}
 

+ 84 - 56
src/sync/sync.inc.php

@@ -35,6 +35,14 @@ const P_TABLE_ID2 = [
 	'product_shop' => 'id_product',
 ];
 
+// Overloaded in each src/sync/model_name/common.inc.php
+//const MODEL_NAME;
+//const MODEL_ID;
+//const MAP_ID;
+//const D_TABLE_MAIN;
+//const P_TABLE_MAIN;
+//const P_TABLE_MAIN_ID;
+
 // Général
 const P_ID_LANG = 1;
 const P_ID_SHOP = 1;
@@ -157,26 +165,14 @@ public static function _class($type, $sens)
 	try {
 		require_once(SYNC_PATH.'/'.$type.'/common.inc.php');
 	} catch(Throwable $e) {
-		if (DEBUG_AFF)
-			var_dump($e);
-		sync_error("Could not load common sync class for type ".$type, $e);
-	} catch(Exception $e) {
-		if (DEBUG_AFF)
-			var_dump($e);
-		sync_error("Could not load common sync class for type ".$type, $e);
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($type, $sens)", "Could not load common sync class for type ".$type, NULL, $e);
 	}
 	
 	// Load specific direction model class
 	try {
 		require_once(SYNC_PATH.'/'.$type.'/'.$sens.'.inc.php');
 	} catch(Throwable $e) {
-		if (DEBUG_AFF)
-			var_dump($e);
-		sync_error("Could not load controller sync class for type ".$type.', sens '.$sens, $e);
-	} catch(Exception $e) {
-		if (DEBUG_AFF)
-			var_dump($e);
-		sync_error("Could not load controller sync class for type ".$type.', sens '.$sens, $e);
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($type, $sens)", "Could not load controller sync class for type ".$type.', sens '.$sens, NULL, $e);
 	}
 	
 	return $classname = 'sync_'.$type.'_'.$sens;
@@ -192,13 +188,8 @@ public static function _action($type, $sens, $action, $otype, $oid)
 		$method = 'execute_'.$action;
 		$r = $controller->$method($otype, $oid);
 	} catch(Throwable $e) {
-		if (DEBUG_AFF)
-			var_dump($e);
-		sync_error('Error executing controller '.$classname.'::'.$method.'('.$otype.','.$oid.')', $e);
-	} catch(Exception $e) {
-		if (DEBUG_AFF)
-			var_dump($e);
-		sync_error('Error executing controller '.$classname.'::'.$method.'('.$otype.','.$oid.')', $e);
+		$context = ['type'=>$type, 'sens'=>$sens, 'action'=>$action, 'otype'=>$otype, 'oid'=>$oid];
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($type, $sens, $action, $otype, $oid)", 'Error executing controller '.$classname.'::'.$method.'('.$otype.','.$oid.')', $context, $e);
 	}
 	
 	if (!empty($r))
@@ -405,13 +396,13 @@ public static function _pd_map_fk($modelname, $tablename, $id)
 
 // -- NOTIF Sync TS --
 
-public static function _notif_ts($type, $otype, $oid, $result=NULL)
+public static function _notif_ts($sens, $otype, $oid, $result=NULL)
 {
 	$sql = 'UPDATE `_sync`
 		SET `sync_ts`=NOW(), `sync_result`='.($result==NULL ?'NULL' :'"'.$result.'"').'
 		WHERE `type`="'.static::MODEL_NAME.'" AND `t_name`="'.$otype.'" AND `t_oid`="'.$oid.'" AND `action` IN ("create", "osync")
 			AND `sync_ts` IS NULL';
-	return ($type=='p' ?DB::p_update($sql) :DB::d_update($sql));
+	return ($sens=='p' ?DB::p_update($sql) :DB::d_update($sql));
 }
 
 
@@ -463,26 +454,25 @@ public function pd_create($otype, $oid)
 		'p_tref'=>$otype,
 		'p_oid'=>$oid,
 	];
+	$context = ['type'=>static::MODEL_NAME, 'sens'=>'pd', 'action'=>'create', 'otype'=>$otype, 'oid'=>$oid];
 
 	// Récupère données source
 	$p_data = $this->p_data($otype, $oid);
 	if (DEBUG_AFF)
 		var_dump($p_data);
 	if (empty($p_data[$otype])) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : Source data does not exists");
-		static::_notif_ts('p', $otype, $oid, 'nodata');
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "Source data does not exists", $context, NULL, 'nodata');
 		return;
 	}
 	
 	// Construit nouvel objet
 	$d_data_map = $d_data_map_create = $this->pd_map_create($o, $p_data);
 	if (is_null($d_data_map)) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : map_create() : NULL");
-		static::_notif_ts('p', $otype, $oid, 'nodatamap');
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "map_create() : NULL", $context, NULL, 'nodatamap');
 		return;
 	}
 	elseif (empty($d_data_map)) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : map_create() : empty");
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "map_create() : empty", $context, NULL, 'nodatamap');
 		return;
 	}
 	$d_data_map_update = $this->pd_map_update($o, $p_data);
@@ -494,8 +484,15 @@ public function pd_create($otype, $oid)
 		echo '<p>CREATION OBJETS</p>';
 	
 	// insert main row
-	if (!($id = DB::d_insert_row($o['d_tref'], $d_data_map[$o['d_tref']]))) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : DB::d_insert_row : ".json_encode($d_data_map[$o['d_tref']]));
+	try {
+		$id = DB::d_insert_row($o['d_tref'], $d_data_map[$o['d_tref']]);
+	} catch(Throwable $e) {
+		if (DEBUG_AFF)
+			var_dump($e);
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "DB::d_insert_row() : ".json_encode($d_data_map[$o['d_tref']]), $context, $e);
+	}
+	if (empty($id)) {
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "DB::d_insert_row() NO ID : ".json_encode($d_data_map[$o['d_tref']]), $context, NULL, 'db');
 		return;
 	}
 
@@ -503,7 +500,7 @@ public function pd_create($otype, $oid)
 	$o['d_oid'] = $id;
 	if (!($this->o_create($o))) {
 		// @todo : delete useless inserted data
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : o_create()");
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "o_create() returns false", $context, NULL, 'object');
 		return;
 	}
 	
@@ -534,6 +531,8 @@ public function dp_create($otype, $oid)
 		'd_tref'=>$otype,
 		'd_oid'=>$oid,
 	];
+	$context = ['type'=>static::MODEL_NAME, 'sens'=>'dp', 'action'=>'create', 'otype'=>$otype, 'oid'=>$oid];
+	
 	if (DEBUG_AFF)
 		var_dump($o);
 
@@ -542,21 +541,18 @@ public function dp_create($otype, $oid)
 	if (DEBUG_AFF)
 		var_dump($d_data);
 	if (empty($d_data[$otype])) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : Source data does not exists");
-		static::_notif_ts('d', $otype, $oid, 'nodata');
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "Source data does not exists", $context, NULL, 'nodata');
 		return;
 	}
 	
 	// Construit nouvel objet
 	$p_data_map = $p_data_map_create = $this->dp_map_create($o, $d_data);
 	if (is_null($p_data_map)) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : map_create() : NULL");
-		static::_notif_ts('d', $otype, $oid, 'nodatamap');
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "map_create() : NULL", $context, NULL, 'nodatamap');
 		return;
 	}
 	elseif (empty($p_data_map)) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : map_create() : empty");
-		//static::_notif_ts('d', $otype, $oid, 'nodatamap');
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "map_create() : empty", $context, NULL, 'nodatamap');
 		return;
 	}
 	$p_data_map_update = $this->dp_map_update($o, $d_data);
@@ -569,9 +565,17 @@ public function dp_create($otype, $oid)
 	if (DEBUG_AFF)
 		echo '<p>CREATION OBJETS</p>';
 
-	// insert main row
-	if (!($id = DB::p_insert_row($o['p_tref'], $p_data_map[$o['p_tref']]))) {
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : DB::d_insert_row() : ".json_encode($d_data_map[$o['p_tref']]));
+	try {
+		// insert main row
+		$id = DB::p_insert_row($o['p_tref'], $p_data_map[$o['p_tref']]);
+	} catch(Throwable $e) {
+		if (DEBUG_AFF)
+			var_dump($e);
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "DB::p_insert_row() : ".$o['p_tref']." -> ".json_encode($p_data_map[$o['p_tref']]), $context, $e);
+	}
+	
+	if (!isset($db) || empty($id)) {
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "DB::p_insert_row() NO ID : ".$o['p_tref']." -> ".json_encode($p_data_map[$o['p_tref']]), $context, NULL, 'db');
 		return;
 	}
 	
@@ -579,7 +583,7 @@ public function dp_create($otype, $oid)
 	$o['p_oid'] = $id;
 	if (!($this->o_create($o))) {
 		// @todo : delete useless inserted data
-		sync_error("ERROR ".__METHOD__."($otype, $oid) : o_create()");
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "o_create() returns false", $context, NULL, 'object');
 		return;
 	}
 	
@@ -608,14 +612,14 @@ public function pd_osync($o)
 {
 	if (DEBUG_AFF)
 		var_dump($o);
+	$context = ['type'=>static::MODEL_NAME, 'sens'=>'pd', 'action'=>'osync', 'otype'=>$o['p_tref'], 'oid'=>$o['p_oid']];
 	
 	// Récupère données source
 	$p_data = $this->p_data($o['p_tref'], $o['p_oid']);
 	if (DEBUG_AFF)
 		var_dump($p_data);
 	if (empty($p_data[$o['p_tref']])) {
-		sync_error("ERROR ".__METHOD__."($o[p_tref], $o[p_oid]) : Source data does not exists");
-		static::_notif_ts('p', $o['p_tref'], $o['p_oid'], 'nodata');
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($o[p_tref], $o[p_oid])", "Source data does not exists", $context, NULL, 'nodata');
 		return;
 	}
 	
@@ -635,7 +639,13 @@ public function pd_osync($o)
 	$d_data_map_create = $this->pd_map_create($o, $p_data);
 	
 	// Update base
-	static::d_update_row($o['d_tref'], ['rowid'=>$o['d_oid']], $d_data_map, $d_data_map_create, $d_data);
+	try {
+		static::d_update_row($o['d_tref'], ['rowid'=>$o['d_oid']], $d_data_map, $d_data_map_create, $d_data);
+	} catch(Throwable $e) {
+		if (DEBUG_AFF)
+			var_dump($e);
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."(".json_encode($o).")", "d_update_row() : ".json_encode($d_data_map), $context, $e);
+	}
 	
 	// Update more
 	$this->pd_update_more($o, $d_data_map, $d_data_map_create, $d_data, $p_data);
@@ -657,14 +667,14 @@ public function dp_osync($o)
 {
 	if (DEBUG_AFF)
 		var_dump($o);
+	$context = ['type'=>static::MODEL_NAME, 'sens'=>'dp', 'action'=>'osync', 'otype'=>$o['d_tref'], 'oid'=>$o['d_oid']];
 	
 	// Récupère données source
 	$d_data = $this->d_data($o['d_tref'], $o['d_oid']);
 	if (DEBUG_AFF)
 		var_dump($d_data);
 	if (empty($d_data[static::D_TABLE_MAIN])) {
-		sync_error("ERROR ".__METHOD__."($o[d_tref], $o[d_oid]) : Source data does not exists");
-		static::_notif_ts('d', $o['d_tref'], $o['d_oid'], 'nodata');
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($o[d_tref], $o[d_oid])", "Source data does not exists", $context, NULL, 'nodata');
 		return;
 	}
 
@@ -714,26 +724,44 @@ public function dp_map_update(&$o, &$d_data, &$p_data=[])
 public function pd_delete($otype, $oid)
 {
 	$o = static::p_o_oid(static::MODEL_NAME, $otype, $oid);
+	$context = ['type'=>static::MODEL_NAME, 'sens'=>'pd', 'action'=>'delete', 'otype'=>$otype, 'oid'=>$oid];
 	if (!empty($o)) {
-		DB::d_delete_row($o['d_tref'], ['rowid'=>$o['d_oid']]);
-		//DB::p_delete_row($o['p_tref']], [static::P_TABLE_ID[$o['p_tref']]]=>$o['p_oid']]);
-		$sql = 'DELETE FROM _objects WHERE id='.$o['id'];
-		DB::o_delete($sql);
-		return true;
+		if ($r=DB::d_delete_row($o['d_tref'], ['rowid'=>$o['d_oid']])) {
+			//DB::p_delete_row($o['p_tref']], [static::P_TABLE_ID[$o['p_tref']]]=>$o['p_oid']]);
+			$sql = 'DELETE FROM _objects WHERE id='.$o['id'];
+			DB::o_delete($sql);
+			return true;
+		}
+		else {
+			sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "Source data does not exists", $context, NULL, 'nodata');
+		}
+	}
+	else {
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "Source data link does not exists", $context, NULL, 'nodata');
 	}
 }
 
 public function dp_delete($otype, $oid)
 {
 	$o = static::d_o_oid(static::MODEL_NAME, $otype, $oid);
+	$context = ['type'=>static::MODEL_NAME, 'sens'=>'dp', 'action'=>'delete', 'otype'=>$otype, 'oid'=>$oid];
 	if (!empty($o)) {
-		if (empty(static::P_TABLE_ID[$o['p_tref']]))
+		if (empty(static::P_TABLE_ID[$o['p_tref']])) {
+			sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "No PK for table ".$o['p_tref'], $context);
 			return;
+		}
 		//DB::d_delete_row($o['d_tref']], ['rowid'=>$o['d_oid']]);
-		DB::p_delete_row($o['p_tref'], [static::P_TABLE_ID[$o['p_tref']]=>$o['p_oid']]);
-		$sql = 'DELETE FROM _objects WHERE id='.$o['id'];
-		DB::o_delete($sql);
-		return true;
+		if ($r=DB::p_delete_row($o['p_tref'], [static::P_TABLE_ID[$o['p_tref']]=>$o['p_oid']])) {
+			$sql = 'DELETE FROM _objects WHERE id='.$o['id'];
+			DB::o_delete($sql);
+			return true;
+		}
+		else {
+			sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "Source data does not exists", $context, NULL, 'nodata');
+		}
+	}
+	else {
+		sync_error(__FILE__.':'.__LINE__.' : '.__METHOD__."($otype, $oid)", "Source data link does not exists", $context, NULL, 'nodata');
 	}
 }
 

BIN
web/favicon.ico


BIN
web/favicon.png


+ 6 - 6
web/sync.php

@@ -5,28 +5,28 @@ require_once "bootstrap.inc.php";
 gettopost();
 
 if (! auth()) {
-	sync_error("Auth failed");
+	sync_error(__FILE__.':'.__LINE__, "Auth failed");
 	die();
 }
 
 if (empty($_POST['type']) || !is_string($type=$_POST['type'])){
-	sync_error("Bad param : type : ".(empty($_POST['type']) ?'empty' :json_encode($_POST['type'])));
+	sync_error(__FILE__.':'.__LINE__, "Bad param : type : ".(empty($_POST['type']) ?'empty' :json_encode($_POST['type'])));
 	die();
 }
 if (empty($_POST['sens']) || !is_string($sens=$_POST['sens']) || !in_array($_POST['sens'], ['pd', 'dp'])){
-	sync_error("Bad param : sens : ".(empty($_POST['sens']) ?'empty' :json_encode($_POST['sens'])));
+	sync_error(__FILE__.':'.__LINE__, "Bad param : sens : ".(empty($_POST['sens']) ?'empty' :json_encode($_POST['sens'])));
 	die();
 }
 if (empty($_POST['action']) || !is_string($action=$_POST['action']) || !in_array($_POST['action'], ['create', 'osync', 'delete'])){
-	sync_error("Bad param : action : ".(empty($_POST['action']) ?'empty' :json_encode($_POST['action'])));
+	sync_error(__FILE__.':'.__LINE__, "Bad param : action : ".(empty($_POST['action']) ?'empty' :json_encode($_POST['action'])));
 	die();
 }
 if (empty($_POST['otype']) || !is_string($otype=$_POST['otype'])){
-	sync_error("Bad param : otype : ".(empty($_POST['otype']) ?'empty' :json_encode($_POST['otype'])));
+	sync_error(__FILE__.':'.__LINE__, "Bad param : otype : ".(empty($_POST['otype']) ?'empty' :json_encode($_POST['otype'])));
 	die();
 }
 if (empty($_POST['oid']) || !is_numeric($oid=$_POST['oid'])){
-	sync_error("Bad param : oid : ".(empty($_POST['oid']) ?'empty' :json_encode($_POST['oid'])));
+	sync_error(__FILE__.':'.__LINE__, "Bad param : oid : ".(empty($_POST['oid']) ?'empty' :json_encode($_POST['oid'])));
 	die();
 }
 

+ 7 - 7
web/syncs.php

@@ -5,34 +5,34 @@ require_once "bootstrap.inc.php";
 gettopost();
 
 if (! auth()) {
-	sync_error("Auth failed");
+	sync_error(__FILE__.':'.__LINE__, "Auth failed");
 	die();
 }
 
 if (empty($_POST['sens']) || !is_string($sens=$_POST['sens']) || !in_array($_POST['sens'], ['pd', 'dp'])){
-	sync_error("Bad param : sens : ".(empty($_POST['sens']) ?'empty' :json_encode($_POST['sens'])));
+	sync_error(__FILE__.':'.__LINE__, "Bad param : sens : ".(empty($_POST['sens']) ?'empty' :json_encode($_POST['sens'])));
 	die();
 }
 if (empty($_POST['list']) || !is_array($list=$_POST['list'])){
-	sync_error("Bad param : list : ".(empty($_POST['list']) ?'empty' :json_encode($_POST['list'])));
+	sync_error(__FILE__.':'.__LINE__, "Bad param : list : ".(empty($_POST['list']) ?'empty' :json_encode($_POST['list'])));
 	die();
 }
 
 foreach($list as $r) {
 	if (empty($r['type']) || !is_string($type=$r['type'])){
-		sync_error("Bad param : type : ".json_encode($r));
+		sync_error(__FILE__.':'.__LINE__, "Bad param : type : ".json_encode($r));
 		break;
 	}
 	if (empty($r['action']) || !is_string($action=$r['action']) || !in_array($r['action'], ['create', 'osync', 'delete'])){
-		sync_error("Bad param : action : ".json_encode($r));
+		sync_error(__FILE__.':'.__LINE__, "Bad param : action : ".json_encode($r));
 		break;
 	}
 	if (empty($r['otype']) || !is_string($otype=$r['otype'])){
-		sync_error("Bad param : otype : ".json_encode($r));
+		sync_error(__FILE__.':'.__LINE__, "Bad param : otype : ".json_encode($r));
 		break;
 	}
 	if (empty($r['oid']) || !is_numeric($oid=$r['oid'])){
-		sync_error("Bad param : oid : ".json_encode($r));
+		sync_error(__FILE__.':'.__LINE__, "Bad param : oid : ".json_encode($r));
 		break;
 	}
 	sync::_action($type, $sens, $action, $otype, $oid);