All checks were successful
Deploy bericht / deploy (push) Successful in 1s
Desktop-Editor Polish:
- Aktives Seiten-Thumbnail deutlich markiert (scale + shadow + blauer
Label-Hintergrund)
- Titel-Feld pro Seite in der DB (llx_bericht_page.title)
Phase 5.2 Vorher/Nachher-Layout:
- Neuer layout-Typ 'before_after' in bericht_render_page_to_pdf
- Zwei Bilder nebeneinander, Labels 'Vorher' / 'Nachher', Titel oben
- 'VN'-Button in der Anhänge-Grid-Leiste
- create_grid_page akzeptiert before_after
- Layout-Dropdown hat before_after + title_only Option
Phase 5.2b Title-Only Seiten:
- Reine Titel/Zwischentitel-Seiten ohne Bild
- 32pt Titel zentriert, optional Notiz darunter
- bericht_render_page_to_pdf behandelt title_only separat
Phase 5.3 Bericht-Versionierung:
- Neue Spalten version + fk_bericht_parent in llx_bericht
- Bericht::duplicateAsNewVersion() kopiert alles inkl. Seiten
- '🔀 Neue Version'-Button im Editor-Footer
- Versions-Links in der Meta-Zeile (v1, v2, v3 …) mit Sprungmöglichkeit
- Alte Versionen bleiben unverändert erhalten
Phase 5.6 Batch-Modus:
- Neue Seite bericht_batch.php mit Filter (Datum von/bis, Suche)
- Checkbox-Liste aller finalisierten Berichte
- 'Ausgewählte als Sammel-PDF herunterladen' → FPDI merged alle
final_pdf_path in ein neues PDF mit Inhaltsverzeichnis-Seite
- Link im Admin-Setup
api/pages.php:
- POST-Update akzeptiert jetzt auch title und layout zusätzlich zu
note und rotation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
589 lines
23 KiB
PHP
589 lines
23 KiB
PHP
<?php
|
|
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
|
|
* GPL v3+
|
|
*/
|
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
|
|
|
|
/**
|
|
* CRUD-Klasse für einen Bericht.
|
|
* Eine Bericht-Instanz gehört zu einem Parent-Objekt (invoice|order|propal)
|
|
* und enthält n Seiten (BerichtPage).
|
|
*/
|
|
class Bericht extends CommonObject
|
|
{
|
|
public $element = 'bericht';
|
|
public $table_element = 'bericht';
|
|
public $picto = 'fa-file-pdf';
|
|
|
|
public $id;
|
|
public $entity;
|
|
public $ref;
|
|
public $titel;
|
|
public $element_type; // invoice | order | propal
|
|
public $fk_element;
|
|
public $auftragsnummer;
|
|
public $template_odt;
|
|
public $page_format = 'A4'; // A4, A3, Letter
|
|
public $page_orientation = 'P'; // P=Portrait, L=Landscape
|
|
public $is_template = 0; // 1 = Vorlage, wird nicht als regulärer Bericht gelistet
|
|
public $template_label; // Optional Label für die Vorlage
|
|
public $version = 1; // Version-Nummer (nur bei versionierten Berichten)
|
|
public $fk_bericht_parent; // Parent-Bericht bei Versionierung
|
|
public $status; // 0 = Entwurf, 1 = Final
|
|
public $final_pdf_path;
|
|
public $fk_user_creat;
|
|
public $fk_user_modif;
|
|
public $datec;
|
|
public $tms;
|
|
public $note;
|
|
|
|
const STATUS_DRAFT = 0;
|
|
const STATUS_FINAL = 1;
|
|
|
|
public function __construct(DoliDB $db)
|
|
{
|
|
$this->db = $db;
|
|
}
|
|
|
|
public function create(User $user, $notrigger = 0)
|
|
{
|
|
global $conf;
|
|
|
|
$this->entity = $conf->entity;
|
|
$this->datec = dol_now();
|
|
$this->status = self::STATUS_DRAFT;
|
|
$this->fk_user_creat = $user->id;
|
|
|
|
if (empty($this->ref)) {
|
|
$this->ref = 'BR'.date('ymd-His', $this->datec);
|
|
}
|
|
|
|
$sql = "INSERT INTO ".$this->db->prefix()."bericht ("
|
|
."entity, ref, titel, element_type, fk_element, auftragsnummer, template_odt, page_format, page_orientation, is_template, template_label, version, fk_bericht_parent, status, fk_user_creat, datec, note"
|
|
.") VALUES ("
|
|
.((int) $this->entity).","
|
|
."'".$this->db->escape($this->ref)."',"
|
|
.($this->titel ? "'".$this->db->escape($this->titel)."'" : "NULL").","
|
|
."'".$this->db->escape($this->element_type)."',"
|
|
.((int) $this->fk_element).","
|
|
.($this->auftragsnummer ? "'".$this->db->escape($this->auftragsnummer)."'" : "NULL").","
|
|
.($this->template_odt ? "'".$this->db->escape($this->template_odt)."'" : "NULL").","
|
|
."'".$this->db->escape($this->page_format)."',"
|
|
."'".$this->db->escape($this->page_orientation)."',"
|
|
.((int) ($this->is_template ? 1 : 0)).","
|
|
.($this->template_label ? "'".$this->db->escape($this->template_label)."'" : "NULL").","
|
|
.((int) ($this->version ?: 1)).","
|
|
.($this->fk_bericht_parent ? (int) $this->fk_bericht_parent : "NULL").","
|
|
.((int) $this->status).","
|
|
.((int) $this->fk_user_creat).","
|
|
."'".$this->db->idate($this->datec)."',"
|
|
.($this->note ? "'".$this->db->escape($this->note)."'" : "NULL")
|
|
.")";
|
|
|
|
$this->db->begin();
|
|
$res = $this->db->query($sql);
|
|
if (!$res) {
|
|
$this->error = $this->db->lasterror();
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
$this->id = $this->db->last_insert_id($this->db->prefix()."bericht");
|
|
$this->db->commit();
|
|
return $this->id;
|
|
}
|
|
|
|
public function fetch($id)
|
|
{
|
|
$sql = "SELECT rowid, entity, ref, titel, element_type, fk_element, auftragsnummer, template_odt,"
|
|
." page_format, page_orientation, COALESCE(is_template,0) AS is_template, template_label,"
|
|
." COALESCE(version,1) AS version, fk_bericht_parent,"
|
|
." status, final_pdf_path, fk_user_creat, fk_user_modif, datec, tms, note"
|
|
." FROM ".$this->db->prefix()."bericht WHERE rowid = ".((int) $id);
|
|
$res = $this->db->query($sql);
|
|
if (!$res) {
|
|
$this->error = $this->db->lasterror();
|
|
return -1;
|
|
}
|
|
if ($this->db->num_rows($res) == 0) {
|
|
return 0;
|
|
}
|
|
$obj = $this->db->fetch_object($res);
|
|
$this->id = $obj->rowid;
|
|
$this->entity = $obj->entity;
|
|
$this->ref = $obj->ref;
|
|
$this->titel = $obj->titel;
|
|
$this->element_type = $obj->element_type;
|
|
$this->fk_element = $obj->fk_element;
|
|
$this->auftragsnummer = $obj->auftragsnummer;
|
|
$this->template_odt = $obj->template_odt;
|
|
$this->page_format = $obj->page_format ?: 'A4';
|
|
$this->page_orientation= $obj->page_orientation ?: 'P';
|
|
$this->is_template = (int) $obj->is_template;
|
|
$this->template_label = $obj->template_label;
|
|
$this->version = (int) $obj->version;
|
|
$this->fk_bericht_parent = $obj->fk_bericht_parent ? (int) $obj->fk_bericht_parent : null;
|
|
$this->status = (int) $obj->status;
|
|
$this->final_pdf_path = $obj->final_pdf_path;
|
|
$this->fk_user_creat = $obj->fk_user_creat;
|
|
$this->fk_user_modif = $obj->fk_user_modif;
|
|
$this->datec = $this->db->jdate($obj->datec);
|
|
$this->tms = $this->db->jdate($obj->tms);
|
|
$this->note = $obj->note;
|
|
return 1;
|
|
}
|
|
|
|
public function update(User $user, $notrigger = 0)
|
|
{
|
|
$sql = "UPDATE ".$this->db->prefix()."bericht SET "
|
|
."titel = ".($this->titel ? "'".$this->db->escape($this->titel)."'" : "NULL").","
|
|
."auftragsnummer = ".($this->auftragsnummer ? "'".$this->db->escape($this->auftragsnummer)."'" : "NULL").","
|
|
."template_odt = ".($this->template_odt ? "'".$this->db->escape($this->template_odt)."'" : "NULL").","
|
|
."page_format = '".$this->db->escape($this->page_format ?: 'A4')."',"
|
|
."page_orientation = '".$this->db->escape($this->page_orientation ?: 'P')."',"
|
|
."status = ".((int) $this->status).","
|
|
."final_pdf_path = ".($this->final_pdf_path ? "'".$this->db->escape($this->final_pdf_path)."'" : "NULL").","
|
|
."note = ".($this->note ? "'".$this->db->escape($this->note)."'" : "NULL").","
|
|
."fk_user_modif = ".((int) $user->id)
|
|
." WHERE rowid = ".((int) $this->id);
|
|
$res = $this->db->query($sql);
|
|
if (!$res) {
|
|
$this->error = $this->db->lasterror();
|
|
return -1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
public function delete(User $user, $notrigger = 0)
|
|
{
|
|
$this->db->begin();
|
|
// Seiten löschen (CASCADE räumt's bereits, aber explizit für robustes Verhalten)
|
|
$this->db->query("DELETE FROM ".$this->db->prefix()."bericht_page WHERE fk_bericht = ".((int) $this->id));
|
|
$res = $this->db->query("DELETE FROM ".$this->db->prefix()."bericht WHERE rowid = ".((int) $this->id));
|
|
if (!$res) {
|
|
$this->error = $this->db->lasterror();
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
$this->db->commit();
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Liefert alle Berichte zu einem Parent-Objekt (direkt zugeordnet).
|
|
*
|
|
* @param string $element_type invoice | order | propal
|
|
* @param int $fk_element ID des Parent-Objekts
|
|
* @return Bericht[]
|
|
*/
|
|
public static function fetchAllForElement(DoliDB $db, $element_type, $fk_element)
|
|
{
|
|
$list = array();
|
|
$sql = "SELECT rowid FROM ".$db->prefix()."bericht"
|
|
." WHERE element_type = '".$db->escape($element_type)."'"
|
|
." AND fk_element = ".((int) $fk_element)
|
|
." AND COALESCE(is_template,0) = 0"
|
|
." ORDER BY datec DESC";
|
|
$res = $db->query($sql);
|
|
if (!$res) return $list;
|
|
while ($obj = $db->fetch_object($res)) {
|
|
$b = new self($db);
|
|
if ($b->fetch($obj->rowid) > 0) {
|
|
$list[] = $b;
|
|
}
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Liefert Berichte, die per llx_element_element zusätzlich zu einem Parent verknüpft wurden.
|
|
*/
|
|
public static function fetchLinkedForElement(DoliDB $db, $targettype, $fk_target)
|
|
{
|
|
$list = array();
|
|
$sql = "SELECT b.rowid FROM ".$db->prefix()."bericht b"
|
|
." JOIN ".$db->prefix()."element_element e ON e.fk_source = b.rowid"
|
|
." WHERE e.sourcetype = 'bericht'"
|
|
." AND e.targettype = '".$db->escape($targettype)."'"
|
|
." AND e.fk_target = ".((int) $fk_target)
|
|
." ORDER BY b.datec DESC";
|
|
$res = $db->query($sql);
|
|
if (!$res) return $list;
|
|
while ($obj = $db->fetch_object($res)) {
|
|
$b = new self($db);
|
|
if ($b->fetch($obj->rowid) > 0) {
|
|
$list[] = $b;
|
|
}
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Erzeugt eine n:m-Verknüpfung zwischen einem Bericht und einem anderen Element.
|
|
*/
|
|
public function linkToElement($targettype, $fk_target)
|
|
{
|
|
// Schon vorhanden?
|
|
$sql = "SELECT rowid FROM ".$this->db->prefix()."element_element"
|
|
." WHERE sourcetype = 'bericht' AND fk_source = ".((int) $this->id)
|
|
." AND targettype = '".$this->db->escape($targettype)."'"
|
|
." AND fk_target = ".((int) $fk_target);
|
|
$res = $this->db->query($sql);
|
|
if ($res && $this->db->num_rows($res) > 0) return 1;
|
|
|
|
$ins = "INSERT INTO ".$this->db->prefix()."element_element"
|
|
." (fk_source, sourcetype, fk_target, targettype) VALUES ("
|
|
.((int) $this->id).", 'bericht', ".((int) $fk_target).", '".$this->db->escape($targettype)."')";
|
|
return $this->db->query($ins) ? 1 : -1;
|
|
}
|
|
|
|
/**
|
|
* Entfernt eine n:m-Verknüpfung.
|
|
*/
|
|
public function unlinkFromElement($targettype, $fk_target)
|
|
{
|
|
$sql = "DELETE FROM ".$this->db->prefix()."element_element"
|
|
." WHERE sourcetype = 'bericht' AND fk_source = ".((int) $this->id)
|
|
." AND targettype = '".$this->db->escape($targettype)."'"
|
|
." AND fk_target = ".((int) $fk_target);
|
|
return $this->db->query($sql) ? 1 : -1;
|
|
}
|
|
|
|
/**
|
|
* Liefert alle Vorlagen (is_template = 1).
|
|
* @return Bericht[]
|
|
*/
|
|
public static function fetchAllTemplates(DoliDB $db)
|
|
{
|
|
$list = array();
|
|
$sql = "SELECT rowid FROM ".$db->prefix()."bericht"
|
|
." WHERE COALESCE(is_template,0) = 1"
|
|
." ORDER BY template_label ASC, ref ASC";
|
|
$res = $db->query($sql);
|
|
if (!$res) return $list;
|
|
while ($obj = $db->fetch_object($res)) {
|
|
$b = new self($db);
|
|
if ($b->fetch($obj->rowid) > 0) $list[] = $b;
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Erstellt einen neuen Bericht aus einer Vorlage:
|
|
* Titel, Format, Orientation, Template-ODT werden übernommen;
|
|
* alle Vorlagen-Seiten werden in den neuen Bericht kopiert (mit Notizen,
|
|
* aber source_path wird nur übernommen wenn es ein dauerhaftes Asset ist).
|
|
*
|
|
* @return int|false Neue Bericht-ID oder false
|
|
*/
|
|
public static function createFromTemplate(DoliDB $db, User $user, $template_id, $element_type, $fk_element, $auftragsnummer)
|
|
{
|
|
$tpl = new self($db);
|
|
if ($tpl->fetch($template_id) <= 0 || !$tpl->is_template) return false;
|
|
|
|
$b = new self($db);
|
|
$b->element_type = $element_type;
|
|
$b->fk_element = $fk_element;
|
|
$b->titel = $tpl->titel ?: ('Bericht '.$auftragsnummer);
|
|
$b->auftragsnummer = $auftragsnummer;
|
|
$b->template_odt = $tpl->template_odt;
|
|
$b->page_format = $tpl->page_format;
|
|
$b->page_orientation = $tpl->page_orientation;
|
|
$b->is_template = 0;
|
|
if ($b->create($user) <= 0) return false;
|
|
|
|
// Seiten kopieren
|
|
$tpl_pages = BerichtPage::fetchAllForBericht($db, $tpl->id);
|
|
foreach ($tpl_pages as $order => $tp) {
|
|
$np = new BerichtPage($db);
|
|
$np->fk_bericht = $b->id;
|
|
$np->page_order = $order + 1;
|
|
$np->source_type = $tp->source_type;
|
|
$np->source_path = $tp->source_path; // zeigt auf die Vorlagen-Assets (werden mitgenutzt, nicht kopiert)
|
|
$np->source_page = $tp->source_page;
|
|
$np->note = $tp->note;
|
|
$np->layout = $tp->layout;
|
|
$np->image_scale = $tp->image_scale;
|
|
$np->image_align = $tp->image_align;
|
|
$np->create();
|
|
}
|
|
return (int) $b->id;
|
|
}
|
|
|
|
/**
|
|
* Dupliziert einen Bericht als neue Version (v+1). Seiten werden kopiert.
|
|
* Der alte Bericht bleibt unverändert.
|
|
*
|
|
* @return int|false Neue Bericht-ID
|
|
*/
|
|
public function duplicateAsNewVersion(User $user)
|
|
{
|
|
$new = new Bericht($this->db);
|
|
$new->element_type = $this->element_type;
|
|
$new->fk_element = $this->fk_element;
|
|
$new->auftragsnummer = $this->auftragsnummer;
|
|
$new->template_odt = $this->template_odt;
|
|
$new->page_format = $this->page_format;
|
|
$new->page_orientation = $this->page_orientation;
|
|
$new->note = $this->note;
|
|
// Parent der Versionskette = ursprünglicher Bericht oder dessen Parent
|
|
$new->fk_bericht_parent = $this->fk_bericht_parent ?: $this->id;
|
|
// Höchste bisherige Version in dieser Kette finden
|
|
$chain_id = $new->fk_bericht_parent;
|
|
$res = $this->db->query("SELECT MAX(COALESCE(version,1)) AS v FROM ".$this->db->prefix()."bericht"
|
|
." WHERE rowid = ".((int) $chain_id)." OR fk_bericht_parent = ".((int) $chain_id));
|
|
$max_v = 1;
|
|
if ($res && ($r = $this->db->fetch_object($res))) $max_v = (int) $r->v;
|
|
$new->version = $max_v + 1;
|
|
$new->titel = ($this->titel ? preg_replace('/\s*\(v\d+\)$/', '', $this->titel) : 'Bericht').' (v'.$new->version.')';
|
|
if ($new->create($user) <= 0) return false;
|
|
|
|
// Seiten kopieren
|
|
$src_pages = BerichtPage::fetchAllForBericht($this->db, $this->id);
|
|
foreach ($src_pages as $order => $p) {
|
|
$np = new BerichtPage($this->db);
|
|
$np->fk_bericht = $new->id;
|
|
$np->page_order = $order + 1;
|
|
$np->source_type = $p->source_type;
|
|
$np->source_path = $p->source_path;
|
|
$np->source_page = $p->source_page;
|
|
$np->note = $p->note;
|
|
$np->title = $p->title;
|
|
$np->rotation = $p->rotation;
|
|
$np->fabric_json = $p->fabric_json;
|
|
$np->layout = $p->layout;
|
|
$np->image_scale = $p->image_scale;
|
|
$np->image_align = $p->image_align;
|
|
$np->create();
|
|
}
|
|
return (int) $new->id;
|
|
}
|
|
|
|
public function getLibStatut($mode = 0)
|
|
{
|
|
global $langs;
|
|
$langs->load("bericht@bericht");
|
|
if ($this->status == self::STATUS_FINAL) {
|
|
return '<span class="badge badge-status4">'.$langs->trans("BerichtStatusFinal").'</span>';
|
|
}
|
|
return '<span class="badge badge-status0">'.$langs->trans("BerichtStatusDraft").'</span>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Eine Seite eines Berichts.
|
|
*
|
|
* Layout-Modi:
|
|
* single = ein Bild/PDF direkt auf source_path
|
|
* grid_2 = 2 Bilder nebeneinander (über llx_bericht_page_image)
|
|
* grid_4 = 2x2 Grid
|
|
* grid_6 = 3x2 Grid
|
|
*
|
|
* Bei single werden image_scale + image_align angewendet:
|
|
* image_scale: 1.0 / 0.7 / 0.5 / 0.3
|
|
* image_align: fit / center / topleft / topright / bottomleft / bottomright
|
|
*/
|
|
class BerichtPage
|
|
{
|
|
public $db;
|
|
public $id;
|
|
public $fk_bericht;
|
|
public $page_order;
|
|
public $source_type;
|
|
public $source_path;
|
|
public $source_page;
|
|
public $rotation;
|
|
public $fabric_json;
|
|
public $note;
|
|
public $title; // Optional Titel/Zwischentitel der Seite
|
|
public $layout = 'single';
|
|
public $image_scale = 1.0;
|
|
public $image_align = 'fit';
|
|
|
|
public function __construct(DoliDB $db)
|
|
{
|
|
$this->db = $db;
|
|
}
|
|
|
|
/**
|
|
* Liefert die Bilder einer Multi-Image-Seite (layout != single).
|
|
* @return array [['rowid'=>..., 'slot'=>..., 'source_path'=>..., 'rotation'=>...], ...]
|
|
*/
|
|
public function getImages()
|
|
{
|
|
$list = array();
|
|
if ($this->layout === 'single') return $list;
|
|
$sql = "SELECT rowid, slot, source_path, rotation FROM ".$this->db->prefix()."bericht_page_image"
|
|
." WHERE fk_page = ".((int) $this->id)
|
|
." ORDER BY slot ASC";
|
|
$res = $this->db->query($sql);
|
|
if (!$res) return $list;
|
|
while ($obj = $this->db->fetch_object($res)) {
|
|
$list[] = array(
|
|
'rowid' => (int) $obj->rowid,
|
|
'slot' => (int) $obj->slot,
|
|
'source_path' => $obj->source_path,
|
|
'rotation' => (int) $obj->rotation,
|
|
);
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Setzt das Bild eines Slots (überschreibt vorhandenes).
|
|
*/
|
|
public function setSlotImage($slot, $source_path, $rotation = 0)
|
|
{
|
|
$this->db->query("DELETE FROM ".$this->db->prefix()."bericht_page_image"
|
|
." WHERE fk_page = ".((int) $this->id)." AND slot = ".((int) $slot));
|
|
$sql = "INSERT INTO ".$this->db->prefix()."bericht_page_image (fk_page, slot, source_path, rotation)"
|
|
." VALUES (".((int) $this->id).", ".((int) $slot).", '".$this->db->escape($source_path)."', ".((int) $rotation).")";
|
|
return $this->db->query($sql) ? 1 : -1;
|
|
}
|
|
|
|
public function clearImages()
|
|
{
|
|
return $this->db->query("DELETE FROM ".$this->db->prefix()."bericht_page_image WHERE fk_page = ".((int) $this->id)) ? 1 : -1;
|
|
}
|
|
|
|
/**
|
|
* Anzahl Slots eines Layouts.
|
|
*/
|
|
public static function slotCountForLayout($layout)
|
|
{
|
|
return array(
|
|
'single' => 1,
|
|
'grid_2' => 2,
|
|
'grid_2v' => 2,
|
|
'grid_4' => 4,
|
|
'grid_6' => 6,
|
|
'before_after' => 2,
|
|
'title_only' => 0,
|
|
)[$layout] ?? 1;
|
|
}
|
|
|
|
/**
|
|
* Berechnet die Slot-Rectangles innerhalb einer Seite (mm) für ein Grid-Layout.
|
|
* @return array [['x'=>..,'y'=>..,'w'=>..,'h'=>..], ...]
|
|
*/
|
|
public static function slotRects($layout, $pageW, $pageH, $margin = 10, $gap = 4)
|
|
{
|
|
$rects = array();
|
|
$iw = $pageW - 2 * $margin;
|
|
$ih = $pageH - 2 * $margin - 10; // 10mm Notiz unten
|
|
|
|
if ($layout === 'grid_2') {
|
|
// 2 Bilder horizontal: 1 oben, 1 unten
|
|
$h = ($ih - $gap) / 2;
|
|
for ($i = 0; $i < 2; $i++) {
|
|
$rects[] = array('x' => $margin, 'y' => $margin + $i * ($h + $gap), 'w' => $iw, 'h' => $h);
|
|
}
|
|
} elseif ($layout === 'grid_2v') {
|
|
// 2 Bilder vertikal nebeneinander
|
|
$w = ($iw - $gap) / 2;
|
|
for ($i = 0; $i < 2; $i++) {
|
|
$rects[] = array('x' => $margin + $i * ($w + $gap), 'y' => $margin, 'w' => $w, 'h' => $ih);
|
|
}
|
|
} elseif ($layout === 'grid_4') {
|
|
$w = ($iw - $gap) / 2;
|
|
$h = ($ih - $gap) / 2;
|
|
for ($r = 0; $r < 2; $r++) {
|
|
for ($c = 0; $c < 2; $c++) {
|
|
$rects[] = array(
|
|
'x' => $margin + $c * ($w + $gap),
|
|
'y' => $margin + $r * ($h + $gap),
|
|
'w' => $w, 'h' => $h
|
|
);
|
|
}
|
|
}
|
|
} elseif ($layout === 'grid_6') {
|
|
$w = ($iw - 2 * $gap) / 3;
|
|
$h = ($ih - $gap) / 2;
|
|
for ($r = 0; $r < 2; $r++) {
|
|
for ($c = 0; $c < 3; $c++) {
|
|
$rects[] = array(
|
|
'x' => $margin + $c * ($w + $gap),
|
|
'y' => $margin + $r * ($h + $gap),
|
|
'w' => $w, 'h' => $h
|
|
);
|
|
}
|
|
}
|
|
}
|
|
return $rects;
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
$sql = "INSERT INTO ".$this->db->prefix()."bericht_page ("
|
|
."fk_bericht, page_order, source_type, source_path, source_page, rotation, fabric_json, note, title, layout, image_scale, image_align"
|
|
.") VALUES ("
|
|
.((int) $this->fk_bericht).","
|
|
.((int) $this->page_order).","
|
|
."'".$this->db->escape($this->source_type)."',"
|
|
."'".$this->db->escape($this->source_path ?: '')."',"
|
|
.($this->source_page !== null ? (int) $this->source_page : "NULL").","
|
|
.((int) ($this->rotation ?? 0)).","
|
|
.($this->fabric_json !== null ? "'".$this->db->escape($this->fabric_json)."'" : "NULL").","
|
|
.($this->note ? "'".$this->db->escape($this->note)."'" : "NULL").","
|
|
.($this->title ? "'".$this->db->escape($this->title)."'" : "NULL").","
|
|
."'".$this->db->escape($this->layout ?: 'single')."',"
|
|
.((float) ($this->image_scale ?: 1.0)).","
|
|
."'".$this->db->escape($this->image_align ?: 'fit')."'"
|
|
.")";
|
|
$res = $this->db->query($sql);
|
|
if (!$res) return -1;
|
|
$this->id = $this->db->last_insert_id($this->db->prefix()."bericht_page");
|
|
return $this->id;
|
|
}
|
|
|
|
public function update()
|
|
{
|
|
$sql = "UPDATE ".$this->db->prefix()."bericht_page SET "
|
|
."page_order = ".((int) $this->page_order).","
|
|
."rotation = ".((int) ($this->rotation ?? 0)).","
|
|
."fabric_json = ".($this->fabric_json !== null ? "'".$this->db->escape($this->fabric_json)."'" : "NULL").","
|
|
."note = ".($this->note ? "'".$this->db->escape($this->note)."'" : "NULL").","
|
|
."layout = '".$this->db->escape($this->layout ?: 'single')."',"
|
|
."image_scale = ".((float) ($this->image_scale ?: 1.0)).","
|
|
."image_align = '".$this->db->escape($this->image_align ?: 'fit')."'"
|
|
." WHERE rowid = ".((int) $this->id);
|
|
return $this->db->query($sql) ? 1 : -1;
|
|
}
|
|
|
|
public function delete()
|
|
{
|
|
return $this->db->query("DELETE FROM ".$this->db->prefix()."bericht_page WHERE rowid = ".((int) $this->id)) ? 1 : -1;
|
|
}
|
|
|
|
public static function fetchAllForBericht(DoliDB $db, $fk_bericht)
|
|
{
|
|
$list = array();
|
|
$sql = "SELECT rowid, fk_bericht, page_order, source_type, source_path, source_page, rotation, fabric_json, note, title,"
|
|
." COALESCE(layout, 'single') AS layout,"
|
|
." COALESCE(image_scale, 1.0) AS image_scale,"
|
|
." COALESCE(image_align, 'fit') AS image_align"
|
|
." FROM ".$db->prefix()."bericht_page"
|
|
." WHERE fk_bericht = ".((int) $fk_bericht)
|
|
." ORDER BY page_order ASC, rowid ASC";
|
|
$res = $db->query($sql);
|
|
if (!$res) return $list;
|
|
while ($obj = $db->fetch_object($res)) {
|
|
$p = new self($db);
|
|
$p->id = $obj->rowid;
|
|
$p->fk_bericht = $obj->fk_bericht;
|
|
$p->page_order = (int) $obj->page_order;
|
|
$p->source_type = $obj->source_type;
|
|
$p->source_path = $obj->source_path;
|
|
$p->source_page = $obj->source_page !== null ? (int) $obj->source_page : null;
|
|
$p->rotation = (int) $obj->rotation;
|
|
$p->fabric_json = $obj->fabric_json;
|
|
$p->note = $obj->note;
|
|
$p->title = $obj->title;
|
|
$p->layout = $obj->layout;
|
|
$p->image_scale = (float) $obj->image_scale;
|
|
$p->image_align = $obj->image_align;
|
|
$list[] = $p;
|
|
}
|
|
return $list;
|
|
}
|
|
}
|