3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2013-2014 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2013-2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
34 * @link http://galette.tuxfamily.org
35 * @since Available since 0.7.5dev - 2013-02-19
38 namespace Galette\Entity
;
42 use Galette\Repository\PdfModels
;
44 use Laminas\Db\Sql\Expression
;
52 * @author Johan Cwiklinski <johan@x-tnd.be>
53 * @copyright 2013-2014 The Galette Team
54 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
55 * @link http://galette.tuxfamily.org
56 * @since Available since 0.7.5dev - 2013-02-19
59 abstract class PdfModel
61 public const TABLE
= 'pdfmodels';
62 public const PK
= 'model_id';
64 public const MAIN_MODEL
= 1;
65 public const INVOICE_MODEL
= 2;
66 public const RECEIPT_MODEL
= 3;
67 public const ADHESION_FORM_MODEL
= 4;
88 * @param Db $zdb Database instance
89 * @param Preferences $preferences Galette preferences
90 * @param int $type Model type
91 * @param mixed $args Arguments
93 public function __construct(Db
$zdb, $preferences, $type, $args = null)
96 $router = $container->get('router');
99 throw new \
RuntimeException(
100 get_class($this) . ' Database instance required!'
108 $this->load($args, $preferences);
109 } elseif ($args !== null && is_object($args)) {
110 $this->loadFromRs($args, $preferences);
113 $this->patterns
= array(
114 'asso_name' => '/{ASSO_NAME}/',
115 'asso_slogan' => '/{ASSO_SLOGAN}/',
116 'asso_address' => '/{ASSO_ADDRESS}/',
117 'asso_address_multi' => '/{ASSO_ADDRESS_MULTI}/',
118 'asso_website' => '/{ASSO_WEBSITE}/',
119 'asso_logo' => '/{ASSO_LOGO}/',
120 'date_now' => '/{DATE_NOW}/'
123 $address = $preferences->getPostalAddress();
124 $address_multi = preg_replace("/\n/", "<br>", $address);
127 if ($preferences->pref_website
!= '') {
128 $website = '<a href="' . $preferences->pref_website
. '">' .
129 $preferences->pref_website
. '</a>';
132 $logo = new Core\
Logo();
134 ' src="' . $preferences->getURL() . $router->pathFor('logo') . '"' .
135 ' width="' . $logo->getOptimalWidth() . '"' .
136 ' height="' . $logo->getOptimalHeight() . '"' .
139 $this->replaces
= array(
140 'asso_name' => $preferences->pref_nom
,
141 'asso_slogan' => $preferences->pref_slogan
,
142 'asso_address' => $address,
143 'asso_address_multi' => $address_multi,
144 'asso_website' => $website,
145 'asso_logo' => $logo_elt,
146 'date_now' => date(_T('Y-m-d'))
151 * Load a Model from its identifier
153 * @param int $id Identifier
154 * @param Preferences $preferences Galette preferences
155 * @param boolean $init Init data if required model is missing
159 protected function load($id, $preferences, $init = true)
162 $select = $this->zdb
->select(self
::TABLE
);
164 ->where(self
::PK
. ' = ' . $id);
166 $results = $this->zdb
->execute($select);
168 $count = $results->count();
170 if ($init === true) {
171 $models = new PdfModels($this->zdb
, $preferences, $this->login
);
172 $models->installInit();
173 $this->load($id, $preferences, false);
175 throw new \
RuntimeException('Model not found!');
178 $this->loadFromRs($results->current(), $preferences);
180 } catch (\Exception
$e) {
182 'An error occurred loading model #' . $id . "Message:\n" .
190 * Load model from a db ResultSet
192 * @param ResultSet $rs ResultSet
193 * @param Preferences $preferences Galette preferences
197 protected function loadFromRs($rs, $preferences)
200 $this->id
= (int)$rs->$pk;
202 $callback = function ($matches) {
203 return _T($matches[1]);
205 $this->name
= preg_replace_callback(
206 '/_T\("([^\"]+)"\)/',
211 $this->title
= $rs->model_title
;
212 $this->subtitle
= $rs->model_subtitle
;
213 $this->header
= $rs->model_header
;
214 $this->footer
= $rs->model_footer
;
215 $this->body
= $rs->model_body
;
216 $this->styles
.= $rs->model_styles
;
218 if ($this->id
> self
::MAIN_MODEL
) {
219 //FIXME: for now, parent will always be a PdfMain
220 $this->parent
= new PdfMain(
223 (int)$rs->model_parent
227 //let's check if some values should be retrieved from parent model
228 /*if ( $this->id > self::MAIN_MODEL ) {
229 //some infos are missing, load parent
230 if ( trim($this->header) === ''
231 || trim($this->footer) === ''
233 if ( trim($this->header) === '' ) {
234 $this->header = $parent->header;
236 if ( trim($this->header) === '' ) {
237 $this->footer = $parent->footer;
244 * Store model in database
248 public function store()
250 $title = $this->title
;
251 if (trim($title === '')) {
252 $title = new Expression('NULL');
255 $subtitle = $this->subtitle
;
256 if (trim($subtitle === '')) {
257 $subtitle = new Expression('NULL');
261 'model_header' => $this->header
,
262 'model_footer' => $this->footer
,
263 'model_type' => $this->type
,
264 'model_title' => $title,
265 'model_subtitle' => $subtitle,
266 'model_body' => $this->body
,
267 'model_styles' => $this->styles
271 if ($this->id
!== null) {
272 $update = $this->zdb
->update(self
::TABLE
);
273 $update->set($data)->where(
274 self
::PK
. '=' . $this->id
276 $this->zdb
->execute($update);
278 $data['model_name'] = $this->name
;
279 $insert = $this->zdb
->insert(self
::TABLE
);
280 $insert->values($data);
281 $add = $this->zdb
->execute($insert);
282 if (!$add->count() > 0) {
283 Analog
::log('Not stored!', Analog
::ERROR
);
288 } catch (\Exception
$e) {
290 'An error occurred storing model: ' . $e->getMessage() .
291 "\n" . print_r($data, true),
299 * Get object class for specified type
301 * @param int $type Type
305 public static function getTypeClass($type)
309 case self
::INVOICE_MODEL
:
310 $class = 'PdfInvoice';
312 case self
::RECEIPT_MODEL
:
313 $class = 'PdfReceipt';
315 case self
::ADHESION_FORM_MODEL
:
316 $class = 'PdfAdhesionFormModel';
322 $class = 'Galette\\Entity\\' . $class;
329 * @param string $value The value
330 * @param int $chars Lenght
331 * @param string $field Field name
332 * @param boolean $empty Can value be empty
336 protected function checkChars($value, $chars, $field, $empty = false)
338 if ($value !== null && trim($value) !== '') {
339 if (mb_strlen($value) > $chars) {
340 throw new \
LengthException(
342 array('%field', '%chars'),
343 array($field, $chars),
344 _T("%field should be less than %chars characters long.")
349 if ($empty === false) {
350 throw new \
UnexpectedValueException(
354 _T("%field should not be empty!")
366 public function extractDynamicPatterns()
370 $parts = array('header', 'footer', 'title', 'subtitle', 'body');
371 foreach ($parts as $part) {
372 $content = $this->$part;
376 '/{((LABEL|INPUT)?_DYNFIELD_[0-9]+_ADH)}/',
380 $patterns = array_merge($patterns, $matches[1]);
382 Analog
::log("dynamic patterns found in $part: " . join(",", $matches[1]), Analog
::DEBUG
);
391 * @param array $patterns Patterns to add
395 public function setPatterns($patterns)
397 $this->patterns
= array_merge(
406 * @param array $replaces Replacements to add
410 public function setReplacements($replaces)
412 $this->replaces
= array_merge(
421 * @param string $name Property name
425 public function __get($name)
444 //get header and footer from parent if not defined in current model
446 $this->id
> self
::MAIN_MODEL
447 && $this->parent
!== null
449 $value = $this->parent
->styles
;
452 $value .= $this->styles
;
460 $pname = substr($name, 1);
461 $prop_value = $this->$pname;
463 //get header and footer from parent if not defined in current model
465 $this->id
> self
::MAIN_MODEL
466 && trim($prop_value) === ''
467 && $this->parent
!== null
468 && ($pname === 'footer'
469 ||
$pname === 'header')
471 $prop_value = $this->parent
->$pname;
474 //handle translations
475 $callback = function ($matches) {
476 return _T($matches[1]);
478 $value = preg_replace_callback(
479 '/_T\("([^\"]+)"\)/',
484 //handle replacements
485 $value = preg_replace(
491 //handle translations with replacements
492 $repl_callback = function ($matches) {
499 $value = preg_replace_callback(
500 '/str_replace\(\'([^,]+)\', ?\'([^,]+)\', ?\'(.*)\'\)/',
509 'Unable to get PdfModel property ' . $name,
519 * @param string $name Property name
520 * @param mixed $value Property value
524 public function __set($name, $value)
529 $value === self
::MAIN_MODEL
530 ||
$value === self
::INVOICE_MODEL
531 ||
$value === self
::RECEIPT_MODEL
532 ||
$value === self
::ADHESION_FORM_MODEL
534 $this->$name = $value;
536 throw new \
UnexpectedValueException(
540 _T("Unknown type %type!")
547 $this->checkChars($value, 50, _T("Name"));
548 $this->$name = $value;
549 } catch (\Exception
$e) {
555 if ($name == 'title') {
556 $field = _T("Title");
558 $field = _T("Subtitle");
561 $this->checkChars($value, 100, $field, true);
562 $this->$name = $value;
563 } catch (\Exception
$e) {
570 if ($value == null ||
trim($value) == '') {
571 if (get_class($this) === 'PdfMain' && $name !== 'body') {
572 throw new \
UnexpectedValueException(
573 _T("header and footer should not be empty!")
575 } elseif (get_class($this) !== 'PdfMain' && $name === 'body') {
576 throw new \
UnexpectedValueException(
577 _T("body should not be empty!")
582 if (function_exists('tidy_parse_string')) {
583 //if tidy extension is present, we use it to clean a bit
584 /*$tidy_config = array(
586 'show-body-only' => true,
587 'join-styles' => false,
588 'join-classes' => false,
591 $tidy = tidy_parse_string($value, $tidy_config, 'UTF8');
592 $tidy->cleanRepair();
593 $this->$name = tidy_get_output($tidy);*/
594 $this->$name = $value;
596 //if it is not... Well, let's serve the text as it.
597 $this->$name = $value;
601 $this->styles
= $value;
605 'Unable to set PdfModel property ' . $name,