".form-item-lookup{padding-bottom:0;margin-bottom:0;}",
'type' => 'inline',
);
$form['add_item']['theme'] = array(
'#type' => 'select',
'#title' => t('Theme'),
'#options' => array_combine($themes, $themes),
'#default_value' => $default_theme,
'#description' => t('Theme Default: %default, Current Theme: %current', array(
'%default' => $default_theme,
'%current' => $global_theme,
)),
);
$form['add_item']['user'] = array(
'#type' => 'select',
'#title' => t('User type'),
'#default_value' => 0,
'#options' => array(
'anonymous' => t('anonymous'),
'authenticated' => t('authenticated'),
'all' => t('all'),
),
);
$type_options = array(
0 => t('Disabled'),
2 => t('URL'),
8 => t('Node Type'),
);
$form['add_item']['type'] = array(
'#type' => 'select',
'#title' => t('Type of lookup'),
'#default_value' => 2,
'#options' => $type_options,
);
$form['add_item']['lookup'] = array(
'#type' => 'textfield',
'#title' => t('Value to lookup'),
'#maxlength' => 255,
'#states' => array(
'disabled' => array(
':input[name="type"]' => array('value' => 0),
),
),
);
$form['add_item']['lookup_container_disabled'] = array(
'#type' => 'container',
'#states' => array(
'visible' => array(
':input[name="type"]' => array('value' => 0),
),
),
);
$form['add_item']['lookup_container_disabled']['disabled'] = array(
'#markup' => '
',
);
$form['add_item']['lookup_container_current_path'] = array(
'#type' => 'container',
'#states' => array(
'visible' => array(
':input[name="type"]' => array('value' => 2),
),
),
);
$form['add_item']['lookup_container_current_path']['current_path'] = array(
'#markup' => t('%front is the front page; can use internal URLs like %internal or an alias like %here', array(
'%front' => '',
'%internal' => 'node/2',
'%here' => current_path(),
)),
);
$form['add_item']['lookup_container_node_type'] = array(
'#type' => 'container',
'#states' => array(
'visible' => array(
':input[name="type"]' => array('value' => 8),
),
),
);
$form['add_item']['lookup_container_node_type']['node_type'] = array(
'#markup' => t('Node type is the machine name of the node; list of node types: @node_types', array(
'@current_path' => 'https://api.drupal.org/api/drupal/includes%21path.inc/function/current_path/7.x',
'@request_path' => 'https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/request_path/7.x',
'@request_uri' => 'https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/request_uri/7.x',
'@node_types' => implode(', ', array_keys(node_type_get_names())),
)),
);
$form['add_item']['css'] = array(
'#type' => 'textarea',
'#title' => t('Critical CSS'),
'#description' => t('Can be generated via https://www.sitelocity.com/critical-path-css-generator. If this field is empty this entry will be deleted.', array(
'@url' => 'https://www.sitelocity.com/critical-path-css-generator',
)),
'#default_value' => '',
);
$form['add_item']['dns'] = array(
'#type' => 'textarea',
'#title' => t('Hostnames to lookup'),
'#description' => t('Hosts that will be connected to.'),
'#default_value' => '',
);
$form['add_item']['pre'] = array(
'#type' => 'textarea',
'#title' => t('Urls to Preload'),
'#description' => t('Assets for the browser that should be downloaded at a high priority.'),
'#default_value' => '',
);
// Lookup saved data.
$query = db_select('advagg_critical_css', 'acc')
->fields('acc')
->comment('Query called from ' . __FUNCTION__ . '()');
$results = $query->execute();
// Put results into array.
$counter = 0;
foreach ($results as $row) {
$counter++;
$row = (array) $row;
foreach ($form['add_item'] as $key => $values) {
// Fix the states array for type.
if (!empty($values['#states'])) {
foreach ($values['#states'] as $states_key => $states_values) {
$states_value = reset($values['#states'][$states_key]);
$values['#states'][$states_key] = array(":input[name=\"{$counter}_type\"]" => $states_value);
}
}
$form['existing_items'][$counter]["{$counter}_{$key}"] = $values;
if (isset($row[$key])) {
$form['existing_items'][$counter]["{$counter}_{$key}"]['#default_value'] = $row[$key];
}
}
// Add in css to move the text hint up.
$form['#attached']['css'][] = array(
'data' => ".form-item-{$counter}-lookup{padding-bottom:0;margin-bottom:0;}",
'type' => 'inline',
);
// Add fieldset.
$filename = advagg_url_to_filename($row['lookup'], FALSE);
$base = drupal_get_path('theme', $row['theme']) . "/critical-css/{$row['user']}/";
if ($row['type'] == 2) {
$base .= "urls/$filename";
}
elseif ($row['type'] == 8) {
$base .= "type/$filename";
}
else {
$base = '';
}
$form['existing_items'][$counter] += array(
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#title' => t('@type @theme @user @lookup', array(
'@theme' => $row['theme'],
'@type' => $type_options[$row['type']],
'@user' => $row['user'],
'@lookup' => $row['lookup'],
)),
);
if (!empty($base)) {
$form['existing_items'][$counter]['#description'] = t('If you wish to store this configuration in a file
Critical CSS: @css
', array(
'@css' => "$base.css",
));
if (!empty($row['dns'])) {
$form['existing_items'][$counter]['#description'] .= t('
Hostnames: @dns
', array(
'@dns' => "$base.dns",
));
}
if (!empty($row['pre'])) {
$form['existing_items'][$counter]['#description'] .= t('
Preload: @pre
', array(
'@pre' => "$base.pre",
));
}
}
}
// Add top level fieldsets.
$form['add_item'] += array(
'#type' => 'fieldset',
'#title' => t('Add Critical CSS'),
'#collapsible' => TRUE,
'#collapsed' => $results->rowCount(),
);
if (!empty($form['existing_items'])) {
$form['existing_items'] += array(
'#type' => 'fieldset',
'#title' => t('Edit Critical CSS'),
);
}
// Clear the cache bins on submit.
$form['#submit'][] = 'advagg_critical_css_admin_settings_form_submit';
// Most code below taken from system_settings_form().
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save configuration'),
);
$form['actions']['disable'] = array(
'#type' => 'submit',
'#value' => t('Disable All From Database'),
'#submit' => array('advagg_critical_css_admin_settings_form_submit_disable'),
);
if (!empty($_POST) && form_get_errors()) {
drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
}
// By default, render the form using theme_system_settings_form().
if (!isset($form['#theme'])) {
$form['#theme'] = 'system_settings_form';
}
return $form;
}
/**
* Submit callback, process the advagg_critical_css form.
*
* Also clear out the advagg cache bin.
*
* @ingroup advagg_forms_callback
*/
function advagg_critical_css_admin_settings_form_submit_disable($form, &$form_state) {
$query = db_select('advagg_critical_css', 'acc')
->fields('acc')
->comment('Query called from ' . __FUNCTION__ . '()');
$results = $query->execute();
// Put results into array.
$insert_update = array();
foreach ($results as $row) {
$row = (array) $row;
$new_row = $row;
$new_row['type'] = 0;
$insert_update[] = array(
$row,
$new_row,
);
}
advagg_critical_css_table_insert_update($insert_update);
}
/**
* Submit callback, process the advagg_critical_css form.
*
* Also clear out the advagg cache bin.
*
* @ingroup advagg_forms_callback
*/
function advagg_critical_css_admin_settings_form_submit($form, &$form_state) {
// Exclude unnecessary elements.
form_state_values_clean($form_state);
// Rearrange form values into key value pairs.
$items = advagg_critical_css_get_rows_from_form($form_state['values']);
// Get default values.
$default_values = advagg_find_all_recommended_admin_values($form_state['complete form'], '#default_value');
unset($default_values['form_token']);
$default_items = advagg_critical_css_get_rows_from_form($default_values);
// Get diff, see what items need to be saved.
$diff = advagg_critical_css_diff_multi($default_items, $items);
$changed_items = array();
foreach ($diff as $key => $values) {
$changed_items[$key] = $items[$key];
}
// Get items to insert/update and delete.
list($insert_update, $delete) = advagg_critical_css_get_db_operations_arrays($changed_items, $default_items);
advagg_critical_css_table_insert_update($insert_update);
advagg_critical_css_table_delete($delete);
// Clear caches.
advagg_cache_clear_admin_submit();
drupal_set_message(t('The configuration options have been saved.'));
}
/**
* Translate from state values into a nested array strucutre.
*
* @param array $form_state_values
* From state values; from $form_state['values'].
*
* @return array
* Nested array strucutre, each index is a row in the db.
*/
function advagg_critical_css_get_rows_from_form(array $form_state_values) {
$items = array();
$counter = 0;
foreach ($form_state_values as $key => $values) {
// Get the index from the start of the form name.
$matches = array();
// 1_type turns into $counter = 1 and $key = type.
preg_match('/^(\d)_(.*)/', $key, $matches);
if (!empty($matches)) {
$counter = $matches[1];
$key = $matches[2];
}
$items[$counter][$key] = $values;
}
return $items;
}
/**
* Given a list of items see what ones need to be inserted/updated or deleted.
*
* @param array $items
* Array of values, representing a row in the db.
*
* @return array
* Nested array strucutre, index 0 is the insert update, 1 is the deleted.
*/
function advagg_critical_css_get_db_operations_arrays(array $items, array $old_items) {
$insert_update = array();
$delete = array();
foreach ($items as $key => $values) {
// If the css is empty then this needs to be deleted.
if (empty($values['css'])) {
// Do not delete the new items entry (0); it's not in the db currently.
if (!empty($key)) {
$delete[$key] = $values;
}
}
else {
// Pass along the old key value pairs for db_merge.
if (!empty($old_items[$key])) {
$keys = $old_items[$key] + $values;
}
else {
$keys = $values;
}
$insert_update[$key] = array($keys, $values);
}
}
return array($insert_update, $delete);
}
/**
* Given a list of items see what ones need to be inserted/updated or deleted.
*
* @param array $defaults
* Array of default values, representing a row in the db.
* @param mixed $new_values
* Array of edited values, representing a row in the db.
*
* @return array
* Nested array strucutre; only the diff.
*/
function advagg_critical_css_diff_multi(array $defaults, $new_values) {
$result = array();
foreach ($defaults as $key => $val) {
if (is_array($val) && isset($new_values[$key])) {
$tmp = advagg_critical_css_diff_multi($val, $new_values[$key]);
if ($tmp) {
$result[$key] = $tmp;
}
}
elseif (!isset($new_values[$key])) {
$result[$key] = NULL;
}
elseif ($val != $new_values[$key]) {
$result[$key] = $new_values[$key];
}
if (isset($new_values[$key])) {
unset($new_values[$key]);
}
}
$result = $result + $new_values;
return $result;
}