3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 class CRM_Core_BAO_Translation
extends CRM_Core_DAO_Translation
implements \Civi\Core\HookInterface
{
19 use CRM_Core_DynamicFKAccessTrait
;
22 * Get a list of valid statuses for translated-strings.
26 public static function getStatuses() {
28 ['id' => 1, 'name' => 'active', 'label' => ts('Active')],
29 ['id' => 2, 'name' => 'draft', 'label' => ts('Draft')],
34 * Get a list of tables with translatable strings.
37 * Ex: ['civicrm_event' => 'civicrm_event']
39 public static function getEntityTables() {
40 if (!isset(Civi
::$statics[__CLASS__
]['allTables'])) {
41 $tables = array_keys(self
::getTranslatedFields());
42 Civi
::$statics[__CLASS__
]['allTables'] = array_combine($tables, $tables);
44 return Civi
::$statics[__CLASS__
]['allTables'];
48 * Get a list of fields with translatable strings.
51 * Ex: ['title' => 'title', 'description' => 'description']
53 public static function getEntityFields() {
54 if (!isset(Civi
::$statics[__CLASS__
]['allFields'])) {
56 foreach (self
::getTranslatedFields() as $columns) {
57 foreach ($columns as $column => $sqlExpr) {
58 $allFields[$column] = $column;
61 Civi
::$statics[__CLASS__
]['allFields'] = $allFields;
63 return Civi
::$statics[__CLASS__
]['allFields'];
68 * List of data fields to translate, organized by table and column.
69 * Omitted/unlisted fields are not translated. Any listed field may be translated.
70 * Values should be TRUE.
71 * Ex: $fields['civicrm_event']['summary'] = TRUE
73 public static function getTranslatedFields() {
74 $key = 'translatedFields';
75 $cache = Civi
::cache('fields');
76 if (($r = $cache->get($key)) !== NULL) {
81 \CRM_Utils_Hook
::translateFields($f);
83 // Future: Assimilate defaults originating in XML (incl extension-entities)
84 // e.g. CRM_Core_I18n_SchemaStructure::columns() will grab core fields
86 $cache->set($key, $f);
91 * When manipulating strings via the `Translation` entity (APIv4), ensure that the references are well-formed.
93 * @param \Civi\Api4\Event\ValidateValuesEvent $e
95 public static function self_civi_api4_validate(\Civi\Api4\Event\ValidateValuesEvent
$e) {
96 $statuses = array_column(self
::getStatuses(), 'id');
97 $dataTypes = [CRM_Utils_Type
::T_STRING
, CRM_Utils_Type
::T_TEXT
, CRM_Utils_Type
::T_LONGTEXT
];
98 $htmlTypes = ['Text', 'TextArea', 'RichTextEditor', ''];
100 foreach ($e->records
as $r => $record) {
101 if (array_key_exists('status_id', $record) && !in_array($record['status_id'], $statuses)) {
102 $e->addError($r, 'status_id', 'invalid', ts('Invalid status'));
105 $entityIdFields = ['entity_table', 'entity_field', 'entity_id'];
106 $entityIdCount = (empty($record['entity_table']) ?
0 : 1)
107 +
(empty($record['entity_field']) ?
0 : 1)
108 +
(empty($record['entity_id']) ?
0 : 1);
109 if ($entityIdCount === 0) {
112 elseif ($entityIdCount < 3) {
113 $e->addError($r, $entityIdFields, 'full_entity', ts('Must specify all entity identification fields'));
116 $simpleName = '/^[a-zA-Z0-9_]+$/';
117 if (!preg_match($simpleName, $record['entity_table']) ||
!preg_match($simpleName, $record['entity_field']) ||
!is_numeric($record['entity_id'])) {
118 $e->addError($r, $entityIdFields, 'malformed_entity', ts('Entity reference is malformed'));
122 // Which fields support translation?
123 // - One could follow the same path as "Multilingual". Use
124 // $translatable = CRM_Core_I18n_SchemaStructure::columns();
125 // if (!isset($translatable[$record['entity_table']][$record['entity_field']])) {
126 // - Or, since we don't need schema-changes, we could be more generous and allow all freeform text fields...
128 $daoClass = CRM_Core_DAO_AllCoreTables
::getClassForTable($record['entity_table']);
130 $e->addError($r, 'entity_table', 'bad_table', ts('Entity reference specifies a non-existent or non-translatable table'));
134 $dao = new $daoClass();
135 $dao->id
= $record['entity_id'];
137 $field = $dao->getFieldSpec($record['entity_field']);
138 if (!$field ||
!in_array($field['type'] ??
'', $dataTypes) ||
!in_array($field['html']['type'] ??
'', $htmlTypes)) {
139 $e->addError($r, 'entity_field', 'bad_field', ts('Entity reference specifies a non-existent or non-translatable field'));
142 $e->addError($r, 'entity_id', 'nonexistent_id', ts('Entity does not exist'));