how to do facets on symfony2 : FOSElasticaBundle? - symfony

how to do a facet query with elasticsearch on symfony2 ?
i can do query, and got result, it works!
now on this query, i would like to facets the results.

public function facetAction()
{
// index
$search = $this->get('fos_elastica.index.appellations.appellation');
$query = new \Elastica\Query\MatchAll();
$elasticaQuery = new \Elastica\Query();
$elasticaQuery->setQuery($query);
$elasticaQuery->setSize(550);
$elasticaFacet = new \Elastica\Facet\Terms('regions');
$elasticaFacet->setField('regions');
$elasticaFacet->setSize(550);
$elasticaFacet->setOrder('reverse_count');
$elasticaQuery->addFacet($elasticaFacet);
// ResultSet
$elasticaResultSet = $search->search($elasticaQuery);
// Get Facets
$elasticaFacets = $elasticaResultSet->getFacets();
foreach ($elasticaFacets['regions']['terms'] as $elasticaFacet) {
$results[] = $elasticaFacet;
}
return $this->container->get('templating')->renderResponse
('ApplicationGhvAppellationsBundle:Default:indexFacets.html.twig', array(
'appellations' => $results
));
}

Since Facets are going to be deprecated here is the updated code with aggregations
public function aggregationAction()
{
// index
$search = $this->get('fos_elastica.index.appellations.appellation');
$query = new \Elastica\Query\MatchAll();
$elasticaQuery = new \Elastica\Query();
$elasticaQuery->setQuery($query);
$elasticaQuery->setSize(550);
$elasticaAggreg= new \Elastica\Aggregation\Terms('regions');
$elasticaAggreg->setField('regions');
$elasticaAggreg->setSize(550);
$elasticaAggreg->setOrder('_count', 'desc');
$elasticaQuery->addAggregation($elasticaAggreg);
// ResultSet
$elasticaResultSet = $search->search($elasticaQuery);
// Get Aggregations
$elasticaAggregs = $elasticaResultSet->getAggregations();
foreach ($elasticaAggregs['regions']['buckets'] as $elasticaAggreg) {
$results[] = $elasticaAggreg;
}
return $this->container->get('templating')->renderResponse
('ApplicationGhvAppellationsBundle:Default:indexFacets.html.twig', array(
'appellations' => $results
));
}

Related

How to create a bulk data endpoint in woocommerce without breaking the site performance

I am trying to create a wordpress plugin that exports or sends out (through an API) bulk data resource by resource (such as products, orders, customers, etc) of a woocommerce site without affecting the performance of the site.
But I am new to php and finding it difficult.
Also, I was planning to use WP-Cron to build the bulk data on certain time interval in order to avoid the hit in performance. But, from some research, I got to know that WP-Cron is not a reliable solution to my goal as it is not a regular cron and also, it can be disabled easily.
As my idea requires a regular bulk data building approach, I am now looking out for different options such as recursive calling.
I have exposed an endpoint where I will be receiving some required details and will call the class that will take care of the bulk data building.
public function getCCBulkSync( $request )
{
$entity = $_GET['entity'];
$startDate = $_GET['start_date'];
$endDate = $_GET['end_date'];
$delivery_url = $_GET['delivery_url'];
$limit = $_GET['limit'];
if(!$delivery_url) return 'Delivery Url cannot be null';
include 'class-wc-cc-bulk-data-builder.php';
$bulkBuilder = WC_CC_Bulk_Data_Builder::getInstance();
$bulkBuilder = ($bulkBuilder === NULL || $bulkBuilder->getObjectDetails()['entity'] === NULL) ? $bulkBuilder->setObjectDetails($entity, $delivery_url, $startDate, $endDate, $limit) : $bulkBuilder;
return 'Bulk sync initiated! Check later for the completion!!!';
}
The bulk data builder class code is given below
class WC_Bulk_Data_Builder
{
private static $instance = NULL;
protected $entity = NULL;
protected $startDate = NULL;
protected $endDate = NULL;
protected $delivery_url = NULL;
protected $dataCount = 0;
protected $limit = 0;
static public function getInstance()
{
if (self::$instance === NULL)
self::$instance = new WC_Bulk_Data_Builder();
return self::$instance;
}
protected function __construct($entity = NULL, $delivery_url = NULL, $startDate = NULL, $endDate = NULL, $limit = 1000)
{
$this->entity = $entity;
$this->delivery_url = $delivery_url;
$this->startDate = $startDate;
$this->endDate = $endDate;
$this->limit = $limit;
}
public function getObjectDetails() {
$objData = array();
$objData['entity'] = $this->entity;
$objData['startDate'] = $this->startDate;
$objData['endDate'] = $this->endDate;
$objData['deliveryUrl'] = $this->delivery_url;
$objData['dataCount'] = $this->dataCount;
$objData['limit'] = $this->limit;
return $objData;
}
public function setObjectDetails($entity = NULL, $delivery_url = NULL, $startDate = NULL, $endDate = NULL, $limit = 1000) {
$this->entity = $entity;
$this->delivery_url = $delivery_url;
$this->startDate = $startDate;
$this->endDate = $endDate;
$this->limit = $limit;
$this->bulk_data_builder();
return self::$instance;
}
function bulk_data_builder()
{
$entity = $this->entity;
if($entity === 'order') {
$this->build_order_data();
}
sleep(20);
$this->bulk_data_builder();
}
protected function build_order_data()
{
$ordersArray = wc_get_orders( array(
'limit' => 250,
'offset' => $this->dataCount,
'orderby' => 'ID',
'order' => 'ASC',
) );
$this->dataCount += count($ordersArray);
$orders = array();
foreach($ordersArray as $order_index=>$order) {
$orders[$order_index]=$order->get_data();
$orders[$order_index]['refunds'] = $order->get_refunds();
}
$header_args = array_keys($orders[0]);
$output = fopen( 'order_csv_export.csv', 'a+' );
fputcsv($output, $header_args);
foreach($orders AS $order_item){
foreach($header_args AS $ind=>$key) {
if('array' === gettype($order_item[$key])) $order_item[$key] = json_encode($order_item[$key]);
}
fputcsv($output, $order_item);
}
if($dataCount>=$limit)
{
$dataCount = 0;
$req_headers = array();
$req_headers[] = 'Content-Type: text/csv; charset=utf-8';
$req_headers[] = 'Content-Disposition: attachment; filename=order_csv_export.csv';
$cURL = curl_init();
$setopt_array = array(CURLOPT_URL => $delivery_url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $req_headers);
curl_setopt_array($cURL, $setopt_array);
$json_response_data = curl_exec($cURL);
curl_close($cURL);
exit;
}
fclose($output);
}
}
Now, what I am expecting is the recursive calling on same bulk_data_builder() method which should build the data continuously on a 20 seconds interval or any other way to do the same until the record count reaches the limit, so that I can send the bulk data built, to the delivery_url.
But, the mentioned method is not getting called recursively. Only for the first time the method is called and giving back 250 records.
As I am new to php, I am not sure about the async functionality also.
Can someone help me to understand what I am doing wrong or what I am missing?

Is there a function to get wp menu in an object or array?

I need to build a custom menu structure so the question as per title is: Is there a native wp function or something not from wp core to get the menu in a data structure as an object or an array ?
Thanks in advance.
add this on your function
function wp_get_menu_array($current_menu) {
$menu_name = $current_menu;
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
$array_menu = wp_get_nav_menu_items( $menu->term_id);
$menu = array();
foreach ($array_menu as $m) {
if (empty($m->menu_item_parent)) {
$menu[$m->ID] = array();
$menu[$m->ID]['ID'] = $m->ID;
$menu[$m->ID]['title'] = $m->title;
$menu[$m->ID]['url'] = $m->url;
$menu[$m->ID]['children'] = array();
}
}
$submenu = array();
foreach ($array_menu as $m) {
if ($m->menu_item_parent) {
$submenu[$m->ID] = array();
$submenu[$m->ID]['ID'] = $m->ID;
$submenu[$m->ID]['title'] = $m->title;
$submenu[$m->ID]['url'] = $m->url;
$menu[$m->menu_item_parent]['children'][$m->ID] = $submenu[$m->ID];
}
}
return $menu;
}
and retrieve the array on your view by
wp_get_menu_array('your_menu_name');

Call to a member function batchGet() on a non-object

I'm working on getting some google analytics api stats and am able to get metrics just fine using this...
$results = getResults($analytics, $profile->getId(), $value);
$rows = $results->getRows();
$myvalue = $rows[0][0];
echo "<b>$value:</b> ". round($myvalue, 0) ."</br>";
but the below code throws an error (see post title) when I call batchGet using same analytics object that works in above code. Unsure why or if there is an alternative way to get the dimension data I'm after.
$device = new Google_Service_AnalyticsReporting_Dimension();
$device->setName("ga:deviceCategory");
// Create the ReportRequest object.
$request = new Google_Service_AnalyticsReporting_ReportRequest();
$request->setDimensions(array($device));
$body = new Google_Service_AnalyticsReporting_GetReportsRequest();
$body->setReportRequests( array( $request) );
return $analytics->reports->batchGet( $body );
Here is how I instantiate the $analytics object
function getService()
{
// service account email, and relative location of your key file.
$service_account_email = 'email#gserviceaccount.com';
$key_file_location = 'pathto/file.p12';
// Create and configure a new client object.
$client = new Google_Client();
$client->setApplicationName("Analytics");
$analytics = new Google_Service_Analytics($client);
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_email,
array(Google_Service_Analytics::ANALYTICS_READONLY),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
return $analytics;
}
Still don't know why batchGet throws an error, but the code below works and will return the deviceCategories.
$optParams = array(
'dimensions' => 'ga:deviceCategory',
'filters' => 'ga:medium==organic');
$devices = $analytics->data_ga->get(
'ga:'.$profile->getId(),
'2015-05-01',
'2015-05-15',
'ga:sessions',
$optParams);
print_r($devices);

Pagerfanta symfony Pagination

I have a mysql database blog with 21 posts in it.
I set $maxPerPage = '3'; So I get 7 pages, but from page 4 I get the following error:
OutOfRangeCurrentPageException: Page "4" does not exist. The currentPage must be inferior to "3"
Here's my code:
public function indexAction($page)
{
$maxPerPage = '3';
$currentPage = $page;
$entityManager = $this->getDoctrine()->getManager();
$queryBuilder = $entityManager->createQueryBuilder()
->select(array('u')) // string 'u' is converted to array internally
->from('AppBundle:Blog', 'u');
$adapter = new DoctrineORMAdapter($queryBuilder);
$pagerfanta = new Pagerfanta($adapter);
if (!$page) $currentPage = '1';
try {
$pagerfanta->setCurrentPage($currentPage);
}
catch(NotValidCurrentPageException $e) {
throw new NotFoundHttpException('Illegal page');
}
$pagerfanta->setMaxPerPage($maxPerPage); // 10 by default
//$textblog = $this->getDoctrine()
//->getRepository('AppBundle:Blog')
//->find($page);
return $this->render('textblog/blog.html.twig',array('pagerfanta' => $pagerfanta));
}
Can anyone help please?
Stupid me...
$pagerfanta->setMaxPerPage($maxPerPage);
This code should be before the 'if'

Multiple rows with same ID in Silverstripe GridField

is there a way to group a GridField (for example, by ID)? The following Query (many_many) returns some dataobjects twice or more, if they havent the same SortOrder. Here is some code. I hope that somebody can help ;-)
private static $many_many = array(
'Mitarbeiter' => 'Mitarbeiter',
);
private static $many_many_extraFields = array(
'Mitarbeiter' => array(
'SortOrder' => "Int"
)
)
// Start Mitarbeiterzuordnung
$MitarbeiterFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldToolbarHeader(),
//new GridFieldSortableHeader(),
new GridFieldDataColumns(),
new GridFieldDeleteAction('unlinkrelation'),
new GridFieldSortableRows('SortOrder'),
new GridFieldManyRelationHandler(), 'GridFieldPaginator',
new GridFieldPaginator(20)
);
$MitarbeiterField = new GridField("Mitarbeiter", "Mitarbeiter", $this->Mitarbeiter()->sort('SortOrder'), $MitarbeiterFieldConfig);
$fields->addFieldToTab('Root.Mitarbeiter', $MitarbeiterField);
There is an issue with GridFieldManyRelationHandler.php and having a private static $many_many_extraFields as sorting field.
The query runs with the SortOrder being different and because it uses distinct, the ones having a different values are seen as extra, this is why the ones that have an order set show up twice.
You need to create a copy of GridFieldManyRelationHandler.php (I called it GridFieldManyManyRelationHandler.php) and edit the following function:
public function getManipulatedData(GridField $gridField, SS_List $list) {
if(!$list instanceof RelationList) {
user_error('GridFieldManyRelationHandler requires the GridField to have a RelationList. Got a ' . get_class($list) . ' instead.', E_USER_WARNING);
}
$state = $this->getState($gridField);
// We don't use setupState() as we need the list
if($state->FirstTime) {
$state->RelationVal = array_values($list->getIdList()) ?: array();
}
if(!$state->ShowingRelation && $this->useToggle) {
return $list;
}
$baseClass = $list->dataClass();
return $baseClass::get();
}
Then call that new class from your code, ie
private static $many_many = array(
'Mitarbeiter' => 'Mitarbeiter',
);
private static $many_many_extraFields = array(
'Mitarbeiter' => array(
'SortOrder' => "Int"
)
)
// Start Mitarbeiterzuordnung
$MitarbeiterFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldToolbarHeader(),
//new GridFieldSortableHeader(),
new GridFieldDataColumns(),
new GridFieldDeleteAction('unlinkrelation'),
new GridFieldSortableRows('SortOrder'),
new GridFieldManyManyRelationHandler(), 'GridFieldPaginator',
new GridFieldPaginator(20)
);
$MitarbeiterField = new GridField("Mitarbeiter", "Mitarbeiter", $this->Mitarbeiter()->sort('SortOrder'), $MitarbeiterFieldConfig);
$fields->addFieldToTab('Root.Mitarbeiter', $MitarbeiterField);
This probably should be refactored and the two classes should be separated (one class handling many_many and the other has_many).

Resources