diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index f1ec086cd03..b1b6de3eb03 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4807,7 +4807,7 @@ abstract class CommonObject { if(is_array($info)) { - if(isset($info['type']) && $info['type']=='float') return true; + if (isset($info['type']) && (preg_match('/^(double|real)/i', $info['type']))) return true; else return false; } else return false; @@ -4846,49 +4846,58 @@ abstract class CommonObject } /** - * Function to prepare the values to insert + * Function to prepare the values to insert. + * Note $this->${field} are set by the page that make the createCommon or the updateCommon. * * @return array */ private function set_save_query() { - $query=array(); - foreach ($this->fields as $field=>$info) + global $conf; + + $queryarray=array(); + foreach ($this->fields as $field=>$info) // Loop on definition of fields { + // Depending on field type ('datetime', ...) if($this->isDate($info)) { if(empty($this->{$field})) { - $query[$field] = NULL; + $queryarray[$field] = NULL; } else { - $query[$field] = $this->db->idate($this->{$field}); + $queryarray[$field] = $this->db->idate($this->{$field}); } } else if($this->isArray($info)) { - $query[$field] = serialize($this->{$field}); + $queryarray[$field] = serialize($this->{$field}); } else if($this->isInt($info)) { - $query[$field] = (int) price2num($this->{$field}); + if ($field == 'entity' && is_null($this->{$field})) $queryarray[$field]=$conf->entity; + else + { + $queryarray[$field] = (int) price2num($this->{$field}); + if (empty($queryarray[$field])) $queryarray[$field]=0; // May be rest to null later if property 'nullifempty' is on for this field. + } } else if($this->isFloat($info)) { - $query[$field] = (double) price2num($this->{$field}); - } - elseif($this->isNull($info)) - { - $query[$field] = (is_null($this->{$field}) || (empty($this->{$field}) && $this->{$field}!==0 && $this->{$field}!=='0') ? null : $this->{$field}); + $queryarray[$field] = (double) price2num($this->{$field}); + if (empty($queryarray[$field])) $queryarray[$field]=0; } else { - $query[$field] = $this->{$field}; + $queryarray[$field] = $this->{$field}; } + + if ($info['type'] == 'timestamp' && empty($queryarray[$field])) unset($queryarray[$field]); + if (! empty($info['nullifempty']) && empty($queryarray[$field])) $queryarray[$field] = null; } - return $query; + return $queryarray; } /** @@ -4947,15 +4956,14 @@ abstract class CommonObject /** * Add quote to field value if necessary * - * @param string|int $value value to protect - * @return string|int + * @param string|int $value Value to protect + * @param array $fieldsentry Properties of field + * @return string */ - protected function quote($value) { - - if(is_null($value)) return 'NULL'; - else if(is_numeric($value)) return $value; - else return "'".$this->db->escape( $value )."'"; - + protected function quote($value, $fieldsentry) { + if (is_null($value)) return 'NULL'; + else if (preg_match('/^(int|double|real)/i', $fieldsentry['type'])) return $this->db->escape("$value"); + else return "'".$this->db->escape($value)."'"; } @@ -4970,23 +4978,27 @@ abstract class CommonObject { $error = 0; - $fields = array_merge(array('datec'=>$this->db->idate(dol_now())), $this->set_save_query()); + $now=dol_now(); + + $fieldvalues = $this->set_save_query(); + if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) $fieldvalues['date_creation']=$this->db->idate($now); $keys=array(); $values = array(); - foreach ($fields as $k => $v) { + foreach ($fieldvalues as $k => $v) { $keys[] = $k; - $values[] = $this->quote($v); + $values[] = $this->quote($v, $this->fields[$k]); } $this->db->begin(); if (! $error) { - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' - ( '.implode( ",", $keys ).' ) - VALUES ( '.implode( ",", $values ).' ) '; - $res = $this->db->query( $sql ); + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' ('.implode( ", ", $keys ).')'; + $sql.= ' VALUES ('.implode( ", ", $values ).')'; + + $res = $this->db->query( $sql ); if ($res===false) { $error++; $this->errors[] = $this->db->lasterror(); @@ -5075,11 +5087,11 @@ abstract class CommonObject { if (empty($id) && empty($ref)) return false; - $sql = 'SELECT '.$this->get_field_list().', datec, tms'; + $sql = 'SELECT '.$this->get_field_list().', date_creation, tms'; $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element; if(!empty($id)) $sql.= ' WHERE rowid = '.$id; - else $sql.= ' WHERE ref = \''.$this->quote($ref).'\''; + else $sql.= " WHERE ref = ".$this->quote($ref, $this->fields['ref']); $res = $this->db->query($sql); if ($res) @@ -5091,7 +5103,7 @@ abstract class CommonObject $this->id = $id; $this->set_vars_by_db($obj); - $this->datec = $this->db->idate($obj->datec); + $this->date_creation = $this->db->idate($obj->date_creation); $this->tms = $this->db->idate($obj->tms); return $this->id; @@ -5127,27 +5139,26 @@ abstract class CommonObject { $error = 0; - $fields = $this->set_save_query(); + $fieldvalues = $this->set_save_query(); - foreach ($fields as $k => $v) { + foreach ($fieldvalues as $k => $v) { if (is_array($key)){ $i=array_search($k, $key); if ( $i !== false) { - $where[] = $key[$i].'=' . $this->quote( $v ) ; + $where[] = $key[$i].'=' . $this->quote($v, $this->fields[$k]); continue; } } else { if ( $k == $key) { - $where[] = $k.'=' .$this->quote( $v ) ; + $where[] = $k.'=' .$this->quote($v, $this->fields[$k]); continue; } } - $tmp[] = $k.'='.$this->quote($v); + $tmp[] = $k.'='.$this->quote($v, $this->fields[$k]); } $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET '.implode( ',', $tmp ).' WHERE rowid='.$this->id ; $this->db->begin(); - if (! $error) { $res = $this->db->query($sql); diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 4f6926b4aed..42bc2ff925a 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -794,6 +794,7 @@ HRAndBank=HR and Bank AutomaticallyCalculated=Automatically calculated TitleSetToDraft=Go back to draft ConfirmSetToDraft=Are you sure you want to go back to Draft status ? +ImportId=Import id # Week day Monday=Monday Tuesday=Tuesday diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 063e1c8d332..457b6fd3fcd 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -54,4 +54,5 @@ SqlFile=Sql file SqlFileExtraFields=Sql file for complementary attributes SqlFileKey=Sql file for keys AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case -UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) \ No newline at end of file +UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) +IsAMeasure=Is a measure \ No newline at end of file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index f6eea45003d..e1e3f41f859 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -360,7 +360,7 @@ if ($dirins && $action == 'confirm_delete') if ($dirins && $action == 'confirm_deleteobject' && $objectname) { - if (preg_match('/\s/', $objectname)) + if (preg_match('/[^a-z0-9]/i', $objectname)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); @@ -604,7 +604,11 @@ if ($action == 'savefile' && empty($cancel)) // Enable module if ($action == 'set' && $user->admin) { - $param='module='.$module; + $param=''; + if ($module) $param.='&module='.$module; + if ($tab) $param.='&tab='.$tab; + if ($tabobj) $param.='&tabobj='.$tabobj; + $value = GETPOST('value','alpha'); $resarray = activateModule($value); if (! empty($resarray['errors'])) setEventMessages('', $resarray['errors'], 'errors'); @@ -635,7 +639,11 @@ if ($action == 'set' && $user->admin) // Disable module if ($action == 'reset' && $user->admin) { - $param='module='.$module; + $param=''; + if ($module) $param.='&module='.$module; + if ($tab) $param.='&tab='.$tab; + if ($tabobj) $param.='&tabobj='.$tabobj; + $value = GETPOST('value','alpha'); $result=unActivateModule($value); if ($result) setEventMessages($result, null, 'errors'); @@ -844,7 +852,11 @@ elseif (! empty($module)) $modulelowercase=strtolower($module); $const_name = 'MAIN_MODULE_'.strtoupper($module); - $param='&tab='.$tab.'&module='.$module; + $param=''; + if ($tab) $param.= '&tab='.$tab; + if ($module) $param.='&module='.$module; + if ($tabobj) $param.='&tabobj='.$tabobj; + $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; $linktoenabledisable=''; if (! empty($conf->global->$const_name)) // If module is already activated @@ -1256,9 +1268,10 @@ elseif (! empty($module)) print ''.$langs->trans("NotNull").''; //print ''.$langs->trans("DefaultValue").''; print ''.$langs->trans("DatabaseIndex").''; + print ''.$langs->trans("Position").''; print ''.$langs->trans("Enabled").''; print ''.$langs->trans("Visible").''; - print ''.$langs->trans("Position").''; + print ''.$langs->trans("IsAMeasure").''; print ''.$langs->trans("SearchAll").''; print ''.$langs->trans("Comment").''; print ''; @@ -1270,9 +1283,10 @@ elseif (! empty($module)) print ''; //print ''; print ''; + print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; @@ -1300,13 +1314,14 @@ elseif (! empty($module)) $propname=$propkey; $proplabel=$propval['label']; $proptype=$propval['type']; - $propposition=$propval['position']; $propnotnull=$propval['notnull']; $propsearchall=$propval['searchall']; //$propdefault=$propval['default']; $propindex=$propval['index']; + $propposition=$propval['position']; $propenabled=$propval['enabled']; $propvisible=$propval['visible']; + $propisameasure=$propval['isameasure']; $propcomment=$propval['comment']; print ''; @@ -1329,14 +1344,17 @@ elseif (! empty($module)) print ''; print $propindex?'X':''; print ''; + print ''; + print $propposition; + print ''; print ''; print $propenabled?$propenabled:''; print ''; print ''; print $propvisible?$propvisible:''; print ''; - print ''; - print $propposition; + print ''; + print $propisameasure?$propisameasure:''; print ''; print ''; print $propsearchall?'X':''; diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index a371d5fad8a..b3c7a99d24e 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -58,21 +58,34 @@ class MyObject extends CommonObject public $picto = 'myobject'; + /** + * 'type' if the field format, 'label' the translation key, 'enabled' is a condition when the filed must be managed, + * 'visible' says if field is visible in list (-1 means not shown by default but can be aded into list to be viewed) + * 'notnull' if not null in database + * 'index' if we want an index in database + * 'position' is the sort order of field + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'comment' is not used. You can store here any text of your choice. + */ + // BEGIN MODULEBUILDER PROPERTIES /** * @var array Array with all fields and their property */ public $fields=array( - 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>true, 'index'=>true, 'visible'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), - 'entity'=>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>true, 'index'=>true, 'visible'=>0, 'position'=>20), - 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'visible'=>1, 'searchall'=>1), - 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'visible'=>-1, 'position'=>500), - 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'visible'=>-1, 'position'=>500), - 'status'=>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'visible'=>1, 'position'=>1000), + 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>true, 'index'=>true, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), + 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>true, 'index'=>true, 'position'=>20), + 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1), + 'qty' =>array('type'=>'double(24,8)', 'label'=>'Qty', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'searchall'=>0, 'isameasure'=>1), + 'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'position'=>1000), + 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-1, 'index'=>true, 'position'=>1000, 'nullifempty'=>1), ); // END MODULEBUILDER PROPERTIES - - + + // If this object has a subtable with lines diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 994aca35c88..9b3029c659d 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -110,6 +110,8 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e if (empty($reshook)) { + $error=0; + if ($cancel) { if ($action != 'addlink') @@ -125,19 +127,11 @@ if (empty($reshook)) // Action to add record if ($action == 'add' && ! empty($user->rights->mymodule->create)) { - if ($cancel) - { - $urltogo=$backtopage?$backtopage:dol_buildpath('/mymodule/myobject_list.php',1); - header("Location: ".$urltogo); - exit; - } - - $error=0; - foreach ($object->fields as $key => $val) { + if (in_array($key, array('entity', 'date_creation', 'tms', 'import_key'))) continue; // Ignore special fields + $object->$key=GETPOST($key,'alpha'); - if (in_array($key, array('entity', 'datec', 'tms'))) continue; if ($val['notnull'] && $object->$key == '') { $error++; @@ -172,20 +166,20 @@ if (empty($reshook)) // Action to update record if ($action == 'update' && ! empty($user->rights->mymodule->create)) { - $error=0; - - $object->prop1=GETPOST("field1"); - $object->prop2=GETPOST("field2"); - - if (empty($object->ref)) - { - $error++; - setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref")), null, 'errors'); - } + foreach ($object->fields as $key => $val) + { + $object->$key=GETPOST($key,'alpha'); + if (in_array($key, array('entity', 'datec', 'tms'))) continue; + if ($val['notnull'] && $object->$key == '') + { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv($val['label'])), null, 'errors'); + } + } if (! $error) { - $result=$object->update($user); + $result=$object->updateCommon($user); if ($result > 0) { $action='view'; @@ -207,7 +201,7 @@ if (empty($reshook)) // Action to delete if ($action == 'confirm_delete' && ! empty($user->rights->mymodule->delete)) { - $result=$object->delete($user); + $result=$object->deleteCommon($user); if ($result > 0) { // Delete OK @@ -267,7 +261,7 @@ if ($action == 'create') print ''."\n"; foreach($object->fields as $key => $val) { - if (in_array($key, array('rowid', 'entity', 'datec', 'tms'))) continue; + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue; print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; @@ -399,7 +399,7 @@ print $hookmanager->resPrint; // Rest of fields search foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; @@ -418,7 +418,7 @@ print ''."\n"; print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; @@ -445,7 +445,7 @@ print $hookmanager->resPrint; // Rest of fields title foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; @@ -476,7 +476,7 @@ while ($i < min($num, $limit)) print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; @@ -488,6 +488,11 @@ while ($i < min($num, $limit)) else print $obj->$key; print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } } } // Extra fields @@ -505,6 +510,11 @@ while ($i < min($num, $limit)) print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1); print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='ef.'.$tmpkey; + $totalarray['val']['ef.'.$tmpkey] += $obj->$tmpkey; + } } } } @@ -515,18 +525,23 @@ while ($i < min($num, $limit)) // Rest of fields foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; - if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; - if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center'; + if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; if (! empty($arrayfields['t.'.$key]['checked'])) { print ''; if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); - elseif ($key == 'status') print ''; + elseif ($key == 'status') print $object->getLibStatut(3); else print $obj->$key; print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } } } // Action column @@ -546,22 +561,23 @@ while ($i < min($num, $limit)) } // Show total line -if (isset($totalarray['totalhtfield'])) +if (isset($totalarray['pos'])) { print ''; $i=0; while ($i < $totalarray['nbfield']) { $i++; - if ($i == 1) + if (! empty($totalarray['pos'][$i])) print ''; + else { - if ($num < $limit) print ''; - else print ''; + if ($i == 1) + { + if ($num < $limit) print ''; + else print ''; + } + print ''; } - elseif ($totalarray['totalhtfield'] == $i) print ''; - elseif ($totalarray['totalvatfield'] == $i) print ''; - elseif ($totalarray['totalttcfield'] == $i) print ''; - else print ''; } print ''; } diff --git a/htdocs/modulebuilder/template/sql/llx_myobject.sql b/htdocs/modulebuilder/template/sql/llx_myobject.sql index b5810f0f227..1c47004f4e7 100644 --- a/htdocs/modulebuilder/template/sql/llx_myobject.sql +++ b/htdocs/modulebuilder/template/sql/llx_myobject.sql @@ -19,8 +19,10 @@ CREATE TABLE llx_myobject( -- BEGIN MODULEBUILDER FIELDS entity INTEGER DEFAULT 1 NOT NULL, label VARCHAR(255), - datec DATETIME NOT NULL, + qty INTEGER, + status INTEGER, + date_creation DATETIME NOT NULL, tms TIMESTAMP NOT NULL, - status INTEGER + import_key VARCHAR(14) -- END MODULEBUILDER FIELDS ) ENGINE=innodb; \ No newline at end of file
'.$object->getLibStatut(3).'
'.price($totalarray['val'][$totalarray['pos'][$i]]).''.$langs->trans("Total").''.$langs->trans("Totalforthispage").''.$langs->trans("Total").''.$langs->trans("Totalforthispage").''.price($totalarray['totalht']).''.price($totalarray['totalvat']).''.price($totalarray['totalttc']).'