diff --git a/apigee_devportal_kickstart.install b/apigee_devportal_kickstart.install index afe6aab6..2a887034 100644 --- a/apigee_devportal_kickstart.install +++ b/apigee_devportal_kickstart.install @@ -23,9 +23,6 @@ * Install, update and uninstall functions for Apigee Kickstart profile. */ -use Drupal\apigee_devportal_kickstart\Installer\Form\ApigeeEdgeConfigurationForm; -use Drupal\Core\Messenger\MessengerInterface; - /** * Implements hook_install(). * @@ -78,65 +75,3 @@ function apigee_devportal_kickstart_install() { } } } - -/** - * Implements hook_install_tasks_alter(). - */ -function apigee_devportal_kickstart_install_tasks_alter(&$tasks, $install_state) { - // Add a task for configuring Apigee Edge Authentication. - $tasks_copy = $tasks; - $apigee_edge_configure_form = [ - 'apigee_edge_configure_form' => [ - 'display_name' => t('Configure Apigee Edge'), - 'type' => 'form', - 'function' => ApigeeEdgeConfigurationForm::class, - ], - ]; - - // The task should run before install_configure_form which creates the user. - $tasks = array_slice($tasks_copy, 0, array_search('install_configure_form', array_keys($tasks))) + $apigee_edge_configure_form + $tasks_copy; -} - -/** - * Implements hook_install_tasks(). - */ -function apigee_devportal_kickstart_install_tasks(&$install_state) { - $tasks = [ - '\Drupal\apigee_devportal_kickstart\Installer\Form\DemoInstallForm' => [ - 'display_name' => t('Install demo content'), - 'type' => 'form', - ], - 'apigee_devportal_kickstart_theme_setup' => [ - 'display_name' => t('Install theme'), - 'display' => FALSE, - ], - ]; - return $tasks; -} - -/** - * Install the theme. - * - * @param array $install_state - * The install state. - */ -function apigee_devportal_kickstart_theme_setup(array &$install_state) { - // Clear all status messages generated by modules installed in previous step. - Drupal::messenger()->deleteByType(MessengerInterface::TYPE_STATUS); - - // Set apigee_kickstart as the default theme. - \Drupal::configFactory() - ->getEditable('system.theme') - ->set('default', 'apigee_kickstart') - ->save(); - - // Ensure that the install profile's theme is used. - // @see _drupal_maintenance_theme() - \Drupal::service('theme.manager')->resetActiveTheme(); - - // Enable the admin theme for editing content. - \Drupal::configFactory() - ->getEditable('node.settings') - ->set('use_admin_theme', TRUE) - ->save(TRUE); -} diff --git a/apigee_devportal_kickstart.libraries.yml b/apigee_devportal_kickstart.libraries.yml new file mode 100644 index 00000000..c288deec --- /dev/null +++ b/apigee_devportal_kickstart.libraries.yml @@ -0,0 +1,5 @@ +apigee_edge_form: + version: VERSION + css: + theme: + css/apigee_devportal_kickstart.apigee_edge_form.css: {} diff --git a/apigee_devportal_kickstart.profile b/apigee_devportal_kickstart.profile index d36b61f3..bbce27a0 100644 --- a/apigee_devportal_kickstart.profile +++ b/apigee_devportal_kickstart.profile @@ -23,8 +23,162 @@ * Enables modules and site configuration for apigee_devportal_kickstart. */ +use Drupal\apigee_devportal_kickstart\Installer\ApigeeDevportalKickstartTasksManager; +use Drupal\apigee_devportal_kickstart\Installer\Form\ApigeeDevportalKickstartMonetizationConfigurationForm; +use Drupal\apigee_devportal_kickstart\Installer\Form\ApigeeEdgeConfigurationForm; +use Drupal\apigee_devportal_kickstart\Installer\Form\DemoInstallForm; use Drupal\contact\Entity\ContactForm; +use Drupal\Core\Extension\InfoParserException; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Messenger\MessengerInterface; + +/** + * Implements hook_install_tasks(). + */ +function apigee_devportal_kickstart_install_tasks(&$install_state) { + $tasks = [ + DemoInstallForm::class => [ + 'display_name' => t('Install demo content'), + 'type' => 'form', + ], + 'apigee_devportal_kickstart_theme_setup' => [ + 'display_name' => t('Install theme'), + 'display' => FALSE, + ], + ]; + + // Add monetization tasks if the configured organization is monetizable. + if (Drupal::moduleHandler()->moduleExists('apigee_edge') + && Drupal::hasService('address.subdivision_repository') + && Drupal::hasService('apigee_devportal_kickstart.monetization') && Drupal::service('apigee_devportal_kickstart.monetization')->isMonetizable()) { + $tasks = array_merge([ + ApigeeDevportalKickstartMonetizationConfigurationForm::class => [ + 'display_name' => t('Configure monetization'), + 'type' => 'form', + ], + 'apigee_devportal_setup_monetization' => [ + 'display_name' => t('Setup monetization'), + 'type' => 'batch', + ], + ], $tasks); + } + + return $tasks; +} + +/** + * Implements hook_install_tasks_alter(). + */ +function apigee_devportal_kickstart_install_tasks_alter(&$tasks, $install_state) { + // Add tasks for configuring Apigee authentication and monetization. + $apigee_kickstart_tasks = [ + ApigeeEdgeConfigurationForm::class => [ + 'display_name' => t('Configure Apigee Edge'), + 'type' => 'form', + ], + 'apigee_devportal_monetization_preflight' => [], + ]; + + // The task should run before install_configure_form which creates the user. + $tasks_copy = $tasks; + $tasks = array_slice($tasks_copy, 0, array_search('install_configure_form', array_keys($tasks))) + $apigee_kickstart_tasks + $tasks_copy; +} + +/** + * Prepares profile for monetization setup. + * + * @param array $install_state + * The install state. + */ +function apigee_devportal_monetization_preflight(array &$install_state) { + // The monetization configuration form needs an address field. + // Enable the address module. + try { + \Drupal::service('module_installer')->install(['address']); + } + catch (\Exception $exception) { + watchdog_exception('apigee_kickstart', $exception); + } +} + +/** + * Install task for setting up monetization and additional modules. + * + * @param array $install_state + * The install state. + * + * @return array + * A batch definition. + */ +function apigee_devportal_setup_monetization(array &$install_state) { + if (isset($install_state['m10n_config']) && ($config = $install_state['m10n_config'])) { + // Add an operations to install modules. + $operations = [ + [ + [ApigeeDevportalKickstartTasksManager::class, 'init'], + [$config] + ], + [ + [ApigeeDevportalKickstartTasksManager::class, 'installModules'], + [$config['modules']], + ], + ]; + + // Perform additional tasks for apigee_kickstart_m10n_add_credit. + if (in_array('apigee_kickstart_m10n_add_credit', $config['modules'])) { + $operations = array_merge($operations, [ + [ + [ApigeeDevportalKickstartTasksManager::class, 'importCurrencies'], + [$config['supported_currencies']], + ], + [ + [ApigeeDevportalKickstartTasksManager::class, 'createStore'], + [$config['store']], + ], + [ + [ApigeeDevportalKickstartTasksManager::class, 'createProducts'], + [$config['supported_currencies']], + ], + ]); + } + + $batch = [ + 'operations' => $operations, + 'title' => t('Setting up monetization'), + 'error_message' => t('The installation has encountered an error.'), + 'progress_message' => t('Completed @current out of @total tasks.'), + ]; + + return $batch; + } +} + +/** + * Install the theme. + * + * @param array $install_state + * The install state. + */ +function apigee_devportal_kickstart_theme_setup(array &$install_state) { + // Clear all status messages generated by modules installed in previous step. + Drupal::messenger()->deleteByType(MessengerInterface::TYPE_STATUS); + + // Set apigee_kickstart as the default theme. + \Drupal::configFactory() + ->getEditable('system.theme') + ->set('default', 'apigee_kickstart') + ->save(); + + // Ensure that the install profile's theme is used. + // @see _drupal_maintenance_theme() + \Drupal::service('theme.manager')->resetActiveTheme(); + + // Enable the admin theme for editing content. + \Drupal::configFactory() + ->getEditable('node.settings') + ->set('use_admin_theme', TRUE) + ->save(TRUE); +} /** * Implements hook_form_FORM_ID_alter() for install_configure_form(). @@ -40,5 +194,8 @@ function apigee_devportal_kickstart_form_install_configure_form_alter(&$form, Fo */ function apigee_devportal_kickstart_form_install_configure_submit($form, FormStateInterface $form_state) { $site_mail = $form_state->getValue('site_mail'); - ContactForm::load('feedback')->setRecipients([$site_mail])->trustData()->save(); + ContactForm::load('feedback') + ->setRecipients([$site_mail]) + ->trustData() + ->save(); } diff --git a/apigee_devportal_kickstart.services.yml b/apigee_devportal_kickstart.services.yml new file mode 100644 index 00000000..3576d562 --- /dev/null +++ b/apigee_devportal_kickstart.services.yml @@ -0,0 +1,4 @@ +services: + apigee_devportal_kickstart.monetization: + class: Drupal\apigee_devportal_kickstart\Installer\ApigeeDevportalKickstartMonetization + # We cannot pass constructor arguments here because dependent services do not exist at this point. diff --git a/css/apigee_devportal_kickstart.apigee_edge_form.css b/css/apigee_devportal_kickstart.apigee_edge_form.css new file mode 100644 index 00000000..8c9d72e0 --- /dev/null +++ b/css/apigee_devportal_kickstart.apigee_edge_form.css @@ -0,0 +1,23 @@ +/* + * Copyright 2018 Google Inc. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +.apigee-edge-authentication-form .messages--warning { + border-color: #0074bd; + box-shadow: -8px 0 0 #0074bd; + background-color: #e6f5ff; + background-image: url(../resources/apigee/questionmark-disc.svg); + color: #666666; +} diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/apigee_kickstart_m10n_add_credit.info.yml b/modules/custom/apigee_kickstart_m10n_add_credit/apigee_kickstart_m10n_add_credit.info.yml new file mode 100644 index 00000000..5804f11f --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/apigee_kickstart_m10n_add_credit.info.yml @@ -0,0 +1,8 @@ +name: Apigee Kickstart Monetization +description: "Handles monetization for Apigee Kickstart. Adds and configures a default product type for adding credit." +type: module +core: 8.x +package: Apigee Kickstart +dependencies: + - apigee_m10n:apigee_m10n + - apigee_m10n_add_credit:apigee_m10n_add_credit diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_order.commerce_order_item_type.add_credit.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_order.commerce_order_item_type.add_credit.yml new file mode 100644 index 00000000..02f80e35 --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_order.commerce_order_item_type.add_credit.yml @@ -0,0 +1,9 @@ +langcode: en +status: true +dependencies: { } +label: 'Add credit' +id: add_credit +purchasableEntityType: commerce_product_variation +orderType: default +traits: { } +locked: false diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_product.commerce_product_type.add_credit.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_product.commerce_product_type.add_credit.yml new file mode 100644 index 00000000..93a359d3 --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_product.commerce_product_type.add_credit.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - apigee_m10n_add_credit +third_party_settings: + apigee_m10n_add_credit: + apigee_m10n_enable_add_credit: true + apigee_m10n_enable_skip_cart: true +id: add_credit +label: 'Add credit' +description: 'This product is used to add credit to prepaid balances.' +variationType: add_credit +multipleVariations: true +injectVariationFields: true +traits: { } +locked: false diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_product.commerce_product_variation_type.add_credit.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_product.commerce_product_variation_type.add_credit.yml new file mode 100644 index 00000000..54124fdc --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/commerce_product.commerce_product_variation_type.add_credit.yml @@ -0,0 +1,9 @@ +langcode: en +status: true +dependencies: { } +id: add_credit +label: 'Add credit' +orderItemType: add_credit +generateTitle: false +traits: { } +locked: false diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_order_item.add_credit.add_to_cart.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_order_item.add_credit.add_to_cart.yml new file mode 100644 index 00000000..cc72a98e --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_order_item.add_credit.add_to_cart.yml @@ -0,0 +1,36 @@ +langcode: en +status: true +dependencies: + config: + - commerce_order.commerce_order_item_type.add_credit + - core.entity_form_mode.commerce_order_item.add_to_cart + module: + - apigee_m10n_add_credit + - commerce_price + - commerce_product +id: commerce_order_item.add_credit.add_to_cart +targetEntityType: commerce_order_item +bundle: add_credit +mode: add_to_cart +content: + add_credit_target: + type: add_credit_target_entity + weight: 1 + region: content + settings: { } + third_party_settings: { } + purchased_entity: + type: commerce_product_variation_attributes + weight: 0 + region: content + settings: { } + third_party_settings: { } + unit_price: + type: commerce_unit_price + weight: 2 + region: content + settings: { } + third_party_settings: { } +hidden: + created: true + quantity: true diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_product.add_credit.default.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_product.add_credit.default.yml new file mode 100644 index 00000000..c5d8f6f7 --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_product.add_credit.default.yml @@ -0,0 +1,79 @@ +langcode: en +status: true +dependencies: + config: + - commerce_product.commerce_product_type.add_credit + - field.field.commerce_product.add_credit.body + - field.field.commerce_product.add_credit.stores + module: + - commerce + - path + - text +id: commerce_product.add_credit.default +targetEntityType: commerce_product +bundle: add_credit +mode: default +content: + apigee_add_credit_enabled: + weight: 25 + region: content + settings: + display_label: true + third_party_settings: { } + type: boolean_checkbox + body: + type: text_textarea_with_summary + weight: 1 + settings: + rows: 9 + summary_rows: 3 + placeholder: '' + third_party_settings: { } + region: content + created: + type: datetime_timestamp + weight: 10 + region: content + settings: { } + third_party_settings: { } + path: + type: path + weight: 30 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 90 + region: content + third_party_settings: { } + stores: + type: commerce_entity_select + weight: -10 + settings: + hide_single_entity: true + autocomplete_threshold: 7 + autocomplete_size: 60 + autocomplete_placeholder: '' + third_party_settings: { } + region: content + title: + type: string_textfield + weight: -5 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 5 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } +hidden: { } diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_product_variation.add_credit.default.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_product_variation.add_credit.default.yml new file mode 100644 index 00000000..f6a52cb7 --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_form_display.commerce_product_variation.add_credit.default.yml @@ -0,0 +1,39 @@ +langcode: en +status: true +dependencies: + config: + - commerce_product.commerce_product_variation_type.add_credit + module: + - apigee_m10n_add_credit +id: commerce_product_variation.add_credit.default +targetEntityType: commerce_product_variation +bundle: add_credit +mode: default +content: + apigee_price_range: + type: price_range_default + weight: 1 + region: content + settings: { } + third_party_settings: { } + sku: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 2 + region: content + third_party_settings: { } +hidden: + created: true + list_price: true + price: true + title: true + uid: true diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_view_display.commerce_product.add_credit.default.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_view_display.commerce_product.add_credit.default.yml new file mode 100644 index 00000000..a8c8712e --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_view_display.commerce_product.add_credit.default.yml @@ -0,0 +1,44 @@ +langcode: en +status: true +dependencies: + config: + - commerce_product.commerce_product_type.add_credit + - field.field.commerce_product.add_credit.body + - field.field.commerce_product.add_credit.stores + - field.field.commerce_product.add_credit.variations + module: + - commerce_product + - text +id: commerce_product.add_credit.default +targetEntityType: commerce_product +bundle: add_credit +mode: default +content: + body: + label: hidden + type: text_default + weight: 2 + settings: { } + third_party_settings: { } + region: content + title: + label: hidden + type: string + weight: 0 + region: content + settings: + link_to_entity: false + third_party_settings: { } + variations: + type: commerce_add_to_cart + weight: 1 + label: hidden + settings: + combine: true + third_party_settings: { } + region: content +hidden: + apigee_add_credit_enabled: true + created: true + stores: true + uid: true diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_view_display.commerce_product_variation.add_credit.default.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_view_display.commerce_product_variation.add_credit.default.yml new file mode 100644 index 00000000..481833c9 --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/core.entity_view_display.commerce_product_variation.add_credit.default.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + config: + - commerce_product.commerce_product_variation_type.add_credit +id: commerce_product_variation.add_credit.default +targetEntityType: commerce_product_variation +bundle: add_credit +mode: default +content: { } +hidden: + apigee_price_range: true + list_price: true + price: true + product_id: true + sku: true + title: true diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.body.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.body.yml new file mode 100644 index 00000000..22871c9b --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.body.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - commerce_product.commerce_product_type.add_credit + - field.storage.commerce_product.body + module: + - text +id: commerce_product.add_credit.body +field_name: body +entity_type: commerce_product +bundle: add_credit +label: Body +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: null +settings: + display_summary: false +field_type: text_with_summary diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.stores.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.stores.yml new file mode 100644 index 00000000..ad7703a1 --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.stores.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - commerce_product.commerce_product_type.add_credit + - field.storage.commerce_product.stores +id: commerce_product.add_credit.stores +field_name: stores +entity_type: commerce_product +bundle: add_credit +label: Stores +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: null +settings: + handler: 'default:commerce_store' + handler_settings: { } +field_type: entity_reference diff --git a/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.variations.yml b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.variations.yml new file mode 100644 index 00000000..5adea712 --- /dev/null +++ b/modules/custom/apigee_kickstart_m10n_add_credit/config/install/field.field.commerce_product.add_credit.variations.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - commerce_product.commerce_product_type.add_credit + - commerce_product.commerce_product_variation_type.add_credit + - field.storage.commerce_product.variations +id: commerce_product.add_credit.variations +field_name: variations +entity_type: commerce_product +bundle: add_credit +label: Variations +description: '' +required: true +translatable: false +default_value: { } +default_value_callback: null +settings: + handler: 'default:commerce_product_variation' + handler_settings: + target_bundles: + - add_credit +field_type: entity_reference diff --git a/resources/apigee/questionmark-disc.svg b/resources/apigee/questionmark-disc.svg new file mode 100644 index 00000000..1363940d --- /dev/null +++ b/resources/apigee/questionmark-disc.svg @@ -0,0 +1 @@ + diff --git a/src/Installer/ApigeeDevportalKickstartMonetization.php b/src/Installer/ApigeeDevportalKickstartMonetization.php new file mode 100644 index 00000000..7dd42e1b --- /dev/null +++ b/src/Installer/ApigeeDevportalKickstartMonetization.php @@ -0,0 +1,83 @@ +getClient()); + $organization = $organization_controller->load($sdk_connector->getOrganization()); + return ($organization->getPropertyValue('features.isMonetizationEnabled') === 'true'); + } + catch (\Exception $exception) { + // Do not log the exception here. This litters the logs since this is run + // before each install tasks. + } + + return FALSE; + } + + /** + * Check if all dependencies are met. + * + * @return bool + * TRUE if all dependencies are met. FALSE otherwise. + */ + protected static function meetsDependencies(): bool { + $extension_list = \Drupal::service('extension.list.module'); + foreach (static::dependencies() as $dependency) { + if (!$extension_list->exists($dependency)) { + return FALSE; + } + } + + return TRUE; + } + + /** + * Returns an array of module names required for monetization. + * + * @return array + * An array of module names. + */ + protected static function dependencies(): array { + return [ + 'address', + 'apigee_m10n', + 'apigee_m10n_add_credit', + 'commerce', + ]; + } + +} diff --git a/src/Installer/ApigeeDevportalKickstartTasksManager.php b/src/Installer/ApigeeDevportalKickstartTasksManager.php new file mode 100644 index 00000000..ec374e02 --- /dev/null +++ b/src/Installer/ApigeeDevportalKickstartTasksManager.php @@ -0,0 +1,159 @@ +install($modules); + $context['message'] = t('Installed monetization modules.'); + } + catch (\Exception $exception) { + watchdog_exception('apigee_kickstart', $exception); + } + } + + /** + * {@inheritdoc} + */ + public static function importCurrencies(array $currencies, array &$context) { + foreach ($currencies as $currency) { + // Import the currency. + \Drupal::service('commerce_price.currency_importer')->import($currency->getName()); + } + + $context['message'] = t('Imported supported currencies.'); + } + + /** + * {@inheritdoc} + */ + public static function createStore(array $values, array &$context) { + try { + $store = \Drupal::entityTypeManager()->getStorage('commerce_store') + ->create($values); + $store->save(); + + // Save to context. + $context['results']['store'] = $store; + $context['message'] = t('Created a default store.'); + } + catch (\Exception $exception) { + watchdog_exception('apigee_kickstart', $exception); + } + } + + /** + * {@inheritdoc} + */ + public static function createPaymentGateway(array $values, array &$context) { + try { + $gateway = \Drupal::entityTypeManager()->getStorage('commerce_payment_gateway') + ->create($values); + $gateway->save(); + + // Save to context. + $context['results']['$gateway'] = $gateway; + $context['message'] = t('Created a default payment gateway.'); + } + catch (\Exception $exception) { + watchdog_exception('apigee_kickstart', $exception); + } + } + + /** + * {@inheritdoc} + */ + public static function createProducts(array $currencies, array &$context) { + if (isset($context['results']['store'])) { + $add_credit_products = []; + + /** @var \Apigee\Edge\Api\Monetization\Entity\SupportedCurrencyInterface $currency */ + foreach ($currencies as $currency) { + try { + $minimum_amount = (string) $currency->getMinimumTopUpAmount(); + $currency_code = $currency->getName(); + // Create a product variation for this currency. + /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ + $variation = \Drupal::entityTypeManager()->getStorage('commerce_product_variation') + ->create([ + 'type' => 'add_credit', + 'sku' => "ADD-CREDIT-{$currency->getName()}", + 'title' => $currency->getName(), + 'status' => 1, + 'price' => new Price($minimum_amount, $currency_code), + ]); + $variation->set('apigee_price_range', [ + 'minimum' => $minimum_amount, + 'maximum' => 999, + 'default' => $minimum_amount, + 'currency_code' => $currency_code, + ]); + $variation->save(); + + // Create an add credit product for this currency. + $product = \Drupal::entityTypeManager()->getStorage('commerce_product') + ->create([ + 'title' => $currency->getName(), + 'type' => 'add_credit', + 'stores' => [$context['results']['store']], + 'variations' => [$variation], + AddCreditConfig::ADD_CREDIT_ENABLED_FIELD_NAME => 1, + ]); + $product->save(); + + $add_credit_products[$currency->getId()] = [ + 'product_id' => $product->id(), + ]; + + // Save config. + \Drupal::configFactory() + ->getEditable(AddCreditConfig::CONFIG_NAME) + ->set('products', $add_credit_products) + ->save(); + + $context['message'] = t('Created default products.'); + } + catch (\Exception $exception) { + watchdog_exception('apigee_kickstart', $exception); + } + } + } + } + +} diff --git a/src/Installer/ApigeeDevportalKickstartTasksManagerInterface.php b/src/Installer/ApigeeDevportalKickstartTasksManagerInterface.php new file mode 100644 index 00000000..a6b84a03 --- /dev/null +++ b/src/Installer/ApigeeDevportalKickstartTasksManagerInterface.php @@ -0,0 +1,88 @@ +sdkConnector = $sdk_connector; + $this->languageManager = $language_manager; + $this->subdivisionRepository = $subdivision_repository; + $this->currencyRepository = new CurrencyRepository(); + + try { + $organization_id = $this->sdkConnector->getOrganization(); + $client = $this->sdkConnector->getClient(); + + // TODO: Figure out if we need to cache these values here. + // This happens only once during installation. We probably do not need to + // cache these values? + $organization_controller = new OrganizationController($client); + $organization = $organization_controller->load($organization_id); + /** @var \Apigee\Edge\Api\Management\Entity\OrganizationInterface $organization */ + if ($this->isMonetizable = $organization->getPropertyValue('features.isMonetizationEnabled') === 'true') { + // Set the organization. + $organization_profile_controller = new OrganizationProfileController($organization_id, $client); + $this->organization = $organization_profile_controller->load($organization_id); + + // Set supported currencies. + $supported_currency_controller = new SupportedCurrencyController($organization_id, $client); + $this->supportedCurrencies = $supported_currency_controller->getEntities(); + } + } + catch (\Exception $exception) { + watchdog_exception('apigee_kickstart', $exception); + } + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('apigee_edge.sdk_connector'), + $container->get('language_manager'), + $container->get('address.subdivision_repository') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'apigee_devportal_kickstart_m10n_configuration_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + // Some messages stick around for installation tasks. Clear them all. + $this->messenger()->deleteAll(); + + $form['#title'] = $this->t('Configure monetization'); + + $form['actions']['#type'] = 'actions'; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Continue'), + '#submit' => [[$this, 'skipStepSubmit']], + '#validate' => [], + '#limit_validation_errors' => [], + ]; + + // If monetization is not enabled, show a message and continue. + if (!$this->isMonetizable) { + $form['message'] = [ + '#theme' => 'status_messages', + '#message_list' => [ + MessengerInterface::TYPE_WARNING => [ + $this->t('Monetization is not enabled for your organization'), + ], + ], + ]; + + return $form; + } + + $form['modules'] = [ + '#type' => 'container', + '#tree' => TRUE, + ]; + + $form['modules']['apigee_m10n'] = [ + '#title' => $this->t('Enable monetization'), + '#type' => 'checkbox', + '#description' => $this->t('Enable monetization for your Apigee Edge organization.'), + ]; + + $form['modules']['apigee_kickstart_m10n_add_credit'] = [ + '#title' => $this->t('Enable prepaid balance top up'), + '#type' => 'checkbox', + '#description' => $this->t('Allow users to add credit to their prepaid balances.'), + '#states' => [ + 'visible' => [ + 'input[name="modules[apigee_m10n]"]' => ['checked' => TRUE], + ], + ], + ]; + + $form['store'] = [ + '#type' => 'details', + '#title' => $this->t('Store'), + '#open' => TRUE, + '#tree' => TRUE, + '#description' => $this->t('Create a store for handling prepaid balance top ups.'), + '#states' => [ + 'visible' => [ + 'input[name="modules[apigee_m10n]"]' => ['checked' => TRUE], + 'input[name="modules[apigee_kickstart_m10n_add_credit]"]' => ['checked' => TRUE], + ], + ], + ]; + + $site_config = $this->configFactory()->get('system.site'); + $form['store']['name'] = [ + '#title' => $this->t('Name'), + '#type' => 'textfield', + '#placeholder' => $this->t('Name of store'), + '#default_value' => $site_config->get('name'), + '#states' => [ + 'required' => [ + 'input[name="modules[apigee_kickstart_m10n_add_credit]"]' => ['checked' => TRUE], + ], + ], + ]; + + $form['store']['mail'] = [ + '#title' => $this->t('Email'), + '#type' => 'email', + '#placeholder' => $this->t('admin@example.com'), + '#default_value' => $site_config->get('mail'), + '#description' => $this->t('Store email notifications are sent from this address.'), + '#states' => [ + 'required' => [ + 'input[name="modules[apigee_kickstart_m10n_add_credit]"]' => ['checked' => TRUE], + ], + ], + ]; + + $form['store']['default_currency'] = [ + '#type' => 'value', + '#value' => $this->organization->getCurrencyCode(), + ]; + + $form['store']['type'] = [ + '#type' => 'value', + '#value' => 'online', + ]; + + // Create individual address fields. + // We cannot use the address field because #ajax forms won't work in the + // installer. + $form['store']['address'] = [ + '#type' => 'tree', + ]; + + $form['store']['address']['country_code'] = [ + '#title' => $this->t('Country'), + '#type' => 'address_country', + '#required' => TRUE, + ]; + + $address_fields = [ + AddressField::ADDRESS_LINE1 => [ + 'size' => 60, + 'placeholder' => 'Acme Street', + ], + AddressField::ADDRESS_LINE2 => [ + 'size' => 60, + 'placeholder' => '', + ], + AddressField::LOCALITY => [ + 'size' => 30, + 'placeholder' => 'Santa Clara', + ], + AddressField::ADMINISTRATIVE_AREA => [ + 'size' => 30, + 'placeholder' => 'CA', + ], + AddressField::POSTAL_CODE => [ + 'size' => 10, + 'placeholder' => '95050', + ], + ]; + $labels = LabelHelper::getGenericFieldLabels(); + foreach ($address_fields as $address_field => $settings) { + $form['store']['address'][FieldHelper::getPropertyName($address_field)] = [ + '#title' => $labels[$address_field], + '#type' => 'textfield', + '#size' => $settings['size'], + '#placeholder' => $settings['placeholder'], + ]; + } + + // Add default address from organization. + if ($addresses = $this->organization->getAddresses()) { + /** @var \Apigee\Edge\Api\Monetization\Structure\Address $address */ + $address = reset($addresses); + + $form['store']['address']['country_code']['#default_value'] = $address->getCountry(); + $form['store']['address'][FieldHelper::getPropertyName(AddressField::ADDRESS_LINE1)]['#default_value'] = $address->getAddress1(); + $form['store']['address'][FieldHelper::getPropertyName(AddressField::ADDRESS_LINE1)]['#default_value'] = $address->getAddress1(); + $form['store']['address'][FieldHelper::getPropertyName(AddressField::LOCALITY)]['#default_value'] = $address->getCity(); + $form['store']['address'][FieldHelper::getPropertyName(AddressField::ADMINISTRATIVE_AREA)]['#default_value'] = $address->getState(); + $form['store']['address'][FieldHelper::getPropertyName(AddressField::POSTAL_CODE)]['#default_value'] = $address->getZip(); + } + + if (count($this->supportedCurrencies)) { + $form['currencies'] = [ + '#type' => 'details', + '#title' => $this->t('Currencies'), + '#open' => TRUE, + '#description' => $this->t('Create a product to add credit for the following supported currencies.'), + '#states' => [ + 'visible' => [ + 'input[name="modules[apigee_m10n]"]' => ['checked' => TRUE], + 'input[name="modules[apigee_kickstart_m10n_add_credit]"]' => ['checked' => TRUE], + ], + ], + ]; + + $currency_options = []; + $importable_currencies = $this->getImportableCurrencies(); + foreach ($this->supportedCurrencies as $currency) { + if ($currency->getStatus() === 'ACTIVE' && isset($importable_currencies[$currency->getName()])) { + $currency_options[$currency->getName()] = "{$currency->getDisplayName()} ({$currency->getName()})"; + } + } + + $form['currencies']['supported_currencies'] = [ + '#type' => 'checkboxes', + '#options' => $currency_options, + '#default_value' => array_keys($currency_options), + ]; + } + + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Save and continue'), + '#button_type' => 'primary', + ]; + + // Add a skip this step button. + $form['actions']['skip'] = [ + '#type' => 'submit', + '#value' => $this->t('Skip this step'), + '#submit' => [[$this, 'skipStepSubmit']], + '#validate' => [], + '#limit_validation_errors' => [], + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + parent::validateForm($form, $form_state); + + // Validate administrative area. + if (($store = $form_state->getValue('store')) + && ($address = $store['address']) + && ($property_name = FieldHelper::getPropertyName(AddressField::ADMINISTRATIVE_AREA)) + && isset($address[$property_name]) + && ($subdivisions = $this->subdivisionRepository->getList([$address['country_code']])) + && !isset($subdivisions[strtoupper($address[$property_name])]) + ) { + $form_state->setErrorByName('address][' . $property_name, $this->t('Please enter a valid administrative area.')); + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $form_state->cleanValues(); + $values = $form_state->getValues(); + $values['modules'] = array_keys(array_filter($values['modules'])); + + if (count($values['modules'])) { + // Update the supported currencies. + if (isset($values['supported_currencies'])) { + $supported_currencies = array_keys(array_filter($values['supported_currencies'])); + $values['supported_currencies'] = []; + foreach ($supported_currencies as $currency_code) { + $values['supported_currencies'][$currency_code] = $this->supportedCurrencies[strtolower($currency_code)]; + } + } + + // Save to install state. + $buildInfo = $form_state->getBuildInfo(); + $buildInfo['args'][0]['m10n_config'] = $values; + $form_state->setBuildInfo($buildInfo); + } + } + + /** + * Provides a submit handler for the skip step button. + * + * @param array $form + * The form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The form state. + */ + public function skipStepSubmit(array $form, FormStateInterface $form_state) { + global $install_state; + $install_state['completed_task'] = install_verify_completed_task(); + } + + /** + * Helper to get importable currencies. + * + * @return array|\CommerceGuys\Intl\Currency\Currency[] + * An array of importable currencies. + */ + protected function getImportableCurrencies() { + $language = $this->languageManager->getConfigOverrideLanguage() ?: $this->languageManager->getCurrentLanguage(); + return $this->currencyRepository->getAll($language->getId()); + } + +} diff --git a/src/Installer/Form/ApigeeEdgeConfigurationForm.php b/src/Installer/Form/ApigeeEdgeConfigurationForm.php index 034c9cce..160058ee 100644 --- a/src/Installer/Form/ApigeeEdgeConfigurationForm.php +++ b/src/Installer/Form/ApigeeEdgeConfigurationForm.php @@ -55,6 +55,9 @@ public function buildForm(array $form, FormStateInterface $form_state) { // Hide the test_connection fields. $form['test_connection']['#access'] = FALSE; + // Rename the submit button. + $form['actions']['submit']['#value'] = $this->t('Save and continue'); + // Add a skip this step button. $form['actions']['skip'] = [ '#type' => 'submit', @@ -64,6 +67,8 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#limit_validation_errors' => [], ]; + $form['#attached']['library'][] = 'apigee_devportal_kickstart/apigee_edge_form'; + return $form; }