You are here

class AvailabilityCalendarsNodeEditCalendarFormHandler in Availability Calendars 7.2

Hierarchy

Expanded class hierarchy of AvailabilityCalendarsNodeEditCalendarFormHandler

File

./availability_calendars.node.inc, line 328

View source
class AvailabilityCalendarsNodeEditCalendarFormHandler {
  private static $instance = NULL;

  /** @var $node object */
  protected $node;

  /** @var $settings object */
  protected $settings;

  /** @var $states array */
  protected $states;

  /** @var $states array */
  protected $commands;

  /**
   * @param object $node
   * @return AvailabilityCalendarsNodeEditCalendarFormHandler
   */
  public static function instance($node = NULL) {
    if (self::$instance === NULL) {
      self::$instance = new AvailabilityCalendarsNodeEditCalendarFormHandler($node);
    }
    return self::$instance;
  }
  protected function __construct($node) {
    $this->node = $node;
    $this->settings = availability_calendars_get_settings($this->node);

    // Show the editor month count.
    $this->settings->monthcount = $this->settings->editormonthcount;

    // Do not show the key. We show our own key here with radio buttons and no special states.
    $this->settings->showkey = false;
  }

  /**
   * Builds the node/%node/availability-calendars page form.
   *
   * @param array $form
   * @return array
   *   The modified form.
   */
  public function build($form) {

    // Add js or the edit functionality.
    availability_calendars_add_js($this->node, NULL, 'edit');

    // Add form fields.
    $year = (int) date('Y');
    $month = (int) date('m');
    $form['availability_calendar'] = array(
      '#type' => 'markup',
      '#theme' => 'availability_calendars_node',
      '#markup' => '',
      '#prefix' => '<div class="description">' . t('To update the calendar: select a state (below the calendar) and click on a begin and end date. Repeat if needed. When finished, click on <em>@button</em>.', array(
        '@button' => t('Update'),
      )) . '</div>',
      '#node' => $this->node,
      '#year' => $year,
      '#month' => $month,
      '#settings' => $this->settings,
    );
    $options = array();
    foreach ($this->settings->states as $class => $state) {
      $options[$class] = t($state['label']);
    }
    $form['availability_states'] = array(
      '#type' => 'radios',
      '#title' => t('States'),
      '#default_value' => $this->settings->defaultstatus,
      '#options' => $options,
    );
    $form['availability_changes'] = array(
      '#type' => 'hidden',
      '#title' => t('Changes in availability'),
      '#default_value' => '',
      '#attributes' => array(
        'id' => 'edit-availability-changes',
      ),
    );

    // Add form button.
    $form['actions'] = array(
      '#type' => 'actions',
    );
    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Update'),
    );
    return $form;
  }

  /**
   * Callback to validate the form for the styles form.
   */
  public function validate($form, &$form_state) {
    $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
    if ($op == t('Update')) {
      $this->commands = array();
      $changes = $form_state['values']['availability_changes'];

      // Silently ignore empty updates.
      if (!empty($changes)) {
        $changes = explode("\n", $changes);
        foreach ($changes as $change) {

          // Ignore empty lines (e.g. the last line).
          if (!empty($change)) {
            $command = $this
              ->validateCommand($change);
            if ($command === FALSE) {
              form_set_error('availability_changes', t('The requested calendar changes contain an invalid request.'));
              break;
            }
            $this->commands[] = $command;
          }
        }
      }
    }
  }

  /**
   * Validates a single command line.
   *
   * @param string $change
   *   Command line: state: <string> from: yyyy-mm-dd[(pm)] to: yyyy-mm-dd[(am)]
   * @return boolean|array
   *   An array with key 'from', 'to' and 'state' representing the parsed and
   *   validated command line or FALSE on validation errors.
   */
  public function validateCommand($change) {

    // Basic syntax checking.
    $parts = explode(' ', trim($change));
    if (count($parts) !== 6 || $parts[0] !== 'state:' || !array_key_exists($parts[1], $this->settings->states) || $parts[2] !== 'from:' || preg_match('/^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9](\\(pm\\))?$/', $parts[3]) !== 1 || $parts[4] !== 'to:' || preg_match('/^[1-2][0-9]{3}-[0-1][0-9]-[0-3][0-9](\\(am\\))?$/', $parts[5]) !== 1) {
      return FALSE;
    }

    // Check dates: valid date, in between ranges of the calendar, no am/pm when no split days
    // allowed, and from <= to (including the pm/am modifier: this prevents the "same day from
    // pm to am" situation.
    $year = date('Y');
    $month = date('m');
    if (!checkdate(substr($parts[3], 5, 2), substr($parts[3], 8, 2), substr($parts[3], 0, 4)) || $parts[3] < date(AC_ISODATE, mktime(0, 0, 0, $month, 1, $year))) {
      return FALSE;
    }
    if (!checkdate(substr($parts[5], 5, 2), substr($parts[5], 8, 2), substr($parts[5], 0, 4)) || $parts[5] > date(AC_ISODATE, mktime(0, 0, 0, $month + $this->settings->monthcount + 1, 0, $year))) {
      return FALSE;
    }
    if ($this->settings->splitday == '0' && (strlen($parts[3]) > 10 || strlen($parts[5]) > 10)) {
      return FALSE;
    }
    if ($parts[3] > $parts[5]) {
      return FALSE;
    }
    return array(
      'from' => $parts[3],
      'to' => $parts[5],
      'state' => $parts[1],
    );
  }

  /**
   * Callback to process form submission for the styles form.
   */
  public function submit($form, &$form_state) {
    $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
    if ($op == t('Update')) {
      foreach ($this->commands as $command) {
        availability_calendars_update_node_states_range($this->settings->calendar_id, $command['from'], $command['to'], $command['state']);
      }

      // Redirect to node view (as is also done on the node edit form).
      $form_state['redirect'] = 'node/' . $this->node->nid;

      // Clear the page and block caches (don't regress #747992).
      entity_get_controller('node')
        ->resetCache(array(
        $this->settings->calendar_id,
      ));
      cache_clear_all();
      drupal_set_message(t('Availability information saved.'));
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AvailabilityCalendarsNodeEditCalendarFormHandler::$commands protected property @var $states array
AvailabilityCalendarsNodeEditCalendarFormHandler::$instance private static property
AvailabilityCalendarsNodeEditCalendarFormHandler::$node protected property @var $node object
AvailabilityCalendarsNodeEditCalendarFormHandler::$settings protected property @var $settings object
AvailabilityCalendarsNodeEditCalendarFormHandler::$states protected property @var $states array
AvailabilityCalendarsNodeEditCalendarFormHandler::build public function Builds the node/%node/availability-calendars page form.
AvailabilityCalendarsNodeEditCalendarFormHandler::instance public static function
AvailabilityCalendarsNodeEditCalendarFormHandler::submit public function Callback to process form submission for the styles form.
AvailabilityCalendarsNodeEditCalendarFormHandler::validate public function Callback to validate the form for the styles form.
AvailabilityCalendarsNodeEditCalendarFormHandler::validateCommand public function Validates a single command line.
AvailabilityCalendarsNodeEditCalendarFormHandler::__construct protected function