/** * The constructor. * * @param Alpha\Model\ActiveRecord $BO * @param bool $useCache * * @since 1.0 */ public function __construct($BO, $useCache = true) { $config = ConfigProvider::getInstance(); $this->BO = $BO; if ($this->BO instanceof \Alpha\Model\Article && $this->BO->isLoadedFromFile()) { $underscoreTimeStamp = str_replace(array('-', ' ', ':'), '_', $this->BO->getContentFileDate()); $this->filename = $config->get('app.file.store.dir') . 'cache/html/' . get_class($this->BO) . '_' . $this->BO->get('title') . '_' . $underscoreTimeStamp . '.html'; } else { $this->filename = $config->get('app.file.store.dir') . 'cache/html/' . get_class($this->BO) . '_' . $this->BO->getID() . '_' . $this->BO->getVersion() . '.html'; } if (!$useCache) { $this->content = $this->markdown($this->BO->get('content', true)); } else { if ($this->checkCache()) { $this->loadCache(); } else { if ($this->BO->get('content', true) == '') { // the content may not be loaded from the DB at this stage due to a previous soft-load $this->BO->reload(); } $this->content = $this->markdown($this->BO->get('content', true)); $this->cache(); } } // Replace all instances of $attachURL in link tags to links to the ViewAttachment controller $attachments = array(); preg_match_all('/href\\=\\"\\$attachURL\\/.*\\"/', $this->content, $attachments); foreach ($attachments[0] as $attachmentURL) { $start = mb_strpos($attachmentURL, '/'); $end = mb_strrpos($attachmentURL, '"'); $fileName = mb_substr($attachmentURL, $start + 1, $end - ($start + 1)); if (method_exists($this->BO, 'getAttachmentSecureURL')) { $this->content = str_replace($attachmentURL, 'href="' . $this->BO->getAttachmentSecureURL($fileName) . '" rel="nofollow"', $this->content); } } // Handle image attachments $attachments = array(); preg_match_all('/\\<img\\ src\\=\\"\\$attachURL\\/.*\\.[a-zA-Z]{3}\\"[^<]*/', $this->content, $attachments); foreach ($attachments[0] as $attachmentURL) { preg_match('/\\/.*\\.[a-zA-Z]{3}/', $attachmentURL, $matches); $fileName = $matches[0]; if ($config->get('cms.images.widget')) { // get the details of the source image $path = $this->BO->getAttachmentsLocation() . $fileName; $image_details = getimagesize($path); $imgType = $image_details[2]; if ($imgType == 1) { $type = 'gif'; } elseif ($imgType == 2) { $type = 'jpg'; } elseif ($imgType == 3) { $type = 'png'; } $img = new Image($path, $image_details[0], $image_details[1], $type, 0.95, false, (bool) $config->get('cms.images.widget.secure')); $this->content = str_replace($attachmentURL, $img->renderHTMLLink(), $this->content); } else { // render a normal image link to the ViewAttachment controller if (method_exists($this->BO, 'getAttachmentSecureURL')) { $this->content = str_replace($attachmentURL, '<img src="' . $this->BO->getAttachmentSecureURL($fileName) . '">', $this->content); } } } }
/** * Cast a BO to another type of BO. A new BO will be returned with the same OID and * version_num as the old BO, so this is NOT a true cast but is a copy. All attribute * values will be copied accross. * * @param string $targetClassName The fully-qualified name of the target BO class. * @param Alpha\Model\ActiveRecord $originalBO The original business object. * * @return Alpha\Model\ActiveRecord The new business object resulting from the cast. * * @since 1.0 */ public function cast($targetClassName, $originalBO) { $BO = new $targetClassName(); $BO->setOID($originalBO->getOID()); $BO->setVersion($originalBO->getVersion()); // get the class attributes $originalBOreflection = new ReflectionClass(get_class($originalBO)); $originalBOproperties = $originalBOreflection->getProperties(); $newBOreflection = new ReflectionClass($targetClassName); $newBOproperties = $newBOreflection->getProperties(); // copy the property values from the old BO to the new BO if (count($originalBOproperties) < count($newBOproperties)) { // the original BO is smaller, so loop over its properties foreach ($originalBOproperties as $propObj) { $propName = $propObj->name; if (!in_array($propName, $this->transientAttributes)) { $BO->set($propName, $originalBO->get($propName)); } } } else { // the new BO is smaller, so loop over its properties foreach ($newBOproperties as $propObj) { $propName = $propObj->name; if (!in_array($propName, $this->transientAttributes)) { $BO->set($propName, $originalBO->get($propName)); } } } return $BO; }
/** * The constructor. * * @param Alpha\Model\ActiveRecord $BO the business object that stores the content will be rendered to Markdown * * @since 1.0 */ public function __construct($BO) { self::$logger = new Logger('TCPDFFacade'); self::$logger->debug('>>__construct()'); $config = ConfigProvider::getInstance(); $this->BO = $BO; $reflect = new \ReflectionClass($this->BO); $classname = $reflect->getShortName(); $this->PDFFilename = $config->get('app.file.store.dir') . 'cache/pdf/' . $classname . '_' . $this->BO->getID() . '_' . $this->BO->getVersion() . '.pdf'; $PDFDownloadName = str_replace(' ', '_', $this->BO->get('title') . '.pdf'); $this->HTMLFilename = $config->get('app.file.store.dir') . 'cache/html/' . $classname . '_' . $this->BO->getID() . '_' . $this->BO->getVersion() . '.html'; // first check the PDF cache if ($this->checkPDFCache()) { return; } if (method_exists($this->BO, 'getAttachmentsURL')) { $attachURL = $this->BO->getAttachmentsURL(); } else { $attachURL = ''; } if ($this->checkHTMLCache()) { $this->loadHTMLCache(); } else { $this->content = $this->markdown($this->BO->get('content', true), $attachURL); $this->HTMLCache(); } // Replace all instances of $attachURL in link tags to links to the ViewAttachment controller $attachments = array(); preg_match_all('/href\\=\\"\\$attachURL\\/.*\\"/', $this->content, $attachments); foreach ($attachments[0] as $attachmentURL) { $start = mb_strpos($attachmentURL, '/'); $end = mb_strrpos($attachmentURL, '"'); $fileName = mb_substr($attachmentURL, $start + 1, $end - ($start + 1)); if (method_exists($this->BO, 'getAttachmentSecureURL')) { $this->content = str_replace($attachmentURL, 'href=' . $this->BO->getAttachmentSecureURL($fileName), $this->content); } } // Handle image attachments $attachments = array(); preg_match_all('/\\<img\\ src\\=\\"\\$attachURL\\/.*\\".*\\>/', $this->content, $attachments); foreach ($attachments[0] as $attachmentURL) { $start = mb_strpos($attachmentURL, '/'); $end = mb_strrpos($attachmentURL, '" alt'); $fileName = mb_substr($attachmentURL, $start + 1, $end - ($start + 1)); if ($config->get('cms.images.widget')) { // get the details of the source image $path = $this->BO->getAttachmentsLocation() . '/' . $fileName; $image_details = getimagesize($path); $imgType = $image_details[2]; if ($imgType == 1) { $type = 'gif'; } elseif ($imgType == 2) { $type = 'jpg'; } elseif ($imgType == 3) { $type = 'png'; } $img = new Image($path, $image_details[0], $image_details[1], $type, 0.95, false, (bool) $config->get('cms.images.widget.secure')); $this->content = str_replace($attachmentURL, $img->renderHTMLLink(), $this->content); } else { // render a normal image link to the ViewAttachment controller if (method_exists($this->BO, 'getAttachmentSecureURL')) { $this->content = str_replace($attachmentURL, '<img src="' . $this->BO->getAttachmentSecureURL($fileName) . '">', $this->content); } } } $this->pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); $this->pdf->SetCreator(PDF_CREATOR); $this->pdf->SetAuthor($this->BO->get('author')); $this->pdf->SetTitle($this->BO->get('title')); $this->pdf->SetSubject($this->BO->get('description')); //set margins $this->pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT); $this->pdf->SetHeaderMargin(PDF_MARGIN_HEADER); $this->pdf->SetFooterMargin(PDF_MARGIN_FOOTER); //set auto page breaks $this->pdf->SetAutoPageBreak(true, PDF_MARGIN_BOTTOM); //set image scale factor $this->pdf->setImageScale(2.5); // add a page $this->pdf->AddPage(); // add the title $title = '<h1>' . $this->BO->get('title') . '</h1>'; // add some custom footer info about the article $footer = '<br><p>Article URL: <a href="' . $this->BO->get('URL') . '">' . $this->BO->get('URL') . '</a><br>Title: ' . $this->BO->get('title') . '<br>Author: ' . $this->BO->get('author') . '</p>'; // write the title self::$logger->debug('Writing the title [' . $title . '] to the PDF'); $this->pdf->writeHTML(utf8_encode($title), true, false, true, false, ''); // output the HTML content self::$logger->debug('Writing the content [' . $this->content . '] to the PDF'); $this->pdf->writeHTML(utf8_encode($this->content), true, false, true, false, ''); // write the article footer $this->pdf->writeHTML(utf8_encode($footer), true, false, true, false, ''); self::$logger->debug('Writing the footer [' . $footer . '] to the PDF'); // save this PDF to the cache $this->pdf->Output($this->PDFFilename, 'F'); self::$logger->debug('<<__construct()'); }
/** * (non-PHPdoc). * * @see Alpha\Model\ActiveRecordProviderInterface::save() */ public function save() { self::$logger->debug('>>save()'); $config = ConfigProvider::getInstance(); $sessionProvider = $config->get('session.provider.name'); $session = SessionProviderFactory::getInstance($sessionProvider); // get the class attributes $reflection = new ReflectionClass(get_class($this->BO)); $properties = $reflection->getProperties(); $sqlQuery = ''; $stmt = null; if ($this->BO->getVersion() != $this->BO->getVersionNumber()->getValue()) { throw new LockingException('Could not save the object as it has been updated by another user. Please try saving again.'); return; } // set the "updated by" fields, we can only set the user id if someone is logged in if ($session->get('currentUser') != null) { $this->BO->set('updated_by', $session->get('currentUser')->getOID()); } $this->BO->set('updated_ts', new Timestamp(date('Y-m-d H:i:s'))); // check to see if it is a transient object that needs to be inserted if ($this->BO->isTransient()) { $savedFieldsCount = 0; $sqlQuery = 'INSERT INTO ' . $this->BO->getTableName() . ' ('; foreach ($properties as $propObj) { $propName = $propObj->name; if (!in_array($propName, $this->BO->getTransientAttributes())) { // Skip the OID, database auto number takes care of this. if ($propName != 'OID' && $propName != 'version_num') { $sqlQuery .= "{$propName},"; ++$savedFieldsCount; } if ($propName == 'version_num') { $sqlQuery .= 'version_num,'; ++$savedFieldsCount; } } } if ($this->BO->isTableOverloaded()) { $sqlQuery .= 'classname,'; } $sqlQuery = rtrim($sqlQuery, ','); $sqlQuery .= ') VALUES ('; for ($i = 0; $i < $savedFieldsCount; ++$i) { $sqlQuery .= '?,'; } if ($this->BO->isTableOverloaded()) { $sqlQuery .= '?,'; } $sqlQuery = rtrim($sqlQuery, ',') . ')'; $this->BO->setLastQuery($sqlQuery); self::$logger->debug('Query [' . $sqlQuery . ']'); $stmt = self::getConnection()->stmt_init(); if ($stmt->prepare($sqlQuery)) { $stmt = $this->bindParams($stmt); $stmt->execute(); } else { throw new FailedSaveException('Failed to save object, error is [' . $stmt->error . '], query [' . $this->BO->getLastQuery() . ']'); } } else { // assume that it is a persistent object that needs to be updated $savedFieldsCount = 0; $sqlQuery = 'UPDATE ' . $this->BO->getTableName() . ' SET '; foreach ($properties as $propObj) { $propName = $propObj->name; if (!in_array($propName, $this->BO->getTransientAttributes())) { // Skip the OID, database auto number takes care of this. if ($propName != 'OID' && $propName != 'version_num') { $sqlQuery .= "{$propName} = ?,"; ++$savedFieldsCount; } if ($propName == 'version_num') { $sqlQuery .= 'version_num = ?,'; ++$savedFieldsCount; } } } if ($this->BO->isTableOverloaded()) { $sqlQuery .= 'classname = ?,'; } $sqlQuery = rtrim($sqlQuery, ','); $sqlQuery .= ' WHERE OID=?;'; $this->BO->setLastQuery($sqlQuery); $stmt = self::getConnection()->stmt_init(); if ($stmt->prepare($sqlQuery)) { $this->bindParams($stmt); $stmt->execute(); } else { throw new FailedSaveException('Failed to save object, error is [' . $stmt->error . '], query [' . $this->BO->getLastQuery() . ']'); } } if ($stmt != null && $stmt->error == '') { // populate the updated OID in case we just done an insert if ($this->BO->isTransient()) { $this->BO->setOID(self::getConnection()->insert_id); } try { foreach ($properties as $propObj) { $propName = $propObj->name; if ($this->BO->getPropObject($propName) instanceof Relation) { $prop = $this->BO->getPropObject($propName); // handle the saving of MANY-TO-MANY relation values if ($prop->getRelationType() == 'MANY-TO-MANY' && count($prop->getRelatedOIDs()) > 0) { try { try { // check to see if the rel is on this class $side = $prop->getSide(get_class($this->BO)); } catch (IllegalArguementException $iae) { $side = $prop->getSide(get_parent_class($this->BO)); } $lookUp = $prop->getLookup(); // first delete all of the old RelationLookup objects for this rel try { if ($side == 'left') { $lookUp->deleteAllByAttribute('leftID', $this->BO->getOID()); } else { $lookUp->deleteAllByAttribute('rightID', $this->BO->getOID()); } } catch (\Exception $e) { throw new FailedSaveException('Failed to delete old RelationLookup objects on the table [' . $prop->getLookup()->getTableName() . '], error is [' . $e->getMessage() . ']'); } $OIDs = $prop->getRelatedOIDs(); if (isset($OIDs) && !empty($OIDs[0])) { // now for each posted OID, create a new RelationLookup record and save foreach ($OIDs as $oid) { $newLookUp = new RelationLookup($lookUp->get('leftClassName'), $lookUp->get('rightClassName')); if ($side == 'left') { $newLookUp->set('leftID', $this->BO->getOID()); $newLookUp->set('rightID', $oid); } else { $newLookUp->set('rightID', $this->BO->getOID()); $newLookUp->set('leftID', $oid); } $newLookUp->save(); } } } catch (\Exception $e) { throw new FailedSaveException('Failed to update a MANY-TO-MANY relation on the object, error is [' . $e->getMessage() . ']'); return; } } // handle the saving of ONE-TO-MANY relation values if ($prop->getRelationType() == 'ONE-TO-MANY') { $prop->setValue($this->BO->getOID()); } } } } catch (\Exception $e) { throw new FailedSaveException('Failed to save object, error is [' . $e->getMessage() . ']'); return; } $stmt->close(); } else { // there has been an error, so decrement the version number back $temp = $this->BO->getVersionNumber()->getValue(); $this->BO->set('version_num', $temp - 1); // check for unique violations if (self::getConnection()->errno == '1062') { throw new ValidationException('Failed to save, the value ' . $this->findOffendingValue(self::getConnection()->error) . ' is already in use!'); return; } else { throw new FailedSaveException('Failed to save object, MySql error is [' . self::getConnection()->error . '], query [' . $this->BO->getLastQuery() . ']'); } } if ($this->BO->getMaintainHistory()) { $this->BO->saveHistory(); } }