/ */ class Setup_Form_Site extends P4Cms_Form { protected $_connection; /** * Defines the elements that make up the site form. * Called automatically when the form object is created. */ public function init() { // form should use p4cms-ui styles. $this->setAttrib('class', 'p4cms-ui site-form'); // form should submit on enter $this->setAttrib('submitOnEnter', true); // set the method for the display form to POST $this->setMethod('post'); // add a hidden id field, this will be auto-populated based on title $this->addElement( 'hidden', 'id', array( 'disabled' => true ) ); // add a field to collect the site title. $this->addElement( 'text', 'title', array( 'label' => 'Title', 'value' => static::getRequestHost(), 'required' => true, 'description' => "Enter a recognizable title for this site.", 'filters' => array('StringTrim') ) ); // add a field to collect the site's description. $this->addElement( 'textarea', 'description', array( 'label' => 'Description', 'value' => '', 'required' => false, 'rows' => 2, 'cols' => 50, 'description' => "Enter a short summary of your site.
" . "This summary will appear in meta description tags for non-content pages." ) ); $this->getElement('description') ->getDecorator('Description') ->setEscape(false); // add a field to collect the site's urls. $this->addElement( 'textarea', 'urls', array( 'label' => 'Site Address', 'value' => $this->_getDefaultUrls(), 'required' => true, 'rows' => 3, 'cols' => 50, 'description' => "Provide a list of urls for which this site will be served.
" . "For example: domain.com, www.domain.com" ) ); $this->getElement('urls') ->getDecorator('Description') ->setEscape(false); // add the submit button $this->addElement( 'SubmitButton', 'create', array( 'label' => 'Create Site', 'class' => 'button-large preferred', 'ignore' => true ) ); $this->addElement( 'SubmitButton', 'goback', array( 'label' => 'Go Back', 'class' => 'button-large', 'ignore' => true ) ); // put the button in a fieldset. $this->addDisplayGroup( array('create', 'goback'), 'buttons', array('class' => 'buttons') ); } /** * Override isValid to check that site title is unique. * * @param array $data the field values to validate. * @return boolean true if the form values are valid. */ public function isValid($data) { // always set id from title $title = isset($data['title']) ? $data['title'] : null; $data['id'] = $this->_composeSiteId($title); if (!parent::isValid($data)) { return false; } $valid = true; // if individual values are valid, ensure that site title/id is unique. if ($this->_isSiteIdTaken($this->getValue('id'))) { $this->getElement('title')->addError( "The site title you provided appears to be taken. Please choose a different title." ); $valid = false; } // ensure that site addresses are not in use $urls = array_map('trim', preg_split("/\n|,/", $this->getValue('urls'))); foreach ($urls as $url) { if ($this->_isSiteAddressTaken($url)) { $this->getElement('urls')->addError( "The site address '$url' you provided appears to be taken. Please choose a different address." ); $valid = false; break; } } return $valid; } /** * Set element values. * * Extended here to set the site id from the site title, if a * title is present in the given defaults array. * * @param P4Cms_Record|array $defaults the default values to set on elements * @return Zend_Form provides fluent interface */ public function setDefaults($defaults) { // always set id from title if title is present if (array_key_exists('title', $defaults)) { $defaults['id'] = $this->_composeSiteId($defaults['title']); } return parent::setDefaults($defaults); } /** * Set the target server connection to use. * * @param P4_Connection_Interface $connection a connection to the server we * intend to create the site in. */ public function setConnection(P4_Connection_Interface $connection = null) { $this->_connection = $connection; } /** * Get the current host name. * * @param boolean $removePort If true, removes the port from the host. * @return false|string the current http host - false if unable to determine the host. */ public static function getRequestHost($removePort = true) { $request = Zend_Controller_Front::getInstance()->getRequest(); if (!$request instanceof Zend_Controller_Request_Http) { return false; } $host = $request->getHttpHost(); if (!$removePort) { return $host; } if (preg_match('#:\d+$#', $host, $result) === 1) { $host = substr($host, 0, -strlen($result[0])); } return $host; } /** * Get the default value for the site urls field. * Defaults to current address with and without 'www' prefix. * * @return false|string the default site urls - false if unable to get current address. */ protected function _getDefaultUrls() { $request = Zend_Controller_Front::getInstance()->getRequest(); if (!$request instanceof Zend_Controller_Request_Http) { return false; } // set default to current address with and without www. // skipping the www prefixed version if we have more/less // than a single period in the hostname (e.g. IP address, // sub-domain, localhost, etc.) $default = static::getRequestHost(false) . $request->getBaseUrl(); if (substr($default, 0, 4) == 'www.') { $default .= "\n" . substr($default, 4); } else if (substr_count($default, '.') == 1) { $default .= "\n" . "www." . $default; } return $default; } /** * Check if the given site id is already in use. * * @param string $id the id of the site to check for. * @return bool true if the id is taken. */ protected function _isSiteIdTaken($id) { // check for conflicting site packages folder. if (is_dir(P4Cms_Site::getSitesPackagesPath($id))) { return true; } // check for conflicting site data directory. if (is_dir(P4Cms_Site::getSitesDataPath($id))) { return true; } // if no connection, can't check perforce for conflicts. // (server type must be 'new' or a connection would have been set) if (!$this->_connection) { return false; } $p4 = $this->_connection; // check for depot name conflict - site ids relate 1:1 with depot names if (P4_Depot::exists($id, $p4)) { return true; } // check for site 'umbrella' group name conflict. // as with depots, site ids relate 1:1 with their parent group. if (P4_Group::exists($id, $p4)) { return true; } // check if any group with prefix exists. $groupPrefix = $id . P4Cms_Acl_Role::PREFIX_DELIMITER; foreach (P4_Group::fetchAll(array(), $p4) as $group) { if (strpos($group->getId(), $groupPrefix) === 0) { return true; } } // appears to be unique. return false; } /** * Check if the given site address is already in use. * * @param string $url the address of the site to check for * @return boolean true, if the site address is used by any existing sites * false, otherwise */ protected function _isSiteAddressTaken($url) { // if no connection, can't check perforce for conflicts. // (server type must be 'new' or a connection would have been set) if (!$this->_connection) { return false; } $sites = P4Cms_Site::fetchAll(null, $this->_connection); // collect urls from all sites $urls = array(); foreach ($sites as $site) { $urls = array_merge($urls, $site->getConfig()->getUrls()); } return in_array($url, $urls); } /** * Generate a site id from a given site title. * * Replaces non-alphanumeric characters with dashes ('-') * and prefixes the site id with the site prefix ('chronicle-'). * * @param string $title the site title to make an id for. * @return string|null the generated site id. */ protected function _composeSiteId($title) { $filter = new P4Cms_Filter_TitleToId; $id = $filter->filter($title); return $id ? P4Cms_Site::SITE_PREFIX . $id : null; } }