]> git.mxchange.org Git - friendica.git/blobdiff - doc/AddonStorageBackend.md
Merge pull request #8179 from MrPetovan/bug/notices
[friendica.git] / doc / AddonStorageBackend.md
index d42c8bbbd7f7aadd87e1804c8ad0fcb1bdbb2919..17c3f0414077ee1dfb4d8a800427aea46372e39c 100644 (file)
@@ -17,22 +17,24 @@ namespace Friendica\Model\Storage;
 ```php
 interface IStorage
 {
 ```php
 interface IStorage
 {
-       public static function get($ref);
-       public static function put($data, $ref = "");
-       public static function delete($ref);
-       public static function getOptions();
-       public static function saveOptions($data);
+       public function get(string $reference);
+       public function put(string $data, string $reference = '');
+       public function delete(string $reference);
+       public function getOptions();
+       public function saveOptions(array $data);
+       public function __toString();
+       public static function getName();
 }
 ```
 
 }
 ```
 
-- `get($ref)` returns data pointed by `$ref`
-- `put($data, $ref)` saves data in `$data` to position `$ref`, or a new position if `$ref` is empty.
-- `delete($ref)` delete data pointed by `$ref`
+- `get(string $reference)` returns data pointed by `$reference`
+- `put(string $data, string $reference)` saves data in `$data` to position `$reference`, or a new position if `$reference` is empty.
+- `delete(string $reference)` delete data pointed by `$reference`
 
 Each storage backend can have options the admin can set in admin page.
 
 - `getOptions()` returns an array with details about each option to build the interface.
 
 Each storage backend can have options the admin can set in admin page.
 
 - `getOptions()` returns an array with details about each option to build the interface.
-- `saveOptions($data)` get `$data` from admin page, validate it and save it.
+- `saveOptions(array $data)` get `$data` from admin page, validate it and save it.
 
 The array returned by `getOptions()` is defined as:
 
 
 The array returned by `getOptions()` is defined as:
 
@@ -84,11 +86,38 @@ See doxygen documentation of `IStorage` interface for details about each method.
 
 Each backend must be registered in the system when the plugin is installed, to be aviable.
 
 
 Each backend must be registered in the system when the plugin is installed, to be aviable.
 
-`Friendica\Core\StorageManager::register($name, $class)` is used to register the backend class.
-The `$name` must be univocal and will be shown to admin.
+`DI::facStorage()->register(string $class)` is used to register the backend class.
 
 When the plugin is uninstalled, registered backends must be unregistered using
 
 When the plugin is uninstalled, registered backends must be unregistered using
-`Friendica\Core\StorageManager::unregister($class)`.
+`DI::facStorage()->unregister(string $class)`.
+
+You have to register a new hook in your addon, listening on `storage_instance(App $a, array $data)`.
+In case `$data['name']` is your storage class name, you have to instance a new instance of your `Friendica\Model\Storage\IStorage` class.
+Set the instance of your class as `$data['storage']` to pass it back to the backend.
+
+This is necessary because it isn't always clear, if you need further construction arguments.
+
+## Adding tests
+
+**Currently testing is limited to core Friendica only, this shows theoretically how tests should work in the future**
+
+Each new Storage class should be added to the test-environment at [Storage Tests](https://github.com/friendica/friendica/tree/develop/tests/src/Model/Storage/).
+
+Add a new test class which's naming convention is `StorageClassTest`, which extend the `StorageTest` in the same directory.
+
+Override the two necessary instances:
+```php
+use Friendica\Model\Storage\IStorage;
+
+abstract class StorageTest 
+{
+       // returns an instance of your newly created storage class
+       abstract protected function getInstance();
+
+       // Assertion for the option array you return for your new StorageClass
+       abstract protected function assertOption(IStorage $storage);
+} 
+```
 
 ## Example
 
 
 ## Example
 
@@ -107,65 +136,96 @@ namespace Friendica\Addon\samplestorage;
 
 use Friendica\Model\Storage\IStorage;
 
 
 use Friendica\Model\Storage\IStorage;
 
-use Friendica\Core\Config;
+use Friendica\Core\Config\IConfig;
 use Friendica\Core\L10n;
 
 class SampleStorageBackend implements IStorage
 {
 use Friendica\Core\L10n;
 
 class SampleStorageBackend implements IStorage
 {
-       public static function get($ref)
+       const NAME = 'Sample Storage';
+
+       /** @var IConfig */
+       private $config;
+       /** @var L10n */
+       private $l10n;
+
+       /**
+         * SampleStorageBackend constructor.
+         * @param IConfig $config The configuration of Friendica
+         *                                                                       
+         * You can add here every dynamic class as dependency you like and add them to a private field
+         * Friendica automatically creates these classes and passes them as argument to the constructor                                                                           
+         */
+       public function __construct(IConfig $config, L10n $l10n) 
        {
        {
-               // we return alwais the same image data. Which file we load is defined by
+               $this->config = $config;
+               $this->l10n   = $l10n;
+       }
+
+       public function get(string $reference)
+       {
+               // we return always the same image data. Which file we load is defined by
                // a config key
                // a config key
-               $filename = Config::get("storage", "samplestorage", "sample.jpg");
+               $filename = $this->config->get('storage', 'samplestorage', 'sample.jpg');
                return file_get_contents($filename);
        }
        
                return file_get_contents($filename);
        }
        
-       public static function put($data, $ref = "")
+       public function put(string $data, string $reference = '')
        {
        {
-               if ($ref === "") {
-                       $ref = "sample";
+               if ($reference === '') {
+                       $reference = 'sample';
                }
                // we don't save $data !
                }
                // we don't save $data !
-               return $ref;
+               return $reference;
        }
        
        }
        
-       public static function delete($ref)
+       public function delete(string $reference)
        {
                // we pretend to delete the data
                return true;
        }
        
        {
                // we pretend to delete the data
                return true;
        }
        
-       public static function getOptions()
+       public function getOptions()
        {
        {
-               $filename = Config::get("storage", "samplestorage", "sample.jpg");
+               $filename = $this->config->get('storage', 'samplestorage', 'sample.jpg');
                return [
                return [
-                       "filename" => [
-                               "input",        // will use a simple text input
-                               L10n::t("The file to return"),  // the label
+                       'filename' => [
+                               'input',        // will use a simple text input
+                               $this->l10n->t('The file to return'),   // the label
                                $filename,      // the current value
                                $filename,      // the current value
-                               L10n::t("Enter the path to a file"), // the help text
-                               // no extra data for "input" type..
+                               $this->l10n->t('Enter the path to a file'), // the help text
+                               // no extra data for 'input' type..
+                       ],
                ];
        }
        
                ];
        }
        
-       public static function saveOptions($data)
+       public function saveOptions(array $data)
        {
                // the keys in $data are the same keys we defined in getOptions()
        {
                // the keys in $data are the same keys we defined in getOptions()
-               $newfilename = trim($data["filename"]);
+               $newfilename = trim($data['filename']);
                
                // this function should always validate the data.
                // in this example we check if file exists
                if (!file_exists($newfilename)) {
                        // in case of error we return an array with
                
                // this function should always validate the data.
                // in this example we check if file exists
                if (!file_exists($newfilename)) {
                        // in case of error we return an array with
-                       // ["optionname" => "error message"]
-                       return ["filename" => "The file doesn't exists"];
+                       // ['optionname' => 'error message']
+                       return ['filename' => 'The file doesn\'t exists'];
                }
                
                }
                
-               Config::set("storage", "samplestorage", $newfilename);
+               $this->config->set('storage', 'samplestorage', $newfilename);
                
                // no errors, return empty array
                return [];
        }
                
                // no errors, return empty array
                return [];
        }
+
+       public function __toString()
+       {
+               return self::NAME;
+       }
+
+       public static function getName()
+       {
+               return self::NAME;
+       }
 }
 ```
 
 }
 ```
 
@@ -182,23 +242,59 @@ The file is `addon/samplestorage/samplestorage.php`
  * Author: Alice <https://alice.social/~alice>
  */
 
  * Author: Alice <https://alice.social/~alice>
  */
 
-use Friendica\Core\StorageManager;
 use Friendica\Addon\samplestorage\SampleStorageBackend;
 use Friendica\Addon\samplestorage\SampleStorageBackend;
+use Friendica\DI;
 
 function samplestorage_install()
 {
        // on addon install, we register our class with name "Sample Storage".
        // note: we use `::class` property, which returns full class name as string
        // this save us the problem of correctly escape backslashes in class name
 
 function samplestorage_install()
 {
        // on addon install, we register our class with name "Sample Storage".
        // note: we use `::class` property, which returns full class name as string
        // this save us the problem of correctly escape backslashes in class name
-       StorageManager::register("Sample Storage", SampleStorageBackend::class);
+       DI::storageManager()->register(SampleStorageBackend::class);
 }
 
 function samplestorage_unistall()
 {
        // when the plugin is uninstalled, we unregister the backend.
 }
 
 function samplestorage_unistall()
 {
        // when the plugin is uninstalled, we unregister the backend.
-       StorageManager::unregister("Sample Storage");
+       DI::storageManager()->unregister(SampleStorageBackend::class);
+}
+
+function samplestorage_storage_instance(\Friendica\App $a, array $data)
+{
+    if ($data['name'] === SampleStorageBackend::getName()) {
+    // instance a new sample storage instance and pass it back to the core for usage
+        $data['storage'] = new SampleStorageBackend(DI::config(), DI::l10n(), DI::cache());
+    }
 }
 ```
 
 }
 ```
 
+**Theoretically - until tests for Addons are enabled too - create a test class with the name `addon/tests/SampleStorageTest.php`:
 
 
+```php
+use Friendica\Model\Storage\IStorage;
+use Friendica\Test\src\Model\Storage\StorageTest;
+
+class SampleStorageTest extends StorageTest 
+{
+       // returns an instance of your newly created storage class
+       protected function getInstance()
+       {
+               // create a new SampleStorageBackend instance with all it's dependencies
+               // Have a look at DatabaseStorageTest or FilesystemStorageTest for further insights
+               return new SampleStorageBackend();
+       }
 
 
+       // Assertion for the option array you return for your new StorageClass
+       protected function assertOption(IStorage $storage)
+       {
+               $this->assertEquals([
+                       'filename' => [
+                               'input',
+                               'The file to return',
+                               'sample.jpg',
+                               'Enter the path to a file'
+                       ],
+               ], $storage->getOptions());
+       }
+} 
+```