/**
* Implements hook_install().
*/
function entity_install() {
entity_clean_local_storage();
}
/**
* Given an entity type, bundle name, form and entity, this will add the
* entity's core fields to the form via the DrupalGap forms api.
* @param {String} entity_type
* @param {String} bundle
* @param {Object} form
* @param {Object} entity
*/
function drupalgap_entity_add_core_fields_to_form(entity_type, bundle,
form, entity) {
try {
// Grab the core fields for this entity type and bundle.
var fields = drupalgap_entity_get_core_fields(entity_type, bundle);
// Iterate over each core field in the entity and add it to the form. If
// there is a value present in the entity, then set the field's form element
// default value equal to the core field value.
for (var name in fields) {
if (!fields.hasOwnProperty(name)) { continue; }
var field = fields[name];
var default_value = field.default_value;
if (entity && entity[name]) { default_value = entity[name]; }
form.elements[name] = field;
form.elements[name].default_value = default_value;
}
}
catch (error) {
console.log('drupalgap_entity_add_core_fields_to_form - ' + error);
}
}
/**
* Deprecated! Given an entity type, the bundle, the entity (assembled from form
* state values) and any options, this assembles the ?data= string for the
* entity service resource call URLs.
* @param {String} entity_type
* @param {String} bundle
* @param {Object} entity
* @param {Object} options
*/
function drupalgap_entity_assemble_data(entity_type, bundle, entity, options) {
try {
console.log('WARNING: drupalgap_entity_assemble_data() has been ' +
'deprecated! Now just call e.g. node_save() for auto assembly.');
return;
}
catch (error) { console.log('drupalgap_entity_assemble_data - ' + error); }
}
/**
* Returns the 'Delete' button object that is used on entity edit forms.
* @param {String} entity_type
* @param {Number} entity_id
* @return {Object}
*/
function drupalgap_entity_edit_form_delete_button(entity_type, entity_id) {
return {
title: t('Delete'),
attributes: {
onclick: "javascript:drupalgap_entity_edit_form_delete_confirmation('" +
entity_type + "', " + entity_id +
');'
}
};
}
/**
* Given an entity type and id, this will display a confirmation dialogue and
* will subsequently delete the entity if the user confirms the dialogue box.
* The Services module retains Drupal user permissions so users without proper
* permissions will not be able to delete the entities from the server.
* @param {String} entity_type
* @param {Number} entity_id
* @return {*}
*/
function drupalgap_entity_edit_form_delete_confirmation(entity_type,
entity_id) {
try {
var confirm_msg =
t('Delete this content, are you sure? This action cannot be undone...');
drupalgap_confirm(confirm_msg, {
confirmCallback: function(button) {
if (button == 2) { return; }
// Change the jQM loader mode to deleting.
drupalgap.loader = 'deleting';
// Set up the api call arguments and success callback.
var call_arguments = {};
call_arguments.success = function(result) {
// Remove the entities page from the DOM, if it exists.
var entity_page_path = entity_type + '/' + entity_id;
var entity_page_id = drupalgap_get_page_id(entity_page_path);
if (drupalgap_page_in_dom(entity_page_id)) {
drupalgap_remove_page_from_dom(entity_page_id);
}
// Remove the entity from local storage.
// @todo - this should be moved to jDrupal.
window.localStorage.removeItem(
entity_local_storage_key(entity_type, entity_id)
);
// Go to the front page, unless a form action path was specified.
var form = drupalgap_form_local_storage_load('node_edit');
var destination = form.action ? form.action : '';
drupalgap_goto(destination, {
reloadPage: true,
form_submission: true
});
};
// Call the delete function.
var name = services_get_resource_function_for_entity(
entity_type,
'delete'
);
var fn = window[name];
fn(entity_id, call_arguments);
}
});
}
catch (error) {
console.log('drupalgap_entity_edit_form_delete_confirmation - ' + error);
}
}
/**
* Given an entity, this will render the content of the entity and place it in
* the entity JSON object as the 'content' property.
* @param {String} entity_type
* @param {Object} entity
*/
function drupalgap_entity_render_content(entity_type, entity) {
try {
entity.content = '';
// Figure out the bundle.
var bundle = entity.type;
if (entity_type == 'comment') { bundle = entity.bundle; }
else if (entity_type == 'taxonomy_term') { bundle = entity.vocabulary_machine_name; }
// Load the field info for this entity and bundle combo.
var field_info = drupalgap_field_info_instances(entity_type, bundle);
if (!field_info) { return; }
// Give modules a chance to pre build the content.
module_invoke_all('entity_pre_build_content', entity, entity_type, bundle);
// Render each field on the entity, using the drupalgap or default display.
var field_weights = {};
var field_displays = {};
for (var field_name in field_info) {
if (!field_info.hasOwnProperty(field_name)) { continue; }
var field = field_info[field_name];
// Determine which display mode to use. The default mode will be used if the drupalgap display mode is not
// present, unless a view mode has been specified in settings.js then we'll use that config for the current
// entity/bundle combo. If a module isn't listed on a custom display, use the default display's module.
if (!field.display) { break; }
var display = field.display['default'];
var view_mode = drupalgap_entity_view_mode(entity_type, bundle);
if (field.display[view_mode]) {
display = field.display[view_mode];
if (typeof display.module === 'undefined' && typeof field.display['default'].module !== 'undefined'
) { display.module = field.display['default'].module; }
}
// Skip hidden fields.
if (display.type == 'hidden') { continue; }
// Save the field display and weight. Use the weight from the field's render element if it's available,
// otherwise fallback to the weight mentioned in the display.
field_displays[field_name] = display;
field_weights[field_name] = entity[field_name] && typeof entity[field_name].weight !== 'undefined' ?
entity[field_name].weight : display.weight;
}
// Give modules a chance to alter the build content.
module_invoke_all('entity_post_build_content', entity, entity_type, bundle);
// Extract the field weights and sort them.
var extracted_weights = [];
for (var field_name in field_weights) {
if (!field_weights.hasOwnProperty(field_name)) { continue; }
var weight = field_weights[field_name];
extracted_weights.push(weight);
}
extracted_weights.sort(function(a, b) { return a - b; });
// Give modules a chance to pre alter the content.
module_invoke_all('entity_pre_render_content', entity, entity_type, bundle);
// For each sorted weight, locate the field with the corresponding weight,
// then render it's field content.
var completed_fields = [];
for (var weight_index in extracted_weights) {
if (!extracted_weights.hasOwnProperty(weight_index)) { continue; }
var target_weight = extracted_weights[weight_index];
for (var field_name in field_weights) {
if (!field_weights.hasOwnProperty(field_name) || typeof entity[field_name] === 'undefined') { continue; }
if (typeof entity[field_name].access !== 'undefined' && !entity[field_name].access) { continue; }
var weight = field_weights[field_name];
if (target_weight == weight) {
if (completed_fields.indexOf(field_name) == -1) {
completed_fields.push(field_name);
entity.content += drupalgap_entity_render_field(
entity_type,
entity,
field_name,
field_info[field_name],
field_displays[field_name]
);
break;
}
}
}
}
// Give modules a chance to alter the content.
module_invoke_all('entity_post_render_content', entity, entity_type, bundle);
// Update this entity in local storage so the content property sticks.
if (entity_caching_enabled(entity_type, bundle)) {
_entity_set_expiration_time(entity_type, entity);
_entity_local_storage_save(
entity_type,
entity[entity_primary_key(entity_type)],
entity
);
}
}
catch (error) {
console.log('drupalgap_entity_render_content - ' + error);
}
}
/**
* Given an entity_type, the entity, a field name, and the field this will
* render the field using the appropriate hook_field_formatter_view().
* @param {String} entity_type
* @param {Object} entity
* @param {String} field_name
* @param {Object} field
* @param {*} display
* @return {String}
*/
function drupalgap_entity_render_field(entity_type, entity, field_name,
field, display) {
try {
var content = '';
// Determine module that implements the hook_field_formatter_view,
// then determine the hook's function name, then render the field content.
// If there wasn't a module specified in the display, look to the module
// specified in the field widget. If we still don't find it, then just
// return.
var module = display['module'];
if (!module) {
if (!field.widget.module) {
var msg = 'drupalgap_entity_render_field - ' +
'unable to locate the module for the field (' + field_name + ')';
console.log(msg);
return content;
}
else { module = field.widget.module; }
}
var function_name = module + '_field_formatter_view';
if (function_exists(function_name)) {
// Grab the field formatter function, then grab the field items
// from the entity, then call the formatter function and append its result
// to the entity's content.
var fn = window[function_name];
var items = null;
// Check to see if translated content based on app's language setting
// is present or not. If yes, then use that language as per setting.
// Determine the language code. Note, multi lingual sites may have a
// language code on the entity, but still have 'und' on the field, so
// fall back to 'und' if the field's language code doesn't match the
// entity's language code.
var default_lang = language_default();
var language = entity.language;
if (entity[field_name]) {
if (entity[field_name][default_lang]) {
items = entity[field_name][default_lang];
}
else if (entity[field_name][language]) {
items = entity[field_name][language];
}
else if (entity[field_name]['und']) {
items = entity[field_name]['und'];
language = 'und';
}
else { items = entity[field_name]; }
}
// @TODO - We've been sending 'field' as the instance
// (drupalgap_field_info_instance), and the 'instance' as the field
// (drupalgap_field_info_field). This is backwards, and should be
// reversed. All contrib modules with field support will need to be
// udpated to reflect this. Lame.
var elements = fn(
entity_type,
entity,
field, /* This is actually the instance, doh! (I think) */
drupalgap_field_info_field(field_name),
language,
items,
display
);
for (var delta in elements) {
if (!elements.hasOwnProperty(delta)) { continue; }
var element = elements[delta];
// If the element has markup, render it as is, if it is
// themeable, then theme it.
var element_content = '';
if (element.markup) { element_content = element.markup; }
else if (element.theme) {
element_content = theme(element.theme, element);
}
content += element_content;
}
}
else {
console.log(
'WARNING: drupalgap_entity_render_field - ' + function_name + '() ' +
'does not exist! (' + field_name + ')'
);
}
// Render the field label, if necessary.
if (content != '' && display['label'] != 'hidden') {
var label = '<h3>' + field.label + '</h3>';
// Place the label above or below the field content.
label = '<div>' + label + '</div>';
switch (display['label']) {
case 'below':
content += label;
break;
case 'above':
default:
content = label + content;
break;
}
}
// Finally, wrap the rendered field in a div, and set the field name as the
// class name on the wrapper.
content = '<div class="' + field_name + '">' + content + '</div>';
// Give modules a chance to alter the field content.
var reference = {'content': content};
module_invoke_all(
'entity_post_render_field', entity, field_name, field, reference
);
if (reference.content != content) { return reference.content; }
return content;
}
catch (error) { console.log('drupalgap_entity_render_field - ' + error); }
}
/**
* Given a form and form_state, this will assemble an entity from the form_state
* values and return the entity as a JSON object.
* @param {Object} form
* @param {Object} form_state
* @return {Object}
*/
function drupalgap_entity_build_from_form_state(form, form_state) {
try {
var entity = {};
var language = language_default();
for (var name in form_state.values) {
if (!form_state.values.hasOwnProperty(name)) { continue; }
var value = form_state.values[name];
// Skip elements with restricted access.
if (
typeof form.elements[name].access !== 'undefined' &&
!form.elements[name].access
) { continue; }
// Determine wether or not this element is a field. If it is, determine
// it's module and field assembly hook.
var is_field = false;
var module = false;
var hook = false;
if (form.elements[name].is_field) {
is_field = true;
module = form.elements[name].field_info_field.module;
hook = module + '_assemble_form_state_into_field';
if (!function_exists(hook)) { hook = false; }
}
// Retrieve the potential key for the element, if we don't get one
// then it is a flat field that should be attached as a property to the
// entity. Otherwise attach the key and value to the entity.
var key = drupalgap_field_key(name); // e.g. value, fid, tid, nid, etc.
if (key) {
// Determine how many allowed values for this field.
var allowed_values = form.elements[name].field_info_field.cardinality;
// Convert unlimited value fields to one, for now...
if (allowed_values == -1) { allowed_values = 1; }
// Make sure there is at least one value before creating the form
// element on the entity.
if (typeof value[language][0] === 'undefined') { continue; }
// Create an empty object to house the field on the entity.
entity[name] = {};
// Some fields do not use a delta value in the service call, so we
// prepare for that here.
// @todo - Do all options_select widgets really have no delta value?
// Or is it only single value fields that don't have it? We need to
// test this.
var use_delta = true;
if (
form.elements[name].type ==
'taxonomy_term_reference' ||
form.elements[name].field_info_instance.widget.type ==
'options_select'
) {
use_delta = false;
entity[name][language] = {};
}
else { entity[name][language] = []; }
// Now iterate over each delta on the form element, and add the value
// to the entity.
for (var delta = 0; delta < allowed_values; delta++) {
if (typeof value[language][delta] !== 'undefined') {
// @TODO - the way values are determined here is turning into
// spaghetti code. Every form element needs its own
// value_callback, just like Drupal's FAPI. Right now DG has
// something similar going on with the use of
// hook_assemble_form_state_into_field(). So replace any spaghetti
// below with a value_callback. Provide a deprecated hook warning
// for any fields not haven't caught up yet, and fallback to the
// hook for a while.
// @UPDATE - Actually, the DG FAPI
// hook_assemble_form_state_into_field() is a good idea, and
// should be used by all field form elements, then in
// drupalgap_field_info_instances_add_to_form(), that function
// should use the value_callback idea to properly map entity data
// to the form element's value.
// Extract the value.
var field_value = value[language][delta];
// By default, we'll assume we'll be attaching this element item's
// value according to a key (usually 'value' is the default key
// used by Drupal fields). However, we'll give modules that
// implement hook_assemble_form_state_into_field() an opportunity
// to specify no usage of a key if their item doesn't need one.
// The geofield module is an example of field that doesn't use a
// key. The use_wrapper flag allows others to completely override
// the use of a wrapper around the field value, e.g. taxonomy term
// reference autocomplete. We'll attach any other helpful
// variables here as well (element name, form id, etc).
var field_key = {
value: 'value',
use_key: true,
use_wrapper: true,
use_delta: use_delta,
name: name,
form_id: form.id,
element_id: form.elements[name][language][delta].id
};
// If this element is a field, give the field's module an
// opportunity to assemble its own value, otherwise we'll just
// use the field value extracted above.
if (is_field && hook) {
var fn = window[hook];
field_value = fn(form.entity_type,
form.bundle,
field_value,
form.elements[name].field_info_field,
form.elements[name].field_info_instance,
language,
delta,
field_key,
form
);
}
// If someone updated the key, use it.
if (key != field_key.value) { key = field_key.value; }
// If we don't need a delta value, place the field value using the
// key, if posible. If we're using a delta value, push the key
// and value onto the field to indicate the delta.
if (!field_key.use_delta) {
if (!field_key.use_wrapper) {
entity[name][language] = field_value;
}
else {
if ($.isArray(entity[name][language])) {
console.log(
'WARNING: drupalgap_entity_build_from_form_state - ' +
'cannot use key (' + key + ') on field (' + name + ') ' +
'language code array, key will be ignored.'
);
entity[name][language].push(field_value);
}
else { entity[name][language][key] = field_value; }
}
}
else {
if (field_key.use_key) {
var item = {};
item[key] = field_value;
entity[name][language].push(item);
}
else {
entity[name][language].push(field_value);
}
}
// If the field value was null, we won't send along the field, so
// just remove it. Except for list_boolean fields, they need a
// null value to set the field value to false.
if (
field_value === null &&
typeof entity[name] !== 'undefined' &&
form.elements[name].type != 'list_boolean'
) {
if (is_field) {
if (delta == 0) { delete entity[name]; }
else if (typeof entity[name][language][delta] !== 'undefined') {
delete entity[name][language][delta];
}
}
else { delete entity[name]; }
}
// If we had an optional select list, and no options were
// selected, delete the empty field from the assembled entity.
// @TODO - will this cause multi value issues?
if (
is_field && !use_delta &&
form.elements[name].field_info_instance.widget.type ==
'options_select' && !form.elements[name].required &&
field_value === '' && typeof entity[name] !== 'undefined'
) { delete entity[name]; }
}
}
}
else if (typeof value !== 'undefined') { entity[name] = value; }
}
return entity;
}
catch (error) {
console.log('drupalgap_entity_build_from_form_state - ' + error);
}
}
/**
* Given a form, form_state and entity, this will call the appropriate service
* resource to create or update the entity.
* @param {Object} form
* @param {Object} form_state
* @param {Object} entity
* @return {*}
*/
function drupalgap_entity_form_submit(form, form_state, entity) {
try {
// Grab the primary key name for this entity type.
var primary_key = entity_primary_key(form.entity_type);
// Determine if we are editing an entity or creating a new one.
var editing = false;
if (entity[primary_key] && entity[primary_key] != '') {
editing = true;
}
// Let's set up the api call arguments.
var call_arguments = {};
// Setup the success call back to go back to the entity page view.
call_arguments.success = function(result) {
try {
// If no one has provided a form.action to submit this form to,
// by default we'll try to redirect to [entity-type]/[entity-id] to view
// the entity. For taxonomy, we replace the underscore with a forward
// slash in the path.
var destination = form.action;
if (!destination) {
var prefix = form.entity_type;
if (prefix == 'taxonomy_vocabulary' || prefix == 'taxonomy_term') {
prefix = prefix.replace('_', '/');
}
destination = prefix + '/' + result[primary_key];
}
// Is there a destination URL query parameter overwriting the action?
if (_GET('destination')) { destination = _GET('destination'); }
// Set up the default goto options, and use any options provided by the
// form.
var goto_options = { form_submission: true };
if (form.action_options) {
goto_options = $.extend({}, goto_options, form.action_options);
}
// Finally goto our destination.
drupalgap_goto(destination, goto_options);
}
catch (error) {
console.log('drupalgap_entity_form_submit - success - ' + error);
}
};
// Setup the error call back.
call_arguments.error = function(xhr, status, message) {
try {
// If there were any form errors, display them in an alert.
var msg = _drupalgap_form_submit_response_errors(form, form_state, xhr,
status, message);
if (msg) { drupalgap_alert(msg); }
}
catch (error) {
console.log('drupalgap_entity_form_submit - error - ' + error);
}
};
// Change the jQM loader mode to saving.
drupalgap.loader = 'saving';
// Depending on if we are creating a new entity, or editing an existing one,
// call the appropriate service resource.
var crud = 'create';
if (editing) {
crud = 'update';
// Remove the entity from local storage.
// @todo This should be moved to jDrupal.
window.localStorage.removeItem(
entity_local_storage_key(form.entity_type, entity[primary_key])
);
}
var fn = window[
services_get_resource_function_for_entity(form.entity_type, crud)
];
fn(entity, call_arguments);
}
catch (error) { console.log('drupalgap_entity_form_submit - ' + error); }
}
/**
* Given an entity type, this returns its core fields as forms api elements.
* @param {String} entity_type
* @param {String} bundle
* @return {Object}
*/
function drupalgap_entity_get_core_fields(entity_type, bundle) {
try {
// @todo - was this function what we were tyring to accomplish with the
// early entity_info hook imitations?
// @todo - And why is this function not populated dynamically via Drupal?
var fields = {};
switch (entity_type) {
case 'comment':
var content_type = bundle.replace('comment_node_', '');
// Add each schema field to the field collection.
var base_table = drupalgap.entity_info[entity_type].schema_fields_sql['base table'];
for (var index in base_table) {
if (!base_table.hasOwnProperty(index)) { continue; }
var name = base_table[index];
var field = {
type: 'hidden',
required: false,
default_value: '',
title: ucfirst(name)
};
fields[name] = field;
}
// Make the node id required.
fields['nid'].required = true;
// Only anonymous users can fill out the name field, authenticated users
// have their name auto filled and disabled.
fields['name'].type = 'textfield';
if (Drupal.user.uid != 0) {
fields['name'].default_value = Drupal.user.name;
fields['name'].disabled = true;
}
// If the 'Allow comment title' is enabled on the content type, show
// the comment subject field.
if (drupalgap.content_types_list[content_type].comment_subject_field) {
fields['subject'].type = 'textfield';
}
// Depending on this content type's comment settings, let's make
// modifications to the form elements.
// admin/structure/types/manage/article
// 0 = Anonymous posters may not enter their contact information
// 1 = Anonymous posters may leave their contact information
// 2 = Anonymous posters must leave their contact information
var comment_anonymous =
drupalgap.content_types_list[content_type].comment_anonymous;
switch (comment_anonymous) {
case '0':
delete(fields['mail']);
delete(fields['homepage']);
break;
case '1':
break;
case '2':
fields['mail'].required = true;
fields['homepage'].required = true;
break;
}
// Only anonymous users get the mail and homepage fields.
if (Drupal.user.uid == 0) {
if (fields['mail']) { fields['mail'].type = 'textfield'; }
if (fields['homepage']) { fields['homepage'].type = 'textfield'; }
}
break;
case 'node':
fields.nid = {
'type': 'hidden',
'required': false,
'default_value': ''
};
fields.title = {
'type': 'textfield',
'title': t('Title'),
'required': true,
'default_value': '',
'description': ''
};
fields.type = {
'type': 'hidden',
'required': true,
'default_value': ''
};
fields.language = {
'type': 'hidden',
'required': true,
'default_value': language_default()
};
break;
case 'user':
fields.uid = {
'type': 'hidden',
'required': false,
'default_value': ''
};
fields.name = {
'type': 'textfield',
'title': t('Username'),
'required': true,
'default_value': '',
'description': ''
};
fields.mail = {
'type': 'email',
'title': t('E-mail address'),
'required': true,
'default_value': '',
'description': ''
};
fields.picture = {
'type': 'image',
'widget_type': 'imagefield_widget',
'title': t('Picture'),
'required': false,
'value': t('Add Picture')
};
break;
case 'taxonomy_term':
fields = {
'vid': {
'type': 'hidden',
'required': true,
'default_value': ''
},
'tid': {
'type': 'hidden',
'required': false,
'default_value': ''
},
'name': {
'type': 'textfield',
'title': t('Name'),
'required': true,
'default_value': ''
},
'description': {
'type': 'textarea',
'title': t('Description'),
'required': false,
'default_value': ''
}
};
break;
case 'taxonomy_vocabulary':
fields = {
'vid': {
'type': 'hidden',
'required': false,
'default_value': ''
},
'name': {
'type': 'textfield',
'title': t('Name'),
'required': true,
'default_value': ''
},
'machine_name': {
'type': 'textfield',
'title': t('Machine Name'),
'required': true,
'default_value': ''
},
'description': {
'type': 'textarea',
'title': t('Description'),
'required': false,
'default_value': ''
}
};
break;
default:
console.log(
'drupalgap_entity_get_core_fields - entity type not supported yet (' +
entity_type +
')'
);
break;
}
return fields;
}
catch (error) { console.log('drupalgap_entity_get_core_fields - ' + error); }
}
/**
* Given an entity_type, this returns the entity JSON info, if it exists, false
* otherwise. You may optionally call this function with no arguments to
* retrieve the JSON info for all entity types. See also
* @see http://api.drupal.org/api/drupal/includes%21common.inc/function/entity_get_info/7
* @return {Object|Boolean}
*/
function drupalgap_entity_get_info() {
try {
if (arguments[0]) {
var entity_type = arguments[0];
if (entity_type && drupalgap.entity_info[entity_type]) {
return drupalgap.entity_info[entity_type];
}
else {
return false;
}
}
return drupalgap.entity_info;
}
catch (error) { console.log('drupalgap_entity_get_info - ' + error); }
}
/**
* @deprecated Since 7.x-1.7-alpha you should use entity_primary_key() instead.
* Given an entity type, this returns the primary key identifier for it.
* @param {String} entity_type
* @return {String}
*/
function drupalgap_entity_get_primary_key(entity_type) {
try {
console.log(
'WARNING: drupalgap_entity_get_primary_key() is deprecated! ' +
'Use entity_primary_key() instead.'
);
return entity_primary_key(entity_type);
}
catch (error) { console.log('drupalgap_entity_get_primary_key - ' + error); }
}
/**
* Given an entity type, an entity id and a mode, this will return a render
* object for the entity's page container.
* @param {String} entity_type
* @param {Number} entity_id
* @param {String} mode
* @return {Object}
*/
function _drupalgap_entity_page_container(entity_type, entity_id, mode) {
try {
var id = _drupalgap_entity_page_container_id(entity_type, entity_id, mode);
var attrs = {
id: id,
'class': entity_type + ' ' + entity_type + '-' + mode
};
return {
markup: '<div ' + drupalgap_attributes(attrs) + '></div>'
};
}
catch (error) { console.log('_drupalgap_entity_page_container - ' + error); }
}
/**
* Given an entity type, an entity id, and a mode, this will return the unique
* id to be used for the entity's page container.
* @param {String} entity_type
* @param {Number} entity_id
* @param {String} mode
* @return {String}
*/
function _drupalgap_entity_page_container_id(entity_type, entity_id, mode) {
return entity_type + '_' + entity_id + '_' + mode + '_container';
}
/**
* Given an entity type, id, mode and page build, this will render the page
* build and inject it into the container on the page.
* @param {String} entity_type
* @param {Number} entity_id
* @param {String} mode
* @param {Object} build
*/
function _drupalgap_entity_page_container_inject(entity_type, entity_id, mode, build) {
try {
// Get the container id, set the drupalgap.output to the page build, then
// inject the rendered page into the container.
var id = _drupalgap_entity_page_container_id(entity_type, entity_id, mode);
module_invoke_all('entity_view_alter', entity_type, entity_id, mode, build);
drupalgap.output = build;
$('#' + id).html(drupalgap_render_page()).trigger('create');
_drupalgap_entity_page_add_css_class_names(entity_type, entity_id, build);
}
catch (error) {
console.log('_drupalgap_entity_page_container_inject - ' + error);
}
}
/**
* An internal function used to add css class names to an entity's jQM page container.
* @param {String} entity_type
* @param {Number} entity_id
* @param {Object} build
* @private
*/
function _drupalgap_entity_page_add_css_class_names(entity_type, entity_id, build) {
try {
var className = entity_type;
var bundleName = entity_get_bundle(entity_type, build[entity_type]);
if (bundleName) { className += '-' + bundleName; }
className += ' ' + entity_type.replace(/_/g, '-') + '-' + entity_id;
$('#' + drupalgap_get_page_id()).addClass(className);
}
catch (error) { console.log('_drupalgap_entity_page_add_css_class_names - ' + error); }
}
/**
* The page callback for entity edit forms.
* @param {String} form_id
* @param {String} entity_type
* @param {Number} entity_id
* @return {Object}
*/
function entity_page_edit(form_id, entity_type, entity_id) {
try {
var content = {
container: _drupalgap_entity_page_container(
entity_type,
entity_id,
'edit'
)
};
return content;
}
catch (error) { console.log('entity_page_edit - ' + error); }
}
/**
* The pageshow callback for entity edit forms.
* @param {String} form_id
* @param {String} entity_type
* @param {Number} entity_id
*/
function entity_page_edit_pageshow(form_id, entity_type, entity_id) {
try {
entity_load(entity_type, entity_id, {
success: function(entity) {
_drupalgap_entity_page_container_inject(
entity_type,
entity_id,
'edit',
drupalgap_get_form(form_id, entity)
);
}
});
}
catch (error) { console.log('entity_page_edit_pageshow - ' + error); }
}
/**
* Returns an entity type's primary title key.
* @param {String} entity_type
* @return {String}
*/
function entity_primary_key_title(entity_type) {
try {
var key;
switch (entity_type) {
case 'comment': key = 'subject'; break;
case 'file': key = 'filename'; break;
case 'node': key = 'title'; break;
case 'taxonomy_term': key = 'name'; break;
case 'taxonomy_vocabulary': key = 'name'; break;
case 'user': key = 'name'; break;
default:
console.log(
'entity_primary_key_title - unsupported entity type (' +
entity_type +
')'
);
break;
}
return key;
}
catch (error) { console.log('entity_primary_key_title - ' + error); }
}
/**
* Implements hook_services_request_pre_postprocess_alter().
* @param {Object} options
* @param {*} result
*/
function entity_services_request_pre_postprocess_alter(options, result) {
try {
// If we're retrieving an entity, render the entity's content, if it isn't
// already set.
if (
options.resource == 'retrieve' &&
in_array(options.service, entity_types()
)) {
// @TODO - does this condition ever evaluate to true?
if (typeof result.content !== 'undefined') { return; }
drupalgap_entity_render_content(options.service, result);
}
// If we're indexing comments, render its content, if it isn't already set.
else if (options.service == 'comment' && options.resource == 'index') {
for (var index in result) {
if (!result.hasOwnProperty(index)) { continue; }
var object = result[index];
// @TODO - does this condition ever evaluate to true?
if (typeof object.content !== 'undefined') { continue; }
drupalgap_entity_render_content(options.service, result[index]);
}
}
}
catch (error) {
console.log('entity_services_request_pre_postprocess_alter - ' + error);
}
}