I'm looking for a way to create an organic group in code.
On the web i find manny resources on how to add a node to a group etc, but not how to create a group itself.
I have done it using the drupal interface, but this isn't very portable. I have tried using the features module, although i found that had to many issues. Missing fields etc.
Through the interface you create a group by making a new contenttype, and then under the tab 'organic groups' you select 'group'
I know how to create a content type in code
$type = array(
'type' => 'Termbase2type',
'name' => t('Termbase2name'),
'base' => 'node_content',
'custom' => 1,
'modified' => 1,
'locked' => 0,
'title_label' => 'Termbase2',
'description' => 's a database consisting of concept-oriented terminological entries (or ‘concepts’) and related information, usually in multilingual format. Entries may include any of the following additional information: a definition; source or context of the term; subject area, domain, or industry; grammatical information (verb, noun, etc.); notes; usage label (figurative, American English, formal, etc.); author (‘created by’), creation/modification date (‘created/modified at’); verification status (‘verified’ or ‘approved’ terms), and an ID. A termbase allows for the systematic management of approved or verified terms and is a powerful tool for promoting consistency in terminology. *wiki',
'og_group_type' => 1,
'og_private' => 0,
'og_register' => 0,
'og_directory' => 0,
'og_selective' => 3,
);
$type = node_type_set_defaults($type);
node_type_save($type);
node_add_body_field($type);
but i can't find any clue as to how to set the content type as a group, so it can have group members.
This worked:
// get existing content types
$content_types = node_type_get_types();
$t = get_t();
// create the currency CT
$type_name = 'cc';
if (!array_key_exists($type_name, $content_types)) {
// Create the type definition array.
$type = array(
'type' => $type_name,
'name' => $t('Community Currency'),
'base' => 'node_content',
'description' => $t('A community that trades in a virtual currency.'),
'custom' => 1,
'modified' => 1,
'locked' => 0,
);
$type = node_type_set_defaults($type);
node_type_save($type);
// Add a body field.
node_add_body_field($type);
variable_set('og_group_type_' . $type_name, TRUE);
og_ui_node_type_save($type_name);
}
One option would be to use Drupal's drupal_form_submit() function to programmatically submit the necessary forms. It may be a bit tedious and not be as straightforward as using an API, but it should work.
Related
I tried several answers from suitecrm forum And here. And I can't implement them to the present version of Suite CRM.
Here is the one I tried last and stuck for further clarification.
add a new file in custom/Extension/modules/yourmodule/Ext/Vardefs e.g. autoincrement.php with the following :
<?php
$dictionary['YOUR_MODULE']['fields']['NAME_OF_AUTO_INC_FIELD'] = array(
'name' => 'NAME_OF_AUTO_INC_FIELD',
'vname' => 'LBL_LABEL_OF_AUTO_INC_FIELD',
'type' => 'int',
'readonly' => true,
'len' => 11,
'auto_increment' => true,
'disable_num_format' => true,
);
?>
and also add unique index for the field in that file
<?php
$dictionary['YOUR_MODULE']['indices']['NAME_FOR_INDEX'] = array(
'name' => 'NAME_FOR_INDEX',
'type' => 'unique',
'fields' => array('NAME_OF_AUTO_INC_FIELD'),
);
?>
Run a Quick Rebuild and Repair in Admin -> Repair and execute the changes.
after that it shows an empty text box. There it iterates automatically, when new account saved. But I want to show the next auto increment number here in this Accounts page itself.
Instead of default value, I want to show the next auto value in the new Account form.
This isn't out the box behaviour - you'll need to add some customisations to do this.
I would create a new vardef auto_inc_preview which is a function type field. This can then be used to grab the largest number from the DB and display this + 1.
A possible issue with this would be that the number a user sees may not be the id that gets generated - for example if two or more people create an account at the same time.
I was setup cake php for website: http://bomnuocebara.com but i have error.
I have very basic question but I'm kind of stuck with the syntax here:
I have an entity query. The entity is associated to another table which has a 'name' property? (many to many association)
My $query looks like this when I debug it:
/plugins/MailCalculator/src/Controller/PostalServicesController.php (line 140)
object(MailCalculator\Model\Entity\PostalService) {
'id' => (int) 1,
'carrier' => 'Deutsche Post'
},
'modified' => null,
'_matchingData' => [
'Insurances' => object(MailCalculator\Model\Entity\Insurance) {
'id' => (int) 2,
'name' => 'Wert',
'price' => (float) 4.3,
...
basically the question is, how do I get the values out from the __matchingData array?
I thought the syntax for it should be something like:
$var = $query->insurance->name or $var = $query->insurances['name'] but both things debugged give me 'null'
This should work with your current results.
$var = $query->_matchingData['Insurances']->name
Note, that if you contain association to your query, it should be available also as standard property in result set.
http://book.cakephp.org/3.0/en/orm/query-builder.html#filtering-by-associated-data
The data from the association that is ‘matched’ will be available on
the _matchingData property of entities. If you both match and contain
the same association, you can expect to get both the _matchingData and
standard association properties in your results.
I'm using this page as a reference guide: core:PHP
It reads as applying to attributes that already exist in my LDAP, but what if I wanted to add a new attribute entirely?
I added the following two new ones; the first is being renamed to something new, and the second one is static:
saml20-idp-hosted.php
_____________________
100 => array(
'class' => 'core:PHP',
'code' => '
if (!empty($attributes["blahblahID"])) {
$employeeID = $attributes["blahblahID"][0];
$attributes["employeeID"] = array($employeeID);
}
$attributes["securityKey"] = array("123456");
if (!empty($attributes["displayname"])) {
$displayname = $attributes["displayname"][0];
$attributes["UserName"] = array($displayname);
}
',
),
saml20-sp-remote.php
____________________
$metadata['Corestream'] = array(
'metadata-set' => 'saml20-sp-remote',
'simplesaml.attributes' => true,
'attributes' => array('UserName','employeeID','securityKey'),
.........
Will the employeeID and securityKey attributes automatically pass to the SP in this way?
EDIT:
I was able to run a test and am getting an error from the SP that the attribute UserName does not exist. What did I do incorrectly?
You will be better off using core:AttributeMap and core:AttributeAdd for this. Usage of the core:PHP module is generally not recommended, due to PHP recommending against these kinds of constructions. If you really need something that is not offered by the included AuthProc filters, consider writing your own.
I'm writing an application that uses Zend Framework 2 and Doctrine (both the latest stable version).
There is much documenation (mainly tutorials and blog posts) that deal with saving doctrine entities to the database in combination with Zend Form. Unfortunately they only deal with simple entities that do not have one-to-many or many-to-many relationships.
This is one of those examples that i have adopted into my own code.
http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/
I understand that in the Album Entity of this example, the artist is a string to keep the (already lengthy) tutorial as simple as possible. But in a real world situation this would of course be a one-to-many releationship with an Artist Entity (or even a many-to-many). In the view, a select-box could be displayed where the artist can be selected, listing all the artist-entities that could be found in the database, so the right one can be selected.
Following the example with the album, this is how i've set up an 'edit' Action in my controller:
public function editAction()
{
// determine the id of the album we're editing
$id = $this->params()->fromRoute("id", false);
$request = $this->getRequest();
// load and set up form
$form = new AlbumForm();
$form->prepareElements();
$form->get("submit")->setAttribute("label", "Edit");
// retrieve album from the service layer
$album = $this->getSl()->get("Application\Service\AlbumService")->findOneByAlbumId($id);
$form->setBindOnValidate(false);
$form->bind($album);
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
// bind formvalues to entity and save it
$form->bindValues();
$this->getEm()->flush();
// redirect to album
return $this->redirect()->toRoute("index/album/view", array("id"=>$id));
}
}
$data = array(
"album" => $album,
"form" => $form
);
return new ViewModel($data);
}
How would this example need to be altered if the artist wasn't a string, but an Artist Entity?
And suppose the album also has multiple Track Entities, how would those be processed?
The example would not need to be changed at all, the changes will happen with your entity and your form.
This is a good reference: Doctrine Orm Mapping
So to save yourself a lot of extra work, your OnToMany relationship would use: cascade = persist:
/**
* #ORM\OneToMany(targetEntity="Artist" , mappedBy="album" , cascade={"persist"})
*/
private $artist;
When it comes to persisting the form object, the entity knows it must save the associated entity as well. If you did not include this, then you would have to do it manually using a collection.
To make like easier with your form, you can use Doctrines Object Select like this:
$this->add(
[
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'artist',
'options' => [
'object_manager' => $this->objectManager,
'target_class' => 'Artist\Entity\Artist',
'property' => 'name', //the name field in Artist, can be any field
'label' => 'Artist',
'instructions' => 'Artists connected to this album'
],
'attributes' => [
'class' => '', //Add any classes you want in your form here
'multiple' => true, //You can select more than one artist
'required' => 'required',
]
]
);
So now your form takes care of the collection for you, the controller as per your example does not need to change since the entity will take care of the persisting...
Hope this gets you on track.
I have two main tables:
Books (id, author, isbn, ...)
Users (id, username, password, ...)
I am looking at building an application, wherein User1 logs in and can:
view list of all books (eg. only title)
view details (author, isbn, ...) of only certain books that he should have access to
Each user may have access to a certain set of books. I don't need various roles.
I have setup the MVC and the relationships (habtm) for the above. I am now looking at developing the permissions. Do you think the CakePHP ACL solves this problem or is it overkill?
If it is overkill, is there another component or easier way to build the desired functionality?
Yes, ACL is overkill
ACL is a very powerful and flexible system - but it doesn't come free it brings with it complexity. Unless you have a usecase where you absolutely need fine-grained permissions (the two rules you've described do not fit this) - don't use ACL.
Restricting to books a user he has added
This rule is easy to implement - e.g. add to relevant find calls:
$results = $BookModelInstance->find('all', array(
'conditions' => array(
'created_by' => AuthComponent::user('id')
)
));
Restricting to books a user he has bought
This rule is also easy to implement, thought slightly more involved:
$BookModelInstance->bindModel(array(
'hasOne' => array( // Yes, hasOne not hasMany
'MyPurchase' => array(
'className' => 'Purchase',
'foriegnKey' => 'user_id'
)
)
));
$results = $BookModelInstance->find('all', array(
'recursive' => 0, // to join hasOne+belongsTo associations into the query
'conditions' => array(
'MyPurchase.user_id' = AuthComponent::user('id'),
)
));
The bindModel call achieves the equivalent of SELECT .. FROM books LEFT JOIN book_users.. The conditions in the find call will therefore restrict results to books where there is a record of the user purchasing the book.
Putting them both together
A simplistic implementation of automatically applying both these rules would be:
model Book extends AppModel {
public $actsAs = array('Containable');
public $restrictToUser = true;
public function beforeSave($options = array()) {
if (!$this->id) {
// Store who created this book
$this->data[$this->alias]['created_by'] = AuthComponent::user('id');
}
return true;
}
public function beforeFind($queryData) {
if (!$this->restrictToUser) {
// we don't want to apply user-level restrictions
return true;
}
$userId = AuthComponent::user('id');
if (!$userId) {
// we want to restrict to the current user - there isn't one.
return false;
}
// define the association to the purchase table
$this->bindModel(array(
'hasOne' => array(
'MyPurchase' => array(
'className' => 'Purchase',
'foriegnKey' => 'user_id'
)
)
));
//ensure the purchase table is included in the current query
$queryData['contain']['MyPurchase'] = array();
// restrict to rows created by the current user, OR purchased by the current user
$queryData['conditions']['OR'] = array(
$this->alias '.created_by' => $userId,
'MyPurchase.user_id' => $userId
);
return $queryData;
}
}
This requires a field created_by (or equivalent) to be in the books table, and uses containable to ensure that the purchases table (or equivalent) is included in all relevant queries.
Most simple solution: Add a condition in your controller, so:
$this->set('books', $this->Book->find(
'all',
array('conditions' => array('Book.user_id' => $user['User']['id']))
);
Disadvantages: You will likely create duplicate code here since this check has to happen also in other places. Also when you start testing your model you can only test that it returns books, you cannot test a model method like: getMyBooks($userId). So no, not the preferred solution.
Next solution: Check in the model
It could be done by a check in for example your books model. You could just check in the afterfind() method whether the returned records are allowed or not. In your beforefind you could also add an additional condition to all queries.
In general a model should be fat so I would suggest implementing clear methods there like: getAllBooks, getBooksOfUser($User), getLatestBooksOfUser($User) etc.
Why is this a nice implementation? Because you now manage the access levels in a central place. You can test the model and you are sure it does only return books from this user.
With beforeSave etc. you can intervene every save attempt and first check: hey, you want to save this but is this really your book?
ACL solution
But in general it could be wise to implement some ACL solution (preferably the built in one) since that makes you application much more future proof. It allows flexibility, for example:
Each user may have access to a certain set of books. I don't need various roles.
That's true for now but the future can change it. So if you need a quick solution just custom filter the records. But think about the future.