├── .github
└── workflows
│ ├── coding_standards.yml
│ └── tests.yml
├── .gitignore
├── .php-cs-fixer.php
├── .travis.yml
├── LICENCE
├── README.md
├── bundle
├── Command
│ ├── AddImageRemoteMediaCommand.php
│ ├── AddRemoteMediaFieldCommand.php
│ ├── MigrateEzImageCommand.php
│ ├── RefreshEzFieldsCommand.php
│ └── ShowApiUsageCommand.php
├── Controller
│ └── EzAdminUI
│ │ ├── BrowseController.php
│ │ ├── Editor
│ │ ├── FetchController.php
│ │ └── InsertController.php
│ │ ├── Facets
│ │ └── Load.php
│ │ └── Folder
│ │ ├── Create.php
│ │ └── Load.php
├── Converter
│ └── XmlText
│ │ └── NgRemoteMediaPreConverter.php
├── Core
│ ├── FieldType
│ │ └── RemoteMedia
│ │ │ ├── AdminInputValue.php
│ │ │ ├── FormMapper.php
│ │ │ ├── InputValue.php
│ │ │ ├── RemoteMediaStorage.php
│ │ │ ├── RemoteMediaStorage
│ │ │ ├── Gateway.php
│ │ │ └── Gateway
│ │ │ │ └── LegacyStorage.php
│ │ │ ├── SearchField.php
│ │ │ ├── Type.php
│ │ │ ├── UpdateFieldHelper.php
│ │ │ ├── Value.php
│ │ │ └── Variation.php
│ └── Persistence
│ │ └── Legacy
│ │ └── Content
│ │ └── FieldValue
│ │ └── Converter
│ │ └── RemoteMediaConverter.php
├── DependencyInjection
│ ├── Compiler
│ │ ├── TransformationHandlersCompilerPass.php
│ │ └── XslRegisterPass.php
│ ├── Configuration.php
│ └── NetgenRemoteMediaExtension.php
├── Entity
│ └── RemoteMediaFieldLink.php
├── Exception
│ ├── MimeCategoryParseException.php
│ ├── TransformationHandlerFailedException.php
│ └── TransformationHandlerNotFoundException.php
├── Form
│ └── FieldType
│ │ ├── FieldValueTransformer.php
│ │ └── RemoteMediaFieldType.php
├── NetgenRemoteMediaBundle.php
├── OpenGraph
│ └── Handler
│ │ └── RemoteMediaHandler.php
├── RemoteMedia
│ ├── Helper.php
│ ├── NextCursorResolver.php
│ ├── Provider
│ │ └── Cloudinary
│ │ │ ├── CloudinaryProvider.php
│ │ │ ├── Gateway.php
│ │ │ ├── Gateway
│ │ │ ├── Cache
│ │ │ │ └── Psr6CachedGateway.php
│ │ │ └── CloudinaryApiGateway.php
│ │ │ ├── Search
│ │ │ ├── Query.php
│ │ │ └── Result.php
│ │ │ └── TransformationHandler
│ │ │ ├── Crop.php
│ │ │ ├── Effect.php
│ │ │ ├── Fill.php
│ │ │ ├── Fit.php
│ │ │ ├── Format.php
│ │ │ ├── Lfill.php
│ │ │ ├── Limit.php
│ │ │ ├── Lpad.php
│ │ │ ├── Mfit.php
│ │ │ ├── Mpad.php
│ │ │ ├── NamedTransformation.php
│ │ │ ├── Pad.php
│ │ │ ├── Quality.php
│ │ │ ├── Resize.php
│ │ │ └── Scale.php
│ ├── RemoteMediaProvider.php
│ ├── Transformation
│ │ ├── HandlerInterface.php
│ │ └── Registry.php
│ ├── UploadFile.php
│ └── VariationResolver.php
├── Resources
│ ├── config
│ │ ├── config.yml.example
│ │ ├── default_parameters.yml
│ │ ├── default_settings.yml
│ │ ├── doctrine
│ │ │ └── RemoteMediaFieldLink.orm.yml
│ │ ├── ezadminui
│ │ │ ├── controllers.yml
│ │ │ ├── custom_tags.yml
│ │ │ ├── ezrichtext.yml
│ │ │ ├── routing.yml
│ │ │ └── twig.yml
│ │ ├── ezpublish.yml
│ │ ├── fieldtypes.yml
│ │ ├── legacy.yml
│ │ ├── opengraph.yml
│ │ ├── routing.yml
│ │ ├── services.yml
│ │ ├── storage
│ │ │ └── cache_psr6.yml
│ │ ├── templating.yml
│ │ └── transformation_handlers.yml
│ ├── encore
│ │ └── ez.config.manager.js
│ ├── public
│ │ ├── css
│ │ │ ├── remotemedia-vendors.css
│ │ │ └── remotemedia.css
│ │ ├── img
│ │ │ └── cloud-upload-alt.svg
│ │ └── js
│ │ │ ├── alloyeditor
│ │ │ ├── buttons
│ │ │ │ └── ngremotemedia.js
│ │ │ └── plugins
│ │ │ │ └── ngremotemedia.js
│ │ │ ├── remotemedia-vendors.js
│ │ │ └── remotemedia.js
│ ├── sql
│ │ └── schema.sql
│ ├── translations
│ │ ├── custom_tags.en.yml
│ │ ├── custom_tags.no.yml
│ │ ├── ngremotemedia.en.yml
│ │ └── ngremotemedia.no.yml
│ ├── views
│ │ ├── ezadminui
│ │ │ ├── field
│ │ │ │ ├── edit
│ │ │ │ │ └── ngremotemedia.html.twig
│ │ │ │ └── view
│ │ │ │ │ └── ngremotemedia.html.twig
│ │ │ ├── field_definition
│ │ │ │ └── view
│ │ │ │ │ └── ngremotemedia.html.twig
│ │ │ ├── field_type
│ │ │ │ └── ezrichtext
│ │ │ │ │ └── custom_tag
│ │ │ │ │ └── ngremotemedia.html.twig
│ │ │ ├── javascripts.html.twig
│ │ │ ├── js_config.html.twig
│ │ │ ├── parts
│ │ │ │ └── edit
│ │ │ │ │ ├── editor_insert.html.twig
│ │ │ │ │ ├── ezrichtext.html.twig
│ │ │ │ │ └── ngrm_field.html.twig
│ │ │ └── stylesheets.html.twig
│ │ └── ngremotemedia_content_field.html.twig
│ └── xsl
│ │ └── ezxml_ngremotemedia.xsl
├── Templating
│ ├── Converter
│ │ └── RemoteMediaValueConverter.php
│ └── Twig
│ │ └── Extension
│ │ └── NetgenRemoteMediaExtension.php
└── ezpublish_legacy
│ └── ngremotemedia
│ ├── .jshintrc
│ ├── autoloads
│ └── eztemplateautoload.php
│ ├── classes
│ └── ezlimitationloader.php
│ ├── datatypes
│ └── ngremotemedia
│ │ └── ngremotemediatype.php
│ ├── design
│ └── standard
│ │ ├── images
│ │ └── .gitkeep
│ │ ├── javascript
│ │ ├── plugins
│ │ │ └── ngremotemedia
│ │ │ │ └── editor_plugin.js
│ │ ├── remotemedia-vendors.js
│ │ └── remotemedia.js
│ │ ├── stylesheets
│ │ ├── remotemedia-vendors.css
│ │ └── remotemedia.css
│ │ └── templates
│ │ ├── content
│ │ └── datatype
│ │ │ ├── edit
│ │ │ └── ngremotemedia.tpl
│ │ │ └── view
│ │ │ ├── ezxmltags
│ │ │ └── ngremotemedia.tpl
│ │ │ └── ngremotemedia.tpl
│ │ └── ezxml_init.tpl
│ ├── extension.xml
│ ├── settings
│ ├── content.ini.append.php
│ ├── datatype.ini.append.php
│ ├── datetime.ini.append.php
│ ├── design.ini.append.php
│ ├── ezoe.ini.append.php
│ ├── ngremotemedia.ini
│ └── site.ini.append.php
│ ├── template_operator
│ └── ngremotemediaoperator.php
│ └── translations
│ ├── nor-NO
│ └── translation.ts
│ └── untranslated
│ └── translation.ts
├── codecov.yml
├── composer.json
├── docs
├── CHANGELOG.md
├── FRONTEND.md
├── INSTALL.md
├── TRANSFORMATIONS.md
├── UPGRADE.md
└── USAGE.md
├── frontend
├── .browserslistrc
├── .env
├── .eslintrc.js
├── babel.config.js
├── copyFiles.js
├── copyFilesDev.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│ └── index.html
├── src
│ ├── components
│ │ ├── Crop.vue
│ │ ├── CropModal.vue
│ │ ├── CropSizes.vue
│ │ ├── EditorInsertModal.vue
│ │ ├── Interactions.vue
│ │ ├── MediaFacets.vue
│ │ ├── MediaGalery.vue
│ │ ├── MediaModal.vue
│ │ ├── Modal.vue
│ │ ├── Preview.vue
│ │ ├── SelectFolder.vue
│ │ └── UploadModal.vue
│ ├── constants
│ │ └── facets.js
│ ├── font
│ │ ├── fa-ngrm.eot
│ │ ├── fa-ngrm.svg
│ │ ├── fa-ngrm.ttf
│ │ ├── fa-ngrm.woff
│ │ └── fa-ngrm.woff2
│ ├── main.js
│ ├── scss
│ │ ├── _iconfont.scss
│ │ ├── _variables.scss
│ │ └── ngremotemedia.scss
│ └── utility
│ │ ├── directives.js
│ │ ├── functional.js
│ │ ├── polyfills.js
│ │ ├── predicates.js
│ │ └── utility.js
└── vue.config.js
├── package-lock.json
├── package.json
├── phpunit.xml
├── tests
├── Core
│ ├── FieldType
│ │ └── RemoteMedia
│ │ │ ├── InputValueTest.php
│ │ │ ├── RemoteMediaStorage
│ │ │ └── Gateway
│ │ │ │ └── LegacyStorageTest.php
│ │ │ ├── RemoteMediaStorageTest.php
│ │ │ ├── TypeTest.php
│ │ │ ├── ValueTest.php
│ │ │ └── VariationTest.php
│ └── Persistence
│ │ └── Legacy
│ │ └── Content
│ │ └── FieldValue
│ │ └── Converter
│ │ └── RemoteMediaConverterTest.php
├── DependencyInjection
│ ├── Compiler
│ │ ├── TransformationHandlersCompilerPassTest.php
│ │ └── XslRegisterPassTest.php
│ ├── ConfigurationTest.php
│ └── NetgenRemoteMediaExtensionTest.php
├── Entity
│ └── RemoteMediaFieldLinkTest.php
├── Exception
│ ├── MimeCategoryParseExceptionTest.php
│ ├── TransformationHandlerFailedExceptionTest.php
│ └── TransformationHandlerNotFoundExceptionTest.php
├── OpenGraph
│ └── Handler
│ │ └── RemoteMediaHandlerTest.php
├── RemoteMedia
│ ├── NextCursorResolverTest.php
│ ├── Provider
│ │ └── Cloudinary
│ │ │ ├── CloudinaryProviderTest.php
│ │ │ ├── Gateway
│ │ │ └── CloudinaryApiGatewayTest.php
│ │ │ └── TransformationHandler
│ │ │ ├── BaseTest.php
│ │ │ ├── CropTest.php
│ │ │ ├── EffectTest.php
│ │ │ ├── FillTest.php
│ │ │ ├── FitTest.php
│ │ │ ├── FormatTest.php
│ │ │ ├── LfillTest.php
│ │ │ ├── LimitTest.php
│ │ │ ├── LpadTest.php
│ │ │ ├── MfitTest.php
│ │ │ ├── MpadTest.php
│ │ │ ├── NamedTransformationTest.php
│ │ │ ├── PadTest.php
│ │ │ ├── QualityTest.php
│ │ │ ├── ResizeTest.php
│ │ │ └── ScaleTest.php
│ ├── Transformation
│ │ └── RegistryTest.php
│ ├── UploadFileTest.php
│ └── VariationResolverTest.php
└── Templating
│ ├── Converter
│ └── RemoteMediaValueConverterTest.php
│ └── Twig
│ └── Extension
│ └── NetgenRemoteMediaExtensionTest.php
├── travis.php.ini
└── update
└── database
└── migrate-data_text4-to-data_text5.sql
/.github/workflows/coding_standards.yml:
--------------------------------------------------------------------------------
1 | name: Coding standards
2 |
3 | on:
4 | push:
5 | branches:
6 | - 'master'
7 | pull_request: ~
8 |
9 | jobs:
10 | php-cs-fixer:
11 | name: PHP CS Fixer
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - uses: OskarStark/php-cs-fixer-ga@2.19.0
17 | with:
18 | args: --diff --dry-run
19 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - 'master'
7 | pull_request: ~
8 |
9 | jobs:
10 | tests:
11 | name: ${{ matrix.php }} / ${{ matrix.symfony }}
12 | runs-on: ubuntu-latest
13 |
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | php: ['7.2', '7.3', '7.4']
18 | symfony: ['~3.4.0']
19 | deps: ['normal']
20 | include:
21 | - php: '7.2'
22 | symfony: '~3.4.0'
23 | deps: 'low'
24 |
25 | steps:
26 | - uses: actions/checkout@v2
27 | - uses: shivammathur/setup-php@v2
28 | with:
29 | php-version: ${{ matrix.php }}
30 | coverage: none
31 |
32 | - run: composer --version
33 | - run: composer validate --strict
34 |
35 | # Install Flex as a global dependency to enable usage of extra.symfony.require
36 | # while keeping Flex recipes from applying
37 | - run: composer global config --no-plugins allow-plugins.symfony/flex true
38 | - run: composer global require --no-scripts symfony/flex
39 |
40 | # Install eZ Publish legacy installer as a global dependency
41 | - run: composer config --no-plugins allow-plugins.ezsystems/ezpublish-legacy-installer true
42 |
43 | - run: composer config extra.symfony.require ${{ matrix.symfony }}
44 |
45 | -
46 | run: composer update --prefer-dist
47 | if: ${{ matrix.deps != 'low' }}
48 |
49 | -
50 | run: composer update --prefer-dist --prefer-lowest --prefer-stable
51 | if: ${{ matrix.deps == 'low' }}
52 |
53 | - run: vendor/bin/phpunit -c phpunit.xml --colors=always
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | vendor/
3 | var/
4 | ezpublish_legacy/
5 | composer.phar
6 | composer.lock
7 | phpunit.phar
8 | .php_cs.cache
9 | **/.sass-cache
10 | npm-debug.log
11 | node_modules
12 | *.css.map
13 | build
14 | .DS_Store
15 | frontend/dist/
16 |
17 | # local env files
18 | .env.local
19 | .env.*.local
20 |
21 | # Log files
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
26 | # Editor directories and files
27 | .vscode
28 | *.suo
29 | *.ntvs*
30 | *.njsproj
31 | *.sln
32 | *.sw?
33 |
--------------------------------------------------------------------------------
/.php-cs-fixer.php:
--------------------------------------------------------------------------------
1 | setRiskyAllowed(true)
8 | ->setRules([
9 | '@Symfony' => true,
10 | '@Symfony:risky' => true,
11 | '@PSR12' => true,
12 | '@PSR12:risky' => true,
13 | '@PhpCsFixer' => true,
14 | '@PhpCsFixer:risky' => true,
15 |
16 | // Overrides for rules included in PhpCsFixer rule sets
17 | 'array_syntax' => ['syntax' => 'short'],
18 | 'cast_spaces' => ['space' => 'single'],
19 | 'concat_space' => ['spacing' => 'one'],
20 | 'method_chaining_indentation' => false,
21 | 'multiline_whitespace_before_semicolons' => false,
22 | 'native_function_invocation' => ['include' => ['@all']],
23 | 'no_superfluous_phpdoc_tags' => false,
24 | 'no_alias_functions' => true,
25 | 'no_unset_on_property' => false,
26 | 'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'],
27 | 'php_unit_internal_class' => false,
28 | 'php_unit_method_casing' => false,
29 | 'php_unit_strict' => false,
30 | 'php_unit_test_annotation' => false,
31 | 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
32 | 'php_unit_test_class_requires_covers' => false,
33 | 'phpdoc_align' => false,
34 | 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
35 | 'return_assignment' => false,
36 | 'self_accessor' => false,
37 | 'single_line_comment_style' => false,
38 | 'space_after_semicolon' => false,
39 | 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false],
40 |
41 | // Additional rules
42 | 'declare_strict_types' => true,
43 | 'date_time_immutable' => true,
44 | 'global_namespace_import' => [
45 | 'import_classes' => null,
46 | 'import_constants' => true,
47 | 'import_functions' => true,
48 | ],
49 | 'heredoc_indentation' => ['indentation' => 'same_as_start'],
50 | 'list_syntax' => ['syntax' => 'short'],
51 | 'mb_str_functions' => true,
52 | 'native_constant_invocation' => true,
53 | 'nullable_type_declaration_for_default_null_value' => true,
54 | 'static_lambda' => true,
55 | 'ternary_to_null_coalescing' => true,
56 | 'use_arrow_functions' => false,
57 | ])
58 | ->setFinder(
59 | PhpCsFixer\Finder::create()
60 | ->exclude(['vendor', 'docs', 'ezpublish_legacy'])
61 | ->in(__DIR__)
62 | )
63 | ;
64 |
65 | return $config;
66 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | # cache directories
4 | cache:
5 | directories:
6 | - vendor
7 | - $HOME/.composer/cache/files
8 |
9 | matrix:
10 | # mark as finished before allow_failures are run
11 | fast_finish: true
12 | include:
13 | - php: 7.0
14 | - php: 7.1
15 | - php: 7.2
16 |
17 | # test only master (+ pull requests)
18 | branches:
19 | only:
20 | - master
21 | - 1.1-release
22 |
23 | # make sure to update composer to latest available version
24 | before_install:
25 | - composer self-update
26 | - phpenv config-add travis.php.ini
27 |
28 | # install dependencies
29 | install:
30 | - travis_wait composer install --no-interaction --no-progress --prefer-dist
31 |
32 | # execute phpunit as the script command
33 | script:
34 | - ./vendor/bin/phpunit -d memory_limit=-1 --colors -c phpunit.xml.dist --coverage-clover=coverage.xml
35 |
36 | # disable mail notifications
37 | notification:
38 | email: false
39 |
40 | # reduce depth (history) of git checkout
41 | git:
42 | depth: 30
43 |
44 | # we don't need sudo
45 | sudo: false
46 |
47 | # enable scrutinizer
48 | after_script:
49 | - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover
50 |
51 | # send coverage to codecov.io
52 | after_success:
53 | - bash <(curl -s https://codecov.io/bash)
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Netgen Remote Media Bundle
2 |
3 | [](https://travis-ci.org/netgen/NetgenRemoteMediaBundle)
4 | [](https://codecov.io/gh/netgen/NetgenRemoteMediaBundle)
5 | [](https://packagist.org/packages/netgen/remote-media-bundle)
6 | [](https://packagist.org/packages/netgen/remote-media-bundle)
7 | [](LICENCE)
8 |
9 | Netgen Remote Media Bundle is an eZ Publish bundle providing field type which supports remote resource providers, primarily [Cloudinary](http://cloudinary.com/).
10 |
11 | This repository contains field type (and legacy data type) implementation and provides the interface for the legacy administration. It also contains integration for eZ XML and Richtext fields (as a custom tag).
12 |
13 | ## Features
14 |
15 | - field type support for remote resources (only Cloudinary supported at the moment)
16 | - eZ XML field custom tag
17 | - eZ Richtext field custom tag
18 | - support for images, videos, audio files, documents and raw files upload
19 | - images cropping editor
20 | - support for both legacy and new stack administrations
21 |
22 | ## Licence and installation instructions
23 |
24 | [Licence](LICENCE)
25 |
26 | [Installation instructions](docs/INSTALL.md)
27 |
28 | [Upgrade instructions](docs/UPGRADE.md)
29 |
30 | ## Documentation
31 |
32 | For usage documentation see [USAGE.md](docs/USAGE.md)
33 |
34 | For transformations usage see [TRANSFORMATIONS.md](docs/TRANSFORMATIONS.md)
35 |
36 | ## Changelog
37 |
38 | For changes in specific versions see [CHANGELOG.md](docs/CHANGELOG.md)
39 |
40 | ## Contributing
41 |
42 | For frontend development see [FRONTEND.md][docs/frontend.md]
43 |
44 | ## Copyright
45 |
46 | - Copyright (C) 2021 Keyteq. All rights reserved.
47 | - Copyright (C) 2021 Netgen. All rights reserved.
48 |
--------------------------------------------------------------------------------
/bundle/Command/ShowApiUsageCommand.php:
--------------------------------------------------------------------------------
1 | provider = $provider;
24 |
25 | parent::__construct(null);
26 | }
27 |
28 | protected function configure()
29 | {
30 | $this
31 | ->setName('netgen:ngremotemedia:usage')
32 | ->setDescription('Show API usage (rate limits etc.)');
33 | }
34 |
35 | protected function execute(InputInterface $input, OutputInterface $output)
36 | {
37 | $usage = $this->provider->usage();
38 |
39 | foreach ($usage as $key => $value) {
40 | $output->writeln($this->getPrettyKey($key) . ': ' . $value . '');
41 | }
42 |
43 | return 0;
44 | }
45 |
46 | private function getPrettyKey(string $key): string
47 | {
48 | return ucfirst(str_replace('_', ' ', $key));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/bundle/Controller/EzAdminUI/BrowseController.php:
--------------------------------------------------------------------------------
1 | remoteMediaProvider = $remoteMediaProvider;
26 | $this->remoteMediaHelper = $remoteMediaHelper;
27 | }
28 |
29 | public function __invoke(Request $request)
30 | {
31 | $limit = 25;
32 | $userQuery = $request->get('q', '');
33 | $tag = $request->get('tag', 'all');
34 | $type = $request->get('mediatype', 'all');
35 | $folder = $request->get('folder', 'all');
36 | $type = $type !== 'all' ? $type : null;
37 | $folder = $folder !== 'all' ? $folder : null;
38 | $tag = $tag !== 'all' ? $tag : null;
39 |
40 | switch ($folder) {
41 | case '(all)':
42 | $folder = null;
43 |
44 | break;
45 |
46 | case '(root)':
47 | $folder = '';
48 |
49 | break;
50 | }
51 |
52 | $nextCursor = $request->get('next_cursor', null);
53 | if ($nextCursor === 'null') {
54 | $nextCursor = null;
55 | }
56 |
57 | $query = new Query(
58 | $userQuery,
59 | $type,
60 | $limit,
61 | $folder,
62 | $tag,
63 | $nextCursor,
64 | );
65 |
66 | $results = $this->remoteMediaProvider->searchResources($query);
67 | $list = $results->getResults();
68 |
69 | $result = [
70 | 'hits' => $this->remoteMediaHelper->formatBrowseList($list),
71 | 'load_more' => $results->getNextCursor() !== null,
72 | 'next_cursor' => $results->getNextCursor(),
73 | ];
74 |
75 | return new JsonResponse($result);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/bundle/Controller/EzAdminUI/Editor/FetchController.php:
--------------------------------------------------------------------------------
1 | remoteMediaProvider = $remoteMediaProvider;
29 | $this->remoteMediaHelper = $remoteMediaHelper;
30 | }
31 |
32 | public function __invoke(Request $request): Response
33 | {
34 | if (!$request->query->has('resource_id') && !$request->query->has('resource_type')) {
35 | throw new BadRequestHttpException('Request has to contain parameters "resource_id" and "resource_type"');
36 | }
37 |
38 | $resourceId = $request->query->get('resource_id');
39 | $resourceType = $request->query->get('resource_type');
40 |
41 | $resource = $this->remoteMediaProvider->getRemoteResource($resourceId, $resourceType);
42 |
43 | return new JsonResponse($this->remoteMediaHelper->formatBrowseItem($resource));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/bundle/Controller/EzAdminUI/Editor/InsertController.php:
--------------------------------------------------------------------------------
1 | updateFieldHelper = $updateFieldHelper;
36 | $this->remoteMediaProvider = $remoteMediaProvider;
37 | $this->remoteMediaHelper = $remoteMediaHelper;
38 | }
39 |
40 | public function __invoke(Request $request): Response
41 | {
42 | $oldValue = new Value();
43 |
44 | if ($request->request->get('new_file') === null) {
45 | $oldValue = $this->remoteMediaProvider->getRemoteResource($request->request->get('resource_id'));
46 | }
47 |
48 | $hash = $request->request->all();
49 | $hash['new_file'] = $request->files->get('new_file');
50 |
51 | $adminInputValue = AdminInputValue::fromHash($hash);
52 | $updatedValue = $this->updateFieldHelper->updateValue($oldValue, $adminInputValue);
53 |
54 | $selectedVariation = $request->request->get('variation');
55 |
56 | $variation = null;
57 | if ($selectedVariation && $updatedValue->mediaType === Value::TYPE_IMAGE) {
58 | $variation = $this->remoteMediaProvider->buildVariation($updatedValue, 'embedded', $selectedVariation);
59 | }
60 |
61 | $thumbnailUrl = null;
62 | $videoTag = null;
63 | if ($updatedValue->resourceType === 'video') {
64 | $thumbnailUrl = $this->remoteMediaProvider->getVideoThumbnail($updatedValue);
65 | $videoTag = $this->remoteMediaProvider->generateVideoTag($updatedValue, 'embedded', $selectedVariation);
66 | }
67 |
68 | $data = $this->remoteMediaHelper->formatBrowseItem($updatedValue);
69 | $data['selected_variation'] = $selectedVariation;
70 | $data['variation_url'] = $variation->url ?? null;
71 | $data['image_variations'] = $adminInputValue->getVariations();
72 | $data['thumbnail_url'] = $thumbnailUrl;
73 | $data['video_tag'] = $videoTag;
74 |
75 | return new JsonResponse($data);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/bundle/Controller/EzAdminUI/Facets/Load.php:
--------------------------------------------------------------------------------
1 | remoteMediaProvider = $remoteMediaProvider;
21 | }
22 |
23 | public function __invoke(): Response
24 | {
25 | $folders = $this->remoteMediaProvider->listFolders();
26 | $tags = $this->remoteMediaProvider->listTags();
27 |
28 | $formattedFolders = [];
29 | foreach ($folders as $folder) {
30 | $formattedFolders[] = [
31 | 'id' => $folder['path'],
32 | 'label' => $folder['name'],
33 | 'children' => null,
34 | ];
35 | }
36 |
37 | $formattedTags = [];
38 | foreach ($tags as $tag) {
39 | $formattedTags[] = [
40 | 'name' => $tag,
41 | 'id' => $tag,
42 | ];
43 | }
44 |
45 | $result = [
46 | 'folders' => $formattedFolders,
47 | 'tags' => $formattedTags,
48 | ];
49 |
50 | return new JsonResponse($result);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/bundle/Controller/EzAdminUI/Folder/Create.php:
--------------------------------------------------------------------------------
1 | remoteMediaProvider = $remoteMediaProvider;
21 | }
22 |
23 | public function __invoke(Request $request): Response
24 | {
25 | $parent = $request->request->get('parent');
26 | $folder = $request->request->get('folder');
27 |
28 | $folderPath = $folder;
29 | if ($parent !== 'null') {
30 | $folderPath = $parent . '/' . $folderPath;
31 | }
32 |
33 | $this->remoteMediaProvider->createFolder($folderPath);
34 |
35 | return new Response();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/bundle/Controller/EzAdminUI/Folder/Load.php:
--------------------------------------------------------------------------------
1 | remoteMediaProvider = $remoteMediaProvider;
22 | }
23 |
24 | public function __invoke(Request $request): Response
25 | {
26 | $folder = $request->query->get('folder');
27 |
28 | if ($folder === '(root)') {
29 | $folder = null;
30 | }
31 |
32 | $folders = $folder === null
33 | ? $this->remoteMediaProvider->listFolders()
34 | : $this->remoteMediaProvider->listSubFolders($folder);
35 |
36 | $formattedFolders = [];
37 | foreach ($folders as $folder) {
38 | $formattedFolders[] = [
39 | 'id' => $folder['path'],
40 | 'label' => $folder['name'],
41 | 'children' => null,
42 | ];
43 | }
44 |
45 | return new JsonResponse($formattedFolders);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/bundle/Converter/XmlText/NgRemoteMediaPreConverter.php:
--------------------------------------------------------------------------------
1 | remoteMediaProvider = $remoteMediaProvider;
25 | }
26 |
27 | public function convert(DOMDocument $xmlDoc)
28 | {
29 | $xpath = new DOMXPath($xmlDoc);
30 | $tags = $xpath->query("//custom[@name='ngremotemedia']");
31 |
32 | /** @var \DOMElement $tag */
33 | foreach ($tags as $tag) {
34 | $src = '';
35 | $videoTag = '';
36 | $filename = '';
37 |
38 | $resourceId = $tag->getAttributeNS(self::CUSTOMTAG_NAMESPACE, 'resourceId');
39 | $resourceType = $tag->getAttributeNS(self::CUSTOMTAG_NAMESPACE, 'resourceType') !== ''
40 | ? $tag->getAttributeNS(self::CUSTOMTAG_NAMESPACE, 'resourceType')
41 | : 'image';
42 | $imageVariations = $tag->getAttributeNS(self::CUSTOMTAG_NAMESPACE, 'coords');
43 | $variation = $tag->getAttributeNS(self::CUSTOMTAG_NAMESPACE, 'variation');
44 |
45 | $resource = $this->remoteMediaProvider->getRemoteResource($resourceId, $resourceType);
46 | $resource->variations = json_decode($imageVariations, true);
47 |
48 | switch ($resource->mediaType) {
49 | case 'video':
50 | $videoTag = $this->remoteMediaProvider->generateVideoTag($resource, 'embedded', $variation);
51 | $src = $this->remoteMediaProvider->getVideoThumbnail($resource);
52 |
53 | break;
54 |
55 | case 'image':
56 | $src = $resource->secure_url;
57 |
58 | if ($variation !== '') {
59 | $variation = $this->remoteMediaProvider->buildVariation($resource, 'embedded', $variation);
60 | $src = $variation->url;
61 | }
62 |
63 | break;
64 |
65 | default:
66 | $src = $this->remoteMediaProvider->generateDownloadLink($resource);
67 | }
68 |
69 | $tag->setAttributeNS(self::CUSTOMTAG_NAMESPACE, 'src', $src);
70 | $tag->setAttributeNS(self::CUSTOMTAG_NAMESPACE, 'videoTag', $videoTag);
71 | $tag->setAttributeNS(self::CUSTOMTAG_NAMESPACE, 'alt', $resource->metaData['alt_text'] ?? '');
72 | $tag->setAttributeNS(self::CUSTOMTAG_NAMESPACE, 'mediaType', $resource->mediaType ?? '');
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/bundle/Core/FieldType/RemoteMedia/FormMapper.php:
--------------------------------------------------------------------------------
1 | add(
20 | $fieldForm->getConfig()->getFormFactory()->createBuilder()
21 | ->create(
22 | 'value',
23 | RemoteMediaFieldType::class,
24 | [
25 | 'required' => $data->fieldDefinition->isRequired,
26 | 'label' => $data->fieldDefinition->getName(),
27 | 'field' => $data->field,
28 | ],
29 | )
30 | ->setAutoInitialize(false)
31 | ->getForm(),
32 | );
33 | }
34 |
35 | public function mapFieldDefinitionForm(FormInterface $fieldDefinitionForm, FieldDefinitionData $data)
36 | {
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/bundle/Core/FieldType/RemoteMedia/InputValue.php:
--------------------------------------------------------------------------------
1 | value->data['url'] ?? null,
29 | new StringField(),
30 | ),
31 | ];
32 | }
33 |
34 | /**
35 | * Get index field types for search backend.
36 | *
37 | * @return \eZ\Publish\SPI\Search\FieldType[]
38 | */
39 | public function getIndexDefinition()
40 | {
41 | return [
42 | 'value' => new StringField(),
43 | ];
44 | }
45 |
46 | /**
47 | * Get name of the default field to be used for matching.
48 | *
49 | * As field types can index multiple fields (see MapLocation field type's
50 | * implementation of this interface), this method is used to define default
51 | * field for matching. Default field is typically used by Field criterion.
52 | *
53 | * @return string
54 | */
55 | public function getDefaultMatchField()
56 | {
57 | return 'value';
58 | }
59 |
60 | /**
61 | * Get name of the default field to be used for sorting.
62 | *
63 | * As field types can index multiple fields (see MapLocation field type's
64 | * implementation of this interface), this method is used to define default
65 | * field for sorting. Default field is typically used by Field sort clause.
66 | *
67 | * @return string
68 | */
69 | public function getDefaultSortField()
70 | {
71 | return $this->getDefaultMatchField();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/bundle/Core/FieldType/RemoteMedia/Variation.php:
--------------------------------------------------------------------------------
1 | 0, 'y' => 0];
16 |
17 | /**
18 | * Returns a string representation of the field value.
19 | *
20 | * @return string
21 | */
22 | public function __toString()
23 | {
24 | return json_encode($this);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/bundle/Core/Persistence/Legacy/Content/FieldValue/Converter/RemoteMediaConverter.php:
--------------------------------------------------------------------------------
1 | dataText = json_encode($value->data);
31 | }
32 |
33 | /**
34 | * Converts data from $value to $fieldValue.
35 | */
36 | public function toFieldValue(StorageFieldValue $value, FieldValue $fieldValue)
37 | {
38 | $fieldValue->data = json_decode($value->dataText, true);
39 | }
40 |
41 | /**
42 | * Converts field definition data in $fieldDef into $storageFieldDef.
43 | */
44 | public function toStorageFieldDefinition(FieldDefinition $fieldDef, StorageFieldDefinition $storageDef)
45 | {
46 | }
47 |
48 | /**
49 | * Converts field definition data in $storageDef into $fieldDef.
50 | */
51 | public function toFieldDefinition(StorageFieldDefinition $storageDef, FieldDefinition $fieldDef)
52 | {
53 | }
54 |
55 | /**
56 | * Returns the name of the index column in the attribute table.
57 | *
58 | * @return string
59 | */
60 | public function getIndexColumn()
61 | {
62 | return 'data_text';
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/bundle/DependencyInjection/Compiler/TransformationHandlersCompilerPass.php:
--------------------------------------------------------------------------------
1 | hasDefinition('netgen_remote_media.handler_registry')) {
20 | return;
21 | }
22 |
23 | $handlerRegistry = $container->getDefinition('netgen_remote_media.handler_registry');
24 |
25 | foreach ($container->findTaggedServiceIds('netgen_remote_media.transformation_handler') as $serviceId => $transformationHandler) {
26 | if (!isset($transformationHandler[0]['alias'])) {
27 | throw new LogicException('netgen_remote_media.transformation_handler service tag needs an "alias" attribute to identify the handler. None given.');
28 | }
29 |
30 | if (!isset($transformationHandler[0]['provider'])) {
31 | throw new LogicException('netgen_remote_media.transformation_handler service tag needs an "provider" attribute to identify which providers it supports. None given.');
32 | }
33 |
34 | $handlerRegistry->addMethodCall(
35 | 'addHandler',
36 | [
37 | $transformationHandler[0]['provider'],
38 | $transformationHandler[0]['alias'],
39 | new Reference($serviceId),
40 | ]
41 | );
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/bundle/DependencyInjection/Compiler/XslRegisterPass.php:
--------------------------------------------------------------------------------
1 | hasParameter('ezpublish.siteaccess.list')) {
24 | return;
25 | }
26 |
27 | $scopes = array_merge(
28 | [ConfigResolver::SCOPE_DEFAULT],
29 | $container->getParameter('ezpublish.siteaccess.list')
30 | );
31 |
32 | if (empty($scopes)) {
33 | return;
34 | }
35 |
36 | foreach ($scopes as $scope) {
37 | if (!$container->hasParameter(sprintf('ezsettings.%s.fieldtypes.ezxml.custom_xsl', $scope))) {
38 | continue;
39 | }
40 |
41 | $xslConfig = $container->getParameter(sprintf('ezsettings.%s.fieldtypes.ezxml.custom_xsl', $scope));
42 | $xslConfig[] = ['path' => __DIR__ . '/../../Resources/xsl/ezxml_ngremotemedia.xsl', 'priority' => 5000];
43 | $container->setParameter(sprintf('ezsettings.%s.fieldtypes.ezxml.custom_xsl', $scope), $xslConfig);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/bundle/Entity/RemoteMediaFieldLink.php:
--------------------------------------------------------------------------------
1 | contentId = $contentId;
44 |
45 | return $this;
46 | }
47 |
48 | /**
49 | * Returns eZ Publish content ID.
50 | *
51 | * @return int
52 | */
53 | public function getContentId()
54 | {
55 | return $this->contentId;
56 | }
57 |
58 | /**
59 | * Sets eZ Publish field ID.
60 | *
61 | * @param mixed $fieldId
62 | *
63 | * @return \Netgen\Bundle\RemoteMediaBundle\Entity\RemoteMediaFieldLink
64 | */
65 | public function setFieldId($fieldId)
66 | {
67 | $this->fieldId = $fieldId;
68 |
69 | return $this;
70 | }
71 |
72 | /**
73 | * Returns eZ Publish field ID.
74 | *
75 | * @return mixed
76 | */
77 | public function getFieldId()
78 | {
79 | return $this->fieldId;
80 | }
81 |
82 | /**
83 | * @param mixed $versionId
84 | *
85 | * @return \Netgen\Bundle\RemoteMediaBundle\Entity\RemoteMediaFieldLink
86 | */
87 | public function setVersionId($versionId)
88 | {
89 | $this->versionId = $versionId;
90 |
91 | return $this;
92 | }
93 |
94 | /**
95 | * @return mixed
96 | */
97 | public function getVersionId()
98 | {
99 | return $this->versionId;
100 | }
101 |
102 | /**
103 | * Sets remote resource id.
104 | *
105 | * @param string $resourceId
106 | *
107 | * @return \Netgen\Bundle\RemoteMediaBundle\Entity\RemoteMediaFieldLink
108 | */
109 | public function setResourceId($resourceId)
110 | {
111 | $this->resourceId = $resourceId;
112 |
113 | return $this;
114 | }
115 |
116 | /**
117 | * Returns remote resource id.
118 | *
119 | * @return string
120 | */
121 | public function getResourceId()
122 | {
123 | return $this->resourceId;
124 | }
125 |
126 | /**
127 | * Sets remote provider identifier.
128 | *
129 | * @param string $provider
130 | *
131 | * @return \Netgen\Bundle\RemoteMediaBundle\Entity\RemoteMediaFieldLink
132 | */
133 | public function setProvider($provider)
134 | {
135 | $this->provider = $provider;
136 |
137 | return $this;
138 | }
139 |
140 | /**
141 | * Returns remote provider identifier.
142 | *
143 | * @return string
144 | */
145 | public function getProvider()
146 | {
147 | return $this->provider;
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/bundle/Exception/MimeCategoryParseException.php:
--------------------------------------------------------------------------------
1 | fieldType = $fieldType;
42 | $this->field = $field;
43 | $this->remoteMediaProvider = $remoteMediaProvider;
44 | $this->updateHelper = $updateFieldHelper;
45 | }
46 |
47 | /**
48 | * @param \Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\Value $value
49 | *
50 | * @return array|null
51 | */
52 | public function transform($value)
53 | {
54 | if (!$value instanceof Value) {
55 | return null;
56 | }
57 |
58 | return [
59 | 'resource_id' => $value->resourceId,
60 | 'alt_text' => $value->metaData['alt_text'] ?? '',
61 | 'tags' => is_array($value->metaData['tags']) ? $value->metaData['tags'] : [],
62 | 'image_variations' => json_encode($value->variations),
63 | 'type' => $value->mediaType,
64 | ];
65 | }
66 |
67 | /**
68 | * @param array|null $value
69 | *
70 | * @return \Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\Value
71 | */
72 | public function reverseTransform($value)
73 | {
74 | if ($value === null) {
75 | return $this->fieldType->getEmptyValue();
76 | }
77 |
78 | $oldValue = $this->field->value;
79 | if ($oldValue === null) {
80 | $oldValue = $this->fieldType->getEmptyValue();
81 | }
82 |
83 | $adminInputValue = AdminInputValue::fromHash($value);
84 |
85 | return $this->updateHelper->updateValue($oldValue, $adminInputValue);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/bundle/NetgenRemoteMediaBundle.php:
--------------------------------------------------------------------------------
1 | addCompilerPass(new XslRegisterPass());
22 | $container->addCompilerPass(new TransformationHandlersCompilerPass());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/NextCursorResolver.php:
--------------------------------------------------------------------------------
1 | cache = $cache;
51 | $this->ttl = $ttl;
52 | }
53 |
54 | /**
55 | * @throws \Psr\Cache\InvalidArgumentException
56 | */
57 | public function resolve(Query $query, int $offset): string
58 | {
59 | $cacheKey = $this->getCacheKey($query, $offset);
60 | $cacheItem = $this->cache->getItem($cacheKey);
61 |
62 | if ($cacheItem->isHit()) {
63 | return $cacheItem->get();
64 | }
65 |
66 | throw new RuntimeException("Can't get cursor key for query: " . (string) $query . " with offset: {$offset}");
67 | }
68 |
69 | /**
70 | * @throws \Psr\Cache\InvalidArgumentException
71 | */
72 | public function save(Query $query, int $offset, string $cursor): void
73 | {
74 | $cacheKey = $this->getCacheKey($query, $offset);
75 | $cacheItem = $this->cache->getItem($cacheKey);
76 |
77 | $cacheItem->set($cursor);
78 | $cacheItem->expiresAfter($this->ttl);
79 |
80 | $this->cache->save($cacheItem);
81 | }
82 |
83 | private function getCacheKey(Query $query, int $offset): string
84 | {
85 | $queryVars = [
86 | $query->getQuery(),
87 | is_array($query->getResourceType()) ? implode(',', $query->getResourceType()) : $query->getResourceType(),
88 | $query->getLimit(),
89 | $query->getFolder(),
90 | $query->getTag(),
91 | http_build_query($query->getSortBy(), '', ','),
92 | ];
93 |
94 | return $this->washKey(
95 | implode('-', [self::PROJECT_KEY, self::PROVIDER_KEY, self::NEXT_CURSOR, implode('|', $queryVars), $offset])
96 | );
97 | }
98 |
99 | private function washKey($key)
100 | {
101 | $forbiddenCharacters = ['{', '}', '(', ')', '/', '\\', '@'];
102 | foreach ($forbiddenCharacters as $char) {
103 | $key = str_replace($char, '_', trim($key, $char));
104 | }
105 |
106 | return $key;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/Search/Result.php:
--------------------------------------------------------------------------------
1 | totalCount = $totalCount;
23 | $this->nextCursor = $nextCursor;
24 | $this->results = $results;
25 | }
26 |
27 | public static function fromResponse(Response $response): self
28 | {
29 | $totalCount = $response['total_count'];
30 | $nextCursor = $response['next_cursor'] ?? null;
31 | $results = $response['resources'];
32 |
33 | return new Result($totalCount, $nextCursor, $results);
34 | }
35 |
36 | public function getTotalCount(): int
37 | {
38 | return $this->totalCount;
39 | }
40 |
41 | /**
42 | * @return string
43 | */
44 | public function getNextCursor(): ?string
45 | {
46 | return $this->nextCursor;
47 | }
48 |
49 | public function getResults(): array
50 | {
51 | return $this->results;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Crop.php:
--------------------------------------------------------------------------------
1 | variations)) {
34 | $coords = $value->variations[$variationName];
35 |
36 | $options[] = [
37 | 'x' => (int) $coords['x'],
38 | 'y' => (int) $coords['y'],
39 | 'width' => (int) $coords['w'],
40 | 'height' => (int) $coords['h'],
41 | 'crop' => 'crop',
42 | ];
43 |
44 | return $options;
45 | }
46 |
47 | throw new TransformationHandlerFailedException(self::class);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Effect.php:
--------------------------------------------------------------------------------
1 | $config[0],
42 | ];
43 | }
44 |
45 | return [
46 | 'effect' => $config[0] . ':' . $config[1],
47 | ];
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Fill.php:
--------------------------------------------------------------------------------
1 | 'fill',
33 | ];
34 |
35 | if (isset($config[0]) && $config[0] !== 0) {
36 | $options['width'] = $config[0];
37 | }
38 |
39 | if (isset($config[1]) && $config[1] !== 0) {
40 | $options['height'] = $config[1];
41 | }
42 |
43 | return $options;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Fit.php:
--------------------------------------------------------------------------------
1 | 'fit',
31 | ];
32 |
33 | if (isset($config[0]) && $config[0] !== 0) {
34 | $options['width'] = $config[0];
35 | }
36 |
37 | if (isset($config[1]) && $config[1] !== 0) {
38 | $options['height'] = $config[1];
39 | }
40 |
41 | return $options;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Format.php:
--------------------------------------------------------------------------------
1 | $config[0],
44 | ];
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Lfill.php:
--------------------------------------------------------------------------------
1 | 'lfill',
36 | ];
37 |
38 | if (isset($config[0]) && $config[0] !== 0) {
39 | $options['width'] = $config[0];
40 | }
41 |
42 | if (isset($config[1]) && $config[1] !== 0) {
43 | $options['height'] = $config[1];
44 | }
45 |
46 | return $options;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Limit.php:
--------------------------------------------------------------------------------
1 | 'limit',
35 | ];
36 |
37 | if (isset($config[0]) && $config[0] !== 0) {
38 | $options['width'] = $config[0];
39 | }
40 |
41 | if (isset($config[1]) && $config[1] !== 0) {
42 | $options['height'] = $config[1];
43 | }
44 |
45 | return $options;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Lpad.php:
--------------------------------------------------------------------------------
1 | 'lpad',
36 | ];
37 |
38 | if (isset($config[0]) && $config[0] !== 0) {
39 | $options['width'] = $config[0];
40 | }
41 |
42 | if (isset($config[1]) && $config[1] !== 0) {
43 | $options['height'] = $config[1];
44 | }
45 |
46 | if (!empty($config[2])) {
47 | $options['background'] = $config[2];
48 | }
49 |
50 | return $options;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Mfit.php:
--------------------------------------------------------------------------------
1 | 'mfit',
35 | ];
36 |
37 | if (isset($config[0]) && $config[0] !== 0) {
38 | $options['width'] = $config[0];
39 | }
40 |
41 | if (isset($config[1]) && $config[1] !== 0) {
42 | $options['height'] = $config[1];
43 | }
44 |
45 | return $options;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Mpad.php:
--------------------------------------------------------------------------------
1 | 'mpad',
37 | ];
38 |
39 | if (isset($config[0]) && $config[0] !== 0) {
40 | $options['width'] = $config[0];
41 | }
42 |
43 | if (isset($config[1]) && $config[1] !== 0) {
44 | $options['height'] = $config[1];
45 | }
46 |
47 | return $options;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/NamedTransformation.php:
--------------------------------------------------------------------------------
1 | $config[0],
42 | ];
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Pad.php:
--------------------------------------------------------------------------------
1 | 'pad',
33 | ];
34 |
35 | if (isset($config[0]) && $config[0] !== 0) {
36 | $options['width'] = $config[0];
37 | }
38 |
39 | if (isset($config[1]) && $config[1] !== 0) {
40 | $options['height'] = $config[1];
41 | }
42 |
43 | if (!empty($config[2])) {
44 | $options['background'] = $config[2];
45 | }
46 |
47 | return $options;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Quality.php:
--------------------------------------------------------------------------------
1 | $config[0],
52 | ];
53 | }
54 |
55 | if ($config[0] === 'auto') {
56 | return [
57 | 'quality' => $config[0] . ':' . $config[1],
58 | ];
59 | }
60 |
61 | throw new TransformationHandlerFailedException(self::class);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Provider/Cloudinary/TransformationHandler/Resize.php:
--------------------------------------------------------------------------------
1 | 'scale',
33 | ];
34 |
35 | if (isset($config[0]) && $config[0] !== 0) {
36 | $options['width'] = $config[0];
37 | }
38 |
39 | if (isset($config[1]) && $config[1] !== 0) {
40 | $options['height'] = $config[1];
41 | }
42 |
43 | return $options;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/Transformation/HandlerInterface.php:
--------------------------------------------------------------------------------
1 | transformationHandlers[$provider][$identifier])) {
26 | $this->transformationHandlers[$provider][$identifier] = $transformationHandler;
27 | }
28 | }
29 |
30 | /**
31 | * Returns handler by its identifier.
32 | *
33 | * @param string $identifier
34 | * @param string $provider
35 | *
36 | * @throws \Netgen\Bundle\RemoteMediaBundle\Exception\TransformationHandlerNotFoundException If the handler is not found
37 | *
38 | * @return \Netgen\Bundle\RemoteMediaBundle\RemoteMedia\Transformation\HandlerInterface
39 | */
40 | public function getHandler($identifier, $provider)
41 | {
42 | if (isset($this->transformationHandlers[$provider][$identifier])) {
43 | return $this->transformationHandlers[$provider][$identifier];
44 | }
45 |
46 | throw new TransformationHandlerNotFoundException($provider, $identifier);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/UploadFile.php:
--------------------------------------------------------------------------------
1 | uri = $uri;
38 | $uploadFile->originalFilename = pathinfo($uri, PATHINFO_FILENAME);
39 | $uploadFile->originalExtension = pathinfo($uri, PATHINFO_EXTENSION);
40 |
41 | return $uploadFile;
42 | }
43 |
44 | /**
45 | * Constructs UploadFile from given eZHTTPFile (usually uploaded through the legacy admin).
46 | *
47 | * @return UploadFile
48 | */
49 | public static function fromZHTTPFile(eZHTTPFile $file)
50 | {
51 | $uploadFile = new self();
52 |
53 | $uploadFile->uri = $file->Filename;
54 | $uploadFile->originalFilename = pathinfo($file->OriginalFilename, PATHINFO_FILENAME);
55 | $uploadFile->originalExtension = pathinfo($file->OriginalFilename, PATHINFO_EXTENSION);
56 |
57 | return $uploadFile;
58 | }
59 |
60 | public static function fromUploadedFile(UploadedFile $file)
61 | {
62 | $uploadFile = new self();
63 |
64 | $uploadFile->uri = $file->getRealPath();
65 | $uploadFile->originalFilename = $file->getClientOriginalName();
66 | $uploadFile->originalExtension = $file->getClientOriginalExtension();
67 |
68 | return $uploadFile;
69 | }
70 |
71 | /**
72 | * Constructs UploadFile from given eZImage field Value.
73 | *
74 | * @param $webRoot
75 | *
76 | * @return UploadFile
77 | */
78 | public static function fromEzImageValue(Value $value, $webRoot)
79 | {
80 | $uploadFile = new self();
81 |
82 | $uploadFile->uri = $webRoot . $value->uri;
83 | $uploadFile->originalFilename = pathinfo($value->fileName, PATHINFO_FILENAME);
84 | $uploadFile->originalExtension = pathinfo($value->fileName, PATHINFO_EXTENSION);
85 |
86 | return $uploadFile;
87 | }
88 |
89 | /**
90 | * @return string
91 | */
92 | public function uri()
93 | {
94 | return $this->uri;
95 | }
96 |
97 | /**
98 | * @return string
99 | */
100 | public function originalFilename()
101 | {
102 | return $this->originalFilename;
103 | }
104 |
105 | /**
106 | * @return string
107 | */
108 | public function originalExtension()
109 | {
110 | return $this->originalExtension;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/bundle/RemoteMedia/VariationResolver.php:
--------------------------------------------------------------------------------
1 | variations = $variations;
21 | }
22 |
23 | /**
24 | * Return merged variations defined for a provided content type and default ones.
25 | *
26 | * @param string $contentTypeIdentifier
27 | *
28 | * @return array
29 | */
30 | public function getVariationsForContentType($contentTypeIdentifier)
31 | {
32 | $defaultVariations = $this->variations['default'] ?? [];
33 | $contentTypeVariations = $this->variations[$contentTypeIdentifier] ?? [];
34 |
35 | return array_merge($defaultVariations, $contentTypeVariations);
36 | }
37 |
38 | /**
39 | * Returns variations for a provided content type which have 'crop' transformation configured.
40 | *
41 | * @param $contentTypeIdentifier
42 | *
43 | * @return array
44 | */
45 | public function getCroppbableVariations($contentTypeIdentifier)
46 | {
47 | $variations = $this->getVariationsForContentType($contentTypeIdentifier);
48 |
49 | $croppableVariations = [];
50 | foreach ($variations as $variationName => $variationOptions) {
51 | if (isset($variationOptions['transformations']['crop'])) {
52 | $croppableVariations[$variationName] = $variationOptions;
53 | }
54 | }
55 |
56 | return $croppableVariations;
57 | }
58 |
59 | /**
60 | * Returns variations to be used when embedding image into ezxml text.
61 | *
62 | * @return array
63 | */
64 | public function getEmbedVariations()
65 | {
66 | $variations = $this->variations['embedded'] ?? [];
67 |
68 | $croppableVariations = [];
69 | foreach ($variations as $variationName => $variationOptions) {
70 | if (isset($variationOptions['transformations']['crop'])) {
71 | $croppableVariations[$variationName] = $variationOptions;
72 | }
73 | }
74 |
75 | return $croppableVariations;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/bundle/Resources/config/config.yml.example:
--------------------------------------------------------------------------------
1 | # Remote Media Configuration
2 | netgen_remote_media:
3 | provider: cloudinary # available options: cloudinary
4 | account_name: cloudname
5 | account_key: cloudinary_key
6 | account_secret: cloudinary_secret_key
7 |
8 | # If set to true, resources that are not connected to any eZ content objects
9 | # will be removed from the remote provider
10 | remove_unused: false
11 |
--------------------------------------------------------------------------------
/bundle/Resources/config/default_parameters.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | netgen_remote_media.parameters.use_subdomains: true
3 | netgen_remote_media.cloudinary.internal_limit: 500
4 | netgen_remote_media.cloudinary.cache_ttl: 7200
5 | netgen_remote_media.default.parameters.audio.enable_waveform: false
6 |
--------------------------------------------------------------------------------
/bundle/Resources/config/default_settings.yml:
--------------------------------------------------------------------------------
1 | system:
2 | default:
3 | image_variations:
4 | default:
5 | admin_preview:
6 | transformations:
7 | - { name: limit, params: [400,400] }
8 | ng_article:
9 | test:
10 | transformations:
11 | - { name: crop, params: [1600, 900] }
12 | - { name: resize, params: [1600, 900] }
13 | embedded:
14 | small:
15 | transformations:
16 | - { name: crop, params: [200, 200] }
17 | - { name: resize, params: [200, 200] }
18 | medium:
19 | transformations:
20 | - { name: crop, params: [800, 450] }
21 | - { name: resize, params: [800, 450] }
22 | large:
23 | transformations:
24 | - { name: crop, params: [1600, 900] }
25 | - { name: resize, params: [1600, 900] }
26 |
--------------------------------------------------------------------------------
/bundle/Resources/config/doctrine/RemoteMediaFieldLink.orm.yml:
--------------------------------------------------------------------------------
1 | Netgen\Bundle\RemoteMediaBundle\Entity\RemoteMediaFieldLink:
2 | type: entity
3 | table: ngremotemedia_field_link
4 | id:
5 | fieldId:
6 | type: integer
7 | column: field_id
8 | versionId:
9 | type: integer
10 | column: version
11 | resourceId:
12 | type: string
13 | column: resource_id
14 | provider:
15 | type: string
16 | column: provider
17 | fields:
18 | contentId:
19 | type: integer
20 | column: contentobject_id
21 |
--------------------------------------------------------------------------------
/bundle/Resources/config/ezadminui/controllers.yml:
--------------------------------------------------------------------------------
1 | services:
2 | netgen_remote_media.controllers.ezadminui.facets.load:
3 | class: Netgen\Bundle\RemoteMediaBundle\Controller\EzAdminUI\Facets\Load
4 | arguments:
5 | - '@netgen_remote_media.provider'
6 |
7 | netgen_remote_media.controllers.ezadminui.folder.load:
8 | class: Netgen\Bundle\RemoteMediaBundle\Controller\EzAdminUI\Folder\Load
9 | arguments:
10 | - '@netgen_remote_media.provider'
11 |
12 | netgen_remote_media.controllers.ezadminui.folder.create:
13 | class: Netgen\Bundle\RemoteMediaBundle\Controller\EzAdminUI\Folder\Create
14 | arguments:
15 | - '@netgen_remote_media.provider'
16 |
17 | netgen_remote_media.controllers.ezadminui.browse:
18 | class: Netgen\Bundle\RemoteMediaBundle\Controller\EzAdminUI\BrowseController
19 | arguments:
20 | - '@netgen_remote_media.provider'
21 | - '@netgen_remote_media.helper'
22 |
23 | netgen_remote_media.controllers.ezadminui.editor.fetch:
24 | class: Netgen\Bundle\RemoteMediaBundle\Controller\EzAdminUI\Editor\FetchController
25 | arguments:
26 | - '@netgen_remote_media.provider'
27 | - '@netgen_remote_media.helper'
28 |
29 | netgen_remote_media.controllers.ezadminui.editor.insert:
30 | class: Netgen\Bundle\RemoteMediaBundle\Controller\EzAdminUI\Editor\InsertController
31 | arguments:
32 | - '@netgen_remote_media.admin.field_update.helper'
33 | - '@netgen_remote_media.provider'
34 | - '@netgen_remote_media.helper'
35 |
--------------------------------------------------------------------------------
/bundle/Resources/config/ezadminui/custom_tags.yml:
--------------------------------------------------------------------------------
1 | ezpublish:
2 | system:
3 | default:
4 | fieldtypes:
5 | ezrichtext:
6 | custom_tags: [ngremotemedia]
7 |
8 | ezrichtext:
9 | custom_tags:
10 | ngremotemedia:
11 | template: '@NetgenRemoteMedia/ezadminui/field_type/ezrichtext/custom_tag/ngremotemedia.html.twig'
12 | attributes:
13 | resourceId:
14 | type: string
15 | required: true
16 | resourceType:
17 | type: string
18 | required: true
19 | coords:
20 | type: string
21 | required: false
22 | variation:
23 | type: string
24 | required: false
25 | caption:
26 | type: string
27 | required: false
28 | cssclass:
29 | type: string
30 | required: false
31 |
--------------------------------------------------------------------------------
/bundle/Resources/config/ezadminui/ezrichtext.yml:
--------------------------------------------------------------------------------
1 | alloy_editor:
2 | extra_plugins: [ngremotemedia]
3 | extra_buttons:
4 | paragraph: [ngremotemedia]
5 | ngremotemedia: [ngremotemedia]
6 |
--------------------------------------------------------------------------------
/bundle/Resources/config/ezadminui/routing.yml:
--------------------------------------------------------------------------------
1 | netgen_remote_media_ezadmin_facets_load:
2 | path: /facets/load
3 | defaults:
4 | _controller: netgen_remote_media.controllers.ezadminui.facets.load
5 |
6 | netgen_remote_media_ezadmin_folder_load:
7 | path: /folder/load
8 | defaults:
9 | _controller: netgen_remote_media.controllers.ezadminui.folder.load
10 |
11 | netgen_remote_media_ezadmin_folder_create:
12 | path: /folder/create
13 | defaults:
14 | _controller: netgen_remote_media.controllers.ezadminui.folder.create
15 |
16 | netgen_remote_media_ezadmin_browse:
17 | path: /browse
18 | defaults:
19 | _controller: netgen_remote_media.controllers.ezadminui.browse
20 |
21 | netgen_remote_media_ezadmin_editor_fetch:
22 | path: /editor/fetch
23 | defaults:
24 | _controller: netgen_remote_media.controllers.ezadminui.editor.fetch
25 |
26 | netgen_remote_media_ezadmin_editor_insert:
27 | path: /editor/insert
28 | defaults:
29 | _controller: netgen_remote_media.controllers.ezadminui.editor.insert
30 |
--------------------------------------------------------------------------------
/bundle/Resources/config/ezadminui/twig.yml:
--------------------------------------------------------------------------------
1 | form_themes:
2 | - '@NetgenRemoteMedia/ezadminui/field/edit/ngremotemedia.html.twig'
3 |
--------------------------------------------------------------------------------
/bundle/Resources/config/ezpublish.yml:
--------------------------------------------------------------------------------
1 | system:
2 | admin_group:
3 | field_templates:
4 | - {template: "@NetgenRemoteMedia/ezadminui/field/view/ngremotemedia.html.twig", priority: 1}
5 | default:
6 | field_templates:
7 | - { template: "NetgenRemoteMediaBundle::ngremotemedia_content_field.html.twig", priority: 0 }
8 | fielddefinition_settings_templates:
9 | - {template: "NetgenRemoteMediaBundle:ezadminui/field_definition/view:ngremotemedia.html.twig", priority: 0}
10 |
--------------------------------------------------------------------------------
/bundle/Resources/config/fieldtypes.yml:
--------------------------------------------------------------------------------
1 | services:
2 | ezpublish.fieldType.ngremotemedia:
3 | class: Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\Type
4 | parent: ezpublish.fieldType
5 | tags:
6 | - {name: ezpublish.fieldType, alias: ngremotemedia}
7 |
8 | ezpublish.fieldType.ngremotemedia.converter:
9 | class: Netgen\Bundle\RemoteMediaBundle\Core\Persistence\Legacy\Content\FieldValue\Converter\RemoteMediaConverter
10 | tags:
11 | - {name: ezpublish.storageEngine.legacy.converter, alias: ngremotemedia}
12 |
13 | ezpublish.fieldType.ngremotemedia.externalStorage:
14 | class: Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\RemoteMediaStorage
15 | arguments:
16 | - "@ezpublish.api.service.content"
17 | - "@netgen_remote_media.provider"
18 | calls:
19 | - [setDeleteUnused, ["%netgen_remote_media.remove_unused_resources%"]]
20 | tags:
21 | - {name: ezpublish.fieldType.externalStorageHandler, alias: ngremotemedia}
22 |
23 | ezpublish.fieldType.ngremotemedia.storage_gateway:
24 | class: Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\RemoteMediaStorage\Gateway\LegacyStorage
25 | tags:
26 | - {name: ezpublish.fieldType.externalStorageHandler.gateway, alias: ngremotemedia, identifier: LegacyStorage}
27 |
28 | ezpublish.fieldType.indexable.netgen_remote_media:
29 | class: Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\SearchField
30 | tags:
31 | - {name: ezpublish.fieldType.indexable, alias: ngremotemedia}
32 |
33 | ezpublish.ezadminui.form.ngremotemedia_field_type:
34 | class: Netgen\Bundle\RemoteMediaBundle\Form\FieldType\RemoteMediaFieldType
35 | public: false
36 | arguments:
37 | - "@ezpublish.api.service.field_type"
38 | - "@netgen_remote_media.provider"
39 | - "@netgen_remote_media.admin.field_update.helper"
40 | tags:
41 | - { name: form.type }
42 |
43 | netgen_remote_media.admin.field_update.helper:
44 | class: Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\UpdateFieldHelper
45 | arguments:
46 | - "@netgen_remote_media.provider"
47 |
48 | ezpublish.fieldtype.ngremotemedia.form_mapper:
49 | class: Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\FormMapper
50 | arguments:
51 | - '@ezpublish.api.service.field_type'
52 | tags:
53 | - {name: ez.fieldFormMapper.value, fieldType: ngremotemedia}
54 |
--------------------------------------------------------------------------------
/bundle/Resources/config/legacy.yml:
--------------------------------------------------------------------------------
1 | services:
2 | netgen_remote_media.templating.converter.ngremotemedia:
3 | class: Netgen\Bundle\RemoteMediaBundle\Templating\Converter\RemoteMediaValueConverter
4 | tags:
5 | - {name: ezpublish_legacy.templating.converter, for: Netgen\Bundle\RemoteMediaBundle\Core\FieldType\RemoteMedia\Value}
6 |
--------------------------------------------------------------------------------
/bundle/Resources/config/opengraph.yml:
--------------------------------------------------------------------------------
1 | services:
2 | netgen_remote_media.open_graph_handler:
3 | class: Netgen\Bundle\RemoteMediaBundle\OpenGraph\Handler\RemoteMediaHandler
4 | parent: netgen_open_graph.handler.field_type.abstract
5 | arguments:
6 | - "@netgen_remote_media.provider"
7 | - "@ezpublish.api.service.content_type"
8 | - "@request_stack"
9 | - "@?logger"
10 | lazy: true
11 | tags:
12 | - { name: netgen_open_graph.meta_tag_handler, alias: field_type/ngremotemedia }
13 |
--------------------------------------------------------------------------------
/bundle/Resources/config/routing.yml:
--------------------------------------------------------------------------------
1 | netgen_remote_media_ezadmin:
2 | resource: "ezadminui/routing.yml"
3 | prefix: /ngremotemedia
4 |
--------------------------------------------------------------------------------
/bundle/Resources/config/storage/cache_psr6.yml:
--------------------------------------------------------------------------------
1 | services:
2 | netgen_remote_media.provider.cloudinary.gateway.cached:
3 | class: Netgen\Bundle\RemoteMediaBundle\RemoteMedia\Provider\Cloudinary\Gateway\Cache\Psr6CachedGateway
4 | arguments:
5 | - "@netgen_remote_media.provider.cloudinary.gateway"
6 | - "@ezpublish.cache_pool"
7 | - "%netgen_remote_media.cloudinary.cache_ttl%"
8 |
--------------------------------------------------------------------------------
/bundle/Resources/config/templating.yml:
--------------------------------------------------------------------------------
1 | services:
2 | netgen_remote_media.templating.twig.extension:
3 | class: Netgen\Bundle\RemoteMediaBundle\Templating\Twig\Extension\NetgenRemoteMediaExtension
4 | arguments:
5 | - "@netgen_remote_media.provider"
6 | - "@ezpublish.translation_helper"
7 | - "@ezpublish.api.service.content_type"
8 | - "@netgen_remote_media.variation.resolver"
9 | tags:
10 | - { name: twig.extension }
11 |
--------------------------------------------------------------------------------
/bundle/Resources/encore/ez.config.manager.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = (eZConfig, eZConfigManager) => {
4 | eZConfigManager.add({
5 | eZConfig,
6 | entryName: 'ezplatform-admin-ui-alloyeditor-js',
7 | newItems: [
8 | path.resolve(__dirname, '../public/js/alloyeditor/buttons/ngremotemedia.js'),
9 | path.resolve(__dirname, '../public/js/alloyeditor/plugins/ngremotemedia.js'),
10 | ]
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/bundle/Resources/public/img/cloud-upload-alt.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/bundle/Resources/public/js/alloyeditor/buttons/ngremotemedia.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import AlloyEditor from 'alloyeditor';
3 | import EzButton
4 | from '../../../../../../../../../vendor/ezsystems/ezplatform-admin-ui/src/bundle/Resources/public/js/alloyeditor/src/base/ez-button.js';
5 |
6 | export default class BtnNgRemoteMedia extends EzButton {
7 | static get key() {
8 | return 'ngremotemedia';
9 | }
10 |
11 | InsertMedia(data) {
12 | this.execCommand(data);
13 | }
14 |
15 | render() {
16 | const title = 'Netgen Remote Media';
17 |
18 | return (
19 |
26 | );
27 | }
28 | }
29 |
30 | AlloyEditor.Buttons[BtnNgRemoteMedia.key] = AlloyEditor.BtnNgRemoteMedia = BtnNgRemoteMedia;
31 | eZ.addConfig('ezAlloyEditor.BtnNgRemoteMedia', BtnNgRemoteMedia);
32 |
33 | BtnNgRemoteMedia.propTypes = {
34 | command: PropTypes.string,
35 | };
36 |
37 | BtnNgRemoteMedia.defaultProps = {
38 | command: 'InsertMedia',
39 | };
40 |
--------------------------------------------------------------------------------
/bundle/Resources/public/js/alloyeditor/plugins/ngremotemedia.js:
--------------------------------------------------------------------------------
1 | (function (global) {
2 | if (CKEDITOR.plugins.get('ngremotemedia')) {
3 | return;
4 | }
5 |
6 | var currentEditorInstance = null;
7 |
8 | function InsertMediaCallback(data, caption, align, cssClass) {
9 | let alignAttr = '';
10 |
11 | if (typeof align !== 'undefined' && align !== '') {
12 | alignAttr = ' data-ezalign="'+align+'"';
13 | }
14 |
15 | let html = '
';
33 |
34 | currentEditorInstance.insertHtml(html);
35 | }
36 |
37 | const InsertMedia = {
38 | exec: function (editor) {
39 | var data = {};
40 | window[`remoteMedia_ezrichtext`].setEditorInsertCallback(InsertMediaCallback);
41 | window[`remoteMedia_ezrichtext`].openEditorInsertModal(data);
42 | currentEditorInstance = editor;
43 | },
44 | };
45 |
46 | global.CKEDITOR.plugins.add('ngremotemedia', {
47 | init: (editor) => editor.addCommand('InsertMedia', InsertMedia),
48 | });
49 | })(window);
50 |
--------------------------------------------------------------------------------
/bundle/Resources/sql/schema.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS `ngremotemedia_field_link` (
2 | `field_id` int(11) NOT NULL,
3 | `version` int(11) NOT NULL,
4 | `resource_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
5 | `provider` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
6 | `contentobject_id` int(11) NOT NULL,
7 | PRIMARY KEY (`field_id`,`version`,`resource_id`,`provider`)
8 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
9 |
--------------------------------------------------------------------------------
/bundle/Resources/translations/custom_tags.en.yml:
--------------------------------------------------------------------------------
1 | ezrichtext.custom_tags.ngremotemedia.label: Netgen Remote Media
2 | ezrichtext.custom_tags.ngremotemedia.description: ''
3 | ezrichtext.custom_tags.ngremotemedia.attributes.resourceId.label: Resource ID
4 | ezrichtext.custom_tags.ngremotemedia.attributes.resourceType.label: Resource type
5 | ezrichtext.custom_tags.ngremotemedia.attributes.coords.label: Image variations
6 | ezrichtext.custom_tags.ngremotemedia.attributes.variation.label: Selected variation
7 | ezrichtext.custom_tags.ngremotemedia.attributes.caption.label: Caption
8 | ezrichtext.custom_tags.ngremotemedia.attributes.cssclass.label: CSS class
9 |
--------------------------------------------------------------------------------
/bundle/Resources/translations/custom_tags.no.yml:
--------------------------------------------------------------------------------
1 | ezrichtext.custom_tags.ngremotemedia.label: Netgen Remote Media
2 | ezrichtext.custom_tags.ngremotemedia.description: ''
3 | ezrichtext.custom_tags.ngremotemedia.attributes.resourceId.label: Ressurs-ID
4 | ezrichtext.custom_tags.ngremotemedia.attributes.resourceType.label: Ressurstype
5 | ezrichtext.custom_tags.ngremotemedia.attributes.coords.label: Bildevariasjoner
6 | ezrichtext.custom_tags.ngremotemedia.attributes.variation.label: Valgt variasjon
7 | ezrichtext.custom_tags.ngremotemedia.attributes.caption.label: Bildetekst
8 | ezrichtext.custom_tags.ngremotemedia.attributes.cssclass.label: CSS-klasse
9 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/field/edit/ngremotemedia.html.twig:
--------------------------------------------------------------------------------
1 | {% block ezplatform_fieldtype_ngremotemedia_widget %}
2 | {% set field = form.parent.vars.value.field %}
3 |
4 | {% set input_fields = {} %}
5 | {% for child in form %}
6 | {% set input_fields = input_fields|merge({(child.vars.name): child.vars.full_name}) %}
7 | {% endfor %}
8 |
9 | {% set content_type_identifier = app.request.attributes.get('contentType').identifier|default(null) %}
10 |
11 | {% include '@NetgenRemoteMedia/ezadminui/parts/edit/ngrm_field.html.twig' with {
12 | 'content_type_identifier': content_type_identifier,
13 | 'field_id': field.id,
14 | 'field_value': field.value,
15 | 'input_fields': input_fields,
16 | } %}
17 | {% endblock %}
18 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/field/view/ngremotemedia.html.twig:
--------------------------------------------------------------------------------
1 | {% extends '@NetgenRemoteMedia/ngremotemedia_content_field.html.twig' %}
2 |
3 | {% block ngremotemedia_field %}
4 | {% set parameters = {format: 'admin_preview'} %}
5 | {{ parent() }}
6 | {% endblock %}
7 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/field_definition/view/ngremotemedia.html.twig:
--------------------------------------------------------------------------------
1 | {% block ngremotemedia_settings %}
2 | {% endblock %}
3 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/field_type/ezrichtext/custom_tag/ngremotemedia.html.twig:
--------------------------------------------------------------------------------
1 | {% set css_class = params.cssclass|default(null) %}
2 | {% set resource_id = params.resourceId|default(null) %}
3 | {% set resource_type = params.resourceType|default(null) %}
4 | {% set coords = params.coords|default('[]') %}
5 | {% set variation = params.variation|default(null) %}
6 | {% set caption = params.caption|default(null) %}
7 | {% set align = align|default(null) %}
8 | {% set css_class = params.cssclass|default(null) %}
9 |
10 | {% if resource_id and resource_type %}
11 | {% set resource = netgen_remote_media_embed(resource_id, resource_type, coords) %}
12 |
13 |
32 | {% endif %}
33 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/javascripts.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/parts/edit/editor_insert.html.twig:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
48 |
49 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/parts/edit/ezrichtext.html.twig:
--------------------------------------------------------------------------------
1 | {% set has_richtext = false %}
2 | {% for field in contentType.fieldDefinitions %}
3 | {% if field.fieldTypeIdentifier == 'ezrichtext' %}
4 | {% set has_richtext = true %}
5 | {% endif %}
6 | {% endfor %}
7 |
8 | {% if has_richtext %}
9 | {% include '@NetgenRemoteMedia/ezadminui/js_config.html.twig' %}
10 |
11 | {% include '@NetgenRemoteMedia/ezadminui/parts/edit/editor_insert.html.twig' with {
12 | 'field_id': '_ezrichtext'
13 | } %}
14 | {% endif %}
15 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/parts/edit/ngrm_field.html.twig:
--------------------------------------------------------------------------------
1 | {% include '@NetgenRemoteMedia/ezadminui/js_config.html.twig' %}
2 |
3 |
40 |
41 |
42 |
47 |
48 |
--------------------------------------------------------------------------------
/bundle/Resources/views/ezadminui/stylesheets.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bundle/Resources/xsl/ezxml_ngremotemedia.xsl:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
remote-image-inline remote-
15 |
16 |
17 |
18 | object-center
19 |
20 |
21 |
22 | object-
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/bundle/Templating/Converter/RemoteMediaValueConverter.php:
--------------------------------------------------------------------------------
1 | 'extension/ngremotemedia/template_operator/ngremotemediaoperator.php',
7 | 'class' => 'NgRemoteMediaOperator',
8 | 'operator_names' => array('ngremotemedia', 'ng_remote_resource', 'ng_remote_croppable', 'ng_image_variations', 'scaling_format', 'list_format')
9 | );
10 |
11 | ?>
12 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/classes/ezlimitationloader.php:
--------------------------------------------------------------------------------
1 | 'Browse', 'id' => 'browse' );
15 |
16 | return $returnArray;
17 | }
18 | }
19 | ?>
20 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/design/standard/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/netgen/NetgenRemoteMediaBundle/61615a8ae0e3c286f4c2bc4f024c77413f6112d6/bundle/ezpublish_legacy/ngremotemedia/design/standard/images/.gitkeep
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/design/standard/javascript/plugins/ngremotemedia/editor_plugin.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prefer-arrow-callback */
2 | (function (tinymce) {
3 | function insertMediaCallback(data, caption, align, cssClass) {
4 | var imageUrl = '';
5 | if (data.mediaType === 'image') {
6 | if (data.variation_url !== null) {
7 | imageUrl = data.variation_url;
8 | } else if (data.url !== null) {
9 | imageUrl = data.url;
10 | }
11 | } else if (data.mediaType === 'video' && data.thumbnail_url !== null && data.thumbnail_url !== '') {
12 | imageUrl = data.thumbnail_url;
13 | }
14 |
15 | let previewUrl = imageUrl !== '' ? imageUrl : '/extension/ezoe/design/standard/images/tango/mail-attachment.png';
16 | let elementClass = "ezoeItemCustomTag ngremotemedia";
17 | let alignAttr = '';
18 |
19 | if (typeof align !== 'undefined' && align !== '') {
20 | elementClass += (' ezoeAlign' + align);
21 | alignAttr = 'align="'+align+'"';
22 | }
23 |
24 | let html = '
';
30 |
31 | tinymce.execCommand('mceInsertContent', false, html);
32 | }
33 |
34 | tinymce.PluginManager.add("ngremotemedia", function (editor) {
35 | const fieldId = editor.settings.ez_attribute_id;
36 |
37 | window[`remoteMedia` + fieldId].setEditorInsertCallback(insertMediaCallback);
38 |
39 | // Add a button that opens a modal
40 | editor.addButton("ngremotemedia", {
41 | title: "Insert remote media",
42 | image: "/bundles/netgenremotemedia/img/cloud-upload-alt.svg",
43 | onclick() {
44 | let attributeType = tinymce.activeEditor.selection.getNode().getAttribute('type');
45 | let attributeString = tinymce.activeEditor.selection.getNode().getAttribute('customattributes');
46 | let hasNgrmClass = tinymce.activeEditor.selection.getNode().classList.contains('ngremotemedia');
47 |
48 | var data = {};
49 | if (attributeType === 'custom' && hasNgrmClass === true && attributeString) {
50 | data.align = tinymce.activeEditor.selection.getNode().getAttribute('align');
51 | let attributes = attributeString.split('attribute_separation');
52 |
53 | attributes.forEach(function (attribute) {
54 | let attributeKey = attribute.split('|')[0];
55 | let attributeValue = attribute.split('|')[1];
56 |
57 | if (attributeKey === 'coords' || attributeKey === 'image_variations') {
58 | try {
59 | data['image_variations'] = JSON.parse(attributeValue);
60 | } catch(e) {
61 | data['image_variations'] = {};
62 | }
63 |
64 | return;
65 | }
66 |
67 | data[attributeKey] = attributeValue;
68 | });
69 | }
70 |
71 | window[`remoteMedia` + fieldId].openEditorInsertModal(data);
72 | },
73 | });
74 |
75 | return {
76 | getMetadata() {
77 | return {
78 | name: "Netgen remote media",
79 | url: "https://github.com/netgen/NetgenRemoteMediaBundle",
80 | };
81 | },
82 | };
83 | });
84 | })(tinymce);
85 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/design/standard/templates/content/datatype/edit/ngremotemedia.tpl:
--------------------------------------------------------------------------------
1 | {def $base='ContentObjectAttribute'}
2 | {def $remote_value = $attribute.content}
3 | {def $field_id = $attribute.id}
4 |
5 | {def $input_fields = hash(
6 | 'alt_text', concat($base, '_alttext_', $field_id),
7 | 'image_variations', concat($base, '_image_variations_', $field_id),
8 | 'media_type', concat($base, '_media_type_', $field_id),
9 | 'new_file', concat($base, '_new_file_', $field_id),
10 | 'resource_id', concat($base, '_media_id_', $field_id),
11 | 'tags', concat($base, '_tags_', $field_id, '[]')
12 | )}
13 |
14 | {symfony_include(
15 | '@NetgenRemoteMedia/ezadminui/parts/edit/ngrm_field.html.twig',
16 | hash(
17 | 'content_type_identifier', $attribute.object.class_identifier,
18 | 'field_id', $field_id,
19 | 'field_value', $remote_value,
20 | 'input_fields', $input_fields
21 | )
22 | )}
23 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/design/standard/templates/content/datatype/view/ezxmltags/ngremotemedia.tpl:
--------------------------------------------------------------------------------
1 | {if not(and(is_set($resourceType), is_string($resourceType), not($resourceType|compare(''))))}
2 | {def $resourceType = 'image'}
3 | {/if}
4 |
5 | {if and($resourceId, $resourceId|is_null|not)}
6 | {def $resource = ng_remote_resource($resourceType, $resourceId, $coords)}
7 | {/if}
8 |
9 | {if and(resource, $resource.resourceId|is_null|not)}
10 |
11 | {if eq($resource.mediaType, 'image')}
12 | {def $image_url = $resource.secure_url}
13 |
14 | {def $image_url = ngremotemedia($resource, 'embedded', $variation).url}
15 |
16 |

20 | {elseif eq($resource.mediaType, 'video')}
21 | {ngremotevideo($resource, $variation, 'embedded')}
22 | {else}
23 |
{$resourceId}
24 | {/if}
25 |
26 | {if and(is_set($caption), is_string($caption), not($caption|compare('')))}
{$caption|wash()}
{/if}
27 |
28 | {/if}
29 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/design/standard/templates/content/datatype/view/ngremotemedia.tpl:
--------------------------------------------------------------------------------
1 | {def $variations = ng_image_variations()}
2 |
3 | {def
4 | $value = $attribute.content
5 | }
6 |
7 | {if $value.resourceId}
8 | {def $format = 'admin_preview'}
9 | {if $value.mediaType|eq('image')}
10 | {def $variation = ngremotemedia($value, $attribute.object.class_identifier, $format)}
11 |
12 | {if not(is_set($alt_text))}
13 | {def $alt_text = $value.metaData.alt_text|default('')}
14 | {/if}
15 |
16 | {if not(is_set($title))}
17 | {def $title = $value.metaData.caption|default('')}
18 | {/if}
19 |
20 |
26 | {elseif $value.mediaType|eq('video')}
27 |
28 | {$value.resourceId}
29 |
30 |
31 |
32 | {def $thumbnail = videoThumbnail($value, hash('content_type_identifier', $attribute.object.class_identifier, 'variation_name', $format))}
33 |
34 | {else}
35 |
36 |
37 | {$value.resourceId}
38 |
39 | {/if}
40 | {else}
41 | No media selected
42 | {/if}
43 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/design/standard/templates/ezxml_init.tpl:
--------------------------------------------------------------------------------
1 | {symfony_include('@NetgenRemoteMedia/ezadminui/js_config.html.twig')}
2 |
3 | {foreach $content_attributes_grouped_data_map as $attribute_group => $content_attributes_grouped}
4 | {foreach $content_attributes_grouped as $attribute_identifier => $attribute}
5 | {if eq($attribute.data_type_string, 'ezxmltext')}
6 | {symfony_include('@NetgenRemoteMedia/ezadminui/parts/edit/editor_insert.html.twig', hash(
7 | 'field_id', $attribute.id
8 | ))}
9 | {/if}
10 | {/foreach}
11 | {/foreach}
12 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/extension.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Netgen Remote Media
5 | 2.0
6 | Copyright (C) 2019 Netgen d.o.o. All rights reserved.
7 | GPL 2.0
8 | http://netgen.io
9 |
10 |
11 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/settings/content.ini.append.php:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/translations/nor-NO/translation.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | extension/ngremotemedia/datatype
6 |
7 | RemoteMedia
8 | Datatype name
9 | RemoteMedia
10 |
11 |
12 |
13 | extension/ngremotemedia/interactions
14 |
15 | Search for media
16 | Søk etter media
17 |
18 |
19 | Load more
20 | last mer
21 |
22 |
23 | Upload new media
24 | Last opp nytt
25 |
26 |
27 | No results
28 | Ingen treff
29 |
30 |
31 | Alternate text
32 | Alternativ tekst
33 |
34 |
35 | CSS class
36 | CSS klasse
37 |
38 |
39 | Create new folder?
40 |
41 |
42 |
43 | Folder
44 | Mappe
45 |
46 |
47 | All
48 | Alle
49 |
50 |
51 | Add tag
52 | Legg til merkelapp
53 |
54 |
55 | Close
56 | Lukk
57 |
58 |
59 | Remove media
60 | Fjern media
61 |
62 |
63 | Manage media
64 |
65 |
66 |
67 | Quick upload
68 | Rask opplasting
69 |
70 |
71 | Scale
72 | Skalér
73 |
74 |
75 | Media type
76 |
77 |
78 |
79 | Image and documents
80 | Bilde og dokumenter
81 |
82 |
83 | Video
84 |
85 |
86 |
87 | Loading...
88 | Lasting...
89 |
90 |
91 | Cancel
92 | Avbryt
93 |
94 |
95 | Save all
96 | Lagre alt
97 |
98 |
99 | Generate
100 | Generere
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/bundle/ezpublish_legacy/ngremotemedia/translations/untranslated/translation.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | extension/ngremotemedia/datatype
6 |
7 | RemoteMedia
8 | Datatype name
9 |
10 |
11 |
12 |
13 | extension/ngremotemedia/interactions
14 |
15 | Search for media
16 |
17 |
18 |
19 | Load more
20 |
21 |
22 |
23 | Upload new media
24 |
25 |
26 |
27 | No results
28 |
29 |
30 |
31 | Alternate text
32 |
33 |
34 |
35 | CSS class
36 |
37 |
38 |
39 | Create new folder?
40 |
41 |
42 |
43 | Folder
44 |
45 |
46 |
47 | All
48 |
49 |
50 |
51 | Add tag
52 |
53 |
54 |
55 | Close
56 |
57 |
58 |
59 | Remove media
60 |
61 |
62 |
63 | Manage media
64 |
65 |
66 |
67 | Quick upload
68 |
69 |
70 |
71 | Scale
72 |
73 |
74 |
75 | Media type
76 |
77 |
78 |
79 | Image and documents
80 |
81 |
82 |
83 | Video
84 |
85 |
86 |
87 | Loading...
88 |
89 |
90 |
91 | Cancel
92 |
93 |
94 |
95 | Save all
96 |
97 |
98 |
99 | Generate
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | patch: false
4 | changes: false
5 | project:
6 | default:
7 | target: auto
8 | comment: off
9 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "netgen/remote-media-bundle",
3 | "description": "Remote media field type implementation",
4 | "type": "ezplatform-bundle",
5 | "keywords": [
6 | "ezpublish",
7 | "ezplatform",
8 | "remote media",
9 | "netgen",
10 | "remote-media-bundle"
11 | ],
12 | "homepage": "https://github.com/netgen/NetgenRemoteMediaBundle",
13 | "license": "GPL-2.0-only",
14 | "authors": [
15 | {
16 | "name": "Netgen",
17 | "homepage": "http://netgen.io",
18 | "email": "info@netgen.io"
19 | },
20 | {
21 | "name": "Ivan Herak",
22 | "email": "ivan@netgen.io"
23 | },
24 | {
25 | "name": "Jurica Hladek",
26 | "email": "jurica@netgen.io"
27 | }
28 | ],
29 | "require": {
30 | "php": "^7.2",
31 | "ezsystems/ezpublish-kernel": "^7.4",
32 | "doctrine/orm": "^2.4",
33 | "cloudinary/cloudinary_php": "^1.10"
34 | },
35 | "require-dev": {
36 | "ezsystems/legacy-bridge": "^2.0",
37 | "netgen/open-graph-bundle": "^1.2",
38 | "netgen/admin-ui-bundle": "^2.0",
39 | "matthiasnoback/symfony-dependency-injection-test": "^3.0",
40 | "mikey179/vfsstream": "^1.2",
41 | "phpunit/phpunit": "^7.0",
42 | "friendsofphp/php-cs-fixer": "^2.18",
43 | "rector/rector": "^0.5.22"
44 | },
45 | "autoload": {
46 | "psr-4": {
47 | "Netgen\\Bundle\\RemoteMediaBundle\\": "bundle"
48 | }
49 | },
50 | "autoload-dev": {
51 | "psr-4": {
52 | "Netgen\\Bundle\\Tests\\": "tests",
53 | "Netgen\\Bundle\\OpenGraphBundle\\Tests\\": "vendor/netgen/open-graph-bundle/tests"
54 | }
55 | },
56 | "scripts": {
57 | "test": "@php vendor/bin/phpunit --colors=always",
58 | "fix": "@php vendor/bin/php-cs-fixer fix"
59 | },
60 | "extra": {
61 | "ezpublish-legacy-dir": "ezpublish_legacy",
62 | "branch-alias": {
63 | "dev-master": "2.0.x-dev"
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/docs/TRANSFORMATIONS.md:
--------------------------------------------------------------------------------
1 | Table of supported transformations from Cloudinary.
2 |
3 | | Transformation name | Transformation alias | Description |
4 | |:-------------------:|:--------------------:|:-----------:|
5 | | Crop | crop | Crops the image if it has been cropped in the administration interface |
6 | | Effect | effect | Applies the effect to change the visual appearance |
7 | | Fill | fill | Exact given width and height while retaining the original aspect ratio, using only part of the image that fills the given dimensions if necessary |
8 | | Fit | fit | The image is resized so that it takes up as much space as possible within a bounding box defined by the given width and height parameters. The original aspect ratio is retained and all of the original image is visible. |
9 | | Format | format | Defines in format should the media be delivered. |
10 | | Lfill | lfill | Same as the fill mode but only if the original image is larger than the given limit (width and height). This mode doesn't scale up the image if your requested dimensions are bigger than the original image's |
11 | | Limit | limit | Same as the fit mode but only if the original image is larger than the given limit (width and height), in which case the image is scaled down. This mode doesn't scale up the image if your requested dimensions are larger than the original image's. |
12 | | Lpad | lpad | Same as the pad mode but only if the original image is larger than the given limit (width and height), in which case the image is scaled down to fill the given width and height while retaining the original aspect ratio. If the proportions of the original image do not match the given width and height, padding is added to the image to reach the required size. |
13 | | Mfit | mfit | Same as the fit mode but only if the original image is smaller than the given minimum (width and height), in which case the image is scaled up. All of the original image is visible. |
14 | | Mpad | mpad | Same as the pad mode but only if the original image is smaller than the given minimum (width and height), in which case the image is scaled up to fill the given width and height while retaining the original aspect ratio and with all of the original image visible. You can also specify the color of the background in the case that padding is added. |
15 | | Named transformation | transformation | A named transformation is a set of image transformations that has been given a custom name for easy reference. |
16 | | Pad | pad | Resize the image to fill the given width and height while retaining the original aspect ratio and with all of the original image visible. If the proportions of the original image do not match the given width and height, padding is added to the image to reach the required size. You can also specify the color of the background in the case that padding is added. |
17 | | Quality | quality | Set compression level to apply to an image as a value between 1 (smallest file size possible) and 100 (best visual quality). Automatic quality selection is also available |
18 | | Resize | resize | Change the size of the image |
19 | | Scale | scale | Change the size of the image exactly to the given width and height without necessarily retaining the original aspect ratio: all original image parts are visible but might be stretched or shrunk. |
20 |
21 |
22 | For additional details on each of the transformation, consult the Cloudinary [documentation](http://cloudinary.com/documentation/image_transformations)
23 |
--------------------------------------------------------------------------------
/frontend/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/frontend/.env:
--------------------------------------------------------------------------------
1 | DEV_PROXY_SESSION_ID=
--------------------------------------------------------------------------------
/frontend/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ['plugin:vue/essential'],
7 | rules: {
8 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
9 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
10 | },
11 | parserOptions: {
12 | parser: 'babel-eslint'
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/frontend/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/frontend/copyFiles.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | const mappings = [
4 | {
5 | source: 'dist/js/app.js',
6 | targets: [
7 | '../bundle/Resources/public/js/remotemedia.js',
8 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/javascript/remotemedia.js'
9 | ]
10 | },
11 | {
12 | source: 'dist/js/chunk-vendors.js',
13 | targets: [
14 | '../bundle/Resources/public/js/remotemedia-vendors.js',
15 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/javascript/remotemedia-vendors.js'
16 | ]
17 | },
18 | {
19 | source: 'dist/css/app.css',
20 | targets: [
21 | '../bundle/Resources/public/css/remotemedia.css',
22 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/stylesheets/remotemedia.css'
23 | ]
24 | },
25 | {
26 | source: 'dist/css/chunk-vendors.css',
27 | targets: [
28 | '../bundle/Resources/public/css/remotemedia-vendors.css',
29 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/stylesheets/remotemedia-vendors.css'
30 | ]
31 | }
32 | ];
33 |
34 | const copyFile = source => destination => {
35 | fs.copyFile(source, destination, err => {
36 | if (err) throw err;
37 | console.log(`${source} copied to ${destination}`);
38 | });
39 | };
40 |
41 | mappings.forEach(map => {
42 | map.targets.forEach(copyFile(map.source));
43 | });
44 |
--------------------------------------------------------------------------------
/frontend/copyFilesDev.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | const mappings = [
4 | {
5 | source: 'dist/app.js',
6 | targets: [
7 | '../bundle/Resources/public/js/remotemedia.js',
8 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/javascript/remotemedia.js'
9 | ]
10 | }
11 | ];
12 |
13 | const fakeFiles = [
14 | {
15 | targets: [
16 | '../bundle/Resources/public/js/remotemedia-vendors.js',
17 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/javascript/remotemedia-vendors.js'
18 | ]
19 | },
20 | {
21 | targets: [
22 | '../bundle/Resources/public/css/remotemedia.css',
23 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/stylesheets/remotemedia.css'
24 | ]
25 | },
26 | {
27 | targets: [
28 | '../bundle/Resources/public/css/remotemedia-vendors.css',
29 | '../bundle/ezpublish_legacy/ngremotemedia/design/standard/stylesheets/remotemedia-vendors.css'
30 | ]
31 | },
32 | ];
33 |
34 | const copyFile = source => destination => {
35 | fs.copyFile(source, destination, err => {
36 | if (err) throw err;
37 | console.log(`${source} copied to ${destination}`);
38 | });
39 | };
40 |
41 | const fakeFile = path => {
42 | fs.closeSync(fs.openSync(path, 'w'))
43 | console.log(`Faked ${path}`);
44 | }
45 |
46 | mappings.forEach(map => {
47 | map.targets.forEach(copyFile(map.source));
48 | });
49 |
50 | fakeFiles.forEach(fakes => {
51 | fakes.targets.forEach(fakeFile);
52 | })
53 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "netgen-remote-media-bundle",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build && node copyFiles.js",
8 | "dev": "vue-cli-service build --mode development && node copyFilesDev.js",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "@riophae/vue-treeselect": "^0.4.0",
13 | "axios": "^0.21.1",
14 | "core-js": "^2.6.5",
15 | "cropperjs": "^1.5.5",
16 | "debounce": "^1.2.0",
17 | "pretty-bytes": "^5.6.0",
18 | "vue": "^2.6.10",
19 | "vue-select": "^3.2.0"
20 | },
21 | "devDependencies": {
22 | "@vue/cli-plugin-babel": "^3.11.0",
23 | "@vue/cli-plugin-eslint": "^3.11.0",
24 | "@vue/cli-service": "^3.11.0",
25 | "@vue/eslint-config-prettier": "^5.0.0",
26 | "babel-eslint": "^10.0.1",
27 | "eslint": "^5.16.0",
28 | "eslint-plugin-prettier": "^3.1.0",
29 | "eslint-plugin-vue": "^5.0.0",
30 | "node-sass": "^4.9.0",
31 | "prettier": "^1.18.2",
32 | "sass-loader": "^7.1.0",
33 | "vue-template-compiler": "^2.6.10"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/frontend/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/frontend/src/components/Modal.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
28 |
29 |
30 |
74 |
--------------------------------------------------------------------------------
/frontend/src/components/Preview.vue:
--------------------------------------------------------------------------------
1 |
2 |
38 |
39 |
40 | {{this.$root.$data.NgRemoteMediaTranslations.interactions_no_media_selected}}
41 |
42 |
43 |
44 |
82 |
--------------------------------------------------------------------------------
/frontend/src/components/UploadModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
47 |
48 |
49 |
73 |
--------------------------------------------------------------------------------
/frontend/src/constants/facets.js:
--------------------------------------------------------------------------------
1 | export const TYPE_ALL = 'all';
2 | export const TYPE_IMAGE = 'image';
3 | export const TYPE_VIDEO = 'video';
4 | export const TYPE_RAW = 'raw';
5 | export const SEARCH_NAME = 'name';
6 | export const FOLDER_ALL = '(all)';
7 | export const FOLDER_ROOT = '(root)';
8 | export const TAG_ALL = 'all';
9 |
--------------------------------------------------------------------------------
/frontend/src/font/fa-ngrm.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/netgen/NetgenRemoteMediaBundle/61615a8ae0e3c286f4c2bc4f024c77413f6112d6/frontend/src/font/fa-ngrm.eot
--------------------------------------------------------------------------------
/frontend/src/font/fa-ngrm.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/frontend/src/font/fa-ngrm.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/netgen/NetgenRemoteMediaBundle/61615a8ae0e3c286f4c2bc4f024c77413f6112d6/frontend/src/font/fa-ngrm.ttf
--------------------------------------------------------------------------------
/frontend/src/font/fa-ngrm.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/netgen/NetgenRemoteMediaBundle/61615a8ae0e3c286f4c2bc4f024c77413f6112d6/frontend/src/font/fa-ngrm.woff
--------------------------------------------------------------------------------
/frontend/src/font/fa-ngrm.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/netgen/NetgenRemoteMediaBundle/61615a8ae0e3c286f4c2bc4f024c77413f6112d6/frontend/src/font/fa-ngrm.woff2
--------------------------------------------------------------------------------
/frontend/src/scss/_iconfont.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'fa-ngrm';
3 | src: url('../font/fa-ngrm.eot?75641014');
4 | src: url('../font/fa-ngrm.eot?75641014#iefix') format('embedded-opentype'),
5 | url('../font/fa-ngrm.woff2?75641014') format('woff2'),
6 | url('../font/fa-ngrm.woff?75641014') format('woff'),
7 | url('../font/fa-ngrm.ttf?75641014') format('truetype'),
8 | url('../font/fa-ngrm.svg?75641014#fa-ngrm') format('svg');
9 | font-weight: normal;
10 | font-style: normal;
11 | }
12 |
13 | [class^="ngrm-icon-"]:before, [class*=" ngrm-icon-"]:before {
14 | font-family: "fa-ngrm";
15 | font-style: normal;
16 | font-weight: normal;
17 | speak: none;
18 |
19 | display: inline-block;
20 | text-decoration: inherit;
21 | width: 1em;
22 | margin-right: .2em;
23 | text-align: center;
24 |
25 | /* For safety - reset parent styles, that can break glyph codes*/
26 | font-variant: normal;
27 | text-transform: none;
28 |
29 | /* fix buttons height, for twitter bootstrap */
30 | line-height: 1em;
31 |
32 | margin-left: .2em;
33 |
34 | /* Font smoothing. That was taken from TWBS */
35 | -webkit-font-smoothing: antialiased;
36 | -moz-osx-font-smoothing: grayscale;
37 | }
38 |
39 | .ngrm-icon-cancel:before { content: '\e800'; } /* '' */
40 | .ngrm-icon-floppy:before { content: '\e801'; } /* '' */
41 | .ngrm-icon-ok:before { content: '\e802'; } /* '' */
42 | .ngrm-icon-ccw:before { content: '\e803'; } /* '' */
43 | .ngrm-icon-folder:before { content: '\e804'; } /* '' */
44 | .ngrm-icon-upload:before { content: '\e805'; } /* '' */
45 | .ngrm-icon-play:before { content: '\e811'; } /* '' */
46 | .ngrm-icon-trash:before { content: '\f1f8'; } /* '' */
47 |
--------------------------------------------------------------------------------
/frontend/src/scss/_variables.scss:
--------------------------------------------------------------------------------
1 | // Variables
2 | $white: #FFFFFF;
3 | $mine-shaft: #333333;
4 | $wild-sand: #F5F5F5;
5 | $alto: #D7D7D7;
6 | $boulder: #757575;
7 | $mercury: #E4E4E4;
8 | $dusty-gray: #999999;
9 | $netgen-primary: #009AC7;
10 | $crimson: #A41034;
11 |
--------------------------------------------------------------------------------
/frontend/src/utility/directives.js:
--------------------------------------------------------------------------------
1 | import { kebabToCamelCase } from './utility';
2 |
3 | export const initDirective = {
4 | bind: function(el, binding, vnode) {
5 | const propertyName = kebabToCamelCase(binding.arg);
6 |
7 | vnode.context[propertyName] = binding.value;
8 | }
9 | };
10 |
--------------------------------------------------------------------------------
/frontend/src/utility/functional.js:
--------------------------------------------------------------------------------
1 | export const objectMap = f => obj => {
2 | return Object.keys(obj).reduce((newObj, property) => {
3 | newObj[property] = f(obj[property], property);
4 | return newObj;
5 | }, {});
6 | };
7 |
8 | export const objectFilter = p => obj => {
9 | return Object.keys(obj).reduce((newObj, property) => {
10 | if (p(obj[property], property)) {
11 | newObj[property] = obj[property];
12 | }
13 | return newObj;
14 | }, {});
15 | };
16 |
17 | export const constant = val => () => val;
18 |
--------------------------------------------------------------------------------
/frontend/src/utility/polyfills.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.difference) {
2 | Array.prototype.difference = function(other) {
3 | return this.filter(el => other.indexOf(el) < 0);
4 | };
5 | }
6 |
--------------------------------------------------------------------------------
/frontend/src/utility/predicates.js:
--------------------------------------------------------------------------------
1 | export const not = f => item => !f(item);
2 | export const equal = value => item => value === item;
3 | export const truthy = value => !!value;
4 | export const notUndefined = not(equal(undefined));
5 |
--------------------------------------------------------------------------------
/frontend/src/utility/utility.js:
--------------------------------------------------------------------------------
1 | export const encodeQueryData = data => {
2 | const ret = [];
3 | for (let d in data)
4 | ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
5 | return ret.join('&');
6 | };
7 |
8 | export const capitalizeFirstLetter = str => str[0].toUpperCase() + str.slice(1);
9 |
10 | export const kebabToCamelCase = str => {
11 | const [first, ...rest] = str.split('-');
12 | return [first, ...rest.map(capitalizeFirstLetter)].join('');
13 | };
14 |
15 | export const format = (num, decimals) => {
16 | const multiplyer = Math.pow(10, decimals);
17 | return parseFloat(Math.round(num * multiplyer) / multiplyer).toFixed(
18 | decimals
19 | );
20 | };
21 |
22 | const sizeDimensionsMap = {
23 | B: 'KB',
24 | KB: 'MB',
25 | MB: 'GB',
26 | GB: 'TB'
27 | };
28 | export const formatByteSize = (size, dim = 'B') => {
29 | const nextDim = sizeDimensionsMap[dim];
30 |
31 | if (!nextDim || size < 1024) {
32 | return `${format(size, 2)} ${dim}`;
33 | }
34 |
35 | return formatByteSize(size / 1024, nextDim);
36 | };
37 |
--------------------------------------------------------------------------------
/frontend/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | runtimeCompiler: true,
3 | devServer: {
4 | proxy: {
5 | '^/ngadminui': {
6 | target: 'http://remote-media.dev6.netgen.biz',
7 | changeOrigin: true,
8 | headers: {
9 | cookie: `eZSESSID=${process.env.DEV_PROXY_SESSION_ID};`
10 | }
11 | }
12 | }
13 | },
14 | filenameHashing: false,
15 | configureWebpack: {
16 | entry: {
17 | app: './src/main.js',
18 | }
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "RemoteMediaBundle",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "handlebars": {
8 | "version": "4.2.0",
9 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz",
10 | "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==",
11 | "requires": {
12 | "neo-async": "^2.6.0",
13 | "optimist": "^0.6.1",
14 | "source-map": "^0.6.1",
15 | "uglify-js": "^3.1.4"
16 | },
17 | "dependencies": {
18 | "source-map": {
19 | "version": "0.6.1",
20 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
21 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
22 | }
23 | }
24 | },
25 | "neo-async": {
26 | "version": "2.6.1",
27 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
28 | "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw=="
29 | },
30 | "optimist": {
31 | "version": "0.6.1",
32 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
33 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
34 | "requires": {
35 | "minimist": "~0.0.1",
36 | "wordwrap": "~0.0.2"
37 | },
38 | "dependencies": {
39 | "minimist": {
40 | "version": "0.0.10",
41 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
42 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
43 | },
44 | "wordwrap": {
45 | "version": "0.0.3",
46 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
47 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
48 | }
49 | }
50 | },
51 | "uglify-js": {
52 | "version": "3.4.10",
53 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
54 | "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
55 | "optional": true,
56 | "requires": {
57 | "commander": "~2.19.0",
58 | "source-map": "~0.6.1"
59 | },
60 | "dependencies": {
61 | "commander": {
62 | "version": "2.19.0",
63 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
64 | "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
65 | "optional": true
66 | },
67 | "source-map": {
68 | "version": "0.6.1",
69 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
70 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
71 | "optional": true
72 | }
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "RemoteMediaBundle",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "dependencies": {
7 | "handlebars": "^4.0.11"
8 | },
9 | "devDependencies": {
10 | },
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "git@bitbucket.org:netgen/netgenremotemedia.git"
17 | },
18 | "author": "",
19 | "license": "ISC"
20 | }
21 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | tests
16 |
17 |
18 |
19 |
20 | bundle
21 |
22 | bundle/ezpublish_legacy
23 | bundle/Command
24 | bundle/Resources
25 | bundle/vendor
26 | bundle/update
27 | bundle/extension
28 | bundle/Core/FieldType/RemoteMedia/SearchField.php
29 | bundle/RemoteMedia/Provider/Cloudinary/Gateway/CachedGateway.php
30 | bundle/RemoteMedia/Helper.php
31 | bundle/NetgenRemoteMediaBundle.php
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/tests/Core/FieldType/RemoteMedia/InputValueTest.php:
--------------------------------------------------------------------------------
1 | 'test/path/image.jpg',
23 | 'alt_text' => 'Test alt text',
24 | 'caption' => 'Test caption',
25 | 'variations' => [],
26 | ];
27 |
28 | $inputValue = new InputValue($parameters);
29 |
30 | self::assertEquals(json_encode($parameters), (string) $inputValue);
31 | }
32 |
33 | public function testConstructionWithoutParameters()
34 | {
35 | $expectedResponseArray = [
36 | 'input_uri' => null,
37 | 'alt_text' => '',
38 | 'caption' => '',
39 | 'variations' => [],
40 | ];
41 |
42 | $inputValue = new InputValue();
43 |
44 | self::assertEquals(json_encode($expectedResponseArray), (string) $inputValue);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/tests/Core/FieldType/RemoteMedia/VariationTest.php:
--------------------------------------------------------------------------------
1 | 'test/path/image.jpg',
23 | 'width' => '150',
24 | 'height' => '200',
25 | 'coords' => [
26 | 'x' => 20,
27 | 'y' => 30,
28 | ],
29 | ];
30 |
31 | $variation = new Variation($parameters);
32 |
33 | self::assertEquals(json_encode($parameters), (string) $variation);
34 | }
35 |
36 | public function testConstructionWithoutParameters()
37 | {
38 | $expectedResponseArray = [
39 | 'url' => null,
40 | 'width' => null,
41 | 'height' => null,
42 | 'coords' => [
43 | 'x' => 0,
44 | 'y' => 0,
45 | ],
46 | ];
47 |
48 | $variation = new Variation();
49 |
50 | self::assertEquals(json_encode($expectedResponseArray), (string) $variation);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/Core/Persistence/Legacy/Content/FieldValue/Converter/RemoteMediaConverterTest.php:
--------------------------------------------------------------------------------
1 | converter = new RemoteMediaConverter();
27 | }
28 |
29 | public function testInstanceOfConverter()
30 | {
31 | self::assertInstanceOf(Converter::class, $this->converter);
32 | }
33 |
34 | public function testGetIndexColumn()
35 | {
36 | self::assertEquals('data_text', $this->converter->getIndexColumn());
37 | }
38 |
39 | public function testCreate()
40 | {
41 | self::assertEquals($this->converter, RemoteMediaConverter::create());
42 | }
43 |
44 | public function testToStorageValue()
45 | {
46 | $fieldValue = new FieldValue(
47 | [
48 | 'data' => 'data',
49 | ]
50 | );
51 |
52 | $storageFieldValue = new StorageFieldValue();
53 |
54 | $this->converter->toStorageValue($fieldValue, $storageFieldValue);
55 | self::assertEquals($storageFieldValue->dataText, json_encode($fieldValue->data));
56 | }
57 |
58 | public function testToFieldValue()
59 | {
60 | $storageFieldValue = new StorageFieldValue(
61 | [
62 | 'dataText' => 'data',
63 | ]
64 | );
65 |
66 | $fieldValue = new FieldValue();
67 |
68 | $this->converter->toFieldValue($storageFieldValue, $fieldValue);
69 | self::assertEquals($fieldValue->data, json_decode($storageFieldValue->dataText, true));
70 | }
71 |
72 | public function testToStorageFieldDefinition()
73 | {
74 | $fieldDefinition = new FieldDefinition();
75 | $storageFieldDefinition = new StorageFieldDefinition();
76 |
77 | self::assertNull($this->converter->toStorageFieldDefinition($fieldDefinition, $storageFieldDefinition));
78 | }
79 |
80 | public function testToFieldDefinition()
81 | {
82 | $storageFieldDefinition = new StorageFieldDefinition();
83 | $fieldDefinition = new FieldDefinition();
84 |
85 | self::assertNull($this->converter->toFieldDefinition($storageFieldDefinition, $fieldDefinition));
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/tests/DependencyInjection/Compiler/XslRegisterPassTest.php:
--------------------------------------------------------------------------------
1 | 'test/test1.xsl',
22 | 'priority' => 0,
23 | ],
24 | ];
25 | $testXslConfig = [
26 | [
27 | 'path' => 'test/test.xsl',
28 | 'priority' => 5000,
29 | ],
30 | ];
31 |
32 | $expectedInjectedParameter = [
33 | 'path' => str_replace('tests/', 'bundle/', __DIR__) . '/../../Resources/xsl/ezxml_ngremotemedia.xsl',
34 | 'priority' => 5000,
35 | ];
36 |
37 | $expectedXslConfig = array_merge($testXslConfig, [$expectedInjectedParameter]);
38 |
39 | $this->setParameter('ezsettings.default.fieldtypes.ezxml.custom_xsl', $testXslConfigDefault);
40 | $this->setParameter('ezpublish.siteaccess.list', $siteaccessList);
41 |
42 | foreach ($siteaccessList as $siteaccess) {
43 | $this->setParameter('ezsettings.' . $siteaccess . '.fieldtypes.ezxml.custom_xsl', $testXslConfig);
44 | }
45 |
46 | $this->compile();
47 |
48 | foreach ($siteaccessList as $siteaccess) {
49 | $this->assertContainerBuilderHasParameter('ezsettings.' . $siteaccess . '.fieldtypes.ezxml.custom_xsl', $expectedXslConfig);
50 | }
51 | }
52 |
53 | public function testCompilerPassWithoutExistingXslConfig()
54 | {
55 | $siteaccessList = ['siteacc1', 'siteacc2'];
56 |
57 | $this->setParameter('ezpublish.siteaccess.list', $siteaccessList);
58 |
59 | $this->compile();
60 |
61 | // Avoid detecting risky tests
62 | self::assertTrue(true);
63 | }
64 |
65 | protected function registerCompilerPass(ContainerBuilder $container)
66 | {
67 | $container->addCompilerPass(new XslRegisterPass());
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/tests/DependencyInjection/NetgenRemoteMediaExtensionTest.php:
--------------------------------------------------------------------------------
1 | setParameter('kernel.bundles', []);
15 | $this->load();
16 |
17 | $this->assertContainerBuilderHasParameter('netgen_remote_media.parameters.testprovider.account_name', 'testname');
18 | $this->assertContainerBuilderHasParameter('netgen_remote_media.parameters.testprovider.account_key', 'testkey');
19 | $this->assertContainerBuilderHasParameter('netgen_remote_media.parameters.testprovider.account_secret', 'testsecret');
20 | $this->assertContainerBuilderHasParameter('netgen_remote_media.remove_unused_resources', false);
21 |
22 | $this->assertContainerBuilderHasAlias('netgen_remote_media.provider', 'netgen_remote_media.provider.testprovider');
23 | }
24 |
25 | /**
26 | * @expectedException \InvalidArgumentException
27 | */
28 | public function testWithoutProviderParameter()
29 | {
30 | $this->load(['provider' => null]);
31 | }
32 |
33 | protected function getContainerExtensions()
34 | {
35 | return [
36 | new NetgenRemoteMediaExtension(),
37 | ];
38 | }
39 |
40 | protected function getMinimalConfiguration()
41 | {
42 | return [
43 | 'provider' => 'testprovider',
44 | 'account_name' => 'testname',
45 | 'account_key' => 'testkey',
46 | 'account_secret' => 'testsecret',
47 | 'system' => [
48 | 'default' => [
49 | 'image_variations' => [
50 | 'ng_frontpage' => [
51 | 'small' => [
52 | 'transformations' => [
53 | 'name' => ['Crop'],
54 | 'params' => [200, 200],
55 | ],
56 | ],
57 | ],
58 | ],
59 | ],
60 | ],
61 | ];
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tests/Entity/RemoteMediaFieldLinkTest.php:
--------------------------------------------------------------------------------
1 | entity = new RemoteMediaFieldLink();
20 | parent::setUp();
21 | }
22 |
23 | public function testSettersAndGetters()
24 | {
25 | $this->entity
26 | ->setContentId(42)
27 | ->setFieldId(24)
28 | ->setVersionId(1)
29 | ->setResourceId('test')
30 | ->setProvider('testprovider');
31 |
32 | self::assertEquals(42, $this->entity->getContentId());
33 | self::assertEquals(24, $this->entity->getFieldId());
34 | self::assertEquals(1, $this->entity->getVersionId());
35 | self::assertEquals('test', $this->entity->getResourceId());
36 | self::assertEquals('testprovider', $this->entity->getProvider());
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/Exception/MimeCategoryParseExceptionTest.php:
--------------------------------------------------------------------------------
1 | value = new Value(
20 | [
21 | 'resourceId' => 'testId',
22 | 'url' => 'http://cloudinary.com/some/url',
23 | 'secure_url' => 'https://cloudinary.com/some/url',
24 | 'variations' => [
25 | 'small' => [
26 | 'x' => 10,
27 | 'y' => 10,
28 | 'w' => 300,
29 | 'h' => 200,
30 | ],
31 | ],
32 | ]
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/CropTest.php:
--------------------------------------------------------------------------------
1 | crop = new Crop();
21 | }
22 |
23 | public function testCrop()
24 | {
25 | self::assertEquals(
26 | [
27 | [
28 | 'x' => 10,
29 | 'y' => 10,
30 | 'width' => 300,
31 | 'height' => 200,
32 | 'crop' => 'crop',
33 | ],
34 | ],
35 | $this->crop->process($this->value, 'small')
36 | );
37 | }
38 |
39 | public function testCropVariationDoesNotExist()
40 | {
41 | $this->expectException(TransformationHandlerFailedException::class);
42 |
43 | $this->crop->process($this->value, 'large');
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/EffectTest.php:
--------------------------------------------------------------------------------
1 | effect = new Effect();
21 | }
22 |
23 | public function testEffectSimple()
24 | {
25 | self::assertEquals(
26 | [
27 | 'effect' => 'grayscale',
28 | ],
29 | $this->effect->process($this->value, 'small', ['grayscale'])
30 | );
31 | }
32 |
33 | public function testEffect()
34 | {
35 | self::assertEquals(
36 | [
37 | 'effect' => 'saturation:50',
38 | ],
39 | $this->effect->process($this->value, 'small', ['saturation', '50'])
40 | );
41 | }
42 |
43 | public function testCropVariationDoesNotExist()
44 | {
45 | $this->expectException(TransformationHandlerFailedException::class);
46 |
47 | $this->effect->process($this->value, 'large');
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/FillTest.php:
--------------------------------------------------------------------------------
1 | fill = new Fill();
20 | }
21 |
22 | public function testFillSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'fill'],
26 | $this->fill->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testFillWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'fill',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->fill->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/FitTest.php:
--------------------------------------------------------------------------------
1 | fit = new Fit();
20 | }
21 |
22 | public function testFitSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'fit'],
26 | $this->fit->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testFitWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'fit',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->fit->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/FormatTest.php:
--------------------------------------------------------------------------------
1 | format = new Format();
21 | }
22 |
23 | public function testFormat()
24 | {
25 | self::assertEquals(
26 | ['fetch_format' => 'png'],
27 | $this->format->process($this->value, 'png_format', ['png'])
28 | );
29 | }
30 |
31 | public function testMissingFormatConfiguration()
32 | {
33 | $this->expectException(TransformationHandlerFailedException::class);
34 |
35 | $this->format->process($this->value, 'png_format');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/LfillTest.php:
--------------------------------------------------------------------------------
1 | lfill = new Lfill();
20 | }
21 |
22 | public function testLfillSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'lfill'],
26 | $this->lfill->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testLfillWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'lfill',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->lfill->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/LimitTest.php:
--------------------------------------------------------------------------------
1 | limit = new Limit();
20 | }
21 |
22 | public function testLimitSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'limit'],
26 | $this->limit->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testLimitWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'limit',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->limit->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/LpadTest.php:
--------------------------------------------------------------------------------
1 | lpad = new Lpad();
20 | }
21 |
22 | public function testLpadSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'lpad'],
26 | $this->lpad->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testLpadWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'lpad',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->lpad->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 |
42 | public function testLpadWithDimensionsAndColour()
43 | {
44 | self::assertEquals(
45 | [
46 | 'crop' => 'lpad',
47 | 'width' => 100,
48 | 'height' => 200,
49 | 'background' => 'red',
50 | ],
51 | $this->lpad->process($this->value, 'small', [100, 200, 'red'])
52 | );
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/MfitTest.php:
--------------------------------------------------------------------------------
1 | mfit = new Mfit();
20 | }
21 |
22 | public function testMfitSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'mfit'],
26 | $this->mfit->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testMfitWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'mfit',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->mfit->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/MpadTest.php:
--------------------------------------------------------------------------------
1 | mpad = new Mpad();
20 | }
21 |
22 | public function testMpadSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'mpad'],
26 | $this->mpad->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testMpadWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'mpad',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->mpad->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/NamedTransformationTest.php:
--------------------------------------------------------------------------------
1 | namedTransformation = new NamedTransformation();
21 | }
22 |
23 | public function testNamedTransformation()
24 | {
25 | self::assertEquals(
26 | ['transformation' => 'thisIsNamedTransformation'],
27 | $this->namedTransformation->process($this->value, 'named', ['thisIsNamedTransformation'])
28 | );
29 | }
30 |
31 | public function testMissingNamedTransformationConfiguration()
32 | {
33 | $this->expectException(TransformationHandlerFailedException::class);
34 |
35 | $this->namedTransformation->process($this->value, 'named');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/PadTest.php:
--------------------------------------------------------------------------------
1 | pad = new Pad();
20 | }
21 |
22 | public function testPadSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'pad'],
26 | $this->pad->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testPadWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'pad',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->pad->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 |
42 | public function testPadWithDimensionsAndColour()
43 | {
44 | self::assertEquals(
45 | [
46 | 'crop' => 'pad',
47 | 'width' => 100,
48 | 'height' => 200,
49 | 'background' => 'red',
50 | ],
51 | $this->pad->process($this->value, 'small', [100, 200, 'red'])
52 | );
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/QualityTest.php:
--------------------------------------------------------------------------------
1 | quality = new Quality();
21 | }
22 |
23 | public function testQualitySimple()
24 | {
25 | self::assertEquals(
26 | ['quality' => 80],
27 | $this->quality->process($this->value, 'test', [80])
28 | );
29 | }
30 |
31 | public function testQualityWithAutoType()
32 | {
33 | self::assertEquals(
34 | [
35 | 'quality' => 'auto:best',
36 | ],
37 | $this->quality->process($this->value, 'test', ['auto', 'best'])
38 | );
39 | }
40 |
41 | public function testQualityWithNonAutoType()
42 | {
43 | $this->expectException(TransformationHandlerFailedException::class);
44 |
45 | $this->quality->process($this->value, 'test', ['test', 'best']);
46 | }
47 |
48 | public function testMissingNamedTransformationConfiguration()
49 | {
50 | $this->expectException(TransformationHandlerFailedException::class);
51 |
52 | $this->quality->process($this->value, 'test');
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/ResizeTest.php:
--------------------------------------------------------------------------------
1 | resize = new Resize();
21 | }
22 |
23 | public function testResizeWithDimensions()
24 | {
25 | self::assertEquals(
26 | [
27 | 'width' => 100,
28 | 'height' => 200,
29 | ],
30 | $this->resize->process($this->value, 'small', [100, 200])
31 | );
32 | }
33 |
34 | public function testMissingResizeConfiguration()
35 | {
36 | $this->expectException(TransformationHandlerFailedException::class);
37 |
38 | $this->resize->process($this->value, 'named');
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Provider/Cloudinary/TransformationHandler/ScaleTest.php:
--------------------------------------------------------------------------------
1 | scale = new Scale();
20 | }
21 |
22 | public function testScaleSimple()
23 | {
24 | self::assertEquals(
25 | ['crop' => 'scale'],
26 | $this->scale->process($this->value, 'small')
27 | );
28 | }
29 |
30 | public function testScaleWithDimensions()
31 | {
32 | self::assertEquals(
33 | [
34 | 'crop' => 'scale',
35 | 'width' => 100,
36 | 'height' => 200,
37 | ],
38 | $this->scale->process($this->value, 'small', [100, 200])
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/Transformation/RegistryTest.php:
--------------------------------------------------------------------------------
1 | registry = new Registry();
30 |
31 | $this->cropTransformation = new Crop();
32 | $this->resizeTransformation = new Resize();
33 | $this->otherProviderCropTransformation = new Fit();
34 |
35 | $this->registry->addHandler('cloudinary', 'crop', $this->cropTransformation);
36 | $this->registry->addHandler('cloudinary', 'resize', $this->resizeTransformation);
37 | $this->registry->addHandler('otherprovider', 'crop', $this->otherProviderCropTransformation);
38 | }
39 |
40 | public function testGetHandler()
41 | {
42 | self::assertEquals(
43 | $this->cropTransformation,
44 | $this->registry->getHandler('crop', 'cloudinary')
45 | );
46 | }
47 |
48 | public function testNoHandler()
49 | {
50 | $this->expectException(TransformationHandlerNotFoundException::class);
51 |
52 | $this->registry->getHandler('cloudinary', 'something');
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/RemoteMedia/UploadFileTest.php:
--------------------------------------------------------------------------------
1 | uri());
21 | self::assertEquals('image', $uploadFile->originalFilename());
22 | self::assertEquals('jpg', $uploadFile->originalExtension());
23 | }
24 |
25 | public function testFromZHTTPFile(): void
26 | {
27 | $eZHTTPFile = new eZHTTPFile(
28 | 'upload_image',
29 | [
30 | 'name' => 'image.jpg',
31 | 'type' => 'image/jpg',
32 | 'tmp_name' => 'oji939i.jpg',
33 | 'size' => 100,
34 | ]
35 | );
36 |
37 | $uploadFile = UploadFile::fromZHTTPFile($eZHTTPFile);
38 |
39 | self::assertEquals('oji939i.jpg', $uploadFile->uri());
40 | self::assertEquals('image', $uploadFile->originalFilename());
41 | self::assertEquals('jpg', $uploadFile->originalExtension());
42 | }
43 |
44 | public function testFromUploadedFile(): void
45 | {
46 | $uri = '/var/www/remote-media/image.jpg';
47 |
48 | $fileMock = $this->createMock(UploadedFile::class);
49 |
50 | $fileMock
51 | ->expects(self::once())
52 | ->method('getRealPath')
53 | ->willReturn($uri);
54 |
55 | $fileMock
56 | ->expects(self::once())
57 | ->method('getClientOriginalName')
58 | ->willReturn('image');
59 |
60 | $fileMock
61 | ->expects(self::once())
62 | ->method('getClientOriginalExtension')
63 | ->willReturn('jpg');
64 |
65 | $uploadFile = UploadFile::fromUploadedFile($fileMock);
66 |
67 | self::assertEquals($uri, $uploadFile->uri());
68 | self::assertEquals('image', $uploadFile->originalFilename());
69 | self::assertEquals('jpg', $uploadFile->originalExtension());
70 | }
71 |
72 | public function testFromEzImageValue(): void
73 | {
74 | $webRoot = '/var/www/remote-media';
75 | $uri = '/image.jpg';
76 |
77 | $value = new Value([
78 | 'uri' => $uri,
79 | 'fileName' => 'image.jpg',
80 | ]);
81 |
82 | $uploadFile = UploadFile::fromEzImageValue($value, $webRoot);
83 |
84 | self::assertEquals($webRoot . $uri, $uploadFile->uri());
85 | self::assertEquals('image', $uploadFile->originalFilename());
86 | self::assertEquals('jpg', $uploadFile->originalExtension());
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/tests/Templating/Converter/RemoteMediaValueConverterTest.php:
--------------------------------------------------------------------------------
1 | converter = new RemoteMediaValueConverter();
18 | }
19 |
20 | public function testConvert()
21 | {
22 | $object = new Value();
23 |
24 | self::assertEquals($object, $this->converter->convert($object));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/travis.php.ini:
--------------------------------------------------------------------------------
1 | [PHP]
2 |
3 | memory_limit = 5G
4 |
--------------------------------------------------------------------------------
/update/database/migrate-data_text4-to-data_text5.sql:
--------------------------------------------------------------------------------
1 | UPDATE ezcontentclass_attribute SET data_text5=data_text4 where data_type_string= 'ngremotemedia';
2 |
3 |
--------------------------------------------------------------------------------