Sorting Versioned ModelAdmin - silverstripe

I'm trying to do a custom sort in ModelAdmin on SiteTree object
public function getList() {
$list = parent::getList();
if($this->modelClass == 'Listing') {
$list = $list->sort(array('Status' => 'ASC','Street' => 'ASC'));
}
return $list;
}
The sort works but when you try to edit a record I get the following error:
[User Error] Couldn't run query: SELECT DISTINCT "SiteTree_Live"."ID", "Status", "Street" FROM "SiteTree_Live" WHERE ("SiteTree_Live"."ClassName" IN ('Listing','UnavailableListing')) ORDER BY "Status" ASC, "Street" ASC LIMIT 30 Unknown column 'Status' in 'field list'
Obviously Status doesn't exist on SiteTree, it exists on Listing.

You've kind of answered your own question. You can't order by Status when querying SiteTree if the column doesn't exist on that table.
You need to change your model class to Listing or add the Status column to your SiteTree table.

Related

Adding a new field to Category Bundle Orocommerce

I'm trying to add a ManyToManyRelation to the category entity, but i get an error that the field doesnt exist when i clear cache.
public function up(Schema $schema, QueryBag $queries)
{
$this->createNewGammeTable($schema);
$this->extendExtension->addManyToManyRelation(
$schema,
self::CATEGORY_TABLE_NAME,
"new_ranges",
self::NEW_GAMME_TABLE_NAME,
["gamme_id"],
["gamme_id"],
["gamme_id"],
[
"extend" => ["owner" => ExtendScope::OWNER_CUSTOM, 'cascade' => ['all']],
'form' => [
'form_type' => NewGammeCollectionType::class
]
]
);
}
protected function createNewGammeTable(Schema $schema)
{
$table = $schema->createTable(self::NEW_GAMME_TABLE_NAME);
$table->addColumn("id", "integer", ["autoincrement" => true]);
$table->addColumn("gamme_id", "integer", ["notnull" => false]);
$table->addColumn("sort_order", "integer");
$table->setPrimaryKey(["id"]);
}
So when i clear cache i get :
In RuntimeReflectionService.php line 76:
Property Oro\Bundle\CatalogBundle\Entity\Category::$new_ranges does not exi
st
and in dev env i dont get this error. but in the orocommerce plateforme when i try to edit a category i get
An exception occurred while executing 'SELECT t0.id AS id_1, t0.sort_order AS sort_order_2, t0.gamme_id AS gamme_id_3 FROM gdm_new_gamme t0 INNER JOIN oro_rel_ff3a7b9752519dfcec0789 ON t0.id = oro_rel_ff3a7b9752519dfcec0789.newgamme_id WHERE oro_rel_ff3a7b9752519dfcec0789.category_id = ?' with params [2]:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'oro_db.oro_rel_ff3a7b9752519dfcec0789' doesn't exist
I fixed my problem by updating my entities using oro:entity-extend:cache:clear
and oro:entity-extend:update-schema

Adding Sort to Group Members

I have a Page that displays a list of Members in a group, but I need to change the sort of the group members. I though the esiest way would be to add a relation editor to the pagetype with the sort order added via a Data Extension
Here is my extension on Group
class MyGroup extends DataExtension {
static $many_many_extraFields = array(
'Members' => array(
'SortOrder' => "Int"
)
);
}
On the Page I have the following:
if($this->GroupID != 0 && Permission::check("APPLY_ROLES")) {
$group = Group::get()->byID($this->GroupID);
$fields->addFieldsToTab("Root.Members", array(
GridField::create(
"Members",
"Members",
$group->DirectMembers(),
GridFieldConfig_RelationEditor::create()->addComponents(
new GridFieldSortableRows('SortOrder')
)
)
));
}
When I try to sort the Members I get an error
Uncaught SS_DatabaseException: Couldn't run query:
UPDATE "" SET "SortOrder" = 1 WHERE "" = 12 AND "" = 18
I'm not sure why GridField isn't getting the Columns
You can define the sort order on the list you use for the gridfield
$group->DirectMembers()->sort('Whatever')
If you want to sort them manually, have a look at https://github.com/silverstripe-australia/silverstripe-gridfieldextensions or https://github.com/UndefinedOffset/SortableGridField.
Both modules give you the possibility to sort the entries with drag and drop.

Filter ModelAdmin by many_many relation

I'm managing the DataObject class 'trainer' with ModelAdmin. A trainer has a many_many relation to my other class 'language'.
On my 'trainer' class I'm manipulating the 'searchableFields' function to display a ListboxField in the filters area.
public function searchableFields() {
$languagesField = ListboxField::create(
'Languages',
'Sprachen',
Language::get()->map()->toArray()
)->setMultiple(true);
return array (
'Languages' => array (
'filter' => 'ExactMatchFilter',
'title' => 'Sprachen',
'field' => $languagesField
)
);
}
That works like expected and shows me the wanted ListboxField. The Problem is, after selecting 1 or 2 or whatever languages and submitting the form, I'm receiving
[Warning] trim() expects parameter 1 to be string, array given
Is it possible here to filter with an many_many relation? And if so, how? Would be great if someone could point me in the right direction.
Update:
Full Error Message: http://www.sspaste.com/paste/show/56589337eea35
Trainer Class: http://www.sspaste.com/paste/show/56589441428d0
You need to define that logic within a $searchable_fields parameter instead of the searchableFields() which actually constructs the searchable fields and logic.
PHP would be likely to throw an error if you go doing fancy form stuff within the array itself, so farm that form field off to a separate method in the same DataObject and simply call upon it.
See my example, I hope it helps.
/* Define this DataObjects searchable Fields */
private static $searchable_fields = array(
'Languages' => array (
'filter' => 'ExactMatchFilter',
'title' => 'Sprachen',
'field' => self::languagesField()
)
);
/* Return the searchable field for Languages */
public function languagesField() {
return ListboxField::create(
'Languages',
'Sprachen',
Language::get()->map()->toArray()
)->setMultiple(true);
}
Yes, it's possible. You just need to override two methods - one in Trainer data object and one in TrainerModelAdmin. First one will make a field, second one will do filtering.
Trainer Data Object:
public function scaffoldSearchFields($_params = null)
{
$fields = parent::scaffoldSearchFields($_params);
// get values from query, if set
$query = Controller::curr()->request->getVar('q');
$value = !empty($query['Languages']) && !empty($query['Languages']) ? $query['Languages'] : array();
// create a field with options and values
$lang = ListboxField::create("Languages", "Sprachen", Language::get()->map()->toArray(), $value, null, true);
// push it to field list
$fields->push($lang);
return $fields;
}
Trainer Model Admin
public function getList()
{
$list = parent::getList();
// check if managed model is right and is query set
$query = $this->request->getVar('q');
if ($this->modelClass === "Trainer" && !empty($query['Languages']) && !empty($query['Languages']))
{
// cast all values to integer, just to be sure
$ids = array();
foreach ($query['Languages'] as $lang)
{
$ids[] = (int)$lang;
}
// make a condition for query
$langs = join(",", $ids);
// run the query and take only trainer IDs
$trainers = DB::query("SELECT * FROM Trainer_Languages WHERE LanguageID IN ({$langs})")->column("TrainerID");
// filter query on those IDs and return it
return $list->filter("ID", $trainers);
}
return $list;
}

cakephp 3 deeper associations

I'm trying to find the right way to handel the next tabel setup.
Products is my main table and contains an id.
UsersCarts has an field product_id and with belongsTo it also loads the products.
So far no problem. I also have an table ProductsNettoDeals where I store possible netto prices. This table has it's own id an an product_id for the hasOne relation when loading products in the productcontroller.
When I load the UsersChart it loads it belongsTo products, but I also want the association with the table ProductsNettoDeals, but this table is connected with products through the id (products.id = products_netto_deals.product_id). I cant find the right syntax or association for the querybuilder. What I have so far:
// src/Model/Table/UsersCartsTable.php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\ORM\Query;
use Cake\Validation\Validator;
class UsersCartsTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$this->belongsTo('Products');
$this->belongsTo('ProductsNettoDeals');
}
public function validationDefault(Validator $validator)
{
return $validator
->notEmpty('user_id', 'A user id is required')
->notEmpty('product_id', 'A product id is required');
}
public function findCart(Query $query, array $options)
{
$query
->where([
'user_id' => $options['user_id'],
//'active' => '1'
])
->contain(['Products','ProductsNettoDeals'])
//->select(['product_id','created','products.name','products.price','products.delivery_time']);
;
return $query;
}
}
In this setup I always have the problem that the matching of the id's are wrong. With the products it's good. The users_carts.product_id links with the products.id, but the products_netto_deals.product_id should link with product.id and not with the users_carts.id. I tryed foreign key and bind, but both are an part of an solution.
Beside this problem, when connecting the association ProductsNettoDeals I get an error when activating the commented active => '1'. This field indicates if an record is active and should be loaded. The same field exist in the products_netto_deals tabel to indicate if an netto price is active.
Error: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'active' in where clause is ambiguous
Can anyone point me in the right direction for the correct way of the association and the error warning. Thanks in forward.
CakePHP uses joins for fetching associations, in order to speed ud the information retrieval process. This means that when having column names repeated across different table, you will need to prefix the column names in the query clause"
Instead of:
$query->where(['active' => true]);
Do:
$query->where(['UsersCarts.active' => true])

Drupal: Modifying a User at Registration

I needed to create a custom select list for the user registration page that pulls a SQL query from nodes I need to link to users. I have successfully accomplished this task.. :)
However, when I submit the value, I can't seem to control where the value is stored. In fact, I can't store the value at all. I have created a custom field for my value, but only the new field name is stored, and it is serialized and stored in the Data column of the user table.
Below is my code, I've commented my issues in it. Any help would be appreciated!
<?php
// $Id$
//create the additional user form field, a select list named "account_name"
//then calls the next function to populate it.
function accountselect_user($op, &$edit, &$account, $category = NULL) {
if ($op == 'register' || 'edit')
$fields['Information']['account_name'] = array(
'#type' => 'select',
'#title' => 'Account',
'#description' => t('Select the account to which the contact belongs'),
'#options' => accountselect_getclubs() ,
);
return $fields;
}
//contains query to pull results to select list...this part is working
function accountselect_getclubs() {
$return = array();
$sql = 'SELECT DISTINCT `title` FROM node WHERE type = \'accounts\' ';
$result = db_query($sql);
while ($row = db_fetch_array($result)) {
$return[] = $row['title'];
}
return $return;
}
//CAN'T GET THIS PART TO WORK - query to update the row - the uid = 29 is for
//testing puposes. Once I get the test value to work
//the test value I will worry about updating the correct user.
function accountselect_submitaccount() {
$sql = "UPDATE users SET account = \'value\' WHERE uid = \'29\'";
db_query($sql);
drupal_set_message(t('The field has been updated.'));
}
//I SUSPECT THE PROBLEM IS HERE...call the submitaccount function.
//I have tried hook_form_alter as well...
function accountselect_submit(&$form, &$form_state) {
if($form_id == 'user-register')
drupal_execute('accountselect_submitaccount');
}
Have you checked Drupal's logs? It should be throwing errors, as this is not a valid query.
$sql = "UPDATE users SET account = \'value\' WHERE uid = \'29\'";
Should be:
$sql = "UPDATE users SET account = 'value' WHERE uid = '29'";
Additionally, in:
function accountselect_submit(&$form, &$form_state) {
if($form_id == 'user-register')
drupal_execute('accountselect_submitaccount');
}
$form_id is never defined.
You say you've created the field in the database, but it must match the name of the Drupal field to be automatically handled. You've got two different names for it - account_name in the Drupal field, but account in the database. Make them consistent and it should be automatically handled, no submit functions required.

Resources