Multiple rows with same ID in Silverstripe GridField - silverstripe

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).

Related

How to use DBFile in cms SS4

I have been attempting to use the new DBFile datatype as in this (pruned) example
class SlideImage extends DataObject
{
private static $table_name = 'SlideImage';
private static $plural_name = 'Slide Images';
private static $singular_name = 'Slide Image';
private static $db = array(
'Name' => 'Varchar(255)',
'TestImageField' => "DBFile('image/supported')"
);
private static $has_one = array(
'Image' => Image::class,
);
The Image is easy to deal with in the function getCMSFields(){
$imageField = new UploadField('Image', 'Choose Image');
$imageField->setFolderName('Uploads/promotionalbanners');
and the new
$imageField = Injector::inst()->create(FileHandleField::class, 'Image','Choose Image');
works as well.
However, attempting to use either of those with the TestImageField as in the attempts below produces the error "Cannot use object of type SilverStripe\Assets\Storage\DBFile as array"
$fields->addFieldToTab('Root.Main', new UploadField('TestImageField', 'Choose Image'));
or perhaps
$imageFielddb = Injector::inst()->create(FileHandleField::class, 'TestImageField');
$imageFielddb = $this->TestImageField->scaffoldFormField('TestImageField');
I know I am doing something really stupid around the concept of DBFile in the db definition but how can I used that as an actual image reference - or can I not on its own?

How to set locale in controller

In my SilverStripe project I have a controller which I call by a cronjob. But in this controller I want to use the translations from the yaml language files. So I want to set the locale to use the right translations. I tried to do something like this, but this doesn't work:
class CronController extends Controller {
public function opendataform() {
i18n::set_locale('it_IT');
$Params = $this->getURLParams();
self::$ad = $Params['ID'];
$selectMemberSelectionField = new DropdownField('SelectionName', _t('General.CHOOSE_SELECTION', "Choose selection"), MemberSelection::get()->map('ID', 'Name'));
$fields = new FieldList($selectMemberSelectionField);
$actions = new FieldList(
FormAction::create("doOpen")->setTitle(_t('General.Open', "Open"))
);
$form = new Form($this, 'OpenForm', $fields, $actions);
return $form;
}
}
Also tried with: Translatable::set_current_locale('it_IT');
Any suggestions? Thanks in advance!

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);

how to do facets on symfony2 : FOSElasticaBundle?

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
));
}

How to attach files with metaWeblog to a blog post?

I'm trying to post to my blog with images.
Yes, I can upload images and I can see that images in the content of post
but it's not in a attached file list.
How can I put the images that I upload in the attached file list?
When I'm posting with MS word 2010 to my blog, images that I put on the word are always updated in a attached file list. But my php source doesn't.
Is there any way to attach files to a blog post?
$cBlog = new blog;
$title = "This is a article's title";
$desc = "IT will be the content";
$return = $cBlog->writePost($title, $desc);
class blog
{
public $g_blog_url;
public $user_id;
public $blogid;
public $password;
public $publish;
function __construct()
{
$this->g_blog_url = "https://api.blog.naver.com/xmlrpc";
$this->user_id = "globeseen";
$this->blogid = "globeseen";
$this->password = "password";
$this->publish = true;
}
function writePost($title, $description, $category="")
{
$client = new xmlrpc_client($this->g_blog_url);
$client->setSSLVerifyPeer(false);
$GLOBALS['xmlrpc_internalencoding']='UTF-8';
$img = $this->upload_image("D:\\1.jpg");
$struct = array(
'title' => new xmlrpcval($title, "string"),
'description' => new xmlrpcval($description."<img src=$img>", "string"),
'categories' => new xmlrpcval($category, "string"),
'tags' => new xmlrpcval('clothing', "string")
);
$f = new xmlrpcmsg("metaWeblog.newPost",
array(
new xmlrpcval($this->blogid, "string"),
new xmlrpcval($this->user_id, "string"),
new xmlrpcval($this->password, "string"),
new xmlrpcval($struct , "struct"),
new xmlrpcval($this->publish, "boolean")
));
$f->request_charset_encoding = 'UTF-8';
return $response = $client->send($f);
}
function upload_image($fpath) {
global $api_url, $blog_user, $blog_passwd;
$api_url = $this->g_blog_url;
$blog_user = $this->user_id;
$blog_passwd = $this->password;
$imgbit = file_get_contents($fpath, FILE_BINARY);
$img = new xmlrpcval(
array (
'bits' => new xmlrpcval($imgbit, 'base64'),
'type' => new xmlrpcval('image/jpeg', 'string'),
'name' => new xmlrpcval(basename($fpath), 'string')
), 'struct');
$c = new xmlrpc_client($api_url);
$c->setSSLVerifyPeer(false);
$x = new xmlrpcmsg("metaWeblog.newMediaObject");
$x->addParam(new xmlrpcval($blog_user, 'string'));
$x->addParam(new xmlrpcval($blog_user, 'string'));
$x->addParam(new xmlrpcval($blog_passwd, 'string'));
$x->addParam($img);
$c->return_type = 'phpvals';
$r =$c->send($x);
if ($r->errno=="0") {
return $r->val['url'];
} else {
echo "There was an error<pre>";
print_r($r);
echo "</pre>";
return null;
}
}
}

Resources