{"id":19640577,"url":"https://github.com/daniel-km/omeka-s-module-common","last_synced_at":"2026-05-04T11:03:33.537Z","repository":{"id":218085344,"uuid":"745554692","full_name":"Daniel-KM/Omeka-S-module-Common","owner":"Daniel-KM","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-22T06:48:12.000Z","size":605,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-22T08:34:13.501Z","etag":null,"topics":["development","omeka-s","omeka-s-module"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cecill-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Daniel-KM.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.en.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-01-19T15:36:09.000Z","updated_at":"2026-04-22T06:48:16.000Z","dependencies_parsed_at":"2024-02-28T12:25:00.788Z","dependency_job_id":"fc4fb0f1-397d-4b4c-8c09-3acb1fe0fdf4","html_url":"https://github.com/Daniel-KM/Omeka-S-module-Common","commit_stats":null,"previous_names":["daniel-km/omeka-s-module-common"],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/Daniel-KM/Omeka-S-module-Common","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Daniel-KM%2FOmeka-S-module-Common","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Daniel-KM%2FOmeka-S-module-Common/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Daniel-KM%2FOmeka-S-module-Common/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Daniel-KM%2FOmeka-S-module-Common/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Daniel-KM","download_url":"https://codeload.github.com/Daniel-KM/Omeka-S-module-Common/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Daniel-KM%2FOmeka-S-module-Common/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32604587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["development","omeka-s","omeka-s-module"],"created_at":"2024-11-11T14:06:10.996Z","updated_at":"2026-05-04T11:03:33.531Z","avatar_url":"https://github.com/Daniel-KM.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"Common Module (module for Omeka S)\n===================================\n\n\u003e __New versions of this module and support for Omeka S version 3.0 and above\n\u003e are available on [GitLab], which seems to respect users and privacy better\n\u003e than the previous repository.__\n\n\n[Common Module] is a module for [Omeka S] that allows to manage internal\nfeatures used in various modules: bulk functions, form elements, view helpers,\none-time tasks for install and settings, etc., so it avoids the developer to\ncopy-paste common code between modules.\n\n- Services, view helpers and controller plugins\n\n  - AssetUrl for internal assets\n  - DefaultSite\n  - DeferredJobDispatch, to run multiple individual jobs in bulk\n  - EasyMeta to get ids, terms and labels from properties, classes, templates,\n    vocabularies; to get main data types too (literal, resource or uri); to get\n    resource api names from any names used in Omeka and modules.\n  - IsHomePage\n  - IsHtml\n  - IsXml\n  - JSend to manage exchanges between a module and js part.\n  - MatchedRouteName\n  - SendEmail to send email with default values, in particular sender.\n  - PrepareMessage to validate and fill messages with placeholders.\n  - SpecifyMediaType\n\n- Form elements\n\n  - SendMessageForm (base form for sending messages with placeholders)\n  - Array Text\n  - Custom Vocab MultiCheckbox\n  - Custom Vocab Radio\n  - Custom Vocab Select\n  - Custom Vocabs Select\n  - Data Textarea\n  - Data Type Select\n  - Group Textarea\n  - Ini Textarea\n  - Note\n  - Media Ingester Select\n  - Media Renderer Select\n  - Media Type Select\n  - Sites Page Select\n  - Optional Checkbox\n  - Optional Date\n  - Optional DateTime\n  - Optional Multi Checkbox\n  - Optional Number\n  - Optional Radio\n  - Optional Select\n  - Optional Url\n  - Optional Item Set Select\n  - Optional Property Select\n  - Optional Resource Select\n  - Optional Resource Class Select\n  - Optional Resource Template Select\n  - Optional Role Select\n  - Optional Site Select\n  - Optional User Select\n  - Url Query\n\n- [PSR-3]\n\n  - The logger can log messages in a standard, simple and translatable way.\n  - The class PsrMessage extends core `\\Omeka\\Stdlib\\PsrMessage` since Omeka S 4.2,\n    with translator awareness, PSR-3 and sprintf support. A polyfill is provided\n    for version before Omeka S 4.2.\n\n- One-Time tasks\n\n  Internally, the logic is \"config over code\": so all settings have just to be\n  set in the main `config/module.config.php` file, inside a key with the\n  lowercas emodule name, with sub-keys `config`, `settings`, `site_settings`,\n  `user_settings` and `block_settings`. All the forms have just to be standard\n  Laminas forms.\n\n  Eventual install and uninstall sql can be set in `data/install/` and upgrade\n  code in `data/scripts`. Another class allows to check and install resources\n  (vocabularies, resource templates, custom vocabs, etc.).\n\n- Improved media type detection\n\n  In many cases, in particular with xml or json, the media type should be\n  refined to make features working. For example `text/xml` is not precise enough\n  for the module IiifServer to manage xml ocr alto files, that should be\n  identified with the right media type `application/alto+xml`. The same issue\n  occurs with xml mets, tei, json-ld, etc. Main formats for 3d files are managed.\n\n- Internal assets\n\n  By default, only external assets can be overridden in themes. This option in\n  the config file allows to by-pass core assets. This is useful mainly for js in\n  admin interface.\n\n- Data base index\n\n  To improve performance of common queries, some indices are added in database:\n\n  - fulltext_search: is_public\n  - media: ingester\n  - media: renderer\n  - media: media_type\n  - media: extension\n  - resource: resource_type\n  - resource: idx_type_created (resource_type, created)\n  - resource: idx_type_modified (resource_type, modified)\n  - value: type\n  - value: lang\n  - value: idx_property_value (property_id, value (190))\n  - session: modified\n\n\nInstallation\n------------\n\nSee general end user documentation for [installing a module].\n\n**IMPORTANT**: As long as [PR #2412] is not merged, use the Zip method or use\nversion 3.4.76.\n\n* With composer (recommended, requires Omeka S with [PR #2412])\n\nFrom the root of Omeka S, install the module:\n\n```sh\ncomposer require daniel-km/omeka-s-module-common\n```\n\nThe module is automatically downloaded in `composer-addons/modules/` and ready to\nbe enabled in the admin interface.\n\n* From the zip\n\nDownload the last release [Common.zip] from the list of releases, and uncompress\nit in the `modules` directory.\n\n* From the sources and for development\n\nInstall the sources in directory `modules`, rename the directory as `Common`, go\nto the root of the module, run composer install, then :\n\n```sh\ncd modules\ngit clone https://gitlab.com/Daniel-KM/Omeka-S-module-Common.git Common\ncd Common\ncomposer install --no-dev\nphp ../../application/data/scripts/install-omeka-assets.php Common\n```\n\n* For test\n\nThe module includes a comprehensive test suite with unit and functional tests.\nRun them from the root of Omeka:\n\n```sh\nvendor/bin/phpunit -c modules/Common/phpunit.xml --testdox\n```\n\n\nUsage (for developer)\n---------------------\n\n### Services, controller plugins and view helpers\n\n#### Api Adapter: Simple and complete query builder\n\nJust add the trait `CommonAdapterTrait`, the list of query arguments for all\ncommon queries and a call to `buildQueryFields()`. Then, all queries will work,\nincluding queries with empty or multiple values and use of operators `\u003c≤=≠≥\u003e`.\n\n#### Api Adapter: Simple hydrator\n\nJust add the trait `CommonAdapterTrait` and it will automatically manage the\nmethod `hydrate()` in a generic way, as long as the entity methods and the keys\nused in the api or the form are compatible.\n\n#### AssetUrl\n\nUse helper assetUrl().\n\n#### DefaultSite\n\nUse helper defaultSite(). As argument, you may set id, slug, id_slug or slug_id.\nThe default is to return the representation.\n\n#### Deferred Job Dispatch\n\nSome modules run a job each time an item or a media is saved, in particular in\nbatch processes, and it implies multiple parallel jobs that are not consistent\nor that overloads server. Furthermore, flushing entity inside an api event may\ntrigger a global flush that conflicts with pending entities in the doctrine\nUnitOfWork.\n\nTo avoid this issue, use the service `Common\\DeferredJobDispatch` in order to\nsend all resource ids to the job as a single request and dispatch them once at\nshutdown. So the service can be used in a module event listener like that:\n\n```php\n$deferred = $services-\u003eget('Common\\DeferredJobDispatch');\n$deferred-\u003edefer(\n    \\MyModule\\Job\\MyJob::class,\n    'job_key',\n    ['item_ids' =\u003e $itemId]\n);\n```\n\nAt shutdown, one job per unique job key is dispatched, with all accumulated\nparams merged via the optional callback set as fourth argument.\n\nReal life implementation can be seen in modules [Bulk Import], [Derivative Media],\n[Easy Admin], [Iiif Server], or [Image Server].\n\n#### EasyMeta\n\nThis service can be used as helper or plugin. It allows to get ids, terms and\nlabels from properties, classes, templates, vocabularies; to get main data types\ntoo (literal, resource or uri); to get resource api names from any names used in\nOmeka and modules.\n\nTo get methods and more details, use the autocompletion of your IDE.\n\n#### IsHomePage\n\nThis view helper allows to check if the current page is the home page.\n\n#### IsHtml\n\nThis view helper allows to check if a string is html, in particular to know if\nit should be escaped or not.\n\nThe check is a basic one: the string should start with a \"\u003c\", end with a \"\u003e\" and\nwithout tags. It may be a partial html. It is not possible to get a more precise\ncheck before php 8.4.\n\n#### IsXml\n\nThis view helper allows to check if a string is xml, in particular to know if\nit should be escaped or not.\n\nThe check is a full one: the string should start with a \"\u003c\", end with a \"\u003e\" and\nshould be parsable via SimpleXml. It may be a partial xml.\n\n#### jSend\n\nThe plugin jSend() allows to output a JsonModel formatted as [jSend] to simplify\nexchanges with a third party or with a module that use some ajax, like [Contact Us],\n[Contribute], [Selection], [Two Factor Authentication], etc.\n\nUnlike [jSend], any response can have a status, data, a message and a code.\nSome values are filled automatically from the messenger.\n\n#### Messages\n\nThe method `getTranslatedMessages()` allows to get all translated messages as\narray. It can be used for a json output.\n\nThe method `log()` allows to convert all messages into logs, for example to\nmanage background jobs and keep track of front-end messages of errors of some\nmodules.\n\n#### Messenger\n\nThis is a fix on the core messenger: A form with any number of levels of\nsub-messages can be managed.\n\n#### MatchedRouteName\n\nAllow to get the matched route name directly.\n\n#### Note\n\n`Note` is a form element to display explication inside forms. It is a simplified\nversion of feature from Zend 1 that was not ported to Zend 3/Laminas. It was\nimplemented in some modules.\n\n#### SendEmail\n\nAllow to send an email. All arguments are optional, except the body. The sender\nis the no-reply email of the module [Easy Admin] by default, else the\nadminstrator email defined in main setting.\n\nA minimal antispam check is applied via keywords listed in `/data/mailer/spam_keywords.php`.\nFor improved checks, install module [Bot Guard].\n\n#### SendFile\n\nSend a file for download, without limit of size or memory, via a stream.\nThe content disposition can be set via the parameters of via the query (download=1 for attachment, else inline).\n\n#### PrepareMessage\n\nThis controller plugin provides helper functions for preparing messages with\nvalidation and placeholder support. It is designed to be used with modules like\n[Contact Us], [Contribute], and [Selection].\n\nFeatures:\n- Validate message body and subject with configurable max lengths\n- Fill messages with placeholders using moustache-style syntax (`{placeholder}`)\n- Common placeholders are automatically available\n- Extensible placeholder system for module-specific values\n\nCommon placeholders:\n- `{ip}`: Client IP address\n- `{main_title}`: Installation title\n- `{main_url}`: Main URL\n- `{site_title}`: Current site title\n- `{site_url}`: Current site URL\n- `{site_slug}`: Current site slug\n- `{user_name}`: Current user name\n- `{user_email}`: Current user email\n- `{owner_name}`: Owner/recipient name\n- `{owner_email}`: Owner/recipient email\n- `{resource_id}`: Resource ID\n- `{resource_title}`: Resource title\n- `{resource_url}`: Resource public URL\n- `{resource_url_admin}`: Resource admin URL\n\nResource property placeholders (when a resource is in context):\n- `{prefix:localName}`: Value of any resource property (e.g. `{dcterms:title}`,\n  `{dcterms:creator}`, `{dcterms:date}`). The first value is used if multiple\n  values exist for the property.\n\nUsage in a controller:\n\n```php\n// Validate message body.\n$result = $this-\u003eprepareMessage()-\u003evalidateBody($body);\nif (!$result['valid']) {\n    // Handle error: $result['error']\n}\n\n// Validate message subject.\n$result = $this-\u003eprepareMessage()-\u003evalidateSubject($subject);\n\n// Fill a message template with placeholders.\n$message = $this-\u003eprepareMessage()-\u003efillMessage(\n    'Hello {user_name}, your {resource_title} has been updated.',\n    ['custom_field' =\u003e 'value'],  // Additional placeholders\n    ['site' =\u003e $site, 'user' =\u003e $user, 'resource' =\u003e $resource]  // Context\n);\n\n// Add custom placeholders for all subsequent calls.\n$this-\u003eprepareMessage()\n    -\u003eaddPlaceholders(['custom_key' =\u003e 'custom_value'])\n    -\u003efillMessage($template);\n\n// Get default subject from settings with fallback.\n$subject = $this-\u003eprepareMessage()-\u003egetDefaultSubject(\n    'mymodule_email_subject',\n    'Default subject for {site_title}',\n    $placeholders,\n    $context\n);\n\n// Process \"myself\" options for cc/bcc/reply-to.\n$cc = $bcc = $replyTo = [];\n$this-\u003eprepareMessage()-\u003eprocessMyselfOptions(\n    ['cc', 'bcc'],  // Values from \"myself\" checkbox\n    $user,\n    $cc,\n    $bcc,\n    $replyTo\n);\n```\n\n#### SendMessageForm\n\nA base form class for sending messages that can be extended by modules.\nIt provides common fields (subject, body) and optional fields (cc, bcc, reply-to,\nresource_id, reject checkbox, \"myself\" multi-checkbox).\n\nForm options:\n- `has_resource_id` (bool): Add a hidden resource_id field\n- `resource_id_name` (string): Name of the resource id field (default: `resource_id`)\n- `has_cc` (bool): Add cc email field\n- `has_bcc` (bool): Add bcc email field\n- `has_reply_to` (bool): Add reply-to email field\n- `has_myself` (bool): Add \"myself\" multi-checkbox for cc/bcc/reply\n- `has_reject` (bool): Add reject checkbox (for moderation workflows)\n- `subject_value` (string): Default value for subject\n- `body_value` (string): Default value for body\n\nUsage in a module:\n\n```php\n// Option 1: Use directly with options.\n$form = $this-\u003egetForm(\\Common\\Form\\SendMessageForm::class);\n$form-\u003esetFormOptions([\n    'has_cc' =\u003e true,\n    'has_bcc' =\u003e true,\n    'has_myself' =\u003e true,\n    'subject_value' =\u003e 'Your contribution',\n    'body_value' =\u003e 'Dear {name}, thank you for your contribution.',\n]);\n$form-\u003einit();\n\n// Option 2: Extend in your module.\nnamespace MyModule\\Form;\n\nuse Common\\Form\\SendMessageForm as BaseSendMessageForm;\n\nclass SendMessageForm extends BaseSendMessageForm\n{\n    protected $formOptions = [\n        'has_resource_id' =\u003e true,\n        'resource_id_name' =\u003e 'contribution_id',\n        'has_cc' =\u003e true,\n        'has_myself' =\u003e true,\n        'has_reject' =\u003e true,\n    ];\n\n    public function init(): void\n    {\n        parent::init();\n        // Add custom fields here.\n    }\n}\n```\n\n#### SpecifyMediaType\n\nGet the right media type of a file, even if it is a generic zipped, json or xml.\nThis helper is used automatically when loading a file via the internal file\nfactory.\n\n### PSR-3\n\n#### Role of PSR-3\n\nThe PHP Framework Interop Group ([PHP-FIG]) represents the majority of php\nframeworks, in particular all main CMS.\n\n[PSR-3] means that the message and its context may be separated in the logs, so\nthey can be translated and managed by any other compliant tools. This is useful\nin particular when an external database is used to store logs.\n\nThe message uses placeholders that are not in C-style of the function `sprintf`\n(`%s`, `%d`, etc.), but in moustache-style, identified with `{` and `}`, without\nspaces.\n\nThe new and old format are automatically managed by the messenger and the\nlogger.\n\nSo, instead of logging like this:\n\n```php\n// Classic logging (not translatable).\n$this-\u003elogger()-\u003einfo(sprintf($message, ...$args));\n$this-\u003elogger()-\u003einfo(sprintf('The %s #%d has been updated.', 'item', 43));\n// output: The item #43 has been updated.\n```\n\nA PSR-3 standard log is:\n\n```php\n// PSR-3 logging.\n$this-\u003elogger()-\u003einfo($message, $context);\n$this-\u003elogger()-\u003einfo(\n    'The {resource} #{id} has been updated.', // @translate\n    ['resource' =\u003e 'item', 'id' =\u003e 43]\n);\n// output: The item #43 has been updated.\n```\n\nIf an Exception object is passed in the context data, it must be in the `exception`\nkey.\n\nBecause the logs are translatable at user level, with a message and context, the\nmessage must not be translated when logging.\n\n#### PSR-3 Message\n\nIf the message may be reused or for the messenger, the helper `PsrMessage()` can\nbe used, with all the values:\n\n```php\n// For logging, it is useless to use PsrMessage, since it is natively supported\n// by the logging.\n$message = new \\Common\\Stdlib\\PsrMessage(\n    'The {resource} #{id} has been updated by user #{userId}.', // @translate\n    ['resource' =\u003e 'item', 'id' =\u003e 43, 'userId' =\u003e $user-\u003eid()]\n);\n$this-\u003elogger()-\u003einfo($message-\u003egetMessage(), $message-\u003egetContext());\necho $message;\n// Or with internal translator (laminas translator style).\necho $message-\u003esetTranslator($translator)-\u003etranslate();\n// With translator (Omeka core style, translator as first argument).\necho $message-\u003etranslate($translator);\n```\n\nSince Omeka S v4.2, the core provides `\\Omeka\\Stdlib\\PsrMessage`, which\nimplements `MessageInterface` and is natively recognized by the core translator\ndelegator. `Common\\Stdlib\\PsrMessage` extends it with additional features:\n\n- TranslatorAwareInterface: set translator then use translate() without args.\n- Variadic constructor: supports both PSR-3 array context and sprintf-style\n  positional arguments for backward compatibility with \\Omeka\\Stdlib\\Message.\n- Polymorphic translate(): accepts TranslatorInterface as first arg (core) or\n  translator interface aware signature (no args).\n\n```php\n// PSR-3 style (recommended):\n$message = new \\Common\\Stdlib\\PsrMessage('Hello {name}', ['name' =\u003e 'World']);\n\n// Sprintf style (backward compatibility with \\Omeka\\Stdlib\\Message):\n$message = new \\Common\\Stdlib\\PsrMessage('Hello %s', 'World');\n```\n\nFor Omeka S \u003c 4.2, a polyfill is provided in `data/compat/` that is loaded\nautomatically.\n\n#### Translator\n\nThe translator to set in PsrMessage() is available through `$this-\u003etranslator()`\nin controller and view.\n\n#### Compatibility\n\n* Compatibility with core\n\n`Common\\Stdlib\\PsrMessage` extends `\\Omeka\\Stdlib\\PsrMessage`, so it implements\n`MessageInterface` and is recognized natively by the core translator delegator,\nthe messenger, and the logger. No special handling is needed.\n\n* Compatibility with messenger\n\nThe helper `messenger()` is compatible and can translate PSR-3 messages.\n\n* Compatibility with the default stream logger\n\nThe PSR-3 messages are converted into simple messages for the default logger.\nOther extra data are appended.\n\n* Compatibility with core messages\n\nThe logger stores the core messages as it, without context, so they can be\ndisplayed. They are not translatable if they use placeholders.\n\n* Compatibility with thrown exceptions\n\nAn exception should not be translated early. Nevertheless, if you really need\nit, you can use:\n\n```php\n# Where `$this-\u003etranslator` is \\Laminas\\I18n\\Translator\\TranslatorInterface or\n# MvcTranslator from services, either:\nthrow new \\RuntimeException($this-\u003etranslator-\u003etranslate($message));\nthrow new \\Exception($message-\u003esetTranslator($this-\u003etranslator)-\u003etranslate());\n```\n\n#### Plural\n\nBy construction, the plural is not managed: only one message is saved in the\nlog. So, if any, the plural message should be prepared before the logging.\n\n### One-time tasks\n\nUnlike old module Generic, there are two ways to get the one-time features\ninside any module: the trait (recommended) or the abstract class (deprecated).\n\nTo use them, replace the following:\n\n```php\nnamespace MyModule;\n\nuse Omeka\\Module\\AbstractModule;\n\nclass Module extends AbstractModule\n{\n}\n```\n\nwith this class with the trait:\n\n```php\nnamespace MyModule;\n\nif (!trait_exists(\\Common\\TraitModule::class, false)) {\n    require_once dirname(__DIR__) . '/Common/src/TraitModule.php';\n}\n\nuse Common\\TraitModule;\nuse Omeka\\Module\\AbstractModule;\n\nclass Module extends AbstractModule\n{\n    const NAMESPACE = __NAMESPACE__;\n\n    use TraitModule;\n}\n```\n\nThe class AbstractModule is still provided, but deprecated. You may extend it:\n\n```php\nif (!class_exists(\\Common\\AbstractModule::class, false)) {\n    require_once dirname(__DIR__) . '/Common/src/AbstractModule.php';\n}\n\nuse Common\\AbstractModule;\n\nclass Module extends AbstractModule\n{\n    const NAMESPACE = __NAMESPACE__;\n}\n```\n\n**Note**: When Common is installed via composer, classes and traits are\nautoloaded via PSR-4 (`Common\\TraitModule`, `Common\\AbstractModule`, etc.). The\n`require_once` with `class_exists()`/`trait_exists()` check ensures backward\ncompatibility with manual (zip) installations in the directory modules/ and is\nneeded during upgrades of module Common. This check will be useless for the next\nmajor upgrade of Omeka.\n\n**WARNING**: with an abstract class, `parent::method()` in the module calls the\nmethod of the abstract class (`Common\\AbstractModule`), but with a trait,\n`parent::method()` is the method of `Omeka\\AbstractModule` if it exists.\nFurthermore, it is not possible to call a method of the trait that is overridden\nby the class Module. This is why there are methods suffixed with \"Auto\" that can\nbe used in such a case.\n\n### Installing resources\n\nTo install resources, the class `ManageModuleAndResources` can be used. It is\ncallable via the module `$this-\u003egetManageModuleAndResources()`. It contains\ntools to manage and update vocabs, custom vocabs, and templates via files\nlocated inside `data/`, that will be automatically imported.\n\n```php\nif (!class_exists(\\Common\\ManageModuleAndResources::class, false)) {\n    require_once dirname(__DIR__) . '/Common/src/ManageModuleAndResources.php';\n}\n```\n\n\nTODO\n----\n\n- [ ] Use key \"psr_log\" instead of \"log\" (see https://docs.laminas.dev/laminas-log/service-manager/#psrloggerabstractadapterfactory).\n- [ ] Use materialized views for EasyMeta?\n\n\nWarning\n-------\n\nUse it at your own risk.\n\nIt’s always recommended to backup your files and your databases and to check\nyour archives regularly so you can roll back if needed.\n\n\nTroubleshooting\n---------------\n\nSee online issues on the [module issues] page on GitLab.\n\n\nLicense\n-------\n\n### Module\n\nThis module is published under the [CeCILL v2.1] license, compatible with\n[GNU/GPL] and approved by [FSF] and [OSI].\n\nIn consideration of access to the source code and the rights to copy, modify and\nredistribute granted by the license, users are provided only with a limited\nwarranty and the software’s author, the holder of the economic rights, and the\nsuccessive licensors only have limited liability.\n\nIn this respect, the risks associated with loading, using, modifying and/or\ndeveloping or reproducing the software by the user are brought to the user’s\nattention, given its Free Software status, which may make it complicated to use,\nwith the result that its use is reserved for developers and experienced\nprofessionals having in-depth computer knowledge. Users are therefore encouraged\nto load and test the suitability of the software as regards their requirements\nin conditions enabling the security of their systems and/or data to be ensured\nand, more generally, to use and operate it in the same conditions of security.\nThis Agreement may be freely reproduced and published, provided it is not\naltered, and that no provisions are either added or removed herefrom.\n\n\n### Libraries\n\n- jQuery-Autocomplete : [MIT]\n\n\nCopyright\n---------\n\n* Copyright Daniel Berthereau, 2017-2026 (see [Daniel-KM] on GitLab)\n* Copyright Tomas Kirda 2017 (library [jQuery-Autocomplete])\n\n\n[Common module]: https://gitlab.com/Daniel-KM/Omeka-S-module-Common\n[Omeka S]: https://omeka.org/s\n[GitLab]: https://gitlab.com/Daniel-KM/Omeka-S-module-Common\n[PSR-3]: http://www.php-fig.org/psr/psr-3\n[PHP-FIG]: http://www.php-fig.org\n[installing a module]: https://omeka.org/s/docs/user-manual/modules/\n[PR #2412]: https://github.com/omeka/omeka-s/pull/2412\n[Common.zip]: https://github.com/Daniel-KM/Omeka-S-module-Common/releases\n[jSend]: https://github.com/omniti-labs/jsend\n[Bot Guard]: https://gitlab.com/Daniel-KM/Omeka-S-module-BotGuard\n[Contact Us]: https://gitlab.com/Daniel-KM/Omeka-S-module-ContactUs\n[Contribute]: https://gitlab.com/Daniel-KM/Omeka-S-module-Contribute\n[Easy Admin]: https://gitlab.com/Daniel-KM/Omeka-S-module-EasyAdmin\n[Selection]: https://gitlab.com/Daniel-KM/Omeka-S-module-Selection\n[Two Factor Authentication]: https://gitlab.com/Daniel-KM/Omeka-S-module-TwoFactAuth\n[Bulk Import]: https://gitlab.com/Daniel-KM/Omeka-S-module-BulkImport\n[Derivative Media]: https://gitlab.com/Daniel-KM/Omeka-S-module-DerivativeMedia\n[Easy Admin]: https://gitlab.com/Daniel-KM/Omeka-S-module-EasyAdmin\n[Iiif Server]: https://gitlab.com/Daniel-KM/Omeka-S-module-IiifServer\n[Image Server]: https://gitlab.com/Daniel-KM/Omeka-S-module-ImageServer\n[jQuery-Autocomplete]: https://github.com/devbridge/jQuery-Autocomplete\n[module issues]: https://gitlab.com/Daniel-KM/Omeka-S-module-Common/-/issues\n[CeCILL v2.1]: https://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html\n[GNU/GPL]: https://www.gnu.org/licenses/gpl-3.0.html\n[FSF]: https://www.fsf.org\n[OSI]: http://opensource.org\n[MIT]: http://opensource.org/licenses/MIT\n[Daniel-KM]: https://gitlab.com/Daniel-KM \"Daniel Berthereau\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaniel-km%2Fomeka-s-module-common","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaniel-km%2Fomeka-s-module-common","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaniel-km%2Fomeka-s-module-common/lists"}