Browse Source

Merge branch 'master' into 3.next

Mark Story 10 years ago
parent
commit
503a74fd59

+ 1 - 0
.travis.yml

@@ -63,6 +63,7 @@ before_install:
   - if [[ $TRAVIS_PHP_VERSION != 'hhvm' ]] ; then echo 'extension = memcached.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
   - if [[ $TRAVIS_PHP_VERSION != 'hhvm' ]] ; then echo 'extension = redis.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
   - if [[ $TRAVIS_PHP_VERSION != 'hhvm' ]] ; then echo 'extension = apcu.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
+  - if [[ $TRAVIS_PHP_VERSION != 'hhvm' ]] ; then echo 'apc.enable_cli = 1' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
   - if [[ $TRAVIS_PHP_VERSION =~ 5.[56] ]] ; then echo yes | pecl install apcu-4.0.10; fi
   - if [[ $TRAVIS_PHP_VERSION = 7.* ]] ; then echo yes | pecl install apcu; fi
   - if [[ $TRAVIS_PHP_VERSION = 7.* ]] ; then pecl config-set preferred_state beta; echo yes | pecl install apcu_bc; fi

+ 14 - 5
src/Cache/Engine/ApcEngine.php

@@ -142,11 +142,20 @@ class ApcEngine extends CacheEngine
         if ($check) {
             return true;
         }
-        $iterator = new APCUIterator(
-            '/^' . preg_quote($this->_config['prefix'], '/') . '/',
-            APC_ITER_NONE
-        );
-        apcu_delete($iterator);
+        if (class_exists('APCUIterator', false)) {
+            $iterator = new APCUIterator(
+                '/^' . preg_quote($this->_config['prefix'], '/') . '/',
+                APC_ITER_NONE
+            );
+            apcu_delete($iterator);
+            return true;
+        }
+        $cache = apcu_cache_info();
+        foreach ($cache['cache_list'] as $key) {
+            if (strpos($key['info'], $this->_config['prefix']) === 0) {
+                apcu_delete($key['info']);
+            }
+        }
         return true;
     }
 

+ 6 - 4
src/Database/Schema/Table.php

@@ -603,10 +603,12 @@ class Table
                     $attrs['columns']
                 ));
 
-                $this->_constraints[$name]['references'][1] = array_unique(array_merge(
-                    (array)$this->_constraints[$name]['references'][1],
-                    [$attrs['references'][1]]
-                ));
+                if (isset($this->_constraints[$name]['references'])) {
+                    $this->_constraints[$name]['references'][1] = array_unique(array_merge(
+                        (array)$this->_constraints[$name]['references'][1],
+                        [$attrs['references'][1]]
+                    ));
+                }
                 return $this;
             }
         } else {

+ 45 - 6
src/Filesystem/Folder.php

@@ -53,6 +53,20 @@ class Folder
     const SKIP = 'skip';
 
     /**
+     * Sort mode by name
+     *
+     * @var string
+     */
+    const SORT_NAME = 'name';
+
+    /**
+     * Sort mode by time
+     *
+     * @var string
+     */
+    const SORT_TIME = 'time';
+
+    /**
      * Path to Folder.
      *
      * @var string
@@ -76,6 +90,14 @@ class Folder
     public $mode = 0755;
 
     /**
+     * Functions array to be called depending on the sort type chosen.
+     */
+    protected $_fsorts = [
+        self::SORT_NAME => 'getPathname',
+        self::SORT_TIME => 'getCTime'
+    ];
+
+    /**
      * Holds messages from last method.
      *
      * @var array
@@ -159,13 +181,13 @@ class Folder
      * Returns an array of the contents of the current directory.
      * The returned array holds two arrays: One of directories and one of files.
      *
-     * @param bool $sort Whether you want the results sorted, set this and the sort property
+     * @param string|bool $sort Whether you want the results sorted, set this and the sort property
      *   to false to get unsorted results.
      * @param array|bool $exceptions Either an array or boolean true will not grab dot files
      * @param bool $fullPath True returns the full path
      * @return array Contents of current directory as an array, an empty array on failure
      */
-    public function read($sort = true, $exceptions = false, $fullPath = false)
+    public function read($sort = self::SORT_NAME, $exceptions = false, $fullPath = false)
     {
         $dirs = $files = [];
 
@@ -183,6 +205,12 @@ class Folder
             return [$dirs, $files];
         }
 
+        if (!is_bool($sort) && isset($this->_fsorts[$sort])) {
+            $methodName = $this->_fsorts[$sort];
+        } else {
+            $methodName = $this->_fsorts[self::SORT_NAME];
+        }
+
         foreach ($iterator as $item) {
             if ($item->isDot()) {
                 continue;
@@ -194,16 +222,27 @@ class Folder
             if ($fullPath) {
                 $name = $item->getPathname();
             }
+
             if ($item->isDir()) {
-                $dirs[] = $name;
+                $dirs[$item->{$methodName}()][] = $name;
             } else {
-                $files[] = $name;
+                $files[$item->{$methodName}()][] = $name;
             }
         }
+
         if ($sort || $this->sort) {
-            sort($dirs);
-            sort($files);
+            ksort($dirs);
+            ksort($files);
         }
+
+        if ($dirs) {
+            $dirs = call_user_func_array('array_merge', $dirs);
+        }
+
+        if ($files) {
+            $files = call_user_func_array('array_merge', $files);
+        }
+
         return [$dirs, $files];
     }
 

+ 3 - 0
src/Network/Request.php

@@ -547,6 +547,9 @@ class Request implements ArrayAccess
         if (!empty($ref) && !empty($base)) {
             if ($local && strpos($ref, $base) === 0) {
                 $ref = substr($ref, strlen($base));
+                if (!strlen($ref)) {
+                    $ref = '/';
+                }
                 if ($ref[0] !== '/') {
                     $ref = '/' . $ref;
                 }

+ 7 - 1
src/Network/Session/DatabaseSession.php

@@ -108,7 +108,13 @@ class DatabaseSession implements SessionHandlerInterface
             return $result['data'];
         }
 
-        return stream_get_contents($result['data']);
+        $session = stream_get_contents($result['data']);
+
+        if ($session === false) {
+            return '';
+        }
+        
+        return $session;
     }
 
     /**

+ 2 - 0
src/ORM/Association/SelectableAssociationTrait.php

@@ -16,6 +16,7 @@ namespace Cake\ORM\Association;
 
 use Cake\Database\Expression\IdentifierExpression;
 use Cake\Database\Expression\TupleComparison;
+use Cake\Database\ValueBinder;
 use InvalidArgumentException;
 
 /**
@@ -250,6 +251,7 @@ trait SelectableAssociationTrait
         $filterQuery->mapReduce(null, null, true);
         $filterQuery->formatResults(null, true);
         $filterQuery->contain([], true);
+        $filterQuery->valueBinder(new ValueBinder());
 
         if (!$filterQuery->clause('limit')) {
             $filterQuery->limit(null);

+ 1 - 1
src/ORM/Rule/ExistsIn.php

@@ -92,7 +92,7 @@ class ExistsIn
             $source = $source->source();
         }
 
-        if (!$entity->extract($this->_fields, true)) {
+        if (!$entity->extract($this->_fields, true) && !$entity->isNew()) {
             return true;
         }
 

+ 61 - 0
src/ORM/Rule/ValidCount.php

@@ -0,0 +1,61 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         3.2.9
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\ORM\Rule;
+
+use Cake\Datasource\EntityInterface;
+use Cake\ORM\Association;
+use Cake\Validation\Validation;
+use Countable;
+
+/**
+ * Validates the count of associated records.
+ */
+class ValidCount
+{
+
+    /**
+     * The field to check
+     *
+     * @var array
+     */
+    protected $_field;
+
+    /**
+     * Constructor.
+     *
+     * @param string $field The field to check the count on.
+     */
+    public function __construct($field)
+    {
+        $this->_field = $field;
+    }
+
+    /**
+     * Performs the count check
+     *
+     * @param \Cake\Datasource\EntityInterface $entity The entity from where to extract the fields.
+     * @param array $options Options passed to the check.
+     * @return bool True if successful, else false.
+     */
+    public function __invoke(EntityInterface $entity, array $options)
+    {
+        $value = $entity->{$this->_field};
+        if (!is_array($value) && !$value instanceof Countable) {
+            return false;
+        }
+
+        return Validation::comparison(count($value), $options['operator'], $options['count']);
+    }
+}

+ 24 - 0
src/ORM/RulesChecker.php

@@ -17,6 +17,7 @@ namespace Cake\ORM;
 use Cake\Datasource\RulesChecker as BaseRulesChecker;
 use Cake\ORM\Rule\ExistsIn;
 use Cake\ORM\Rule\IsUnique;
+use Cake\ORM\Rule\ValidCount;
 
 /**
  * ORM flavoured rules checker.
@@ -89,4 +90,27 @@ class RulesChecker extends BaseRulesChecker
         $errorField = is_string($field) ? $field : current($field);
         return $this->_addError(new ExistsIn($field, $table), '_existsIn', compact('errorField', 'message'));
     }
+
+    /**
+     * Validates the count of associated records.
+     *
+     * @param string $field The field to check the count on.
+     * @param int $count The expected count.
+     * @param string $operator The operator for the count comparison.
+     * @param string|null $message The error message to show in case the rule does not pass.
+     * @return callable
+     */
+    public function validCount($field, $count = 0, $operator = '>', $message = null)
+    {
+        if (!$message) {
+            if ($this->_useI18n) {
+                $message = __d('cake', 'The count does not match {0}{1}', [$operator, $count]);
+            } else {
+                $message = sprintf('The count does not match %s%d', $operator, $count);
+            }
+        }
+
+        $errorField = $field;
+        return $this->_addError(new ValidCount($field, $count, $operator), '_validCount', compact('count', 'operator', 'errorField', 'message'));
+    }
 }

+ 1 - 0
src/ORM/Table.php

@@ -35,6 +35,7 @@ use Cake\ORM\Association\HasOne;
 use Cake\ORM\Exception\MissingEntityException;
 use Cake\ORM\Rule\IsUnique;
 use Cake\Utility\Inflector;
+use Cake\Validation\Validation;
 use Cake\Validation\ValidatorAwareTrait;
 use InvalidArgumentException;
 use RuntimeException;

+ 1 - 1
src/Shell/Task/CommandTask.php

@@ -163,7 +163,7 @@ class CommandTask extends Shell
             }
         }
 
-        $return += array_diff($methodNames, $shellMethodNames);
+        $return = array_merge($return, array_diff($methodNames, $shellMethodNames));
         sort($return);
 
         return $return;

+ 5 - 1
src/Validation/Validator.php

@@ -504,11 +504,15 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
      * @param bool|string|callable $when Indicates when the field is allowed to be empty
      * Valid values are true (always), 'create', 'update'. If a callable is passed then
      * the field will allowed to be empty only when the callback returns true.
+     * @param string|null $message The message to show if the field is not
      * @return $this
      */
-    public function allowEmpty($field, $when = true)
+    public function allowEmpty($field, $when = true, $message = null)
     {
         $this->field($field)->isEmptyAllowed($when);
+        if ($message) {
+            $this->_allowEmptyMessages[$field] = $message;
+        }
         return $this;
     }
 

+ 2 - 2
src/View/ViewVarsTrait.php

@@ -70,8 +70,8 @@ trait ViewVarsTrait
     public function createView($viewClass = null)
     {
         $builder = $this->viewBuilder();
-        if ($viewClass === null) {
-            $viewClass = $this->viewClass;
+        if ($viewClass === null && $builder->className() === null) {
+            $builder->className($this->viewClass);
         }
         if ($viewClass) {
             $builder->className($viewClass);

+ 33 - 0
tests/TestCase/Database/Schema/TableTest.php

@@ -304,6 +304,39 @@ class TableTest extends TestCase
     }
 
     /**
+     * Test adding an constraint with an overlapping unique index
+     * >
+     * @return void
+     */
+    public function testAddConstraintOverwriteUniqueIndex()
+    {
+        $table = new Table('articles');
+        $table->addColumn('project_id', [
+            'type' => 'integer',
+            'default' => null,
+            'limit' => 11,
+            'null' => false,
+        ])->addColumn('id', [
+            'type' => 'integer',
+            'autoIncrement' => true,
+            'limit' => 11
+        ])->addColumn('user_id', [
+            'type' => 'integer',
+            'default' => null,
+            'limit' => 11,
+            'null' => false,
+        ])->addConstraint('users_idx', [
+            'type' => 'unique',
+            'columns' => ['project_id', 'user_id']
+        ])->addConstraint('users_idx', [
+            'type' => 'foreign',
+            'references' => ['users', 'project_id', 'id'],
+            'columns' => ['project_id', 'user_id']
+        ]);
+        $this->assertEquals(['users_idx'], $table->constraints());
+    }
+
+    /**
      * Dataprovider for invalid addConstraint calls.
      *
      * @return array

+ 74 - 0
tests/TestCase/Filesystem/FolderTest.php

@@ -1247,4 +1247,78 @@ class FolderTest extends TestCase
         $this->assertFalse(is_dir($folderTwo . '/folderA'));
         $this->assertFalse(file_exists($folderTwo . '/folderA/fileA.php'));
     }
+
+    /**
+     * testSortByTime method
+     *
+     * Verify that the order using modified time is correct.
+     *
+     * @return void
+     */
+    public function testSortByTime()
+    {
+        $Folder = new Folder(TMP . 'tests', true);
+
+        $file2 = new File($Folder->pwd() . DS . 'file_2.tmp');
+        $file2->create();
+
+        sleep(1);
+
+        $file1 = new File($Folder->pwd() . DS . 'file_1.tmp');
+        $file1->create();
+
+        $results = $Folder->find('.*', Folder::SORT_TIME);
+
+        $this->assertSame(['file_2.tmp', 'file_1.tmp'], $results);
+    }
+
+    /**
+     * testSortByTime2 method
+     *
+     * Verify that the order using modified time is correct.
+     *
+     * @return void
+     */
+    public function testSortByTime2()
+    {
+        $Folder = new Folder(TMP . 'tests', true);
+
+        $fileA = new File($Folder->pwd() . DS . 'a.txt');
+        $fileA->create();
+
+        $fileC = new File($Folder->pwd() . DS . 'c.txt');
+        $fileC->create();
+
+        sleep(1);
+
+        $fileB = new File($Folder->pwd() . DS . 'b.txt');
+        $fileB->create();
+
+        $results = $Folder->find('.*', Folder::SORT_TIME);
+
+        $this->assertSame(['a.txt', 'c.txt', 'b.txt'], $results);
+    }
+
+    /**
+     * Verify that the order using name is correct.
+     */
+    public function testSortByName()
+    {
+        $Folder = new Folder(TMP . 'tests', true);
+
+        $fileA = new File($Folder->pwd() . DS . 'a.txt');
+        $fileA->create();
+
+        $fileC = new File($Folder->pwd() . DS . 'c.txt');
+        $fileC->create();
+
+        sleep(1);
+
+        $fileB = new File($Folder->pwd() . DS . 'b.txt');
+        $fileB->create();
+
+        $results = $Folder->find('.*', Folder::SORT_NAME);
+
+        $this->assertSame(['a.txt', 'b.txt', 'c.txt'], $results);
+    }
 }

+ 8 - 0
tests/TestCase/Network/RequestTest.php

@@ -591,6 +591,14 @@ class RequestTest extends TestCase
         $result = $request->referer(true);
         $this->assertSame('/some/path', $result);
 
+        $request->env('HTTP_REFERER', Configure::read('App.fullBaseUrl') . '/0');
+        $result = $request->referer(true);
+        $this->assertSame('/0', $result);
+
+        $request->env('HTTP_REFERER', Configure::read('App.fullBaseUrl') . '/');
+        $result = $request->referer(true);
+        $this->assertSame('/', $result);
+
         $request->env('HTTP_REFERER', Configure::read('App.fullBaseUrl') . '/some/path');
         $result = $request->referer(false);
         $this->assertSame(Configure::read('App.fullBaseUrl') . '/some/path', $result);

+ 29 - 0
tests/TestCase/ORM/Association/HasManyTest.php

@@ -20,6 +20,7 @@ use Cake\Database\Expression\TupleComparison;
 use Cake\Database\IdentifierQuoter;
 use Cake\Database\TypeMap;
 use Cake\Datasource\ConnectionManager;
+use Cake\ORM\Association;
 use Cake\ORM\Association\HasMany;
 use Cake\ORM\Entity;
 use Cake\ORM\TableRegistry;
@@ -536,6 +537,34 @@ class HasManyTest extends TestCase
     }
 
     /**
+     * Test that the ValueBinder is reset when using strategy = Association::STRATEGY_SUBQUERY
+     *
+     * @return void
+     */
+    public function testValueBinderUpdateOnSubQueryStrategy()
+    {
+        $Authors = TableRegistry::get('Authors');
+        $Authors->hasMany('Articles', [
+            'strategy' => Association::STRATEGY_SUBQUERY
+        ]);
+
+        $query = $Authors->find();
+        $authorsAndArticles = $query
+            ->select([
+                'id',
+                'slug' => $query->func()->concat([
+                    '---',
+                    'name' => 'identifier'
+                ])
+            ])
+            ->contain('Articles')
+            ->where(['name' => 'mariano'])
+            ->first();
+
+        $this->assertCount(2, $authorsAndArticles->get('articles'));
+    }
+
+    /**
      * Assertion method for order by clause contents.
      *
      * @param array $expected The expected join clause.

+ 81 - 3
tests/TestCase/ORM/RulesCheckerIntegrationTest.php

@@ -29,7 +29,10 @@ class RulesCheckerIntegrationTest extends TestCase
      *
      * @var array
      */
-    public $fixtures = ['core.articles', 'core.articles_tags', 'core.authors', 'core.tags', 'core.special_tags'];
+    public $fixtures = [
+        'core.articles', 'core.articles_tags', 'core.authors', 'core.tags',
+        'core.special_tags', 'core.categories'
+    ];
 
     /**
      * Tear down
@@ -472,7 +475,7 @@ class RulesCheckerIntegrationTest extends TestCase
     /**
      * ExistsIn uses the schema to verify that nullable fields are ok.
      *
-     * @return
+     * @return void
      */
     public function testExistsInNullValue()
     {
@@ -491,9 +494,32 @@ class RulesCheckerIntegrationTest extends TestCase
     }
 
     /**
+     * Test ExistsIn on not dirty field in new Entity
+     *
+     * @return void
+     */
+    public function testExistsInNotNullValue()
+    {
+        $entity = new Entity([
+            'name' => 'A Category',
+        ]);
+
+        $table = TableRegistry::get('Categories');
+        $table->belongsTo('Categories', [
+            'foreignKey' => 'parent_id',
+            'bindingKey' => 'id',
+        ]);
+        $rules = $table->rulesChecker();
+        $rules->add($rules->existsIn('parent_id', 'Categories'));
+
+        $this->assertFalse($table->save($entity));
+        $this->assertEquals(['_existsIn' => 'This value does not exist'], $entity->errors('parent_id'));
+    }
+
+    /**
      * Tests exists in uses the bindingKey of the association
      *
-     * @return
+     * @return void
      */
     public function testExistsInWithBindingKey()
     {
@@ -941,4 +967,56 @@ class RulesCheckerIntegrationTest extends TestCase
         $this->assertFalse($table->save($entity));
         $this->assertEquals(['_existsIn' => 'This value does not exist'], $entity->errors('author_id'));
     }
+
+    /**
+     * Tests that associated items have a count of X.
+     *
+     * @return void
+     */
+    public function testCountOfAssociatedItems()
+    {
+        $entity = new \Cake\ORM\Entity([
+            'title' => 'A Title',
+            'body' => 'A body'
+        ]);
+        $entity->tags = [
+            new \Cake\ORM\Entity([
+                'name' => 'Something New'
+            ]),
+            new \Cake\ORM\Entity([
+                'name' => '100'
+            ])
+        ];
+
+        TableRegistry::get('ArticlesTags');
+
+        $table = TableRegistry::get('articles');
+        $table->belongsToMany('tags');
+
+        $rules = $table->rulesChecker();
+        $rules->add($rules->validCount('tags', 3));
+
+        $this->assertFalse($table->save($entity));
+        $this->assertEquals($entity->errors(), [
+            'tags' => [
+                '_validCount' => 'The count does not match >3'
+            ]
+        ]);
+
+        // Testing that undesired types fail
+        $entity->tags = null;
+        $this->assertFalse($table->save($entity));
+
+        $entity->tags = new \stdClass();
+        $this->assertFalse($table->save($entity));
+
+        $entity->tags = 'string';
+        $this->assertFalse($table->save($entity));
+
+        $entity->tags = 123456;
+        $this->assertFalse($table->save($entity));
+
+        $entity->tags = 0.512;
+        $this->assertFalse($table->save($entity));
+    }
 }

+ 2 - 2
tests/TestCase/Shell/CompletionShellTest.php

@@ -203,7 +203,7 @@ class CompletionShellTest extends TestCase
         $this->Shell->runCommand(['subcommands', 'app.sample']);
         $output = $this->out->output;
 
-        $expected = "derp sample\n";
+        $expected = "derp load sample\n";
         $this->assertTextEquals($expected, $output);
     }
 
@@ -261,7 +261,7 @@ class CompletionShellTest extends TestCase
         $this->Shell->runCommand(['subcommands', 'sample']);
         $output = $this->out->output;
 
-        $expected = "derp sample\n";
+        $expected = "derp load sample\n";
         $this->assertTextEquals($expected, $output);
     }
 

+ 15 - 1
tests/TestCase/Validation/ValidatorTest.php

@@ -712,7 +712,21 @@ class ValidatorTest extends TestCase
     }
 
     /**
-     * Tests custom error mesages generated when a field is not allowed to be empty
+     * Tests custom error messages generated when a field is allowed to be empty
+     *
+     * @return void
+     */
+    public function testCustomErrorsWithAllowedEmpty()
+    {
+        $validator = new Validator;
+        $validator->allowEmpty('title', false, 'Custom message');
+        $errors = $validator->errors(['title' => null]);
+        $expected = ['title' => ['_empty' => 'Custom message']];
+        $this->assertEquals($expected, $errors);
+    }
+
+    /**
+     * Tests custom error messages generated when a field is not allowed to be empty
      *
      * @return void
      */

+ 38 - 0
tests/TestCase/View/ViewVarsTraitTest.php

@@ -189,6 +189,44 @@ class ViewVarsTraitTest extends TestCase
     }
 
     /**
+     * test that viewClass is used to create the view
+     *
+     * @return void
+     */
+    public function testCreateViewViewClass()
+    {
+        $this->subject->viewClass = 'Json';
+        $view = $this->subject->createView();
+        $this->assertInstanceof('Cake\View\JsonView', $view);
+    }
+
+    /**
+     * test that viewBuilder settings override viewClass
+     *
+     * @return void
+     */
+    public function testCreateViewViewBuilder()
+    {
+        $this->subject->viewBuilder()->className('Xml');
+        $this->subject->viewClass = 'Json';
+        $view = $this->subject->createView();
+        $this->assertInstanceof('Cake\View\XmlView', $view);
+    }
+
+    /**
+     * test that parameters beats viewBuilder() and viewClass
+     *
+     * @return void
+     */
+    public function testCreateViewParameter()
+    {
+        $this->subject->viewBuilder()->className('View');
+        $this->subject->viewClass = 'Json';
+        $view = $this->subject->createView('Xml');
+        $this->assertInstanceof('Cake\View\XmlView', $view);
+    }
+
+    /**
      * test createView() throws exception if view class cannot be found
      *
      * @expectedException \Cake\View\Exception\MissingViewException

+ 1 - 1
tests/test_app/TestApp/Shell/SampleShell.php

@@ -26,7 +26,7 @@ use Cake\Console\Shell;
 class SampleShell extends Shell
 {
 
-    public $tasks = ['Sample'];
+    public $tasks = ['Sample', 'Load'];
 
     /**
      * main method