[
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the\n// README at: https://github.com/devcontainers/templates/tree/main/src/php\n{\n\t\"name\": \"FM Elfinder Bundle Dev Container\",\n\t// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile\n\t\"image\": \"mcr.microsoft.com/devcontainers/php:0-8.2\",\n\n\t// Features to add to the dev container. More info: https://containers.dev/features.\n\t// \"features\": {},\n\n\t// Configure tool-specific properties.\n\t\"customizations\": {\n\t\t// Configure properties specific to VS Code.\n\t\t\"vscode\": {\n\t\t\t\"settings\": {},\n\t\t\t\"extensions\": [\n\t\t\t\t\"streetsidesoftware.code-spell-checker\"\n\t\t\t]\n\t\t}\n\t}\n\n\t// Use 'postCreateCommand' to run commands after the container is created.\n\t// \"postCreateCommand\": \"sudo chmod a+x \\\"$(pwd)\\\" && sudo rm -rf /var/www/html && sudo ln -s \\\"$(pwd)\\\" /var/www/html\"\n\n\t// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.\n\t// \"remoteUser\": \"root\"\n}"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\n\n---\n\n**Describe the bug**\nExplain what you wanted to do and the wrong result you got.\n\n**To Reproduce**\nSteps to reproduce this error and also, the FMElfinderBundle version used.\n\n**(OPTIONAL) Additional context**\nIf they are useful, include logs, code samples, screenshots, etc.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\n\n---\n\n**Short description of what this feature will allow to do:**\n_(One short paragraph is enough)_\n\n**Example of how to use this feature**\n_(Show some PHP code and/or YAML config explaining how to use this feature in a real app)_\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nThanks for your contribution! If you are proposing a new feature that is complex,\nplease open an issue first so we can discuss it.\n\nNote: all your contributions adhere implicitly to the MIT license\n-->\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: composer\n  directory: \"/\"\n  schedule:\n    interval: weekly\n  open-pull-requests-limit: 10\n"
  },
  {
    "path": ".github/workflows/test.yaml",
    "content": "# OS: Linux; Symfony: latest stable; PHP: all the commonly used versions supported by this bundle\nname: \"Tests\"\n\non:\n  pull_request:\n  push:\n    branches:\n      - 'main'\n\nenv:\n  fail-fast: true\n\njobs:\n  tests:\n    name: \"PHP ${{ matrix.php-version }}\"\n    runs-on: 'ubuntu-latest'\n    continue-on-error: false\n    strategy:\n      matrix:\n        php-version: ['8.1', '8.2', '8.3', '8.4', '8.5']\n    steps:\n      - name: 'Checkout code'\n        uses: actions/checkout@v4\n\n      - name: 'Install PHP with extensions'\n        uses: shivammathur/setup-php@2.27.1\n        with:\n          coverage: xdebug\n          php-version: ${{ matrix.php-version }}\n          tools: composer:v2\n          extensions: mbstring, intl\n          ini-values: date.timezone=UTC\n\n      - name: 'Install project dependencies'\n        run: |\n          composer global config --no-plugins allow-plugins.symfony/flex true\n          composer global require --no-progress --no-scripts --no-plugins symfony/flex\n          composer update --no-interaction --prefer-dist --optimize-autoloader --prefer-stable\n          vendor/bin/simple-phpunit install\n      - name: 'Run tests'\n        run: XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-clover ./coverage.xml\n      - name: codecov\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          files: ./coverage.xml\n          verbose: true # optional (default = false)"
  },
  {
    "path": ".gitignore",
    "content": "composer.lock\nTests/cache\nTests/log\nTests/Functional/cache\nTests/Functional/log\nvendor\n.php-cs-fixer.cache\nclover.xml\n.vscode\n.phpunit.result.cache\n###> symfony/framework-bundle ###\n/.env.local\n/.env.local.php\n/.env.*.local\n/config/secrets/prod/prod.decrypt.private.php\n/public/bundles/\n/var/\n/vendor/\n###< symfony/framework-bundle ###\n/.phpunit.cache\n/phpunit.xml\n/bin"
  },
  {
    "path": ".php-cs-fixer.php",
    "content": "<?php\n\nreturn (new PhpCsFixer\\Config())\n    ->setRiskyAllowed(false)\n    ->setRules([\n        '@Symfony' => true,\n        '@PHP80Migration' => true,\n        'array_syntax' => ['syntax' => 'short'],\n        'combine_consecutive_unsets' => true,\n        // one should use PHPUnit methods to set up expected exception instead of annotations\n        'general_phpdoc_annotation_remove' => [\n            'annotations' => [\n                'author',\n                'package',\n                'expectedException',\n                'expectedExceptionMessage',\n                'expectedExceptionMessageRegExp',\n            ],\n        ],\n        'function_typehint_space' => false,\n        'no_empty_phpdoc' => true,\n        'global_namespace_import' => ['import_classes' => true, 'import_functions' => true, 'import_constants' => true],\n        'no_superfluous_phpdoc_tags' => ['allow_mixed' => false, 'allow_unused_params' => false],\n        'phpdoc_line_span' => ['property' => 'single'],\n        'heredoc_to_nowdoc' => true,\n        'list_syntax' => ['syntax' => 'short'],\n        'blank_line_before_statement' => ['statements' => ['if', 'break', 'continue', 'declare', 'return', 'throw', 'try', 'yield']],\n        'no_extra_blank_lines' => [\n            'tokens' => [\n                'break',\n                'continue',\n                'extra',\n                'return',\n                'throw',\n                'use',\n                'parenthesis_brace_block',\n                'square_brace_block',\n                'curly_brace_block',\n            ],\n        ],\n        'echo_tag_syntax' => true,\n        'method_argument_space' => false,\n        'no_useless_else' => true,\n        'no_useless_return' => true,\n        'ordered_class_elements' => true,\n        'ordered_imports' => ['sort_algorithm' => 'alpha', 'imports_order' => ['const', 'class', 'function']],\n        'php_unit_test_class_requires_covers' => true,\n        'phpdoc_align' => [\n            'tags' => [\n                'param', 'return', 'throws', 'type', 'var'\n            ],\n        ],\n        'phpdoc_add_missing_param_annotation' => true,\n        'phpdoc_order' => true,\n        'phpdoc_no_alias_tag' => ['replacements' => ['link' => 'website']],\n        'phpdoc_summary' => false,\n        'phpdoc_to_comment' => false,\n        'phpdoc_types_order' => false, // breaks psalm-specific notation sometimes!\n        'semicolon_after_instruction' => true,\n        'single_blank_line_at_eof' => true,\n        'single_line_throw' => false,\n        'types_spaces' => false,\n        'binary_operator_spaces' => [\n            'default' => 'single_space',\n            'operators' => [\n                '=' => 'align_single_space_minimal',\n                '-=' => 'align_single_space_minimal',\n                '+=' => 'align_single_space_minimal',\n                '=>' => 'align_single_space_minimal',\n                '===' => null,\n                '??=' => 'align_single_space_minimal',\n            ],\n        ],\n        'concat_space' => [\n            'spacing' => 'one',\n        ],\n        'operator_linebreak' => ['only_booleans' => true, 'position' => 'end'],\n        'yoda_style' => false,\n    ])\n    ->setFinder(\n        PhpCsFixer\\Finder::create()\n            ->in(__DIR__ . '/src')\n    );\n"
  },
  {
    "path": ".symfony.bundle.yaml",
    "content": "branches: [\"main\"]\nmaintained_branches: [\"main\"]\ncurrent_branch: \"main\"\ndev_branch: \"main\"\ndev_branch_alias: \"12.x\"\ndoc_dir: \"docs/\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "#\n\n## [12.1.2](https://github.com/helios-ag/FMElfinderBundle/tree/12.1.2) (2022-01-21)\n\n**Merged pull requests:**\n\n- Fix elfinder\\_tinymce\\_init4 duplicate definition [\\#473](https://github.com/helios-ag/FMElfinderBundle/pull/473)\n\n## [12.1.1](https://github.com/helios-ag/FMElfinderBundle/tree/12.1.1) (2022-01-21)\n\n**Closed issues:**\n\n- ElFinderType in EasyAdmin 4.x \\(with Symfony 6.x\\) form shows only a text field [\\#472](https://github.com/helios-ag/FMElfinderBundle/issues/472)\n- Symfony 6.0 [\\#464](https://github.com/helios-ag/FMElfinderBundle/issues/464)\n- Deprecation in Symfony 5.4: \"...ConfigurationInterface::getConfigTreeBuilder\\(\\)\" might add \"TreeBuilder\" as a native return type declaration [\\#461](https://github.com/helios-ag/FMElfinderBundle/issues/461)\n- is can  cdn  config? [\\#460](https://github.com/helios-ag/FMElfinderBundle/issues/460)\n- Easyadmin CollectionField not working [\\#457](https://github.com/helios-ag/FMElfinderBundle/issues/457)\n- Deprecation \\(Since Symfony 5.3\\) : RegisterListenersPass configuration [\\#456](https://github.com/helios-ag/FMElfinderBundle/issues/456)\n\n## [12.1](https://github.com/helios-ag/FMElfinderBundle/tree/12.1) (2022-01-09)\n\n**Closed issues:**\n\n- Considering tagging a new release [\\#463](https://github.com/helios-ag/FMElfinderBundle/issues/463)\n- Directory removed in public after composer install [\\#459](https://github.com/helios-ag/FMElfinderBundle/issues/459)\n- Error after all steps \\(Symfony 5\\) [\\#458](https://github.com/helios-ag/FMElfinderBundle/issues/458)\n\n**Merged pull requests:**\n\n- Allow SF6 [\\#471](https://github.com/helios-ag/FMElfinderBundle/pull/471)\n- Directly inject twig [\\#469](https://github.com/helios-ag/FMElfinderBundle/pull/469)\n- Added symfony 6 to deps [\\#466](https://github.com/helios-ag/FMElfinderBundle/pull/466)\n\n## [11.0](https://github.com/helios-ag/FMElfinderBundle/tree/11.0) (2021-08-29)\n\n**Closed issues:**\n\n- Support implementation of a custom driver class [\\#449](https://github.com/helios-ag/FMElfinderBundle/issues/449)\n- Lost logged user [\\#446](https://github.com/helios-ag/FMElfinderBundle/issues/446)\n- Duplicated Bucket Name in Endpoint URL [\\#439](https://github.com/helios-ag/FMElfinderBundle/issues/439)\n- Unable to run elfinder:install via absolute path [\\#431](https://github.com/helios-ag/FMElfinderBundle/issues/431)\n- Pass formTypeId to custom editor [\\#420](https://github.com/helios-ag/FMElfinderBundle/issues/420)\n- Browser hangs when opening folder in form editor [\\#413](https://github.com/helios-ag/FMElfinderBundle/issues/413)\n- Very slow for large data [\\#410](https://github.com/helios-ag/FMElfinderBundle/issues/410)\n- Symfony5 - elfinder:install [\\#407](https://github.com/helios-ag/FMElfinderBundle/issues/407)\n\n**Merged pull requests:**\n\n- Tinymce5 [\\#455](https://github.com/helios-ag/FMElfinderBundle/pull/455)\n- Symfony bundle config [\\#454](https://github.com/helios-ag/FMElfinderBundle/pull/454)\n- Use github CI [\\#452](https://github.com/helios-ag/FMElfinderBundle/pull/452)\n- Replaced deprecated calls [\\#451](https://github.com/helios-ag/FMElfinderBundle/pull/451)\n- Improved error message for custom adapter service. [\\#448](https://github.com/helios-ag/FMElfinderBundle/pull/448)\n- Fix typos in elfinder\\_type.html.twig [\\#447](https://github.com/helios-ag/FMElfinderBundle/pull/447)\n- Upgrade to GitHub-native Dependabot [\\#440](https://github.com/helios-ag/FMElfinderBundle/pull/440)\n- Add missing constant [\\#437](https://github.com/helios-ag/FMElfinderBundle/pull/437)\n\n## [10.1](https://github.com/helios-ag/FMElfinderBundle/tree/10.1) (2021-01-29)\n\n**Closed issues:**\n\n- PHP8.0 and Symfony 5.2 [\\#432](https://github.com/helios-ag/FMElfinderBundle/issues/432)\n- Cross-Site Scripting reflected [\\#430](https://github.com/helios-ag/FMElfinderBundle/issues/430)\n- Symfony 4.4 - elfinder:install [\\#427](https://github.com/helios-ag/FMElfinderBundle/issues/427)\n- Failed to load ressource elfinder.main.js:1 Symfony 5 [\\#426](https://github.com/helios-ag/FMElfinderBundle/issues/426)\n- Good syntaxe for README [\\#421](https://github.com/helios-ag/FMElfinderBundle/issues/421)\n- relative\\_path missing from doc [\\#417](https://github.com/helios-ag/FMElfinderBundle/issues/417)\n- Styling issue & missing buttons/text [\\#416](https://github.com/helios-ag/FMElfinderBundle/issues/416)\n- More one home folder [\\#412](https://github.com/helios-ag/FMElfinderBundle/issues/412)\n- Add elfinder:install command to composer scripts via flex recipe [\\#408](https://github.com/helios-ag/FMElfinderBundle/issues/408)\n- ElFinderType in EasyAdmin [\\#406](https://github.com/helios-ag/FMElfinderBundle/issues/406)\n- Missing upgrade notes? [\\#405](https://github.com/helios-ag/FMElfinderBundle/issues/405)\n- Blank page displayed [\\#402](https://github.com/helios-ag/FMElfinderBundle/issues/402)\n- Can't install assets [\\#401](https://github.com/helios-ag/FMElfinderBundle/issues/401)\n- baseUrl configuration [\\#397](https://github.com/helios-ag/FMElfinderBundle/issues/397)\n- Combine SF roles and FMElfinderBundle [\\#393](https://github.com/helios-ag/FMElfinderBundle/issues/393)\n- Unable to make elfinder installing and working on Symfony 4.4 [\\#389](https://github.com/helios-ag/FMElfinderBundle/issues/389)\n- Image compression [\\#380](https://github.com/helios-ag/FMElfinderBundle/issues/380)\n- Symfony 5 support [\\#377](https://github.com/helios-ag/FMElfinderBundle/issues/377)\n\n**Merged pull requests:**\n\n- Added option to select docroot [\\#436](https://github.com/helios-ag/FMElfinderBundle/pull/436)\n- Apply fixes from StyleCI [\\#435](https://github.com/helios-ag/FMElfinderBundle/pull/435)\n- Symfony 5.2 and PHP 8.0 [\\#433](https://github.com/helios-ag/FMElfinderBundle/pull/433)\n- Apply fixes from StyleCI [\\#425](https://github.com/helios-ag/FMElfinderBundle/pull/425)\n- Pass formTypeId to custom editor [\\#424](https://github.com/helios-ag/FMElfinderBundle/pull/424)\n- Fix elfinder:install root dir [\\#418](https://github.com/helios-ag/FMElfinderBundle/pull/418)\n- Apply fixes from StyleCI [\\#415](https://github.com/helios-ag/FMElfinderBundle/pull/415)\n- More one home folder [\\#411](https://github.com/helios-ag/FMElfinderBundle/pull/411)\n- Add support for the quarantine parameter [\\#403](https://github.com/helios-ag/FMElfinderBundle/pull/403)\n- Update events-listeners-subscribers.md [\\#400](https://github.com/helios-ag/FMElfinderBundle/pull/400)\n- Fix Yaml syntax issue [\\#398](https://github.com/helios-ag/FMElfinderBundle/pull/398)\n\n## [10.0.4](https://github.com/helios-ag/FMElfinderBundle/tree/10.0.4) (2020-02-11)\n\n**Closed issues:**\n\n- AWS S3 upload issue [\\#388](https://github.com/helios-ag/FMElfinderBundle/issues/388)\n- chunk upload feature [\\#358](https://github.com/helios-ag/FMElfinderBundle/issues/358)\n\n**Merged pull requests:**\n\n- yml extensions changed to yaml [\\#396](https://github.com/helios-ag/FMElfinderBundle/pull/396)\n- Setting MIME reply to text/javascript for mainJS [\\#395](https://github.com/helios-ag/FMElfinderBundle/pull/395)\n- Using asset\\(\\) to ensure the URL is correct \\(if website not deployed under /\\) [\\#394](https://github.com/helios-ag/FMElfinderBundle/pull/394)\n\n## [10.0.3](https://github.com/helios-ag/FMElfinderBundle/tree/10.0.3) (2020-01-26)\n\n**Closed issues:**\n\n- S3 Thumbnail issue [\\#369](https://github.com/helios-ag/FMElfinderBundle/issues/369)\n- Retrieve file name on remove command [\\#298](https://github.com/helios-ag/FMElfinderBundle/issues/298)\n- Error when selecting a file [\\#290](https://github.com/helios-ag/FMElfinderBundle/issues/290)\n- Is there any way to disabled/remove some actions based on the user role [\\#289](https://github.com/helios-ag/FMElfinderBundle/issues/289)\n- Upload failure on symfony 2.7.\\* [\\#272](https://github.com/helios-ag/FMElfinderBundle/issues/272)\n\n**Merged pull requests:**\n\n- changed path in require and added maxconn option [\\#392](https://github.com/helios-ag/FMElfinderBundle/pull/392)\n\n## [10.0.2](https://github.com/helios-ag/FMElfinderBundle/tree/10.0.2) (2020-01-25)\n\n**Merged pull requests:**\n\n- Fixed description for aws [\\#391](https://github.com/helios-ag/FMElfinderBundle/pull/391)\n- Fixed wrong import [\\#390](https://github.com/helios-ag/FMElfinderBundle/pull/390)\n\n## [10.0.1](https://github.com/helios-ag/FMElfinderBundle/tree/10.0.1) (2020-01-14)\n\n**Closed issues:**\n\n- PHP 7.2 Function create\\_function\\(\\) is deprecated [\\#376](https://github.com/helios-ag/FMElfinderBundle/issues/376)\n- ElFinderLoader::encode\\($path\\) does not return any valid result [\\#368](https://github.com/helios-ag/FMElfinderBundle/issues/368)\n- Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller is deprecated [\\#361](https://github.com/helios-ag/FMElfinderBundle/issues/361)\n- The ElfinderController::loadAction never return a Symfony Response [\\#352](https://github.com/helios-ag/FMElfinderBundle/issues/352)\n- Max upload size [\\#311](https://github.com/helios-ag/FMElfinderBundle/issues/311)\n- Unable to upload \"test.jpg\". \"test.jpg\" transfer error. [\\#295](https://github.com/helios-ag/FMElfinderBundle/issues/295)\n- Feature request: Add volume icon config. [\\#294](https://github.com/helios-ag/FMElfinderBundle/issues/294)\n- El finder showing folder not found.  [\\#286](https://github.com/helios-ag/FMElfinderBundle/issues/286)\n- modifity root dir in listener [\\#274](https://github.com/helios-ag/FMElfinderBundle/issues/274)\n- Error on upload : Unknow command [\\#271](https://github.com/helios-ag/FMElfinderBundle/issues/271)\n- Unable to override properly the configuration provider - the right way ? [\\#257](https://github.com/helios-ag/FMElfinderBundle/issues/257)\n\n**Merged pull requests:**\n\n- Routing file extension changed to yaml [\\#387](https://github.com/helios-ag/FMElfinderBundle/pull/387)\n- Update flysystem.md [\\#386](https://github.com/helios-ag/FMElfinderBundle/pull/386)\n\n## [10](https://github.com/helios-ag/FMElfinderBundle/tree/10) (2020-01-12)\n\n**Merged pull requests:**\n\n- Symfony5 [\\#379](https://github.com/helios-ag/FMElfinderBundle/pull/379)\n\n## [9.3.2](https://github.com/helios-ag/FMElfinderBundle/tree/9.3.2) (2019-11-21)\n\n**Closed issues:**\n\n- Summernote insertion of an image or a link to a pdf file [\\#372](https://github.com/helios-ag/FMElfinderBundle/issues/372)\n- Service as Driver, Driver not found [\\#267](https://github.com/helios-ag/FMElfinderBundle/issues/267)\n- How to set s3 file acl to public-read after upload? [\\#259](https://github.com/helios-ag/FMElfinderBundle/issues/259)\n\n**Merged pull requests:**\n\n- Update twig extension to use supported Twig classes instead of legacy ones [\\#374](https://github.com/helios-ag/FMElfinderBundle/pull/374)\n- PDF fix \\#372 [\\#373](https://github.com/helios-ag/FMElfinderBundle/pull/373)\n- Replaced old templates for gh issues [\\#371](https://github.com/helios-ag/FMElfinderBundle/pull/371)\n- Removed deprecated settings [\\#370](https://github.com/helios-ag/FMElfinderBundle/pull/370)\n- Update README.md [\\#367](https://github.com/helios-ag/FMElfinderBundle/pull/367)\n\n## [9.3.1](https://github.com/helios-ag/FMElfinderBundle/tree/9.3.1) (2019-07-28)\n\n**Merged pull requests:**\n\n- Apply fixes from StyleCI [\\#366](https://github.com/helios-ag/FMElfinderBundle/pull/366)\n- This is to add an opportunity for injecting S3 options like ACL permissions [\\#365](https://github.com/helios-ag/FMElfinderBundle/pull/365)\n- Allow endpoint and path-style endpoint configuration for aws\\_s3\\_v3 [\\#362](https://github.com/helios-ag/FMElfinderBundle/pull/362)\n\n## [9.3](https://github.com/helios-ag/FMElfinderBundle/tree/9.3) (2019-05-11)\n\n**Closed issues:**\n\n- How to remove toolbar / hide tollbar : Any idea [\\#356](https://github.com/helios-ag/FMElfinderBundle/issues/356)\n- Help: multiple: true for multiple slection [\\#355](https://github.com/helios-ag/FMElfinderBundle/issues/355)\n- Modify the path dynamically [\\#354](https://github.com/helios-ag/FMElfinderBundle/issues/354)\n- Plugins configuration does not work [\\#353](https://github.com/helios-ag/FMElfinderBundle/issues/353)\n- Symfony 4.2 deprecation: A tree builder without a root node is deprecated [\\#346](https://github.com/helios-ag/FMElfinderBundle/issues/346)\n- .tmb location [\\#345](https://github.com/helios-ag/FMElfinderBundle/issues/345)\n\n**Merged pull requests:**\n\n- Add homeFolder to url [\\#359](https://github.com/helios-ag/FMElfinderBundle/pull/359)\n- fixed call to a protected member [\\#357](https://github.com/helios-ag/FMElfinderBundle/pull/357)\n\n## [9.2.1](https://github.com/helios-ag/FMElfinderBundle/tree/9.2.1) (2019-03-10)\n\n**Closed issues:**\n\n- Mission option tmpPath under onedrive\\_setting [\\#351](https://github.com/helios-ag/FMElfinderBundle/issues/351)\n- Find file by Hash in controller\\(backend\\) [\\#341](https://github.com/helios-ag/FMElfinderBundle/issues/341)\n- FIX : Popup elfinder [\\#270](https://github.com/helios-ag/FMElfinderBundle/issues/270)\n- Option buttons issue in modal  [\\#266](https://github.com/helios-ag/FMElfinderBundle/issues/266)\n- Adding a prompt box when duplicate folders in S3 Volume Driver [\\#251](https://github.com/helios-ag/FMElfinderBundle/issues/251)\n- Plugin Sanitizer won't work. [\\#248](https://github.com/helios-ag/FMElfinderBundle/issues/248)\n- Can the parent directories to be set from the URL handled in a better way? [\\#244](https://github.com/helios-ag/FMElfinderBundle/issues/244)\n\n**Merged pull requests:**\n\n- Fix tree builder deprecation [\\#350](https://github.com/helios-ag/FMElfinderBundle/pull/350)\n- Post execution event fix [\\#349](https://github.com/helios-ag/FMElfinderBundle/pull/349)\n- Travis test [\\#348](https://github.com/helios-ag/FMElfinderBundle/pull/348)\n- Fix deprecation for symfony/config 4.2+ [\\#347](https://github.com/helios-ag/FMElfinderBundle/pull/347)\n- Update satooshi/php-coveralls requirement from ~1 to ~2 [\\#344](https://github.com/helios-ag/FMElfinderBundle/pull/344)\n\n## [9.2](https://github.com/helios-ag/FMElfinderBundle/tree/9.2) (2018-12-11)\n\n**Merged pull requests:**\n\n- Apply fixes from StyleCI [\\#343](https://github.com/helios-ag/FMElfinderBundle/pull/343)\n- replaced hash with getpath [\\#342](https://github.com/helios-ag/FMElfinderBundle/pull/342)\n\n## [9.1.1](https://github.com/helios-ag/FMElfinderBundle/tree/9.1.1) (2018-11-01)\n\n**Closed issues:**\n\n- How to give upload path for browser server [\\#335](https://github.com/helios-ag/FMElfinderBundle/issues/335)\n- How can I set privateKey for Flysystem ftp\\(sftp\\) [\\#332](https://github.com/helios-ag/FMElfinderBundle/issues/332)\n- Invalid parameters for command \"mkdir\" [\\#288](https://github.com/helios-ag/FMElfinderBundle/issues/288)\n\n**Merged pull requests:**\n\n- Throw not found exception on unknown instance [\\#338](https://github.com/helios-ag/FMElfinderBundle/pull/338)\n- Explicitly call resize\\(\\) after registering handler to always trigger resize on first load [\\#337](https://github.com/helios-ag/FMElfinderBundle/pull/337)\n- Added azure support via flysystem [\\#336](https://github.com/helios-ag/FMElfinderBundle/pull/336)\n\n## [9.1](https://github.com/helios-ag/FMElfinderBundle/tree/9.1) (2018-10-10)\n\n**Closed issues:**\n\n- Driver \"elFinderVolumeFlysystem\" does not exist ? [\\#327](https://github.com/helios-ag/FMElfinderBundle/issues/327)\n- Options not passed properly with dropbox2 driver ? [\\#325](https://github.com/helios-ag/FMElfinderBundle/issues/325)\n- Public link from dropbox volume [\\#324](https://github.com/helios-ag/FMElfinderBundle/issues/324)\n\n**Merged pull requests:**\n\n- Apply fixes from StyleCI [\\#334](https://github.com/helios-ag/FMElfinderBundle/pull/334)\n- Separated sftp and ftp settings, added additional fields to sftp [\\#333](https://github.com/helios-ag/FMElfinderBundle/pull/333)\n- Updated Changelog and referenced version 9 of the bundle in Readme [\\#331](https://github.com/helios-ag/FMElfinderBundle/pull/331)\n\n## [9](https://github.com/helios-ag/FMElfinderBundle/tree/9) (2018-10-06)\n\n**Closed issues:**\n\n- Twig error after updating [\\#330](https://github.com/helios-ag/FMElfinderBundle/issues/330)\n- Problem with uploading image using CKEditor [\\#320](https://github.com/helios-ag/FMElfinderBundle/issues/320)\n- JqueryUi name mismatch [\\#314](https://github.com/helios-ag/FMElfinderBundle/issues/314)\n- version 8 doesn't work with symfony-cmf/media-bundle [\\#313](https://github.com/helios-ag/FMElfinderBundle/issues/313)\n- Using collection form type of elfinder form type not working well [\\#310](https://github.com/helios-ag/FMElfinderBundle/issues/310)\n- Folder .tmb is locked, unable to move the directory. [\\#307](https://github.com/helios-ag/FMElfinderBundle/issues/307)\n- Unable to find template \"FMElfinderBundle:Form:elfinder\\_widget.html.twig\"  [\\#306](https://github.com/helios-ag/FMElfinderBundle/issues/306)\n- Notice: Undefined index: instance\\_name stfalcon\\_tinymce [\\#285](https://github.com/helios-ag/FMElfinderBundle/issues/285)\n- How to assign a home folder to a user? [\\#276](https://github.com/helios-ag/FMElfinderBundle/issues/276)\n- Quarantine configuration option invalid. [\\#256](https://github.com/helios-ag/FMElfinderBundle/issues/256)\n- unable to upload image [\\#255](https://github.com/helios-ag/FMElfinderBundle/issues/255)\n- Is it able to fetch\\(GET\\) filename only \\(don't want to display thumbnails\\) on ELFinder's display [\\#243](https://github.com/helios-ag/FMElfinderBundle/issues/243)\n\n**Merged pull requests:**\n\n- Volume drivers [\\#329](https://github.com/helios-ag/FMElfinderBundle/pull/329)\n- Update configuration to match elfinder volume configuration. [\\#326](https://github.com/helios-ag/FMElfinderBundle/pull/326)\n- New way to referencing controller [\\#323](https://github.com/helios-ag/FMElfinderBundle/pull/323)\n- Apply fixes from StyleCI [\\#322](https://github.com/helios-ag/FMElfinderBundle/pull/322)\n- Changed directory structure [\\#321](https://github.com/helios-ag/FMElfinderBundle/pull/321)\n- Change default /assets path to assets [\\#317](https://github.com/helios-ag/FMElfinderBundle/pull/317)\n- Allow Flysystem filesystem service to be injected directly without ex… [\\#280](https://github.com/helios-ag/FMElfinderBundle/pull/280)\n\n## [8.0.3](https://github.com/helios-ag/FMElfinderBundle/tree/8.0.3) (2018-05-25)\n\n**Closed issues:**\n\n- Migrate to FOSCKEditorBundle [\\#316](https://github.com/helios-ag/FMElfinderBundle/issues/316)\n\n**Merged pull requests:**\n\n- Compatibility to SF4 in FMElfinderExtension.php [\\#318](https://github.com/helios-ag/FMElfinderBundle/pull/318)\n\n## [8.0.2](https://github.com/helios-ag/FMElfinderBundle/tree/8.0.2) (2018-05-25)\n\n**Closed issues:**\n\n- Blank Screen?? [\\#315](https://github.com/helios-ag/FMElfinderBundle/issues/315)\n- Invalid backend configuration. Readable volumes not available [\\#312](https://github.com/helios-ag/FMElfinderBundle/issues/312)\n- Configure Elfinder Bundle to connect with a MySQL database [\\#300](https://github.com/helios-ag/FMElfinderBundle/issues/300)\n- Support for \"encoding\" at fm\\_elfinder.instances.instance\\_name.connector.roots.connector\\_name [\\#291](https://github.com/helios-ag/FMElfinderBundle/issues/291)\n- srcset possible? [\\#264](https://github.com/helios-ag/FMElfinderBundle/issues/264)\n- How to preview image and show image thumb? [\\#258](https://github.com/helios-ag/FMElfinderBundle/issues/258)\n- multiple file select [\\#254](https://github.com/helios-ag/FMElfinderBundle/issues/254)\n- Use original library studio-42/elfinder [\\#247](https://github.com/helios-ag/FMElfinderBundle/issues/247)\n- fm-elfinder-php-connector error [\\#225](https://github.com/helios-ag/FMElfinderBundle/issues/225)\n- wrong assets path requested [\\#213](https://github.com/helios-ag/FMElfinderBundle/issues/213)\n- Issue with plugins \\(with solution\\) [\\#208](https://github.com/helios-ag/FMElfinderBundle/issues/208)\n- Issue for custom service driver \\(with solution\\) [\\#205](https://github.com/helios-ag/FMElfinderBundle/issues/205)\n- How to dynamicly create folder ? [\\#189](https://github.com/helios-ag/FMElfinderBundle/issues/189)\n- Accepted configuration for \"attributes\" under \"roots\" is incorrect [\\#188](https://github.com/helios-ag/FMElfinderBundle/issues/188)\n- Bug on getUrl function with HomeFolder [\\#161](https://github.com/helios-ag/FMElfinderBundle/issues/161)\n- Backwards slash as directory separator on windows web servers. [\\#113](https://github.com/helios-ag/FMElfinderBundle/issues/113)\n\n## [8.0.1](https://github.com/helios-ag/FMElfinderBundle/tree/8.0.1) (2018-04-04)\n\n**Merged pull requests:**\n\n- Fix default encoding parameter value [\\#309](https://github.com/helios-ag/FMElfinderBundle/pull/309)\n\n## [8.0](https://github.com/helios-ag/FMElfinderBundle/tree/8.0) (2018-04-01)\n\n**Closed issues:**\n\n- Update to latest version of elFinder [\\#301](https://github.com/helios-ag/FMElfinderBundle/issues/301)\n- edit twig files [\\#287](https://github.com/helios-ag/FMElfinderBundle/issues/287)\n- Optional prefix not implemented for flysystem aws\\_s3\\_v3 adapter [\\#237](https://github.com/helios-ag/FMElfinderBundle/issues/237)\n\n**Merged pull requests:**\n\n- Dev [\\#308](https://github.com/helios-ag/FMElfinderBundle/pull/308)\n\n## [7.0.1](https://github.com/helios-ag/FMElfinderBundle/tree/7.0.1) (2018-01-22)\n\n**Closed issues:**\n\n- Symfony 4 compatibility [\\#299](https://github.com/helios-ag/FMElfinderBundle/issues/299)\n- Make bundle compatible with Symfony 4.0 [\\#296](https://github.com/helios-ag/FMElfinderBundle/issues/296)\n\n**Merged pull requests:**\n\n- Fixed twig extension for SF4. [\\#302](https://github.com/helios-ag/FMElfinderBundle/pull/302)\n\n## [7.0](https://github.com/helios-ag/FMElfinderBundle/tree/7.0) (2017-12-10)\n\n**Closed issues:**\n\n- Multiple AppKernel class [\\#282](https://github.com/helios-ag/FMElfinderBundle/issues/282)\n- is there any way to disable/enable commands using config.yml [\\#281](https://github.com/helios-ag/FMElfinderBundle/issues/281)\n- Is is possible to create unique filenames? [\\#279](https://github.com/helios-ag/FMElfinderBundle/issues/279)\n- Strange characters when inserting images [\\#278](https://github.com/helios-ag/FMElfinderBundle/issues/278)\n- AutoResize plugin not working [\\#277](https://github.com/helios-ag/FMElfinderBundle/issues/277)\n- Uploading png works, jpg fails [\\#275](https://github.com/helios-ag/FMElfinderBundle/issues/275)\n- Symfony 3.x support? [\\#273](https://github.com/helios-ag/FMElfinderBundle/issues/273)\n- Option: URL [\\#268](https://github.com/helios-ag/FMElfinderBundle/issues/268)\n- Notice: Undefined variable: header [\\#265](https://github.com/helios-ag/FMElfinderBundle/issues/265)\n- Unable to connect to backend. [\\#262](https://github.com/helios-ag/FMElfinderBundle/issues/262)\n- Cant Connect to Backend [\\#261](https://github.com/helios-ag/FMElfinderBundle/issues/261)\n- enable popup  [\\#260](https://github.com/helios-ag/FMElfinderBundle/issues/260)\n- ckeditor integration  [\\#221](https://github.com/helios-ag/FMElfinderBundle/issues/221)\n- Expand \"elfinder\" type [\\#200](https://github.com/helios-ag/FMElfinderBundle/issues/200)\n- Usage of \"elfinder\" Form Type in version \"~6\" [\\#196](https://github.com/helios-ag/FMElfinderBundle/issues/196)\n- Rewrite elfinder form type in pure js [\\#102](https://github.com/helios-ag/FMElfinderBundle/issues/102)\n\n**Merged pull requests:**\n\n- Sf4 [\\#297](https://github.com/helios-ag/FMElfinderBundle/pull/297)\n- Consistent urls [\\#293](https://github.com/helios-ag/FMElfinderBundle/pull/293)\n- Fix Symfony versions [\\#292](https://github.com/helios-ag/FMElfinderBundle/pull/292)\n- Apply fixes from StyleCI [\\#284](https://github.com/helios-ag/FMElfinderBundle/pull/284)\n- Readme patch [\\#283](https://github.com/helios-ag/FMElfinderBundle/pull/283)\n- Update Readme.md [\\#269](https://github.com/helios-ag/FMElfinderBundle/pull/269)\n\n## [6.2.1](https://github.com/helios-ag/FMElfinderBundle/tree/6.2.1) (2016-09-03)\n\n**Merged pull requests:**\n\n- made archivers node optional [\\#263](https://github.com/helios-ag/FMElfinderBundle/pull/263)\n\n## [6.2](https://github.com/helios-ag/FMElfinderBundle/tree/6.2) (2016-07-26)\n\n**Closed issues:**\n\n- Againe stop to work!! [\\#252](https://github.com/helios-ag/FMElfinderBundle/issues/252)\n- Notice: ob\\_end\\_clean\\(\\): failed to delete buffer. No buffer to delete \\(FlySystem S3 adapter\\) [\\#249](https://github.com/helios-ag/FMElfinderBundle/issues/249)\n- use cumsom theme [\\#246](https://github.com/helios-ag/FMElfinderBundle/issues/246)\n- Cannot work, still get error: Unable to connect to the backend. [\\#241](https://github.com/helios-ag/FMElfinderBundle/issues/241)\n- Special characters in filename not allowing to upload files [\\#239](https://github.com/helios-ag/FMElfinderBundle/issues/239)\n- How to reset the field [\\#227](https://github.com/helios-ag/FMElfinderBundle/issues/227)\n- Request: Custom Flysystem adapter [\\#224](https://github.com/helios-ag/FMElfinderBundle/issues/224)\n- Can't create archive.  [\\#220](https://github.com/helios-ag/FMElfinderBundle/issues/220)\n- No callback sync to form field [\\#212](https://github.com/helios-ag/FMElfinderBundle/issues/212)\n- Send it to Server returns ckeditor instance [\\#165](https://github.com/helios-ag/FMElfinderBundle/issues/165)\n\n**Merged pull requests:**\n\n- Improved configuration for archivers support [\\#253](https://github.com/helios-ag/FMElfinderBundle/pull/253)\n- Use locale from request object if it is not provided in configuration. [\\#250](https://github.com/helios-ag/FMElfinderBundle/pull/250)\n- add fileMode connector option [\\#245](https://github.com/helios-ag/FMElfinderBundle/pull/245)\n- add missing documentation [\\#242](https://github.com/helios-ag/FMElfinderBundle/pull/242)\n- Configuration Reader upated to allow usage of Google Cloud Storage In… [\\#240](https://github.com/helios-ag/FMElfinderBundle/pull/240)\n\n## [6.1.2](https://github.com/helios-ag/FMElfinderBundle/tree/6.1.2) (2016-04-26)\n\n**Closed issues:**\n\n- Missing file extension [\\#236](https://github.com/helios-ag/FMElfinderBundle/issues/236)\n\n**Merged pull requests:**\n\n- added aws s3 v3 optional\\_prefix parameter [\\#238](https://github.com/helios-ag/FMElfinderBundle/pull/238)\n\n## [6.1.1](https://github.com/helios-ag/FMElfinderBundle/tree/6.1.1) (2016-03-29)\n\n**Closed issues:**\n\n- When upload image file, elfinder say「unable to connect to backend.」 [\\#229](https://github.com/helios-ag/FMElfinderBundle/issues/229)\n- Dynamic path doesn't work after upgrading from 5 to 6 [\\#228](https://github.com/helios-ag/FMElfinderBundle/issues/228)\n\n**Merged pull requests:**\n\n- wrap jQuery around DOMContentLoaded [\\#235](https://github.com/helios-ag/FMElfinderBundle/pull/235)\n- Applied fixes from StyleCI [\\#233](https://github.com/helios-ag/FMElfinderBundle/pull/233)\n- Flysystem custom adapter [\\#232](https://github.com/helios-ag/FMElfinderBundle/pull/232)\n- Applied fixes from StyleCI [\\#231](https://github.com/helios-ag/FMElfinderBundle/pull/231)\n- Rackspace driver and allowcustom options [\\#230](https://github.com/helios-ag/FMElfinderBundle/pull/230)\n\n## [6.1](https://github.com/helios-ag/FMElfinderBundle/tree/6.1) (2016-02-27)\n\n**Closed issues:**\n\n- Custom Elfinder theme [\\#222](https://github.com/helios-ag/FMElfinderBundle/issues/222)\n\n**Merged pull requests:**\n\n- composer tweak, summernote helper blank line added and removed blank … [\\#226](https://github.com/helios-ag/FMElfinderBundle/pull/226)\n- fixed simple template and improved readme file [\\#223](https://github.com/helios-ag/FMElfinderBundle/pull/223)\n\n## [6.0.3](https://github.com/helios-ag/FMElfinderBundle/tree/6.0.3) (2016-02-19)\n\n**Closed issues:**\n\n- Content of Elfinder page is not displayed [\\#218](https://github.com/helios-ag/FMElfinderBundle/issues/218)\n\n**Merged pull requests:**\n\n- tmbURL unit test merge fix [\\#217](https://github.com/helios-ag/FMElfinderBundle/pull/217)\n\n## [6.0.2](https://github.com/helios-ag/FMElfinderBundle/tree/6.0.2) (2016-01-24)\n\n**Closed issues:**\n\n- Symfony 2.8 Asset folder not find. [\\#210](https://github.com/helios-ag/FMElfinderBundle/issues/210)\n- How can get url that selected Image? [\\#209](https://github.com/helios-ag/FMElfinderBundle/issues/209)\n- config Elfinder Form Type have problem [\\#204](https://github.com/helios-ag/FMElfinderBundle/issues/204)\n- Bad asset path [\\#203](https://github.com/helios-ag/FMElfinderBundle/issues/203)\n- Used \"helios-ag/fm-elfinder-bundle\": \"~6\" shows nothing [\\#202](https://github.com/helios-ag/FMElfinderBundle/issues/202)\n- Full absolute path to image [\\#199](https://github.com/helios-ag/FMElfinderBundle/issues/199)\n- How to show only certain mime types from configuration? [\\#193](https://github.com/helios-ag/FMElfinderBundle/issues/193)\n- Amazon s3 integration [\\#191](https://github.com/helios-ag/FMElfinderBundle/issues/191)\n\n**Merged pull requests:**\n\n- Fix case of tmbURL option [\\#216](https://github.com/helios-ag/FMElfinderBundle/pull/216)\n- file URL double slashes removal + unit tests [\\#215](https://github.com/helios-ag/FMElfinderBundle/pull/215)\n- CKEditor integration doc homeFolder precision [\\#214](https://github.com/helios-ag/FMElfinderBundle/pull/214)\n- events doc precision [\\#211](https://github.com/helios-ag/FMElfinderBundle/pull/211)\n- Used asset function to valid addresses of assets [\\#207](https://github.com/helios-ag/FMElfinderBundle/pull/207)\n- Replaced {% include %} by {{ include\\(\\) }} [\\#206](https://github.com/helios-ag/FMElfinderBundle/pull/206)\n- contributing info [\\#201](https://github.com/helios-ag/FMElfinderBundle/pull/201)\n- Applied fixes from StyleCI [\\#198](https://github.com/helios-ag/FMElfinderBundle/pull/198)\n- Patch 1 [\\#197](https://github.com/helios-ag/FMElfinderBundle/pull/197)\n\n## [6.0.1](https://github.com/helios-ag/FMElfinderBundle/tree/6.0.1) (2015-12-08)\n\n**Closed issues:**\n\n- Symfony 3.0 [\\#190](https://github.com/helios-ag/FMElfinderBundle/issues/190)\n\n**Merged pull requests:**\n\n- Bundle configuration for visible mime types [\\#195](https://github.com/helios-ag/FMElfinderBundle/pull/195)\n\n## [6.0](https://github.com/helios-ag/FMElfinderBundle/tree/6.0) (2015-12-06)\n\n**Closed issues:**\n\n- FMElfinderBundle shows white window [\\#184](https://github.com/helios-ag/FMElfinderBundle/issues/184)\n- fabric.image.fromURL [\\#183](https://github.com/helios-ag/FMElfinderBundle/issues/183)\n- Access to the encode/decode function From onPreExecute [\\#174](https://github.com/helios-ag/FMElfinderBundle/issues/174)\n\n**Merged pull requests:**\n\n- updated readme, before tagging [\\#194](https://github.com/helios-ag/FMElfinderBundle/pull/194)\n- fixed aws\\_s3\\_v3 configuration [\\#192](https://github.com/helios-ag/FMElfinderBundle/pull/192)\n- Applied fixes from StyleCI [\\#187](https://github.com/helios-ag/FMElfinderBundle/pull/187)\n- \\[WIP\\] Sf3 [\\#179](https://github.com/helios-ag/FMElfinderBundle/pull/179)\n\n## [5.3](https://github.com/helios-ag/FMElfinderBundle/tree/5.3) (2015-11-15)\n\n**Merged pull requests:**\n\n- fm\\_tinymce\\_bundle [\\#182](https://github.com/helios-ag/FMElfinderBundle/pull/182)\n\n## [5.2.1](https://github.com/helios-ag/FMElfinderBundle/tree/5.2.1) (2015-11-12)\n\n**Closed issues:**\n\n- Assets not found [\\#180](https://github.com/helios-ag/FMElfinderBundle/issues/180)\n\n**Merged pull requests:**\n\n- Fix paths for elfinder-component 2.0 compatibility  [\\#181](https://github.com/helios-ag/FMElfinderBundle/pull/181)\n\n## [5.2](https://github.com/helios-ag/FMElfinderBundle/tree/5.2) (2015-11-09)\n\n**Closed issues:**\n\n- Encode / Decode Path [\\#169](https://github.com/helios-ag/FMElfinderBundle/issues/169)\n- Wrong mime type with flysystem s3 driver [\\#164](https://github.com/helios-ag/FMElfinderBundle/issues/164)\n- FMElfinderBundle shows nothing [\\#159](https://github.com/helios-ag/FMElfinderBundle/issues/159)\n- Why this bundle generates Symfony2 doctrine migration file? [\\#157](https://github.com/helios-ag/FMElfinderBundle/issues/157)\n- Path error with nested folders \\(uploads/bob\\) [\\#152](https://github.com/helios-ag/FMElfinderBundle/issues/152)\n- GridFs support ? \\(Flysystem / Gaufrette\\) [\\#145](https://github.com/helios-ag/FMElfinderBundle/issues/145)\n- \\[bug\\] asset can not load from relative path [\\#142](https://github.com/helios-ag/FMElfinderBundle/issues/142)\n- Dynamic path depending on the user ? [\\#138](https://github.com/helios-ag/FMElfinderBundle/issues/138)\n- Relative path option not works as expected [\\#116](https://github.com/helios-ag/FMElfinderBundle/issues/116)\n- How to override the paste method [\\#98](https://github.com/helios-ag/FMElfinderBundle/issues/98)\n\n**Merged pull requests:**\n\n- increased number of tests [\\#178](https://github.com/helios-ag/FMElfinderBundle/pull/178)\n- coveralls support [\\#177](https://github.com/helios-ag/FMElfinderBundle/pull/177)\n- Access to the encode/decode function From onPreExecute \\(2/2\\) [\\#176](https://github.com/helios-ag/FMElfinderBundle/pull/176)\n- readme split [\\#175](https://github.com/helios-ag/FMElfinderBundle/pull/175)\n- encode/decode access from FMElfinderBundle Loader \\(2/2\\)  [\\#172](https://github.com/helios-ag/FMElfinderBundle/pull/172)\n- bower component [\\#167](https://github.com/helios-ag/FMElfinderBundle/pull/167)\n\n## [5.1](https://github.com/helios-ag/FMElfinderBundle/tree/5.1) (2015-09-24)\n\n**Closed issues:**\n\n- Error - Window does not connect folders [\\#158](https://github.com/helios-ag/FMElfinderBundle/issues/158)\n- S3 Driver [\\#153](https://github.com/helios-ag/FMElfinderBundle/issues/153)\n\n**Merged pull requests:**\n\n- Applied fixes from StyleCI [\\#163](https://github.com/helios-ag/FMElfinderBundle/pull/163)\n- Summernote support [\\#162](https://github.com/helios-ag/FMElfinderBundle/pull/162)\n- Events unit tests [\\#150](https://github.com/helios-ag/FMElfinderBundle/pull/150)\n\n## [5.0.5](https://github.com/helios-ag/FMElfinderBundle/tree/5.0.5) (2015-07-16)\n\n**Closed issues:**\n\n- Unable to connect to the backend. [\\#149](https://github.com/helios-ag/FMElfinderBundle/issues/149)\n- Issue with adding images to ckeditor [\\#148](https://github.com/helios-ag/FMElfinderBundle/issues/148)\n- FMElfinder not created and an input persists [\\#146](https://github.com/helios-ag/FMElfinderBundle/issues/146)\n- Uncaught TypeError: a.indexOf is not a function \\(IvoryCkEditor Insert Image\\) [\\#144](https://github.com/helios-ag/FMElfinderBundle/issues/144)\n- Overriding templates [\\#143](https://github.com/helios-ag/FMElfinderBundle/issues/143)\n- Table created and not used. [\\#141](https://github.com/helios-ag/FMElfinderBundle/issues/141)\n- Elfinder Form Type [\\#140](https://github.com/helios-ag/FMElfinderBundle/issues/140)\n- Disallow creating/uploading new folder [\\#139](https://github.com/helios-ag/FMElfinderBundle/issues/139)\n- showhidden: false ! [\\#136](https://github.com/helios-ag/FMElfinderBundle/issues/136)\n- can't access to assets JS and CSS [\\#129](https://github.com/helios-ag/FMElfinderBundle/issues/129)\n- Plugin ?? [\\#127](https://github.com/helios-ag/FMElfinderBundle/issues/127)\n- Undefined index: ckeditor  [\\#121](https://github.com/helios-ag/FMElfinderBundle/issues/121)\n\n**Merged pull requests:**\n\n- region & signature S3 configuration parameters needed [\\#156](https://github.com/helios-ag/FMElfinderBundle/pull/156)\n- reworked on relative\\(absolute from root\\) paths [\\#154](https://github.com/helios-ag/FMElfinderBundle/pull/154)\n- Expose pathPrefix to custom editors [\\#151](https://github.com/helios-ag/FMElfinderBundle/pull/151)\n- readme small improvements, and newline chars at end of files [\\#147](https://github.com/helios-ag/FMElfinderBundle/pull/147)\n- Fixed configuration loading of attributes. [\\#137](https://github.com/helios-ag/FMElfinderBundle/pull/137)\n- Command execution events + subrequests support + volume\\_id setting [\\#128](https://github.com/helios-ag/FMElfinderBundle/pull/128)\n\n## [5.0.4](https://github.com/helios-ag/FMElfinderBundle/tree/5.0.4) (2015-04-11)\n\n**Merged pull requests:**\n\n- Scrutinizer enabled [\\#135](https://github.com/helios-ag/FMElfinderBundle/pull/135)\n\n## [5.0.3](https://github.com/helios-ag/FMElfinderBundle/tree/5.0.3) (2015-04-03)\n\n**Merged pull requests:**\n\n- Allow setting the directoryPerm parameter [\\#133](https://github.com/helios-ag/FMElfinderBundle/pull/133)\n- Fixed configuration loading for root parameter \\(ftp\\) [\\#132](https://github.com/helios-ag/FMElfinderBundle/pull/132)\n\n## [5.0.2](https://github.com/helios-ag/FMElfinderBundle/tree/5.0.2) (2015-04-02)\n\n**Closed issues:**\n\n- php 5.4 syntax used \\(symfony2 and the bundle itself state minimum requirement to \\>= php 5.3.3\\) [\\#130](https://github.com/helios-ag/FMElfinderBundle/issues/130)\n- Incorrect path [\\#125](https://github.com/helios-ag/FMElfinderBundle/issues/125)\n- assetic generation path [\\#40](https://github.com/helios-ag/FMElfinderBundle/issues/40)\n\n**Merged pull requests:**\n\n- array short syntax removed [\\#131](https://github.com/helios-ag/FMElfinderBundle/pull/131)\n\n## [5.0.1](https://github.com/helios-ag/FMElfinderBundle/tree/5.0.1) (2015-03-23)\n\n**Closed issues:**\n\n- Permission / Override configuration [\\#100](https://github.com/helios-ag/FMElfinderBundle/issues/100)\n- ReferenceError: $ is not defined [\\#87](https://github.com/helios-ag/FMElfinderBundle/issues/87)\n\n**Merged pull requests:**\n\n- Fix bug \"pathPrefix\" when use Form Type [\\#124](https://github.com/helios-ag/FMElfinderBundle/pull/124)\n\n## [5](https://github.com/helios-ag/FMElfinderBundle/tree/5) (2015-03-21)\n\n**Merged pull requests:**\n\n- Component [\\#123](https://github.com/helios-ag/FMElfinderBundle/pull/123)\n\n## [4.0.2](https://github.com/helios-ag/FMElfinderBundle/tree/4.0.2) (2015-03-20)\n\n**Closed issues:**\n\n- S3 folder not shown after creation [\\#120](https://github.com/helios-ag/FMElfinderBundle/issues/120)\n- Path issues and upload [\\#118](https://github.com/helios-ag/FMElfinderBundle/issues/118)\n- ElFinder and two or more instances with ckeditor [\\#117](https://github.com/helios-ag/FMElfinderBundle/issues/117)\n- liip image [\\#84](https://github.com/helios-ag/FMElfinderBundle/issues/84)\n\n**Merged pull requests:**\n\n- connector options override [\\#122](https://github.com/helios-ag/FMElfinderBundle/pull/122)\n- S3 example configuration and url fix [\\#119](https://github.com/helios-ag/FMElfinderBundle/pull/119)\n\n## [4.0.1](https://github.com/helios-ag/FMElfinderBundle/tree/4.0.1) (2015-02-21)\n\n**Merged pull requests:**\n\n- Added homeFolder parameter to ElFinderType [\\#115](https://github.com/helios-ag/FMElfinderBundle/pull/115)\n\n## [4.0](https://github.com/helios-ag/FMElfinderBundle/tree/4.0) (2015-02-18)\n\n###\n\n- Support new drivers via FlySystem [\\#105](https://github.com/helios-ag/FMElfinderBundle/issues/105)\n\n**Closed issues:**\n\n- Enable CORS [\\#106](https://github.com/helios-ag/FMElfinderBundle/issues/106)\n- Wrong url when select the picture [\\#99](https://github.com/helios-ag/FMElfinderBundle/issues/99)\n- dynamic 'path' setting ? [\\#91](https://github.com/helios-ag/FMElfinderBundle/issues/91)\n\n**Merged pull requests:**\n\n- updated README [\\#114](https://github.com/helios-ag/FMElfinderBundle/pull/114)\n- conv to unix [\\#112](https://github.com/helios-ag/FMElfinderBundle/pull/112)\n- flysystem driver support [\\#111](https://github.com/helios-ag/FMElfinderBundle/pull/111)\n- CORS and home folder guides [\\#110](https://github.com/helios-ag/FMElfinderBundle/pull/110)\n- Multiple upload folder by instance [\\#109](https://github.com/helios-ag/FMElfinderBundle/pull/109)\n- Non hard exit [\\#108](https://github.com/helios-ag/FMElfinderBundle/pull/108)\n- Add triggering of change event [\\#107](https://github.com/helios-ag/FMElfinderBundle/pull/107)\n- overridable loader [\\#104](https://github.com/helios-ag/FMElfinderBundle/pull/104)\n- IvoryCKEditor sample was incorrect [\\#103](https://github.com/helios-ag/FMElfinderBundle/pull/103)\n\n## [3.4](https://github.com/helios-ag/FMElfinderBundle/tree/3.4) (2015-01-20)\n\n**Merged pull requests:**\n\n- Allow custom template renderer [\\#97](https://github.com/helios-ag/FMElfinderBundle/pull/97)\n\n## [3.3](https://github.com/helios-ag/FMElfinderBundle/tree/3.3) (2015-01-17)\n\n**Closed issues:**\n\n- Relative path image [\\#93](https://github.com/helios-ag/FMElfinderBundle/issues/93)\n- attach files? [\\#90](https://github.com/helios-ag/FMElfinderBundle/issues/90)\n- There is no \"uglifycss\" filter [\\#77](https://github.com/helios-ag/FMElfinderBundle/issues/77)\n\n**Merged pull requests:**\n\n- Fix test [\\#96](https://github.com/helios-ag/FMElfinderBundle/pull/96)\n- plugin\\_support [\\#95](https://github.com/helios-ag/FMElfinderBundle/pull/95)\n\n## [3.2.1](https://github.com/helios-ag/FMElfinderBundle/tree/3.2.1) (2015-01-06)\n\n**Merged pull requests:**\n\n- tinymce relative path [\\#94](https://github.com/helios-ag/FMElfinderBundle/pull/94)\n\n## [3.2](https://github.com/helios-ag/FMElfinderBundle/tree/3.2) (2014-12-28)\n\n**Closed issues:**\n\n- add class.  ``form-control`` [\\#88](https://github.com/helios-ag/FMElfinderBundle/issues/88)\n\n**Merged pull requests:**\n\n- Assetic [\\#92](https://github.com/helios-ag/FMElfinderBundle/pull/92)\n\n## [2.3.3](https://github.com/helios-ag/FMElfinderBundle/tree/2.3.3) (2014-12-06)\n\n**Closed issues:**\n\n- multi path folder. [\\#86](https://github.com/helios-ag/FMElfinderBundle/issues/86)\n- get error - Undefined index: ckeditor - [\\#85](https://github.com/helios-ag/FMElfinderBundle/issues/85)\n- Elfinder form type in form type collection [\\#81](https://github.com/helios-ag/FMElfinderBundle/issues/81)\n- BC between 2.5 and 2.5.1 [\\#80](https://github.com/helios-ag/FMElfinderBundle/issues/80)\n- Feature Request: ability to inject the VolumeDriver as a Service [\\#66](https://github.com/helios-ag/FMElfinderBundle/issues/66)\n\n**Merged pull requests:**\n\n- Noassetic [\\#89](https://github.com/helios-ag/FMElfinderBundle/pull/89)\n\n## [3.1](https://github.com/helios-ag/FMElfinderBundle/tree/3.1) (2014-11-09)\n\n**Closed issues:**\n\n- Customizing Elfinder form [\\#82](https://github.com/helios-ag/FMElfinderBundle/issues/82)\n- Request : change the folder path [\\#68](https://github.com/helios-ag/FMElfinderBundle/issues/68)\n\n**Merged pull requests:**\n\n- restored ability to use services as drivers [\\#83](https://github.com/helios-ag/FMElfinderBundle/pull/83)\n\n## [3.0](https://github.com/helios-ag/FMElfinderBundle/tree/3.0) (2014-11-07)\n\n**Closed issues:**\n\n- unable to add symfony service as a volume driver [\\#79](https://github.com/helios-ag/FMElfinderBundle/issues/79)\n\n**Merged pull requests:**\n\n- Update README.md [\\#78](https://github.com/helios-ag/FMElfinderBundle/pull/78)\n\n## [2.3.2](https://github.com/helios-ag/FMElfinderBundle/tree/2.3.2) (2014-10-29)\n\n**Merged pull requests:**\n\n- Made the changes of patch 2.5.1 available in 2.3 [\\#76](https://github.com/helios-ag/FMElfinderBundle/pull/76)\n\n## [2.5.1](https://github.com/helios-ag/FMElfinderBundle/tree/2.5.1) (2014-10-24)\n\n**Closed issues:**\n\n- How to disable command? [\\#74](https://github.com/helios-ag/FMElfinderBundle/issues/74)\n- Injecting Non existent Service Symfony \\<=2.3 [\\#71](https://github.com/helios-ag/FMElfinderBundle/issues/71)\n- Symfony version in composer.json [\\#61](https://github.com/helios-ag/FMElfinderBundle/issues/61)\n\n**Merged pull requests:**\n\n- Multiple elfinder instances in one page/form [\\#75](https://github.com/helios-ag/FMElfinderBundle/pull/75)\n\n## [2.5](https://github.com/helios-ag/FMElfinderBundle/tree/2.5) (2014-10-11)\n\n## [2.3.1](https://github.com/helios-ag/FMElfinderBundle/tree/2.3.1) (2014-10-10)\n\n## [2.3.0](https://github.com/helios-ag/FMElfinderBundle/tree/2.3.0) (2014-10-03)\n\n**Closed issues:**\n\n- Relative path in 'form' instance [\\#72](https://github.com/helios-ag/FMElfinderBundle/issues/72)\n- Unrecognized options \"instances\" under \"fm\\_elfinder\" [\\#67](https://github.com/helios-ag/FMElfinderBundle/issues/67)\n\n**Merged pull requests:**\n\n- Fix dialog icons css [\\#73](https://github.com/helios-ag/FMElfinderBundle/pull/73)\n- showhidden in another node [\\#70](https://github.com/helios-ag/FMElfinderBundle/pull/70)\n- Required only necessary dependencies [\\#69](https://github.com/helios-ag/FMElfinderBundle/pull/69)\n\n## [2.1](https://github.com/helios-ag/FMElfinderBundle/tree/2.1) (2014-08-24)\n\n**Closed issues:**\n\n- Upload file window [\\#65](https://github.com/helios-ag/FMElfinderBundle/issues/65)\n- Change of image URL [\\#64](https://github.com/helios-ag/FMElfinderBundle/issues/64)\n\n## [v2.0](https://github.com/helios-ag/FMElfinderBundle/tree/v2.0) (2014-08-09)\n\n**Closed issues:**\n\n- DataFixtures error? [\\#62](https://github.com/helios-ag/FMElfinderBundle/issues/62)\n- \\[Insight\\] The Symfony Dependency Injection Container should not be passed as an argument [\\#57](https://github.com/helios-ag/FMElfinderBundle/issues/57)\n- Image absolute/relative path [\\#56](https://github.com/helios-ag/FMElfinderBundle/issues/56)\n\n**Merged pull requests:**\n\n- Wrap READ and WRITE columns in quotes [\\#63](https://github.com/helios-ag/FMElfinderBundle/pull/63)\n- 2.0 [\\#60](https://github.com/helios-ag/FMElfinderBundle/pull/60)\n- Update composer.json [\\#59](https://github.com/helios-ag/FMElfinderBundle/pull/59)\n- Update ElFinderFile.php [\\#58](https://github.com/helios-ag/FMElfinderBundle/pull/58)\n\n## [1.5](https://github.com/helios-ag/FMElfinderBundle/tree/1.5) (2014-05-09)\n\n**Closed issues:**\n\n- Standalone elfinder [\\#55](https://github.com/helios-ag/FMElfinderBundle/issues/55)\n- Is or will be there a way to set metadata for media files in elfinder? [\\#54](https://github.com/helios-ag/FMElfinderBundle/issues/54)\n- S3 integration [\\#53](https://github.com/helios-ag/FMElfinderBundle/issues/53)\n- ElFinder resize doesn't update image dimensions [\\#52](https://github.com/helios-ag/FMElfinderBundle/issues/52)\n- config error - parse asset\\[bundles/stfalcontinymce/vendor/ [\\#48](https://github.com/helios-ag/FMElfinderBundle/issues/48)\n\n## [1.4.2](https://github.com/helios-ag/FMElfinderBundle/tree/1.4.2) (2013-12-19)\n\n**Merged pull requests:**\n\n- Add a Bitdeli Badge to README [\\#51](https://github.com/helios-ag/FMElfinderBundle/pull/51)\n\n## [1.4.1](https://github.com/helios-ag/FMElfinderBundle/tree/1.4.1) (2013-11-13)\n\n**Closed issues:**\n\n- Hi  [\\#46](https://github.com/helios-ag/FMElfinderBundle/issues/46)\n- default \\(ckeditor\\) template requires yui\\_css and yui\\_js filters [\\#44](https://github.com/helios-ag/FMElfinderBundle/issues/44)\n- Configuration of elfinder path [\\#42](https://github.com/helios-ag/FMElfinderBundle/issues/42)\n- Problems with dump assets image path and CSSEMBED [\\#34](https://github.com/helios-ag/FMElfinderBundle/issues/34)\n\n**Merged pull requests:**\n\n- document new config options, fix ckeditor compressed template [\\#50](https://github.com/helios-ag/FMElfinderBundle/pull/50)\n- Use request locale as default [\\#49](https://github.com/helios-ag/FMElfinderBundle/pull/49)\n\n## [1.4](https://github.com/helios-ag/FMElfinderBundle/tree/1.4) (2013-10-03)\n\n**Closed issues:**\n\n- Cannot rename files/folders [\\#45](https://github.com/helios-ag/FMElfinderBundle/issues/45)\n- Installation problem [\\#41](https://github.com/helios-ag/FMElfinderBundle/issues/41)\n- so slow ? [\\#35](https://github.com/helios-ag/FMElfinderBundle/issues/35)\n\n**Merged pull requests:**\n\n- Cmf [\\#47](https://github.com/helios-ag/FMElfinderBundle/pull/47)\n- fix dialog image position [\\#43](https://github.com/helios-ag/FMElfinderBundle/pull/43)\n\n## [1.3](https://github.com/helios-ag/FMElfinderBundle/tree/1.3) (2013-08-27)\n\n**Closed issues:**\n\n- no \\_popup.js in STFalconTinyMCE public resources [\\#39](https://github.com/helios-ag/FMElfinderBundle/issues/39)\n- typo? in docs - step 3 [\\#38](https://github.com/helios-ag/FMElfinderBundle/issues/38)\n- in Prod mode error 500 [\\#36](https://github.com/helios-ag/FMElfinderBundle/issues/36)\n- Integration with Tinymce 4 [\\#33](https://github.com/helios-ag/FMElfinderBundle/issues/33)\n- Standalone filebrowser usage [\\#28](https://github.com/helios-ag/FMElfinderBundle/issues/28)\n\n**Merged pull requests:**\n\n- Tinymce4 [\\#37](https://github.com/helios-ag/FMElfinderBundle/pull/37)\n\n## [1.2](https://github.com/helios-ag/FMElfinderBundle/tree/1.2) (2013-08-03)\n\n**Closed issues:**\n\n- RangeError when loading elfinder [\\#31](https://github.com/helios-ag/FMElfinderBundle/issues/31)\n\n**Merged pull requests:**\n\n- Fix \\#31 Uncaught RangeError: Maximum call stack size exceeded in some browsers [\\#32](https://github.com/helios-ag/FMElfinderBundle/pull/32)\n- added feature to use a symfony service as a volumeDriver [\\#30](https://github.com/helios-ag/FMElfinderBundle/pull/30)\n- Added support for an optional 'url' parameter in the 'roots' section [\\#29](https://github.com/helios-ag/FMElfinderBundle/pull/29)\n\n## [1.1](https://github.com/helios-ag/FMElfinderBundle/tree/1.1) (2013-06-12)\n\n**Closed issues:**\n\n- Dependency twig-bundle is wrong for SF 2.3 [\\#26](https://github.com/helios-ag/FMElfinderBundle/issues/26)\n- Image path in CSS are broken [\\#25](https://github.com/helios-ag/FMElfinderBundle/issues/25)\n\n**Merged pull requests:**\n\n- Issues \\#25 & \\#26 fix [\\#27](https://github.com/helios-ag/FMElfinderBundle/pull/27)\n\n## [1.0](https://github.com/helios-ag/FMElfinderBundle/tree/1.0) (2013-06-07)\n\n**Closed issues:**\n\n- Missing icon images [\\#23](https://github.com/helios-ag/FMElfinderBundle/issues/23)\n- CSS generation with assetic [\\#20](https://github.com/helios-ag/FMElfinderBundle/issues/20)\n- Variable \"fullscreen\" does not exist and images not loading [\\#17](https://github.com/helios-ag/FMElfinderBundle/issues/17)\n- Elfinder slow loading [\\#15](https://github.com/helios-ag/FMElfinderBundle/issues/15)\n- Bad asset URL [\\#14](https://github.com/helios-ag/FMElfinderBundle/issues/14)\n- Standalone filebrowser [\\#13](https://github.com/helios-ag/FMElfinderBundle/issues/13)\n- Javascripts missing [\\#12](https://github.com/helios-ag/FMElfinderBundle/issues/12)\n- Dependency error [\\#11](https://github.com/helios-ag/FMElfinderBundle/issues/11)\n- Overriding FMElfinderLoader [\\#9](https://github.com/helios-ag/FMElfinderBundle/issues/9)\n- Assetic cssrewrite css image path [\\#3](https://github.com/helios-ag/FMElfinderBundle/issues/3)\n- Browse Image Return Value in Integration with CKEditor  [\\#2](https://github.com/helios-ag/FMElfinderBundle/issues/2)\n- install error [\\#1](https://github.com/helios-ag/FMElfinderBundle/issues/1)\n\n**Merged pull requests:**\n\n- Fix for images in CSS for newer version of AsseticBundle and cssrewriter [\\#24](https://github.com/helios-ag/FMElfinderBundle/pull/24)\n- fix templates & filters for assetic [\\#22](https://github.com/helios-ag/FMElfinderBundle/pull/22)\n- Update compiled path for assetic js & css [\\#21](https://github.com/helios-ag/FMElfinderBundle/pull/21)\n- fullscreen option [\\#18](https://github.com/helios-ag/FMElfinderBundle/pull/18)\n- El finder php [\\#16](https://github.com/helios-ag/FMElfinderBundle/pull/16)\n- Integration with TinyMCE bundle [\\#10](https://github.com/helios-ag/FMElfinderBundle/pull/10)\n- Update README.md [\\#8](https://github.com/helios-ag/FMElfinderBundle/pull/8)\n- TinyMCE integration + Multiple roots configuration [\\#6](https://github.com/helios-ag/FMElfinderBundle/pull/6)\n- Elfinder fullscreen [\\#5](https://github.com/helios-ag/FMElfinderBundle/pull/5)\n- Ckeditor integration fix [\\#4](https://github.com/helios-ag/FMElfinderBundle/pull/4)\n\n\n\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contribution Guidelines\n=======================\n\nFirst of all, each single contribution is appreciated, whether a typo fix,\nimproved documentation, a fixed bug or a whole new feature.\n\n## Making your changes\n\n 1. Fork the repository on GitHub\n 2. Pull requests must be sent from a new hotfix/feature branch, not from `master`.\n 3. Make your modifications, coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)\n 4. Commit small logical changes, each with a descriptive commit message.\n    Please don't mix unrelated changes in a single commit.\n\n## Commit messages\n\nPlease format your commit messages as follows:\n\n    Short summary of the change (up to 50 characters)\n\n    Optionally add a more extensive description of your change after a\n    blank line. Wrap the lines in this and the following paragraphs after\n    72 characters.\n\n## Submitting your changes\n\n 1. Push your changes to a topic branch in your fork of the repository.\n 2. [Submit a pull request][pr] to the original repository.\n    Describe your changes as short as possible, but as detailed as needed for\n    others to get an overview of your modifications.\n\n## Further information\n\n * [General GitHub documentation][gh-help]\n * [GitHub pull request documentation][gh-pr]\n\n [gh-help]: https://help.github.com\n [gh-pr]:   https://help.github.com/send-pull-requests\n [issue]:   https://github.com/helios-ag/FMElfinderBundle/issues/new\n [pr]:      https://github.com/helios-ag/FMElfinderBundle/pull/new\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2012- Al Ganiev\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "FMElfinderBundle\n================\n\n[ElFinder](https://github.com/Studio-42/elFinder) integration in Symfony\n\n### Code Quality Assurance ###\n\n| Tests | Coverage| License | Version |\n|-------------|-----------------|-----------------|----------------|\n|[![Tests - Linux](https://github.com/helios-ag/FMElfinderBundle/actions/workflows/test.yaml/badge.svg)](https://github.com/helios-ag/FMElfinderBundle/actions/workflows/test.yaml)|[![codecov](https://codecov.io/gh/helios-ag/FMElfinderBundle/graph/badge.svg?token=JcZh9UHGKs)](https://codecov.io/gh/helios-ag/FMElfinderBundle)|[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)|[![Latest Stable Version](https://poser.pugx.org/helios-ag/fm-elfinder-bundle/v/stable.svg)](https://packagist.org/packages/helios-ag/fm-elfinder-bundle)|\n\n\n| Downloads |\n|----------|\n|[![Total Downloads](https://poser.pugx.org/helios-ag/fm-elfinder-bundle/downloads.svg)](https://packagist.org/packages/helios-ag/fm-elfinder-bundle)|\n\n\n**elFinder** is an open-source file manager for web, written in JavaScript using jQuery UI.\nCreation is inspired by simplicity and convenience of Finder program used in Mac OS X operating system.\n\nRecommended bundles to use with:\n\n\n| FMTinyMCEBundle | FOSCKEditorBundle | FMSummernoteBundle |\n| ------------------------|-------------|-----------------|\n|[![FMTinyMCEBundle](https://img.shields.io/badge/FMTinyMCEBundle-download-brightgreen.svg)](https://github.com/helios-ag/FMTinyMCEBundle)|[![FOSCKEditorBundle](https://img.shields.io/badge/FOSCKEditorBundle-download-orange.svg)](https://github.com/FriendsOfSymfony/FOSCKEditorBundle)|[![FMSummernoteBundle](https://img.shields.io/badge/FMSummernoteBundle-download-brightgreen.svg)](https://github.com/helios-ag/summernote-bundle)|\n\n\n**Table of contents**\n\n- [Installation](#installation)\n  - [Step 1: Installation](#step-1-installation)\n  - [Step 2: Enable the bundle](#step-2-enable-the-bundle-optional)\n  - [Step 3: Import FMElfinderBundle routing file](#step-3-import-fmelfinderbundle-routing-file)\n  - [Step 4: Securing paths](#step-4-configure-your-applications-securityyaml)\n- [Basic configuration](#basic-configuration)\n  - [Add configuration options to your config.yaml](#add-configuration-options-to-your-configyaml)\n  - [Use multiple upload folder by instance](#use-multiple-upload-folder-by-instance)\n- [CORS support](/docs/cors-support.md)\n- [Events listeners / subscribers](/docs/events-listeners-subscribers.md)\n  - [Events](/docs/events-listeners-subscribers.md#events)\n  - [Sub requests](/docs/events-listeners-subscribers.md#sub-requests)\n- [Elfinder Form Type](/docs/elfinder-form-type.md)\n  - [Configuration](/docs/elfinder-form-type.md#configuration)\n  - [EasyAdmin 2.x](/docs/elfinder-form-type.md#easyadmin-2x-integration)\n  - [EasyAdmin 3.x/4.x](/docs/elfinder-form-type.md#easyadmin-3x/4x-integration)\n- [CKEditor integration](/docs/ckeditor-integration.md)\n  - [Installation](/docs/ckeditor-integration.md#step-1-installation)\n  - [Configuration](/docs/ckeditor-integration.md#step-2-configure-ckeditor-setting-via-settingsyml-or-through-form-builder)\n- [TinyMCE integration](/docs/tinymce-integration.md)\n  - [Integration with TinyMCE 3](/docs/tinymce-integration.md#tinymce-3x)\n  - [Integration with TinyMCE 4](/docs/tinymce-integration.md#tinymce-4x)\n- [Summernote integration](/docs/summernote-integration.md)\n- [Advanced configuration](/docs/advanced-configuration.md)\n  - [Custom configuration provider](/docs/advanced-configuration.md#custom-configuration-provider)\n  - [Custom loader](/docs/advanced-configuration.md#custom-loader)\n  - [Plugins](/docs/advanced-configuration.md#plugins)\n  - [Service as volume driver](/docs/advanced-configuration.md#symfony-service-as-a-volume-driver)\n  - [Flysystem configuration](/docs/advanced-configuration.md#flysystem-configuration)\n- [Configuration dump](/docs/configuration-dump.md)\n\n## Installation\n\n### Step 1: Installation\n\nFor Symfony Flex installation you need to enable community recipes:\n\n```sh\n  composer config extra.symfony.allow-contrib true\n```\n\nInstall\n\n```sh\n  composer require helios-ag/fm-elfinder-bundle\n```\n\nCopy elfinder assets to public folder\n\n```sh\n  bin/console elfinder:install\n```\n\n\n### Step 2: Enable the bundle (Optional)\n\nEnable the bundle in the kernel (not needed with symfony flex):\n\n```php\n<?php\n// app/AppKernel.php\n\npublic function registerBundles()\n{\n    $bundles = array(\n        // ...\n        new FM\\ElfinderBundle\\FMElfinderBundle(),\n    );\n}\n```\n\n### Step 3: Import FMElfinderBundle routing file\n\n``` yaml\n# app/config/routing.yaml\nelfinder:\n     resource: \"@FMElfinderBundle/Resources/config/routing.yaml\"\n```\n\n### Step 4: Configure your application's security.yaml\n\nSecure ElFinder with access_control:\n``` yaml\n# app/config/security.yaml\nsecurity:\n\n    //....\n    access_control:\n        - { path: ^/efconnect, role: ROLE_USER }\n        - { path: ^/elfinder, role: ROLE_USER }\n\n```\n\n## Basic configuration\n\n### Add configuration options to your config.yaml\n\n```yaml\nfm_elfinder:\n    #assets_path: / # default is /assets, this is where css/js elfinder files are\n    instances:\n        default:\n            locale: '%locale%' # defaults to current request locale\n            editor: ckeditor # other options are tinymce, tinymce4, fm_tinymce, form, simple, custom\n            relative_path: false #default true, will produce absolute urls to specified file(s)\n            #editor_template: custom template for your editor # default null\n            #path_prefix: / # for setting custom assets path prefix, useful for non vhost configurations, i.e. http://127.0.0.1/mysite/\n            #fullscreen: true|false # default is true, applies to simple and ckeditor editors\n            #theme: smoothness # jquery theme, default is 'smoothness'\n            #visible_mime_types: ['image/png', 'image/jpg', 'image/jpeg'] # only show these mime types, defaults to show all\n            connector:\n                #debug: true|false # defaults to false\n                roots:       # at least one root must be defined, defines root filemanager directories\n                    uploads:\n                        #show_hidden: true|false # defaults to false, hides dotfiles\n                        driver: LocalFileSystem\n                        path: uploads\n                        upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\n                        upload_deny: ['all']\n                        upload_max_size: 2M # also file upload sizes restricted in php.ini\n                        #attributes: example of setting attributes permission\n                        #    - { pattern: '/(.*?)/', read: true, write: false, locked: true }\n```\n* **default** - instance of elfinder, can be used to define multiple configurations of ElFinder, allows simultaneous configuration for different types of WYSIWYG editors in your project\n* **path** - define root directory for the files inside web/ directory, default is \"uploads\". Make sure to set proper write/read and owner permissions to this directory.\n* **url** - url to be prefixed to image path, for displaying. Can be either `absolute` or `relative`. If absolute, you can use `{homeFolder}` string as placeholder which will be replaced automatically. If relative, it will be prefixed with the applications base-url. If left blank, url will be the base-url, append with the value of the 'path' parameter\n* **driver** - can be LocalFileSystem, FTP or MySQL, Flysystem, S3 and etc, check class FM\\ElfinderBundle\\DependencyInjection\\Configuration\n* **locale** - locale determines, which language, ElFinder will use, to translate user interface, default is current request locale\n* **cors_support** - allows cross domain responses handling (default false)\n* **editor** - determines what template to render, to be compatible with WYSIWYG web editor, currently supported options are:\n  \"ckeditor\" (to use with FOSCKEditorBundle or TrsteelCkeditorBundle), \"fm_tinymce\" for tinymce4 (to use with FMTinyMCEBundle), \"form\" for form type, \"simple\" for standalone and \"custom\" for custom template.\n  How to configure CKEDitor and TinyMCE to work with this bundle, will be explained further in this document.\n* **editor_template** - define template to render when editor is set to \"custom\".\n* **connector** - root node for defining options for elfinder root directories.\n* **roots** - define \"virtual directories\" that reflect directories in your project.\n* **path_prefix** - path prefix with relative_path enabled, default is slash ('/')\n* **show_hidden** - show files and folders that starts from . (dot)\n* **driver** - driver type, LocalFileSystem, Dropbox, FTP\n* **volume_id** - (optional) can be used to force a volume id when mounting volume (default auto-increments). If provided, it must be an integer bigger than 0.\n* **alias** - directory alias\n* **path** - directory that contains files\n* **upload_allow**: ['image/png', 'image/jpg', 'image/jpeg']\n* **upload_deny**: ['all']\n* **upload_max_size**: 2M\n\nYou can see the full list of roots options [here](https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options#root-options \"connector options list\"). To use them,\nconvert camelCased option name to snake_case name.\n\n### Use multiple upload folder by instance\n\nYou can set multiple upload root folder by instance configuration.\n\nIf you have configured your instance with `/uploads` path, you can provide\nan additional folder as a home folder (e.g. for a multi-users application) when accessing to the instance URL :\n\n`/elfinder/{instance}/{homeFolder}` or `/efconnect/{instance}/{homeFolder}`\n\nFor example, accessing to `/elfinder/acmeInstance/bob` URL will open up elfinder with\n`/uploads/bob` as root directory which only contains Bob's files.\n\nThen, accessing to `/elfinder/acmeInstance/alice` URL will re-use your instance,\nbut open up elfinder with `/uploads/alice` folder as root directory, containing only Alice's files.\n\nTo use this feature, you **must** provide the instance name in the URL,\nand of course be sure to set proper write/read permissions on home folders.\n\n**Note:** this feature is only available with `LocalFileSystem` driver.\n\n\n## If I want more one home folder is possible ?\n\nYes you can with this configuration in your fm_elfinder.yaml\n\n```yaml\nwhere_is_multi:\n    {connector}: {index of the connector}\nmulti_home_folder: true\nfolder_separator: {one char other of /}\n```\n\n### Example\n```\nfm_elfinder:\n    instances:\n        default:\n            locale: fr # defaults to current request locale\n            editor: ckeditor # other options are tinymce, tinymce4, fm_tinymce, form, simple, custom\n            #editor_template: custom template for your editor # default null\n            #path_prefix: http://localhost/ # for setting custom assets path prefix, useful for non vhost configurations, i.e. http://127.0.0.1/mysite/\n            fullscreen: false # default is true, applies to simple and ckeditor editors\n            where_is_multi:\n                roots: 0\n            multi_home_folder: true\n            folder_separator: \"|\"\n            #theme: smoothness # jquery theme, default is 'smoothness'\n            #visible_mime_types: ['image/png', 'image/jpg', 'image/jpeg'] # only show these mime types, defaults to show all\n            connector:\n                #debug: true|false # defaults to false\n                roots:       # at least one root must be defined, defines root filemanager directories\n                    uploads:\n                        #show_hidden: true|false # defaults to false, hides dotfiles\n                        driver: LocalFileSystem\n                        path: \"/var\"\n                        alias: Bibliothèque générale\n                        upload_allow: ['all']\n                        #upload_deny: ['all']\n                        upload_max_size: 500M # also file upload sizes restricted in php.ini\n                        attributes:\n                            - {pattern: '..', read: true, write: true, locked: false}\n                        #attributes: example of setting attributes permission\n                        #    - { pattern: '/(.*?)/', read: true, write: false, locked: true }\n\n```\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"helios-ag/fm-elfinder-bundle\",\n    \"description\": \"ElFinder bundle, adds ElFinder file manager to your Symfony project\",\n    \"keywords\": [\"elfinder\", \"file manager\", \"wysiwyg\"],\n    \"type\": \"symfony-bundle\",\n    \"homepage\": \"https://github.com/helios-ag/FMElfinderBundle\",\n    \"minimum-stability\": \"dev\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Al Ganiev\",\n            \"email\": \"helios.ag@gmail.com\"\n        },\n        {\n            \"name\": \"Symfony Community\",\n            \"homepage\": \"https://github.com/helios-ag/FMElfinderBundle/contributors\"\n        }\n    ],\n    \"archive\": {\n      \"exclude\": [\"/tests\", \"./github\"]\n    },\n    \"require\": {\n        \"php\":                                 \"^8.1\",\n        \"ext-json\":                            \"*\",\n        \"symfony/console\":                     \"^6.4 || ^7.0 || ^8.0\",\n        \"symfony/framework-bundle\":            \"^6.4 || ^7.0 || ^8.0\",\n        \"symfony/twig-bundle\":                 \"^6.4 || ^7.0 || ^8.0\",\n        \"symfony/form\":                        \"^6.4 || ^7.0 || ^8.0\",\n        \"symfony/asset\":                       \"^6.4 || ^7.0 || ^8.0\",\n        \"studio-42/elfinder\":                  \"~2.1.62\"\n    },\n    \"require-dev\" : {\n        \"symfony/phpunit-bridge\":                           \"^6.4 || ^7.0.1 || ^8.0\",\n        \"matthiasnoback/symfony-config-test\":               \"^6.0\",\n        \"matthiasnoback/symfony-dependency-injection-test\": \"^6.0\",\n        \"symfony/finder\":                                   \"^6.4 || ^7.0 || ^8.0\",\n        \"php-coveralls/php-coveralls\":                      \"^2.0\",\n        \"friendsofphp/php-cs-fixer\":                        \"dev-master\"\n    },\n    \"suggest\": {\n        \"helios-ag/fm-tinymce-bundle\": \"FMTinyMCEBundle WYSIWYG Editor Bundle\",\n        \"helios-ag/fm-summernote-bundle\": \"FMSummernoteBundle WYSIWYG Editor Bundle\",\n        \"friendsofsymfony/ckeditor-bundle\": \"FOSCKEditorBundle WYSIWYG Editor Bundle\",\n        \"barryvdh/elfinder-flysystem-driver\": \"Flysystem driver for elfinder\",\n        \"spatie/flysystem-dropbox\": \"Dropbox 2 Driver for Flysystem\"\n    },\n    \"config\": {\n        \"sort-packages\": true,\n        \"preferred-install\": {\n            \"symfony/doctrine-bridge\": \"source\",\n            \"*\": \"dist\"\n        },\n        \"allow-plugins\": {\n            \"composer/installers\": true,\n            \"composer/package-versions-deprecated\": true,\n            \"oomphinc/composer-installers-extender\": true\n        }\n    },\n    \"autoload\": {\n        \"psr-4\": { \"FM\\\\ElfinderBundle\\\\\": \"src/\" }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": { \"FM\\\\ElfinderBundle\\\\Tests\\\\\": \"tests/\" }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-main\": \"13.x-dev\"\n        }\n    },\n    \"scripts\": {\n        \"auto-scripts\": {\n            \"cache:clear\": \"symfony-cmd\",\n            \"assets:install %PUBLIC_DIR%\": \"symfony-cmd\"\n        }\n    }\n}\n"
  },
  {
    "path": "config/command.yaml",
    "content": "services:\n    fm_elfinder.command.installer:\n        class: FM\\ElfinderBundle\\Command\\ElFinderInstallerCommand\n        arguments:\n            - '@Symfony\\Component\\Filesystem\\Filesystem'\n            - '@Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface'\n        tags:\n            - { name: 'console.command', command: 'elfinder:install' }\n"
  },
  {
    "path": "config/elfinder.yaml",
    "content": "parameters:\n    fm_elfinder.loader: FM\\ElfinderBundle\\Loader\\ElFinderLoader\n    fm_elfinder.configurator: FM\\ElfinderBundle\\Configuration\\ElFinderConfigurationReader\n\nservices:\n    fm_elfinder.configurator.default:\n        class: '%fm_elfinder.configurator%'\n        arguments:\n            - '%fm_elfinder%'\n            - '@request_stack'\n            - '@service_container'\n\n    fm_elfinder.loader.default:\n        class: '%fm_elfinder.loader%'\n        autowire: true\n        arguments:\n            - '@fm_elfinder.configurator'\n\n    FM\\ElfinderBundle\\Loader\\ElFinderLoader:\n        alias: fm_elfinder.loader.default\n\n    twig.extension.fm_elfinder_init:\n        class: FM\\ElfinderBundle\\Twig\\Extension\\FMElfinderExtension\n        arguments:\n            - '@twig'\n        tags:\n            - { name: 'twig.extension', alias: 'fm_elfinder_init' }\n\n    FM\\ElfinderBundle\\Controller\\ElFinderController:\n        tags:\n            - { name: 'controller.service_arguments' }\n        arguments:\n            - '@twig'\n            - ~\n            - '@fm_elfinder.loader'\n"
  },
  {
    "path": "config/form.yaml",
    "content": "parameters:\n    elfinder.form.type.class: FM\\ElfinderBundle\\Form\\Type\\ElFinderType\n\nservices:\n    fm_elfinder.form.type:\n        class: '%elfinder.form.type.class%'\n        tags:\n            - { name: 'form.type' }"
  },
  {
    "path": "docs/advanced-configuration.md",
    "content": "# Advanced configuration\n\n## Custom configuration provider\n\nElFinder bundle allows to override his configuration provider service:\n\n```yaml\nfm_elfinder:\n    configuration_provider: elfinder.configurator\n```\nwhere 'elfinder.configurator' is default ElFinder's bundle service to read configuration from DIC\n\nTo override service, simply define your own service:\n```yaml\nservices:\n    my_elfinder_configurator:\n        class:        Acme\\DemoBundle\\MyElfinderConfigurator\n        arguments:    [\"%my_arguments%\"]\n```\n\nConfiguration class must implement  ElFinderConfigurationProviderInterface\n\nmethod getConfiguration($instance) should return array of parameters compatible with ElFinder bundle configuration\n\n## Custom loader\n\nIt is possible to override loader service with your own class:\n\n```yaml\nservices:\n    my_loader:\n        class:        AppBundle\\Service\\MyElFinderLoader\n        arguments:    [@fm_elfinder.configurator]\n\nfm_elfinder:\n  loader: my_loader\n```\n\n## Custom archivers\n\nElfinder has the ability to make/extract diffrent type of archives. Using the following configuration you can add/remove/override archive types based on mime type.\n\n```yaml\nfm_elfinder:\n    instances:\n        themes:\n            locale: %locale% # defaults to current request locale\n            cors_support: true\n            editor: simple\n            connector:\n                debug: true # defaults to false\n                roots:       # at least one root must be defined\n                    uploads:\n                        driver: LocalFileSystem\n                        path: %theme_root%\n                        upload_allow: ['all']\n                        upload_max_size: 10M\n                        archive_mimes: \"application/zip\"\n                        archivers:\n                            create:\n                                application/zip:\n                                    cmd: \"phpfunction\"\n                                    argc: \"self::zipArchiveZip\"\n                                    ext: \"zip\"\n                            extract:\n                                application/myzip:\n                                    cmd: \"phpfunction\"\n                                    argc: \"self::zipArchiveUnzip\"\n                                    ext: \"zip\"\n```\n\n\n\n## Plugins\n\nElFinder comes with some plugins, like auto-resize, which can be enabled, by the following configuration:\n\n```yaml\nfm_elfinder:\n  instances:\n    tinymce:\n      locale: %locale%\n      editor: tinymce4\n      relative_path: true\n      fullscreen: true\n      connector:\n          debug: true # defaults to false\n          binds:\n              upload.presave:\n                  - Plugin.AutoResize.onUpLoadPreSave\n          plugins:\n              AutoResize: # global resize options, applies to root which don't have his own resize configuraion\n                  enable: true\n                  maxWidth: 750\n                  maxHeight: 750\n                  quality: 95 # JPEG image save quality\n          roots:       # at least one root must be defined\n              uploads:\n                  driver: LocalFileSystem\n                  path: uploads\n                  plugins:\n                      AutoResize:\n                          enable: true\n                          maxWidth: 500\n                          maxHeight: 500\n                          quality: 95 # JPEG image save quality\n                  upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\n                  upload_deny: ['all']\n                  upload_max_size: 2M\n              resize1:\n                  driver: LocalFileSystem\n                  path: uploads\n                  plugins:\n                      AutoResize:\n                          enable: true # For control by volume driver\n                          maxWidth: 800 # Path to Water mark image\n                          maxHeight: 800 # Margin right pixel\n                          quality: 95 # JPEG image save quality\n                  upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\n                  upload_deny: ['all']\n                  upload_max_size: 2M\n              resize2:\n                  driver: LocalFileSystem\n                  path: uploads\n                  plugins:\n                      AutoResize:\n                          enable: true\n                          maxWidth: 800\n                          maxHeight: 800\n                          quality: 95\n                  upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\n                  upload_deny: ['all']\n                  upload_max_size: 2M\n```\n\nElFinder comes with other plugins, check Plugins folder under ElFinderPHP for more information.\n\n## Symfony service as a volume driver\n\nvolumeDriver can be declared as Symfony service\nThe service should however be an instance of the FM\\ElFinderPHP\\Driver\\ElFinderVolumeDriver class. This check is to\nensure the service is a valid ElFinder VolumeDriver.\n\nTo configure a root with a service-driver you can simply use the service id as the drive key:\n\n```\nfm_elfinder:\n    connector:\n        roots:\n            uploads:\n                driver: elfinder.driver.filesystem\n                path: uploads\n```\n\nThis means that if you add the service definition:\n\n```xml\n<service id=\"elfinder.driver.filesystem\" class=\"FM\\ElFinderPHP\\Driver\\ElFinderVolumeLocalFileSystem\" />\n```\n\n## Flysystem configuration\n\nSince 4.0 bundle supports [flysystem](https://github.com/thephpleague/flysystem) filesystem abstraction library\n\nExample configuration can be found here [Flysystem](/docs/flysystem.md)\n"
  },
  {
    "path": "docs/ckeditor-integration.md",
    "content": "# CKEditor integration\n\nMostly filebrowsers used with WYSIWYG editors to upload images and other files. There are two bundles to work with CKEditor\navailable: [TrsteelCKEditorBundle](https://github.com/trsteel88/TrsteelCkeditorBundle) and [FOSCKEditorBundle](https://github.com/FriendsOfSymfony/FOSCKEditorBundle)\nBoth will work with this bundle.\n\n## Step 1: Installation\n\nInstall both bundles according README files\n\n## Step 2: Configure CKEditor setting via settings.yml or through form builder:\n\n```yaml\ntrsteel_ckeditor:\n    ...\n    filebrowser_image_browse_url:\n        route: elfinder\n        route_parameters:\n             instance: ckeditor\n```\n\nor if you prefer FOSCKEditorBundle\n\n```yaml\nfos_ck_editor:\n    default_config: default\n    configs:\n        default:\n            filebrowserBrowseRoute: elfinder\n            filebrowserBrowseRouteParameters: []\n```\n\nNote that instance name should be the same as configured in elfinder bundle\n\n```php\n// applies to Ivory CKEditor Bundle\n$form = $this->createFormBuilder()\n    ->add('content', 'ckeditor', array(\n            'config' => array(\n                'filebrowserBrowseRoute' => 'elfinder',\n                'filebrowserBrowseRouteParameters' => array(\n                    'instance' => 'default',\n                    'homeFolder' => ''\n                )\n            ),\n        ),\n    ))\n    ->getForm()\n;\n```\n\nElFinder will be available under Insert Image dialog\n"
  },
  {
    "path": "docs/configuration-dump.md",
    "content": "# Bundle configuration dump \n\n```\n# Default configuration for extension with alias: \"fm_elfinder\"\nfm_elfinder:\n    configuration_provider: fm_elfinder.configurator.default\n    assets_path:          assets\n    loader:               fm_elfinder.loader.default\n    instances:            # Required\n\n        # Prototype\n        name:\n            locale:               null\n            cors_support:         false\n            editor:               simple\n            editor_template:      null\n            fullscreen:           true\n            theme:                smoothness\n            include_assets:       true\n            tinymce_popup_path:   ''\n            relative_path:        true\n            path_prefix:          /\n            visible_mime_types:   []\n            connector:\n                debug:                false\n                binds:\n\n                    # Prototype\n                    name:\n\n                        # Prototype\n                        name:                 ~\n                plugins:\n\n                    # Prototype\n                    name:\n\n                        # Prototype\n                        name:                 ~\n                roots:                # Required\n\n                    # Prototype\n                    name:\n                        driver:               LocalFileSystem # Required\n                        volume_id:            0\n                        path:                 ''\n                        autoload:             false\n                        phash:                ''\n                        trash_hash:           ''\n                        locale:               ''\n                        i18n_folder_name:     false\n                        mime_detect:          auto\n                        mimefile:             ''\n                        security_voter:       ''\n                        start_path:           ''\n                        encoding:             UTF-8\n                        url:                  ''\n                        alias:                ''\n                        img_lib:              auto\n                        tmb_path:             .tmb\n                        tmb_path_mode:        511\n                        tmb_url:              ''\n                        tmb_size:             48\n                        tmb_crop:             true\n                        tmb_bg_color:         '#ffffff'\n                        copy_overwrite:       true\n                        copy_join:            true\n                        copy_from:            true\n                        copy_to:              true\n                        upload_overwrite:     true\n                        fileMode:             420\n                        upload_allow:\n\n                            # Default:\n                            - image\n                        upload_deny:\n\n                            # Default:\n                            - all\n                        upload_order:\n\n                            # Defaults:\n                            - deny\n                            - allow\n                        upload_max_size:      0\n                        defaults:\n\n                            # Prototype\n                            defaults:             ~\n                        attributes:\n\n                            # Prototype\n                            -\n                                pattern:              ~\n                                read:                 true\n                                write:                true\n                                locked:               false\n                                hidden:               false\n                        accepted_name:        '/^\\w[\\w\\s\\.\\%\\-]*$/u'\n                        show_hidden:          false\n                        disabled_commands:    []\n                        tree_deep:            0\n                        check_subfolders:     1\n                        separator:            /\n                        date_format:          'j M Y H:i'\n                        time_format:          'H:i'\n                        archive_mimes:        []\n                        archivers:\n                            enabled:              false\n                            create:\n\n                                # Prototype\n                                -\n                                    cmd:                  ~\n                                    argc:                 ~\n                                    ext:                  ~\n                            extract:\n\n                                # Prototype\n                                -\n                                    cmd:                  ~\n                                    argc:                 ~\n                                    ext:                  ~\n                        flysystem:\n                            enabled:              false\n                            filesystem:           ''\n                            type:                 ''\n                            adapter_service:      ''\n                            options:\n                                local:\n                                    enabled:              false\n                                    path:                 ''\n                                ftp:\n                                    enabled:              false\n                                    host:                 ''\n                                    username:             ''\n                                    password:             ''\n                                    port:                 21\n                                    passive:              true\n                                    ssl:                  true\n                                    timeout:              30\n                                    root:                 /\n                                    directoryPerm:        484\n                                sftp:\n                                    enabled:              false\n                                    host:                 ''\n                                    username:             ''\n                                    password:             ''\n                                    port:                 21\n                                    privateKey:           ''\n                                    timeout:              10\n                                    root:                 /\n                                azure:\n                                    enabled:              false\n                                    account_name:         ''\n                                    account_key:          ''\n                                    container_name:       ''\n                                aws_s3_v2:\n                                    enabled:              false\n                                    key:                  ''\n                                    secret:               ''\n                                    region:               ''\n                                    bucket_name:          ''\n                                    optional_prefix:      ''\n                                    base_url:             ''\n                                aws_s3_v3:\n                                    enabled:              false\n                                    key:                  ''\n                                    secret:               ''\n                                    region:               ''\n                                    version:              ''\n                                    bucket_name:          ''\n                                    optional_prefix:      ''\n                                    endpoint:             ''\n                                    use_path_style_endpoint: false\n                                    use_aws_shared_config_files: true\n                                    options:\n                                        enabled:              false\n                                        ACL:                  ''\n                                copy_com:\n                                    enabled:              false\n                                    consumer_key:         ''\n                                    consumer_secret:      ''\n                                    access_token:         ''\n                                    token_secret:         ''\n                                    optional_prefix:      ''\n                                gridfs:\n                                    enabled:              false\n                                    db_name:              ''\n                                zip:\n                                    enabled:              false\n                                    path:                 ''\n                                dropbox:\n                                    enabled:              false\n                                    app:                  ''\n                                    token:                ''\n                                rackspace:\n                                    enabled:              false\n                                    username:             ''\n                                    apikey:               ''\n                                    endpoint:             ''\n                                    container:            ''\n                                    region:               ''\n                        glide_url:            ''\n                        glide_key:            ''\n                        plugins:\n\n                            # Prototype\n                            name:\n\n                                # Prototype\n                                name:                 ~\n                        driver_options:\n\n                            # Prototype\n                            name:\n\n                                # Prototype\n                                name:                 ~\n                        dropbox2_settings:\n                            enabled:              false\n                            app_key:              ~\n                            app_secret:           ~\n                            access_token:         ~\n                            aliasFormat:          '%s@Dropbox'\n                            path:                 /\n                            separator:            /\n                            acceptedName:         '%s@Dropbox'\n                            rootCssClass:         elfinder-navbar-root-dropbox\n                            publishPermission:\n                                requested_visibility: public\n                            getThumbSize:         medium\n                        box_settings:\n                            enabled:              false\n                            client_id:            ~\n                            client_secret:        ~\n                            accessToken:          ~\n                            root:                 Box.com\n                            path:                 /\n                            separator:            /\n                            tmbPath:              ''\n                            tmbURL:               ''\n                            tmpPath:              ''\n                            acceptedName:         '#^[^/\\?*:|\"<>]*[^./\\?*:|\"<>]$#'\n                            rootCssClass:         elfinder-navbar-root-box\n                        onedrive_settings:\n                            enabled:              false\n                            client_id:            ~\n                            client_secret:        ~\n                            accessToken:          ~\n                            root:                 OneDrive.com\n                            OneDriveApiClient:    ''\n                            path:                 /\n                            separator:            /\n                            tmbPath:              ''\n                            tmbURL:               ''\n                            tmpPath:              ''\n                            acceptedName:         '#^[^/\\?*:|\"<>]*[^./\\?*:|\"<>]$#'\n                            rootCssClass:         elfinder-navbar-root-onedrive\n                            useApiThumbnail:      true\n                        ftp_settings:\n                            enabled:              false\n                            host:                 ~\n                            user:                 ~\n                            password:             ~\n                            path:                 ~\n                        s3_settings:\n                            enabled:              false\n                            access_key:           ~\n                            secret_key:           ~\n                            bucket:               ~\n                            tmp_path:             ~\n                            signature:            ~\n                            region:               ~\n                        mysql_settings:\n                            enabled:              false\n                            host:                 ~\n                            user:                 ~\n                            pass:                 ~\n                            db:                   ~\n                            port:                 null\n                            socket:               null\n                            files_table:          elfinder_file\n                            tmbPath:              ''\n                            tmpPath:              ''\n                            rootCssClass:         elfinder-navbar-root-sql\n                            noSessionCache:       hasdirs\n```"
  },
  {
    "path": "docs/cors-support.md",
    "content": "# CORS support\n\nIf you want access connector URL from an other domain on the client side,\nsimply configure FMElFinder bundle as you used to, and add the `cors_support: true` option to the cross domain instance:\n```yaml\n# app/config/config.yml\nfm_elfinder:\n    instances:\n        default:\n            locale: %locale% # defaults to current request locale\n            cors_support: true # allows cross domain responses handling (default false)\n            editor: ckeditor # other options are tinymce, tinymce4, form, custom and simple,\n            # ...\n```\n\nThen you have to add the CORS headers (`Access-Control-Allow-Origin`) to the response.\nIt can be easily done with [NelmioCORSBundle](https://github.com/nelmio/NelmioCorsBundle \"NelmioCORSBundle\") :\n\n```yaml\n# app/config/config.yml\nnelmio_cors:\n    defaults:\n        allow_credentials: false\n        allow_origin: []\n        allow_headers: []\n        allow_methods: []\n        expose_headers: []\n        max_age: 0\n        hosts: []\n    paths:\n        '^/efconnect':\n            allow_origin: ['*']\n            allow_headers: ['X-Custom-Auth', 'Content-Type', 'X-Requested-With']\n            allow_methods: ['POST', 'GET', 'PATCH', 'PUT', 'DELETE']\n            max_age: 3600\n            allow_credentials: true\n```\n"
  },
  {
    "path": "docs/elfinder-form-type.md",
    "content": "# Elfinder Form Type\n\n## Configuration\n\nBundle come with custom form type, `<input type=\"text\"/>`, that provide elfinder callback (opens Elfinder window).\n\nFirst, define instance with editor set to \"form\":\n\n```yaml\nfm_elfinder:\n    instances:\n        form:\n            locale: '%locale%' # defaults to current request locale\n            editor: form # other choices are tinymce or simple, and form\n            show_hidden: false # defaults to false\n            fullscreen: true # defaults true, applies to simple and ckeditor editors\n            connector:\n                debug: false # defaults to false\n                roots:       # at least one root must be defined\n                    uploads:\n                        driver: LocalFileSystem\n                        path: uploads\n                        upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\n                        upload_deny: ['all']\n                        upload_max_size: 2M\n```\n\nOn the second step, add to your form builder (or form class), elfinder type, and pass instance and `enable` parameters:\n\n```php\n// ...\nuse FM\\ElfinderBundle\\Form\\Type\\ElFinderType;\n// ...\n\n$form = $this->createFormBuilder()\n    ->add('elfinder', ElFinderType::class, ['instance' => 'form', 'enable' => true])\n    ->getForm();\n\n```\n\n\n```jinja\n<form action=\"\" method=\"post\" {{ form_enctype(form) }}>\n    {{ form_widget(form) }}\n    <input type=\"submit\" />\n</form>\n```\n\n## EasyAdmin 2.x integration\nTo get to work with EasyAdmin bundle (2.x):\n\n```yaml\n- { property: 'images', type: 'collection', label: 'Images', type_options: { allow_add: false, allow_delete: false, entry_type: 'FM\\ElfinderBundle\\Form\\Type\\ElFinderType' }}\n```\n\nand `easyadmin.yaml`\n\n```yaml\ndesign:\n    form_theme:\n      - '@EasyAdmin/form/bootstrap_4.html.twig'\n      - '@FMElfinder/Form/elfinder_widget.html.twig'\n``` \n\n## EasyAdmin 3.x/4.x integration\n\nAlmost same as for 2.x, but you need to add\n\n```php\n\n// ProjectCrudController.php\n// ...\npublic function configureFields(string $pageName): iterable\n{\n    // ...\n    yield Field::new('image', 'Image')\n        ->setFormType(ElFinderType::class)\n        ->setFormTypeOptions([\n            'instance' => 'default',\n            'enable' => true,\n        ])\n        ->onlyOnForms()\n    ;\n    // ...\n}\n\npublic function configureCrud(Crud $crud): Crud\n{\n    return $crud\n        // ...\n        ->addFormTheme('@FMElfinder/Form/elfinder_widget.html.twig')\n    ;\n}\n```\n\nCollection field:\n```php\n    return [\n        Field::new('cover', 'Cover')->setFormType(ElFinderType::class)\n                        ->setFormTypeOptions(\n                            [\n                                'instance' => 'image_form',\n                                'attr' => ['class' => 'col-6'],\n                            ]\n                        )\n                        ->hideOnIndex(),\n                    CollectionField::new('photos', 'Photos')\n                    ->setEntryType(PhotoType::class)\n    ];\n```\n\n```php\n    public function buildForm(FormBuilderInterface $builder, array $options)\n        {\n            $builder\n                ->add('path', ElFinderType::class, [\n                    'instance' => 'image_form',\n                    'enable' => true\n                ])\n                ->add('translations', TranslationsType::class, [\n                    'fields' => [\n                        'description' => [\n                            'field_type' => CKEditorType::class,\n                            'label' => 'Description',\n                        ],\n                    ],\n                ]);\n        }\n```\n\nAnd override elfidner_widget.html.twig\n```js\n    live('click', '[data-type=\"elfinder-input-field\"]', function (event) {\n                var id = $(this).attr('id');\n                var childWin = window.open(\"{{path('elfinder', {'instance': instance, 'homeFolder': homeFolder })}}?id=\"+id, \"popupWindow\", \"height=450, width=900\");\n        });\n```"
  },
  {
    "path": "docs/events-listeners-subscribers.md",
    "content": "# Events listeners / subscribers\n\n## Events\n\nThe bundle is throwing some events during an elFinder command execution :\n- `FM\\ElfinderBundle\\Event\\ElFinderEvents::PRE_EXECUTION` : `fm_elfinder.event.pre_execution`\n- `FM\\ElfinderBundle\\Event\\ElFinderEvents::POST_EXECUTION` : `fm_elfinder.event.post_execution`\n\nThe pre execution event has its own class (`FM\\ElfinderBundle\\Event\\ElFinderPreExecutionEvent`) which contains\nthe http request object, the elFinder instance name and the home folder.\n\nThe post execution event (`FM\\ElfinderBundle\\Event\\ElFinderPostExecutionEvent`) has the same attributes\nthan the pre execution events, plus the command result and a `hasErrors()` function indicating if\nerrors has been encountered during command execution.\nThe result to return to the elFinder.js client can be modified with the post execution event\nusing the `setResult` function on this event.\n\nYou can register event listeners with the `fm_elfinder.event_listener` tag\nand event subscribers with the `fm_elfinder.event_subscriber` tag.\n\n**Note:** you must set the [`cors_support`](https://github.com/helios-ag/FMElfinderBundle/blob/master/docs/cors-support.md \"CORS Support documentation\") option to `true` to use events.\nIf you don't, the symfony life cycle won't end properly and the post execution event won't be dispatched.\nOnly use the NelmioCORSBundle if your elFinder client is on an other domain.\n\nYou can access to all commands names [here](https://github.com/helios-ag/ElFinderPHP/blob/master/src/ElFinder.php#L61 \"elFinder commands\").\n\n## Sub requests\n\nEvents allows you to perform sub requests (only for commands used with HTTP GET method, i.e. not to upload a file).\nThese subrequests are working the same way than `forward` function on symfony controllers,\nand are also hookable.\n\n**Note:** You will have to set a `volume_id` to your instance's root to be sure the volume\nis mounted with the same ID between each requests.\n\nHere is an exemple of event listener on the post execution event, making a sub request :\n\n```xml\n<!-- src/AppBundle/Resources/config/services.xml -->\n<service id=\"app_bundle.listener.elfinder_post_execution\" class=\"AppBundle\\EventListener\\ElFinder\\PostExecutionListener\">\n    <tag name=\"fm_elfinder.event_listener\" event=\"fm_elfinder.event.post_execution\" method=\"onPostExecute\" />\n</service>\n```\n\n```php\n// src/AppBundle/EventListener/ElFinder/PostExecutionListener.php\nnamespace AppBundle\\EventListener\\ElFinder;\n\nuse FM\\ElfinderBundle\\Event\\ElFinderPostExecutionEvent;\n\nclass PostExecutionListener\n{\n    /**\n     * @param  ElFinderPostExecutionEvent $event\n     */\n    public function onPostExecute(ElFinderPostExecutionEvent $event)\n    {\n        if (!$event->hasErrors() && $event->getCommand() == 'tmb') { // 'tmb', 'mkdir', 'open', etc...\n            // do your stuff here\n            // ...\n            // you can perform a sub request\n            $queryParameters = $event->getRequest()->query->all(); // getting original request parameters\n            $queryParameters['cmd'] = 'info'; // changing the command to execute in sub request\n\n            $jsonResponse = $event->subRequest(array(\n                'instance' => $event->getInstance(),    // you can also make a subrequest on an other instance\n                'homeFolder' => $event->getHomeFolder() // and an other homeFolder\n            ), $queryParameters);\n\n            $data = json_decode($jsonResponse->getContent());\n            // work with sub request data\n            // ...\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/flysystem.md",
    "content": "Flysystem example configuration\r\n===============================\r\n\r\nYou will need library files to work with Flysystem:\r\n\r\nFirst add flysystem elfinder driver:\r\n\r\n```sh\r\ncomposer require barryvdh/elfinder-flysystem-driver\r\n```\r\n\r\nDepending which driver you want to use, you need require appropriate driver, for example:\r\n\r\n```sh\r\ncomposer require league/flysystem-aws-s3-v3\r\n```\r\n\r\nBelow example of configuring flysystem:\r\n\r\n```yaml\r\nfm_elfinder:\r\n    instances:\r\n        default:\r\n            locale: %locale% # defaults to current request locale\r\n            editor: ckeditor # other options are tinymce, tinymce4, form, custom and simple\r\n            fullscreen: true # defaults true, applies to simple and ckeditor editors\r\n            connector:\r\n                debug: false # defaults to false\r\n                roots:       # at least one root must be defined\r\n                      local:\r\n                          driver: Flysystem\r\n                          path: uploads\r\n                          flysystem:\r\n                              type: local\r\n                              options:\r\n                                local:\r\n                                    path: %kernel.root_dir%/../web/uploads/\r\n                          upload_allow: ['all']\r\n                          #upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\r\n                          #upload_deny: ['all']\r\n                          upload_max_size: 2M\r\n                      dropbox:\r\n                          driver: Flysystem\r\n                          path: uploads\r\n                          flysystem:\r\n                              type: dropbox\r\n                              options:\r\n                                dropbox:\r\n                                    app: YourAppname // see dropbox developer site\r\n                                    token: ToKeN // can be aquired via developer console\r\n                          upload_allow: ['all']\r\n                      aws_s3:\r\n                          driver: Flysystem\r\n                          path: uploads\r\n                          url: 'http://[my-bucket-name].s3.[region].amazonaws.com'\r\n                          tmb_url: 'self' # For thumbnail generation on aws\r\n                          flysystem:\r\n                              type: aws_s3_v3\r\n                              options:\r\n                                aws_s3_v3:\r\n                                    version: 'latest'\r\n                                    key: 'MY_AWS_KEY'\r\n                                    secret: 'MY_AWS_SECRET'\r\n                                    region: 'MY_AWS_REGION'\r\n                                    bucket_name: 'MY_BUCKET_NAME'\r\n                          upload_allow: ['all']\r\n```                          \r\n\r\nfor more options see [ElFinderConfigurationReader.php](https://github.com/helios-ag/FMElfinderBundle/blob/master/Configuration/ElFinderConfigurationReader.php)\r\n\r\n# Amazon S3 Configuration\r\n\r\nTo work with your S3 account and upload your files directly to S3 you have to set the following properties in your config file (config.yml).\r\n\r\n```yaml\r\nfm_elfinder:\r\n    instances:\r\n        default:\r\n            locale: %locale%\r\n            editor: ckeditor\r\n            fullscreen: true\r\n            relative_path: false\r\n            connector:\r\n                debug: false\r\n                roots:\r\n                  aws_s3:\r\n                      driver: Flysystem\r\n                      path: uploads\r\n                      url: 'http://[my-bucket-name].s3.[region].amazonaws.com'\r\n                      tmb_url: 'self' # For thumbnail generation on aws\r\n                      flysystem:\r\n                          type: aws_s3_v3\r\n                          options:\r\n                            aws_s3_v3:\r\n                                version: 'latest'\r\n                                key: 'MY_AWS_KEY'\r\n                                secret: 'MY_AWS_SECRET'\r\n                                region: 'MY_AWS_REGION'\r\n                                bucket_name: 'MY_BUCKET_NAME'\r\n                      upload_allow: ['all']\r\n```\r\n\r\nIn that case you use an S3 domain so the **relative_path** have to be false and the url have to be set to your S3 or Cloudfront Domain if you have mapped S3 directly to your filesystem work with the relative path.\r\n\r\nIf you don't set the **relative_path** to false you get a wrong URL after inserting that image to CKEditor for example.\r\nDefine the variables in your config.yml or set it directly.\r\n\r\nIf you don't use subdomain that contains your `bucket_name` and want to use your own **endpoint** make sure to set **use_path_style_endpoint** to `true` so that it will format the url correctly.\r\n\r\nTo prevent AWS PHP SDK from verifying the presence of a shared configuration in .aws/configuration make sure to set **use_aws_shared_config_files**  to `false`.\r\n\r\nAlso possible to define Flysystem adapters as services, it can be useful for self written adapters.\r\nTo use adapter as service, define it under 'services' node in your services.yml (or use DI)\r\n\r\n```services.yml\r\nservices:\r\n    local_adapter:\r\n        class: League\\Flysystem\\Adapter\\Local\r\n        arguments: [\"%kernel.root_dir%/../web/uploads/\"]\r\n```\r\n\r\nand configure flysystem node accordingly to use it\r\n\r\n```config.yml\r\nfm_elfinder:\r\n    instances:\r\n        adapter:\r\n            locale: %locale%\r\n            editor: simple\r\n            relative_path: true\r\n            connector:\r\n                roots:      \r\n                    uploads:\r\n                        show_hidden: false\r\n                        driver: Flysystem # !set driver to Flysystem\r\n                        flysystem:\r\n                            type: custom # !set type to custom, it will tell bundle to use custom driver\r\n                            adapter_service: 'local_adapter' # select previously configured adapter service\r\n                            options:\r\n                        path: ''\r\n                        upload_allow: ['all']\r\n```                        \r\n"
  },
  {
    "path": "docs/summernote-integration.md",
    "content": "# Summernote integration\n\nUpdate the editor property in your app/config.yml\nSet Summernote editor type:\n\n```yaml\nfm_elfinder:\n    editor: summernote\n```\n\nEdit template that contains summernote instance (the same way as for tinymce)\n\n```jinja\n{{ elfinder_summernote_init('instance_name') }}\n{{ summernote_init() }}\n```\n\nDon't forget to enable elfinder plugin in summernote configuration.\n"
  },
  {
    "path": "docs/tinymce-integration.md",
    "content": "# TinyMCE integration\n\nYou can integrate TinyMCE byself or use Bundles that already add TinyMCE functionality to your Symfony project.\nBelow instruction how to integrate [FMElfinderBundle](https://github.com/helios-ag/FMElfinderBundle) with [TinyMCEBundle](https://github.com/stfalcon/TinymceBundle)\n\nHow to use ElfinderBundle with [TinyMCEBundle](https://github.com/stfalcon/TinymceBundle)\n\n## TinyMCE 3.x\nInstruction for version 0.2.1 (TinyMCE 3.x)\nDownload bundles, configure, dump and install assets as written in installation steps\n\n**Configuration**\n\nUpdate the editor property in your app/config.yml\nSet TinyMce popup path:\n```yaml\nfm_elfinder:\n    editor: tinymce\n    tinymce_popup_path: \"asset[bundles/stfalcontinymce/vendor/tiny_mce/tiny_mce_popup.js]\"\n```\nUnder tinymce configuration node, theme configuration, add:\nfile_browser_callback : 'elFinderBrowser'\n\n```yaml\nstfalcon_tinymce:\n    theme:\n        simple:\n            file_browser_callback : 'elFinderBrowser'\n```\n\nafter (  {{ tinymce_init() }} ) function call\nplace ElfinderBundle's function:\n\n```jinja\n{{ elfinder_tinymce_init('instance_name', {'width':'900', 'height': '450', 'title':'ElFinder 2.0'}) }}\n```\n\nas shown below\n\n```jinja\n{{ tinymce_init() }}\n{{ elfinder_tinymce_init('instance_name') }}\n```\n\ninstance_name is an instance of elfinder's configuration\n\n## TinyMCE 4.x\n\nUpdate the editor property in your app/config.yml\n\n```yaml\nfm_elfinder:\n    editor: tinymce4\n```\n\nUnder tinymce configuration node, theme configuration, add:\nfile_browser_callback : elFinderBrowser\n\n```yaml\nstfalcon_tinymce:\n    theme:\n        simple:\n            file_browser_callback : elFinderBrowser\n```\n\nbefore (  {{ tinymce_init() }} ) function call (order is important)\nplace ElfinderBundle's function:\n{{ elfinder_tinymce_init4('instance_name', {'width':'900', 'height': '450', 'title':'ElFinder 2.0'} ) }}\nas shown below\n\n```jinja\n{{ elfinder_tinymce_init4('instance_name') }}\n{{ tinymce_init() }}\n```\n\ninstance_name is instance of elfinder configuration\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         bootstrap=\"tests/autoload.php\"\n         colors=\"true\"\n         xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/11.5/phpunit.xsd\"\n         cacheDirectory=\".phpunit.cache\"\n>\n<!--  <coverage>-->\n<!--    <report>-->\n<!--      <clover outputFile=\"./clover.xml\"/>-->\n<!--    </report>-->\n<!--  </coverage>-->\n  <php>\n    <server name=\"KERNEL_DIR\" value=\"./tests/Functional\"/>\n    <ini name=\"error_reporting\" value=\"-1\"/>\n    <!-- ###+ symfony/framework-bundle ### -->\n    <env name=\"APP_ENV\" value=\"dev\"/>\n    <env name=\"APP_SECRET\" value=\"\"/>\n    <!-- ###- symfony/framework-bundle ### -->\n  </php>\n  <testsuites>\n    <testsuite name=\"FMElfinderBundle test suite\">\n      <directory>./tests</directory>\n    </testsuite>\n  </testsuites>\n  <logging>\n    <!-- and this is where your report will be written -->\n  </logging>\n  <source>\n    <include>\n      <directory>./</directory>\n    </include>\n    <exclude>\n      <directory>./src/Controller</directory>\n      <directory>./src/Resources</directory>\n      <directory>./tests</directory>\n      <directory>./vendor</directory>\n    </exclude>\n  </source>\n</phpunit>\n"
  },
  {
    "path": "src/Bridge/ElFinderBridge.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Bridge;\n\nuse elFinderVolumeDriver;\nuse FM\\ElfinderBundle\\ElFinder\\ElFinder;\nuse Symfony\\Component\\HttpFoundation\\Session\\SessionInterface;\n\nclass ElFinderBridge extends ElFinder\n{\n    /** @var SessionInterface */\n    protected $session;\n\n    public function __construct($opts)\n    {\n        if ($this->session) {\n            $opts = array_merge($opts, ['session' => $this->session]);\n        }\n        parent::__construct($opts);\n    }\n\n    public function setSession($session)\n    {\n        $this->session = $session;\n    }\n\n    public function getVolumes(): array\n    {\n        return $this->volumes;\n    }\n\n    /**\n     * @param array $opts\n     */\n    protected function mountVolumes($opts)\n    {\n        foreach ($opts['roots'] as $i => $o) {\n            $volume = null;\n\n            if (isset($o['service'])) {\n                $driver = $o['service'];\n\n                if ($driver instanceof elFinderVolumeDriver) {\n                    $volume = $driver;\n                    unset($opts['roots'][$i]);\n                }\n            }\n\n            if ($volume && $volume->mount($o)) {\n                // unique volume id (ends on \"_\") - used as prefix to files hash\n                $id = $volume->id();\n\n                $this->volumes[$id] = $volume;\n\n                if (!$this->default && $volume->isReadable()) {\n                    $this->default = $this->volumes[$id];\n                }\n            }\n        }\n        parent::mountVolumes($opts);\n    }\n}\n"
  },
  {
    "path": "src/Command/ElFinderInstallerCommand.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Command;\n\nuse ReflectionClass;\nuse Symfony\\Component\\Console\\Attribute\\AsCommand;\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\nuse Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface;\nuse Symfony\\Component\\Filesystem\\Filesystem;\n\n#[AsCommand(\n    name: 'elfinder:install',\n    description: 'Copies elfinder assets to public directory',\n)]\nfinal class ElFinderInstallerCommand extends Command\n{\n    private const ELFINDER_CSS_DIR = 'css';\n\n    private const ELFINDER_JS_DIR = 'js';\n\n    private const ELFINDER_SOUNDS_DIR = 'sounds';\n\n    private const ELFINDER_IMG_DIR = 'img';\n\n    public function __construct(\n        protected Filesystem $fileSystem,\n        protected ParameterBagInterface $parameterBag\n    ) {\n        parent::__construct();\n    }\n\n    protected function configure(): void\n    {\n        $this\n            ->addOption('docroot', null, InputOption::VALUE_OPTIONAL, 'Website document root.', 'public')\n            ->addOption('elfinder-vendor-dir', null, InputOption::VALUE_REQUIRED, 'Vendor containing elfinder assets', 'studio-42/elfinder')\n            ->setHelp(<<<'EOF'\n                Default docroot:\n                  <info>public</info>\n\n                You can pass docroot:\n                  <info>Where to install elfinder</info>\n                  <info>php %command.full_name% --docroot=public_html</info>\n                EOF\n            );\n    }\n\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $io = new SymfonyStyle($input, $output);\n        $dr = $input->getOption('docroot');\n        $vendorDir = $input->getOption('elfinder-vendor-dir');\n        $io->title('elFinder Installer');\n        $io->comment(sprintf('Trying to install elfinder to %s directory', $dr));\n\n        $rootDir = $this->parameterBag->get('kernel.project_dir');\n\n        $publicDir = sprintf('%s/%s/bundles/fmelfinder', $rootDir, $dr);\n\n        $reflection = new ReflectionClass(\\Composer\\Autoload\\ClassLoader::class);\n        $vendorRootDir = dirname($reflection->getFileName(), 3) . '/vendor';\n\n        $io->note(sprintf('Starting to install elfinder to %s folder', $publicDir));\n\n        // validate $vendorDir to match namespace/vendor name\n        if (!preg_match('/^([a-z0-9-]+)\\/([a-z0-9-]+)$/i', $vendorDir)) {\n            $io->error(sprintf('Invalid vendor directory name %s', $vendorDir));\n\n            return Command::FAILURE;\n        }\n\n        $this->fileSystem->mirror($vendorRootDir . '/' . $vendorDir . '/' . self::ELFINDER_CSS_DIR, $publicDir . '/css');\n        $this->fileSystem->mirror($vendorRootDir . '/' . $vendorDir . '/' . self::ELFINDER_IMG_DIR, $publicDir . '/img');\n        $this->fileSystem->mirror($vendorRootDir . '/' . $vendorDir . '/' . self::ELFINDER_JS_DIR, $publicDir . '/js');\n        $this->fileSystem->mirror($vendorRootDir . '/' . $vendorDir . '/' . self::ELFINDER_SOUNDS_DIR, $publicDir . '/sounds');\n\n        $io->success('elFinder assets successfully installed');\n\n        return Command::SUCCESS;\n    }\n}\n"
  },
  {
    "path": "src/Configuration/ElFinderConfigurationProviderInterface.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Configuration;\n\ninterface ElFinderConfigurationProviderInterface\n{\n    public function getConfiguration(string $instance): array;\n}\n"
  },
  {
    "path": "src/Configuration/ElFinderConfigurationReader.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Configuration;\n\nuse Aws\\S3\\S3Client;\nuse Barracuda\\Copy\\API;\nuse Exception;\nuse FM\\ElfinderBundle\\Security\\ElfinderSecurityInterface;\nuse League\\Flysystem\\Adapter\\Ftp;\nuse League\\Flysystem\\Adapter\\Local;\nuse League\\Flysystem\\AdapterInterface;\nuse League\\Flysystem\\AwsS3v2\\AwsS3Adapter as AwsS3v2;\nuse League\\Flysystem\\AwsS3V3\\AwsS3V3Adapter as AwsS3v3;\nuse League\\Flysystem\\AzureBlobStorage\\AzureBlobStorageAdapter;\nuse League\\Flysystem\\Copy\\CopyAdapter;\nuse League\\Flysystem\\Filesystem;\nuse League\\Flysystem\\GridFS\\GridFSAdapter;\nuse League\\Flysystem\\Rackspace\\RackspaceAdapter;\nuse League\\Flysystem\\Sftp\\SftpAdapter;\nuse League\\Flysystem\\ZipArchive\\ZipArchiveAdapter;\nuse MicrosoftAzure\\Storage\\Blob\\BlobRestProxy;\nuse MongoClient;\nuse OpenCloud\\Rackspace;\nuse Spatie\\Dropbox\\Client;\nuse Spatie\\FlysystemDropbox\\DropboxAdapter;\nuse Symfony\\Component\\DependencyInjection\\ContainerInterface;\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpFoundation\\RequestStack;\nuse TypeError;\n\nclass ElFinderConfigurationReader implements ElFinderConfigurationProviderInterface\n{\n    protected array $options = [];\n\n    protected array $parameters;\n\n    protected RequestStack $requestStack;\n\n    protected ContainerInterface $container;\n\n    public function __construct(array $parameters, RequestStack $requestStack, ContainerInterface $container)\n    {\n        $this->parameters   = $parameters;\n        $this->requestStack = $requestStack;\n        $this->container    = $container;\n    }\n\n    public function getConfiguration(string $instance): array\n    {\n        $request                = $this->requestStack->getCurrentRequest();\n        $efParameters           = $this->parameters;\n        $parameters             = $efParameters['instances'][$instance];\n        $options                = [];\n        $options['corsSupport'] = $parameters['cors_support'];\n        $options['debug']       = $parameters['connector']['debug'];\n        $options['bind']        = $parameters['connector']['binds'];\n        $options['plugin']      = $parameters['connector']['plugins'];\n        $options['roots']       = [];\n\n        foreach ($parameters['connector']['roots'] as $parameter) {\n            $path              = $parameter['path'];\n            $homeFolder        = $request->attributes->get('homeFolder');\n            $pathAndHomeFolder = $homeFolder ? sprintf('%s/%s', $path, $homeFolder) : $path;\n\n            if ($parameter['flysystem']['enabled']) {\n                if ($parameter['flysystem']['filesystem']) {\n                    $serviceName = $parameter['flysystem']['filesystem'];\n                    $filesystem  = $this->getFlysystemFilesystem($serviceName);\n                } else {\n                    $adapter     = $parameter['flysystem']['type']; // ftp ex.\n                    $serviceName = $parameter['flysystem']['adapter_service'];\n                    $opt         = $parameter['flysystem']['options'];\n                    $filesystem  = $this->configureFlysystem($opt, $adapter, $serviceName);\n                }\n            }\n            $driver = $this->container->has($parameter['driver']) ? $this->container->get($parameter['driver']) : false;\n\n            $driverOptions = [\n                'driver'          => $parameter['driver'],\n                'service'         => $driver,\n                'glideURL'        => $parameter['glide_url'],\n                'glideKey'        => $parameter['glide_key'],\n                'plugin'          => $options['plugin'],\n                'path'            => $pathAndHomeFolder,\n                'startPath'       => $parameter['start_path'],\n                'encoding'        => $parameter['encoding'],\n                'URL'             => $this->getURL($parameter, $request, $homeFolder, $path),\n                'alias'           => $parameter['alias'],\n                'mimeDetect'      => $parameter['mime_detect'],\n                'mimefile'        => $parameter['mimefile'],\n                'imgLib'          => $parameter['img_lib'],\n                'tmbPath'         => $parameter['tmb_path'],\n                'tmbPathMode'     => $parameter['tmb_path_mode'],\n                'tmbURL'          => $parameter['tmb_url'],\n                'tmbSize'         => $parameter['tmb_size'],\n                'tmbCrop'         => $parameter['tmb_crop'],\n                'tmbBgColor'      => $parameter['tmb_bg_color'],\n                'copyOverwrite'   => $parameter['copy_overwrite'],\n                'copyJoin'        => $parameter['copy_join'],\n                'copyFrom'        => $parameter['copy_from'],\n                'copyTo'          => $parameter['copy_to'],\n                'uploadOverwrite' => $parameter['upload_overwrite'],\n                'uploadAllow'     => $parameter['upload_allow'],\n                'uploadDeny'      => $parameter['upload_deny'],\n                'uploadMaxSize'   => $parameter['upload_max_size'],\n                'uploadMaxConn'   => $parameter['upload_max_conn'],\n                'defaults'        => $parameter['defaults'],\n                'attributes'      => $parameter['attributes'],\n                'acceptedName'    => $parameter['accepted_name'],\n                'disabled'        => $parameter['disabled_commands'],\n                'treeDeep'        => $parameter['tree_deep'],\n                'checkSubfolders' => $parameter['check_subfolders'],\n                'separator'       => $parameter['separator'],\n                'timeFormat'      => $parameter['time_format'],\n                'archiveMimes'    => $parameter['archive_mimes'],\n                'archivers'       => $parameter['archivers'],\n                'fileMode'        => $parameter['fileMode'],\n                'trashHash'       => $parameter['trash_hash'],\n            ];\n\n            if (null !== $parameter['quarantine']) {\n                $driverOptions['quarantine'] = $parameter['quarantine'];\n            }\n\n            if ($parameter['volume_id'] > 0) {\n                $driverOptions['id'] = $parameter['volume_id'];\n            }\n\n            if (!$parameter['show_hidden']) {\n                $driverOptions['accessControl'] = [$this, 'access'];\n            }\n\n            if ($parameter['security_voter']) {\n                /** @var ElfinderSecurityInterface $voter */\n                $voter = $this->container->get($parameter['security_voter']);\n\n                $driverOptions['disabled'] = $this->parseSecurityConfiguration($voter);\n            }\n\n            if ('Flysystem' == $parameter['driver']) {\n                $driverOptions['filesystem'] = $filesystem;\n            }\n            $options['roots'][] = array_merge($driverOptions, $this->configureDriver($parameter));\n        }\n\n        return $options;\n    }\n\n    /**\n     * Simple function to demonstrate how to control file access using \"accessControl\" callback.\n     * This method will disable accessing files/folders starting from '.' (dot).\n     *\n     * @param string $attr attribute name (read|write|locked|hidden)\n     * @param string $path file path relative to volume root directory started with directory separator\n     *\n     * @return bool|null\n     */\n    public function access($attr, $path, $data, $volume)\n    {\n        return 0 === strpos(basename($path), '.')       // if file/folder begins with '.' (dot)\n            ? !('read' == $attr || 'write' == $attr)    // set read+write to false, other (locked+hidden) set to true\n            : null;                                    // else elFinder decide it itself\n    }\n\n    /**\n     * @return array\n     */\n    protected function parseSecurityConfiguration(ElfinderSecurityInterface $voter)\n    {\n        $configuration = $voter->getConfiguration();\n\n        if (!is_array($configuration)) {\n            throw new Exception('ElfinderSecurityVoter should return array');\n        }\n\n        foreach ($configuration as $role => $commands) {\n            if ($this->container->get('security.authorization_checker')->isGranted($role)) {\n                return $commands;\n            }\n        }\n\n        return [];\n    }\n\n    private function getURL(array $parameter, Request $request, string $homeFolder, string $path): string\n    {\n        if (isset($parameter['url']) && $parameter['url']) {\n            if (0 === strpos($parameter['url'], 'http')) {\n                return str_replace('{homeFolder}', $homeFolder, $parameter['url']);\n            }\n\n            $path = $parameter['url'] . '/' . $homeFolder;\n        } else {\n            $path = $path . '/' . $homeFolder;\n        }\n\n        return $request->getUriForPath('/' . trim($path, '/'));\n    }\n\n    /**\n     * @return Filesystem\n     */\n    private function configureFlysystem($opt, $adapter, $serviceName)\n    {\n        $filesystem = null;\n        switch ($adapter) {\n            case 'local':\n                $filesystem = new Filesystem(new Local($opt['local']['path']));\n\n                break;\n            case 'ftp':\n                $settings = [\n                    'host'     => $opt['ftp']['host'],\n                    'username' => $opt['ftp']['username'],\n                    'password' => $opt['ftp']['password'],\n\n                    /* optional config settings */\n                    'port'          => $opt['ftp']['port'],\n                    'root'          => $opt['ftp']['root'],\n                    'passive'       => $opt['ftp']['passive'],\n                    'ssl'           => $opt['ftp']['ssl'],\n                    'timeout'       => $opt['ftp']['timeout'],\n                    'directoryPerm' => $opt['ftp']['directoryPerm'],\n                ];\n                $filesystem = new Filesystem(new Ftp($settings));\n\n                break;\n            case 'sftp':\n                $settings = [\n                  'host'       => $opt['sftp']['host'],\n                  'port'       => $opt['sftp']['port'],\n                  'username'   => $opt['sftp']['username'],\n                  'password'   => $opt['sftp']['password'],\n                  'privateKey' => $opt['sftp']['privateKey'],\n                  'root'       => $opt['sftp']['root'],\n                  'timeout'    => $opt['sftp']['timeout'],\n                ];\n                $filesystem = new Filesystem(new SftpAdapter($settings));\n\n                break;\n            case 'azure':\n                $client = BlobRestProxy::createBlobService(\n                    sprintf('DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;', $opt['azure']['account_name'], $opt['azure']['account_key'])\n                );\n                $adapter    = new AzureBlobStorageAdapter($client, $opt['azure']['container_name']);\n                $filesystem = new Filesystem($adapter);\n\n                break;\n            case 'aws_s3_v2':\n                $options = [\n                    'key'    => $opt['aws_s3_v2']['key'],\n                    'secret' => $opt['aws_s3_v2']['secret'],\n                    'region' => $opt['aws_s3_v2']['region'],\n                ];\n\n                if (isset($opt['aws_s3_v2']['base_url']) && $opt['aws_s3_v2']['base_url']) {\n                    $options['base_url'] = $opt['aws_s3_v2']['base_url'];\n                }\n                $client     = S3Client::factory($options);\n                $filesystem = new Filesystem(new AwsS3v2($client, $opt['aws_s3_v2']['bucket_name'], $opt['aws_s3_v2']['optional_prefix']));\n\n                break;\n            case 'aws_s3_v3':\n                $s3Options = [\n                    'region'                      => $opt['aws_s3_v3']['region'],\n                    'version'                     => $opt['aws_s3_v3']['version'],\n                    'endpoint'                    => $opt['aws_s3_v3']['endpoint'],\n                    'use_path_style_endpoint'     => $opt['aws_s3_v3']['use_path_style_endpoint'],\n                    'use_aws_shared_config_files' => $opt['aws_s3_v3']['use_aws_shared_config_files'],\n                ];\n\n                if (!empty($opt['aws_s3_v3']['key']) && !empty($opt['aws_s3_v3']['secret'])) {\n                    $s3Options['credentials'] = [\n                        'key'    => $opt['aws_s3_v3']['key'],\n                        'secret' => $opt['aws_s3_v3']['secret'],\n                    ];\n                }\n                $client     = new S3Client($s3Options);\n                $filesystem = new Filesystem(new AwsS3v3($client, $opt['aws_s3_v3']['bucket_name'], $opt['aws_s3_v3']['optional_prefix'], null, null, $opt['aws_s3_v3']['options'] ?? []));\n\n                break;\n            case 'copy_com':\n                $client = new API(\n                    $opt['copy_com']['consumer_key'],\n                    $opt['copy_com']['consumer_secret'],\n                    $opt['copy_com']['access_token'],\n                    $opt['copy_com']['token_secret']\n                );\n                $filesystem = new Filesystem(new CopyAdapter($client, $opt['copy_com']['optional_prefix']));\n\n                break;\n            case 'gridfs':\n                $mongoClient = new MongoClient();\n                $gridFs      = $mongoClient->selectDB($opt['gridfs']['db_name'])->getGridFS();\n                $filesystem  = new Filesystem(new GridFSAdapter($gridFs));\n\n                break;\n            case 'zip':\n                $filesystem = new Filesystem(new ZipArchiveAdapter($opt['zip']['path']));\n\n                break;\n            case 'dropbox':\n                $filesystem = new Filesystem(new DropboxAdapter(new Client($opt['dropbox']['token'])));\n\n                break;\n            case 'rackspace':\n                $client = new Rackspace(Rackspace::$opt['rackspace']['endpoint'], [\n                    'username' => $opt['rackspace']['username'],\n                    'apiKey'   => $opt['rackspace']['apikey'],\n                ]);\n                $store      = $client->objectStoreService('cloudFiles', $opt['rackspace']['region']);\n                $container  = $store->getContainer($opt['rackspace']['container']);\n                $filesystem = new Filesystem(new RackspaceAdapter($container));\n\n                break;\n            case 'custom':\n                $adapter = $this->container->get($serviceName);\n\n                try {\n                    $filesystem = new Filesystem($adapter);\n                } catch (TypeError $error) {\n                    throw new Exception(sprintf('Service %s is not an instance of %s.', $serviceName, AdapterInterface::class));\n                }\n\n                break;\n        }\n\n        return $filesystem;\n    }\n\n    private function getFlysystemFilesystem(string $serviceName): Filesystem\n    {\n        $filesystem = $this->container->get($serviceName);\n\n        if (!is_object($filesystem) || (!$filesystem instanceof Filesystem)) {\n            throw new Exception(sprintf('Service %s is not an instance of %s.', $serviceName, Filesystem::class));\n        }\n\n        return $filesystem;\n    }\n\n    private function configureDriver(array $parameter): array\n    {\n        $settings = [];\n\n        switch (strtolower($parameter['driver'])) {\n            case 'ftp':\n                $settings['host'] = $parameter['ftp_settings']['host'];\n                $settings['user'] = $parameter['ftp_settings']['user'];\n                $settings['pass'] = $parameter['ftp_settings']['password'];\n                $settings['path'] = $parameter['ftp_settings']['path'];\n\n                break;\n            case 'mysql':\n                $settings['host']           = $parameter['mysql_settings']['host'];\n                $settings['user']           = $parameter['mysql_settings']['user'];\n                $settings['pass']           = $parameter['mysql_settings']['pass'];\n                $settings['db']             = $parameter['mysql_settings']['db'];\n                $settings['port']           = $parameter['mysql_settings']['port'];\n                $settings['socket']         = $parameter['mysql_settings']['socket'];\n                $settings['files_table']    = $parameter['mysql_settings']['files_table'];\n                $settings['tmbPath']        = $parameter['mysql_settings']['tmbPath'];\n                $settings['tmpPath']        = $parameter['mysql_settings']['tmpPath'];\n                $settings['rootCssClass']   = $parameter['mysql_settings']['rootCssClass'];\n                $settings['noSessionCache'] = explode(',', $parameter['mysql_settings']['noSessionCache']);\n\n                break;\n            case 'dropbox2':\n                $settings['app_key']           = $parameter['dropbox2_settings']['app_key'];\n                $settings['app_secret']        = $parameter['dropbox2_settings']['app_secret'];\n                $settings['access_token']      = $parameter['dropbox2_settings']['access_token'];\n                $settings['aliasFormat']       = $parameter['dropbox2_settings']['aliasFormat'];\n                $settings['path']              = $parameter['dropbox2_settings']['path'];\n                $settings['separator']         = $parameter['dropbox2_settings']['separator'];\n                $settings['acceptedName']      = $parameter['dropbox2_settings']['acceptedName'];\n                $settings['rootCssClass']      = $parameter['dropbox2_settings']['rootCssClass'];\n                $settings['publishPermission'] = $parameter['dropbox2_settings']['publishPermission'];\n                $settings['getThumbSize']      = $parameter['dropbox2_settings']['getThumbSize'];\n\n                break;\n            case 'onedrive':\n                $settings['client_id']         = $parameter['onedrive_settings']['client_id'];\n                $settings['client_secret']     = $parameter['onedrive_settings']['client_secret'];\n                $settings['accessToken']       = $parameter['onedrive_settings']['accessToken'];\n                $settings['root']              = $parameter['onedrive_settings']['root'];\n                $settings['OneDriveApiClient'] = $parameter['onedrive_settings']['OneDriveApiClient'];\n                $settings['path']              = $parameter['onedrive_settings']['path'];\n                $settings['separator']         = $parameter['onedrive_settings']['separator'];\n                $settings['tmbPath']           = $parameter['onedrive_settings']['tmbPath'];\n                $settings['tmbURL']            = $parameter['onedrive_settings']['tmbURL'];\n                $settings['tmpPath']           = $parameter['onedrive_settings']['tmpPath'];\n                $settings['acceptedName']      = $parameter['onedrive_settings']['acceptedName'];\n                $settings['rootCssClass']      = $parameter['onedrive_settings']['rootCssClass'];\n                $settings['useApiThumbnail']   = $parameter['onedrive_settings']['useApiThumbnail'];\n\n                break;\n            case 'box':\n                $settings['client_id']     = $parameter['box_settings']['client_id'];\n                $settings['client_secret'] = $parameter['box_settings']['client_secret'];\n                $settings['accessToken']   = $parameter['box_settings']['accessToken'];\n                $settings['root']          = $parameter['box_settings']['root'];\n                $settings['path']          = $parameter['box_settings']['path'];\n                $settings['separator']     = $parameter['box_settings']['separator'];\n                $settings['tmbPath']       = $parameter['box_settings']['tmbPath'];\n                $settings['tmbURL']        = $parameter['box_settings']['tmbURL'];\n                $settings['acceptedName']  = $parameter['box_settings']['acceptedName'];\n                $settings['rootCssClass']  = $parameter['box_settings']['rootCssClass'];\n\n                break;\n            default:\n                break;\n        }\n\n        return $settings;\n    }\n}\n"
  },
  {
    "path": "src/Connector/ElFinderConnector.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Connector;\n\nuse elFinder;\n\nclass ElFinderConnector extends \\elFinderConnector\n{\n    public function run($queryParameters = null)\n    {\n        if (null === $queryParameters) {\n            $queryParameters = $_GET;\n        }\n\n        return $this->execute($queryParameters);\n    }\n\n    public function execute($queryParameters)\n    {\n        $isPost = 'POST' == $_SERVER['REQUEST_METHOD'];\n        $src    = 'POST' == $_SERVER['REQUEST_METHOD'] ? array_merge($_POST, $queryParameters) : $queryParameters;\n\n        if ($isPost && !$src && $rawPostData = @file_get_contents('php://input')) {\n            // for support IE XDomainRequest()\n            $parts = explode('&', $rawPostData);\n            foreach ($parts as $part) {\n                [$key, $value] = array_pad(explode('=', $part), 2, '');\n                $src[$key]     = rawurldecode($value);\n            }\n            $_POST    = $src;\n            $_REQUEST = array_merge_recursive($src, $_REQUEST);\n        }\n        $cmd  = $src['cmd'] ?? '';\n        $args = [];\n\n        if (!function_exists('json_encode')) {\n            $error = $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_JSON);\n\n            return $this->output(['error' => '{\"error\":[\"' . implode('\",\"', $error) . '\"]}', 'raw' => true]);\n        }\n\n        if (!$this->elFinder->loaded()) {\n            return $this->output(['error' => $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_VOL), 'debug' => $this->elFinder->mountErrors]);\n        }\n\n        // telepat_mode: on\n        if (!$cmd && $isPost) {\n            return $this->output(['error' => $this->elFinder->error(elFinder::ERROR_UPLOAD, elFinder::ERROR_UPLOAD_TOTAL_SIZE), 'header' => 'Content-Type: text/html']);\n        }\n        // telepat_mode: off\n\n        if (!$this->elFinder->commandExists($cmd)) {\n            return $this->output(['error' => $this->elFinder->error(elFinder::ERROR_UNKNOWN_CMD)]);\n        }\n\n        // collect required arguments to exec command\n        foreach ($this->elFinder->commandArgsList($cmd) as $name => $req) {\n            $arg = 'FILES' == $name\n                ? $_FILES\n                : ($src[$name] ?? '');\n\n            if (!is_array($arg)) {\n                $arg = trim($arg);\n            }\n\n            if ($req && (!isset($arg) || '' === $arg)) {\n                return $this->output(['error' => $this->elFinder->error(elFinder::ERROR_INV_PARAMS, $cmd)]);\n            }\n            $args[$name] = $arg;\n        }\n\n        $args['debug'] = isset($src['debug']) && $src['debug'];\n\n        return $this->output($this->elFinder->exec($cmd, $this->input_filter($args)));\n    }\n\n    protected function output(array $data)\n    {\n        if (isset($data['pointer'])) {\n            parent::output($data);\n        }\n\n        return $data;\n    }\n}\n"
  },
  {
    "path": "src/Controller/ElFinderController.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Controller;\n\nuse Exception;\nuse FM\\ElfinderBundle\\Event\\ElFinderPostExecutionEvent;\nuse FM\\ElfinderBundle\\Event\\ElFinderPreExecutionEvent;\nuse FM\\ElfinderBundle\\Loader\\ElFinderLoader;\nuse FM\\ElfinderBundle\\Loader\\ElFinderLoaderInterface;\nuse Symfony\\Component\\Asset\\Package;\nuse Symfony\\Component\\Asset\\VersionStrategy\\EmptyVersionStrategy;\nuse Symfony\\Component\\EventDispatcher\\EventDispatcherInterface;\nuse Symfony\\Component\\HttpFoundation\\JsonResponse;\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpFoundation\\Response;\nuse Symfony\\Component\\HttpFoundation\\Session\\SessionInterface;\nuse Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException;\nuse Symfony\\Component\\HttpKernel\\HttpKernelInterface;\nuse Twig\\Environment;\n\nclass ElFinderController\n{\n    protected array $params;\n    private Environment $twig;\n    private ElFinderLoaderInterface $loader;\n\n    public function __construct(Environment $twig, array $params, ElFinderLoaderInterface $loader)\n    {\n        $this->twig   = $twig;\n        $this->params = $params;\n        $this->loader = $loader;\n    }\n\n    /**\n     * Renders Elfinder.\n     *\n     * @throws Exception\n     */\n    public function show(Request $request, string $instance, string $homeFolder): Response\n    {\n        $efParameters = $this->params;\n\n        if (empty($efParameters['instances'][$instance])) {\n            throw new NotFoundHttpException('Instance not found');\n        }\n        $parameters = $efParameters['instances'][$instance];\n\n        if (empty($parameters['locale'])) {\n            $parameters['locale'] = $request->getLocale();\n        }\n\n        $assetsPath = $efParameters['assets_path'];\n        $result     = $this->selectEditor($parameters, $instance, $homeFolder, $assetsPath, $request->query->get('id'));\n\n        return new Response($this->twig->render($result['template'], $result['params']));\n    }\n\n    public function load(SessionInterface $session, HttpKernelInterface $httpKernel, EventDispatcherInterface $eventDispatcher, Request $request, string $instance, string $homeFolder): JsonResponse\n    {\n        $loader       = $this->loader;\n        $efParameters = $this->params;\n        $loader->initBridge($instance, $efParameters); // builds up the Bridge object for the loader with the given instance\n\n        if ($loader instanceof ElFinderLoader) {\n            $loader->setSession($session);\n        }\n\n        $preExecutionEvent = new ElFinderPreExecutionEvent($request, $httpKernel, $instance, $homeFolder);\n        $eventDispatcher->dispatch($preExecutionEvent);\n\n        $result = $loader->load($request); // the instance is already set\n\n        $postExecutionEvent = new ElFinderPostExecutionEvent($request, $httpKernel, $instance, $homeFolder, $result);\n        $eventDispatcher->dispatch($postExecutionEvent);\n\n        // returning result (who may have been modified by a post execution event listener)\n        return new JsonResponse($postExecutionEvent->getResult());\n    }\n\n    public function mainJS(): Response\n    {\n        $version = new EmptyVersionStrategy();\n        $package = new Package($version);\n        $mainUrl = $package->getUrl(sprintf('%s/bundles/fmelfinder/js', $this->params['assets_path']));\n\n        return new Response(\n            $this->twig->render('@FMElfinder/Elfinder/helper/main.js.twig',['mainUrl' => $mainUrl]),\n            200,\n            [\n                'Content-type' => 'text/javascript',\n            ]\n        );\n    }\n\n    /**\n     * @throws Exception\n     */\n    private function selectEditor(array $parameters, string $instance, string $homeFolder, string $assetsPath, ?string $formTypeId = null): array\n    {\n        $editor       = $parameters['editor'];\n        $locale       = $parameters['locale'] ?: $this->container->getParameter('locale');\n        $fullScreen   = $parameters['fullscreen'];\n        $relativePath = $parameters['relative_path'];\n        $pathPrefix   = $parameters['path_prefix'];\n        $theme        = $parameters['theme'];\n        // convert to javascript array\n        $onlyMimes = count($parameters['visible_mime_types'])\n                              ? \"['\" . implode(\"','\", $parameters['visible_mime_types']) . \"']\"\n                              : '[]';\n        $result = [];\n\n        switch ($editor) {\n            case 'custom':\n                if (empty($parameters['editor_template'])) {\n                    throw new Exception(\"Configuration error : 'custom' editor must define 'editor_template' parameter\");\n                }\n\n                $result['template'] = $parameters['editor_template'];\n                $result['params']   = [\n                    'locale'        => $locale,\n                    'fullscreen'    => $fullScreen,\n                    'instance'      => $instance,\n                    'homeFolder'    => $homeFolder,\n                    'relative_path' => $relativePath,\n                    'prefix'        => $assetsPath,\n                    'theme'         => $theme,\n                    'pathPrefix'    => $pathPrefix,\n                    'onlyMimes'     => $onlyMimes,\n                    'id'            => $formTypeId,\n                ];\n\n                return $result;\n            case 'ckeditor':\n                $result['template'] = '@FMElfinder/Elfinder/ckeditor.html.twig';\n                $result['params']   = [\n                    'locale'        => $locale,\n                    'fullscreen'    => $fullScreen,\n                    'instance'      => $instance,\n                    'homeFolder'    => $homeFolder,\n                    'relative_path' => $relativePath,\n                    'prefix'        => $assetsPath,\n                    'theme'         => $theme,\n                    'pathPrefix'    => $pathPrefix,\n                    'onlyMimes'     => $onlyMimes,\n                ];\n\n                return $result;\n            case 'summernote':\n                $result['template'] = '@FMElfinder/Elfinder/summernote.html.twig';\n                $result['params']   = [\n                    'locale'        => $locale,\n                    'fullscreen'    => $fullScreen,\n                    'instance'      => $instance,\n                    'homeFolder'    => $homeFolder,\n                    'relative_path' => $relativePath,\n                    'prefix'        => $assetsPath,\n                    'theme'         => $theme,\n                    'pathPrefix'    => $pathPrefix,\n                    'onlyMimes'     => $onlyMimes,\n                ];\n\n                return $result;\n            case 'tinymce':\n                $result['template'] = '@FMElfinderBundle/Elfinder/tinymce.html.twig';\n                $result['params']   = [\n                    'locale'             => $locale,\n                    'tinymce_popup_path' => $parameters['tinymce_popup_path'],\n                    'instance'           => $instance,\n                    'homeFolder'         => $homeFolder,\n                    'prefix'             => $assetsPath,\n                    'theme'              => $theme,\n                    'pathPrefix'         => $pathPrefix,\n                    'onlyMimes'          => $onlyMimes,\n                ];\n\n                return $result;\n            case 'tinymce4':\n                $result['template'] = '@FMElfinder/Elfinder/tinymce4.html.twig';\n                $result['params']   = [\n                    'locale'        => $locale,\n                    'instance'      => $instance,\n                    'homeFolder'    => $homeFolder,\n                    'relative_path' => $relativePath,\n                    'prefix'        => $assetsPath,\n                    'theme'         => $theme,\n                    'pathPrefix'    => $pathPrefix,\n                    'onlyMimes'     => $onlyMimes,\n                ];\n\n                return $result;\n            case 'fm_tinymce':\n                $result['template'] = '@FMElfinder/Elfinder/fm_tinymce.html.twig';\n                $result['params']   = [\n                    'locale'        => $locale,\n                    'instance'      => $instance,\n                    'homeFolder'    => $homeFolder,\n                    'relative_path' => $relativePath,\n                    'prefix'        => $assetsPath,\n                    'theme'         => $theme,\n                    'pathPrefix'    => $pathPrefix,\n                    'onlyMimes'     => $onlyMimes,\n                ];\n\n                return $result;\n            case 'form':\n                $result['template'] = '@FMElfinder/Elfinder/elfinder_type.html.twig';\n                $result['params']   = [\n                    'locale'        => $locale,\n                    'fullscreen'    => $fullScreen,\n                    'instance'      => $instance,\n                    'homeFolder'    => $homeFolder,\n                    'id'            => $formTypeId,\n                    'relative_path' => $relativePath,\n                    'prefix'        => $assetsPath,\n                    'theme'         => $theme,\n                    'pathPrefix'    => $pathPrefix,\n                    'onlyMimes'     => $onlyMimes,\n                ];\n\n                return $result;\n            default:\n                $result['template'] = '@FMElfinder/Elfinder/simple.html.twig';\n                $result['params']   = [\n                    'locale'     => $locale,\n                    'fullscreen' => $fullScreen,\n                    'instance'   => $instance,\n                    'homeFolder' => $homeFolder,\n                    'prefix'     => $assetsPath,\n                    'onlyMimes'  => $onlyMimes,\n                    'theme'      => $theme,\n                    'pathPrefix' => $pathPrefix,\n                ];\n\n                return $result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/DependencyInjection/Compiler/ElFinderConfigurationPass.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\DependencyInjection\\Compiler;\n\nuse const E_USER_DEPRECATED;\n\nuse Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface;\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\nuse Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass;\n\nuse function count;\nuse function trigger_error;\n\nfinal class ElFinderConfigurationPass implements CompilerPassInterface\n{\n    public function process(ContainerBuilder $container): void\n    {\n        // use main symfony dispatcher\n        if (!$container->hasDefinition('event_dispatcher') && !$container->hasAlias('event_dispatcher')) {\n            return;\n        }\n\n        $listeners   = $container->findTaggedServiceIds('fm_elfinder.listener');\n        $subscribers = $container->findTaggedServiceIds('fm_elfinder.subscriber');\n\n        foreach ($listeners as $serviceId => $tags) {\n            @trigger_error('Using \"fm_elfinder.listener\" tag is deprecated, use \"kernel.event_listener\" instead.', E_USER_DEPRECATED);\n        }\n\n        foreach ($subscribers as $serviceId => $tags) {\n            @trigger_error('Using \"fm_elfinder.subscriber\" tag is deprecated, use \"kernel.event_subscriber\" instead.', E_USER_DEPRECATED);\n        }\n\n        if (count($listeners) > 0 || count($subscribers) > 0) {\n            $pass = new RegisterListenersPass('event_dispatcher', 'fm_elfinder.listener', 'fm_elfinder.subscriber');\n            $pass->process($container);\n        }\n    }\n}\n"
  },
  {
    "path": "src/DependencyInjection/Compiler/TwigFormPass.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\DependencyInjection\\Compiler;\n\nuse Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface;\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\n\nclass TwigFormPass implements CompilerPassInterface\n{\n    public function process(ContainerBuilder $container): void\n    {\n        if (!$container->hasParameter('twig.form.resources')) {\n            return;\n        }\n\n        $container->setParameter('twig.form.resources', array_merge(\n            ['@FMElfinder/Form/elfinder_widget.html.twig'],\n            $container->getParameter('twig.form.resources')\n        ));\n    }\n}\n"
  },
  {
    "path": "src/DependencyInjection/Configuration.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\DependencyInjection;\n\nuse Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition;\nuse Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder;\nuse Symfony\\Component\\Config\\Definition\\ConfigurationInterface;\n\nuse function method_exists;\n\nfinal class Configuration implements ConfigurationInterface\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function getConfigTreeBuilder(): TreeBuilder\n    {\n        $treeBuilder = new TreeBuilder('fm_elfinder');\n        $rootNode    = $treeBuilder->getRootNode();\n\n        $rootNode\n            ->fixXmlConfig('instance')\n            ->children()\n                ->scalarNode('configuration_provider')->defaultValue('fm_elfinder.configurator.default')->end()\n                ->scalarNode('assets_path')->defaultValue('assets')->end()\n                ->scalarNode('loader')->defaultValue('fm_elfinder.loader.default')->end()\n                ->arrayNode('instances')\n                    ->isRequired()\n                    ->requiresAtLeastOneElement()\n                    ->useAttributeAsKey('name')\n                    ->prototype('array')\n                        ->children()\n                            ->scalarNode('locale')->defaultNull()->end()\n                            ->booleanNode('cors_support')->defaultFalse()->end()\n                            ->scalarNode('editor')->defaultValue('simple')->end()\n                            ->scalarNode('editor_template')->defaultNull()->end()\n                            ->booleanNode('fullscreen')->defaultTrue()->end()\n                            ->booleanNode('multi_home_folder')->defaultFalse()->end()\n                            ->scalarNode('folder_separator')->defaultValue('')->end()\n                            ->scalarNode('theme')->defaultValue('smoothness')->end() // jQuery UI theme name\n                            ->scalarNode('tinymce_popup_path')->defaultValue('')->end()\n                            ->booleanNode('relative_path')->defaultTrue()->end()\n                            ->scalarNode('path_prefix')->defaultValue('/')->end()\n                            ->arrayNode('where_is_multi')\n                                ->beforeNormalization()\n                                    ->ifTrue(function ($v) {\n                                        return is_string($v);\n                                    })\n                                    ->then(function ($v) {\n                                        return array_map('trim', explode(',', $v));\n                                    })\n                                ->end()\n                                ->prototype('scalar')->end()\n                                ->defaultValue([])\n                            ->end()\n                            ->arrayNode('visible_mime_types')\n                                ->beforeNormalization()\n                                    ->ifTrue(function ($v) {\n                                        return is_string($v);\n                                    })\n                                    ->then(function ($v) {\n                                        return array_map('trim', explode(',', $v));\n                                    })\n                                ->end()\n                                ->prototype('scalar')->end()\n                                ->defaultValue([])\n                            ->end()\n                            ->arrayNode('connector')\n                                ->addDefaultsIfNotSet()\n                                ->fixXmlConfig('root')\n                                ->children()\n                                    ->booleanNode('debug')->defaultFalse()->end()\n                                    ->append($this->createBindsNode())\n                                    ->append($this->createPluginsNode())\n                                    ->arrayNode('roots')\n                                        ->useAttributeAsKey('name')\n                                        ->isRequired()\n                                        ->requiresAtLeastOneElement()\n                                        ->prototype('array')\n                                            ->children()\n                                                ->scalarNode('driver')\n                                                    ->isRequired()\n                                                ->end() // driver\n                                                ->integerNode('volume_id')->defaultValue(0)->min(0)->end()\n                                                ->scalarNode('path')->defaultValue('')->end()\n                                                ->booleanNode('autoload')->defaultFalse()->end()\n                                                ->scalarNode('phash')->defaultValue('')->end()\n                                                ->scalarNode('trash_hash')->defaultValue('')->end()\n                                                ->scalarNode('locale')->defaultValue('')->end()\n                                                ->booleanNode('i18n_folder_name')->defaultFalse()->end()\n                                                ->scalarNode('mime_detect')->defaultValue('auto')->end()\n                                                ->scalarNode('mimefile')->defaultValue('')->end()\n                                                ->scalarNode('security_voter')->defaultValue('')->end()\n                                                ->scalarNode('start_path')->defaultValue('')->end()\n                                                ->scalarNode('encoding')->defaultValue('UTF-8')->end()\n                                                ->scalarNode('url')->defaultValue('')->end()\n                                                ->scalarNode('alias')->defaultValue('')->end()\n                                                ->scalarNode('img_lib')->defaultValue('auto')->end()\n                                                ->scalarNode('tmb_path')->defaultValue('.tmb')->end()\n                                                ->scalarNode('tmb_path_mode')->defaultValue(0777)->end()\n                                                ->scalarNode('tmb_url')->defaultValue('')->end()\n                                                ->integerNode('tmb_size')->defaultValue(48)->end()\n                                                ->booleanNode('tmb_crop')->defaultTrue()->end()\n                                                ->scalarNode('tmb_bg_color')->defaultValue('#ffffff')->end()\n                                                ->scalarNode('quarantine')->defaultNull()->end()\n                                                ->booleanNode('copy_overwrite')->defaultTrue()->end()\n                                                ->booleanNode('copy_join')->defaultTrue()->end()\n                                                ->booleanNode('copy_from')->defaultTrue()->end()\n                                                ->booleanNode('copy_to')->defaultTrue()->end()\n                                                ->booleanNode('upload_overwrite')->defaultTrue()->end()\n                                                ->scalarNode('fileMode')->defaultValue(0644)->end()\n                                                ->arrayNode('upload_allow')\n                                                    ->beforeNormalization()\n                                                        ->ifTrue(function ($v) {\n                                                            return is_string($v);\n                                                        })\n                                                        ->then(function ($v) {\n                                                            return array_map('trim', explode(',', $v));\n                                                        })\n                                                    ->end()\n                                                    ->prototype('scalar')->end()\n                                                    ->defaultValue(['image'])\n                                                ->end() // upload_allow\n                                                ->arrayNode('upload_deny')\n                                                    ->beforeNormalization()\n                                                        ->ifTrue(function ($v) {\n                                                            return is_string($v);\n                                                        })\n                                                        ->then(function ($v) {\n                                                            return array_map('trim', explode(',', $v));\n                                                        })\n                                                    ->end()\n                                                    ->prototype('scalar')->end()\n                                                    ->defaultValue(['all'])\n                                                ->end() // upload_deny\n                                                ->arrayNode('upload_order')\n                                                    ->beforeNormalization()\n                                                        ->ifTrue(function ($v) {\n                                                            return is_string($v);\n                                                        })\n                                                        ->then(function ($v) {\n                                                            return array_map('trim', explode(',', $v));\n                                                        })\n                                                    ->end()\n                                                    ->prototype('scalar')->end()\n                                                    ->defaultValue(['deny', 'allow'])\n                                                ->end() // upload_order\n                                                ->scalarNode('upload_max_size')->defaultValue(0)->end()\n                                                ->integerNode('upload_max_conn')->defaultValue(3)->end()\n                                                ->arrayNode('defaults')\n                                                    ->useAttributeAsKey('defaults')\n                                                    ->normalizeKeys(false)\n                                                    ->prototype('boolean')->end()\n                                                    ->defaultValue(['read' => true, 'write' => true])\n                                                ->end() // defaults\n                                                ->arrayNode('attributes')\n                                                    ->prototype('array')\n                                                        ->children()\n                                                            ->scalarNode('pattern')->end()\n                                                            ->scalarNode('read')->defaultValue(true)->end()\n                                                            ->scalarNode('write')->defaultValue(true)->end()\n                                                            ->scalarNode('locked')->defaultValue(false)->end()\n                                                            ->scalarNode('hidden')->defaultValue(false)->end()\n                                                        ->end()\n                                                    ->end()\n                                                    ->defaultValue([])\n                                                ->end() // attributes\n                                                ->scalarNode('accepted_name')->defaultValue('/^\\w[\\w\\s\\.\\%\\-]*$/u')->end()\n                                                ->booleanNode('show_hidden')->defaultFalse()->end()\n                                                ->arrayNode('disabled_commands')\n                                                    ->beforeNormalization()\n                                                        ->ifTrue(function ($v) {\n                                                            return is_string($v);\n                                                        })\n                                                        ->then(function ($v) {\n                                                            return array_map('trim', explode(',', $v));\n                                                        })\n                                                    ->end()\n                                                    ->prototype('scalar')->end()\n                                                    ->defaultValue([])\n                                                ->end() // disabled_commands\n                                                ->integerNode('tree_deep')->defaultValue(0)->end()\n                                                ->integerNode('check_subfolders')->defaultValue(1)->end()\n                                                ->scalarNode('separator')->defaultValue(DIRECTORY_SEPARATOR)->end()\n                                                ->scalarNode('date_format')->defaultValue('j M Y H:i')->end()\n                                                ->scalarNode('time_format')->defaultValue('H:i')->end()\n                                                ->arrayNode('archive_mimes')\n                                                    ->beforeNormalization()\n                                                        ->ifTrue(function ($v) {\n                                                            return is_string($v);\n                                                        })\n                                                        ->then(function ($v) {\n                                                            return array_map('trim', explode(',', $v));\n                                                        })\n                                                    ->end()\n                                                    ->prototype('scalar')->end()\n                                                    ->defaultValue([])\n                                                ->end() // archive_mimes\n                                                ->arrayNode('archivers')\n                                                    ->canBeEnabled()\n                                                    ->children()\n                                                        ->arrayNode('create')\n                                                            ->prototype('array')\n                                                                ->children()\n                                                                    ->scalarNode('cmd')->end()\n                                                                    ->scalarNode('argc')->end()\n                                                                    ->scalarNode('ext')->end()\n                                                                ->end()\n                                                            ->end()\n                                                        ->end()\n                                                        ->arrayNode('extract')\n                                                            ->prototype('array')\n                                                                ->children()\n                                                                    ->scalarNode('cmd')->end()\n                                                                    ->scalarNode('argc')->end()\n                                                                    ->scalarNode('ext')->end()\n                                                                ->end()\n                                                            ->end()\n                                                        ->end()\n                                                    ->end()\n                                                ->end() // archivers\n                                                ->arrayNode('flysystem')\n                                                    ->canBeEnabled()\n                                                    ->children()\n                                                        ->scalarNode('filesystem')->defaultValue('')->end()\n                                                        ->scalarNode('type')->defaultValue('')->end()\n                                                        ->scalarNode('adapter_service')->defaultValue('')->end()\n                                                        ->append($this->createFlysystemNode())\n                                                    ->end()\n                                                ->end()\n                                                ->scalarNode('glide_url')->defaultValue('')->end()\n                                                ->scalarNode('glide_key')->defaultValue('')->end()\n                                                ->append($this->createPluginsNode())\n                                                ->append($this->createDriverOptionsNode())\n                                                ->arrayNode('dropbox2_settings')\n                                                    ->canBeEnabled()\n                                                    ->children()\n                                                        ->scalarNode('app_key')->end()\n                                                        ->scalarNode('app_secret')->end()\n                                                        ->scalarNode('access_token')->end()\n                                                        ->scalarNode('aliasFormat')->defaultValue('%s@Dropbox')->end()\n                                                        ->scalarNode('path')->defaultValue('/')->end()\n                                                        ->scalarNode('separator')->defaultValue('/')->end()\n                                                        ->scalarNode('acceptedName')->defaultValue('%s@Dropbox')->end()\n                                                        ->scalarNode('rootCssClass')->defaultValue('elfinder-navbar-root-dropbox')->end()\n                                                        ->arrayNode('publishPermission')\n                                                            ->children()\n                                                                ->scalarNode('requested_visibility')->defaultValue('public')->end()\n                                                            ->end()\n                                                        ->end()\n                                                        ->scalarNode('getThumbSize')->defaultValue('medium')->end()\n                                                    ->end()\n                                                ->end()\n                                                ->arrayNode('box_settings')\n                                                    ->canBeEnabled()\n                                                    ->children()\n                                                        ->scalarNode('client_id')->end()\n                                                        ->scalarNode('client_secret')->end()\n                                                        ->scalarNode('accessToken')->end()\n                                                        ->scalarNode('root')->defaultValue('Box.com')->end()\n                                                        ->scalarNode('path')->defaultValue('/')->end()\n                                                        ->scalarNode('separator')->defaultValue('/')->end()\n                                                        ->scalarNode('tmbPath')->defaultValue('')->end()\n                                                        ->scalarNode('tmbURL')->defaultValue('')->end()\n                                                        ->scalarNode('tmpPath')->defaultValue('')->end()\n                                                        ->scalarNode('acceptedName')->defaultValue('#^[^/\\\\?*:|\"<>]*[^./\\\\?*:|\"<>]$#')->end()\n                                                        ->scalarNode('rootCssClass')->defaultValue('elfinder-navbar-root-box')->end()\n                                                    ->end()\n                                                ->end()\n                                                ->arrayNode('onedrive_settings')\n                                                    ->canBeEnabled()\n                                                    ->children()\n                                                        ->scalarNode('client_id')->end()\n                                                        ->scalarNode('client_secret')->end()\n                                                        ->scalarNode('accessToken')->end()\n                                                        ->scalarNode('root')->defaultValue('OneDrive.com')->end()\n                                                        ->scalarNode('OneDriveApiClient')->defaultValue('')->end()\n                                                        ->scalarNode('path')->defaultValue('/')->end()\n                                                        ->scalarNode('separator')->defaultValue('/')->end()\n                                                        ->scalarNode('tmbPath')->defaultValue('')->end()\n                                                        ->scalarNode('tmbURL')->defaultValue('')->end()\n                                                        ->scalarNode('tmpPath')->defaultValue('')->end()\n                                                        ->scalarNode('acceptedName')->defaultValue('#^[^/\\\\?*:|\"<>]*[^./\\\\?*:|\"<>]$#')->end()\n                                                        ->scalarNode('rootCssClass')->defaultValue('elfinder-navbar-root-onedrive')->end()\n                                                        ->booleanNode('useApiThumbnail')->defaultTrue()->end()\n                                                    ->end()\n                                                ->end()\n                                                ->arrayNode('ftp_settings')\n                                                    ->canBeEnabled()\n                                                    ->children()\n                                                        ->scalarNode('host')->end()\n                                                        ->scalarNode('user')->end()\n                                                        ->scalarNode('password')->end()\n                                                        ->scalarNode('path')->end()\n                                                    ->end()\n                                                ->end()\n                                                ->arrayNode('mysql_settings')\n                                                    ->canBeEnabled()\n                                                    ->children()\n                                                        ->scalarNode('host')->end()\n                                                        ->scalarNode('user')->end()\n                                                        ->scalarNode('pass')->end()\n                                                        ->scalarNode('db')->end()\n                                                        ->scalarNode('port')->defaultNull()->end()\n                                                        ->scalarNode('socket')->defaultNull()->end()\n                                                        ->scalarNode('files_table')->defaultValue('elfinder_file')->end()\n                                                        ->scalarNode('tmbPath')->defaultValue('')->end()\n                                                        ->scalarNode('tmpPath')->defaultValue('')->end()\n                                                        ->scalarNode('rootCssClass')->defaultValue('elfinder-navbar-root-sql')->end()\n                                                        ->scalarNode('noSessionCache')->defaultValue('hasdirs')->end()\n                                                    ->end()\n                                                ->end()\n                                            ->end()\n                                        ->end()\n                                    ->end()\n                                ->end()\n                            ->end()\n                ->end();\n\n        return $treeBuilder;\n    }\n\n    /**\n     * @return NodeDefinition the Flysystem node\n     */\n    private function createFlysystemNode()\n    {\n        return $this->createNode('options')\n            ->children()\n                ->arrayNode('local')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('path')->defaultvalue('')->end()\n                    ->end()\n                ->end()\n                ->arrayNode('ftp')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('host')->defaultValue('')->end()\n                            ->scalarNode('username')->defaultValue('')->end()\n                            ->scalarNode('password')->defaultValue('')->end()\n                            ->integerNode('port')->defaultValue(21)->end()\n                            ->booleanNode('passive')->defaultTrue()->end()\n                            ->booleanNode('ssl')->defaultTrue()->end()\n                            ->integerNode('timeout')->defaultValue(30)->end()\n                            ->scalarNode('root')->defaultValue('/')->end()\n                            ->integerNode('directoryPerm')->defaultValue(0744)->end()\n                    ->end()\n                ->end()\n                ->arrayNode('sftp')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('host')->defaultValue('')->end()\n                            ->scalarNode('username')->defaultValue('')->end()\n                            ->scalarNode('password')->defaultValue('')->end()\n                            ->integerNode('port')->defaultValue(21)->end()\n                            ->scalarNode('privateKey')->defaultValue('')->end()\n                            ->integerNode('timeout')->defaultValue(10)->end()\n                            ->scalarNode('root')->defaultValue('/')->end()\n                    ->end()\n                ->end()\n                ->arrayNode('azure')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('account_name')->defaultvalue('')->end()\n                            ->scalarNode('account_key')->defaultvalue('')->end()\n                            ->scalarNode('container_name')->defaultvalue('')->end()\n                    ->end()\n                ->end()\n                ->arrayNode('aws_s3_v2')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('key')->defaultvalue('')->end()\n                            ->scalarNode('secret')->defaultvalue('')->end()\n                            ->scalarNode('region')->defaultvalue('')->end()\n                            ->scalarNode('bucket_name')->defaultvalue('')->end()\n                            ->scalarNode('optional_prefix')->defaultvalue('')->end()\n                            ->scalarNode('base_url')->defaultvalue('')->end()\n                    ->end()\n                ->end()\n\n                ->arrayNode('aws_s3_v3')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('key')->defaultvalue('')->end()\n                            ->scalarNode('secret')->defaultvalue('')->end()\n                            ->scalarNode('region')->defaultvalue('')->end()\n                            ->scalarNode('version')->defaultvalue('')->end()\n                            ->scalarNode('bucket_name')->defaultvalue('')->end()\n                            ->scalarNode('optional_prefix')->defaultvalue('')->end()\n                            ->scalarNode('endpoint')->defaultNull()->end()\n                            ->booleanNode('use_path_style_endpoint')->defaultFalse()->end()\n                            ->booleanNode('use_aws_shared_config_files')->defaultTrue()->end()\n                            ->arrayNode('options')\n                                ->canBeEnabled()\n                                    ->children()\n                                        ->scalarNode('ACL')->defaultvalue('')->end()\n                                ->end()\n                            ->end()\n                    ->end()\n                ->end()\n                ->arrayNode('copy_com')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('consumer_key')->defaultvalue('')->end()\n                            ->scalarNode('consumer_secret')->defaultvalue('')->end()\n                            ->scalarNode('access_token')->defaultvalue('')->end()\n                            ->scalarNode('token_secret')->defaultvalue('')->end()\n                            ->scalarNode('optional_prefix')->defaultvalue('')->end()\n                        ->end()\n                ->end()\n                ->arrayNode('gridfs')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('db_name')->defaultvalue('')->end()\n                        ->end()\n                ->end()\n                ->arrayNode('zip')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('path')->defaultvalue('')->end()\n                        ->end()\n                ->end()\n                ->arrayNode('dropbox')\n                    ->canBeEnabled()\n                        ->children()\n                            ->scalarNode('app')->defaultvalue('')->end()\n                            ->scalarNode('token')->defaultvalue('')->end()\n                        ->end()\n                ->end()\n                ->arrayNode('rackspace')\n                    ->canBeEnabled()\n                        ->children()\n                          ->scalarNode('username')->defaultValue('')->end()\n                          ->scalarNode('apikey')->defaultValue('')->end()\n                          ->scalarNode('endpoint')->defaultValue('')->end()\n                          ->scalarNode('container')->defaultValue('')->end()\n                          ->scalarNode('region')->defaultValue('')->end()\n                       ->end()\n                ->end()\n            ->end();\n    }\n\n    /**\n     * @return NodeDefinition the plugins node\n     */\n    private function createPluginsNode()\n    {\n        return $this->createNode('plugins')\n            ->useAttributeAsKey('name')\n                ->prototype('array')\n                ->useAttributeAsKey('name')\n                ->prototype('variable')->end()\n            ->end();\n    }\n\n    /**\n     * @return NodeDefinition the bind node\n     */\n    private function createBindsNode()\n    {\n        return $this->createNode('binds')\n            ->useAttributeAsKey('name')\n                ->prototype('array')\n                ->useAttributeAsKey('name')\n                ->prototype('variable')->end()\n            ->end();\n    }\n\n    /**\n     * @return NodeDefinition the bind node\n     */\n    private function createDriverOptionsNode()\n    {\n        return $this->createNode('driver_options')\n            ->useAttributeAsKey('name')\n                ->prototype('array')\n                ->useAttributeAsKey('name')\n                ->prototype('variable')->end()\n            ->end();\n    }\n\n    /**\n     * @param string $name the node name\n     *\n     * @return NodeDefinition the node\n     */\n    private function createNode($name)\n    {\n        $treeBuilder = new TreeBuilder($name);\n\n        if (method_exists($treeBuilder, 'getRootNode')) {\n            $rootNode = $treeBuilder->getRootNode();\n        } else {\n            $rootNode = $treeBuilder->root($name);\n        }\n\n        return $rootNode;\n    }\n}\n"
  },
  {
    "path": "src/DependencyInjection/FMElfinderExtension.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\DependencyInjection;\n\nuse FM\\ElfinderBundle\\Controller\\ElFinderController;\nuse Symfony\\Component\\Config\\FileLocator;\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\nuse Symfony\\Component\\DependencyInjection\\Extension\\Extension;\nuse Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader;\n\nfinal class FMElfinderExtension extends Extension\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function load(array $configs, ContainerBuilder $container): void\n    {\n        $config = $this->processConfiguration(new Configuration(), $configs);\n\n        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config'));\n        $loader->load('elfinder.yaml');\n        $loader->load('form.yaml');\n        $loader->load('command.yaml');\n        $container->setParameter('fm_elfinder', $config);\n\n        $repo = $container->getDefinition(ElFinderController::class);\n        $repo->replaceArgument(1, $config);\n        $container->setAlias('fm_elfinder.configurator', $config['configuration_provider']);\n        $container->setAlias('fm_elfinder.loader', $config['loader']);\n        $container->getAlias('fm_elfinder.loader')->setPublic(true);\n    }\n\n    public function getNamespace(): string\n    {\n        return 'http://helios-ag.github.io/schema/dic/fm_elfinder';\n    }\n}\n"
  },
  {
    "path": "src/ElFinder/ElFinder.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\ElFinder;\n\nuse elFinder as BaseElFinder;\nuse elFinderSession;\nuse elFinderSessionInterface;\n\nclass ElFinder extends BaseElFinder\n{\n    /**\n     * Constructor.\n     *\n     * @param  array  elFinder and roots configurations\n     */\n    public function __construct($opts)\n    {\n        // set default_charset\n        if (version_compare(PHP_VERSION, '5.6', '>=')) {\n            ini_set('internal_encoding', 'UTF-8');\n            ini_set('default_charset', 'UTF-8');\n        }\n\n        // define accept constant of server commands path\n        !defined('ELFINDER_TAR_PATH') && define('ELFINDER_TAR_PATH', 'tar');\n        !defined('ELFINDER_GZIP_PATH') && define('ELFINDER_GZIP_PATH', 'gzip');\n        !defined('ELFINDER_BZIP2_PATH') && define('ELFINDER_BZIP2_PATH', 'bzip2');\n        !defined('ELFINDER_XZ_PATH') && define('ELFINDER_XZ_PATH', 'xz');\n        !defined('ELFINDER_ZIP_PATH') && define('ELFINDER_ZIP_PATH', 'zip');\n        !defined('ELFINDER_UNZIP_PATH') && define('ELFINDER_UNZIP_PATH', 'unzip');\n        !defined('ELFINDER_RAR_PATH') && define('ELFINDER_RAR_PATH', 'rar');\n        !defined('ELFINDER_UNRAR_PATH') && define('ELFINDER_UNRAR_PATH', 'unrar');\n        !defined('ELFINDER_7Z_PATH') && define('ELFINDER_7Z_PATH', ('WIN' === substr(PHP_OS, 0, 3)) ? '7z' : '7za');\n        !defined('ELFINDER_CONVERT_PATH') && define('ELFINDER_CONVERT_PATH', 'convert');\n        !defined('ELFINDER_EXIFTRAN_PATH') && define('ELFINDER_EXIFTRAN_PATH', 'exiftran');\n        !defined('ELFINDER_JPEGTRAN_PATH') && define('ELFINDER_JPEGTRAN_PATH', 'jpegtran');\n        !defined('ELFINDER_FFMPEG_PATH') && define('ELFINDER_FFMPEG_PATH', 'ffmpeg');\n        !defined('ELFINDER_IMAGEMAGICK_PS') && define('ELFINDER_IMAGEMAGICK_PS', false);\n\n        // for backward compat\n        $this->version = (string) self::$ApiVersion;\n\n        // set error handler of WARNING, NOTICE\n        $errLevel = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR;\n\n        if (defined('E_DEPRECATED')) {\n            $errLevel |= E_DEPRECATED | E_USER_DEPRECATED;\n        }\n        set_error_handler(elFinder::phpErrorHandler(...), $errLevel);\n\n        // Associative array of files to delete at the end of script: ['temp file path' => true]\n        $GLOBALS['elFinderTempFiles'] = [];\n        // regist Shutdown function\n        register_shutdown_function(['elFinder', 'onShutdown']);\n\n        // convert PATH_INFO to GET query\n        if (!empty($_SERVER['PATH_INFO'])) {\n            $_ps = explode('/', trim($_SERVER['PATH_INFO'], '/'));\n\n            if (!isset($_GET['cmd'])) {\n                $_cmd = $_ps[0];\n\n                if (isset($this->commands[$_cmd])) {\n                    $_GET['cmd'] = $_cmd;\n                    $_i          = 1;\n                    foreach (array_keys($this->commands[$_cmd]) as $_k) {\n                        if (isset($_ps[$_i])) {\n                            if (!isset($_GET[$_k])) {\n                                $_GET[$_k] = $_ps[$_i];\n                            }\n                        } else {\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        // set elFinder instance\n        self::$instance = $this;\n\n        // setup debug mode\n        $this->debug = (isset($opts['debug']) && $opts['debug'] ? true : false);\n\n        if ($this->debug) {\n            error_reporting(defined('ELFINDER_DEBUG_ERRORLEVEL') ? ELFINDER_DEBUG_ERRORLEVEL : -1);\n            ini_set('diaplay_errors', '1');\n            // clear output buffer and stop output filters\n            while (ob_get_level() && ob_end_clean()) {\n            }\n        }\n\n        if (!interface_exists('elFinderSessionInterface')) {\n            include_once dirname(__FILE__) . '/elFinderSessionInterface.php';\n        }\n\n        // session handler\n        if (!empty($opts['session']) && $opts['session'] instanceof elFinderSessionInterface) {\n            $this->session = $opts['session'];\n        } else {\n            $sessionOpts = [\n                'base64encode' => !empty($opts['base64encodeSessionData']),\n                'keys'         => [\n                    'default'   => !empty($opts['sessionCacheKey']) ? $opts['sessionCacheKey'] : 'elFinderCaches',\n                    'netvolume' => !empty($opts['netVolumesSessionKey']) ? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes',\n                ],\n            ];\n            $this->session = new elFinderSession($sessionOpts);\n        }\n        // try session start | restart\n        $this->session->start();\n\n        $sessionUseCmds = [];\n\n        if (isset($opts['sessionUseCmds']) && is_array($opts['sessionUseCmds'])) {\n            $sessionUseCmds = $opts['sessionUseCmds'];\n        }\n\n        // set self::$volumesCnt by HTTP header \"X-elFinder-VolumesCntStart\"\n        if (isset($_SERVER['HTTP_X_ELFINDER_VOLUMESCNTSTART']) && ($volumesCntStart = intval($_SERVER['HTTP_X_ELFINDER_VOLUMESCNTSTART']))) {\n            self::$volumesCnt = $volumesCntStart;\n        }\n\n        $this->time                = $this->utime();\n        $this->sessionCloseEarlier = isset($opts['sessionCloseEarlier']) ? (bool) $opts['sessionCloseEarlier'] : true;\n        $this->sessionUseCmds      = array_flip($sessionUseCmds);\n        $this->timeout             = ($opts['timeout'] ?? 0);\n        $this->uploadTempPath      = ($opts['uploadTempPath'] ?? '');\n        $this->callbackWindowURL   = ($opts['callbackWindowURL'] ?? '');\n        $this->maxTargets          = (isset($opts['maxTargets']) ? intval($opts['maxTargets']) : $this->maxTargets);\n        self::$commonTempPath      = ($opts['commonTempPath'] ?? './.tmp');\n\n        if (!is_writable(self::$commonTempPath)) {\n            self::$commonTempPath = sys_get_temp_dir();\n\n            if (!is_writable(self::$commonTempPath)) {\n                self::$commonTempPath = '';\n            }\n        }\n\n        if (isset($opts['connectionFlagsPath']) && is_writable($opts['connectionFlagsPath'])) {\n            self::$connectionFlagsPath = $opts['connectionFlagsPath'];\n        } else {\n            self::$connectionFlagsPath = self::$commonTempPath;\n        }\n\n        if (!empty($opts['tmpLinkPath'])) {\n            self::$tmpLinkPath = $opts['tmpLinkPath'];\n        }\n\n        if (!empty($opts['tmpLinkUrl'])) {\n            self::$tmpLinkUrl = $opts['tmpLinkUrl'];\n        }\n\n        if (!empty($opts['tmpLinkLifeTime'])) {\n            self::$tmpLinkLifeTime = $opts['tmpLinkLifeTime'];\n        }\n\n        if (!empty($opts['textMimes']) && is_array($opts['textMimes'])) {\n            self::$textMimes = $opts['textMimes'];\n        }\n        $this->maxArcFilesSize   = isset($opts['maxArcFilesSize']) ? intval($opts['maxArcFilesSize']) : 0;\n        $this->optionsNetVolumes = (isset($opts['optionsNetVolumes']) && is_array($opts['optionsNetVolumes'])) ? $opts['optionsNetVolumes'] : [];\n\n        if (isset($opts['itemLockExpire'])) {\n            $this->itemLockExpire = intval($opts['itemLockExpire']);\n        }\n\n        // deprecated settings\n        $this->netVolumesSessionKey = !empty($opts['netVolumesSessionKey']) ? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes';\n        self::$sessionCacheKey      = !empty($opts['sessionCacheKey']) ? $opts['sessionCacheKey'] : 'elFinderCaches';\n\n        // check session cache\n        $_optsMD5 = md5(json_encode($opts['roots']));\n\n        if ($this->session->get('_optsMD5') !== $_optsMD5) {\n            $this->session->set('_optsMD5', $_optsMD5);\n        }\n\n        // setlocale and global locale regists to elFinder::locale\n        self::$locale = !empty($opts['locale']) ? $opts['locale'] : ('WIN' === substr(PHP_OS, 0, 3) ? 'C' : 'en_US.UTF-8');\n\n        if (false === setlocale(LC_ALL, self::$locale)) {\n            self::$locale = setlocale(LC_ALL, '0');\n        }\n\n        // set defaultMimefile\n        self::$defaultMimefile = ($opts['defaultMimefile'] ?? '');\n\n        // bind events listeners\n        if (!empty($opts['bind']) && is_array($opts['bind'])) {\n            $_req    = 'POST' == $_SERVER['REQUEST_METHOD'] ? $_POST : $_GET;\n            $_reqCmd = $_req['cmd'] ?? '';\n            foreach ($opts['bind'] as $cmd => $handlers) {\n                $doRegist = (false !== strpos($cmd, '*'));\n\n                if (!$doRegist) {\n                    $doRegist = ($_reqCmd && in_array($_reqCmd, array_map(elFinder::getCmdOfBind(...), explode(' ', $cmd))));\n                }\n\n                if ($doRegist) {\n                    // for backward compatibility\n                    if (!is_array($handlers)) {\n                        $handlers = [$handlers];\n                    } else {\n                        if (2 === count($handlers) && is_object($handlers[0])) {\n                            $handlers = [$handlers];\n                        }\n                    }\n                    foreach ($handlers as $handler) {\n                        if ($handler) {\n                            if (is_string($handler) && strpos($handler, '.')) {\n                                [$_domain, $_name, $_method] = array_pad(explode('.', $handler), 3, '');\n\n                                if (0 === strcasecmp($_domain, 'plugin')) {\n                                    if ($plugin = $this->getPluginInstance($_name, $opts['plugin'][$_name] ?? []) and\n                                        method_exists($plugin, $_method)) {\n                                        $this->bind($cmd, $plugin->$_method(...));\n                                    }\n                                }\n                            } else {\n                                $this->bind($cmd, $handler);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!isset($opts['roots']) || !is_array($opts['roots'])) {\n            $opts['roots'] = [];\n        }\n\n        // check for net volumes stored in session\n        $netVolumes = $this->getNetVolumes();\n        foreach ($netVolumes as $key => $root) {\n            if (!isset($root['id'])) {\n                // given fixed unique id\n                if (!$root['id'] = $this->getNetVolumeUniqueId($netVolumes)) {\n                    $this->mountErrors[] = 'Netmount Driver \"' . $root['driver'] . '\" : Could\\'t given volume id.';\n\n                    continue;\n                }\n            }\n            $opts['roots'][$key] = $root;\n        }\n\n        $this->mountVolumes($opts);\n\n        // if at least one readable volume - ii desu >_<\n        $this->loaded = !empty($this->default);\n\n        // restore error handler for now\n        restore_error_handler();\n    }\n\n    /**\n     * Mount volumes.\n     *\n     * Instantiate corresponding driver class and\n     * add it to the list of volumes.\n     *\n     * @param array $opts\n     */\n    protected function mountVolumes($opts)\n    {\n        foreach ($opts['roots'] as $i => $o) {\n            $class = 'elFinderVolume' . ($o['driver'] ?? '');\n\n            if (class_exists($class)) {\n                $volume = new $class();\n\n                try {\n                    if ($this->maxArcFilesSize && (empty($o['maxArcFilesSize']) || $this->maxArcFilesSize < $o['maxArcFilesSize'])) {\n                        $o['maxArcFilesSize'] = $this->maxArcFilesSize;\n                    }\n                    // pass session handler\n                    $volume->setSession($this->session);\n\n                    if ($volume->mount($o)) {\n                        // unique volume id (ends on \"_\") - used as prefix to files hash\n                        $id = $volume->id();\n\n                        $this->volumes[$id] = $volume;\n\n                        if ((!$this->default || $volume->root() !== $volume->defaultPath()) && $volume->isReadable()) {\n                            $this->default = $this->volumes[$id];\n                        }\n                    } else {\n                        $this->removeNetVolume($i, $volume);\n                        $this->mountErrors[] = 'Driver \"' . $class . '\" : ' . implode(' ', $volume->error());\n                    }\n                } catch (Exception $e) {\n                    $this->removeNetVolume($i, $volume);\n                    $this->mountErrors[] = 'Driver \"' . $class . '\" : ' . $e->getMessage();\n                }\n            } else {\n                $this->removeNetVolume($i, $volume);\n                $this->mountErrors[] = 'Driver \"' . $class . '\" does not exist';\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Event/ElFinderPostExecutionEvent.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Event;\n\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpKernel\\HttpKernelInterface;\n\nclass ElFinderPostExecutionEvent extends ElFinderPreExecutionEvent\n{\n    /** Command execution result. */\n    protected array $result;\n\n    /**\n     * Constructor.\n     */\n    public function __construct(Request $request, HttpKernelInterface $httpKernel, string $instance, string $homeFolder, ?array $result = null)\n    {\n        parent::__construct($request, $httpKernel, $instance, $homeFolder);\n\n        $this->result = $result;\n    }\n\n    /**\n     * Tells if execution has encountered errors.\n     */\n    public function hasErrors(): bool\n    {\n        return isset($this->result['error']);\n    }\n\n    public function getResult(): array\n    {\n        return $this->result;\n    }\n\n    public function setResult(array $result): void\n    {\n        $this->result = $result;\n    }\n}\n"
  },
  {
    "path": "src/Event/ElFinderPreExecutionEvent.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Event;\n\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpKernel\\HttpKernelInterface;\nuse Symfony\\Contracts\\EventDispatcher\\Event;\n\nclass ElFinderPreExecutionEvent extends Event\n{\n    /** Request object containing ElFinder command and parameters. */\n    protected Request $request;\n\n    /** ElFinder instance. */\n    protected string $instance;\n\n    /** Home folder. */\n    protected string $homeFolder;\n\n    /** Used to make sub requests. */\n    private HttpKernelInterface $httpKernel;\n\n    public function __construct(Request $request, HttpKernelInterface $httpKernel, string $instance, string $homeFolder)\n    {\n        $this->request    = $request;\n        $this->httpKernel = $httpKernel;\n        $this->instance   = $instance;\n        $this->homeFolder = $homeFolder;\n    }\n\n    /**\n     * Makes a sub request to elFinder.\n     * Function based on 'forward' function from Symfony controllers.\n     *\n     * @see https://github.com/symfony/symfony/blob/2.5/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php\n     *\n     * @param array $path  An array of path parameters\n     * @param array $query An array of query parameters\n     *\n     * @return \\Symfony\\Component\\HttpFoundation\\Response A Response instance\n     */\n    public function subRequest(array $path, array $query)\n    {\n        $path['_controller'] = 'FMElfinderBundle:ElFinder:load';\n        $subRequest          = $this->request->duplicate($query, null, $path);\n\n        return $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);\n    }\n\n    /**\n     * Returns executed command.\n     */\n    public function getCommand(): string\n    {\n        return $this->request->query->get('cmd');\n    }\n\n    public function getRequest(): Request\n    {\n        return $this->request;\n    }\n\n    public function getInstance(): string\n    {\n        return $this->instance;\n    }\n\n    public function getHomeFolder(): string\n    {\n        return $this->homeFolder;\n    }\n}\n"
  },
  {
    "path": "src/FMElfinderBundle.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle;\n\nuse FM\\ElfinderBundle\\DependencyInjection\\Compiler\\ElFinderConfigurationPass;\nuse FM\\ElfinderBundle\\DependencyInjection\\Compiler\\TwigFormPass;\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\nuse Symfony\\Component\\HttpKernel\\Bundle\\Bundle;\n\nclass FMElfinderBundle extends Bundle\n{\n    public function build(ContainerBuilder $container): void\n    {\n        parent::build($container);\n\n        $container->addCompilerPass(new TwigFormPass());\n        $container->addCompilerPass(new ElFinderConfigurationPass());\n    }\n}\n"
  },
  {
    "path": "src/Form/Type/ElFinderType.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Form\\Type;\n\nuse Symfony\\Component\\Form\\AbstractType;\nuse Symfony\\Component\\Form\\FormBuilderInterface;\nuse Symfony\\Component\\Form\\FormInterface;\nuse Symfony\\Component\\Form\\FormView;\nuse Symfony\\Component\\OptionsResolver\\OptionsResolver;\n\nclass ElFinderType extends AbstractType\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function buildForm(FormBuilderInterface $builder, array $options): void\n    {\n        $builder->setAttribute('enable', $options['enable']);\n\n        if ($builder->getAttribute('enable')) {\n            $builder->setAttribute('instance', $options['instance']);\n        }\n        $builder->setAttribute('homeFolder', $options['homeFolder']);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function buildView(FormView $view, FormInterface $form, array $options): void\n    {\n        $view->vars['enable'] = $options['enable'];\n\n        if ($options['enable']) {\n            $view->vars['instance']   = $options['instance'];\n            $view->vars['homeFolder'] = $options['homeFolder'];\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function configureOptions(OptionsResolver $resolver): void\n    {\n        $resolver\n            ->setDefaults([\n                'enable'     => true,\n                'instance'   => 'default',\n                'homeFolder' => '',\n            ])\n            ->setAllowedTypes('enable', 'bool')\n            ->setAllowedTypes('instance', ['string', 'null'])\n            ->setAllowedTypes('homeFolder', ['string', 'null']);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getParent(): ?string\n    {\n        if (method_exists('Symfony\\Component\\Form\\AbstractType', 'getBlockPrefix')) {\n            return 'Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType';\n        }\n\n        return 'text';\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getName(): string\n    {\n        return $this->getBlockPrefix();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getBlockPrefix(): string\n    {\n        return 'elfinder';\n    }\n}\n"
  },
  {
    "path": "src/Loader/ElFinderLoader.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Loader;\n\nuse Exception;\nuse FM\\ElfinderBundle\\Bridge\\ElFinderBridge;\nuse FM\\ElfinderBundle\\Configuration\\ElFinderConfigurationProviderInterface;\nuse FM\\ElfinderBundle\\Connector\\ElFinderConnector;\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpFoundation\\Session\\SessionInterface;\n\nclass ElFinderLoader implements ElFinderLoaderInterface\n{\n    protected string $instance;\n\n    protected ElFinderConfigurationProviderInterface $configurator;\n\n    protected array $config;\n\n    protected ElFinderBridge $bridge;\n\n    protected ?SessionInterface $session = null;\n\n    public function __construct(ElFinderConfigurationProviderInterface $configurator)\n    {\n        $this->configurator = $configurator;\n    }\n\n    /**\n     * @throws Exception\n     */\n    public function configure(): array\n    {\n        $configurator = $this->configurator;\n\n        return $configurator->getConfiguration($this->instance);\n    }\n\n    /**\n     * Configure the Bridge to ElFinder.\n     * @throws Exception\n     */\n    public function initBridge(string $instance, array $efParameters): void\n    {\n        $this->setInstance($instance);\n\n        $arrayInstance = $efParameters['instances'][$instance];\n        $whereIsMulti  = $arrayInstance['where_is_multi'];\n        $multiHome     = $arrayInstance['multi_home_folder'];\n        $separator     = $arrayInstance['folder_separator'];\n\n        $this->config = $this->configure();\n\n        if (count($whereIsMulti) > 0) {\n            foreach ($whereIsMulti as $key => $value) {\n                if ($multiHome) {\n                    $this->config[$key][$value]['path'] = str_replace($separator, '/', $this->config[$key][$value]['path']);\n                    $this->config[$key][$value]['URL']  = str_replace($separator, '/', $this->config[$key][$value]['URL']);\n                }\n            }\n        }\n\n        $this->bridge = new ElFinderBridge($this->config);\n\n        if ($this->session) {\n            $this->bridge->setSession($this->session);\n        }\n    }\n\n    /**\n     * Starts ElFinder.\n     */\n    public function load(Request $request): array|string\n    {\n        $connector = new ElFinderConnector($this->bridge);\n\n        if ($this->config['corsSupport']) {\n            return $connector->execute($request->query->all());\n        }\n\n        return $connector->run($request->query->all());\n    }\n\n    public function setInstance(string $instance): void\n    {\n        $this->instance = $instance;\n    }\n\n    public function setConfigurator(ElFinderConfigurationProviderInterface $configurator): void\n    {\n        $this->configurator = $configurator;\n    }\n\n    /**\n     * Encode path into hash.\n     */\n    public function encode(string $path): mixed\n    {\n        $aPathEncoded = [];\n\n        $volumes = $this->bridge->getVolumes();\n\n        foreach ($volumes as $hashId => $volume) {\n            $aPathEncoded[$hashId] = $volume->getHash($path);\n        }\n\n        if (1 == count($aPathEncoded)) {\n            return array_values($aPathEncoded)[0];\n        } elseif (count($aPathEncoded) > 1) {\n            return $aPathEncoded;\n        }\n\n        return false;\n    }\n\n    /**\n     * Decode path from hash.\n     */\n    public function decode(string $hash): string\n    {\n        $volume = $this->bridge->getVolume($hash);\n\n        /* @var $volume \\elFinderVolumeDriver */\n        return (!empty($volume)) ? $volume->getPath($hash) : false;\n    }\n\n    public function setSession(?SessionInterface $session): void\n    {\n        $this->session = $session;\n    }\n}\n"
  },
  {
    "path": "src/Loader/ElFinderLoaderInterface.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace FM\\ElfinderBundle\\Loader;\n\nuse Exception;\nuse FM\\ElfinderBundle\\Configuration\\ElFinderConfigurationProviderInterface;\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse Symfony\\Component\\HttpFoundation\\Session\\SessionInterface;\n\ninterface ElFinderLoaderInterface\n{\n    /**\n     * @throws Exception\n     */\n    public function configure(): array;\n\n    /**\n     * Configure the Bridge to ElFinder.\n     *\n     * @throws Exception\n     */\n    public function initBridge(string $instance, array $efParameters);\n\n    public function load(Request $request): array|string;\n\n    public function setInstance(string $instance): void;\n\n    public function setConfigurator(ElFinderConfigurationProviderInterface $configurator);\n\n    public function encode(string $path): mixed;\n\n    public function decode(string $hash): string;\n\n    public function setSession(?SessionInterface $session): void;\n}\n"
  },
  {
    "path": "src/Resources/config/routing.yaml",
    "content": "ef_connect:\n    path:  /efconnect/{instance}/{homeFolder}\n    defaults: { _controller: FM\\ElfinderBundle\\Controller\\ElFinderController::load, instance: default, homeFolder: '' }\nef_main_js:\n    path:  /elfinder.main.js\n    defaults: { _controller: FM\\ElfinderBundle\\Controller\\ElFinderController::mainJS }\nelfinder:\n    path: /elfinder/{instance}/{homeFolder}\n    defaults: { _controller: FM\\ElfinderBundle\\Controller\\ElFinderController::show, instance: default, homeFolder: '' }\n"
  },
  {
    "path": "src/Resources/public/tinymceElfinder.js",
    "content": "window.tinymceElfinder = function(opts) {\n    // elFinder node\n    let elfNode = $('<div/>');\n    if (opts.nodeId) {\n        elfNode.attr('id', opts.nodeId);\n        delete opts.nodeId;\n    }\n\n    // upload target folder hash\n    const uploadTargetHash = opts.uploadTargetHash || 'L1_Lw';\n    delete opts.uploadTargetHash;\n\n    // get elFinder insrance\n    const getfm = open => {\n        // CSS class name of TinyMCE conntainer\n        const cls = (tinymce.majorVersion < 5)? 'mce-container' : 'tox';\n        return new Promise((resolve, reject) => {\n            // elFinder instance\n            let elf;\n\n            // Execute when the elFinder instance is created\n            const done = () => {\n                if (open) {\n                    // request to open folder specify\n                    if (!Object.keys(elf.files()).length) {\n                        // when initial request\n                        elf.one('open', () => {\n                            elf.file(open)? resolve(elf) : reject(elf, 'errFolderNotFound');\n                        });\n                    } else {\n                        // elFinder has already been initialized\n                        new Promise((res, rej) => {\n                            if (elf.file(open)) {\n                                res();\n                            } else {\n                                // To acquire target folder information\n                                elf.request({cmd: 'parents', target: open}).done(e =>{\n                                    elf.file(open)? res() : rej();\n                                }).fail(() => {\n                                    rej();\n                                });\n                            }\n                        }).then(() => {\n                            if (elf.cwd().hash == open) {\n                                resolve(elf);\n                            } else {\n                                // Open folder after folder information is acquired\n                                elf.exec('open', open).done(() => {\n                                    resolve(elf);\n                                }).fail(err => {\n                                    reject(elf, err? err : 'errFolderNotFound');\n                                });\n                            }\n                        }).catch((err) => {\n                            reject(elf, err? err : 'errFolderNotFound');\n                        });\n                    }\n                } else {\n                    // show elFinder manager only\n                    resolve(elf);\n                }\n            };\n\n            // Check elFinder instance\n            if (elf = elfNode.elfinder('instance')) {\n                // elFinder instance has already been created\n                done();\n            } else {\n                // To create elFinder instance\n                elf = elfNode.dialogelfinder(Object.assign({\n                    // dialog title\n                    title : 'File Manager',\n                    // start folder setting\n                    startPathHash : open? open : void(0),\n                    // Set to do not use browser history to un-use location.hash\n                    useBrowserHistory : false,\n                    // Disable auto open\n                    autoOpen : false,\n                    // elFinder dialog width\n                    width : '90%',\n                    // elFinder dialog height\n                    height : '90%',\n                    // set getfile command options\n                    commandsOptions : {\n                        getfile: {\n                            oncomplete : 'close'\n                        }\n                    },\n                    bootCallback : (fm) => {\n                        // set z-index\n                        fm.getUI().css('z-index', parseInt($('body>.'+cls+':last').css('z-index')) + 100);\n                    },\n                    getFileCallback : (files, fm) => {}\n                }, opts)).elfinder('instance');\n                done();\n            }\n        });\n    };\n\n    this.browser = function(callback, value, meta) {\n        getfm().then(fm => {\n            let cgf = fm.getCommand('getfile');\n            const regist = () => {\n                fm.options.getFileCallback = cgf.callback = (file, fm) => {\n                    var url, reg, info;\n\n                    // URL normalization\n                    url = fm.convAbsUrl(file.url);\n\n                    // Make file info\n                    info = file.name + ' (' + fm.formatSize(file.size) + ')';\n\n                    // Provide file and text for the link dialog\n                    if (meta.filetype == 'file') {\n                        callback(url, {text: info, title: info});\n                    }\n\n                    // Provide image and alt text for the image dialog\n                    if (meta.filetype == 'image') {\n                        callback(url, {alt: info});\n                    }\n\n                    // Provide alternative source and posted for the media dialog\n                    if (meta.filetype == 'media') {\n                        callback(url);\n                    }\n                };\n                fm.getUI().dialogelfinder('open');\n            };\n            if (cgf) {\n                // elFinder booted\n                regist();\n            } else {\n                // elFinder booting now\n                fm.bind('init', () => {\n                    cgf = fm.getCommand('getfile');\n                    regist();\n                });\n            }\n        });\n\n        return false;\n    };\n\n    this.uploadHandler = function (blobInfo, success, failure) {\n        new Promise(function(resolve, reject) {\n            getfm(uploadTargetHash).then(fm => {\n                let fmNode = fm.getUI(),\n                    file = blobInfo.blob(),\n                    clipdata = true;\n                const err = (e) => {\n                        var dlg = e.data.dialog || {};\n                        if (dlg.hasClass('elfinder-dialog-error') || dlg.hasClass('elfinder-confirm-upload')) {\n                            fmNode.dialogelfinder('open');\n                            fm.unbind('dialogopened', err);\n                        }\n                    },\n                    closeDlg = () => {\n                        if (!fm.getUI().find('.elfinder-dialog-error:visible,.elfinder-confirm-upload:visible').length) {\n                            fmNode.dialogelfinder('close');\n                        }\n                    };\n\n                // check file object\n                if (file.name) {\n                    // file blob of client side file object\n                    clipdata = void(0);\n                }\n                // Bind err function and exec upload\n                fm.bind('dialogopened', err).exec('upload', {\n                    files: [file],\n                    target: uploadTargetHash,\n                    clipdata: clipdata, // to get unique name on connector\n                    dropEvt: {altKey: true, ctrlKey: true} // diable watermark on demo site\n                }, void(0), uploadTargetHash)\n                    .done(data => {\n                        if (data.added && data.added.length) {\n                            fm.url(data.added[0].hash, { async: true }).done(function(url) {\n                                // prevent to use browser cache\n                                url += (url.match(/\\?/)? '&' : '?') + '_t=' + data.added[0].ts;\n                                resolve(fm.convAbsUrl(url));\n                            }).fail(function() {\n                                reject(fm.i18n('errFileNotFound'));\n                            });\n                        } else {\n                            reject(fm.i18n(data.error? data.error : 'errUpload'));\n                        }\n                    })\n                    .fail(err => {\n                        const error = fm.parseError(err);\n                        reject(fm.i18n(error? (error === 'userabort'? 'errAbort' : error) : 'errUploadNoFiles'));\n                    })\n                    .always(() => {\n                        fm.unbind('dialogopened', err);\n                        closeDlg();\n                    });\n            }).catch((fm, err) => {\n                const error = fm.parseError(err);\n                reject(fm.i18n(error? (error === 'userabort'? 'errAbort' : error) : 'errUploadNoFiles'));\n            });\n        }).then((url) => {\n            success(url);\n        }).catch((err) => {\n            failure(err);\n        });\n    };\n};\n"
  },
  {
    "path": "src/Resources/views/Elfinder/ckeditor.html.twig",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=2\">\n    <script data-main=\"{{path('ef_main_js')}}\" src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\"></script>\n    <script>\n        function getUrlParam(paramName) {\n            const reParam = new RegExp('(?:[\\?&]|&amp;)' + paramName + '=([^&]+)', 'i');\n            const match = window.location.search.match(reParam);\n\n            return (match && match.length > 1) ? match[1] : '' ;\n        }\n        const funcNum = getUrlParam('CKEditorFuncNum');\n        const mode = getUrlParam('mode');\n        define('elFinderConfig', {\n            // elFinder options (REQUIRED)\n            // Documentation for client options:\n            // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options\n            defaultOpts : {\n                url : '{{path('ef_connect', { 'instance': instance, 'homeFolder': homeFolder } )}}',\n                lang : '{{locale}}',\n                onlyMimes: {{ onlyMimes|raw }},\n                getFileCallback : function(file) {\n                    if (funcNum) {\n                        {% if relative_path %}\n                        window.opener.CKEDITOR.tools.callFunction(funcNum, '{{ pathPrefix }}'+file.url.replace(\"{{ app.request.schemeAndHttpHost }}/\", \"\"));\n                        {% else %}\n                        window.opener.CKEDITOR.tools.callFunction(funcNum, file.url);\n                        {% endif %}\n                        window.close();\n                    }\n                },\n                commandsOptions : {\n                    edit : {\n                        extraOptions : {\n                            // set API key to enable Creative Cloud image editor\n                            // see https://console.adobe.io/\n                            creativeCloudApiKey : '',\n                            // browsing manager URL for CKEditor, TinyMCE\n                            // uses self location with the empty value\n                            managerUrl : ''\n                        }\n                    },\n                    quicklook : {\n                        // to enable CAD-Files and 3D-Models preview with sharecad.org\n                        sharecadMimes : ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile'],\n                        // to enable preview with Google Docs Viewer\n                        googleDocsMimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf'],\n                        // to enable preview with Microsoft Office Online Viewer\n                        // these MIME types override \"googleDocsMimes\"\n                        officeOnlineMimes : ['application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']\n                    }\n                },\n                // bootCalback calls at before elFinder boot up\n                bootCallback : function(fm, extraObj) {\n                    /* any bind functions etc. */\n                    fm.bind('init', function() {\n                        // any your code\n                    });\n                    // for example set document.title dynamically.\n                    var title = document.title;\n                    fm.bind('open', function() {\n                        var path = '',\n                            cwd  = fm.cwd();\n                        if (cwd) {\n                            path = fm.path(cwd.hash) || null;\n                        }\n                        document.title = path? path + ':' + title : title;\n                    }).bind('destroy', function() {\n                        document.title = title;\n                    });\n                }\n            },\n            managers : {\n                // 'DOM Element ID': { /* elFinder options of this DOM Element */ }\n                'elfinder': {}\n            }\n        });\n    </script>\n</head>\n<body>\n\n<!-- Element where elFinder will be created (REQUIRED) -->\n<div id=\"elfinder\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/elfinder_type.html.twig",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=2\">\n    <script data-main=\"{{path('ef_main_js')}}\" src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\"></script>\n    <script>\n        define('elFinderConfig', {\n            // elFinder options (REQUIRED)\n            // Documentation for client options:\n            // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options\n            defaultOpts : {\n                url : '{{path('ef_connect', { 'instance': instance, 'homeFolder': homeFolder } )}}',\n                lang : '{{locale}}',\n                onlyMimes: {{ onlyMimes|raw }},\n                getFileCallback: function(file) {\n                    {% if relative_path %}\n                        window.opener.setValue('{{ pathPrefix }}'+file.url.replace(\"{{ app.request.schemeAndHttpHost }}/\", \"\"), \"{{ id }}\");\n                    {% else %}\n                        window.opener.setValue(file.url, \"{{ id }}\");\n                    {% endif %}\n                    window.close();\n                },\n                commandsOptions : {\n                    edit : {\n                        extraOptions : {\n                            // set API key to enable Creative Cloud image editor\n                            // see https://console.adobe.io/\n                            creativeCloudApiKey : '',\n                            // browsing manager URL for CKEditor, TinyMCE\n                            // uses self location with the empty value\n                            managerUrl : ''\n                        }\n                    },\n                    quicklook : {\n                        // to enable CAD-Files and 3D-Models preview with sharecad.org\n                        sharecadMimes : ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile'],\n                        // to enable preview with Google Docs Viewer\n                        googleDocsMimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf'],\n                        // to enable preview with Microsoft Office Online Viewer\n                        // these MIME types override \"googleDocsMimes\"\n                        officeOnlineMimes : ['application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']\n                    }\n                },\n                // bootCallback calls before elFinder boots up\n                bootCallback : function(fm, extraObj) {\n                    /* any bind functions etc. */\n                    fm.bind('init', function() {\n                        // any of your code\n                    });\n                    // for example set document.title dynamically.\n                    var title = document.title;\n                    fm.bind('open', function() {\n                        var path = '',\n                            cwd  = fm.cwd();\n                        if (cwd) {\n                            path = fm.path(cwd.hash) || null;\n                        }\n                        document.title = path? path + ':' + title : title;\n                    }).bind('destroy', function() {\n                        document.title = title;\n                    });\n                }\n            },\n            managers : {\n                // 'DOM Element ID': { /* elFinder options of this DOM Element */ }\n                'elfinder': {}\n            }\n        });\n    </script>\n</head>\n<body>\n\n<!-- Element where elFinder will be created (REQUIRED) -->\n<div id=\"elfinder\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/fm_tinymce.html.twig",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=2\">\n    <script data-main=\"{{path('ef_main_js')}}\" src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\"></script>\n    <script>\n        var FileBrowserDialogue = {\n            mySubmit: function (file, elf) {\n                // pass selected file data to TinyMCE\n                parent.tinymce.activeEditor.windowManager.getParams().oninsert(file, elf);\n                // close popup window\n                parent.tinymce.activeEditor.windowManager.close();\n            }\n        };\n        define('elFinderConfig', {\n            // elFinder options (REQUIRED)\n            // Documentation for client options:\n            // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options\n            defaultOpts : {\n                url : '{{path('ef_connect', { 'instance': instance, 'homeFolder': homeFolder } )}}',\n                lang : '{{locale}}',\n                onlyMimes: {{ onlyMimes|raw }},\n                getFileCallback: function(file) { // editor callback\n                    {% if relative_path %}\n                    file.url = '{{ pathPrefix }}' + file.url.replace(\"{{ app.request.schemeAndHttpHost }}/\", \"\");\n                    FileBrowserDialogue.mySubmit(file, elf); // pass selected file path to TinyMCE\n                    {% else %}\n                    FileBrowserDialogue.mySubmit(file, elf); // pass selected file path to TinyMCE\n                    {% endif %}\n                },\n                commandsOptions : {\n                    edit : {\n                        extraOptions : {\n                            // set API key to enable Creative Cloud image editor\n                            // see https://console.adobe.io/\n                            creativeCloudApiKey : '',\n                            // browsing manager URL for CKEditor, TinyMCE\n                            // uses self location with the empty value\n                            managerUrl : ''\n                        }\n                    },\n                    quicklook : {\n                        // to enable CAD-Files and 3D-Models preview with sharecad.org\n                        sharecadMimes : ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile'],\n                        // to enable preview with Google Docs Viewer\n                        googleDocsMimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf'],\n                        // to enable preview with Microsoft Office Online Viewer\n                        // these MIME types override \"googleDocsMimes\"\n                        officeOnlineMimes : ['application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']\n                    }\n                },\n                // bootCalback calls at before elFinder boot up\n                bootCallback : function(fm, extraObj) {\n                    /* any bind functions etc. */\n                    fm.bind('init', function() {\n                        // any your code\n                    });\n                    // for example set document.title dynamically.\n                    var title = document.title;\n                    fm.bind('open', function() {\n                        var path = '',\n                            cwd  = fm.cwd();\n                        if (cwd) {\n                            path = fm.path(cwd.hash) || null;\n                        }\n                        document.title = path? path + ':' + title : title;\n                    }).bind('destroy', function() {\n                        document.title = title;\n                    });\n                }\n            },\n            managers : {\n                // 'DOM Element ID': { /* elFinder options of this DOM Element */ }\n                'elfinder': {}\n            }\n        });\n    </script>\n</head>\n<body>\n\n<!-- Element where elFinder will be created (REQUIRED) -->\n<div id=\"elfinder\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/helper/_summernote.html.twig",
    "content": "<script type=\"text/javascript\">\n    function elFinderBrowser(){\n            window.open(\n                \"{{ url('elfinder', {'instance': instance}) }}\",\n                \"\",\n                \"width={{ width }}, height={{ height }}, resizable=yes, scrollbars=no, status=no, toolbar=no\"\n            );\n            return false;\n        }\n</script>\n\n"
  },
  {
    "path": "src/Resources/views/Elfinder/helper/_tinymce.html.twig",
    "content": "<script type=\"text/javascript\">\n    //<![CDATA[\n    function elFinderBrowser (field_name, url, type, win) {\n        tinyMCE.activeEditor.windowManager.open({\n            file: \"{{ url('elfinder', {'instance': instance}) }}\",\n            title: \"{{ title }}\",\n            width: {{ width }},\n            height: {{ height }},\n            resizable: 'yes',\n            inline: 'yes',    // This parameter only has an effect if you use the inlinepopups plugin!\n            popup_css: false, // Disable TinyMCE's default popup CSS\n            close_previous: 'no'\n        }, {\n            window: win,\n            input: field_name\n        });\n        return false;\n    }\n    //]]>\n</script>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/helper/_tinymce4.html.twig",
    "content": "<script type=\"text/javascript\">\n    function elFinderBrowser (field_name, url, type, win) {\n        tinymce.activeEditor.windowManager.open({\n            file:\"{{ url('elfinder', {'instance': instance}) }}\",\n            title: \"{{ title }}\",\n            width: {{ width }},\n            height: {{ height }},\n            resizable: 'yes'\n        }, {\n            setUrl: function (url) {\n                win.document.getElementById(field_name).value = url;\n            }\n        });\n        return false;\n    }\n</script>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/helper/_tinymce5.html.twig",
    "content": "<script type=\"text/javascript\">\n(function() {\n    const mceElf = new tinymceElfinder({\n        // connector URL (Use elFinder Demo site's connector for this demo)\n        url: \"{{ url('elfinder', {'instance': instance}) }}\",\n        nodeId: 'elfinder'\n    });\n})();\n</script>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/helper/main.js.twig",
    "content": "(function(){\n    \"use strict\";\n    var // jQuery and jQueryUI version\n        jqver = '3.3.1',\n        uiver = '1.12.1',\n\n        // Detect language (optional)\n        lang = (function() {\n            var locq = window.location.search,\n                map = {\n                    'pt' : 'pt_BR',\n                    'ug' : 'ug_CN',\n                    'zh' : 'zh_CN'\n                },\n                full = {\n                    'zh_tw' : 'zh_TW',\n                    'zh_cn' : 'zh_CN',\n                    'fr_ca' : 'fr_CA'\n                },\n                fullLang, locm, lang;\n            if (locq && (locm = locq.match(/lang=([a-zA-Z_-]+)/))) {\n                // detection by url query (?lang=xx)\n                fullLang = locm[1];\n            } else {\n                // detection by browser language\n                fullLang = (navigator.browserLanguage || navigator.language || navigator.userLanguage || '');\n            }\n            fullLang = fullLang.replace('-', '_').substr(0,5).toLowerCase();\n            if (full[fullLang]) {\n                lang = full[fullLang];\n            } else {\n                lang = (fullLang || 'en').substr(0,2);\n                if (map[lang]) {\n                    lang = map[lang];\n                }\n            }\n            return lang;\n        })(),\n\n        // Start elFinder (REQUIRED)\n        start = function(elFinder, editors, config) {\n            // load jQueryUI CSS\n            elFinder.prototype.loadCss('//cdnjs.cloudflare.com/ajax/libs/jqueryui/'+uiver+'/themes/smoothness/jquery-ui.css');\n\n            $(function() {\n                var optEditors = {\n                        commandsOptions: {\n                            edit: {\n                                editors: Array.isArray(editors)? editors : []\n                            }\n                        }\n                    },\n                    opts = {};\n\n                // Interpretation of \"elFinderConfig\"\n                if (config && config.managers) {\n                    $.each(config.managers, function(id, mOpts) {\n                        opts = Object.assign(opts, config.defaultOpts || {});\n                        // editors marges to opts.commandOptions.edit\n                        try {\n                            mOpts.commandsOptions.edit.editors = mOpts.commandsOptions.edit.editors.concat(editors || []);\n                        } catch(e) {\n                            Object.assign(mOpts, optEditors);\n                        }\n                        // Make elFinder\n                        $('#' + id).elfinder(\n                            // 1st Arg - options\n                            $.extend(true, { lang: lang }, opts, mOpts || {}),\n                            // 2nd Arg - before boot up function\n                            function(fm, extraObj) {\n                                // `init` event callback function\n                                fm.bind('init', function() {\n                                    // Optional for Japanese decoder \"encoding-japanese\"\n                                    if (fm.lang === 'ja') {\n                                        require(\n                                            [ 'encoding-japanese' ],\n                                            function(Encoding) {\n                                                if (Encoding && Encoding.convert) {\n                                                    fm.registRawStringDecoder(function(s) {\n                                                        return Encoding.convert(s, {to:'UNICODE',type:'string'});\n                                                    });\n                                                }\n                                            }\n                                        );\n                                    }\n                                });\n                            }\n                        );\n                    });\n                } else {\n                    alert('\"elFinderConfig\" object is wrong.');\n                }\n            });\n        },\n\n        // JavaScript loader (REQUIRED)\n        load = function() {\n            require([\n                    'elfinder'\n                    , 'extras/editors.default.min'               // load text, image editors\n                    , 'elFinderConfig'\n                    //\t, 'extras/quicklook.googledocs.min'          // optional preview for GoogleApps contents on the GoogleDrive volume\n                ],\n                start,\n                function(error) {\n                    alert(error.message);\n                }\n            );\n        },\n\n        // is IE8 or :? for determine the jQuery version to use (optional)\n        old = (typeof window.addEventListener === 'undefined' && typeof document.getElementsByClassName === 'undefined')\n            ||\n            (!window.chrome && !document.unqueID && !window.opera && !window.sidebar && 'WebkitAppearance' in document.documentElement.style && document.body.style && typeof document.body.style.webkitFilter === 'undefined');\n\n    // config of RequireJS (REQUIRED)\n    require.config({\n        baseUrl : \"{{ mainUrl }}\",\n        paths : {\n            'jquery'   : '//cdnjs.cloudflare.com/ajax/libs/jquery/'+(old? '1.12.4' : jqver)+'/jquery.min',\n            'jquery-ui': '//cdnjs.cloudflare.com/ajax/libs/jqueryui/'+uiver+'/jquery-ui.min',\n            'elfinder' : 'elfinder.min',\n            'encoding-japanese': '//cdn.rawgit.com/polygonplanet/encoding.js/1.0.26/encoding.min'\n        },\n        waitSeconds : 10 // optional\n    });\n\n    // load JavaScripts (REQUIRED)\n    load();\n\n})();\n"
  },
  {
    "path": "src/Resources/views/Elfinder/simple.html.twig",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=2\">\n    <script data-main=\"{{path('ef_main_js')}}\" src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\"></script>\n    <script>\n        define('elFinderConfig', {\n            // elFinder options (REQUIRED)\n            // Documentation for client options:\n            // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options\n            defaultOpts : {\n                url : '{{path('ef_connect', { 'instance': instance, 'homeFolder': homeFolder } )}}',\n                lang : '{{locale}}',\n                onlyMimes: {{ onlyMimes|raw }},\n                commandsOptions : {\n                    edit : {\n                        extraOptions : {\n                            // set API key to enable Creative Cloud image editor\n                            // see https://console.adobe.io/\n                            creativeCloudApiKey : '',\n                            // browsing manager URL for CKEditor, TinyMCE\n                            // uses self location with the empty value\n                            managerUrl : ''\n                        }\n                    },\n                    quicklook : {\n                        // to enable CAD-Files and 3D-Models preview with sharecad.org\n                        sharecadMimes : ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile'],\n                        // to enable preview with Google Docs Viewer\n                        googleDocsMimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf'],\n                        // to enable preview with Microsoft Office Online Viewer\n                        // these MIME types override \"googleDocsMimes\"\n                        officeOnlineMimes : ['application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']\n                    }\n                },\n                // bootCalback calls at before elFinder boot up\n                bootCallback : function(fm, extraObj) {\n                    /* any bind functions etc. */\n                    fm.bind('init', function() {\n                        // any your code\n                    });\n                    // for example set document.title dynamically.\n                    var title = document.title;\n                    fm.bind('open', function() {\n                        var path = '',\n                            cwd  = fm.cwd();\n                        if (cwd) {\n                            path = fm.path(cwd.hash) || null;\n                        }\n                        document.title = path? path + ':' + title : title;\n                    }).bind('destroy', function() {\n                        document.title = title;\n                    });\n                }\n            },\n            managers : {\n                // 'DOM Element ID': { /* elFinder options of this DOM Element */ }\n                'elfinder': {}\n            }\n        });\n    </script>\n</head>\n<body>\n\n<!-- Element where elFinder will be created (REQUIRED) -->\n<div id=\"elfinder\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/summernote.html.twig",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=2\">\n    <script data-main=\"{{path('ef_main_js')}}\" src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\"></script>\n    <script>\n        define('elFinderConfig', {\n            // elFinder options (REQUIRED)\n            // Documentation for client options:\n            // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options\n            defaultOpts : {\n                url : '{{path('ef_connect', { 'instance': instance, 'homeFolder': homeFolder } )}}',\n                lang : '{{locale}}',\n                onlyMimes: {{ onlyMimes|raw }},\n                destroyOnClose : true,\n                getFileCallback : function(files, fm) {\n                    if (files.mime.match('application')) {\n                        window.opener.$('.summernote').summernote('createLink', {\n                            text: files.name,\n                            url: files.url,\n                            newWindow: true\n                        });\n                        window.close();\n                    }\n                    if(files.mime.match('image')){\n                        window.opener.$('.summernote').summernote('editor.insertImage', files.url);\n                        window.close();\n                    }\n                },\n                commandsOptions : {\n                    edit : {\n                        extraOptions : {\n                            // set API key to enable Creative Cloud image editor\n                            // see https://console.adobe.io/\n                            creativeCloudApiKey : '',\n                            // browsing manager URL for CKEditor, TinyMCE\n                            // uses self location with the empty value\n                            managerUrl : ''\n                        }\n                    },\n                    quicklook : {\n                        // to enable CAD-Files and 3D-Models preview with sharecad.org\n                        sharecadMimes : ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile'],\n                        // to enable preview with Google Docs Viewer\n                        googleDocsMimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf'],\n                        // to enable preview with Microsoft Office Online Viewer\n                        // these MIME types override \"googleDocsMimes\"\n                        officeOnlineMimes : ['application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']\n                    }\n                },\n                // bootCalback calls at before elFinder boot up\n                bootCallback : function(fm, extraObj) {\n                    /* any bind functions etc. */\n                    fm.bind('init', function() {\n                        // any your code\n                    });\n                    // for example set document.title dynamically.\n                    var title = document.title;\n                    fm.bind('open', function() {\n                        var path = '',\n                            cwd  = fm.cwd();\n                        if (cwd) {\n                            path = fm.path(cwd.hash) || null;\n                        }\n                        document.title = path? path + ':' + title : title;\n                    }).bind('destroy', function() {\n                        document.title = title;\n                    });\n                }\n            },\n            managers : {\n                // 'DOM Element ID': { /* elFinder options of this DOM Element */ }\n                'elfinder': {}\n            }\n        });\n    </script>\n</head>\n<body>\n\n<!-- Element where elFinder will be created (REQUIRED) -->\n<div id=\"elfinder\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/Resources/views/Elfinder/tinymce.html.twig",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=2\">\n    <script data-main=\"{{path('ef_main_js')}}\" src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\"></script>\n    <script>\n        var FileBrowserDialogue = {\n            init: function () {},\n            mySubmit: function (URL) {\n\n                var win = tinyMCEPopup.getWindowArg('window');\n\n                // pass selected file path to TinyMCE\n                win.document.getElementById(tinyMCEPopup.getWindowArg('input')).value = URL;\n\n                // are we an image browser?\n                if (typeof(win.ImageDialog) != 'undefined') {\n                    // update image dimensions\n                    if (win.ImageDialog.getImageData) {\n                        win.ImageDialog.getImageData();\n                    }\n                    // update preview if necessary\n                    if (win.ImageDialog.showPreviewImage) {\n                        win.ImageDialog.showPreviewImage(URL);\n                    }\n                }\n\n                // close popup window\n                tinyMCEPopup.close();\n            }\n        };\n\n        tinyMCEPopup.onInit.add(FileBrowserDialogue.init, FileBrowserDialogue);\n        define('elFinderConfig', {\n            // elFinder options (REQUIRED)\n            // Documentation for client options:\n            // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options\n            defaultOpts : {\n                url : '{{path('ef_connect', { 'instance': instance, 'homeFolder': homeFolder } )}}',\n                lang : '{{locale}}',\n                onlyMimes: {{ onlyMimes|raw }},\n                getfile : {\n                    onlyURL : true,\n                    multiple : false,\n                    folders : false\n                },\n                getFileCallback : function(url) {\n                    path = '/' + url.replace(\"{{ app.request.schemeAndHttpHost }}/\", \"\");\n                    FileBrowserDialogue.mySubmit(path);\n                },\n                commandsOptions : {\n                    edit : {\n                        extraOptions : {\n                            // set API key to enable Creative Cloud image editor\n                            // see https://console.adobe.io/\n                            creativeCloudApiKey : '',\n                            // browsing manager URL for CKEditor, TinyMCE\n                            // uses self location with the empty value\n                            managerUrl : ''\n                        }\n                    },\n                    quicklook : {\n                        // to enable CAD-Files and 3D-Models preview with sharecad.org\n                        sharecadMimes : ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile'],\n                        // to enable preview with Google Docs Viewer\n                        googleDocsMimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf'],\n                        // to enable preview with Microsoft Office Online Viewer\n                        // these MIME types override \"googleDocsMimes\"\n                        officeOnlineMimes : ['application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']\n                    }\n                },\n                // bootCalback calls at before elFinder boot up\n                bootCallback : function(fm, extraObj) {\n                    /* any bind functions etc. */\n                    fm.bind('init', function() {\n                        // any your code\n                    });\n                    // for example set document.title dynamically.\n                    var title = document.title;\n                    fm.bind('open', function() {\n                        var path = '',\n                            cwd  = fm.cwd();\n                        if (cwd) {\n                            path = fm.path(cwd.hash) || null;\n                        }\n                        document.title = path? path + ':' + title : title;\n                    }).bind('destroy', function() {\n                        document.title = title;\n                    });\n                }\n            },\n            managers : {\n                // 'DOM Element ID': { /* elFinder options of this DOM Element */ }\n                'elfinder': {}\n            }\n        });\n    </script>\n</head>\n<body>\n\n<!-- Element where elFinder will be created (REQUIRED) -->\n<div id=\"elfinder\"></div>\n\n</body>\n</html>"
  },
  {
    "path": "src/Resources/views/Elfinder/tinymce4.html.twig",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=2\">\n    <script data-main=\"{{path('ef_main_js')}}\" src=\"//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js\"></script>\n    <script>\n        var FileBrowserDialogue = {\n            init: function () {\n                // Here goes your code for setting your custom things onLoad.\n            },\n            mySubmit: function (URL) {\n                // pass selected file path to TinyMCE\n                top.tinymce.activeEditor.windowManager.getParams().setUrl(URL);\n\n                // close popup window\n                top.tinymce.activeEditor.windowManager.close();\n            }\n        };\n        define('elFinderConfig', {\n            // elFinder options (REQUIRED)\n            // Documentation for client options:\n            // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options\n            defaultOpts : {\n                url : '{{path('ef_connect', { 'instance': instance, 'homeFolder': homeFolder } )}}',\n                lang : '{{locale}}',\n                onlyMimes: {{ onlyMimes|raw }},\n                getFileCallback: function(file) { // editor callback\n                    {% if relative_path %}\n                    FileBrowserDialogue.mySubmit('{{ pathPrefix }}'+file.url.replace(\"{{ app.request.schemeAndHttpHost }}/\", \"\")); // pass selected file path to TinyMCE\n                    {% else %}\n                    FileBrowserDialogue.mySubmit(file.url); // pass selected file path to TinyMCE\n                    {% endif %}\n\n                },\n                commandsOptions : {\n                    edit : {\n                        extraOptions : {\n                            // set API key to enable Creative Cloud image editor\n                            // see https://console.adobe.io/\n                            creativeCloudApiKey : '',\n                            // browsing manager URL for CKEditor, TinyMCE\n                            // uses self location with the empty value\n                            managerUrl : ''\n                        }\n                    },\n                    quicklook : {\n                        // to enable CAD-Files and 3D-Models preview with sharecad.org\n                        sharecadMimes : ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile'],\n                        // to enable preview with Google Docs Viewer\n                        googleDocsMimes : ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf'],\n                        // to enable preview with Microsoft Office Online Viewer\n                        // these MIME types override \"googleDocsMimes\"\n                        officeOnlineMimes : ['application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']\n                    }\n                },\n                // bootCalback calls at before elFinder boot up\n                bootCallback : function(fm, extraObj) {\n                    /* any bind functions etc. */\n                    fm.bind('init', function() {\n                        // any your code\n                    });\n                    // for example set document.title dynamically.\n                    var title = document.title;\n                    fm.bind('open', function() {\n                        var path = '',\n                            cwd  = fm.cwd();\n                        if (cwd) {\n                            path = fm.path(cwd.hash) || null;\n                        }\n                        document.title = path? path + ':' + title : title;\n                    }).bind('destroy', function() {\n                        document.title = title;\n                    });\n                }\n            },\n            managers : {\n                // 'DOM Element ID': { /* elFinder options of this DOM Element */ }\n                'elfinder': {}\n            }\n        });\n    </script>\n</head>\n<body>\n\n<!-- Element where elFinder will be created (REQUIRED) -->\n<div id=\"elfinder\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "src/Resources/views/Form/elfinder_widget.html.twig",
    "content": "{% block elfinder_widget %}\n    <input type=\"text\" {{ block('widget_attributes') }} {% if value is not empty %}value=\"{{ value }}\" {% endif %} data-type=\"elfinder-input-field\" />\n    {% if enable and instance is defined %}\n        <script type=\"text/javascript\" charset=\"utf-8\">\n            live('click', '[data-type=\"elfinder-input-field\"][id=\"{{ id }}\"]', function (event) {\n                console.warn('Test');\n                var childWin = window.open(\"{{path('elfinder', {'instance': instance, 'homeFolder': homeFolder })}}?id={{ id }}\", \"popupWindow\", \"height=450, width=900\");\n            });\n            function live (eventType, elementQuerySelector, cb) {\n                document.addEventListener(eventType, function (event) {\n                    var qs = document.querySelectorAll(elementQuerySelector);\n                    if (qs) {\n                        var el = event.target, index = -1;\n                        while (el && ((index = Array.prototype.indexOf.call(qs, el)) === -1)) {\n                            el = el.parentElement;\n                        }\n                        if (index > -1) {\n                            cb.call(el, event);\n                        }\n                    }\n                })\n            }\n            function setValue(value, element_id) {\n                document.querySelector('[data-type=\"elfinder-input-field\"]' + (element_id ? '[id=\"'+ element_id +'\"]': '')).value = value;\n            }\n        </script>\n    {% endif %}\n{% endblock %}\n"
  },
  {
    "path": "src/Security/ElfinderSecurityInterface.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Security;\n\ninterface ElfinderSecurityInterface\n{\n    /**\n     * Array structure should have roles as keys and values as array of disabled commands\n     * array('ROLE_USER' => array('rm','delete'));\n     * First items (roles) in array has higher priority.\n     */\n    public function getConfiguration(): array;\n}\n"
  },
  {
    "path": "src/Session/ElFinderSession.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Session;\n\nuse elFinderSessionInterface;\nuse Symfony\\Component\\HttpFoundation\\Session\\SessionInterface;\n\nclass ElFinderSession implements elFinderSessionInterface\n{\n    protected SessionInterface $session;\n\n    public function __construct(SessionInterface $session)\n    {\n        $this->session = $session;\n    }\n\n    public function start()\n    {\n        $this->session->start();\n    }\n\n    public function close()\n    {\n        $this->session->save();\n    }\n\n    public function get($key, $empty = '')\n    {\n        return $this->session->get($key, $empty);\n    }\n\n    public function set($key, $data)\n    {\n        $this->session->set($key, $data);\n    }\n\n    public function remove($key)\n    {\n        $this->session->remove($key);\n    }\n}\n"
  },
  {
    "path": "src/Twig/Extension/FMElfinderExtension.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Twig\\Extension;\n\nuse Twig\\Environment;\nuse Twig\\Error\\LoaderError;\nuse Twig\\Error\\RuntimeError;\nuse Twig\\Error\\SyntaxError;\nuse Twig\\Extension\\AbstractExtension;\nuse Twig\\TwigFunction;\n\nclass FMElfinderExtension extends AbstractExtension\n{\n    protected Environment $twig;\n\n    public function __construct(Environment $twig)\n    {\n        $this->twig = $twig;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return array\n     */\n    public function getFunctions(): array\n    {\n        $options = ['is_safe' => ['html']];\n\n        return [\n            new TwigFunction('elfinder_tinymce_init', $this->tinymce(...), $options),\n            new TwigFunction('elfinder_tinymce_init4', $this->tinymce4(...), $options),\n            new TwigFunction('elfinder_tinymce_init5', $this->tinymce5(...), $options),\n            new TwigFunction('elfinder_summernote_init', $this->summernote(...), $options),\n        ];\n    }\n\n    /**\n     * @throws LoaderError\n     * @throws RuntimeError\n     * @throws SyntaxError\n     */\n    public function tinymce(string $instance = 'default', array $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0']): string\n    {\n        if (!is_string($instance)) {\n            throw new RuntimeError('The function can be applied to strings only.');\n        }\n\n        return $this->twig->render(\n            '@FMElfinder/Elfinder/helper/_tinymce.html.twig',\n            [\n                'instance' => $instance,\n                'width' => $parameters['width'],\n                'height' => $parameters['height'],\n                'title' => $parameters['title'],\n            ]\n        );\n    }\n\n    /**\n     * @throws LoaderError\n     * @throws RuntimeError\n     * @throws SyntaxError\n     */\n    public function tinymce4(string $instance = 'default', array $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0']): string\n    {\n        return $this->twig->render(\n            '@FMElfinder/Elfinder/helper/_tinymce4.html.twig',\n            [\n                'instance' => $instance,\n                'width' => $parameters['width'],\n                'height' => $parameters['height'],\n                'title' => $parameters['title'],\n            ]\n        );\n    }\n\n    public function tinymce5(string $instance = 'default'): string\n    {\n        return $this->twig->render(\n            '@FMElfinder/Elfinder/helper/_tinymce5.html.twig', [\n                'instance' => $instance,\n            ]\n        );\n    }\n\n    /**\n     * @throws LoaderError\n     * @throws RuntimeError\n     * @throws SyntaxError\n     */\n    public function summernote(\n        string $instance = 'default',\n        string $selector = '.summernote',\n        array  $parameters = ['width' => 900, 'height' => 450, 'title' => 'elFinder 2.0']\n    ): string {\n        return $this->twig->render(\n            '@FMElfinder/Elfinder/helper/_summernote.html.twig',\n            [\n                'instance' => $instance,\n                'selector' => $selector,\n                'width' => $parameters['width'],\n                'height' => $parameters['height'],\n                'title' => $parameters['title'],\n            ]\n        );\n    }\n\n    /**\n     * (non-PHPdoc).\n     *\n     * @see Twig_ExtensionInterface::getName()\n     */\n    public function getName(): string\n    {\n        return 'fm_elfinder_init';\n    }\n}\n"
  },
  {
    "path": "tests/Command/ElFinderInstallerCommandTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\Command;\n\nuse FM\\ElfinderBundle\\Command\\ElFinderInstallerCommand;\nuse PHPUnit\\Framework\\TestCase;\nuse Symfony\\Component\\Console\\Application;\nuse Symfony\\Component\\Console\\Tester\\CommandTester;\nuse Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface;\nuse Symfony\\Component\\Filesystem\\Filesystem;\nuse ReflectionClass;\n\nclass ElFinderInstallerCommandTest extends TestCase\n{\n    private Filesystem $fileSystem;\n    private ParameterBagInterface $parameterBag;\n    private CommandTester $commandTester;\n    private string $projectDir;\n    private string $vendorDir;\n\n    protected function setUp(): void\n    {\n        // Calculate real paths\n        $reflection = new ReflectionClass(\\Composer\\Autoload\\ClassLoader::class);\n        $this->vendorDir = dirname($reflection->getFileName(), 3) . DIRECTORY_SEPARATOR . 'vendor';\n        $this->projectDir = dirname($this->vendorDir);\n\n        $this->fileSystem = $this->createMock(Filesystem::class);\n        $this->parameterBag = $this->createMock(ParameterBagInterface::class);\n\n        $this->parameterBag\n            ->method('get')\n            ->willReturnMap([\n                ['kernel.project_dir', $this->projectDir]\n            ]);\n\n        $application = new Application();\n        $command = new ElFinderInstallerCommand($this->fileSystem, $this->parameterBag);\n        $application->addCommands([$command]);\n\n\n\n\n        $this->commandTester = new CommandTester($application->find('elfinder:install'));\n    }\n\n    public function testExecuteWithDefaultDocroot(): void\n    {\n        $this->assertFileSystemOperations('public');\n        $this->commandTester->execute([]);\n        $this->assertCommandOutput();\n        $this->assertEquals(0, $this->commandTester->getStatusCode());\n    }\n\n    public function testExecuteWithCustomDocroot(): void\n    {\n        $this->assertFileSystemOperations('custom');\n        $this->commandTester->execute(['--docroot' => 'custom']);\n        $this->assertCommandOutput();\n        $this->assertEquals(0, $this->commandTester->getStatusCode());\n    }\n\n    private function assertFileSystemOperations(string $docroot): void\n    {\n        $expectedCalls = [\n            [\n                $this->vendorDir . '/studio-42/elfinder/css',\n                $this->projectDir . \"/$docroot/bundles/fmelfinder/css\"\n            ],\n            [\n                $this->vendorDir . '/studio-42/elfinder/img',\n                $this->projectDir . \"/$docroot/bundles/fmelfinder/img\"\n            ],\n            [\n                $this->vendorDir . '/studio-42/elfinder/js',\n                $this->projectDir . \"/$docroot/bundles/fmelfinder/js\"\n            ],\n            [\n                $this->vendorDir . '/studio-42/elfinder/sounds',\n                $this->projectDir . \"/$docroot/bundles/fmelfinder/sounds\"\n            ]\n        ];\n\n        $callIndex = 0;\n        $this->fileSystem\n            ->expects($this->exactly(4))\n            ->method('mirror')\n            ->willReturnCallback(function ($source, $target) use (&$callIndex, $expectedCalls) {\n                $this->assertEquals($expectedCalls[$callIndex][0], $source, \"Incorrect source path for call $callIndex\");\n                $this->assertEquals($expectedCalls[$callIndex][1], $target, \"Incorrect target path for call $callIndex\");\n                $callIndex++;\n            });\n    }\n\n    private function assertCommandOutput(): void\n    {\n        $output = $this->commandTester->getDisplay();\n        $this->assertStringContainsString('elFinder Installer', $output);\n        $this->assertStringContainsString('elFinder assets successfully installed', $output);\n    }\n}\n"
  },
  {
    "path": "tests/Configuration/ElFinderConfigurationReaderTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\Configuration;\n\nuse FM\\ElfinderBundle\\Configuration\\ElFinderConfigurationReader;\nuse Symfony\\Component\\DependencyInjection\\ContainerInterface;\n\nclass ElFinderConfigurationReaderTest extends \\PHPUnit\\Framework\\TestCase\n{\n    /**\n     * @var ElFinderConfigurationReader\n     */\n    protected $reader;\n\n    /**\n     * @var \\elFinderVolumeLocalFileSystem\n     */\n    protected $elFinderVolumeMock;\n\n    private function getConfigurationReader($attributesObject)\n    {\n        /* @var \\Symfony\\Component\\DependencyInjection\\ContainerInterface|\\PHPUnit_Framework_MockObject_MockObject */\n        $containerMock = $this->createMock('Symfony\\Component\\DependencyInjection\\ContainerInterface');\n\n        $this->elFinderVolumeMock = $this->createMock('\\elFinderVolumeLocalFileSystem');\n\n        $containerMock\n            ->expects($this->any())\n            ->method('has')\n            ->willReturn(true);\n\n        $containerMock\n            ->expects($this->any())\n            ->method('get')\n            ->willReturnMap([\n                [\n                    'elfinder.driver.local',\n                    ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE,\n                    $this->elFinderVolumeMock,\n                ],\n            ]);\n\n        /** @var \\Symfony\\Component\\HttpFoundation\\RequestStack $requestStack|\\PHPUnit_Framework_MockObject_MockObject */\n        $requestStack = $this->createMock('Symfony\\Component\\HttpFoundation\\RequestStack');\n        /** @var \\Symfony\\Component\\HttpFoundation\\Request $requestObject */\n        $requestObject = $this->createPartialMock('Symfony\\Component\\HttpFoundation\\Request', ['getScheme', 'getHttpHost', 'getBaseUrl']);\n\n        $requestObject\n            ->expects($this->any())\n            ->method('getScheme')\n            ->willReturn('http');\n        $requestObject\n            ->expects($this->any())\n            ->method('getHttpHost')\n            ->willReturn('test.com');\n        $requestObject\n            ->expects($this->any())\n            ->method('getBaseUrl')\n            ->willReturn('/unit-test');\n\n        $requestObject->attributes = $attributesObject;\n\n        $requestStack\n            ->expects($this->any())\n            ->method('getCurrentRequest')\n            ->willReturn($requestObject);\n\n        $params = [\n            'instances' => [\n                'default'  => [\n                    'cors_support' => '',\n                    'connector'    => [\n                        'debug' => '', 'binds' => '', 'plugins' => '',\n                        'roots' => [\n                            'uploads' => [\n                                'flysystem'         => ['enabled' => false],\n                                'volume_id'         => 0,\n                                'security_voter'    => '',\n                                'show_hidden'       => false,\n                                'path'              => '',\n                                'driver'            => 'LocalFileSystem',\n                                'glide_url'         => '',\n                                'glide_key'         => '',\n                                'plugins'           => '',\n                                'start_path'        => '',\n                                'encoding'          => '',\n                                'alias'             => '',\n                                'mime_detect'       => '',\n                                'mimefile'          => '',\n                                'img_lib'           => '',\n                                'tmb_path'          => '',\n                                'tmb_path_mode'     => '',\n                                'tmb_url'           => '',\n                                'tmb_size'          => '',\n                                'tmb_crop'          => '',\n                                'tmb_bg_color'      => '',\n                                'copy_overwrite'    => '',\n                                'copy_join'         => '',\n                                'copy_from'         => '',\n                                'copy_to'           => '',\n                                'upload_overwrite'  => '',\n                                'upload_allow'      => '',\n                                'upload_deny'       => '',\n                                'upload_max_size'   => '',\n                                'upload_max_conn'   => 3,\n                                'defaults'          => '',\n                                'attributes'        => '',\n                                'accepted_name'     => '',\n                                'disabled_commands' => '',\n                                'tree_deep'         => '',\n                                'check_subfolders'  => '',\n                                'separator'         => '',\n                                'time_format'       => '',\n                                'archive_mimes'     => '',\n                                'archivers'         => '',\n                                'fileMode'          => '',\n                                'quarantine'        => null,\n                                'trash_hash'        => null,\n                            ],\n                        ],\n                    ],\n                ],\n                'with_path_with_url'  => [\n                    'cors_support' => true,\n                    'connector'    => [\n                        'debug' => '', 'binds' => '', 'plugins' => '',\n                        'roots' => [\n                            'uploads' => [\n                                'flysystem'         => ['enabled' => false],\n                                'volume_id'         => 1,\n                                'security_voter'    => '',\n                                'show_hidden'       => false,\n                                'path'              => '/home',\n                                'driver'            => 'LocalFileSystem',\n                                'url'               => 'home-url',\n                                'glide_url'         => '',\n                                'glide_key'         => '',\n                                'plugins'           => '',\n                                'driver_options'    => '',\n                                'start_path'        => '',\n                                'encoding'          => '',\n                                'alias'             => '',\n                                'mime_detect'       => '',\n                                'mimefile'          => '',\n                                'img_lib'           => '',\n                                'tmb_path'          => '',\n                                'tmb_path_mode'     => '',\n                                'tmb_url'           => '',\n                                'tmb_size'          => '',\n                                'tmb_crop'          => '',\n                                'tmb_bg_color'      => '',\n                                'copy_overwrite'    => '',\n                                'copy_join'         => '',\n                                'copy_from'         => '',\n                                'copy_to'           => '',\n                                'upload_overwrite'  => '',\n                                'upload_allow'      => '',\n                                'upload_deny'       => '',\n                                'upload_max_size'   => '',\n                                'upload_max_conn'   => 3,\n                                'defaults'          => '',\n                                'attributes'        => '',\n                                'accepted_name'     => '',\n                                'disabled_commands' => '',\n                                'tree_deep'         => '',\n                                'check_subfolders'  => '',\n                                'separator'         => '',\n                                'time_format'       => '',\n                                'archive_mimes'     => '',\n                                'archivers'         => '',\n                                'fileMode'          => '',\n                                'quarantine'        => null,\n                                'trash_hash'        => null,\n                            ],\n                        ],\n                    ],\n                ],\n                'without_path_with_url'  => [\n                    'cors_support' => true,\n                    'connector'    => [\n                        'debug' => '', 'binds' => '', 'plugins' => '',\n                        'roots' => [\n                            'uploads' => [\n                                'flysystem'         => ['enabled' => false],\n                                'volume_id'         => 2,\n                                'security_voter'    => '',\n                                'show_hidden'       => false,\n                                'path'              => '',\n                                'driver'            => 'LocalFileSystem',\n                                'url'               => 'home-url-without-path',\n                                'glide_url'         => '',\n                                'glide_key'         => '',\n                                'plugins'           => '',\n                                'driver_options'    => '',\n                                'start_path'        => '',\n                                'encoding'          => '',\n                                'alias'             => '',\n                                'mime_detect'       => '',\n                                'mimefile'          => '',\n                                'img_lib'           => '',\n                                'tmb_path'          => '',\n                                'tmb_path_mode'     => '',\n                                'tmb_url'           => '',\n                                'tmb_size'          => '',\n                                'tmb_crop'          => '',\n                                'tmb_bg_color'      => '',\n                                'copy_overwrite'    => '',\n                                'copy_join'         => '',\n                                'copy_from'         => '',\n                                'copy_to'           => '',\n                                'upload_overwrite'  => '',\n                                'upload_allow'      => '',\n                                'upload_deny'       => '',\n                                'upload_max_size'   => '',\n                                'upload_max_conn'   => 3,\n                                'defaults'          => '',\n                                'attributes'        => '',\n                                'accepted_name'     => '',\n                                'disabled_commands' => '',\n                                'tree_deep'         => '',\n                                'check_subfolders'  => '',\n                                'separator'         => '',\n                                'time_format'       => '',\n                                'archive_mimes'     => '',\n                                'archivers'         => '',\n                                'fileMode'          => '',\n                                'quarantine'        => null,\n                                'trash_hash'        => null,\n                            ],\n                        ],\n                    ],\n                ],\n                'without_path_with_url_absolute_homeFolder'  => [\n                    'cors_support' => true,\n                    'connector'    => [\n                        'debug' => '', 'binds' => '', 'plugins' => '',\n                        'roots' => [\n                            'uploads' => [\n                                'flysystem'         => ['enabled' => false],\n                                'volume_id'         => 2,\n                                'security_voter'    => '',\n                                'show_hidden'       => false,\n                                'path'              => '',\n                                'driver'            => 'LocalFileSystem',\n                                'url'               => 'https://test.com/{homeFolder}',\n                                'glide_url'         => '',\n                                'glide_key'         => '',\n                                'plugins'           => '',\n                                'driver_options'    => '',\n                                'start_path'        => '',\n                                'encoding'          => '',\n                                'alias'             => '',\n                                'mime_detect'       => '',\n                                'mimefile'          => '',\n                                'img_lib'           => '',\n                                'tmb_path'          => '',\n                                'tmb_path_mode'     => '',\n                                'tmb_url'           => '',\n                                'tmb_size'          => '',\n                                'tmb_crop'          => '',\n                                'tmb_bg_color'      => '',\n                                'copy_overwrite'    => '',\n                                'copy_join'         => '',\n                                'copy_from'         => '',\n                                'copy_to'           => '',\n                                'upload_overwrite'  => '',\n                                'upload_allow'      => '',\n                                'upload_deny'       => '',\n                                'upload_max_size'   => '',\n                                'upload_max_conn'   => 3,\n                                'defaults'          => '',\n                                'attributes'        => '',\n                                'accepted_name'     => '',\n                                'disabled_commands' => '',\n                                'tree_deep'         => '',\n                                'check_subfolders'  => '',\n                                'separator'         => '',\n                                'time_format'       => '',\n                                'archive_mimes'     => '',\n                                'archivers'         => '',\n                                'fileMode'          => '',\n                                'quarantine'        => null,\n                                'trash_hash'        => null,\n                            ],\n                        ],\n                    ],\n                ],\n            ],\n        ];\n\n        return new ElFinderConfigurationReader($params, $requestStack, $containerMock);\n    }\n\n    private function getDefaultAttributesObject()\n    {\n        /** @var \\Symfony\\Component\\HttpFoundation\\ParameterBag $attributesObject */\n        $attributesObject = $this->createMock('\\Symfony\\Component\\HttpFoundation\\ParameterBag');\n        $attributesObject\n            ->expects($this->any())\n            ->method('get')\n            ->willReturn('');\n\n        return $attributesObject;\n    }\n\n    private function getHomeFolderAwareAttributesObject()\n    {\n        /** @var \\Symfony\\Component\\HttpFoundation\\ParameterBag $attributesObject */\n        $attributesObject = $this->createMock('\\Symfony\\Component\\HttpFoundation\\ParameterBag');\n        $attributesObject\n            ->expects($this->any())\n            ->method('get')\n            ->with($this->equalTo('homeFolder'))\n            ->willReturn('bob');\n\n        return $attributesObject;\n    }\n\n    public function testConfiguration(): void\n    {\n        $reader        = $this->getConfigurationReader($this->getDefaultAttributesObject());\n        $configuration = $reader->getConfiguration('default');\n        $this->assertArrayHasKey('roots', $configuration);\n        $this->assertArrayHasKey('corsSupport', $configuration);\n        $this->assertSame('LocalFileSystem', $configuration['roots'][0]['driver']);\n    }\n\n    public function testSubClassOfHelper(): void\n    {\n        $rc = new \\ReflectionClass('FM\\ElfinderBundle\\Configuration\\ElFinderConfigurationReader');\n\n        $this->assertTrue($rc->isSubclassOf('FM\\ElfinderBundle\\Configuration\\ElFinderConfigurationProviderInterface'));\n    }\n\n    public function testAccessHidden(): void\n    {\n        $reader     = $this->getConfigurationReader($this->getDefaultAttributesObject());\n        $hiddenPath = '.hiddenPath';\n        $this->assertFalse($reader->access('read', $hiddenPath, 'dummy', 'dummy'));\n        $this->assertFalse($reader->access('write', $hiddenPath, 'dummy', 'dummy'));\n    }\n\n    public function testAccessVisible()\n    {\n        $reader      = $this->getConfigurationReader($this->getDefaultAttributesObject());\n        $visiblePath = 'hiddenPath';\n        $this->assertNull($reader->access('read', $visiblePath, 'dummy', 'dummy'));\n        $this->assertNull($reader->access('write', $visiblePath, 'dummy', 'dummy'));\n    }\n\n    public function testPathAndUrlAndHomeFolder(): void\n    {\n        // with path and without homeFolder\n        $reader        = $this->getConfigurationReader($this->getDefaultAttributesObject());\n        $configuration = $reader->getConfiguration('with_path_with_url');\n        $this->assertEquals('/home', $configuration['roots'][0]['path']);\n        $this->assertEquals('http://test.com/unit-test/home-url', $configuration['roots'][0]['URL']);\n\n        // with path and with homeFolder\n        $reader        = $this->getConfigurationReader($this->getHomeFolderAwareAttributesObject());\n        $configuration = $reader->getConfiguration('with_path_with_url');\n        $this->assertEquals('/home/bob', $configuration['roots'][0]['path']);\n        $this->assertEquals('http://test.com/unit-test/home-url/bob', $configuration['roots'][0]['URL']);\n\n        // without path and without homeFolder\n        $reader        = $this->getConfigurationReader($this->getDefaultAttributesObject());\n        $configuration = $reader->getConfiguration('without_path_with_url');\n        $this->assertEquals('', $configuration['roots'][0]['path']);\n        $this->assertEquals('http://test.com/unit-test/home-url-without-path', $configuration['roots'][0]['URL']);\n\n        // without path and with homeFolder\n        $reader        = $this->getConfigurationReader($this->getHomeFolderAwareAttributesObject());\n        $configuration = $reader->getConfiguration('without_path_with_url');\n        $this->assertEquals('/bob', $configuration['roots'][0]['path']);\n        $this->assertEquals('http://test.com/unit-test/home-url-without-path/bob', $configuration['roots'][0]['URL']);\n\n        // without path and with url absolute and homeFolder\n        $reader        = $this->getConfigurationReader($this->getHomeFolderAwareAttributesObject());\n        $configuration = $reader->getConfiguration('without_path_with_url_absolute_homeFolder');\n        $this->assertEquals('/bob', $configuration['roots'][0]['path']);\n        $this->assertEquals('https://test.com/bob', $configuration['roots'][0]['URL']);\n    }\n\n    public function testAccessTmbURLOption(): void\n    {\n        $reader        = $this->getConfigurationReader($this->getDefaultAttributesObject());\n        $configuration = $reader->getConfiguration('default');\n        $this->assertArrayHasKey('tmbURL', $configuration['roots'][0]);\n    }\n}\n"
  },
  {
    "path": "tests/DependencyInjection/Compiler/TwigFormPassTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\DependencyInjection\\Compiler;\n\nuse FM\\ElfinderBundle\\DependencyInjection\\Compiler\\TwigFormPass;\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\n\nclass TwigFormPassTest extends \\PHPUnit\\Framework\\TestCase\n{\n    public function testProcess()\n    {\n        $container = new ContainerBuilder();\n        $pass      = new TwigFormPass();\n        $pass->process($container);\n        $this->assertFalse($container->hasParameter('twig.form.resources'));\n        $container = new ContainerBuilder();\n        $container->setParameter('twig.form.resources', []);\n        $pass->process($container);\n        $this->assertEquals([\n            '@FMElfinder/Form/elfinder_widget.html.twig',\n        ], $container->getParameter('twig.form.resources'));\n    }\n}\n"
  },
  {
    "path": "tests/DependencyInjection/ConfigurationLoadTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\DependencyInjection;\n\nuse FM\\ElfinderBundle\\DependencyInjection\\FMElfinderExtension;\nuse FM\\ElfinderBundle\\DependencyInjection\\Configuration;\nuse Matthias\\SymfonyDependencyInjectionTest\\PhpUnit\\AbstractExtensionConfigurationTestCase;\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse Symfony\\Component\\Config\\Definition\\ConfigurationInterface;\nuse Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface;\n\nclass ConfigurationLoadTest extends AbstractExtensionConfigurationTestCase\n{\n    protected function getContainerExtension(): ExtensionInterface\n    {\n        return new FMElfinderExtension();\n    }\n\n    protected function getConfiguration(): ConfigurationInterface\n    {\n        return new Configuration();\n    }\n\n    #[DataProvider('getSupportsAllConfigFormatsData')]\n    public function testSupportsAllConfigFormats($path): void\n    {\n        $expectedConfiguration = [\n            'configuration_provider' => 'app.configurator.custom',\n            'assets_path'            => 'assets',\n            'loader'                 => 'fm_elfinder.loader.default',\n            'instances'              => [\n                'default' => [\n                    'locale'             => 'en',\n                    'editor'             => 'tinymce',\n                    'theme'              => 'smoothness',\n                    'editor_template'    => 'Elfinder/editor.html.twig',\n                    'fullscreen'         => false,\n                    'where_is_multi'     => [],\n                    'multi_home_folder'  => false,\n                    'folder_separator'   => '',\n                    'cors_support'       => false,\n                    'tinymce_popup_path' => '/pop-up',\n                    'relative_path'      => false,\n                    'path_prefix'        => '/',\n                    'visible_mime_types' => [],\n                    'connector'          => [\n                        'debug'   => true,\n                        'binds'   => [],\n                        'plugins' => [],\n                        'roots'   => [\n                            'uploads' => [\n                                'driver'            => 'LocalFileSystem',\n                                'volume_id'         => 0,\n                                'security_voter'    => '',\n                                'phash'             => '',\n                                'trash_hash'        => 'trash_hash',\n                                'i18n_folder_name'  => false,\n                                'locale'            => '',\n                                'disabled_commands' => [],\n                                'plugins'           => [],\n                                'driver_options'    => [],\n                                'path'              => 'uploads',\n                                'show_hidden'       => true,\n                                'flysystem'         => [\n                                    'filesystem'      => '',\n                                    'enabled'         => false,\n                                    'type'            => '',\n                                    'adapter_service' => '',\n                                ],\n                                'start_path'       => '',\n                                'encoding'         => 'UTF-8',\n                                'url'              => '',\n                                'mime_detect'      => 'auto',\n                                'mimefile'         => '',\n                                'img_lib'          => 'auto',\n                                'tmb_path'         => '.tmb',\n                                'tmb_url'          => '',\n                                'tmb_size'         => 48,\n                                'tmb_crop'         => true,\n                                'tmb_bg_color'     => '#ffffff',\n                                'tmb_path_mode'    => 511,\n                                'copy_overwrite'   => true,\n                                'copy_join'        => true,\n                                'copy_from'        => true,\n                                'copy_to'          => true,\n                                'upload_overwrite' => true,\n                                'fileMode'         => 0644,\n                                'attributes'       => [\n                                    'some_pattern' => [\n                                        'pattern' => '/^some_pattern$/',\n                                        'read'    => true,\n                                        'write'   => true,\n                                        'locked'  => false,\n                                        'hidden'  => false,\n                                    ],\n                                ],\n                                'accepted_name'    => '/^\\w[\\w\\s\\.\\%\\-]*$/u',\n                                'check_subfolders' => 1,\n                                'separator'        => DIRECTORY_SEPARATOR,\n                                'date_format'      => 'j M Y H:i',\n                                'time_format'      => 'H:i',\n                                'archive_mimes'    => [],\n                                'archivers'        => [\n                                  'enabled' => false,\n                                  'create'  => [],\n                                  'extract' => [],\n                                ],\n                                'glide_url'         => '',\n                                'glide_key'         => '',\n                                'alias'             => 'foo',\n                                'tree_deep'         => 1,\n                                'upload_allow'      => ['image/png', 'image/jpg', 'image/jpeg'],\n                                'upload_order'      => ['deny', 'allow'],\n                                'defaults'          => ['read' => true, 'write' => true],\n                                'upload_deny'       => ['all'],\n                                'upload_max_size'   => 0,\n                                'upload_max_conn'   => 3,\n                                'dropbox2_settings' => [\n                                    'aliasFormat'     => '%s@Dropbox',\n                                    'path'            => '/',\n                                    'separator'       => '/',\n                                    'acceptedName'    => '%s@Dropbox',\n                                    'rootCssClass'    => 'elfinder-navbar-root-dropbox',\n                                    'getThumbSize'    => 'medium',\n                                    'app_key'         => 'some_consumer',\n                                    'app_secret'      => 'con$umer',\n                                    'enabled'         => true,\n                                ],\n                                'box_settings' => [\n                                    'client_id'      => 'some_consumer',\n                                    'client_secret'  => 'con$umer',\n                                    'accessToken'    => 'token',\n                                    'root'           => 'Box.com',\n                                    'path'           => '/',\n                                    'separator'      => '/',\n                                    'tmbPath'        => '',\n                                    'tmbURL'         => '',\n                                    'tmpPath'        => '',\n                                    'acceptedName'   => '#^[^/\\?*:|\"<>]*[^./\\?*:|\"<>]$#',\n                                    'rootCssClass'   => 'elfinder-navbar-root-box',\n                                    'enabled'        => true,\n                                ],\n                                'onedrive_settings' => [\n                                    'client_id'         => 'some_consumer',\n                                    'client_secret'     => 'con$umer',\n                                    'accessToken'       => 'token',\n                                    'root'              => 'OneDrive.com',\n                                    'OneDriveApiClient' => '',\n                                    'path'              => '/',\n                                    'separator'         => '/',\n                                    'tmbPath'           => '',\n                                    'tmbURL'            => '',\n                                    'tmpPath'           => '',\n                                    'acceptedName'      => '#^[^/\\?*:|\"<>]*[^./\\?*:|\"<>]$#',\n                                    'rootCssClass'      => 'elfinder-navbar-root-onedrive',\n                                    'useApiThumbnail'   => true,\n                                    'enabled'           => true,\n                                ],\n                                'ftp_settings' => [\n                                    'host'    => '127.0.0.1',\n                                    'user'    => 'root',\n                                    'enabled' => true,\n                                ],\n                                'mysql_settings' => [\n                                    'enabled'        => true,\n                                    'host'           => 'localhost',\n                                    'files_table'    => 'elfinder_file',\n                                    'port'           => null,\n                                    'socket'         => null,\n                                    'tmbPath'        => '',\n                                    'tmpPath'        => '',\n                                    'rootCssClass'   => 'elfinder-navbar-root-sql',\n                                    'noSessionCache' => 'hasdirs',\n                                ],\n                                'autoload'   => false,\n                                'quarantine' => null,\n                            ],\n                        ],\n                    ],\n                ],\n            ],\n        ];\n\n        $this->assertProcessedConfigurationEquals($expectedConfiguration, [__DIR__.'/../Fixtures/'.$path]);\n    }\n\n    public static function getSupportsAllConfigFormatsData(): array\n    {\n        return [\n            'yml' => ['config/config.yml'],\n            'php' => ['config/config.php'],            \n        ];\n    }\n}\n"
  },
  {
    "path": "tests/DependencyInjection/FMElfinderExtensionTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\DependencyInjection;\n\nuse FM\\ElfinderBundle\\DependencyInjection\\FMElfinderExtension;\nuse Matthias\\SymfonyDependencyInjectionTest\\PhpUnit\\AbstractExtensionTestCase;\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\nuse Symfony\\Component\\Yaml\\Parser;\n\nclass FMElfinderExtensionTest extends AbstractExtensionTestCase\n{\n    protected function getContainerExtensions(): array\n    {\n        return [\n            new FMElfinderExtension(),\n        ];\n    }\n\n    public function testServices()\n    {\n        $this->load();\n        $this->assertContainerBuilderHasAlias('fm_elfinder.configurator');\n        $this->assertContainerBuilderHasService('fm_elfinder.loader');\n        $this->assertContainerBuilderHasService('fm_elfinder.configurator.default');\n        $this->assertContainerBuilderHasService('twig.extension.fm_elfinder_init');\n    }\n\n    public function testMinimumConfiguration()\n    {\n        $this->container = new ContainerBuilder();\n        $loader          = new FMElfinderExtension();\n        $loader->load([$this->getMinimalConfiguration()], $this->container);\n        $this->assertTrue($this->container instanceof ContainerBuilder);\n    }\n\n    protected function getMinimalConfiguration(): array\n    {\n        $yaml = <<<'EOF'\ninstances:\n    default:\n      locale: '%locale%'\n      editor: simple # other choices are tinymce or simple\n      fullscreen: true\n      connector:\n          debug: true # defaults to false\n          roots:       # at least one root must be defined\n              uploads:\n                  driver: LocalFileSystem\n                  path: uploads\n                  upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\n                  upload_deny: ['all']\n                  upload_max_size: 2M\nEOF;\n        $parser = new Parser();\n\n        return $parser->parse($yaml);\n    }\n}\n"
  },
  {
    "path": "tests/Event/ElFinderPostExecutionEventTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\Event;\n\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse FM\\ElfinderBundle\\Event\\ElFinderPostExecutionEvent;\n\nclass ElFinderPostExecutionEventTest extends \\PHPUnit\\Framework\\TestCase\n{\n    public function testHasErrors()\n    {\n        $request    = new Request();\n        $httpKernel = $this->createMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface');\n        $event      = new ElFinderPostExecutionEvent($request, $httpKernel, 'testInstance', 'testHomeFolder', []);\n        $this->assertEquals(false, $event->hasErrors());\n\n        $event = new ElFinderPostExecutionEvent($request, $httpKernel, 'testInstance', 'testHomeFolder', ['error' => true]);\n        $this->assertEquals(true, $event->hasErrors());\n    }\n}\n"
  },
  {
    "path": "tests/Event/ElFinderPreExecutionEventTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\Event;\n\nuse Symfony\\Component\\HttpFoundation\\Request;\nuse FM\\ElfinderBundle\\Event\\ElFinderPreExecutionEvent;\n\nclass ElFinderPreExecutionEventTest extends \\PHPUnit\\Framework\\TestCase\n{\n    public function testGetCommand()\n    {\n        $command    = 'rm';\n        $request    = new Request(['cmd' => $command]);\n        $httpKernel = $this->createMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface');\n        $event      = new ElFinderPreExecutionEvent($request, $httpKernel, 'testInstance', 'testHomeFolder');\n        $this->assertEquals($command, $event->getCommand());\n    }\n\n    public function testSubRequest()\n    {\n        $request    = new Request(['cmd' => 'info']);\n        $httpKernel = $this->createMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface');\n        $httpKernel\n            ->expects($this->once())\n            ->method('handle');\n        $event = new ElFinderPreExecutionEvent($request, $httpKernel, 'testInstance', 'testHomeFolder');\n\n        $jsonResponse = $event->subRequest([\n            'instance'   => $event->getInstance(),\n            'homeFolder' => $event->getHomeFolder(),\n        ], $request->query->all());\n    }\n}\n"
  },
  {
    "path": "tests/FMElfinderBundleTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests;\n\nuse FM\\ElfinderBundle\\FMElfinderBundle;\nuse Symfony\\Component\\DependencyInjection\\ContainerBuilder;\nuse Symfony\\Component\\HttpKernel\\Bundle\\Bundle;\n\nclass FMElfinderBundleTest extends \\PHPUnit\\Framework\\TestCase\n{\n    public function testBundle(): void\n    {\n        $bundle = new FMElfinderBundle();\n        $this->assertInstanceOf(Bundle::class, $bundle);\n    }\n\n}\n"
  },
  {
    "path": "tests/Fixtures/config/config.php",
    "content": "<?php\n\n$container->loadFromExtension('fm_elfinder', [\n    'configuration_provider' => 'app.configurator.custom',\n    'instances'              => [\n        'default' => [\n            'locale'             => 'en',\n            'cors_support'       => false,\n            'editor'             => 'tinymce',\n            'editor_template'    => 'Elfinder/editor.html.twig',\n            'fullscreen'         => false,\n            'tinymce_popup_path' => '/pop-up',\n            'relative_path'      => false,\n            'connector'          => [\n                'debug' => true,\n                'roots' => [\n                    'uploads' => [\n                        'driver'            => 'LocalFileSystem',\n                        'path'              => 'uploads',\n                        'show_hidden'       => true,\n                        'trash_hash'        => 'trash_hash',\n                        'alias'             => 'foo',\n                        'check_subfolders'  => 1,\n                        'tree_deep'         => 1,\n                        'upload_allow'      => ['image/png', 'image/jpg', 'image/jpeg'],\n                        'upload_deny'       => ['all'],\n                        'upload_max_size'   => 0,\n                        'upload_max_conn'   => 3,\n                        'dropbox2_settings' => [\n                            'app_key'         => 'some_consumer',\n                            'app_secret'      => 'con$umer',\n                        ],\n                        'box_settings' => [\n                            'client_id'       => 'some_consumer',\n                            'client_secret'   => 'con$umer',\n                            'accessToken'     => 'token',\n                        ],\n                        'onedrive_settings' => [\n                            'client_id'       => 'some_consumer',\n                            'client_secret'   => 'con$umer',\n                            'accessToken'     => 'token',\n                        ],\n                        'ftp_settings' => [\n                            'host' => '127.0.0.1',\n                            'user' => 'root',\n                        ],\n                        'mysql_settings' => [\n                            'host' => 'localhost',\n                        ],\n                        'attributes' => [\n                            'some_pattern' => [\n                                'pattern' => '/^some_pattern$/',\n                                'read'    => true,\n                                'write'   => true,\n                                'locked'  => false,\n                                'hidden'  => false,\n                            ],\n                        ],\n                    ],\n                ],\n            ],\n        ],\n    ],\n]);\n"
  },
  {
    "path": "tests/Fixtures/config/config.yml",
    "content": "fm_elfinder:\r\n    configuration_provider: app.configurator.custom\r\n    instances:\r\n        default:\r\n            locale: en\r\n            editor: tinymce\r\n            editor_template: Elfinder/editor.html.twig\r\n            fullscreen: false\r\n            tinymce_popup_path: /pop-up\r\n            relative_path: false\r\n            connector:\r\n                debug: true\r\n                roots:\r\n                    uploads:\r\n                        driver: LocalFileSystem\r\n                        path: uploads\r\n                        show_hidden: true\r\n                        trash_hash: trash_hash\r\n                        check_subfolders: 1\r\n                        alias: foo\r\n                        tree_deep: 1\r\n                        upload_allow: ['image/png', 'image/jpg', 'image/jpeg']\r\n                        dropbox2_settings:\r\n                            app_key: some_consumer\r\n                            app_secret: con$umer\r\n                        onedrive_settings:\r\n                            client_id: some_consumer\r\n                            client_secret: con$umer\r\n                            accessToken: token\r\n                        box_settings:\r\n                            client_id: some_consumer\r\n                            client_secret: con$umer\r\n                            accessToken: token\r\n                        ftp_settings:\r\n                            host: 127.0.0.1\r\n                            user: root\r\n                        mysql_settings:\r\n                            host: localhost\r\n                        attributes:\r\n                            some_pattern:\r\n                                pattern: '/^some_pattern$/'\r\n                                read: true\r\n                                write: true\r\n                                locked: false\r\n                                hidden: false\r\n"
  },
  {
    "path": "tests/Form/Type/ElFinderTypeTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\Form\\Type;\n\nuse FM\\ElfinderBundle\\Form\\Type\\ElFinderType;\nuse Symfony\\Component\\OptionsResolver\\OptionsResolver;\nuse Symfony\\Component\\Form\\FormView;\n\nclass ElFinderTypeTest extends \\PHPUnit\\Framework\\TestCase\n{\n    public function testGetName()\n    {\n        $type = new ElFinderType();\n        $this->assertEquals('elfinder', $type->getName());\n    }\n\n    public function testConfigureOptions()\n    {\n        $resolver = new OptionsResolver();\n        $type     = new ElFinderType();\n        $type->configureOptions($resolver);\n        $this->assertTrue($resolver->isDefined('enable'));\n        $this->assertTrue($resolver->isDefined('instance'));\n        $this->assertTrue($resolver->isDefined('homeFolder'));\n    }\n\n    public function testBuildView()\n    {\n        $options = [\n            'instance'   => 'default1',\n            'enable'     => true,\n            'homeFolder' => '/home',\n        ];\n        $view = new FormView();\n        $type = new ElFinderType();\n        $form = $this->createMock('Symfony\\Component\\Form\\Test\\FormInterface');\n        $type->buildView($view, $form, $options);\n        foreach ($options as $name => $value) {\n            $this->assertArrayHasKey($name, $view->vars);\n            $this->assertEquals($value, $view->vars[$name]);\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Functional/AppKernel.php",
    "content": "<?php\n\nuse Symfony\\Component\\HttpKernel\\Kernel;\nuse Symfony\\Component\\Config\\Loader\\LoaderInterface;\n\nclass AppKernel extends Kernel\n{\n    public function registerBundles()\n    {\n        $bundles = [\n            new Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle(),\n            new Symfony\\Bundle\\TwigBundle\\TwigBundle(),\n            new FM\\ElfinderBundle\\FMElfinderBundle(),\n        ];\n\n        return $bundles;\n    }\n\n    public function registerContainerConfiguration(LoaderInterface $loader)\n    {\n        $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');\n    }\n}\n"
  },
  {
    "path": "tests/Functional/config/config.yml",
    "content": "framework:\n    secret:          \"thisismysecret\"\n    router:\n        resource: \"%kernel.root_dir%/config/routing.yaml\"\n        strict_requirements: ~\n    form:            ~\n    csrf_protection: ~\n    validation:      { enable_annotations: true }\n    templating:\n        engines: ['twig']\n    default_locale:  \"en\"\n    trusted_hosts:   ~\n    trusted_proxies: ~\n    session:\n        # handler_id set to null will use default session handler from php.ini\n        handler_id:  ~\n    fragments:       ~\n    http_method_override: true\n\n\n# ElFinder file manager\nfm_elfinder:\n    instances:\n        default:\n            locale: en # defaults to current request locale\n            editor: custom # other options are tinymce, tinymce4, form, custom and simple, \n            cors_support: true # full symfony life cycle\n            fullscreen: true # defaults true, applies to simple and ckeditor editors\n            connector:\n                debug: false # defaults to false\n                roots:       # at least one root must be defined\n                    uploads:\n                        show_hidden: false # defaults to false\n                        driver: LocalFileSystem\n                        volume_id: 1\n                        path: uploads\n\n\n"
  },
  {
    "path": "tests/Functional/config/config_test.yml",
    "content": "imports:\n    - { resource: config.yml }\n\nframework:\n    test: ~\n    session:\n        storage_id: session.storage.mock_file\n    profiler:\n        collect: false\n"
  },
  {
    "path": "tests/Functional/config/routing.yml",
    "content": "# ElFinder file manager\nelfinder:\n    resource: \"@FMElfinderBundle/Resources/config/routing.yaml\"\n\n"
  },
  {
    "path": "tests/Loader/ElFinderLoaderTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\Loader;\n\nuse FM\\ElfinderBundle\\Configuration\\ElFinderConfigurationProviderInterface;\nuse FM\\ElfinderBundle\\Loader\\ElFinderLoader;\n\nclass ElFinderLoaderTest extends \\PHPUnit\\Framework\\TestCase\n{\n    protected $loader;\n\n    protected $configuratorMock;\n\n    public function setUp(): void\n    {\n        $this->configuratorMock = $this->createMock(ElFinderConfigurationProviderInterface::class);\n        $this->configuratorMock->expects($this->any())\n                               ->method('getConfiguration')\n                               ->willReturn(['parameters' => []]);\n        $this->loader = new ElFinderLoader($this->configuratorMock);\n        $this->loader->setInstance('minimal');\n    }\n\n    public function testConfigure()\n    {\n        $this->loader->configure();\n        $this->assertEquals(['parameters' => []], $this->configuratorMock->getConfiguration('minimal'));\n    }\n}\n"
  },
  {
    "path": "tests/Twig/Extension/FMElfinderExtensionTest.php",
    "content": "<?php\n\nnamespace FM\\ElfinderBundle\\Tests\\Twig\\Extension;\n\nuse FM\\ElfinderBundle\\Twig\\Extension\\FMElfinderExtension;\nuse Symfony\\Bridge\\Twig\\Extension\\RoutingExtension;\nuse Symfony\\Component\\Config\\FileLocator;\nuse Symfony\\Component\\Routing\\Generator\\UrlGenerator;\nuse Symfony\\Component\\Routing\\Loader\\YamlFileLoader;\nuse Symfony\\Component\\Routing\\RequestContext;\nuse Symfony\\Component\\Routing\\RouteCollection;\nuse Twig\\Environment;\nuse Twig\\Loader\\FilesystemLoader;\nuse Twig\\Template;\n\nclass FMElfinderExtensionTest extends \\PHPUnit\\Framework\\TestCase\n{\n    /** @var \\Symfony\\Component\\DependencyInjection\\ContainerInterface|\\PHPUnit_Framework_MockObject_MockObject */\n    protected $containerMock;\n\n    /** @var \\Symfony\\Component\\Routing\\RouterInterface|\\PHPUnit_Framework_MockObject_MockObject */\n    protected $routerMock;\n\n    /** @var \\FM\\ElfinderBundle\\Twig\\Extension\\FMElFinderExtension */\n    protected $extension;\n\n    /** @var Environment */\n    protected $twig;\n\n    /** @var Template */\n    protected $template;\n\n    protected function setUp(): void\n    {\n        $this->twig      = new Environment(new FilesystemLoader([__DIR__.'/../../../src/Resources/views/Elfinder/helper']));\n        $this->extension = new FMElfinderExtension($this->twig);\n        $this->twig->addExtension($this->extension);\n        $loader     = new YamlFileLoader(new FileLocator(__DIR__.'/../../../src/Resources/config'));\n        $routes     = new RouteCollection();\n        $collection = $loader->load('routing.yaml');\n        $routes->addCollection($collection);\n        $this->twig->addExtension(new RoutingExtension(new UrlGenerator($routes, new RequestContext())));\n    }\n\n    public function testRenderTinyMCE3()\n    {\n        $testData = $this->twig->render('_tinymce.html.twig', ['instance' => 'minimal']);\n\n        $expected = <<<'EOF'\n<script type=\"text/javascript\">\n    //<![CDATA[\n    function elFinderBrowser (field_name, url, type, win) {\n        tinyMCE.activeEditor.windowManager.open({\n            file: \"http://localhost/elfinder/minimal\",\n            title: \"\",\n            width:,\n            height:,\n            resizable: 'yes',\n            inline: 'yes',    // This parameter only has an effect if you use the inlinepopups plugin!\n            popup_css: false, // Disable TinyMCE's default popup CSS\n            close_previous: 'no'\n        }, {\n            window: win,\n            input: field_name\n        });\n        return false;\n    }\n    //]]>\n</script>\nEOF;\n\n        $this->assertSame($this->normalizeOutput($expected), $this->normalizeOutput($testData));\n    }\n\n    public function testRenderTinyMCE4()\n    {\n        $testData = $this->twig->render('_tinymce4.html.twig', ['instance' => 'minimal']);\n\n        $expected = <<<'EOF'\n<script type=\"text/javascript\">\n    function elFinderBrowser (field_name, url, type, win) {\n        tinymce.activeEditor.windowManager.open({\n            file:\"http://localhost/elfinder/minimal\",\n            title:\"\",\n            width:,\n            height:,\n            resizable: 'yes'\n        }, {\n            setUrl: function (url) {\n                win.document.getElementById(field_name).value = url;\n            }\n        });\n        return false;\n    }\n</script>\nEOF;\n\n        $this->assertSame($this->normalizeOutput($expected), $this->normalizeOutput($testData));\n    }\n\n    public function testRenderSummernote()\n    {\n        $testData = $this->twig->render('_summernote.html.twig', ['instance' => 'minimal']);\n\n        $expected  = <<<'EOF'\n<script type=\"text/javascript\">\n    function elFinderBrowser(){\n            window.open(\n                \"http://localhost/elfinder/minimal\",\n                \"\",\n                \"width=, height=, resizable=yes, scrollbars=no, status=no, toolbar=no\"\n            );\n            return false;\n        }\n</script>\nEOF;\n        $this->assertSame($this->normalizeOutput($expected), $this->normalizeOutput($testData));\n    }\n\n    public function testName()\n    {\n        $this->assertEquals('fm_elfinder_init', $this->extension->getName());\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function tearDown(): void\n    {\n        unset($this->template);\n        unset($this->twig);\n    }\n\n    /**\n     * Normalizes the output by removing the heading whitespaces.\n     *\n     * @param string $output the output\n     *\n     * @return string the normalized output\n     */\n    protected function normalizeOutput($output)\n    {\n        return preg_replace(\"/\\r|\\n/\", '', str_replace(PHP_EOL, '', str_replace(' ', '', $output)));\n    }\n\n    public function testSubClassOfTwigExtension()\n    {\n        $rc = new \\ReflectionClass('FM\\ElfinderBundle\\Twig\\Extension\\FMElfinderExtension');\n\n        $this->assertTrue($rc->isSubclassOf('Twig\\Extension\\AbstractExtension'));\n    }\n\n    public function testSummernoteInstanceNotString()\n    {\n        $this->expectException(\\Twig\\Error\\LoaderError::class);\n        $this->extension->summernote(1);\n    }\n\n    public function testTinyMCEInstanceNotString()\n    {\n        $this->expectException(\\Twig\\Error\\LoaderError::class);\n        $this->extension->tinymce(1);\n    }\n\n    public function testTinyMCE4InstanceNotString()\n    {\n        $this->expectException(\\Twig\\Error\\LoaderError::class);\n        $this->extension->tinymce4(1);\n    }\n\n    public function testGetFunctions()\n    {\n        $twigFunctions = $this->extension->getFunctions();\n\n        foreach ($twigFunctions as $twigFunction) {\n            $this->assertInstanceOf('Twig\\TwigFunction', $twigFunction);\n        }\n    }\n}\n"
  },
  {
    "path": "tests/autoload.php",
    "content": "<?php\n\nrequire_once __DIR__.'/../vendor/autoload.php';\n"
  },
  {
    "path": "tests/bootstrap.php",
    "content": "<?php\n\nuse Doctrine\\Common\\Annotations\\AnnotationRegistry;\n\nif (!file_exists($file = __DIR__.'/../vendor/autoload.php')) {\n    throw new \\RuntimeException('Install the dependencies to run the test suite.');\n}\n\n$loader = require $file;\n\nAnnotationRegistry::registerLoader($loader->loadClass(...));\n"
  }
]