/concrete/core/models/block_types.php
PHP | 1056 lines | 627 code | 149 blank | 280 comment | 105 complexity | c0f0e4e2cb23e200084fd840700a6847 MD5 | raw file
- <?php
- defined('C5_EXECUTE') or die("Access Denied.");
- /**
- * Contains the blocktype object, the block type list (which is just a wrapper for querying the system for block types, and the block type
- * DB wrapper for ADODB.
- * @package Blocks
- * @author Andrew Embler <andrew@concrete5.org>
- * @category Concrete
- * @copyright Copyright (c) 2003-2008 Concrete5. (http://www.concrete5.org)
- * @license http://www.concrete5.org/license/ MIT License
- *
- */
-
- /**
- *
- * The block type list object holds types of blocks, takes care of querying the file system for newly available
- * @author Andrew Embler <andrew@concrete5.org>
- * @copyright Copyright (c) 2003-2008 Concrete5. (http://www.concrete5.org)
- * @license http://www.concrete5.org/license/ MIT License
- * @package Blocks
- * @category Concrete
- */
- class Concrete5_Model_BlockTypeList extends Object {
- /**
- * array of BlockType objects - should likely be considered a protected property
- * use getBlockTypeList instead of accessing this property directly
- * @see BlockTypeList::getBlockTypeList()
- * @var BlockType[] $btArray
- */
- public $btArray = array();
-
- /**
- * Gets an array of BlockTypes for a given Package
- * @param Package $pkg
- * @return BlockType[]
- */
- public static function getByPackage($pkg) {
- $db = Loader::db();
- $r = $db->Execute("select btID from BlockTypes where pkgID = ?", $pkg->getPackageID());
- $blockTypes = array();
- while ($row = $r->FetchRow()) {
- $blockTypes[] = BlockType::getByID($row['btID']);
- }
- return $blockTypes;
- }
-
-
- /**
- * @todo comment this one
- * @param string $xml
- * @return void
- */
- public static function exportList($xml) {
- $attribs = self::getInstalledList();
- $nxml = $xml->addChild('blocktypes');
- foreach($attribs as $bt) {
- $type = $nxml->addChild('blocktype');
- $type->addAttribute('handle', $bt->getBlockTypeHandle());
- $type->addAttribute('package', $bt->getPackageHandle());
- }
- }
-
- /**
- * returns an array of Block Types used in the concrete5 Dashboard
- * @param Area $ap
- * @return BlockType[]
- */
- public static function getDashboardBlockTypes() {
- $db = Loader::db();
- $btIDs = $db->GetCol('select btID from BlockTypes where btHandle like "dashboard_%" order by btDisplayOrder asc, btID asc');
- $blockTypes = array();
- foreach($btIDs as $btID) {
- $blockTypes[] = BlockType::getByID($btID);
- }
- return $blockTypes;
- }
-
- /**
- * BlockTypeList class constructor
- * @param array $allowedBlocks array of allowed BlockType id's if you'd like to limit the list to just those
- * @return BlockTypeList
- */
- function __construct($allowedBlocks = null) {
- $db = Loader::db();
- $this->btArray = array();
-
- $q = "select btID from BlockTypes where btIsInternal = 0 ";
- if ($allowedBlocks != null) {
- $q .= ' and btID in (' . implode(',', $allowedBlocks) . ') ';
- }
- $q .= ' order by btDisplayOrder asc, btName asc, btID asc';
-
- $r = $db->query($q);
-
- if ($r) {
- while ($row = $r->fetchRow()) {
- $bt = BlockType::getByID($row['btID']);
- if (is_object($bt)) {
- $this->btArray[] = $bt;
- }
- }
- $r->free();
- }
-
- return $this;
- }
-
- /**
- * gets the array of BlockType objects
- * @return BlockType[]
- * @see BlockTypeList::getInstalledList()
- */
- public function getBlockTypeList() {
- return $this->btArray;
- }
- /**
- * Gets a list of block types that are not installed, used to get blocks that can be installed
- * This function only surveys the web/blocks directory - it's not looking at the package level.
- * @return BlockType[]
- */
- public static function getAvailableList() {
- $env = Environment::get();
- $env->clearOverrideCache();
- $blocktypes = array();
- $dir = DIR_FILES_BLOCK_TYPES;
- $db = Loader::db();
-
- $btHandles = $db->GetCol("select btHandle from BlockTypes order by btDisplayOrder asc, btName asc, btID asc");
-
- $aDir = array();
- if (is_dir($dir)) {
- $currentLocale = Localization::activeLocale();
- if ($currentLocale != 'en_US') {
- Localization::changeLocale('en_US');
- }
- $handle = opendir($dir);
- while(($file = readdir($handle)) !== false) {
- if (strpos($file, '.') === false) {
- $fdir = $dir . '/' . $file;
- if (is_dir($fdir) && !in_array($file, $btHandles) && file_exists($fdir . '/' . FILENAME_BLOCK_CONTROLLER)) {
- $bt = new BlockType;
- $bt->btHandle = $file;
- $class = $bt->getBlockTypeClass();
-
- require_once($fdir . '/' . FILENAME_BLOCK_CONTROLLER);
- if (!class_exists($class)) {
- continue;
- }
- $bta = new $class;
- $bt->btName = $bta->getBlockTypeName();
- $bt->btDescription = $bta->getBlockTypeDescription();
- $bt->hasCustomViewTemplate = file_exists(DIR_FILES_BLOCK_TYPES . '/' . $file . '/' . FILENAME_BLOCK_VIEW);
- $bt->hasCustomEditTemplate = file_exists(DIR_FILES_BLOCK_TYPES . '/' . $file . '/' . FILENAME_BLOCK_EDIT);
- $bt->hasCustomAddTemplate = file_exists(DIR_FILES_BLOCK_TYPES . '/' . $file . '/' . FILENAME_BLOCK_ADD);
- $bt->installed = false;
- $bt->btID = null;
- $blocktypes[] = $bt;
-
- }
- }
- }
- if ($currentLocale != 'en_US') {
- Localization::changeLocale($currentLocale);
- }
- }
-
- return $blocktypes;
- }
- /**
- * gets a list of installed BlockTypes
- * @return BlockType[]
- */
- public static function getInstalledList() {
- $db = Loader::db();
- $r = $db->query("select btID from BlockTypes order by btDisplayOrder asc, btName asc, btID asc");
- $btArray = array();
- while ($row = $r->fetchRow()) {
- $bt = BlockType::getByID($row['btID']);
- if (is_object($bt)) {
- $btArray[] = $bt;
- }
- }
- return $btArray;
- }
-
- /**
- * Gets a list of installed BlockTypes
- * - could be defined as static
- * @todo we have three duplicate functions getBlockTypeArray, getInstalledList, getBlockTypeList
- * @return BlockType[]
- */
- public function getBlockTypeArray() {
- $db = Loader::db();
- $q = "select btID from BlockTypes order by btDisplayOrder asc, btName asc, btID asc";
- $r = $db->query($q);
- $btArray = array();
- if ($r) {
- while ($row = $r->fetchRow()) {
- $bt = BlockType::getByID($row['btID']);
- if (is_object($bt)) {
- $btArray[] = $bt;
- }
- }
- $r->free();
- }
- return $btArray;
- }
-
- /**
- * gets the form post action for the current block type given the area
- * @param Area $a
- * @return string
- */
- public function getBlockTypeAddAction(&$a) {
- $step = ($_REQUEST['step']) ? '&step=' . $_REQUEST['step'] : '';
- $arHandle = urlencode($a->getAreaHandle());
- $c = $a->getAreaCollectionObject();
- $cID = $c->getCollectionID();
- $valt = Loader::helper('validation/token');
- $str = DIR_REL . "/" . DISPATCHER_FILENAME . "?cID={$cID}&areaName={$arHandle}&mode=edit&btask=add" . $step . '&' . $valt->getParameter();
- return $str;
- }
-
- /**
- * gets the form post action for the current block type given the area
- * @param Area $a
- * @return string
- */
- public function getBlockTypeAliasAction(&$a) {
- $step = ($_REQUEST['step']) ? '&step=' . $_REQUEST['step'] : '';
- $arHandle = urlencode($a->getAreaHandle());
- $c = $a->getAreaCollectionObject();
- $cID = $c->getCollectionID();
- $str = DIR_REL . "/" . DISPATCHER_FILENAME . "?cID={$cID}&areaName={$arHandle}&mode=edit&btask=alias" . $step . '&' . $valt->getParameter();
- return $str;
- }
-
- public static function resetBlockTypeDisplayOrder($column = 'btID') {
- $db = Loader::db();
- $stmt = $db->Prepare("UPDATE BlockTypes SET btDisplayOrder = ? WHERE btID = ?");
- $btDisplayOrder = 1;
- $blockTypes = $db->GetArray("SELECT btID, btHandle, btIsInternal FROM BlockTypes ORDER BY {$column} ASC");
- foreach ($blockTypes as $bt) {
- if ($bt['btIsInternal']) {
- $db->Execute($stmt, array(0, $bt['btID']));
- } else {
- $db->Execute($stmt, array($btDisplayOrder, $bt['btID']));
- $btDisplayOrder++;
- }
- }
- }
-
- }
- /**
- *
- * @access private
- */
- class Concrete5_Model_BlockTypeDB extends ADOdb_Active_Record {
- public $_table = 'BlockTypes';
- }
- /**
- *
- * Any type of content that can be added to pages is represented as a type of block, and thereby a block type object.
- * @package Blocks
- * @author Andrew Embler <andrew@concrete5.org>
- * @license http://www.concrete5.org/license/ MIT License
- * @package Blocks
- * @category Concrete
- */
- class Concrete5_Model_BlockType extends Object {
- /**
- * @var array $addBTUArray
- */
- public $addBTUArray = array();
-
- /**
- * @var array $addBTGArray
- */
- public $addBTGArray = array();
-
- /**
- * @var BlockTypeController
- */
- public $controller;
-
- /**
- * Gets the BlockType object for the given Block Type Handle
- * ex:
- * <code><?php
- * $bt = BlockType::getByHandle('content'); // returns the BlockType object for the core Content block
- * ?></code>
- * @param string $handle
- * @return BlockType|false
- */
- public static function getByHandle($handle) {
- $bt = CacheLocal::getEntry('blocktype', $handle);
- if ($bt === -1) {
- return false;
- }
- if (is_object($bt)) {
- $bt->controller = Loader::controller($bt);
- return $bt;
- }
- $bt = BlockType::get('btHandle = ?', array($handle));
- if (is_object($bt)) {
- CacheLocal::set('blocktype', $handle, $bt);
- $bt->controller = Loader::controller($bt);
- return $bt;
- }
- CacheLocal::set('blocktype', $handle, -1);
- return false;
- }
- /**
- * Gets the BlockType for a given Block Type ID
- * @param int $btID
- * @return BlockType
- */
- public static function getByID($btID) {
- $bt = CacheLocal::getEntry('blocktype', $btID);
- if ($bt === -1) {
- return false;
- } else if (!is_object($bt)) {
- $where = 'btID = ?';
- $bt = BlockType::get($where, array($btID));
- if (is_object($bt)) {
- CacheLocal::set('blocktype', $btID, $bt);
- } else {
- CacheLocal::set('blocktype', $btID, -1);
- }
- }
- $bt->controller = Loader::controller($bt);
- return $bt;
- }
-
-
- /**
- * internal method to query the BlockTypes table and get a BlockType object
- * @param string
- * @param array
- */
- protected static function get($where, $properties) {
- $db = Loader::db();
-
- $q = "select btID, btName, btDescription, btHandle, pkgID, btActiveWhenAdded, btIsInternal, btCopyWhenPropagate, btIncludeAll, btDisplayOrder, btInterfaceWidth, btInterfaceHeight from BlockTypes where {$where}";
-
- $r = $db->query($q, $properties);
-
- if ($r->numRows() > 0) {
- $row = $r->fetchRow();
- $bt = new BlockType;
- $bt->setPropertiesFromArray($row);
- return $bt;
- }
-
- }
-
- /**
- * if a the current BlockType is Internal or not - meaning one of the core built-in concrete5 blocks
- * @access private
- * @return boolean
- */
- function isBlockTypeInternal() {return $this->btIsInternal;}
-
- /**
- * Returns true if the block type is internal (and therefore cannot be removed) a core block
- * @return boolean
- */
- public function isInternalBlockType() {
- return $this->btIsInternal;
- }
-
- /**
- * Returns true if the block type ships with concrete5 by checking to see if it's in the concrete/blocks/ directory
- * @deprecated
- */
- public function isCoreBlockType() {
- return is_dir(DIR_FILES_BLOCK_TYPES_CORE . '/' . $this->getBlockTypeHandle());
- }
- /**
- * Determines if the block type has templates available
- * @return boolean
- */
- public function hasAddTemplate() {
- $bv = new BlockView();
- $bv->setBlockObject($this);
- $path = $bv->getBlockPath(FILENAME_BLOCK_ADD);
- if (file_exists($path . '/' . FILENAME_BLOCK_ADD)) {
- return true;
- }
- return false;
- }
-
-
- /**
- * returns the width in pixels that the block type's editing dialog will open in
- * @return int
- */
- public function getBlockTypeInterfaceWidth() {return $this->btInterfaceWidth;}
-
- /**
- * returns the height in pixels that the block type's editing dialog will open in
- * @return int
- */
- public function getBlockTypeInterfaceHeight() {return $this->btInterfaceHeight;}
-
- /**
- * returns the id of the BlockType's package if it's in a package
- * @return int
- */
- public function getPackageID() {return $this->pkgID;}
-
- /**
- * returns the handle of the BlockType's package if it's in a package
- * @return string
- */
- public function getPackageHandle() {
- return PackageList::getHandle($this->pkgID);
- }
-
-
- /**
- * determines if a user or group can add a block of the current BlockType
- * @param UserInfo|Group $obj
- * @return boolean
- */
- public function canAddBlock($obj) {
- switch(strtolower(get_class($obj))) {
- case 'group':
- return in_array($obj->getGroupID(), $this->addBTGArray);
- break;
- case 'userinfo':
- return in_array($obj->getUserID(), $this->addBTUArray);
- break;
- }
- }
-
- /**
- * Returns the number of unique instances of this block throughout the entire site
- * note - this count could include blocks in areas that are no longer rendered by the theme
- * @param boolean specify true if you only want to see the number of blocks in active pages
- * @return int
- */
- public function getCount($ignoreUnapprovedVersions = false) {
- $db = Loader::db();
- if ($ignoreUnapprovedVersions) {
- $count = $db->GetOne("SELECT count(btID) FROM Blocks b
- WHERE btID=?
- AND EXISTS (
- SELECT 1 FROM CollectionVersionBlocks cvb
- INNER JOIN CollectionVersions cv ON cv.cID=cvb.cID AND cv.cvID=cvb.cvID
- WHERE b.bID=cvb.bID AND cv.cvIsApproved=1
- )", array($this->btID));
- }
- else {
- $count = $db->GetOne("SELECT count(btID) FROM Blocks WHERE btID = ?", array($this->btID));
- }
- return $count;
- }
-
- /**
- * Not a permissions call. Actually checks to see whether this block is not an internal one.
- * @return boolean
- */
- public function canUnInstall() {
- /*$cnt = $this->getCount();
- if ($cnt > 0 || $this->isBlockTypeInternal()) {
- return false;
- }*/
-
- return (!$this->isBlockTypeInternal());
- }
-
- /**
- * gets the BlockTypes description text
- * @return string
- */
- function getBlockTypeDescription() {
- return $this->btDescription;
- }
-
- /**
- * Gets the custom templates available for the current BlockType
- * @return array an array of strings
- */
- function getBlockTypeCustomTemplates() {
- $btHandle = $this->getBlockTypeHandle();
- $pkgHandle = $this->getPackageHandle();
- $templates = array();
- $fh = Loader::helper('file');
-
- if (file_exists(DIR_FILES_BLOCK_TYPES . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES)) {
- $templates = array_merge($templates, $fh->getDirectoryContents(DIR_FILES_BLOCK_TYPES . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES));
- }
-
- /*
- if ($pkgHandle != null) {
- if (is_dir(DIR_PACKAGES . '/' . $pkgHandle)) {
- $templates = array_merge($templates, $fh->getDirectoryContents(DIR_PACKAGES . "/{$pkgHandle}/" . DIRNAME_BLOCKS . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES));
- } else {
- $templates = array_merge($templates, $fh->getDirectoryContents(DIR_PACKAGES_CORE . "/{$pkgHandle}/" . DIRNAME_BLOCKS . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES));
- }
- }
- */
-
- // NOW, we check to see if this btHandle has any custom templates that have been installed as separate packages
- $pl = PackageList::get();
- $packages = $pl->getPackages();
- foreach($packages as $pkg) {
- $d = (is_dir(DIR_PACKAGES . '/' . $pkg->getPackageHandle())) ? DIR_PACKAGES . '/'. $pkg->getPackageHandle() : DIR_PACKAGES_CORE . '/'. $pkg->getPackageHandle();
- if (is_dir($d . '/' . DIRNAME_BLOCKS . '/' . $btHandle . '/' . DIRNAME_BLOCK_TEMPLATES)) {
- $templates = array_merge($templates, $fh->getDirectoryContents($d . '/' . DIRNAME_BLOCKS . '/' . $btHandle . '/' . DIRNAME_BLOCK_TEMPLATES));
- }
- }
-
- if (file_exists(DIR_FILES_BLOCK_TYPES_CORE . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES)) {
- $templates = array_merge($templates, $fh->getDirectoryContents(DIR_FILES_BLOCK_TYPES_CORE . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES));
- }
- $templates = array_unique($templates);
-
- return $templates;
- }
-
- /**
- * gets the available composer templates
- * used for editing instances of the BlockType while in the composer ui in the dashboard
- * @return array array of strings
- */
- function getBlockTypeComposerTemplates() {
- $btHandle = $this->getBlockTypeHandle();
- $pkgHandle = $this->getPackageHandle();
- $templates = array();
- $fh = Loader::helper('file');
-
- if (file_exists(DIR_FILES_BLOCK_TYPES . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES_COMPOSER)) {
- $templates = array_merge($templates, $fh->getDirectoryContents(DIR_FILES_BLOCK_TYPES . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES_COMPOSER));
- }
- if (file_exists(DIR_FILES_BLOCK_TYPES_CORE . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES_COMPOSER)) {
- $templates = array_merge($templates, $fh->getDirectoryContents(DIR_FILES_BLOCK_TYPES_CORE . "/{$btHandle}/" . DIRNAME_BLOCK_TEMPLATES_COMPOSER));
- }
- $templates = array_unique($templates);
-
- return $templates;
- }
-
- function setBlockTypeDisplayOrder($displayOrder) {
- $db = Loader::db();
-
- $displayOrder = intval($displayOrder); //in case displayOrder came from a string (so ADODB escapes it properly)
-
- $sql = "UPDATE BlockTypes SET btDisplayOrder = btDisplayOrder - 1 WHERE btDisplayOrder > ?";
- $vals = array($this->btDisplayOrder);
- $db->Execute($sql, $vals);
-
- $sql = "UPDATE BlockTypes SET btDisplayOrder = btDisplayOrder + 1 WHERE btDisplayOrder >= ?";
- $vals = array($displayOrder);
- $db->Execute($sql, $vals);
-
- $sql = "UPDATE BlockTypes SET btDisplayOrder = ? WHERE btID = ?";
- $vals = array($displayOrder, $this->btID);
- $db->Execute($sql, $vals);
-
- // now we remove the block type from cache
- $ca = new Cache();
- $ca->delete('blockTypeByID', $this->btID);
- $ca->delete('blockTypeByHandle', $this->btHandle);
- $ca->delete('blockTypeList', false);
- }
- /**
- * installs a new BlockType from a package,
- * typicaly called from a package controller's install() method durring package installation
- * @todo Documentation how is the btID used, if you want to reserve/specify a btID??
- * @param string $btHandle the block Type's handle
- * @param Package $pkg
- * @param int $btID if it's an existing block type
- * @return void|string error message
- */
- public function installBlockTypeFromPackage($btHandle, $pkg, $btID = 0) {
- $dir1 = DIR_PACKAGES . '/' . $pkg->getPackageHandle() . '/' . DIRNAME_BLOCKS;
- $dir2 = DIR_PACKAGES_CORE . '/' . $pkg->getPackageHandle() . '/' . DIRNAME_BLOCKS;
-
- if (file_exists($dir1)) {
- $dir = $dir1;
- $dirDbXml = $dir;
- } else {
- $dir = $dir2;
- $dirDbXml = $dir;
- }
- // now we check to see if it's been overridden in the site root and if so we do it there
- if ($btID > 0) {
- // this is only necessary when it's an existing refresh
- if (file_exists(DIR_FILES_BLOCK_TYPES . '/' . $btHandle . '/' . FILENAME_BLOCK_CONTROLLER)) {
- $dir = DIR_FILES_BLOCK_TYPES;
- }
- if (file_exists(DIR_FILES_BLOCK_TYPES . '/' . $btHandle . '/' . FILENAME_BLOCK_DB)) {
- $dirDbXml = DIR_FILES_BLOCK_TYPES;
- }
- }
-
- $bt = new BlockType;
- $bt->btHandle = $btHandle;
- $bt->pkgHandle = $pkg->getPackageHandle();
- $bt->pkgID = $pkg->getPackageID();
- return BlockType::doInstallBlockType($btHandle, $bt, $dir, $btID, $dirDbXml);
- }
-
- /**
- * refreshes the BlockType's database schema throws an Exception if error
- * @return void
- */
- public function refresh() {
- if ($this->getPackageID() > 0) {
- $pkg = Package::getByID($this->getPackageID());
- $resp = BlockType::installBlockTypeFromPackage($this->getBlockTypeHandle(), $pkg, $this->getBlockTypeID());
- if ($resp != '') {
- throw new Exception($resp);
- }
- } else {
- $resp = BlockType::installBlockType($this->getBlockTypeHandle(), $this->getBlockTypeID());
- if ($resp != '') {
- throw new Exception($resp);
- }
- }
- }
-
- /**
- * installs a core or root level BlockType (from /blocks or /concrete/blocks, not a package)
- * should likely be a static method
- * @param string $btHandle
- * @param int $btID btID if it's an existing block type
- */
- public function installBlockType($btHandle, $btID = 0) {
-
- if ($btID == 0) {
- // then we don't allow one to already exist
- $db = Loader::db();
- $cnt = $db->GetOne("select btID from BlockTypes where btHandle = ?", array($btHandle));
- if ($cnt > 0) {
- return false;
- }
- }
-
- if (file_exists(DIR_FILES_BLOCK_TYPES . '/' . $btHandle . '/' . FILENAME_BLOCK_CONTROLLER)) {
- $dir = DIR_FILES_BLOCK_TYPES;
- } else {
- $dir = DIR_FILES_BLOCK_TYPES_CORE;
- }
- if (file_exists(DIR_FILES_BLOCK_TYPES . '/' . $btHandle . '/' . FILENAME_BLOCK_DB)) {
- $dirDbXml = DIR_FILES_BLOCK_TYPES;
- } else {
- $dirDbXml = DIR_FILES_BLOCK_TYPES_CORE;
- }
-
- $bt = new BlockType;
- $bt->btHandle = $btHandle;
- $bt->pkgHandle = null;
- $bt->pkgID = 0;
- return BlockType::doInstallBlockType($btHandle, $bt, $dir, $btID, $dirDbXml);
- }
-
- /**
- * Renders a particular view of a block type, using the public $controller variable as the block type's controller
- * @param string template 'view' for the default
- * @return void
- */
- public function render($view = 'view') {
- $bv = new BlockView();
- $bv->setController($this->controller);
- $bv->render($this, $view);
- }
-
- /**
- * get's the block type controller
- * @return BlockTypeController
- */
- public function getController() {
- return $this->controller;
- }
-
- /**
- * installs a block type
- * @param string $btHandle
- * @param BlockType $bt
- * @param string $dir
- * @param int $btID
- * @param string $dirDbXml
- */
- protected function doInstallBlockType($btHandle, $bt, $dir, $btID = 0, $dirDbXml) {
- $db = Loader::db();
- $env = Environment::get();
- $env->clearOverrideCache();
-
- if (file_exists($dir . '/' . $btHandle . '/' . FILENAME_BLOCK_CONTROLLER)) {
- $class = $bt->getBlockTypeClass();
-
- $path = $dirDbXml . '/' . $btHandle;
- if (!class_exists($class)) {
- require_once($dir . '/' . $btHandle . '/' . FILENAME_BLOCK_CONTROLLER);
- }
-
- if (!class_exists($class)) {
- throw new Exception(t("%s not found. Please check that the block controller file contains the correct class name.", $class));
- }
- $bta = new $class;
-
- //Attempt to run the subclass methods (install schema from db.xml, etc.)
- $r = $bta->install($path);
- //Validate
- if ($r === false) {
- return t('Error: Block Type cannot be installed because no db.xml file can be found. Either create a db.xml file for this block type, or remove the $btTable variable from its controller.');
- } else if (!$r->result && $r->message) {
- return $r->message;
- } else if (!$r->result && !$r->message) {
- return t('Error: Block Type cannot be installed due to an unknown database error. Please check that the db.xml file for this block type is formatted correctly.');
- } else if ($message = BlockType::validateInstalledDatabaseTable($bta->getBlockTypeDatabaseTable())) {
- $db->Execute('DROP TABLE IF EXISTS ' . $bta->getBlockTypeDatabaseTable());
- return $message;
- }
-
- $currentLocale = Localization::activeLocale();
- if ($currentLocale != 'en_US') {
- // Prevent the database records being stored in wrong language
- Localization::changeLocale('en_US');
- }
- //Install the block
- $btd = new BlockTypeDB();
- $btd->btHandle = $btHandle;
- $btd->btName = $bta->getBlockTypeName();
- $btd->btDescription = $bta->getBlockTypeDescription();
- $btd->btActiveWhenAdded = $bta->isActiveWhenAdded();
- $btd->btCopyWhenPropagate = $bta->isCopiedWhenPropagated();
- $btd->btIncludeAll = $bta->includeAll();
- $btd->btIsInternal = $bta->isBlockTypeInternal();
- $btd->btInterfaceHeight = $bta->getInterfaceHeight();
- $btd->btInterfaceWidth = $bta->getInterfaceWidth();
- $btd->pkgID = $bt->getPackageID();
- if ($currentLocale != 'en_US') {
- Localization::changeLocale($currentLocale);
- }
-
- if ($btID > 0) {
- $btd->btID = $btID;
- $btDisplayOrder = $db->GetOne('select btDisplayOrder from BlockTypes where btID = ?', array($btID));
- if (!$btDisplayOrder) {
- $btDisplayOrder = 0;
- }
- $btd->btDisplayOrder = $btDisplayOrder;
- $r = $btd->Replace();
- } else {
- if ($bta->isBlockTypeInternal()) {
- $btd->btDisplayOrder = 0;
- } else {
- $btMax = $db->GetOne('select max(btDisplayOrder) from BlockTypes');
- if ($btMax < 1 && $btMax !== '0') {
- $btd->btDisplayOrder = 0;
- } else {
- $btd->btDisplayOrder = $btMax + 1;
- }
- }
- $r = $btd->save();
- }
-
- // now we remove the block type from cache
- $ca = new Cache();
- $ca->delete('blockTypeByID', $btID);
- $ca->delete('blockTypeByHandle', $btHandle);
- $ca->delete('blockTypeList', false);
- if (!$r) {
- return $db->ErrorMsg();
- }
- } else {
- return t("No block found with the handle %s.", $btHandle);
- }
- }
-
- /**
- * Internal helper function for doInstallBlockType().
- *
- * Checks if the database table with the given name
- * has at least 2 fields and one of those is called "btID".
- *
- * If valid, we return an empty string.
- * If not valid, we return an error message.
- * If passed an empty string, we return an empty string.
- */
- private function validateInstalledDatabaseTable($btTable) {
- $message = '';
- if (!empty($btTable)) {
- $fields = Loader::db()->MetaColumnNames($btTable);
- if (count($fields) < 2) {
- $message = t('Error: Block Type table must contain at least two fields.');
- } else if (!in_array('bID', $fields)) {
- $message = t('Error: Block Type table must contain a "bID" primary key field.');
- }
- }
- return $message;
- }
-
- /*
- * Returns a path to where the block type's files are located.
- * @access public
- * @return string $path
- */
- public function getBlockTypePath() {
- if ($this->getPackageID() > 0) {
- $pkgHandle = $this->getPackageHandle();
- $dirp = (is_dir(DIR_PACKAGES . '/' . $pkgHandle)) ? DIR_PACKAGES : DIR_PACKAGES_CORE;
- $dir = $dirp . '/' . $pkgHandle . '/' . DIRNAME_BLOCKS . '/' . $this->getBlockTypeHandle();
- } else {
- if (is_dir(DIR_FILES_BLOCK_TYPES . '/' . $this->getBlockTypeHandle())) {
- $dir = DIR_FILES_BLOCK_TYPES . '/' . $this->getBlockTypeHandle();
- } else {
- $dir = DIR_FILES_BLOCK_TYPES_CORE . '/' . $this->getBlockTypeHandle();
- }
- }
- return $dir;
- }
-
- /** @todo Continue documenting from here down **/
-
-
- /*
- * @access private
- *
- */
- protected function _getClass() {
- $btHandle = $this->btHandle;
- $pkgHandle = $this->getPackageHandle();
- $env = Environment::get();
- require_once($env->getPath(DIRNAME_BLOCKS . '/' . $this->btHandle . '/' . FILENAME_BLOCK_CONTROLLER, $pkgHandle));
-
- // takes the handle and performs some magic to get the class;
- $btHandle = $this->getBlockTypeHandle();
- // split by underscores or dashes
- $words = preg_split('/\_|\-/', $btHandle);
- for ($i = 0; $i < count($words); $i++) {
- $words[$i] = ucfirst($words[$i]);
- }
-
- $class = implode('', $words);
- $class = $class . 'BlockController';
- return $class;
- }
-
- public function inc($file, $args = array()) {
- extract($args);
- $bt = $this;
- global $c;
- global $a;
- $env = Environment::get();
- include($env->getPath(DIRNAME_BLOCKS . '/' . $this->getBlockTypeHandle() . '/' . $file, $this->getPackageHandle()));
- }
-
- public function getBlockTypeClass() {
- return $this->_getClass();
- }
-
- /**
- * Deprecated -- use getBlockTypeClass() instead.
- */
- public function getBlockTypeClassFromHandle() {
- return $this->getBlockTypeClass();
- }
-
- /**
- * Removes the block type. Also removes instances of content.
- */
- public function delete() {
- $db = Loader::db();
- $r = $db->Execute('select cID, cvID, b.bID, arHandle from CollectionVersionBlocks cvb inner join Blocks b on b.bID = cvb.bID where btID = ?', array($this->getBlockTypeID()));
- while ($row = $r->FetchRow()) {
- $nc = Page::getByID($row['cID'], $row['cvID']);
- $b = Block::getByID($row['bID'], $nc, $row['arHandle']);
- if (is_object($b)) {
- $b->deleteBlock();
- }
- }
-
- $ca = new Cache();
- $ca->delete('blockTypeByID', $this->btID);
- $ca->delete('blockTypeByHandle', $this->btHandle);
- $ca->delete('blockTypeList', false);
- $db->Execute("delete from BlockTypes where btID = ?", array($this->btID));
-
- //Remove gaps in display order numbering (to avoid future sorting errors)
- BlockTypeList::resetBlockTypeDisplayOrder('btDisplayOrder');
- }
-
- /**
- * Allows block types to be updated
- * @param array $data
- */
-
- public function update($data) {
- $db = Loader::db();
- $btHandle = $this->btHandle;
- $btName = $this->btName;
- $btDescription = $this->btDescription;
- if (isset($data['btHandle'])) {
- $btHandle = $data['btHandle'];
- }
- if (isset($data['btName'])) {
- $btName = $data['btName'];
- }
- if (isset($data['btDescription'])) {
- $btDescription = $data['btDescription'];
- }
- $db->Execute('update BlockTypes set btHandle = ?, btName = ?, btDescription = ? where btID = ?', array($btHandle, $btName, $btDescription, $this->btID));
- // now we remove the block type from cache
- $ca = new Cache();
- $ca->delete('blockTypeByID', $this->btID);
- $ca->delete('blockTypeByHandle', $btHandle);
- $ca->delete('blockTypeList', false);
- }
-
-
- /*
- * Adds a block to the system without adding it to a collection.
- * Passes page and area data along if it is available, however.
- */
- public function add($data, $c = false, $a = false) {
- $db = Loader::db();
-
- $u = new User();
- if (isset($data['uID'])) {
- $uID = $data['uID'];
- } else {
- $uID = $u->getUserID();
- }
- $btID = $this->btID;
- $dh = Loader::helper('date');
- $bDate = $dh->getSystemDateTime();
- $bIsActive = ($this->btActiveWhenAdded == 1) ? 1 : 0;
-
- $v = array($_POST['bName'], $bDate, $bDate, $bIsActive, $btID, $uID);
- $q = "insert into Blocks (bName, bDateAdded, bDateModified, bIsActive, btID, uID) values (?, ?, ?, ?, ?, ?)";
-
- $r = $db->prepare($q);
- $res = $db->execute($r, $v);
- $bIDnew = $db->Insert_ID();
- // we get the block object for the block we just added
- if ($res) {
- $nb = Block::getByID($bIDnew);
-
- $btHandle = $this->getBlockTypeHandle();
-
- $class = $this->getBlockTypeClass();
- $bc = new $class($nb);
- if (is_object($c)) {
- $bc->setCollectionObject($c);
- }
- $bc->save($data);
-
- // the previous version of the block above is cached without the values
- $nb->refreshCache();
-
- return Block::getByID($bIDnew);
-
- }
-
- }
-
- function getBlockTypeID() {
- return $this->btID;
- }
-
- function getBlockTypeHandle() {
- return $this->btHandle;
- }
-
- // getBlockAddAction vs. getBlockTypeAddAction() - The difference is very simple. We call getBlockTypeAddAction() to grab the
- // action properties for the form that presents the drop-down select menu for selecting which type of block to add. We call the other
- // function when we've already chosen a type to add, and we're interested in actually adding the block - content completed - to the database
-
- function getBlockAddAction(&$a, $alternateHandler = null) {
- // Note: This is fugly, since we're just grabbing query string variables, but oh well. Not _everything_ can be object oriented
- $btID = $this->btID;
- $step = ($_REQUEST['step']) ? '&step=' . $_REQUEST['step'] : '';
- $c = $a->getAreaCollectionObject();
- $cID = $c->getCollectionID();
- $arHandle = urlencode($a->getAreaHandle());
- $valt = Loader::helper('validation/token');
-
-
- if ($alternateHandler) {
- $str = $alternateHandler . "?cID={$cID}&arHandle={$arHandle}&btID={$btID}&mode=edit" . $step . '&' . $valt->getParameter();
- } else {
- $str = DIR_REL . "/" . DISPATCHER_FILENAME . "?cID={$cID}&arHandle={$arHandle}&btID={$btID}&mode=edit" . $step . '&' . $valt->getParameter();
- }
- return $str;
- }
-
-
- function getBlockTypeName() {
- return $this->btName;
- }
-
- function isInstalled() {
- return $this->installed;
- }
-
- function getBlockTypeActiveWhenAdded() {
- return $this->btActiveWhenAdded;
- }
-
- function isCopiedWhenPropagated() {
- return $this->btCopyWhenPropagate;
- }
- function includeAll() {
- return $this->btIncludeAll;
- }
-
- function hasCustomEditTemplate() {
- return $this->hasCustomEditTemplate;
- }
-
- function hasCustomViewTemplate() {
- return $this->hasCustomViewTemplate;
- }
-
- function hasCustomAddTemplate() {
- return $this->hasCustomAddTemplate;
- }
- }