public function tearDown()
 {
     parent::tearDown();
     i18n::set_locale($this->originalLocale);
     Config::inst()->remove('SilverStripe\\Forms\\TimeField', 'default_config');
     Config::inst()->update('SilverStripe\\Forms\\TimeField', 'default_config', $this->origTimeConfig);
 }
 /**
  * Triggered early in the request when a flush is requested
  */
 public static function flush()
 {
     $disabled = Config::inst()->get(static::class, 'disable_flush_combined');
     if (!$disabled) {
         self::delete_all_combined_files();
     }
 }
 /**
  * Register a new batch action.  Each batch action needs to be represented by a subclass
  * of {@link CMSBatchAction}.
  *
  * @param string $urlSegment The URL Segment of the batch action - the URL used to process this
  * action will be admin/pages/batchactions/(urlSegment)
  * @param string $batchActionClass The name of the CMSBatchAction subclass to register
  * @param string $recordClass
  */
 public static function register($urlSegment, $batchActionClass, $recordClass = SiteTree::class)
 {
     if (!is_subclass_of($batchActionClass, CMSBatchAction::class)) {
         throw new InvalidArgumentException("CMSBatchActionHandler::register() - Bad class '{$batchActionClass}'");
     }
     Config::inst()->update(CMSBatchActionHandler::class, 'batch_actions', array($urlSegment => array('class' => $batchActionClass, 'recordClass' => $recordClass)));
 }
 public function connect($parameters, $selectDB = false)
 {
     // Normally $selectDB is set to false by the MySQLDatabase controller, as per convention
     $selectedDB = $selectDB && !empty($parameters['database']) ? $parameters['database'] : null;
     // Connection charset and collation
     $connCharset = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'connection_charset');
     $connCollation = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'connection_collation');
     if (!empty($parameters['port'])) {
         $this->dbConn = new MySQLi($parameters['server'], $parameters['username'], $parameters['password'], $selectedDB, $parameters['port']);
     } else {
         $this->dbConn = new MySQLi($parameters['server'], $parameters['username'], $parameters['password'], $selectedDB);
     }
     if ($this->dbConn->connect_error) {
         $this->databaseError("Couldn't connect to MySQL database | " . $this->dbConn->connect_error);
     }
     // Set charset and collation if given and not null. Can explicitly set to empty string to omit
     $charset = isset($parameters['charset']) ? $parameters['charset'] : $connCharset;
     if (!empty($charset)) {
         $this->dbConn->set_charset($charset);
     }
     $collation = isset($parameters['collation']) ? $parameters['collation'] : $connCollation;
     if (!empty($collation)) {
         $this->dbConn->query("SET collation_connection = {$collation}");
     }
 }
 public function setUp()
 {
     parent::setUp();
     $this->logInWithPermission('ADMIN');
     // Save versioned state
     $this->oldReadingMode = Versioned::get_reading_mode();
     Versioned::set_stage(Versioned::DRAFT);
     // Set backend root to /UploadFieldTest
     AssetStoreTest_SpyStore::activate('UploadFieldTest');
     // Set the File Name Filter replacements so files have the expected names
     Config::inst()->update('SilverStripe\\Assets\\FileNameFilter', 'default_replacements', array('/\\s/' => '-', '/_/' => '-', '/[^A-Za-z0-9+.\\-]+/' => '', '/[\\-]{2,}/' => '-', '/^[\\.\\-_]+/' => ''));
     // Create a test folders for each of the fixture references
     foreach (Folder::get() as $folder) {
         $path = AssetStoreTest_SpyStore::getLocalPath($folder);
         Filesystem::makeFolder($path);
     }
     // Create a test files for each of the fixture references
     $files = File::get()->exclude('ClassName', 'SilverStripe\\Assets\\Folder');
     foreach ($files as $file) {
         $path = AssetStoreTest_SpyStore::getLocalPath($file);
         Filesystem::makeFolder(dirname($path));
         $fh = fopen($path, "w+");
         fwrite($fh, str_repeat('x', 1000000));
         fclose($fh);
     }
 }
 /**
  * Get maximum file size for all or specified file extension.
  *
  * @param string $ext
  * @return int Filesize in bytes
  */
 public function getAllowedMaxFileSize($ext = null)
 {
     // Check if there is any defined instance max file sizes
     if (empty($this->allowedMaxFileSize)) {
         // Set default max file sizes if there isn't
         $fileSize = Config::inst()->get('SilverStripe\\Assets\\Upload_Validator', 'default_max_file_size');
         if ($fileSize) {
             $this->setAllowedMaxFileSize($fileSize);
         } else {
             // When no default is present, use maximum set by PHP
             $maxUpload = File::ini2bytes(ini_get('upload_max_filesize'));
             $maxPost = File::ini2bytes(ini_get('post_max_size'));
             $this->setAllowedMaxFileSize(min($maxUpload, $maxPost));
         }
     }
     $ext = strtolower($ext);
     if ($ext) {
         if (isset($this->allowedMaxFileSize[$ext])) {
             return $this->allowedMaxFileSize[$ext];
         }
         $category = File::get_app_category($ext);
         if ($category && isset($this->allowedMaxFileSize['[' . $category . ']'])) {
             return $this->allowedMaxFileSize['[' . $category . ']'];
         }
     }
     return isset($this->allowedMaxFileSize['*']) ? $this->allowedMaxFileSize['*'] : false;
 }
 public function setUp()
 {
     parent::setUp();
     // Set backend
     AssetStoreTest_SpyStore::activate('DBFileTest');
     Config::inst()->update('SilverStripe\\Control\\Director', 'alternate_base_url', '/mysite/');
 }
 public function testNice()
 {
     $time = DBField::create_field('Time', '17:15:55');
     $this->assertEquals('5:15pm', $time->Nice());
     Config::inst()->update('SilverStripe\\ORM\\FieldType\\DBTime', 'nice_format', 'H:i:s');
     $this->assertEquals('17:15:55', $time->Nice());
 }
 /**
  * Configure server files for this store
  *
  * @param bool $forceOverwrite Force regeneration even if files already exist
  * @throws \Exception
  */
 protected function configureServer($forceOverwrite = false)
 {
     // Get server type
     $type = isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '*';
     list($type) = explode('/', strtolower($type));
     // Determine configurations to write
     $rules = Config::inst()->get(get_class($this), 'server_configuration', Config::FIRST_SET);
     if (empty($rules[$type])) {
         return;
     }
     $configurations = $rules[$type];
     // Apply each configuration
     $config = new FlysystemConfig();
     $config->set('visibility', 'private');
     foreach ($configurations as $file => $template) {
         if ($forceOverwrite || !$this->has($file)) {
             // Evaluate file
             $content = $this->renderTemplate($template);
             $success = $this->write($file, $content, $config);
             if (!$success) {
                 throw new \Exception("Error writing server configuration file \"{$file}\"");
             }
         }
     }
 }
 public function testEnablePluginsByArrayWithPaths()
 {
     Config::inst()->update('SilverStripe\\Control\\Director', 'alternate_base_url', 'http://mysite.com/subdir');
     $c = new TinyMCEConfig();
     $c->setTheme('modern');
     $c->setOption('language', 'es');
     $c->disablePlugins('table', 'emoticons', 'paste', 'code', 'link', 'importcss');
     $c->enablePlugins(array('plugin1' => 'mypath/plugin1.js', 'plugin2' => '/anotherbase/mypath/plugin2.js', 'plugin3' => 'https://www.google.com/plugin.js', 'plugin4' => null, 'plugin5' => null));
     $attributes = $c->getAttributes();
     $config = Convert::json2array($attributes['data-config']);
     $plugins = $config['external_plugins'];
     $this->assertNotEmpty($plugins);
     // Plugin specified via relative url
     $this->assertContains('plugin1', array_keys($plugins));
     $this->assertEquals('http://mysite.com/subdir/mypath/plugin1.js', $plugins['plugin1']);
     // Plugin specified via root-relative url
     $this->assertContains('plugin2', array_keys($plugins));
     $this->assertEquals('http://mysite.com/anotherbase/mypath/plugin2.js', $plugins['plugin2']);
     // Plugin specified with absolute url
     $this->assertContains('plugin3', array_keys($plugins));
     $this->assertEquals('https://www.google.com/plugin.js', $plugins['plugin3']);
     // Plugin specified with standard location
     $this->assertContains('plugin4', array_keys($plugins));
     $this->assertEquals('http://mysite.com/subdir/' . ADMIN_THIRDPARTY_DIR . '/tinymce/plugins/plugin4/plugin.min.js', $plugins['plugin4']);
     // Check that internal plugins are extractable separately
     $this->assertEquals(['plugin4', 'plugin5'], $c->getInternalPlugins());
     // Test plugins included via gzip compresser
     HTMLEditorField::config()->update('use_gzip', true);
     $this->assertEquals(ADMIN_THIRDPARTY_DIR . '/tinymce/tiny_mce_gzip.php?js=1&plugins=plugin4,plugin5&themes=modern&languages=es&diskcache=true&src=true', $c->getScriptURL());
     // If gzip is disabled only the core plugin is loaded
     HTMLEditorField::config()->remove('use_gzip');
     $this->assertEquals(ADMIN_THIRDPARTY_DIR . '/tinymce/tinymce.min.js', $c->getScriptURL());
 }
 public function requireField()
 {
     // @todo: Remove mysql-centric logic from this
     $charset = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'charset');
     $collation = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'collation');
     $values = array('type' => 'set', 'parts' => array('enums' => $this->enum, 'character set' => $charset, 'collate' => $collation, 'default' => $this->default, 'table' => $this->tableName, 'arrayValue' => $this->arrayValue));
     DB::require_field($this->tableName, $this->name, $values);
 }
 /**
  * (non-PHPdoc)
  * @see DBField::requireField()
  */
 public function requireField()
 {
     $charset = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'charset');
     $collation = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'collation');
     $parts = array('datatype' => 'varchar', 'precision' => $this->size, 'character set' => $charset, 'collate' => $collation, 'arrayValue' => $this->arrayValue);
     $values = array('type' => 'varchar', 'parts' => $parts);
     DB::require_field($this->tableName, $this->name, $values);
 }
 public function setUp()
 {
     parent::setUp();
     $this->rootDir = ASSETS_PATH . '/AssetAdapterTest';
     Filesystem::makeFolder($this->rootDir);
     Config::inst()->update('SilverStripe\\Control\\Director', 'alternate_base_url', '/');
     $this->originalServer = $_SERVER;
 }
 /**
  * (non-PHPdoc)
  * @see DBField::requireField()
  */
 public function requireField()
 {
     $charset = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'charset');
     $collation = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'collation');
     $parts = ['datatype' => 'mediumtext', 'character set' => $charset, 'collate' => $collation, 'default' => $this->defaultVal, 'arrayValue' => $this->arrayValue];
     $values = ['type' => 'text', 'parts' => $parts];
     DB::require_field($this->tableName, $this->name, $values);
 }
 public function testPermissionFieldRespectsHiddenPermissions()
 {
     $this->session()->inst_set('loggedInAs', $this->idFromFixture('SilverStripe\\Security\\Member', 'admin'));
     $group = $this->objFromFixture('SilverStripe\\Security\\Group', 'admin');
     Config::inst()->update('SilverStripe\\Security\\Permission', 'hidden_permissions', array('CMS_ACCESS_ReportAdmin'));
     $response = $this->get(sprintf('admin/security/EditForm/field/Groups/item/%d/edit', $group->ID));
     $this->assertContains('CMS_ACCESS_SecurityAdmin', $response->getBody());
     $this->assertNotContains('CMS_ACCESS_ReportAdmin', $response->getBody());
 }
 public function setUpOnce()
 {
     Config::nest();
     VersionableExtensionsTest_DataObject::add_extension('SilverStripe\\ORM\\Versioning\\Versioned');
     VersionableExtensionsTest_DataObject::add_extension('VersionableExtensionsTest_Extension');
     $cfg = Config::inst();
     $cfg->update('VersionableExtensionsTest_DataObject', 'versionableExtensions', array('VersionableExtensionsTest_Extension' => array('test1', 'test2', 'test3')));
     parent::setUpOnce();
 }
 /**
  * Retrieves the config for a named service without performing a hierarchy walk
  *
  * @param string $name Name of service
  * @return mixed Get config for this service
  */
 protected function configFor($name)
 {
     // Return cached result
     if (array_key_exists($name, $this->configs)) {
         return $this->configs[$name];
     }
     $config = Config::inst()->get('SilverStripe\\Core\\Injector\\Injector', $name);
     $this->configs[$name] = $config;
     return $config;
 }
 public function setUp()
 {
     parent::setUp();
     if (!extension_loaded("gd")) {
         $this->markTestSkipped("The GD extension is required");
         return;
     }
     /** @skipUpgrade */
     Config::inst()->update('SilverStripe\\Core\\Injector\\Injector', 'Image_Backend', 'SilverStripe\\Assets\\GDBackend');
 }
 public function setUp()
 {
     parent::setUp();
     if (!extension_loaded("imagick")) {
         $this->markTestSkipped("The Imagick extension is not available.");
         return;
     }
     /** @skipUpgrade */
     Config::inst()->update('SilverStripe\\Core\\Injector\\Injector', 'Image_Backend', 'SilverStripe\\Assets\\ImagickBackend');
 }
 public function testTimeFormatDefaultCheckedInFormField()
 {
     Config::inst()->update('SilverStripe\\i18n\\i18n', 'time_format', 'h:mm:ss a');
     $field = $this->createTimeFormatFieldForMember($this->objFromFixture('SilverStripe\\Security\\Member', 'noformatmember'));
     /** @skipUpgrade */
     $field->setForm(new Form(new MemberDatetimeOptionsetFieldTest_Controller(), 'Form', new FieldList(), new FieldList()));
     // fake form
     $parser = new CSSContentParser($field->Field());
     $xmlArr = $parser->getBySelector('#Form_Form_TimeFormat_h:mm:ss_a');
     $this->assertEquals('checked', (string) $xmlArr[0]['checked']);
 }
 protected function findRoot($root)
 {
     // Use explicitly defined path
     if ($root) {
         return parent::findRoot($root);
     }
     // Use environment defined path
     if (defined('SS_PROTECTED_ASSETS_PATH')) {
         return SS_PROTECTED_ASSETS_PATH;
     }
     // Default location is under assets
     return ASSETS_PATH . '/' . Config::inst()->get(get_class($this), 'secure_folder');
 }
 function testValidAlternativeDatabaseName()
 {
     $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
     Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'dev');
     $this->assertTrue(DB::valid_alternative_database_name($prefix . 'tmpdb1234567'));
     $this->assertFalse(DB::valid_alternative_database_name($prefix . 'tmpdb12345678'));
     $this->assertFalse(DB::valid_alternative_database_name('tmpdb1234567'));
     $this->assertFalse(DB::valid_alternative_database_name('random'));
     $this->assertFalse(DB::valid_alternative_database_name(''));
     Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'live');
     $this->assertFalse(DB::valid_alternative_database_name($prefix . 'tmpdb1234567'));
     Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'dev');
 }
 public function setUp()
 {
     parent::setUp();
     // Set backend root to /HTMLEditorFieldTest
     AssetStoreTest_SpyStore::activate('HTMLEditorFieldTest');
     // Set the File Name Filter replacements so files have the expected names
     Config::inst()->update('SilverStripe\\Assets\\FileNameFilter', 'default_replacements', array('/\\s/' => '-', '/_/' => '-', '/[^A-Za-z0-9+.\\-]+/' => '', '/[\\-]{2,}/' => '-', '/^[\\.\\-_]+/' => ''));
     // Create a test files for each of the fixture references
     $files = File::get()->exclude('ClassName', 'SilverStripe\\Assets\\Folder');
     foreach ($files as $file) {
         $fromPath = FRAMEWORK_PATH . '/tests/forms/images/' . $file->Name;
         $destPath = AssetStoreTest_SpyStore::getLocalPath($file);
         // Only correct for test asset store
         Filesystem::makeFolder(dirname($destPath));
         copy($fromPath, $destPath);
     }
 }
 public function testNiceDate()
 {
     $this->assertEquals('31/03/2008', DBField::create_field('Date', 1206968400)->Nice(), "Date->Nice() works with timestamp integers");
     $this->assertEquals('30/03/2008', DBField::create_field('Date', 1206882000)->Nice(), "Date->Nice() works with timestamp integers");
     $this->assertEquals('31/03/2008', DBField::create_field('Date', '1206968400')->Nice(), "Date->Nice() works with timestamp strings");
     $this->assertEquals('30/03/2008', DBField::create_field('Date', '1206882000')->Nice(), "Date->Nice() works with timestamp strings");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '4/3/03')->Nice(), "Date->Nice() works with D/M/YY format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '04/03/03')->Nice(), "Date->Nice() works with DD/MM/YY format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '4/3/03')->Nice(), "Date->Nice() works with D/M/YY format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '4/03/03')->Nice(), "Date->Nice() works with D/M/YY format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '4/3/2003')->Nice(), "Date->Nice() works with D/M/YYYY format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '4-3-2003')->Nice(), "Date->Nice() works with D-M-YYYY format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '2003-03-04')->Nice(), "Date->Nice() works with YYYY-MM-DD format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '04/03/2003')->Nice(), "Date->Nice() works with DD/MM/YYYY format");
     $this->assertEquals('04/03/2003', DBField::create_field('Date', '04-03-2003')->Nice(), "Date->Nice() works with DD/MM/YYYY format");
     $date = DBField::create_field('Date', '2003-03-04');
     Config::inst()->update('SilverStripe\\ORM\\FieldType\\DBDate', 'nice_format', 'd F Y');
     $this->assertEquals('04 March 2003', $date->Nice());
 }
 /**
  * This implementation allows for a list of columns to be passed into MATCH() instead of just one.
  *
  * @example
  * <code>
  * 	MyDataObject::get()->filter('SearchFields:fulltext', 'search term')
  * </code>
  *
  * @throws Exception
  * @return string
  */
 public function getDbName()
 {
     $indexes = Config::inst()->get($this->model, "indexes");
     if (is_array($indexes) && array_key_exists($this->getName(), $indexes)) {
         $index = $indexes[$this->getName()];
         if (is_array($index) && array_key_exists("value", $index)) {
             return $this->prepareColumns($index['value']);
         } else {
             // Parse a fulltext string (eg. fulltext ("ColumnA", "ColumnB")) to figure out which columns
             // we need to search.
             if (preg_match('/^fulltext\\s+\\((.+)\\)$/i', $index, $matches)) {
                 return $this->prepareColumns($matches[1]);
             } else {
                 throw new Exception(sprintf("Invalid fulltext index format for '%s' on '%s'", $this->getName(), $this->model));
             }
         }
     }
     return parent::getDbName();
 }
 public function process($item, $arguments = null, $scope = null)
 {
     $hash = sha1($this->content);
     $cacheFile = TEMP_FOLDER . "/.cache.{$hash}";
     if (!file_exists($cacheFile) || isset($_GET['flush'])) {
         $content = $this->parseTemplateContent($this->content, "string sha1={$hash}");
         $fh = fopen($cacheFile, 'w');
         fwrite($fh, $content);
         fclose($fh);
     }
     $val = $this->includeGeneratedTemplate($cacheFile, $item, $arguments, null, $scope);
     if ($this->cacheTemplate !== null) {
         $cacheTemplate = $this->cacheTemplate;
     } else {
         $cacheTemplate = Config::inst()->get('SilverStripe\\View\\SSViewer_FromString', 'cache_template');
     }
     if (!$cacheTemplate) {
         unlink($cacheFile);
     }
     return $val;
 }
 public function testDefaultClasses()
 {
     Config::nest();
     FormField::config()->update('default_classes', array('class1'));
     $field = new FormField('MyField');
     $this->assertContains('class1', $field->extraClass(), 'Class list does not contain expected class');
     FormField::config()->update('default_classes', array('class1', 'class2'));
     $field = new FormField('MyField');
     $this->assertContains('class1 class2', $field->extraClass(), 'Class list does not contain expected class');
     FormField::config()->update('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');
     TextField::config()->update('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();
 }
 /**
  * Enable the default configuration of MySQL full-text searching on the given data classes.
  * It can be used to limit the searched classes, but not to add your own classes.
  * For this purpose, please use {@link Object::add_extension()} directly:
  * <code>
  * MyObject::add_extension("FulltextSearchable('MySearchableField,MyOtherField')");
  * </code>
  *
  * Caution: This is a wrapper method that should only be used in _config.php,
  * and only be called once in your code.
  *
  * @param array $searchableClasses The extension will be applied to all DataObject subclasses
  *  listed here. Default: {@link SiteTree} and {@link File}.
  * @throws Exception
  */
 public static function enable($searchableClasses = array('SilverStripe\\CMS\\Model\\SiteTree', 'SilverStripe\\Assets\\File'))
 {
     $defaultColumns = array('SilverStripe\\CMS\\Model\\SiteTree' => '"Title","MenuTitle","Content","MetaDescription"', 'SilverStripe\\Assets\\File' => '"Name","Title"');
     if (!is_array($searchableClasses)) {
         $searchableClasses = array($searchableClasses);
     }
     foreach ($searchableClasses as $class) {
         if (!class_exists($class)) {
             continue;
         }
         if (isset($defaultColumns[$class])) {
             Config::inst()->update($class, 'create_table_options', array(MySQLSchemaManager::ID => 'ENGINE=MyISAM'));
             $class::add_extension(__CLASS__ . "('{$defaultColumns[$class]}')");
         } else {
             throw new Exception("FulltextSearchable::enable() I don't know the default search columns for class '{$class}'");
         }
     }
     self::$searchable_classes = $searchableClasses;
     if (class_exists("SilverStripe\\CMS\\Controllers\\ContentController")) {
         ContentController::add_extension("SilverStripe\\CMS\\Search\\ContentControllerSearchExtension");
     }
 }
 /**
  * Test with default -v prefix
  */
 public function testWithDefaultPrefix()
 {
     Config::inst()->update('SilverStripe\\Assets\\Storage\\DefaultAssetNameGenerator', 'version_prefix', '-v');
     // Test with item that doesn't contain the prefix
     $generator = new DefaultAssetNameGenerator('folder/MyFile-001.jpg');
     $suggestions = iterator_to_array($generator);
     $this->assertEquals(100, count($suggestions));
     $this->assertEquals('folder/MyFile-001.jpg', $suggestions[0]);
     $this->assertEquals('folder/MyFile-001-v2.jpg', $suggestions[1]);
     $this->assertEquals('folder/MyFile-001-v4.jpg', $suggestions[3]);
     $this->assertEquals('folder/MyFile-001-v21.jpg', $suggestions[20]);
     $this->assertEquals('folder/MyFile-001-v99.jpg', $suggestions[98]);
     $this->assertNotEquals('folder/MyFile-001-v100.jpg', $suggestions[99]);
     // Last suggestion is semi-random
     // Test with item that contains prefix
     $generator = new DefaultAssetNameGenerator('folder/MyFile-v24.jpg');
     $suggestions = iterator_to_array($generator);
     $this->assertEquals(100, count($suggestions));
     $this->assertEquals('folder/MyFile-v24.jpg', $suggestions[0]);
     $this->assertEquals('folder/MyFile-v25.jpg', $suggestions[1]);
     $this->assertEquals('folder/MyFile-v26.jpg', $suggestions[2]);
     $this->assertEquals('folder/MyFile-v48.jpg', $suggestions[24]);
     $this->assertEquals('folder/MyFile-v122.jpg', $suggestions[98]);
     $this->assertNotEquals('folder/MyFile-v123.jpg', $suggestions[99]);
     $this->assertNotEquals('folder/MyFile-123.jpg', $suggestions[99]);
     // Test without numeric value
     $generator = new DefaultAssetNameGenerator('folder/MyFile.jpg');
     $suggestions = iterator_to_array($generator);
     $this->assertEquals(100, count($suggestions));
     $this->assertEquals('folder/MyFile.jpg', $suggestions[0]);
     $this->assertEquals('folder/MyFile-v2.jpg', $suggestions[1]);
     $this->assertEquals('folder/MyFile-v3.jpg', $suggestions[2]);
     $this->assertEquals('folder/MyFile-v25.jpg', $suggestions[24]);
     $this->assertEquals('folder/MyFile-v99.jpg', $suggestions[98]);
     $this->assertNotEquals('folder/MyFile-v100.jpg', $suggestions[99]);
 }
 /**
  * this function is used to provide modifications to the fields labels in CMS
  * by the extension
  * By default, the fieldLabels() of its owner will merge more fields defined in the extension's
  * $extra_fields['field_labels']
  *
  * @param array $labels Array of field labels
  */
 public function updateFieldLabels(&$labels)
 {
     $field_labels = Config::inst()->get($this->class, 'field_labels');
     if ($field_labels) {
         $labels = array_merge($labels, $field_labels);
     }
 }