/** * Build the File package object * * @param string $pathfile The path to the file * @param \collection $collection The destination collection * @param Application $app An application * @param string $originalName An optionnal original name (if * different from the $pathfile filename) * @throws \InvalidArgumentException * * @return File */ public static function buildFromPathfile($pathfile, \collection $collection, Application $app, $originalName = null) { try { $media = $app->getMediaFromUri($pathfile); } catch (FileNotFoundException $e) { throw new \InvalidArgumentException(sprintf('Unable to build media file from non existant %s', $pathfile)); } return new File($app, $media, $collection, $originalName); }
/** * Creates a record * * @param \collection $collection The destination collection * @param string $pathfile The file to archive * @param string|null $captionFile The Phrasea XML caption file or null if no caption file * @param integer $grp_rid Add the record to a story * @param integer $force Force lazaret or record ; use \Alchemy\Phrasea\Border\Manager::FORCE_* constants * @return \record_adapter */ public function createRecord(Application $app, \collection $collection, $pathfile, $captionFile, $grp_rid, $force, $stat0, $stat1) { $status = \databox_status::operation_or($stat0, $stat1); $media = $app->getMediaFromUri($pathfile); $databox = $collection->get_databox(); $metadatasStructure = $databox->get_meta_structure(); $metadatas = $this->getIndexByFieldName($metadatasStructure, $media->getMetadatas()); $metaFields = []; if ($captionFile !== null && true === $app['filesystem']->exists($captionFile)) { $metaFields = $this->readXMLForDatabox($app, $metadatasStructure, $captionFile); $captionStatus = $this->parseStatusBit(@simplexml_load_file($captionFile)); if ($captionStatus) { $status = \databox_status::operation_mask($status, $captionStatus); } } $file = new File($app, $media, $collection); $file->addAttribute(new BorderAttribute\Status($app, $status)); $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfFilepath(), new MonoValue($media->getFile()->getRealPath())))); $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfDirname(), new MonoValue(dirname($media->getFile()->getRealPath()))))); $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfAtime(), new MonoValue($media->getFile()->getATime())))); $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfMtime(), new MonoValue($media->getFile()->getMTime())))); $file->addAttribute(new BorderAttribute\Metadata(new Metadata(new PhraseaTag\TfCtime(), new MonoValue($media->getFile()->getCTime())))); foreach ($metadatas as $meta) { $file->addAttribute(new BorderAttribute\Metadata($meta)); } foreach ($metaFields as $metaField) { $file->addAttribute($metaField); } if ($grp_rid) { $file->addAttribute(new BorderAttribute\Story(new \record_adapter($app, $databox->get_sbas_id(), $grp_rid))); } $record = null; $postProcess = function ($element, $visa, $code) use(&$record) { $record = $element; }; $app['border-manager']->process($this->getLazaretSession($app), $file, $postProcess, $force); return $record; }
/** * * @param File $file * @param Application $app * * @return \record_adapter */ public static function createFromFile(File $file, Application $app) { $databox = $file->getCollection()->get_databox(); $sql = 'INSERT INTO record (coll_id, record_id, parent_record_id, moddate, credate , type, sha256, uuid, originalname, mime) VALUES (:coll_id, null, :parent_record_id, NOW(), NOW() , :type, :sha256, :uuid , :originalname, :mime)'; $stmt = $databox->get_connection()->prepare($sql); $stmt->execute([':coll_id' => $file->getCollection()->get_coll_id(), ':parent_record_id' => 0, ':type' => $file->getType() ? $file->getType()->getType() : 'unknown', ':sha256' => $file->getMedia()->getHash('sha256'), ':uuid' => $file->getUUID(true), ':originalname' => $file->getOriginalName(), ':mime' => $file->getFile()->getMimeType()]); $stmt->closeCursor(); $record_id = $databox->get_connection()->lastInsertId(); $record = new self($app, $databox->get_sbas_id(), $record_id); try { $log_id = $app['phraseanet.logger']($databox)->get_id(); $sql = 'INSERT INTO log_docs (id, log_id, date, record_id, action, final, comment) VALUES (null, :log_id, now(), :record_id, "add", :coll_id,"")'; $stmt = $databox->get_connection()->prepare($sql); $stmt->execute([':log_id' => $log_id, ':record_id' => $record_id, ':coll_id' => $file->getCollection()->get_coll_id()]); $stmt->closeCursor(); } catch (\Exception $e) { unset($e); } $pathhd = databox::dispatch($app['filesystem'], trim($databox->get_sxml_structure()->path)); $newname = $record->get_record_id() . "_document." . pathinfo($file->getOriginalName(), PATHINFO_EXTENSION); $app['filesystem']->copy($file->getFile()->getRealPath(), $pathhd . $newname, true); $media = $app->getMediaFromUri($pathhd . $newname); media_subdef::create($app, $record, 'document', $media); $record->delete_data_from_cache(\record_adapter::CACHE_SUBDEFS); $record->insertTechnicalDatas($app['mediavorus']); $record->dispatch(RecordEvents::CREATED, new RecordCreatedEvent($record)); return $record; }
/** * {@inheritdoc} */ public function apply(base $appbox, Application $app) { $conn = $appbox->get_connection(); try { //get all old lazaret file & transform them to LazaretFile object $sql = 'SELECT * FROM lazaret'; $stmt = $conn->prepare($sql); $stmt->execute(); $rs = $stmt->fetchAll(); $stmt->closeCursor(); } catch (DBALException $e) { // table not found if ($e->getCode() == '42S02') { } return; } //order matters for foreign keys constraints //truncate all altered tables $this->truncateTable($app['orm.em'], 'Alchemy\\Phrasea\\Model\\Entities\\LazaretAttribute'); $this->truncateTable($app['orm.em'], 'Alchemy\\Phrasea\\Model\\Entities\\LazaretCheck'); $this->truncateTable($app['orm.em'], 'Alchemy\\Phrasea\\Model\\Entities\\LazaretFile'); $this->truncateTable($app['orm.em'], 'Alchemy\\Phrasea\\Model\\Entities\\LazaretSession'); $i = 0; foreach ($rs as $row) { $filePath = $app['tmp.lazaret.path'] . '/' . $row['filepath']; if (null === ($user = $this->loadUser($app['orm.em'], $row['usr_id']))) { continue; } if (file_exists($filePath)) { $spec = new ImageSpec(); $spec->setResizeMode(ImageSpec::RESIZE_MODE_INBOUND_FIXEDRATIO); $spec->setDimensions(375, 275); $thumbPath = $app['tmp.lazaret.path'] . '/' . sprintf("thumb_%s", $row['filepath']); try { $app['media-alchemyst']->turnInto($filePath, $thumbPath, $spec); } catch (MediaAlchemystException $e) { } $media = $app->getMediaFromUri($filePath); $collection = \collection::get_from_base_id($app, $row['base_id']); $borderFile = new \Alchemy\Phrasea\Border\File($app, $media, $collection); $lazaretSession = new LazaretSession(); $lazaretSession->setUser($user); $lazaretFile = new LazaretFile(); $lazaretFile->setBaseId($row['base_id']); if (null === $row['uuid']) { $uuid = $borderFile->getUUID(true); $lazaretFile->setUuid($uuid); } else { $lazaretFile->setUuid($row['uuid']); } if (null === $row['sha256']) { $sha256 = $media->getHash('sha256'); $lazaretFile->setSha256($sha256); } else { $lazaretFile->setSha256($row['sha256']); } $lazaretFile->setOriginalName($row['filename']); $lazaretFile->setFilename($row['filepath']); $lazaretFile->setThumbFilename(pathinfo($thumbPath), PATHINFO_BASENAME); $lazaretFile->setCreated(new \DateTime($row['created_on'])); $lazaretFile->setSession($lazaretSession); $app['orm.em']->persist($lazaretFile); if (0 === ++$i % 100) { $app['orm.em']->flush(); $app['orm.em']->clear(); } } } $app['orm.em']->flush(); $app['orm.em']->clear(); $stmt->closeCursor(); return true; }
/** * @param Application $app * @param \media_subdef $subdef * * @return string The path to the stamped file */ public static function stamp(Application $app, \media_subdef $subdef) { static $palette; if (null === $palette) { $palette = new RGB(); } $xmlToColor = function ($attr, $ret = [255, 255, 255]) use($palette) { try { $alpha = 100; $attr = explode(',', $attr); if (count($attr) == 4) { // 0..127 -> 100..0 $alpha = (int) ((127 - (int) array_pop($attr)) / 1.27); } return $palette->color($attr, $alpha); } catch (ImagineException $e) { return $palette->color($ret); } }; $base_id = $subdef->get_record()->get_base_id(); if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) { return $subdef->get_pathfile(); } if (!$subdef->is_physically_present()) { return $subdef->get_pathfile(); } $rotation = null; try { $image = $app->getMediaFromUri($subdef->get_pathfile()); if (MediaInterface::TYPE_IMAGE === $image->getType()) { $rotation = $image->getOrientation(); } } catch (\Exception $e) { // getting orientation failed but we don't care the reason } $domprefs = new DOMDocument(); if (false === $domprefs->loadXML($subdef->get_record()->get_collection()->get_prefs())) { return $subdef->get_pathfile(); } if (false === ($sxxml = simplexml_load_string($app['serializer.caption']->serialize($subdef->get_record()->get_caption(), CaptionSerializer::SERIALIZE_XML)))) { return $subdef->get_pathfile(); } $xpprefs = new DOMXPath($domprefs); $stampNodes = $xpprefs->query('/baseprefs/stamp'); if ($stampNodes->length == 0) { return $subdef->get_pathfile(); } $pathIn = $subdef->get_path() . $subdef->get_file(); $pathOut = $subdef->get_path() . 'stamp_' . $subdef->get_file(); $vars = $xpprefs->query('/baseprefs/stamp/*/var'); // no way to cache when date changes for ($i = 0; $i < $vars->length; $i++) { if (strtoupper($vars->item($i)->getAttribute('name')) == 'DATE') { @unlink($pathOut); break; } } // get from cache ? if (is_file($pathOut)) { return $pathOut; } // open the document $image_in = $app['imagine']->open($pathIn); $image_size = $image_in->getSize(); switch ($rotation) { case Image::ORIENTATION_90: $image_width = $image_size->getHeight(); $image_height = $image_size->getWidth(); $image_in->rotate(90); $rotation = '90'; break; case Image::ORIENTATION_270: $image_width = $image_size->getHeight(); $image_height = $image_size->getWidth(); $image_in->rotate(270); break; case Image::ORIENTATION_180: $image_width = $image_size->getWidth(); $image_height = $image_size->getHeight(); $image_in->rotate(180); break; default: $image_width = $image_size->getWidth(); $image_height = $image_size->getHeight(); break; } // open the logo $logo_phywidth = $logo_phyheight = 0; // physical size $logo_file = $app['root.path'] . '/config/stamp/' . $base_id; try { $logo_obj = $app['imagine']->open($logo_file); $logo_size = $logo_obj->getSize(); $logo_phywidth = $logo_size->getWidth(); $logo_phyheight = $logo_size->getHeight(); } catch (ImagineException $e) { } $tables = ['TOP' => ['h' => 0, 'rows' => []], 'TOP-OVER' => ['h' => 0, 'rows' => []], 'BOTTOM' => ['h' => 0, 'rows' => []], 'BOTTOM-OVER' => ['h' => 0, 'rows' => []]]; for ($istamp = 0; $istamp < $stampNodes->length; $istamp++) { $stamp = $stampNodes->item($istamp); $stamp_background = $xmlToColor($stamp->getAttribute('background'), [255, 255, 255]); $stamp_position = strtoupper(trim($stamp->getAttribute('position'))); if (!in_array($stamp_position, ['TOP', 'TOP-OVER', 'BOTTOM-OVER', 'BOTTOM'])) { $stamp_position = 'BOTTOM'; } // replace "var" nodes with their value $vars = $xpprefs->query('*/var', $stamp); for ($i = 0; $i < $vars->length; $i++) { $varval = ''; $n = $vars->item($i); switch (strtoupper($n->getAttribute('name'))) { case 'DATE': if (!($format = $n->getAttribute('format'))) { $format = 'Y/m/d H:i:s'; } $varval = date($format); @unlink($pathOut); // no cache possible when date changes break; case 'RECORD_ID': $varval = $subdef->get_record()->get_record_id(); break; } $n->parentNode->replaceChild($domprefs->createTextNode($varval), $n); } // replace "field" nodes with their values $fields = $xpprefs->query('*/field', $stamp); for ($i = 0; $i < $fields->length; $i++) { $fldval = ''; $n = $fields->item($i); $fieldname = $n->getAttribute('name'); $x = $sxxml->description->{$fieldname}; if (is_array($x)) { foreach ($x as $v) { $fldval .= ($fldval ? '; ' : '') . (string) $v; } } else { $fldval .= ($fldval ? '; ' : '') . (string) $x; } $n->parentNode->replaceChild($domprefs->createTextNode($fldval), $n); } $domprefs->normalizeDocument(); $text_width = $image_width; $logopos = null; // compute logo position / size $logo_reswidth = 0; $logo_resheight = 0; if ($logo_phywidth > 0 && $logo_phyheight > 0) { $v = $xpprefs->query('logo', $stamp); if ($v->length > 0) { $logo_reswidth = $logo_phywidth; $logo_resheight = $logo_phyheight; $logopos = @strtoupper($v->item(0)->getAttribute('position')); if (($logowidth = trim($v->item(0)->getAttribute('width'))) != '') { if (substr($logowidth, -1) == '%') { $logo_reswidth = (int) ($logowidth * $image_width / 100); } else { $logo_reswidth = (int) $logowidth; } $logo_resheight = (int) ($logo_phyheight * ($logo_reswidth / $logo_phywidth)); } if ($logopos == 'LEFT' || $logopos == 'RIGHT') { if ($logo_reswidth > $image_width / 2) { // logo too large, resize please $logo_reswidth = (int) ($image_width / 2); $logo_resheight = (int) ($logo_phyheight * ($logo_reswidth / $logo_phywidth)); } $text_width -= $logo_reswidth; if ($logopos == 'LEFT') { $logo_xpos = 0; } else { $logo_xpos = $image_width - $logo_reswidth; } } } } // compute text blocks $txth = 0; $txtblock = []; $texts = $xpprefs->query('text', $stamp); $fontsize = "100%"; for ($i = 0; $i < $texts->length; $i++) { if (($tmpfontsize = trim($texts->item($i)->getAttribute('size'))) != '') { if (substr($tmpfontsize, -1) == '%') { $tmpfontsize = (int) ($tmpfontsize * $image_width / 4000); } else { $tmpfontsize = (int) $tmpfontsize; } $fontsize = $tmpfontsize; } if ($fontsize < 2) { $fontsize = 2; } elseif ($fontsize > 300) { $fontsize = 300; } $txtline = $texts->item($i)->nodeValue; if ($txtline != '') { $wrap = static::wrap($app['imagine'], $fontsize, 0, __DIR__ . '/arial.ttf', $txtline, $text_width); $txtblock[] = ['fontsize' => $fontsize, 'fontcolor' => $xmlToColor($texts->item($i)->getAttribute('color'), [0, 0, 0]), 'h' => $wrap['toth'], 'lines' => $wrap['l']]; $txth += $wrap['toth']; } } $stampheight = max($logo_resheight, $txth); if ($stamp_position == 'TOP-OVER' || $stamp_position == 'BOTTOM-OVER') { if ($tables[$stamp_position]['h'] + $stampheight > $image_height) { $stampheight = $image_height - $tables[$stamp_position]['h']; } } if ($stampheight <= 0) { continue; } // create the block $imfg = $app['imagine']->create(new Box($image_width, $stampheight), $stamp_background); // copy the logo if ($logo_reswidth > 0 && $logo_resheight > 0) { if ($logo_reswidth != $logo_phywidth) { $imfg->paste($logo_obj->copy()->resize(new Box($logo_reswidth, $logo_resheight)), new Point($logo_xpos, 0)); } else { $imfg->paste($logo_obj, new Point($logo_xpos, 0)); } } // fill with text $draw = $imfg->draw(); $txt_ypos = 0; foreach ($txtblock as $block) { $font = $app['imagine']->font(__DIR__ . '/arial.ttf', $block['fontsize'], $block['fontcolor']); foreach ($block['lines'] as $line) { if ($line['t'] != '') { $draw->text($line['t'], $font, new Point($logo_reswidth, $txt_ypos), 0); } $txt_ypos += $line['h']; } } // memo into one of the 4 buffer $tables[$stamp_position]['rows'][] = ['x0' => 0, 'y0' => $tables[$stamp_position]['h'], 'w' => $image_width, 'h' => $stampheight, 'img' => $imfg]; $tables[$stamp_position]['h'] += $stampheight; } $newh = $tables['TOP']['h'] + $image_height + $tables['BOTTOM']['h']; // create the output image $image_out = $app['imagine']->create(new Box($image_width, $newh), $palette->color("FFFFFF", 64)); // paste the input image into $image_out->paste($image_in, new Point(0, $tables['TOP']['h'])); // fix the coordinates foreach ($tables['TOP-OVER']['rows'] as $k => $row) { $tables['TOP-OVER']['rows'][$k]['y0'] += $tables['TOP']['h']; } foreach ($tables['BOTTOM-OVER']['rows'] as $k => $row) { $tables['BOTTOM-OVER']['rows'][$k]['y0'] += $tables['TOP']['h'] + $image_height - $tables['BOTTOM-OVER']['h']; } foreach ($tables['BOTTOM']['rows'] as $k => $row) { $tables['BOTTOM']['rows'][$k]['y0'] += $tables['TOP']['h'] + $image_height; } // paste blocks foreach (['TOP', 'TOP-OVER', 'BOTTOM-OVER', 'BOTTOM'] as $ta) { foreach ($tables[$ta]['rows'] as $row) { if ($row['h'] > 0) { $image_out->paste($row['img'], new Point($row['x0'], $row['y0'])); } } } // save the output $image_out->save($pathOut); if (is_file($pathOut)) { // copy metadatas to the stamped file if we can if (method_exists($app['exiftool.writer'], "copy")) { $app['exiftool.writer']->copy($subdef->get_pathfile(), $pathOut); } return $pathOut; } return $subdef->get_pathfile(); }