Google Programmable Search Engine allows the creation of custom search engines for a website. Integrating with the core Drupal search functionality, this module provides for the creation of search pages that use a JSON API to retrieve results from a Google custom search engine.

Support for both the Google Custom Search JSON API and the Google Custom Search Site Restricted JSON API is provided.

Previously, the google_cse module provided integration with Google Custom Search. However, Google rebranded as Google Programmable Search and the google_cse module does not provide support for the JSON APIs. After discussions with some of the google_cse maintainers, the google_cse module will also not support the JSON API going forward as indicated here: https://www.drupal.org/project/google_cse/issues/3279974

Project link

https://www.drupal.org/project/google_json_api

Git instructions

git clone --branch '1.0.x' https://git.drupalcode.org/project/google_json_api.git

Comments

tzura created an issue. See original summary.

LuongGiap’s picture

Status: Needs review » Needs work

Hi @tzura,
I ran Drupal Coding Standards, You can review and fix.

$ phpcs --standard=Drupal --extensions=php,module,inc,install,test,profile,theme,css,info,txt,md,yml web/modules/contrib/google_json_api

FILE: C:\Ampps\www\my_coding_review\web\modules\contrib\google_json_api\css\google_json_api.css
-----------------------------------------------------------------------------------------------
FOUND 9 ERRORS AFFECTING 6 LINES
-----------------------------------------------------------------------------------------------
 11 | ERROR | [x] Line indented incorrectly; expected 0 spaces, found 2
 11 | ERROR | [x] Whitespace found at end of line
 19 | ERROR | [x] Line indented incorrectly; expected 0 spaces, found 2
 19 | ERROR | [x] Whitespace found at end of line
 29 | ERROR | [x] Line indented incorrectly; expected 0 spaces, found 2
 29 | ERROR | [x] Whitespace found at end of line
 38 | ERROR | [x] Whitespace found at end of line
 62 | ERROR | [x] Expected 1 newline at end of file; 2 found
 63 | ERROR | [x] Additional whitespace found at end of file
-----------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 9 MARKED SNIFF VIOLATIONS AUTOMATICALLY
-----------------------------------------------------------------------------------------------


FILE: C:\Ampps\www\my_coding_review\web\modules\contrib\google_json_api\css\google_json_api_search_form.css
-----------------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
-----------------------------------------------------------------------------------------------------------
 53 | ERROR | [x] CSS colours must be defined in lowercase; expected #0071bc but found #0071BC
-----------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
-----------------------------------------------------------------------------------------------------------


FILE: C:\Ampps\www\my_coding_review\web\modules\contrib\google_json_api\google_json_api.info.yml
-------------------------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 3 WARNINGS AFFECTING 1 LINE
-------------------------------------------------------------------------------------------------------------
 1 | WARNING | Remove "project" from the info file, it will be added by drupal.org packaging automatically
 1 | WARNING | Remove "datestamp" from the info file, it will be added by drupal.org packaging automatically
 1 | WARNING | Remove "version" from the info file, it will be added by drupal.org packaging automatically
-------------------------------------------------------------------------------------------------------------


FILE: C:\Ampps\www\my_coding_review\web\modules\contrib\google_json_api\google_json_api.links.menu.yml
------------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
------------------------------------------------------------------------------------------------------
 6 | ERROR | [x] Expected 1 newline at end of file; 0 found
------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------------------


FILE: C:\Ampps\www\my_coding_review\web\modules\contrib\google_json_api\google_json_api.tokens.inc
--------------------------------------------------------------------------------------------------
FOUND 1 ERROR AND 1 WARNING AFFECTING 2 LINES
--------------------------------------------------------------------------------------------------
  6 | ERROR   | [x] There must be exactly one blank line after the file comment
 10 | WARNING | [x] Unused use statement
--------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
--------------------------------------------------------------------------------------------------

avpaderno’s picture

Issue summary: View changes
avpaderno’s picture

Title: Google Programmable Search JSON API » [D9] Google Programmable Search JSON API

Thank you for applying! Reviewers will review the project files, describing what needs to be changed.

Please read Review process for security advisory coverage: What to expect for more details and Security advisory coverage application checklist to understand what reviewers look for. Tips for ensuring a smooth review gives some hints for a smother review.

To reviewers: Please read How to review security advisory coverage applications, What to cover in an application review, and Drupal.org security advisory coverage application workflow.

Since the project is being used for this application, for the time this application is open, only the user who created the application can commit code.

timozura’s picture

Status: Needs work » Needs review

@LuongGiap Thanks for identifying the formatting issues. They have been corrected.

avpaderno’s picture

Status: Needs review » Needs work
  • What follows is a quick review of the project; it doesn't mean to be complete
  • Each review point doesn't show all the lines that should be changed; it shows a single example of what is wrong in the code
  • The review points are about code that doesn't follow the coding standards, contains possible security issue, or doesn't correctly use the Drupal API; they aren't listed in any particular order, not even in order of importance

The correct placeholder for URLs is :variable as shown in the documentation for FormattableMarkup::placeholderFormat(). That is the placeholder used also by Drupal core code for URLs that take to drupal.org.

      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Actions module provides tasks that can be executed by the site such as unpublishing content, sending email messages, or blocking a user. Other modules can trigger these actions when specific system events happen; for example, when new content is posted or when a user logs in. Modules can also provide additional actions. For more information, see the <a href=":documentation">online documentation for the Actions module</a>.', [
        ':documentation' => 'https://www.drupal.org/documentation/modules/action',
      ]) . '</p>';
 /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {

  }

If validation isn't required, that method can be removed.

    $config->save();

    return parent::submitForm($form, $form_state);

The parent method doesn't return any value, so return can be removed. To call the parent method, parent::submitForm($form, $form_state); is sufficient.

  /**
   * {@inheritdoc}
   */
  public function __construct(
      array $configuration,
      $plugin_id,
      $plugin_definition,
      ConfigFactoryInterface $configFactory,
      Client $httpClient,
      SearchPageRepositoryInterface $searchPageRepository,
      RequestStack $requestStack,
      Token $tokenManager,
      PagerManagerInterface $pagerManager
      ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->requestStack = $requestStack;
    $this->configFactory = $configFactory;
    $this->httpClient = $httpClient;
    $this->searchPageRepository = $searchPageRepository;
    $this->tokenManager = $tokenManager;
    $this->pagerManager = $pagerManager;
  }

For a class constructor, {@inheritdoc} isn't used.

  /**
   * {@inheritdoc}
   */
  public function getConfiguration() {
    return $this->configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function setConfiguration(array $configuration) {
    $this->configuration = $configuration;
  }

It's not necessary to implement those methods, since the parent class already implement them using that code.

        \Drupal::logger('google_json_api')
          ->error('Exception in GoogleJsonApiSearch::execute(): @message', ['@message' => $e->getMessage()]);
        return ['error' => TRUE];

Any dependency must be injected using Dependency Injection. To log an exception, the code used by watchdog_exception() should be used. The function is going to be deprecated in Drupal 10; that's why I am not suggesting to call it.

    $form['google_config_info']['cx'] = [
      '#title' => $this->t('Google Custom Search Engine ID'),
      '#type' => 'textfield',
      '#default_value' => $this->configuration['cx'] ?? '',
      '#description' => $this->t('Enter your @google (click on control panel).', [
        '@google' => Link::fromTextAndUrl('Google JSON API unique ID',
        Url::fromUri('http://www.google.com/cse/manage/all'))->toString(),
      ]),
      '#required' => TRUE,
    ];

See the previous point about the correct placeholder to use for URLs for how a URL is placed in a translatable string.

  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {

    $jsonapiconfig = $this->configFactory->getEditable('google_json_api.settings');

    $values = $form_state->getValues();
    $this->configuration['page_id'] = $values['id'];
    $this->configuration['path'] = $values['path'];
    $this->configuration['label'] = $values['label'];
    $this->configuration['cx'] = $values['cx'];
    $this->configuration['apikey'] = $values['apikey'];
    $this->configuration['apiendpoint'] = $values['apiendpoint'];
    $this->configuration['apiendpointurl'] = $jsonapiconfig->get('google_json_api.' . $values['apiendpoint']);
    $this->configuration['resultsperpage'] = $values['resultsperpage'];
    $this->configuration['displaysearchform'] = $values['displaysearchform'];
    $this->configuration['displaysearchpageselection'] = $values['displaysearchpageselection'];
    $this->configuration['displaysort'] = $values['displaysort'];
    $this->configuration['results_message'] = $values['results_message'];
    $this->configuration['results_message_singular'] = $values['results_message_singular'];
    $this->configuration['results_limitation_message'] = $values['results_limitation_message'];
    $this->configuration['no_results_message'] = $values['no_results_message'];
    $this->configuration['no_keywords_message'] = $values['no_keywords_message'];
    $this->configuration['results_last_page_message'] = $values['results_last_page_message'];
    $this->configuration['classsearchkeys'] = $values['classsearchkeys'];
    $this->configuration['classsearchsubmit'] = $values['classsearchsubmit'];
    $this->configuration['classsearchpageselect'] = $values['classsearchpageselect'];
    $this->configuration['classsearchsort'] = $values['classsearchsort'];

  }

See OEmbed::submitConfigurationForm() for how a plugin submits its configuration form. (Getting a configuration object from $this->configFactory->getEditable() isn't necessary.)

/**
 * Implements hook_help().
 *
 * @see hook_help()
 */

For hook documentation, it's necessary only the first line. The other one isn't necessary, since the first one already link the function to the hook_help() documentation.

timozura’s picture

Thanks, @apaderno

I've gone through your review and made appropriate changes. Appreciate your input.

avpaderno’s picture

Status: Needs work » Needs review
avpaderno’s picture

Assigned: Unassigned » avpaderno
Status: Needs review » Fixed

Thank you for your contribution! I am going to update your account.

These are some recommended readings to help with excellent maintainership:

You can find more contributors chatting on the Slack #contribute channel. So, come hang out and stay involved.
Thank you, also, for your patience with the review process.
Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

I thank all the reviewers too.

timozura’s picture

Thanks, @apaderno! Appreciate the assistance!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.