public function tearDown()
 {
     $_SERVER['HTTP_HOST'] = $this->oldhost;
     Config::unnest();
     Email::set_mailer(new Mailer());
     parent::tearDown();
 }
 public function tearDown()
 {
     Injector::unnest();
     SS_Datetime::clear_mock_now();
     Config::unnest();
     parent::tearDown();
 }
Example #3
0
 public function testPermissionFailureSetsCorrectFormMessages()
 {
     Config::nest();
     // Controller that doesn't attempt redirections
     $controller = new SecurityTest_NullController();
     $controller->response = new SS_HTTPResponse();
     Security::permissionFailure($controller, array('default' => 'Oops, not allowed'));
     $this->assertEquals('Oops, not allowed', Session::get('Security.Message.message'));
     // Test that config values are used correctly
     Config::inst()->update('Security', 'default_message_set', 'stringvalue');
     Security::permissionFailure($controller);
     $this->assertEquals('stringvalue', Session::get('Security.Message.message'), 'Default permission failure message value was not present');
     Config::inst()->remove('Security', 'default_message_set');
     Config::inst()->update('Security', 'default_message_set', array('default' => 'arrayvalue'));
     Security::permissionFailure($controller);
     $this->assertEquals('arrayvalue', Session::get('Security.Message.message'), 'Default permission failure message value was not present');
     // Test that non-default messages work.
     // NOTE: we inspect the response body here as the session message has already
     // been fetched and output as part of it, so has been removed from the session
     $this->logInWithPermission('EDITOR');
     Config::inst()->update('Security', 'default_message_set', array('default' => 'default', 'alreadyLoggedIn' => 'You are already logged in!'));
     Security::permissionFailure($controller);
     $this->assertContains('You are already logged in!', $controller->response->getBody(), 'Custom permission failure message was ignored');
     Security::permissionFailure($controller, array('default' => 'default', 'alreadyLoggedIn' => 'One-off failure message'));
     $this->assertContains('One-off failure message', $controller->response->getBody(), "Message set passed to Security::permissionFailure() didn't override Config values");
     Config::unnest();
 }
 public function tearDown()
 {
     AssetStoreTest_SpyStore::reset();
     SS_Filesystem::removeFolder($this->getBasePath());
     parent::tearDown();
     Config::unnest();
 }
 public function tearDown()
 {
     while ($this->nestingLevel > 0) {
         $this->nestingLevel--;
         Config::unnest();
     }
     parent::tearDown();
 }
 function getCustomerNote()
 {
     Config::nest();
     Config::inst()->update('SSViewer', 'theme_enabled', true);
     $html = $this->renderWith("LogDispatchPhysicalOrderCustomerNote");
     Config::unnest();
     return $html;
 }
 public function tearDown()
 {
     if ($this->oldProcessor) {
         SearchUpdater::$processor = $this->oldProcessor;
     }
     Config::unnest();
     Injector::inst()->unregisterNamedObject('QueuedJobService');
     FullTextSearch::force_index_list();
     parent::tearDown();
 }
 /**
  * Render the object using SSViewer
  * @return string
  */
 public function forPDF($variables = array())
 {
     Config::nest();
     Config::inst()->update('Director', 'alternate_base_url', static::get_render_host());
     $file = $this->owner->getPDFTemplate();
     $viewer = new SSViewer($file);
     $output = $viewer->process($this->owner, $variables);
     Config::unnest();
     return $output;
 }
 function testCustomGetVar()
 {
     Config::nest();
     Config::inst()->update('MultiForm', 'get_var', 'SuperSessionID');
     $form = $this->controller->Form();
     $this->assertContains('SuperSessionID', $form::$ignored_fields, "GET var wasn't added to ignored fields");
     $this->assertContains('SuperSessionID', $form->FormAction(), "Form action doesn't contain correct session \n\t\t\tID parameter");
     $this->assertContains('SuperSessionID', $form->getCurrentStep()->Link(), "Form step doesn't contain correct \n\t\t\tsession ID parameter");
     Config::unnest();
 }
 public function tearDown()
 {
     if ($this->securityWasEnabled) {
         SecurityToken::enable();
     } else {
         SecurityToken::disable();
     }
     Injector::unnest();
     Config::unnest();
     parent::tearDown();
 }
 public function testTruncatesByMaxLength()
 {
     Config::nest();
     Config::inst()->update('FileTextCache_Database', 'max_content_length', 5);
     $cache = new FileTextCache_Database();
     $file = $this->getMock('File', array('write'));
     $content = '0123456789';
     $cache->save($file, $content);
     $this->assertEquals($cache->load($file), '01234');
     Config::unnest();
 }
 public function testFieldPosition()
 {
     Config::nest();
     Config::inst()->update('MetaTitleExtension', 'InsertBefore', 'MetaDescription');
     $testObject = new MetaTitleExtensionTest_DataObject();
     $fields = $testObject->getCMSFields();
     $descriptionPosition = $fields->fieldPosition('MetaDescription');
     $this->assertEquals($descriptionPosition - 1, $fields->fieldPosition('MetaTitle'));
     Config::inst()->update('MetaTitleExtension', 'InsertBefore', 'URLSegment');
     $fields = $testObject->getCMSFields();
     $urlSegmentPosition = $fields->fieldPosition('URLSegment');
     $this->assertEquals($urlSegmentPosition - 1, $fields->fieldPosition('MetaTitle'));
     Config::unnest();
 }
 function getTableTitle()
 {
     $tableTitle = _t("Product.UNKNOWN", "Unknown Product");
     if ($product = $this->Product()) {
         Config::nest();
         Config::inst()->update('SSViewer', 'theme_enabled', true);
         $tableTitle = strip_tags($product->renderWith("ProductTableTitle"));
         Config::unnest();
     }
     $updatedTableTitle = $this->extend('updateTableTitle', $tableTitle);
     if ($updatedTableTitle !== null && is_array($updatedTableTitle) && count($updatedTableTitle)) {
         $tableTitle = implode($updatedTableTitle);
     }
     return $tableTitle;
 }
 public function testDefaultClasses()
 {
     Config::nest();
     Config::inst()->update('FormField', 'default_classes', array('class1'));
     $field = new FormField('MyField');
     $this->assertContains('class1', $field->extraClass(), 'Class list does not contain expected class');
     Config::inst()->update('FormField', 'default_classes', array('class1', 'class2'));
     $field = new FormField('MyField');
     $this->assertContains('class1 class2', $field->extraClass(), 'Class list does not contain expected class');
     Config::inst()->update('FormField', 'default_classes', array('class3'));
     $field = new FormField('MyField');
     $this->assertContains('class3', $field->extraClass(), 'Class list does not contain expected class');
     $field->removeExtraClass('class3');
     $this->assertNotContains('class3', $field->extraClass(), 'Class list contains unexpected class');
     Config::inst()->update('TextField', 'default_classes', array('textfield-class'));
     $field = new TextField('MyField');
     //check default classes inherit
     $this->assertContains('class3', $field->extraClass(), 'Class list does not contain inherited class');
     $this->assertContains('textfield-class', $field->extraClass(), 'Class list does not contain expected class');
     Config::unnest();
 }
 /**
  * @param string $identifier Unique identifier for this fixture type
  * @param array $data Map of property names to their values.
  * @param array $fixtures Map of fixture names to an associative array of their in-memory
  *                        identifiers mapped to their database IDs. Used to look up
  *                        existing fixtures which might be referenced in the $data attribute
  *                        via the => notation.
  * @return DataObject
  * @throws Exception
  */
 public function createObject($identifier, $data = null, $fixtures = null)
 {
     // We have to disable validation while we import the fixtures, as the order in
     // which they are imported doesnt guarantee valid relations until after the import is complete.
     // Also disable filesystem manipulations
     Config::nest();
     Config::inst()->update('SilverStripe\\ORM\\DataObject', 'validation_enabled', false);
     Config::inst()->update('File', 'update_filesystem', false);
     $this->invokeCallbacks('beforeCreate', array($identifier, &$data, &$fixtures));
     try {
         $class = $this->class;
         $obj = DataModel::inst()->{$class}->newObject();
         // If an ID is explicitly passed, then we'll sort out the initial write straight away
         // This is just in case field setters triggered by the population code in the next block
         // Call $this->write().  (For example, in FileTest)
         if (isset($data['ID'])) {
             $obj->ID = $data['ID'];
             // The database needs to allow inserting values into the foreign key column (ID in our case)
             $conn = DB::get_conn();
             $baseTable = DataObject::getSchema()->baseDataTable($class);
             if (method_exists($conn, 'allowPrimaryKeyEditing')) {
                 $conn->allowPrimaryKeyEditing($baseTable, true);
             }
             $obj->write(false, true);
             if (method_exists($conn, 'allowPrimaryKeyEditing')) {
                 $conn->allowPrimaryKeyEditing($baseTable, false);
             }
         }
         // Populate defaults
         if ($this->defaults) {
             foreach ($this->defaults as $fieldName => $fieldVal) {
                 if (isset($data[$fieldName]) && $data[$fieldName] !== false) {
                     continue;
                 }
                 if (is_callable($fieldVal)) {
                     $obj->{$fieldName} = $fieldVal($obj, $data, $fixtures);
                 } else {
                     $obj->{$fieldName} = $fieldVal;
                 }
             }
         }
         // Populate overrides
         if ($data) {
             foreach ($data as $fieldName => $fieldVal) {
                 // Defer relationship processing
                 if ($obj->manyManyComponent($fieldName) || $obj->hasManyComponent($fieldName) || $obj->hasOneComponent($fieldName)) {
                     continue;
                 }
                 $this->setValue($obj, $fieldName, $fieldVal, $fixtures);
             }
         }
         $obj->write();
         // Save to fixture before relationship processing in case of reflexive relationships
         if (!isset($fixtures[$class])) {
             $fixtures[$class] = array();
         }
         $fixtures[$class][$identifier] = $obj->ID;
         // Populate all relations
         if ($data) {
             foreach ($data as $fieldName => $fieldVal) {
                 if ($obj->manyManyComponent($fieldName) || $obj->hasManyComponent($fieldName)) {
                     $obj->write();
                     $parsedItems = array();
                     if (is_array($fieldVal)) {
                         // handle lists of many_many relations. Each item can
                         // specify the many_many_extraFields against each
                         // related item.
                         foreach ($fieldVal as $relVal) {
                             $item = key($relVal);
                             $id = $this->parseValue($item, $fixtures);
                             $parsedItems[] = $id;
                             array_shift($relVal);
                             $obj->getManyManyComponents($fieldName)->add($id, $relVal);
                         }
                     } else {
                         $items = preg_split('/ *, */', trim($fieldVal));
                         foreach ($items as $item) {
                             // Check for correct format: =><relationname>.<identifier>.
                             // Ignore if the item has already been replaced with a numeric DB identifier
                             if (!is_numeric($item) && !preg_match('/^=>[^\\.]+\\.[^\\.]+/', $item)) {
                                 throw new InvalidArgumentException(sprintf('Invalid format for relation "%s" on class "%s" ("%s")', $fieldName, $class, $item));
                             }
                             $parsedItems[] = $this->parseValue($item, $fixtures);
                         }
                         if ($obj->hasManyComponent($fieldName)) {
                             $obj->getComponents($fieldName)->setByIDList($parsedItems);
                         } elseif ($obj->manyManyComponent($fieldName)) {
                             $obj->getManyManyComponents($fieldName)->setByIDList($parsedItems);
                         }
                     }
                 } else {
                     $hasOneField = preg_replace('/ID$/', '', $fieldName);
                     if ($className = $obj->hasOneComponent($hasOneField)) {
                         $obj->{$hasOneField . 'ID'} = $this->parseValue($fieldVal, $fixtures, $fieldClass);
                         // Inject class for polymorphic relation
                         if ($className === 'SilverStripe\\ORM\\DataObject') {
                             $obj->{$hasOneField . 'Class'} = $fieldClass;
                         }
                     }
                 }
             }
         }
         $obj->write();
         // If LastEdited was set in the fixture, set it here
         if ($data && array_key_exists('LastEdited', $data)) {
             $this->overrideField($obj, 'LastEdited', $data['LastEdited'], $fixtures);
         }
     } catch (Exception $e) {
         Config::unnest();
         throw $e;
     }
     Config::unnest();
     $this->invokeCallbacks('afterCreate', array($obj, $identifier, &$data, &$fixtures));
     return $obj;
 }
 public function tearDown()
 {
     parent::tearDown();
     Config::unnest();
 }
 /**
  * Uses {@link Director::test()} to perform in-memory HTTP requests
  * on the passed-in URLs.
  * 
  * @param  array $urls Relative URLs 
  * @return array Result, keyed by URL. Keys: 
  *               - "statuscode": The HTTP status code
  *               - "redirect": A redirect location (if applicable)
  *               - "path": The filesystem path where the cache has been written
  */
 public function publishPages($urls)
 {
     $result = array();
     //nest the config so we can make changes to the config and revert easily
     Config::nest();
     // Do we need to map these?
     // Detect a numerically indexed arrays
     if (is_numeric(join('', array_keys($urls)))) {
         $urls = $this->urlsToPaths($urls);
     }
     // This can be quite memory hungry and time-consuming
     // @todo - Make a more memory efficient publisher
     increase_time_limit_to();
     increase_memory_limit_to();
     // Set the appropriate theme for this publication batch.
     // This may have been set explicitly via StaticPublisher::static_publisher_theme,
     // or we can use the last non-null theme.
     $customTheme = Config::inst()->get('StaticPublisher', 'static_publisher_theme');
     if ($customTheme) {
         Config::inst()->update('SSViewer', 'theme', $customTheme);
     }
     // Ensure that the theme that is set gets used.
     Config::inst()->update('SSViewer', 'theme_enabled', true);
     $staticBaseUrl = Config::inst()->get('FilesystemPublisher', 'static_base_url');
     if ($staticBaseUrl) {
         Config::inst()->update('Director', 'alternate_base_url', $staticBaseUrl);
     }
     if ($this->fileExtension == 'php') {
         Config::inst()->update('SSViewer', 'rewrite_hash_links', 'php');
     }
     if (Config::inst()->get('StaticPublisher', 'echo_progress')) {
         echo $this->class . ": Publishing to " . $staticBaseUrl . "\n";
     }
     $files = array();
     $i = 0;
     $totalURLs = sizeof($urls);
     foreach ($urls as $url => $path) {
         $origUrl = $url;
         $result[$origUrl] = array('statuscode' => null, 'redirect' => null, 'path' => null);
         $i++;
         if ($url && !is_string($url)) {
             user_error("Bad url:" . var_export($url, true), E_USER_WARNING);
             continue;
         }
         if (Config::inst()->get('StaticPublisher', 'echo_progress')) {
             echo " * Publishing page {$i}/{$totalURLs}: {$url}\n";
             flush();
         }
         Requirements::clear();
         if ($url == "") {
             $url = "/";
         }
         if (Director::is_relative_url($url)) {
             $url = Director::absoluteURL($url);
         }
         $response = Director::test(str_replace('+', ' ', $url));
         if (!$response) {
             continue;
         }
         if ($response) {
             $result[$origUrl]['statuscode'] = $response->getStatusCode();
         }
         Requirements::clear();
         singleton('DataObject')->flushCache();
         // Check for ErrorPages generating output - we want to handle this in a special way below.
         $isErrorPage = false;
         $pageObject = null;
         if ($response && is_object($response) && (int) $response->getStatusCode() >= 400) {
             $pageObject = SiteTree::get_by_link($url);
             if ($pageObject && $pageObject instanceof ErrorPage) {
                 $isErrorPage = true;
             }
         }
         // Skip any responses with a 404 status code unless it's the ErrorPage itself.
         if (!$isErrorPage && is_object($response) && $response->getStatusCode() == '404') {
             continue;
         }
         // Generate file content
         // PHP file caching will generate a simple script from a template
         if ($this->fileExtension == 'php') {
             if (is_object($response)) {
                 if ($response->getStatusCode() == '301' || $response->getStatusCode() == '302') {
                     $content = $this->generatePHPCacheRedirection($response->getHeader('Location'));
                 } else {
                     $content = $this->generatePHPCacheFile($response->getBody(), HTTP::get_cache_age(), date('Y-m-d H:i:s'), $response->getHeader('Content-Type'));
                 }
             } else {
                 $content = $this->generatePHPCacheFile($response . '', HTTP::get_cache_age(), date('Y-m-d H:i:s'), $response->getHeader('Content-Type'));
             }
             // HTML file caching generally just creates a simple file
         } else {
             if (is_object($response)) {
                 if ($response->getStatusCode() == '301' || $response->getStatusCode() == '302') {
                     $absoluteURL = Director::absoluteURL($response->getHeader('Location'));
                     $result[$origUrl]['redirect'] = $response->getHeader('Location');
                     $content = "<meta http-equiv=\"refresh\" content=\"2; URL={$absoluteURL}\">";
                 } else {
                     $content = $response->getBody();
                 }
             } else {
                 $content = $response . '';
             }
         }
         if (Config::inst()->get('StaticPublisher', 'include_caching_metadata')) {
             $content = str_replace('</html>', sprintf("</html>\n\n<!-- %s -->", implode(" ", $this->getMetadata($url))), $content);
         }
         if (!$isErrorPage) {
             $files[$origUrl] = array('Content' => $content, 'Folder' => dirname($path) . '/', 'Filename' => basename($path));
         } else {
             // Generate a static version of the error page with a standardised name, so they can be plugged
             // into catch-all webserver statements such as Apache's ErrorDocument.
             $code = (int) $response->getStatusCode();
             $files[$origUrl] = array('Content' => $content, 'Folder' => dirname($path) . '/', 'Filename' => "error-{$code}.html");
         }
     }
     //return config to its previous state
     Config::unnest();
     $base = BASE_PATH . "/{$this->destFolder}";
     foreach ($files as $origUrl => $file) {
         Filesystem::makeFolder("{$base}/{$file['Folder']}");
         $path = "{$base}/{$file['Folder']}{$file['Filename']}";
         $result[$origUrl]['path'] = $path;
         if (isset($file['Content'])) {
             $fh = fopen($path, "w");
             fwrite($fh, $file['Content']);
             fclose($fh);
         } else {
             if (isset($file['Copy'])) {
                 copy($file['Copy'], $path);
             }
         }
     }
     return $result;
 }
 /**
  * Test against a theme.
  *
  * @param $themeBaseDir string - themes directory
  * @param $theme string - theme name
  * @param $callback Closure
  */
 protected function useTestTheme($themeBaseDir, $theme, $callback)
 {
     Config::nest();
     global $project;
     $manifest = new SS_TemplateManifest($themeBaseDir, $project, true, true);
     SS_TemplateLoader::instance()->pushManifest($manifest);
     Config::inst()->update('SSViewer', 'theme', $theme);
     $e = null;
     try {
         $callback();
     } catch (Exception $e) {
         /* NOP for now, just save $e */
     }
     // Remove all the test themes we created
     SS_TemplateLoader::instance()->popManifest();
     Config::unnest();
     if ($e) {
         throw $e;
     }
 }
 public function tearDown()
 {
     Config::unnest();
     Injector::unnest();
     parent::tearDown();
 }
Example #20
0
 public function testDefaultClasses()
 {
     Config::nest();
     Config::inst()->update('Form', 'default_classes', array('class1'));
     $form = $this->getStubForm();
     $this->assertContains('class1', $form->extraClass(), 'Class list does not contain expected class');
     Config::inst()->update('Form', 'default_classes', array('class1', 'class2'));
     $form = $this->getStubForm();
     $this->assertContains('class1 class2', $form->extraClass(), 'Class list does not contain expected class');
     Config::inst()->update('Form', 'default_classes', array('class3'));
     $form = $this->getStubForm();
     $this->assertContains('class3', $form->extraClass(), 'Class list does not contain expected class');
     $form->removeExtraClass('class3');
     $this->assertNotContains('class3', $form->extraClass(), 'Class list contains unexpected class');
     Config::unnest();
 }
Example #21
0
 public function testShortCodeParsedInTemplateHelpers()
 {
     $parser = ShortcodeParser::get('HTMLTextTest');
     $parser->register('shortcode', function ($arguments, $content, $parser, $tagName, $extra) {
         return 'Replaced short code with this. <a href="home">home</a>';
     });
     ShortcodeParser::set_active('HTMLTextTest');
     /** @var HTMLText $field */
     $field = DBField::create_field('HTMLText', '<p>[shortcode]</p>');
     $this->assertEquals('&lt;p&gt;Replaced short code with this. &lt;a href=&quot;home&quot;&gt;home&lt;/a&gt;&lt;/p&gt;', $field->HTMLATT());
     $this->assertEquals('%3Cp%3EReplaced+short+code+with+this.+%3Ca+href%3D%22home%22%3Ehome%3C%2Fa%3E%3C%2Fp%3E', $field->URLATT());
     $this->assertEquals('%3Cp%3EReplaced%20short%20code%20with%20this.%20%3Ca%20href%3D%22home%22%3Ehome%3C%2Fa%3E%3C%2Fp%3E', $field->RAWURLATT());
     $this->assertEquals('&lt;p&gt;Replaced short code with this. &lt;a href=&quot;home&quot;&gt;home&lt;/a&gt;&lt;/p&gt;', $field->ATT());
     $this->assertEquals('<p>Replaced short code with this. <a href="home">home</a></p>', $field->RAW());
     $this->assertEquals('\\x3cp\\x3eReplaced short code with this. \\x3ca href=\\"home\\"\\x3ehome\\x3c/a\\x3e\\x3c/p\\x3e', $field->JS());
     $this->assertEquals('&lt;p&gt;Replaced short code with this. &lt;a href=&quot;home&quot;&gt;home&lt;/a&gt;&lt;/p&gt;', $field->HTML());
     $this->assertEquals('&lt;p&gt;Replaced short code with this. &lt;a href=&quot;home&quot;&gt;home&lt;/a&gt;&lt;/p&gt;', $field->XML());
     $this->assertEquals('Repl...', $field->LimitCharacters(4, '...'));
     $this->assertEquals('Replaced...', $field->LimitCharactersToClosestWord(10, '...'));
     $this->assertEquals('Replaced...', $field->LimitWordCount(1, '...'));
     $this->assertEquals('<p>replaced short code with this. <a href="home">home</a></p>', $field->LowerCase());
     $this->assertEquals('<P>REPLACED SHORT CODE WITH THIS. <A HREF="HOME">HOME</A></P>', $field->UpperCase());
     $this->assertEquals('Replaced short code with this. home', $field->NoHTML());
     Config::nest();
     Config::inst()->update('Director', 'alternate_base_url', 'http://example.com/');
     $this->assertEquals('<p>Replaced short code with this. <a href="http://example.com/home">home</a></p>', $field->AbsoluteLinks());
     Config::unnest();
     $this->assertEquals('Replaced short code with this.', $field->LimitSentences(1));
     $this->assertEquals('Replaced short code with this.', $field->FirstSentence());
     $this->assertEquals('Replaced short...', $field->Summary(2));
     $this->assertEquals('Replaced short code with...', $field->BigSummary(4));
     $this->assertEquals('Replaced short code with this. home[home]', $field->FirstParagraph());
     $this->assertEquals('Replaced <span class="highlight">short</span> <span class="highlight">code</span> with this. home', $field->ContextSummary(500, 'short code'));
     ShortcodeParser::set_active('default');
 }
 /**
  * Converts the Order into HTML, based on the Order Template.
  * @return HTML Object
  **/
 public function ConvertToHTML()
 {
     Config::nest();
     Config::inst()->update('SSViewer', 'theme_enabled', true);
     $html = $this->renderWith("Order");
     Config::unnest();
     $html = preg_replace('/(\\s)+/', ' ', $html);
     return DBField::create_field('HTMLText', $html);
 }
 public function testGetAllowedMaxFileSize()
 {
     Config::nest();
     // Check the max file size uses the config values
     $configMaxFileSizes = array('[image]' => '1k', 'txt' => 1000);
     Config::inst()->update('Upload_Validator', 'default_max_file_size', $configMaxFileSizes);
     $v = new UploadTest_Validator();
     $retrievedSize = $v->getAllowedMaxFileSize('[image]');
     $this->assertEquals(1024, $retrievedSize, 'Max file size check on default values failed (config category set check)');
     $retrievedSize = $v->getAllowedMaxFileSize('txt');
     $this->assertEquals(1000, $retrievedSize, 'Max file size check on default values failed (config extension set check)');
     // Check instance values for max file size
     $maxFileSizes = array('[document]' => 2000, 'txt' => '4k');
     $v = new UploadTest_Validator();
     $v->setAllowedMaxFileSize($maxFileSizes);
     $retrievedSize = $v->getAllowedMaxFileSize('[document]');
     $this->assertEquals(2000, $retrievedSize, 'Max file size check on instance values failed (instance category set check)');
     // Check that the instance values overwrote the default values
     // ie. The max file size will not exist for [image]
     $retrievedSize = $v->getAllowedMaxFileSize('[image]');
     $this->assertFalse($retrievedSize, 'Max file size check on instance values failed (config overridden check)');
     // Check a category that has not been set before
     $retrievedSize = $v->getAllowedMaxFileSize('[archive]');
     $this->assertFalse($retrievedSize, 'Max file size check on instance values failed (category not set check)');
     // Check a file extension that has not been set before
     $retrievedSize = $v->getAllowedMaxFileSize('mp3');
     $this->assertFalse($retrievedSize, 'Max file size check on instance values failed (extension not set check)');
     $retrievedSize = $v->getAllowedMaxFileSize('txt');
     $this->assertEquals(4096, $retrievedSize, 'Max file size check on instance values failed (instance extension set check)');
     Config::unnest();
 }
Example #24
0
 public function testNest()
 {
     // Check basic config
     $this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
     $this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
     // Test nest copies data
     Config::nest();
     $this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
     $this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
     // Test nested data can be updated
     Config::inst()->update('ConfigTest_TestNest', 'foo', 4);
     $this->assertEquals(4, Config::inst()->get('ConfigTest_TestNest', 'foo'));
     $this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
     // Test unnest restores data
     Config::unnest();
     $this->assertEquals(3, Config::inst()->get('ConfigTest_TestNest', 'foo'));
     $this->assertEquals(5, Config::inst()->get('ConfigTest_TestNest', 'bar'));
 }
 /**
  * Start the actual execution of a job.
  * The assumption is the jobID refers to a {@link QueuedJobDescriptor} that is status set as "Queued".
  *
  * This method will continue executing until the job says it's completed
  *
  * @param int $jobId
  *			The ID of the job to start executing
  * @return boolean
  */
 public function runJob($jobId)
 {
     // first retrieve the descriptor
     $jobDescriptor = DataObject::get_by_id('QueuedJobDescriptor', (int) $jobId);
     if (!$jobDescriptor) {
         throw new Exception("{$jobId} is invalid");
     }
     // now lets see whether we have a current user to run as. Typically, if the job is executing via the CLI,
     // we want it to actually execute as the RunAs user - however, if running via the web (which is rare...), we
     // want to ensure that the current user has admin privileges before switching. Otherwise, we just run it
     // as the currently logged in user and hope for the best
     // We need to use $_SESSION directly because SS ties the session to a controller that no longer exists at
     // this point of execution in some circumstances
     $originalUserID = isset($_SESSION['loggedInAs']) ? $_SESSION['loggedInAs'] : 0;
     $originalUser = $originalUserID ? DataObject::get_by_id('Member', $originalUserID) : null;
     $runAsUser = null;
     if (Director::is_cli() || !$originalUser || Permission::checkMember($originalUser, 'ADMIN')) {
         $runAsUser = $jobDescriptor->RunAs();
         if ($runAsUser && $runAsUser->exists()) {
             // the job runner outputs content way early in the piece, meaning there'll be cookie errors
             // if we try and do a normal login, and we only want it temporarily...
             if (Controller::has_curr()) {
                 Session::set('loggedInAs', $runAsUser->ID);
             } else {
                 $_SESSION['loggedInAs'] = $runAsUser->ID;
             }
             // this is an explicit coupling brought about by SS not having
             // a nice way of mocking a user, as it requires session
             // nastiness
             if (class_exists('SecurityContext')) {
                 singleton('SecurityContext')->setMember($runAsUser);
             }
         }
     }
     // set up a custom error handler for this processing
     $errorHandler = new JobErrorHandler();
     $job = null;
     $broken = false;
     // Push a config context onto the stack for the duration of this job run.
     Config::nest();
     if ($this->grabMutex($jobDescriptor)) {
         try {
             $job = $this->initialiseJob($jobDescriptor);
             // get the job ready to begin.
             if (!$jobDescriptor->JobStarted) {
                 $jobDescriptor->JobStarted = date('Y-m-d H:i:s');
             } else {
                 $jobDescriptor->JobRestarted = date('Y-m-d H:i:s');
             }
             $jobDescriptor->JobStatus = QueuedJob::STATUS_RUN;
             $jobDescriptor->write();
             $lastStepProcessed = 0;
             // have we stalled at all?
             $stallCount = 0;
             if ($job->SubsiteID && class_exists('Subsite')) {
                 Subsite::changeSubsite($job->SubsiteID);
                 // lets set the base URL as far as Director is concerned so that our URLs are correct
                 $subsite = DataObject::get_by_id('Subsite', $job->SubsiteID);
                 if ($subsite && $subsite->exists()) {
                     $domain = $subsite->domain();
                     $base = rtrim(Director::protocol() . $domain, '/') . '/';
                     Config::inst()->update('Director', 'alternate_base_url', $base);
                 }
             }
             // while not finished
             while (!$job->jobFinished() && !$broken) {
                 // see that we haven't been set to 'paused' or otherwise by another process
                 $jobDescriptor = DataObject::get_by_id('QueuedJobDescriptor', (int) $jobId);
                 if (!$jobDescriptor || !$jobDescriptor->exists()) {
                     $broken = true;
                     SS_Log::log(array('errno' => 0, 'errstr' => 'Job descriptor ' . $jobId . ' could not be found', 'errfile' => __FILE__, 'errline' => __LINE__, 'errcontext' => array()), SS_Log::ERR);
                     break;
                 }
                 if ($jobDescriptor->JobStatus != QueuedJob::STATUS_RUN) {
                     // we've been paused by something, so we'll just exit
                     $job->addMessage(sprintf(_t('QueuedJobs.JOB_PAUSED', "Job paused at %s"), date('Y-m-d H:i:s')));
                     $broken = true;
                 }
                 if (!$broken) {
                     try {
                         $job->process();
                     } catch (Exception $e) {
                         // okay, we'll just catch this exception for now
                         $job->addMessage(sprintf(_t('QueuedJobs.JOB_EXCEPT', 'Job caused exception %s in %s at line %s'), $e->getMessage(), $e->getFile(), $e->getLine()), 'ERROR');
                         SS_Log::log($e, SS_Log::ERR);
                         $jobDescriptor->JobStatus = QueuedJob::STATUS_BROKEN;
                     }
                     // now check the job state
                     $data = $job->getJobData();
                     if ($data->currentStep == $lastStepProcessed) {
                         $stallCount++;
                     }
                     if ($stallCount > Config::inst()->get(__CLASS__, 'stall_threshold')) {
                         $broken = true;
                         $job->addMessage(sprintf(_t('QueuedJobs.JOB_STALLED', "Job stalled after %s attempts - please check"), $stallCount), 'ERROR');
                         $jobDescriptor->JobStatus = QueuedJob::STATUS_BROKEN;
                     }
                     // now we'll be good and check our memory usage. If it is too high, we'll set the job to
                     // a 'Waiting' state, and let the next processing run pick up the job.
                     if ($this->isMemoryTooHigh()) {
                         $job->addMessage(sprintf(_t('QueuedJobs.MEMORY_RELEASE', 'Job releasing memory and waiting (%s used)'), $this->humanReadable($this->getMemoryUsage())));
                         $jobDescriptor->JobStatus = QueuedJob::STATUS_WAIT;
                         $broken = true;
                     }
                     // Also check if we are running too long
                     if ($this->hasPassedTimeLimit()) {
                         $job->addMessage(_t('QueuedJobs.TIME_LIMIT', 'Queue has passed time limit and will restart before continuing'));
                         $jobDescriptor->JobStatus = QueuedJob::STATUS_WAIT;
                         $broken = true;
                     }
                 }
                 if ($jobDescriptor) {
                     $this->copyJobToDescriptor($job, $jobDescriptor);
                     $jobDescriptor->write();
                 } else {
                     SS_Log::log(array('errno' => 0, 'errstr' => 'Job descriptor has been set to null', 'errfile' => __FILE__, 'errline' => __LINE__, 'errcontext' => array()), SS_Log::WARN);
                     $broken = true;
                 }
             }
             // a last final save. The job is complete by now
             if ($jobDescriptor) {
                 $jobDescriptor->write();
             }
             if (!$broken) {
                 $job->afterComplete();
                 $jobDescriptor->cleanupJob();
             }
         } catch (Exception $e) {
             // okay, we'll just catch this exception for now
             SS_Log::log($e, SS_Log::ERR);
             $jobDescriptor->JobStatus = QueuedJob::STATUS_BROKEN;
             $jobDescriptor->write();
             $broken = true;
         }
     }
     $errorHandler->clear();
     Config::unnest();
     // okay let's reset our user if we've got an original
     if ($runAsUser && $originalUser) {
         Session::clear("loggedInAs");
         if ($originalUser) {
             Session::set("loggedInAs", $originalUser->ID);
         }
     }
     return !$broken;
 }
 /**
  * many_many_extraFields is allowed to have an array value, so shouldn't throw an exception
  */
 public function testValidateModelDefinitionsPassesWithExtraFields()
 {
     Config::nest();
     $object = new DataObjectTest_Team();
     $method = $this->makeAccessible($object, 'validateModelDefinitions');
     Config::inst()->update('DataObjectTest_Team', 'many_many_extraFields', array('Relations' => array('Price' => 'Int')));
     try {
         $method->invoke($object);
     } catch (Exception $e) {
         Config::unnest();
         $this->fail('Exception should not be thrown');
         throw $e;
     }
     Config::unnest();
 }
 /**
  * Test a URL request, returning a response object. This method is the counterpart of
  * Director::direct() that is used in functional testing. It will execute the URL given, and
  * return the result as an SS_HTTPResponse object.
  *
  * @uses getControllerForURL() The rule-lookup logic is handled by this.
  * @uses Controller::run() Handles the page logic for a Director::direct() call.
  *
  * @param string $url The URL to visit.
  * @param array $postVars The $_POST & $_FILES variables.
  * @param array|Session $session The {@link Session} object representing the current session.
  * By passing the same object to multiple  calls of Director::test(), you can simulate a persisted
  * session.
  * @param string $httpMethod The HTTP method, such as GET or POST.  It will default to POST if
  * postVars is set, GET otherwise. Overwritten by $postVars['_method'] if present.
  * @param string $body The HTTP body.
  * @param array $headers HTTP headers with key-value pairs.
  * @param array|Cookie_Backend $cookies to populate $_COOKIE.
  * @param HTTP_Request $request The {@see HTTP_Request} object generated as a part of this request.
  *
  * @return SS_HTTPResponse
  *
  * @throws SS_HTTPResponse_Exception
  */
 public static function test($url, $postVars = null, $session = array(), $httpMethod = null, $body = null, $headers = array(), $cookies = array(), &$request = null)
 {
     Config::nest();
     Injector::nest();
     // These are needed so that calling Director::test() does not muck with whoever is calling it.
     // Really, it's some inappropriate coupling and should be resolved by making less use of statics.
     $oldReadingMode = Versioned::get_reading_mode();
     $getVars = array();
     if (!$httpMethod) {
         $httpMethod = $postVars || is_array($postVars) ? "POST" : "GET";
     }
     if (!$session) {
         $session = Injector::inst()->create('Session', array());
     }
     $cookieJar = $cookies instanceof Cookie_Backend ? $cookies : Injector::inst()->createWithArgs('Cookie_Backend', array($cookies ?: array()));
     // Back up the current values of the superglobals
     $existingRequestVars = isset($_REQUEST) ? $_REQUEST : array();
     $existingGetVars = isset($_GET) ? $_GET : array();
     $existingPostVars = isset($_POST) ? $_POST : array();
     $existingSessionVars = isset($_SESSION) ? $_SESSION : array();
     $existingCookies = isset($_COOKIE) ? $_COOKIE : array();
     $existingServer = isset($_SERVER) ? $_SERVER : array();
     $existingRequirementsBackend = Requirements::backend();
     Config::inst()->update('Cookie', 'report_errors', false);
     Requirements::set_backend(Injector::inst()->create('Requirements_Backend'));
     // Set callback to invoke prior to return
     $onCleanup = function () use($existingRequestVars, $existingGetVars, $existingPostVars, $existingSessionVars, $existingCookies, $existingServer, $existingRequirementsBackend, $oldReadingMode) {
         // Restore the super globals
         $_REQUEST = $existingRequestVars;
         $_GET = $existingGetVars;
         $_POST = $existingPostVars;
         $_SESSION = $existingSessionVars;
         $_COOKIE = $existingCookies;
         $_SERVER = $existingServer;
         Requirements::set_backend($existingRequirementsBackend);
         // These are needed so that calling Director::test() does not muck with whoever is calling it.
         // Really, it's some inappropriate coupling and should be resolved by making less use of statics
         Versioned::set_reading_mode($oldReadingMode);
         Injector::unnest();
         // Restore old CookieJar, etc
         Config::unnest();
     };
     if (strpos($url, '#') !== false) {
         $url = substr($url, 0, strpos($url, '#'));
     }
     // Handle absolute URLs
     if (parse_url($url, PHP_URL_HOST)) {
         $bits = parse_url($url);
         // If a port is mentioned in the absolute URL, be sure to add that into the HTTP host
         if (isset($bits['port'])) {
             $_SERVER['HTTP_HOST'] = $bits['host'] . ':' . $bits['port'];
         } else {
             $_SERVER['HTTP_HOST'] = $bits['host'];
         }
     }
     // Ensure URL is properly made relative.
     // Example: url passed is "/ss31/my-page" (prefixed with BASE_URL), this should be changed to "my-page"
     $url = self::makeRelative($url);
     $urlWithQuerystring = $url;
     if (strpos($url, '?') !== false) {
         list($url, $getVarsEncoded) = explode('?', $url, 2);
         parse_str($getVarsEncoded, $getVars);
     }
     // Replace the super globals with appropriate test values
     $_REQUEST = ArrayLib::array_merge_recursive((array) $getVars, (array) $postVars);
     $_GET = (array) $getVars;
     $_POST = (array) $postVars;
     $_SESSION = $session ? $session->inst_getAll() : array();
     $_COOKIE = $cookieJar->getAll(false);
     Injector::inst()->registerService($cookieJar, 'Cookie_Backend');
     $_SERVER['REQUEST_URI'] = Director::baseURL() . $urlWithQuerystring;
     $request = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body);
     if ($headers) {
         foreach ($headers as $k => $v) {
             $request->addHeader($k, $v);
         }
     }
     // Pre-request filtering
     // @see issue #2517
     $model = DataModel::inst();
     $output = Injector::inst()->get('RequestProcessor')->preRequest($request, $session, $model);
     if ($output === false) {
         $onCleanup();
         throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400);
     }
     // TODO: Pass in the DataModel
     $result = Director::handleRequest($request, $session, $model);
     // Ensure that the result is an SS_HTTPResponse object
     if (is_string($result)) {
         if (substr($result, 0, 9) == 'redirect:') {
             $response = new SS_HTTPResponse();
             $response->redirect(substr($result, 9));
             $result = $response;
         } else {
             $result = new SS_HTTPResponse($result);
         }
     }
     $output = Injector::inst()->get('RequestProcessor')->postRequest($request, $result, $model);
     if ($output === false) {
         $onCleanup();
         throw new SS_HTTPResponse_Exception("Invalid response");
     }
     // Return valid response
     $onCleanup();
     return $result;
 }
 public function tearDown()
 {
     Versioned::set_reading_mode($this->oldMode);
     Config::unnest();
     parent::tearDown();
 }
 public function tearDown()
 {
     // restores the config variables
     Config::unnest();
     parent::tearDown();
 }
 /**
  * Test against a theme.
  *
  * @param $themeBaseDir string - themes directory
  * @param $theme string - theme name
  * @param $callback Closure
  */
 protected function useTestTheme($themeBaseDir, $theme, $callback)
 {
     Config::nest();
     if (strpos($themeBaseDir, BASE_PATH) === 0) {
         $themeBaseDir = substr($themeBaseDir, strlen(BASE_PATH));
     }
     SSViewer::set_themes([$themeBaseDir . '/themes/' . $theme, '$default']);
     $e = null;
     try {
         $callback();
     } catch (Exception $e) {
         /* NOP for now, just save $e */
     }
     Config::unnest();
     if ($e) {
         throw $e;
     }
 }