Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
This belongs in /src/Plugin/DevelGenerate
It attempts to put existing content in generated groups, so that the new groups can be populated.
I couldn't attach a php file so here goes
<?php
namespace Drupal\group\Plugin\DevelGenerate;
use Drupal\devel_generate\DevelGenerateBase;
use Drupal\group\Entity\GroupContent;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Component\Utility\Random;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Generate a group and populate with content.
*
* @DevelGenerate(
* id = "group",
* label = @Translation("Group"),
* description = @Translation("Generate groups"),
* url = "group",
* permission = "administer devel_generate",
* settings = {
* "num" = 10,
* "kill" = TRUE
* }
* )
*/
class GroupGenerate extends DevelGenerateBase implements ContainerFactoryPluginInterface {
protected $groupStorage;
/**
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param array $plugin_definition
* The definition array of the plugin.
* @param \Drupal\Core\Entity\EntityStorageInterface $group_storage
* The group entity storage controller
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, $group_storage) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->groupStorage = $group_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration, $plugin_id, $plugin_definition,
$container->get('entity_type.manager')->getStorage('group')
);
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$form['kill'] = [
'#type' => 'checkbox',
'#title' => $this->t('Clear all existing groups'),
'#default_value' => $this->getSetting('kill'),
];
$form['num'] = [
'#title' => $this->t('Number of groups to generate'),
'#type' => 'number',
'#default_value' => $this->getSetting('num'),
'#min' => 1
];
$form['role'] = [
'#title' => $this->t('Role of group creators'),
'#type' => 'select',
];
foreach (\Drupal\user\Entity\Role::loadMultiple() as $rid => $role) {
if ($rid == 'anonymous') {
continue;
}
$form['role']['#options'][$rid] = $role->label();
}
$form['type'] = [
'#title' => $this->t('Group type'),
'#type' => 'select',
];
foreach(\Drupal\group\Entity\GroupType::loadMultiple() as $id => $type) {
$form['type']['#options'][$id] = $type->label();
$form[$id] = [
'#title' => $this->t('Relate existing content'),
'#description' => $this->t('A fraction of the existing content will be put into each group.'),
'#type' => 'checkboxes',
'#states' => [
'visible' => [
':input[name="type"]' => ['value' => $id],
]
]
];
foreach ($type->getInstalledContentPlugins() as $content_plugin_id => $plugin) {
$form[$id]['#options'][$content_plugin_id] = $plugin->getLabel();
}
}
return $form;
}
/**
* {@inheritdoc}
*/
protected function generateElements(array $values) {
if ($values['num'] <= 2) {
$this->generateContent($values);
}
else {
$this->generateBatchContent($values);
}
}
/**
* Method responsible for creating a small number of groups.
*
* @param string or int or object... $values
* kill, num, shared, unique, closed, deactivated, av_users, av_transactions
*
* @throws \Exception
*/
private function generateContent($values) {
if (!empty($values['kill'])) {
$this->contentKill($values);
}
if (!empty($values['type'])) {
$start = time();
for ($i = 1; $i <= $values['num']; $i++) {
$this->develGenerateGroupAdd($values);
}
}
}
/**
* Method responsible for creating content when
* the number of elements is greater than 50.
*/
private function generateBatchContent($values) {
// Add the kill operation.
if ($values['kill']) {
$operations[] = ['devel_generate_operation', [$this, 'contentKill', $values]];
}
// Add the operations to create the groups.
for ($num = 0; $num < $values['num']; $num++) {
$operations[] = ['devel_generate_operation', [$this, 'batchContentAddGroup', $values]];
}
// Start the batch.
$batch = [
'title' => $this->t('Generating Groups'),
'operations' => $operations,
'finished' => 'devel_generate_batch_finished',
'file' => drupal_get_path('module', 'devel_generate') . '/devel_generate.batch.inc',
'results' => [
'num' => 0,
],
];
batch_set($batch);
}
/**
*
* @param array $values
* The results of the form submission.
* @param array $context
* Batch context, includes array sandbox, array results, finished & message.
*/
public function batchContentAddGroup($values, &$context) {
$this->develGenerateGroupAdd($values);
$context['results']['num']++;
}
/**
* {@inheritdoc}
*/
public function validateDrushParams($args) {
$values['kill'] = drush_get_option('kill');
$values['num'] = array_shift($args);
$values['role'] = array_shift($args);
$values['type'] = array_shift($args);
// I don't know the best way to use command line to specify which enabled
// content to relate to the new groups.
return $values;
}
/**
* Deletes all groups of the given type .
*
* @param array $values
* The input values from the settings form.
*/
public function contentKill($values) {
$groups = $this->groupStorage->loadByProperties(['type' => $values['type']]);
if (!empty($groups)) {
$this->groupStorage->delete($groups);
}
}
/**
* Create one group and put stuff in it
*/
protected function develGenerateGroupAdd(&$values) {
//get the ids of users with the given role
$query = \Drupal::entityQuery('user');
if ($values['role'] != 'authenticated') {
$query->condition('roles', $values['role']);
}
$uids = $query->execute();
unset($uids[array_search(0, $uids)]);
// Create a group.
// Currently the populateFields doesn't work on baseFields, like label
$random = new Random();
$creator_uid = $uids[array_rand($uids)];
$props = [
'label' => $random->word(mt_rand(4, 12)),
'uid' => $creator_uid,
'type' => $values['type'],
];
$group = \Drupal\group\Entity\Group::create($props);
// Populate all fields with sample values.
$this->populateFields($group);
$group->save();
// Associate the new group with the specified EnabledContentTypes
$group_type = \Drupal\group\Entity\GroupType::load($values['type']);
$plugins = array_filter($values[$values['type']]);
foreach ($plugins as $content_plugin_id) {
generateContentByPlugin($group, $content_plugin_id, $values['num'] + 1);
}
return $group;
}
/**
* Relate existing content to a group
*
* @param Group $group
* The group to which the content will be related.
* @param string $content_plugin_id
* The id of the plugin e.g. group-membership.
* @param int $fraction
* The inverse of the proportion of total content of that type to put in the
* group.
* @return type
*/
function generateContentByPlugin($group, $content_plugin_id, $fraction) {
$content_plugin = $group_type->getContentPlugin($content_plugin_id);
$def = $content_plugin->getPluginDefinition();
$entity_type_id = $def['entity_type_id'];
$query = \Drupal::entityQuery($entity_type_id);
if ($def['entity_bundle']) {
$entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
$query->condition($entity_type->getKey('bundle'), $def['entity_bundle']);
}
$ids = $query->execute();
// Special case for users, remove the creator from the list of possible members
if ($content_plugin_id == 'group-membership') {
unset($ids[array_search($creator_uid, $ids)]);
}
shuffle($ids);
$limit = floor(count($ids) / ($fraction));
if ($limit < 1) {
//don't add any content
return;
}
$added = 0;
$group_content_type_id = $group_type->id() .'-'. $content_plugin_id;
while ($added < $limit) {
$props = [
'gid' => $group->id(),
'type' => $content_plugin->getContentTypeConfigId(),//should be exchange-group_membership
'entity_id' => array_pop($ids),
];
$content = GroupContent::create($props);
// If we can't add an entity because of the cardinality limit, it will
// fail to save here, and we just go around the loop again until enough
// entities are added to the group.
if ($content->save() == SAVED_NEW) {
$added++;
}
}
}
}
Comments
Comment #2
matslats CreditAttribution: matslats as a volunteer commentedComment #3
matslats CreditAttribution: matslats as a volunteer commentedComment #4
kristiaanvandeneyndeThis seems like a duplicate of #2746839: Add Devel Generate plugin for generating groups. I have already reviewed the code there, could you cross-reference it to your code and contribute to that issue? I'll add you to the list of people to receive credit there.
Comment #5
matslats CreditAttribution: matslats as a volunteer commentedOops I'm sorry I missed this.
The code there is a bit more thorough and probably the best code to commit for now.
My code is more interesting in that it has a further option to populate the groups with existing content, type by type.