You are here

pwa_webpush.admin.inc in Progressive Web App 7.2

PWA administration forms.

File

modules/pwa_webpush/pwa_webpush.admin.inc
View source
<?php

/**
 * @file
 * PWA administration forms.
 */
use Minishlink\WebPush\Encryption;

/**
 * Configure PWA settings for Web Push notifications.
 */
function pwa_webpush_admin_configuration() {
  $form = [];
  $form['pwa_webpush_autoregister'] = [
    '#type' => 'checkbox',
    '#title' => t('Autoregister Push notifications'),
    '#description' => t('For users who granted the notification permission, we can autoregister them to push notifications. This helps to keep users subscribed when the serviceworker changes.'),
    '#default_value' => (bool) variable_get('pwa_webpush_autoregister', TRUE),
  ];
  $form['webpush'] = [
    '#type' => 'fieldset',
    '#title' => t('WebPush library settings'),
    '#description' => t('Settings for the <code>minishlink/web-push</code> library'),
  ];
  $payload_length = (string) Encryption::MAX_PAYLOAD_LENGTH;
  $form['webpush']['pwa_webpush_notification_padding'] = [
    '#type' => 'textfield',
    '#title' => t('Automatic padding size'),
    '#required' => TRUE,
    '#attributes' => [
      'min' => 0,
      'max' => $payload_length,
    ],
    '#default_value' => variable_get('pwa_webpush_notification_padding', PWA_WEBPUSH_AUTOMATIC_PADDING_LIMIT),
    '#size' => 5,
    '#description' => t('Automatic padding is a security feature. If set higher than @limit it is possible to have <a href="@webpush_firefox">issues delivering notifications</a> to Firefox mobile. The webpush library default is @default.', [
      '@limit' => PWA_WEBPUSH_AUTOMATIC_PADDING_LIMIT,
      '@webpush_firefox' => 'https://github.com/web-push-libs/web-push-php/issues/108#issuecomment-390811099',
      '@default' => Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH,
    ]),
  ];
  $form['webpush']['pwa_webpush_notification_batchsize'] = [
    '#title' => t('Delivery batch size'),
    '#type' => 'textfield',
    '#default_value' => variable_get('pwa_webpush_notification_batchsize', 1000),
    '#size' => 5,
    '#description' => t("If you send tens of thousands notifications at a time, you may get memory overflows due to how endpoints are called in Guzzle. In order to fix this, WebPush sends notifications in batches. The default size is 1000. Depending on your server configuration (memory), you may want to decrease this number."),
  ];
  $form['webpush']['pwa_webpush_notification_ttl'] = [
    '#title' => t('Notification Time To Live (in seconds)'),
    '#type' => 'select',
    '#options' => [
      '2419200' => t('4 weeks'),
      '86400' => t('24 hours'),
      '43200' => t('12 hours'),
      '0' => t('None (0s)'),
    ],
    '#default_value' => variable_get('pwa_webpush_notification_ttl', 2419200),
    '#description' => t("Defines how long a push message is retained by the push service (eg. Mozilla) in case the user browser is not yet accessible (eg. is not connected). You may want to use a very long time for important notifications. The default TTL is 4 weeks. However, if you send multiple nonessential notifications, set a TTL of 0: the push notification will be delivered only if the user is currently connected. For other cases, you should use a minimum of one day if your users have multiple time zones, and if they don't several hours will suffice."),
  ];
  $form['webpush']['vapid'] = [
    '#type' => 'fieldset',
    '#title' => t('Voluntary Application Server Identification'),
    '#description' => t('Manage <a href="@vapid">VAPID</a> configuration for Web Push.', [
      '@vapid' => 'https://tools.ietf.org/html/draft-ietf-webpush-vapid-01',
    ]),
    '#collapsible' => TRUE,
    '#collapsed' => !empty(variable_get('pwa_webpush_vapid_public', '')) && !empty(variable_get('pwa_webpush_vapid_private', '')),
  ];
  $form['webpush']['vapid']['pwa_webpush_vapid_subject'] = [
    '#type' => 'textfield',
    '#title' => t('Subject'),
    '#required' => TRUE,
    '#description' => t('Optional, Contact details, can be a mailto: or https: URI.'),
    '#default_value' => variable_get('pwa_webpush_vapid_subject', 'mailto:' . variable_get('site_mail', '')),
  ];
  $form['webpush']['vapid']['pwa_webpush_vapid_public'] = [
    '#type' => 'textfield',
    '#title' => t('Public key'),
    // 87 char string
    '#size' => 120,
    '#required' => TRUE,
    '#description' => t('Base64 encoded private key.'),
    // If the key is already set it can not be changed in the UI.
    '#disabled' => !empty(variable_get('pwa_webpush_vapid_public', '')),
    '#default_value' => variable_get('pwa_webpush_vapid_public', ''),
  ];
  $form['webpush']['vapid']['pwa_webpush_vapid_private'] = [
    '#type' => 'textfield',
    '#title' => t('Private key'),
    // 43 char string
    '#size' => 60,
    '#required' => TRUE,
    '#description' => t('Base64 encoded private key.'),
    // If the key is already set it can not be changed in the UI.
    '#disabled' => !empty(variable_get('pwa_webpush_vapid_private', '')),
    '#default_value' => variable_get('pwa_webpush_vapid_private', ''),
  ];
  $form = system_settings_form($form);
  return $form;
}
function pwa_webpush_admin_configuration_validate($form, &$form_state) {
  $values =& $form_state['values'];
  $padding = (int) $values['pwa_webpush_notification_padding'];
  if ($padding > Encryption::MAX_PAYLOAD_LENGTH) {
    form_set_error('pwa_webpush_notification_padding', t('The padding size is higher than the maximum payload size allowed, the value must be smaller than @limit', [
      '@limit' => Encryption::MAX_PAYLOAD_LENGTH,
    ]));
  }
  elseif ($padding < 0) {
    form_set_error('pwa_webpush_notification_padding', t('The padding size must be higher or equal to 0'));
  }
  else {
    if ($padding > PWA_WEBPUSH_AUTOMATIC_PADDING_LIMIT) {
      drupal_set_message(t('Automatic padding is set higher than @limit, there might be problems delivering notifications to Firefox Mobile users.', [
        '@limit' => PWA_WEBPUSH_AUTOMATIC_PADDING_LIMIT,
      ]), 'warning');
    }
  }
}

/**
 * @param $form
 * @param $form_state
 */
function pwa_webpush_send_notification($form, &$form_state) {

  // Only users that have an active subscription.
  $uids = db_query('SELECT DISTINCT(uid) FROM {pwa_webpush_subscription} WHERE expired = 0')
    ->fetchCol();
  $users = user_load_multiple($uids);
  $form['users'] = [
    '#type' => 'select',
    '#title' => t('Send notification to users'),
    '#description' => t('Only users who have an active subscriptions are listed.'),
    '#required' => TRUE,
    '#multiple' => TRUE,
    '#options' => array_map(function ($u) {
      return $u->uid == 0 ? 'anonymous' : $u->name;
    }, $users),
  ];
  $form['notification'] = [
    '#type' => 'fieldset',
    '#title' => t('Notification'),
  ];
  $form['notification']['title'] = [
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#required' => TRUE,
    '#description' => '',
    '#default_value' => '',
  ];
  $form['notification']['body'] = [
    '#type' => 'textarea',
    '#title' => t('Body (plain text)'),
    '#required' => TRUE,
    '#description' => '',
    '#default_value' => '',
  ];
  $form['notification']['url'] = [
    '#type' => 'textfield',
    '#title' => t('URL'),
    '#description' => t('Destination when clicking on the notification.'),
    '#default_value' => url('<front>', [
      'absolute' => TRUE,
    ]),
  ];
  $form['metadata'] = [
    '#type' => 'fieldset',
    '#title' => t('Metadata'),
  ];

  // Get icons from the manifest file.
  $icons = [];
  foreach (_pwa_manifest_file()['icons'] as $icon) {
    $icons[$icon['src']] = basename($icon['src']) . ' (' . $icon['sizes'] . ')';
  }
  $form['metadata']['icon'] = [
    '#type' => 'select',
    '#title' => t('Notification icon'),
    '#description' => '',
    '#options' => $icons,
  ];
  $form['metadata']['tag'] = [
    '#type' => 'textfield',
    '#title' => t('Tag'),
    '#description' => t('Used to group and manage notifications on the client side.'),
    '#default_value' => '',
  ];
  $form['actions'] = [];
  $form['actions']['submit'] = [
    '#type' => 'submit',
    '#value' => t('Send notification'),
  ];
  return $form;
}

/**
 * @param $form
 * @param $form_state
 */
function pwa_webpush_send_notification_validate($form, &$form_state) {
  $values = $form_state['values'];
}

/**
 * @param $form
 * @param $form_state
 */
function pwa_webpush_send_notification_submit($form, &$form_state) {
  $values = $form_state['values'];
  $payload = array_filter([
    'title' => $values['title'],
    'body' => $values['body'],
    'icon' => $values['icon'],
    'tag' => $values['tag'],
    'data' => [
      'url' => $values['url'],
    ],
  ]);
  $users = array_values($values['users']);
  watchdog('webpush', 'Notification sent to users: %users. <br> <pre>@payload</pre>', [
    '%users' => implode(', ', $users),
    '@payload' => json_encode($payload, JSON_PRETTY_PRINT),
  ]);
  pwa_webpush_send($payload, $users);
}