Passing uid as an argument works fine with this code:
$bouts = views_get_view_result('Results', 'page_1', array($user->uid));
The key line in views_get_view_result that sets arguments is:
$view->set_arguments($args);
But what about passing date ranges?
Also, if something is specified as a filter on a view, is there a way to prorammatically alter it?
views_get_view_result:
/**
* Investigate the result of a view.
* from Drupal.org.
*
* #param string $viewname
* The name of the view to retrieve the data from.
* #param string $display_id
* The display id. On the edit page for the view in question, you'll find
* a list of displays at the left side of the control area. "Defaults"
* will be at the top of that list. Hover your cursor over the name of the
* display you want to use. A URL will appear in the status bar of your
* browser. This is usually at the bottom of the window, in the chrome.
* Everything after #views-tab- is the display ID, e.g. page_1.
* #param array $args
* Array of arguments. (no keys, just args)
* #return
* array
* An array containing an object for each view item.
* string
* If the view is not found a message is returned.
*/
function views_get_view_result($viewname, $display_id = NULL, $args = NULL) {
$view = views_get_view($viewname);
if (is_object($view)) {
if (is_array($args)) {
$view->set_arguments($args);
}
if (is_string($display_id)) {
$view->set_display($display_id);
}
else {
$view->init_display();
}
$view->pre_execute();
$view->execute();
/* print "<pre> $viewname: $display_id";
print_r(get_class_methods($view)); */
return $view->result;
}
else {
return t('View %viewname not found.', array('%viewname' => $viewname));
}
}
As for passing data ranges and given the posted function definition, you could pass date ranges to that only if the view would accept them as arguments. I'm not 100% sure, but afaik date ranges can only be defined as filters, not as arguments, which leads to your second Question:
Programmatically altering the views filter settings is possible, but a bit messy, given the rather complicated view object/array mashup structure. In your posted function above, the first line is
$view = views_get_view($viewname);
After that, $view contains the whole view object. The filter settings are defined per display, so assuming you have a view with only a default display, you will find the filter settings under
$view->display['default']->display_options['filters']
(Note the object/array notation mix - the display is a contained object of type views_display)
The 'filters' array contains one entry per filter, with varying elements depending on the filter type. For your purpose, I would suggest to create a dummy view with just the filter you are interested in, with preconfigured/hardcoded values. Using a debugger (or var_dump/print_r) you can then take a look at the filter array after view creation. From what you find there, you should be able to deduce how to inject your custom date range.
Disclaimer: Poking around in the view like this is a bit annoying and not to effective, but it works. As of yet, I have not found a concise documentation of Views2 that would explain the innards in a straight forward way, as I find the official API documentation a bit lacking concerning the usage from code. (Of course this could well be just me being to stupid ;)
If you're using views 2, you can use the GUI to add a date argument. Then in the url, you can put :
www.yousite.com/yourview/startDate--finishDate
For the startDate/finishDate, the format is YYYY-MM-DD-HH.
GL!
Related
As part of my ongoing efforts to simplify the legacy codebase for a CodeIgniter3 application, I'm currently running into a problem. In short, I've dealt with an error statement earlier stating:
can't use method return value in write context
which might ring a bell for some readers. Nonetheless, I haven't seen this error since but I suspect that something is still going wrong. In short, I'm trying to push an associative array into another associative, multidimensional array which is the result of a method that returns a reference.
I've set up a system to easily alter the contents of a JSON, which is returned by reference through this method:
/**
* Function : items
* Target : Retrieves a reference to the items, decoded
*
* #author : Angev
* #since : 2.0
* #version : 1.0
*
* #return Referenced link to index 'items'.
*/
public function & items()
{
$list = (is_array($this->data)) ? $this->data : json_decode($this->data, true);
return $list['items'];
}
In short, the method $this->items() is part of a Model named 'CheckList'. The Checklist corresponds with a data-table in my database, which includes a 'data' column that represents the data belonging to a certain checklist: the JSON I'm trying to alter and which you can see being returned in this method. Another way of seeing the output of $this->items() is that it should return a reference to $this->data['items'].
This goes all and well, I've used this method many times during development - as a shorthand to accessing ['list'] - and it always returns exactly what I need it to return: a multidimensional array filled with unique indexes (strings) that contain the data belonging to each item of the checklist.
The problem however, arises in a method named update_checklist() in particular the following section:
$this->items()[$uid] = [
'parent_id' => $parent['id'],
... ,
];
I'd expect the method to add an index to the array returned by $this->items(), but it doesn't.
I'm not quite sure what goes wrong in this context, since I have earlier seen the error message written at the top of this question, but haven't seen it since.
However, no index is added to the array and whenever I do an immediate var_dump($this->items()) afterwards. It just shows the state of the array as it was before the execution of update_checklist().
In search of an answer, I've also tried wrapping the callback in parentheses, but to no avail:
( $this->items() )[$uid] = . . .
To temporary fix the problem, I've resorted to a more direct alteration of the ['items'] array by doing the following:
$this->data = json_decode($this->data, true);
$this->data['items'][$uid] = [
'parent_id' => $parent['id'],
... ,
];
Nonetheless, even though the code above works, I'm left wondering what the flaw is in my logic concerning the method reference return of $this->items() and why I cannot use this method when pushing into the referenced array.
How can I write the required changes to make $this->items()[] function as intended? Or I'd be interested in more clarity into the theory behind this structure and why it can't work.
As always, once you start formulating a question, you stumble upon the flaws in your logic. I've read over this question with a colleague and while discussing the solution just magically presented itself. I'll include the answer for future reference to anyone having the same problem.
/**
* Function : items
* Target : Retrieves a reference to the items, decoded
*
* #author : Angev
* #since : 2.0
* #version : 1.0
*
* #return Referenced link to index 'items'.
*/
public function & items()
{
$list = (is_array($this->data)) ? $this->data : json_decode($this->data, true);
return $list['items'];
}
The problem lies withing the items() method. This method surely returns a reference, but the reference is made to the preliminary variable $list, which in turn has no direct reference to $this->data. So instead of refering to $this->data['items'], the method returns a reference to $list, which is essentially a copy of $this->data, no no real reference.
To fix the problem, the following code was used:
public function & items()
{
if(!is_array($this->data) ) $this->data = json_decode($this->data, true);
return $this->data['items'];
}
As expected, the method now returns a reference to the actual data object.
So in short, what I've learned is that if you let a method return a reference, you need to make sure that whatever the method returns is actually a reference instead of a copy of the data you're trying to reference to.
I'll leave this question open for now to allow others to share any knowledge of insights in this matter.
I've got a prestashop setup that has a small 'customization form' that currently saves the information to the products default customization text input. I did this to save time on having to write a complete custom module to add additional customization form fields and such.
Currently all the inputs are serialized (json) and entered as a long string into the text input like this:
Client Customization: %5B%5B%7B%22name%22%3A%22trophy%5B1%5D%5Bline1%5D%22%2C%22engraving%22%3A%22Test%20Trophy%22%7D%2C%7B%22name%22%3A%22trophy%5B1%5D%5Bline2%5D%22%2C%22engraving%22%3A%22test%20trophy%22%7D%2C%7B%22name%22%3A%22trophy%5B1%5D%5Bline3%5D%22%2C%22engraving%22%3A%221111111%22%7D%5D%5D
On the front end - when the customized data is displayed I can use PHP to decode & display it appropriately.
Is there a way where I can change that globally somewhere so I don't have to try and find every place where it might display and add that PHP code?
I'm running into the issue that I can't seem to find where to add the PHP code to 'decode' that string for the emails that are being sent out - so the long ugly string is being seen instead of the nice few lines of customization the user entered.
Any thoughts on how to handle this? Is there a spot where I can globally assign the decoded string to the products customization?
You could either try the PaymentModule class to decode the string just before the emails are sent, or Product's method called "getAllCustomizedDatas" for a more "global" approach.
And then test a lot, of course :)
Here's a quick draft of the second approach:
<?php
class Product extends ProductCore
{
public static function getAllCustomizedDatas($id_cart, $id_lang = null, $only_in_cart = true, $id_shop = null)
{
$datas = parent::getAllCustomizedDatas($id_cart, $id_lang, $only_in_cart, $id_shop);
/*
* Iterate over $datas, you're looking for
* [id_product][id_product_attribute][id_address_delivery][id_customization][datas]
* Datas will contain an array of fields broken by their type. You can then decode
* the ones that need to be decoded and return the result:
*/
return $datas;
}
}
First let me say that the new API Explorer in Restler is great. Very happy about its addition. Now, in typical fashion, let me complain about something that isn't working for me ...
The fact that Restler can return results in multiple formats is a very nice feature but I'm currently not using it (choosing to only use JSON as my return format). In the API Explorer I'd like all references to .json to not show up as this just complicates the look of the service architecture.
Here's a quick example:
class Users {
/**
* Preferences
*
* Preferences returns a dictionary of name-value pairs that provide input to applications that want to make user-specific decisions
*
* #url GET /{user_id}/preferences
**/
function preferences ($user_id , $which = 'all') {
return "$which preferences for {$user_id}";
}
/**
* GET Sensors
*
* Get a list of all sensors associated with a user.
*
* #url GET /{user_id}/sensor
**/
function sensor ($user_id) {
return "sensor";
}
/**
* GET Sensors by Type
*
* #param $user_id The user who's sensors you are interested in
* #param $type The type of sensor you want listed.
*
* #url GET /{user_id}/sensor/{type}
**/
function sensor_by_type ($user_id, $type) {
return "specific sensor";
}
/**
* ADD a Sensor
*
* #param $user_id The user who you'll be adding the sensor to
*
* #url POST /sensor
**/
function postSensor() {
return "post sensor";
}
}
In this example the API Explorer looks like this:
The basic problem I'd like to remove is remove all ".json" references as the calling structure without the optional .json works perfectly fine.
Also, for those that DO want the .json showing up there's a secondary problem of WHERE does this post-item modifier show up? In the example above you have .json attaching to the "users" element in the GET's and to the "sensor" element in the PUT. This has nothing to do with the HTTP operation but rather it seems to choose the element which immediately precedes the first variable which may not be intuitive to the user and actually isn't a requirement in Restler (at least its my impression that you can attache .json anywhere in the chain and get the desired effect).
We are using safer defaults that will work for everyone, but made it completely configurable.
if you prefer .json to be added at the end, add the following to index.php (gateway)
use Luracast\Restler\Resources;
Resources::$placeFormatExtensionBeforeDynamicParts = false;
If you prefer not to add .json extension, add the following to index.php
use Luracast\Restler\Resources;
Resources::$useFormatAsExtension = false;
I have created a RESTful API that has an optional parameter passed in as a URL variable. It seems to work correctly when executing from the browser directly but when trying it in the API Explorer it lists the parameter but ignores it when executing it. I have no idea where to start to look in solving this. Any help would be greatly appreciated.
The class definition is as follows:
class actions {
/**
* LIST available Actions
*
* List all the actions that a user (or app) can choose from. The response list
* will include [name],[slug/id], and [description] attributes. If you want a more complete set of
* meta attributes for the actions then you can specify "meta=all" in the request url. For full spec of
* response please review LG_actions_list.json.
*
* #url GET /available
*
* #param $meta {#from url} Optional parameter to control the amount of meta-data passed back. Values are "none","normal", and "all"
**/
public function available ($meta="normal")
{
return "list actions (meta level set to $meta)";
}
}
In this case I can type "all" as the value of $meta in the API explorer but the response is still "list actions (meta level set to normal)".
UPDATE:
In order to clarify this behaviour I am adding the API Explorers output and the output I get when I call the service directly:
In comparison, when actually using the API I get the correct results. Typing this into Chrome:
http://[domain]/api/actions/available?meta=foobar
I get the desired output of:
"list actions (meta level set to foobar)"
There are few problems with what you are doing with the above code
Optional Parameters are better left to query string
When you add a manual route using #url no auto routes will be added for that method
Do the following to make it work.
Changed the method name to get to map it to root of the class
Turned off smart auto routing
Now in the explorer there will be two operations listed
actions.json
actions.json/{meta}
.
class actions {
/**
* LIST available Actions
*
* List all the actions that a user (or app) can choose from. The response list
* will include [name],[slug/id], and [description] attributes. If you want a more complete set of
* meta attributes for the actions then you can specify "meta=all" in the request url. For full spec of
* response please review LG_actions_list.json.
*
* #smart-auto-routing false
* #param $meta Optional parameter to control the amount of meta-data passed back. Values are "none","normal", and "all"
**/
public function get ($meta="normal")
{
return "list actions (meta level set to $meta)";
}
}
I'm using Yii but I'm trying to understand a good logic to implement this, so even if your not a Yii proficient I could use a help.
We have those event types with names that may containing special characters like:
"Amça"
"Áli Çulo"
etc...
I cannot simple grab those names and call statically the model on view to display those, because I will get an invalid css class.
The model:
/**
* #desc Get Event Type Name normalized.
* #param int $id
* #return object
*/
public function getEventTypeName($id) {
return normalizer_normalize(self::model()->findByPk($id)->name);
}
The view:
<p class="event-resume-<?= function_exists('normalizer_normalize') ? EventType::getEventTypeName($data->event->type) : '';?>"></p>
I've tried to user normalizer_normalize but, it doesn't work with "Áli Çulo" due to the space between the words.
The logic issue:
We can create a method that says:
If the id is 1 then return a constant string named "nameoftype1"
If the id is 2 then return a constant string named "nameoftype2"
But this is not a good approach because if we later have another database were other id's, correspond to other types, we need to change this method again.
What would be a better approach here ?
Should I provide more information? Please advice.
You can get a hash value of the event type and use that instead:
<p class="event-resume-<?= md5( $data->event->type ) ?>"></p>
This might cause the .css file to be less readable, but you can use comments to deal with that.