Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | ||
3 | require_once 'CRM/Core/Page.php'; | |
4 | ||
5 | /** | |
6 | * This class is not a real page -- it contains helpers for rendering the profile-selector and profile-editor | |
7 | * widgets | |
8 | */ | |
9 | class CRM_UF_Page_ProfileEditor extends CRM_Core_Page { | |
10 | function run() { | |
11 | CRM_Core_Error::fatal('This is not a real page!'); | |
12 | } | |
13 | ||
14 | static function registerProfileScripts() { | |
15 | static $loaded = FALSE; | |
16 | if ($loaded) { | |
17 | return; | |
18 | } | |
19 | $loaded = TRUE; | |
20 | ||
21 | CRM_Core_Resources::singleton() | |
22 | ->addSettingsFactory(function(){ | |
23 | return array( | |
24 | 'PseudoConstant' => array( | |
25 | 'locationType' => CRM_Core_PseudoConstant::locationType(), | |
26 | 'phoneType' => CRM_Core_PseudoConstant::phoneType(), | |
27 | ), | |
28 | 'initialProfileList' => civicrm_api('UFGroup', 'get', array( | |
29 | 'version' => 3, | |
30 | 'sequential' => 1, | |
342936e2 | 31 | 'is_active' => 1, |
6a488035 TO |
32 | 'rowCount' => 1000, // FIXME |
33 | )), | |
34 | 'profilePreviewKey' => CRM_Core_Key::get('CRM_UF_Form_Inline_Preview', TRUE), | |
35 | ); | |
36 | }) | |
37 | ->addScriptFile('civicrm', 'packages/backbone/json2.js', 100, 'html-header', FALSE) | |
38 | ->addScriptFile('civicrm', 'packages/backbone/underscore.js', 110, 'html-header', FALSE) | |
39 | ->addScriptFile('civicrm', 'packages/backbone/backbone.js', 120, 'html-header') | |
40 | ->addScriptFile('civicrm', 'packages/backbone/backbone.marionette.js', 125, 'html-header', FALSE) | |
41 | ->addScriptFile('civicrm', 'packages/backbone/backbone.collectionsubset.js', 125, 'html-header', FALSE) | |
42 | ->addScriptFile('civicrm', 'packages/backbone-forms/distribution/backbone-forms.js', 130, 'html-header', FALSE) | |
43 | ->addScriptFile('civicrm', 'packages/backbone-forms/distribution/adapters/backbone.bootstrap-modal.min.js', 140, 'html-header', FALSE) | |
44 | ->addScriptFile('civicrm', 'packages/backbone-forms/distribution/editors/list.min.js', 140, 'html-header', FALSE) | |
45 | ->addStyleFile('civicrm', 'packages/backbone-forms/distribution/templates/default.css', 140, 'html-header') | |
46 | ->addScriptFile('civicrm', 'packages/jquery/plugins/jstree/jquery.jstree.js', 0, 'html-header', FALSE) | |
47 | ->addStyleFile('civicrm', 'packages/jquery/plugins/jstree/themes/default/style.css', 0, 'html-header') | |
48 | ->addStyleFile('civicrm', 'css/crm.designer.css', 140, 'html-header') | |
49 | ->addScriptFile('civicrm', 'js/crm.backbone.js', 150) | |
50 | ->addScriptFile('civicrm', 'js/model/crm.schema-mapped.js', 200) | |
51 | ->addScriptFile('civicrm', 'js/model/crm.uf.js', 200) | |
52 | ->addScriptFile('civicrm', 'js/model/crm.designer.js', 200) | |
53 | ->addScriptFile('civicrm', 'js/model/crm.profile-selector.js', 200) | |
54 | ->addScriptFile('civicrm', 'js/view/crm.designer.js', 200) | |
55 | ->addScriptFile('civicrm', 'js/view/crm.profile-selector.js', 200) | |
56 | ->addScriptFile('civicrm', 'js/jquery/jquery.crmProfileSelector.js', 250) | |
57 | ->addScriptFile('civicrm', 'js/crm.designerapp.js', 250); | |
58 | ||
59 | CRM_Core_Region::instance('page-header')->add(array( | |
60 | 'template' => 'CRM/UF/Page/ProfileTemplates.tpl', | |
61 | )); | |
62 | } | |
63 | ||
64 | /** | |
65 | * Register entity schemas for use in the editor's palette | |
66 | * | |
67 | * @param array $entityTypes strings, e.g. "IndividualModel", "ActivityModel" | |
68 | */ | |
69 | static function registerSchemas($entityTypes) { | |
70 | // TODO in cases where registerSchemas is called multiple times for same entity, be more efficient | |
71 | CRM_Core_Resources::singleton()->addSettingsFactory(function () use ($entityTypes) { | |
72 | return array( | |
73 | 'civiSchema' => CRM_UF_Page_ProfileEditor::getSchema($entityTypes), | |
74 | ); | |
75 | }); | |
76 | } | |
77 | ||
78 | /** | |
79 | * AJAX callback | |
80 | */ | |
81 | static function getSchemaJSON() { | |
82 | $entityTypes = explode(',', $_REQUEST['entityTypes']); | |
83 | echo json_encode(self::getSchema($entityTypes)); | |
84 | CRM_Utils_System::civiExit(); | |
85 | } | |
86 | ||
87 | /** | |
88 | * Get a list of Backbone-Form models | |
89 | * | |
90 | * @param array $entityTypes model names ("IndividualModel") | |
91 | * @return array; keys are model names ("IndividualModel") and values describe 'sections' and 'schema' | |
92 | * @see js/model/crm.core.js | |
93 | * @see js/model/crm.mappedcore.js | |
94 | */ | |
95 | static function getSchema($entityTypes) { | |
96 | // FIXME: Depending on context (eg civicrm/profile/create vs search-columns), it may be appropriate to | |
97 | // pick importable or exportable fields | |
98 | ||
99 | $entityTypes = array_unique($entityTypes); | |
100 | $availableFields = NULL; | |
101 | foreach ($entityTypes as $entityType) { | |
102 | if (!$availableFields) { | |
103 | $availableFields = CRM_Core_BAO_UFField::getAvailableFieldsFlat(); | |
104 | //dpm($availableFields); | |
105 | } | |
106 | switch ($entityType) { | |
107 | case 'IndividualModel': | |
108 | $civiSchema[$entityType] = self::convertCiviModelToBackboneModel( | |
109 | 'Individual', | |
110 | ts('Individual'), | |
111 | $availableFields | |
112 | ); | |
113 | break; | |
114 | case 'ActivityModel': | |
115 | $civiSchema[$entityType] = self::convertCiviModelToBackboneModel( | |
116 | 'Activity', | |
117 | ts('Activity'), | |
118 | $availableFields | |
119 | ); | |
120 | break; | |
121 | case 'ContributionModel': | |
122 | $civiSchema[$entityType] = self::convertCiviModelToBackboneModel( | |
123 | 'Contribution', | |
124 | ts('Contribution'), | |
125 | $availableFields | |
126 | ); | |
127 | break; | |
128 | case 'MembershipModel': | |
129 | $civiSchema[$entityType] = self::convertCiviModelToBackboneModel( | |
130 | 'Membership', | |
131 | ts('Membership'), | |
132 | $availableFields | |
133 | ); | |
134 | break; | |
135 | case 'ParticipantModel': | |
136 | $civiSchema[$entityType] = self::convertCiviModelToBackboneModel( | |
137 | 'Participant', | |
138 | ts('Participant'), | |
139 | $availableFields | |
140 | ); | |
141 | break; | |
142 | default: | |
143 | throw new CRM_Core_Exception("Unrecognized entity type: $entityType"); | |
144 | } | |
145 | } | |
146 | ||
147 | return $civiSchema; | |
148 | } | |
149 | ||
150 | /** | |
151 | * FIXME: Move to somewhere more useful | |
152 | * FIXME: Do real mapping of "types" | |
153 | * | |
154 | * @param string $extends entity type; note: "Individual" means "Individual|Contact"; "Household" means "Household|Contact" | |
155 | * @param string $title a string to use in section headers | |
156 | * @param array $availableFields list of fields that are allowed in profiles, e.g. $availableFields['my_field']['field_type'] | |
157 | * @return array with keys 'sections' and 'schema' | |
158 | * @see js/model/crm.core.js | |
159 | * @see js/model/crm.mappedcore.js | |
160 | */ | |
161 | static function convertCiviModelToBackboneModel($extends, $title, $availableFields) { | |
162 | $locationFields = CRM_Core_BAO_UFGroup::getLocationFields(); | |
163 | ||
164 | $result = array( | |
165 | 'schema' => array(), // array($fieldName => $fieldSchema) | |
166 | 'sections' => array(), // array($sectionName => $section) | |
167 | ); | |
168 | ||
169 | // build field list | |
170 | foreach ($availableFields as $fieldName => $field) { | |
171 | switch ($extends) { | |
172 | case 'Individual': | |
173 | case 'Organization': | |
174 | case 'Household': | |
175 | if ($field['field_type'] != $extends && $field['field_type'] != 'Contact') { | |
176 | continue 2; | |
177 | } | |
178 | break; | |
179 | default: | |
180 | if ($field['field_type'] != $extends) { | |
181 | continue 2; | |
182 | } | |
183 | } | |
184 | $result['schema'][$fieldName] = array( | |
185 | 'type' => 'Text', // FIXME, | |
186 | 'title' => $field['title'], | |
187 | 'civiFieldType' => $field['field_type'], | |
188 | ); | |
189 | if (in_array($fieldName, $locationFields)) { | |
190 | $result['schema'][$fieldName]['civiIsLocation'] = TRUE; | |
191 | } | |
192 | if (in_array($fieldName, array('phone', 'phone_and_ext'))) { // FIXME what about phone_ext? | |
193 | $result['schema'][$fieldName]['civiIsPhone'] = TRUE; | |
194 | } | |
195 | } | |
196 | ||
197 | // build section list | |
198 | $result['sections']['default'] = array( | |
199 | 'title' => $title, | |
200 | 'is_addable' => FALSE, | |
201 | ); | |
202 | ||
203 | $customGroup = CRM_Core_BAO_CustomGroup::getAllCustomGroupsByBaseEntity($extends); | |
204 | $customGroup->orderBy('weight'); | |
205 | $customGroup->is_active = 1; | |
206 | $customGroup->find(); | |
207 | while ($customGroup->fetch()) { | |
208 | $sectionName = 'cg_' . $customGroup->id; | |
209 | $section = array( | |
210 | 'title' => ts('%1: %2', array(1 => $title, 2 => $customGroup->title)), | |
211 | 'is_addable' => TRUE, | |
212 | 'custom_group_id' => $customGroup->id, | |
213 | 'extends_entity_column_id' => $customGroup->extends_entity_column_id, | |
214 | 'extends_entity_column_value' => CRM_Utils_Array::explodePadded($customGroup->extends_entity_column_value), | |
215 | ); | |
216 | $result['sections'][$sectionName] = $section; | |
217 | } | |
218 | ||
219 | // put fields in their sections | |
220 | $fields = CRM_Core_BAO_CustomField::getFields($extends); | |
221 | foreach ($fields as $fieldId => $field) { | |
222 | $sectionName = 'cg_' . $field['custom_group_id']; | |
223 | $fieldName = 'custom_' . $fieldId; | |
224 | if (isset($result['schema'][$fieldName])) { | |
225 | $result['schema'][$fieldName]['section'] = $sectionName; | |
226 | $result['schema'][$fieldName]['civiIsMultiple'] = (bool) CRM_Core_BAO_CustomField::isMultiRecordField($fieldId); | |
227 | } | |
228 | } | |
229 | return $result; | |
230 | } | |
231 | } |