{"action":"created","comment":{"url":"https://api.github.com/repos/ding2/bpi/pulls/comments/39493873","id":39493873,"diff_hunk":"@@ -543,3 +688,217 @@ function bpi_syndicate_action($bpi_id) {\n     drupal_goto('admin/bpi');\n   }\n }\n+\n+/**\n+ * Build facets form fields.\n+ *\n+ * @param array $form\n+ *   The form.\n+ */\n+function bpi_build_search_facets(array &$form) {\n+  $facets = bpi_get_facets();\n+\n+  if ($facets) {\n+    $filter_form = array(\n+      '#type' => 'fieldset',\n+      '#title' => t('Filters'),\n+      '#collapsible' => TRUE,\n+      '#collapsed' => !_bpi_is_filter_applied(),\n+      '#attributes' => array(\n+        'class' => array(\n+          'bpi-filters',\n+        ),\n+      ),\n+    );\n+\n+    $facets_form = array(\n+      '#type' => 'container',\n+      '#tree' => TRUE,\n+      '#attributes' => array(\n+        'class' => array(\n+          'bpi-facets',\n+        ),\n+      ),\n+    );\n+\n+    $use_chosen = TRUE;\n+\n+    if ($use_chosen) {\n+      $form['#attached']['css'][] = drupal_get_path('module', 'bpi') . '/js/chosen/chosen.min.css';\n+      $form['#attached']['js'][] = drupal_get_path('module', 'bpi') . '/js/chosen/chosen.jquery.min.js';\n+    }\n+\n+    foreach ($facets as $name => $terms) {\n+      $id = $name;\n+      $type = $use_chosen ? 'select' : 'checkboxes';\n+      $multiple = TRUE;\n+      $options = array();\n+      foreach ($terms as $term => $item) {\n+        $options[$term] = $item['title'];\n+      }\n+      $default_value = _bpi_get_query_parameter(array('filter', $name), array());\n+\n+      switch ($name) {\n+        case 'agency_internal':\n+          $options = array(\n+            '' => t('All'),\n+          );\n+          if (isset($terms[0])) {\n+            $options['false'] = t('No');\n+          }\n+          if (isset($terms[1])) {\n+            $options['true'] = t('Yes');\n+          }\n+          $default_value = _bpi_get_query_parameter(array('filter', $name));\n+          $multiple = FALSE;\n+          $type = 'select';\n+          break;\n+      }\n+\n+      $facets_form[$id] = array(\n+        '#type' => $type,\n+        '#multiple' => $multiple,\n+        '#chosen' => $multiple && $use_chosen,\n+        '#size' => $multiple ? min(20, count($options)) : NULL,\n+        '#title' => bpi_label_mapper($name) ? bpi_label_mapper($name) : $name,\n+        '#options' => $options,\n+        '#default_value' => $default_value,\n+        '#attributes' => array(\n+          'data-placeholder' => $multiple ? t('Pick some values') : t('Pick a value'),\n+          'data-no-matches' => t('Nothing matches'),\n+        ),\n+        '#prefix' => '<div class=\"bpi-facet bpi-facet-' . drupal_html_class($name) . '\">',\n+        '#suffix' => '</div>',\n+      );\n+    }\n+\n+    // Add logical operator.\n+    $name = 'logicalOperator';\n+    $id = $name;\n+    $facets_form[$id] = array(\n+      '#type' => 'select',\n+      '#title' => bpi_label_mapper($name) ? bpi_label_mapper($name) : $name,\n+      '#options' => array(\n+        'and' => t('All must apply'),\n+        'or' => t('Any must apply'),\n+      ),\n+      '#default_value' => _bpi_get_query_parameter(array('filter', $name), 'and'),\n+      '#weight' => -10,\n+    );\n+\n+    $filter_form['bpi_facets'] = $facets_form;\n+\n+    $filter_form['bpi_actions'] = array(\n+      '#type' => 'container',\n+      '#attributes' => array(\n+        'class' => array(\n+          drupal_html_class('container-inline'),\n+        ),\n+      ),\n+    );\n+\n+    if (_bpi_get_current_filter()) {\n+      $filter_form['bpi_actions']['reset_filter'] = array(\n+        '#type' => 'item',\n+        '#markup' => l(t('Reset filters'), current_path(), array(\n+          'query' => _bpi_get_current_search_query(),\n+          'attributes' => array(\n+            'class' => array('button'),\n+          ),\n+        )),\n+      );\n+    }\n+\n+    $form['bpi_filter'] = $filter_form;\n+  }\n+}\n+\n+/**\n+ * Get facets as an array.\n+ *\n+ * For performance reasons facets will only be loaded when no search or\n+ * filters are applied.\n+ *\n+ * @return array\n+ *   All facets.\n+ */\n+function bpi_get_facets() {\n+  // Reload facets if they're not cached locally.\n+  $reload = !isset($_SESSION['bpi_all_facets']) || !is_array($_SESSION['bpi_all_facets']);\n+  if (!$reload) {\n+    $query = _bpi_get_query_parameter();\n+    // Reload if neither text nor filter is applied.\n+    $reload = !_bpi_get_current_search_phrase() || !_bpi_get_current_filter();\n+  }\n+\n+  if ($reload) {\n+    $response = bpi_search_content();\n+    if ($response) {\n+      $facets = $response->getFacets();\n+      $_SESSION['bpi_all_facets'] = bpi_facets_to_array($facets);\n+    }\n+    else {\n+      $_SESSION['bpi_all_facets'] = NULL;\n+    }\n+  }\n+\n+  return $_SESSION['bpi_all_facets'];\n+}\n+\n+/**\n+ * Set search facets.\n+ *\n+ * Used to store facets from actual search in the session as we need the\n+ * facets when rendering the form on postback.\n+ *\n+ * @param \\Bpi\\Sdk\\Facets $facets\n+ *   The facets returned from the search.\n+ */\n+function bpi_set_search_facets(\\Bpi\\Sdk\\Facets $facets = NULL) {\n+  // Convert facets to array for safe storage in session.\n+  $_SESSION['bpi_search_facets'] = $facets ? bpi_facets_to_array($facets) : NULL;\n+}\n+\n+/**\n+ * Get facets from last search.\n+ *\n+ * @return array $facets\n+ *   The facets.\n+ */\n+function bpi_get_search_facets() {\n+  return isset($_SESSION['bpi_search_facets']) ? $_SESSION['bpi_search_facets'] : NULL;\n+}\n+\n+/**\n+ * Convert facets into an array.\n+ *\n+ * @param \\Bpi\\Sdk\\Facets $facets\n+ *   The facets.\n+ *\n+ * @return array\n+ *   The facets as an associative array.\n+ *   term => [\n+ *     title => term title,\n+ *     count => item count\n+ *   ]\n+ */\n+function bpi_facets_to_array(\\Bpi\\Sdk\\Facets $facets) {\n+  $data = NULL;\n+\n+  if ($facets) {\n+    $data = array();\n+    foreach ($facets->getFacets() as $facet) {\n+      $data[$facet->getFacetName()] = array();\n+      foreach ($facet->getFacetTerms() as $name => $term) {\n+        $data[$facet->getFacetName()][$name] = array(\n+          'title' => $term->getTitle(),\n+          'count' => $term->getAmount(),\n+        );\n+      }\n+    }\n+\n+    ksort($data);","path":"bpi.syndicate.inc","position":911,"original_position":911,"commit_id":"3e6bacfbb3161ed9bd7b6645449ff89c3449fe2b","original_commit_id":"3e6bacfbb3161ed9bd7b6645449ff89c3449fe2b","user":{"login":"cableman","id":111397,"avatar_url":"https://avatars.githubusercontent.com/u/111397?v=3","gravatar_id":"","url":"https://api.github.com/users/cableman","html_url":"https://github.com/cableman","followers_url":"https://api.github.com/users/cableman/followers","following_url":"https://api.github.com/users/cableman/following{/other_user}","gists_url":"https://api.github.com/users/cableman/gists{/gist_id}","starred_url":"https://api.github.com/users/cableman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cableman/subscriptions","organizations_url":"https://api.github.com/users/cableman/orgs","repos_url":"https://api.github.com/users/cableman/repos","events_url":"https://api.github.com/users/cableman/events{/privacy}","received_events_url":"https://api.github.com/users/cableman/received_events","type":"User","site_admin":false},"body":"Maybe a comment about why it's sorted by key ?","created_at":"2015-09-15T10:07:56Z","updated_at":"2015-09-15T10:07:56Z","html_url":"https://github.com/ding2/bpi/pull/5#discussion_r39493873","pull_request_url":"https://api.github.com/repos/ding2/bpi/pulls/5","_links":{"self":{"href":"https://api.github.com/repos/ding2/bpi/pulls/comments/39493873"},"html":{"href":"https://github.com/ding2/bpi/pull/5#discussion_r39493873"},"pull_request":{"href":"https://api.github.com/repos/ding2/bpi/pulls/5"}}},"pull_request":{"url":"https://api.github.com/repos/ding2/bpi/pulls/5","id":44902085,"html_url":"https://github.com/ding2/bpi/pull/5","diff_url":"https://github.com/ding2/bpi/pull/5.diff","patch_url":"https://github.com/ding2/bpi/pull/5.patch","issue_url":"https://api.github.com/repos/ding2/bpi/issues/5","number":5,"state":"open","locked":false,"title":"Implement facet filtering in bpi ui","user":{"login":"rimi-itk","id":11267554,"avatar_url":"https://avatars.githubusercontent.com/u/11267554?v=3","gravatar_id":"","url":"https://api.github.com/users/rimi-itk","html_url":"https://github.com/rimi-itk","followers_url":"https://api.github.com/users/rimi-itk/followers","following_url":"https://api.github.com/users/rimi-itk/following{/other_user}","gists_url":"https://api.github.com/users/rimi-itk/gists{/gist_id}","starred_url":"https://api.github.com/users/rimi-itk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rimi-itk/subscriptions","organizations_url":"https://api.github.com/users/rimi-itk/orgs","repos_url":"https://api.github.com/users/rimi-itk/repos","events_url":"https://api.github.com/users/rimi-itk/events{/privacy}","received_events_url":"https://api.github.com/users/rimi-itk/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-09-14T08:01:03Z","updated_at":"2015-09-15T10:07:56Z","closed_at":null,"merged_at":null,"merge_commit_sha":"486527557482014d816b0c4348d3e61808b5b744","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ding2/bpi/pulls/5/commits","review_comments_url":"https://api.github.com/repos/ding2/bpi/pulls/5/comments","review_comment_url":"https://api.github.com/repos/ding2/bpi/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ding2/bpi/issues/5/comments","statuses_url":"https://api.github.com/repos/ding2/bpi/statuses/3e6bacfbb3161ed9bd7b6645449ff89c3449fe2b","head":{"label":"aakb:develop","ref":"develop","sha":"3e6bacfbb3161ed9bd7b6645449ff89c3449fe2b","user":{"login":"aakb","id":111706,"avatar_url":"https://avatars.githubusercontent.com/u/111706?v=3","gravatar_id":"","url":"https://api.github.com/users/aakb","html_url":"https://github.com/aakb","followers_url":"https://api.github.com/users/aakb/followers","following_url":"https://api.github.com/users/aakb/following{/other_user}","gists_url":"https://api.github.com/users/aakb/gists{/gist_id}","starred_url":"https://api.github.com/users/aakb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aakb/subscriptions","organizations_url":"https://api.github.com/users/aakb/orgs","repos_url":"https://api.github.com/users/aakb/repos","events_url":"https://api.github.com/users/aakb/events{/privacy}","received_events_url":"https://api.github.com/users/aakb/received_events","type":"Organization","site_admin":false},"repo":{"id":38877362,"name":"bpi","full_name":"aakb/bpi","owner":{"login":"aakb","id":111706,"avatar_url":"https://avatars.githubusercontent.com/u/111706?v=3","gravatar_id":"","url":"https://api.github.com/users/aakb","html_url":"https://github.com/aakb","followers_url":"https://api.github.com/users/aakb/followers","following_url":"https://api.github.com/users/aakb/following{/other_user}","gists_url":"https://api.github.com/users/aakb/gists{/gist_id}","starred_url":"https://api.github.com/users/aakb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aakb/subscriptions","organizations_url":"https://api.github.com/users/aakb/orgs","repos_url":"https://api.github.com/users/aakb/repos","events_url":"https://api.github.com/users/aakb/events{/privacy}","received_events_url":"https://api.github.com/users/aakb/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aakb/bpi","description":"","fork":true,"url":"https://api.github.com/repos/aakb/bpi","forks_url":"https://api.github.com/repos/aakb/bpi/forks","keys_url":"https://api.github.com/repos/aakb/bpi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aakb/bpi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aakb/bpi/teams","hooks_url":"https://api.github.com/repos/aakb/bpi/hooks","issue_events_url":"https://api.github.com/repos/aakb/bpi/issues/events{/number}","events_url":"https://api.github.com/repos/aakb/bpi/events","assignees_url":"https://api.github.com/repos/aakb/bpi/assignees{/user}","branches_url":"https://api.github.com/repos/aakb/bpi/branches{/branch}","tags_url":"https://api.github.com/repos/aakb/bpi/tags","blobs_url":"https://api.github.com/repos/aakb/bpi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aakb/bpi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aakb/bpi/git/refs{/sha}","trees_url":"https://api.github.com/repos/aakb/bpi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aakb/bpi/statuses/{sha}","languages_url":"https://api.github.com/repos/aakb/bpi/languages","stargazers_url":"https://api.github.com/repos/aakb/bpi/stargazers","contributors_url":"https://api.github.com/repos/aakb/bpi/contributors","subscribers_url":"https://api.github.com/repos/aakb/bpi/subscribers","subscription_url":"https://api.github.com/repos/aakb/bpi/subscription","commits_url":"https://api.github.com/repos/aakb/bpi/commits{/sha}","git_commits_url":"https://api.github.com/repos/aakb/bpi/git/commits{/sha}","comments_url":"https://api.github.com/repos/aakb/bpi/comments{/number}","issue_comment_url":"https://api.github.com/repos/aakb/bpi/issues/comments{/number}","contents_url":"https://api.github.com/repos/aakb/bpi/contents/{+path}","compare_url":"https://api.github.com/repos/aakb/bpi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aakb/bpi/merges","archive_url":"https://api.github.com/repos/aakb/bpi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aakb/bpi/downloads","issues_url":"https://api.github.com/repos/aakb/bpi/issues{/number}","pulls_url":"https://api.github.com/repos/aakb/bpi/pulls{/number}","milestones_url":"https://api.github.com/repos/aakb/bpi/milestones{/number}","notifications_url":"https://api.github.com/repos/aakb/bpi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aakb/bpi/labels{/name}","releases_url":"https://api.github.com/repos/aakb/bpi/releases{/id}","created_at":"2015-07-10T11:34:53Z","updated_at":"2015-07-10T11:34:54Z","pushed_at":"2015-09-07T13:27:25Z","git_url":"git://github.com/aakb/bpi.git","ssh_url":"git@github.com:aakb/bpi.git","clone_url":"https://github.com/aakb/bpi.git","svn_url":"https://github.com/aakb/bpi","homepage":null,"size":426,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ding2:master","ref":"master","sha":"de8c4d23c0f78338aeeb19f5a31c1cf2084f3073","user":{"login":"ding2","id":564698,"avatar_url":"https://avatars.githubusercontent.com/u/564698?v=3","gravatar_id":"","url":"https://api.github.com/users/ding2","html_url":"https://github.com/ding2","followers_url":"https://api.github.com/users/ding2/followers","following_url":"https://api.github.com/users/ding2/following{/other_user}","gists_url":"https://api.github.com/users/ding2/gists{/gist_id}","starred_url":"https://api.github.com/users/ding2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ding2/subscriptions","organizations_url":"https://api.github.com/users/ding2/orgs","repos_url":"https://api.github.com/users/ding2/repos","events_url":"https://api.github.com/users/ding2/events{/privacy}","received_events_url":"https://api.github.com/users/ding2/received_events","type":"Organization","site_admin":false},"repo":{"id":28138629,"name":"bpi","full_name":"ding2/bpi","owner":{"login":"ding2","id":564698,"avatar_url":"https://avatars.githubusercontent.com/u/564698?v=3","gravatar_id":"","url":"https://api.github.com/users/ding2","html_url":"https://github.com/ding2","followers_url":"https://api.github.com/users/ding2/followers","following_url":"https://api.github.com/users/ding2/following{/other_user}","gists_url":"https://api.github.com/users/ding2/gists{/gist_id}","starred_url":"https://api.github.com/users/ding2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ding2/subscriptions","organizations_url":"https://api.github.com/users/ding2/orgs","repos_url":"https://api.github.com/users/ding2/repos","events_url":"https://api.github.com/users/ding2/events{/privacy}","received_events_url":"https://api.github.com/users/ding2/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ding2/bpi","description":"","fork":true,"url":"https://api.github.com/repos/ding2/bpi","forks_url":"https://api.github.com/repos/ding2/bpi/forks","keys_url":"https://api.github.com/repos/ding2/bpi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ding2/bpi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ding2/bpi/teams","hooks_url":"https://api.github.com/repos/ding2/bpi/hooks","issue_events_url":"https://api.github.com/repos/ding2/bpi/issues/events{/number}","events_url":"https://api.github.com/repos/ding2/bpi/events","assignees_url":"https://api.github.com/repos/ding2/bpi/assignees{/user}","branches_url":"https://api.github.com/repos/ding2/bpi/branches{/branch}","tags_url":"https://api.github.com/repos/ding2/bpi/tags","blobs_url":"https://api.github.com/repos/ding2/bpi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ding2/bpi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ding2/bpi/git/refs{/sha}","trees_url":"https://api.github.com/repos/ding2/bpi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ding2/bpi/statuses/{sha}","languages_url":"https://api.github.com/repos/ding2/bpi/languages","stargazers_url":"https://api.github.com/repos/ding2/bpi/stargazers","contributors_url":"https://api.github.com/repos/ding2/bpi/contributors","subscribers_url":"https://api.github.com/repos/ding2/bpi/subscribers","subscription_url":"https://api.github.com/repos/ding2/bpi/subscription","commits_url":"https://api.github.com/repos/ding2/bpi/commits{/sha}","git_commits_url":"https://api.github.com/repos/ding2/bpi/git/commits{/sha}","comments_url":"https://api.github.com/repos/ding2/bpi/comments{/number}","issue_comment_url":"https://api.github.com/repos/ding2/bpi/issues/comments{/number}","contents_url":"https://api.github.com/repos/ding2/bpi/contents/{+path}","compare_url":"https://api.github.com/repos/ding2/bpi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ding2/bpi/merges","archive_url":"https://api.github.com/repos/ding2/bpi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ding2/bpi/downloads","issues_url":"https://api.github.com/repos/ding2/bpi/issues{/number}","pulls_url":"https://api.github.com/repos/ding2/bpi/pulls{/number}","milestones_url":"https://api.github.com/repos/ding2/bpi/milestones{/number}","notifications_url":"https://api.github.com/repos/ding2/bpi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ding2/bpi/labels{/name}","releases_url":"https://api.github.com/repos/ding2/bpi/releases{/id}","created_at":"2014-12-17T13:34:18Z","updated_at":"2015-03-04T09:30:32Z","pushed_at":"2015-09-14T13:27:32Z","git_url":"git://github.com/ding2/bpi.git","ssh_url":"git@github.com:ding2/bpi.git","clone_url":"https://github.com/ding2/bpi.git","svn_url":"https://github.com/ding2/bpi","homepage":null,"size":424,"stargazers_count":1,"watchers_count":1,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":3,"forks":4,"open_issues":3,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ding2/bpi/pulls/5"},"html":{"href":"https://github.com/ding2/bpi/pull/5"},"issue":{"href":"https://api.github.com/repos/ding2/bpi/issues/5"},"comments":{"href":"https://api.github.com/repos/ding2/bpi/issues/5/comments"},"review_comments":{"href":"https://api.github.com/repos/ding2/bpi/pulls/5/comments"},"review_comment":{"href":"https://api.github.com/repos/ding2/bpi/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ding2/bpi/pulls/5/commits"},"statuses":{"href":"https://api.github.com/repos/ding2/bpi/statuses/3e6bacfbb3161ed9bd7b6645449ff89c3449fe2b"}}}}