I want to migrate data from custom table to book content type, however I have no idea how to achieve that.
This is my config\install\migrate.migration.book_content.yml file:
id: book_content
label: Book content
migration_group: example
source:
plugin: book_content
target: db_migration
destination:
plugin: entity:node
process:
type:
plugin: default_value
default_value: article
title: title
uid:
plugin: default_value
default_value: 1
sticky:
plugin: default_value
default_value: 0
status:
plugin: default_value
default_value: 1
'body/value': content
'body/summary': excerpt
'body/format':
plugin: default_value
default_value: full_html
# Use of the migration process plugin.
# That will use the id map of the specified migration
# to retrieve the corresponding id ('source' parameter) in the destination database.
field_description:
plugin: migration
source: body
src\Plugin\migrate\source\BookContent.php
<?php
/**
* #file
* Contains \Drupal\docapi_migrate\Plugin\migrate\source\BookContent.
*/
namespace Drupal\example_migrate\Plugin\migrate\source;
use Drupal\migrate\Plugin\migrate\source\SqlBase;
use Drupal\migrate\Row;
/**
* Drupal 8 node from database.
*
* #MigrateSource(
* id = "book_content"
* )
*/
class BookContent extends SqlBase {
/**
* {#inheritdoc}
*/
public function query() {
$query = $this->select('docapi_migrate', 'dm')
->fields('dm', array('url', 'depth', 'body', 'meta'));
return $query;
}
/**
* {#inheritdoc}
*/
public function fields() {
$fields = array(
'url' => $this->t('Content url'),
'depth' => $this->t('Depth of the content'),
'body' => $this->t('Full text of the content'),
'meta' => $this->t('yaml data'),
);
return $fields;
}
However when I do:
drush migrate-import book_content
I get:
The drush command 'migrate-import book_content' could not be found.
I don't understand how this functions in BookContent.php work.
There should be the tags_field with is taxonomy reference, but I have no idea, where should I process the meta, so for example I get a list of Tags.
And when I have tags, how should I combine it, so the migration works.
I was searching via google for information, but nothing really make sense. How can I understand this?
You namespace is set to example_migrate. It needs to be set to the name of your module, so unless the module is called "example_migrate" it cannot find the class.
Change the name space to match YOUR_MODULE_NAME.
namespace Drupal\YOUR_MODULE_NAME\Plugin\migrate\source;
More about namespaces can be found when Googling for PSR0.
Related
I'm using Translatable and EasyAdmin in a Symfony 5 project and I have configured 2 languages.
The issue is I need to be able to edit the different languages of a record in EasyAdmin, I have checked the docs of Translatable, EasyAdmin and Symfony, There is very little information about how to integrate database translations into EasyAdmin.
Therefore, I'm a bit stuck in terms of code, I have tried configuring setTranslationParameters() inside the entity CRUD controller and changing some configuration in the DashboardController however, I don't think this is the right approach.
Any suggestions of how to solve this issue?
Thank you for your effort and time.
as of writing, this feature doesn't exist in EasyAdmin, please see the link to the answer to the issue on Github.
https://github.com/EasyCorp/EasyAdminBundle/issues/4982
However, a work around is possible with a different package:
remove doctrine-extensions/DoctrineExtensions and then install KnpLabs/DoctrineBehaviors
install a2lix/translation-form-bundle
Create a translation field:
<?php
declare(strict_types=1);
namespace App\Controller\Admin\Field;
use A2lix\TranslationFormBundle\Form\Type\TranslationsType;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
final class TranslationField implements FieldInterface
{
use FieldTrait;
public static function new(string $propertyName, ?string $label = null, array $fieldsConfig = []): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
->setFormType(TranslationsType::class)
->setFormTypeOptions([
'default_locale' => 'cz',
'fields' => $fieldsConfig,
]);
}
}
Use the TranslationField inside your admin CRUD controller:
public function configureFields(string $pageName): iterable
{
return [
TextField::new('title', 'title')->hideOnForm(),
TranslationField::new('translations', 'translations', [
'title' => [
'field_type' => TextType::class,
'required' => true,
]
// add more translatable properties into the array
])->setRequired(true)
->hideOnIndex()
];
}
I have setup a database table in which the ID values will be created by my application and NOT the database.
/**
* #ORM\Column(type="bigint", precision=14, options={"unsigned":true})
* #ORM\Id()
* #ORM\GeneratedValue("NONE")
*/
private $id;
This works fine in symfony, but I am trying to edit the table using EasyAdmin and EasyAdmin simply omits the 'id' column.
I found out that I can manipulate edit/new views configuration from EasyAdmin documentation.
Now I have the following configuration (the mentioned id is for Product):
easy_admin:
entities:
- AppBundle\Entity\Category
- AppBundle\Entity\Product
Question:
1- How do I setup the YAML configuration so id field will also appear? I found out that this partially works:
easy_admin:
entities:
Product:
class: AppBundle\Entity\Product
form:
fields:
- 'id'
But this shows only 'id', is there a way to tell that I want 'id' in addition to all the other fields so I don't have to list them manually?
2- My original config is using a list of entities with dash (-) in the YAML file. I am a YAML noob, when I make a Product: key I am not able to use the dash anymore, is there a way to keep using dash list and just make an exception for 'Product? For example the code below does NOT work, it says it is not valid YAML.
easy_admin:
entities:
- AppBundle\Entity\Category
Product:
class: AppBundle\Entity\Product
form:
fields:
- 'id'
Well, for now I solved the problem like this and abandoned the dash notation altogether:
easy_admin:
entities:
Category:
class: AppBundle\Entity\Category
Store:
class: AppBundle\Entity\Store
Product:
class: AppBundle\Entity\Product
edit:
fields:
- { property: 'stores', label: 'Stores', type_options: { by_reference: false } }
form:
fields:
- 'id'
- 'name'
- 'category'
- 'stores'
Q1: you can use customization based on entity controllers. See doc here: https://symfony.com/doc/master/bundles/EasyAdminBundle/book/complex-dynamic-backends.html#customization-based-on-entity-controllers
app/config/config.yml
User:
class: AppBundle\Entity\User
controller: UserBundle\Controller\Admin\UserController
And then in your UserController you can have something like this. Pay attention you must use the exact entity name in method signature: createUserEntityFormBuilder in your case
protected function createUserEntityFormBuilder($entity, $view)
{
$form = parent::createEntityFormBuilder($entity, $view);
$form->add('Anyfield', TextType::class, [
'label' => 'id' // feel free to add other options
]); // add fieldlike you would do in FormType
$form->remove('anyField');
return $form;
}
Q2: I can't answer to this question for sure. I do not use "Dashed" notation.
Maybe take a look at doc here: https://symfony.com/doc/current/components/yaml/yaml_format.html#collections
I'm trying to set up an Admin as a child of an other Admin in Sonata Admin Bundle.
I have 2 Admin classes:
CategoryAdmin
This class contains the following method
protected function configureSideMenu(MenuItemInterface $menu, $action, AdminInterface $childAdmin = null)
{
$id = $this->getRequest()->get('id');
$menu->addChild(
$this->trans('Projects'),
array('uri' => $this->getChild('sonata.admin.project')->generateUrl('list', array('id' => $id)))
);
}
ProjectAdmin
This class contains protected $parentAssociationMapping = 'category';
category is the property in the model class representing the ManyToOne association.
I added the following lines to my service configuration for CategoryAdmin
calls:
- [ addChild, ["#sonata.admin.project"]]
The routes for the child Admin are not being generated with this configuration. The link in the SideMenu (top menu) points to /admin/project/list?childId=1&id=1
Here is the output of the children of CategoryAdmin with dump()
array:1 [▼
"sonata.admin.project" => ProjectAdmin {#406 ▶}
]
This means that the configuration for my child admin seems to be correct. I have no idea, why the routes for the child admin are not being generated.
I hope somebody can give me a hint, what the problem could be.
Note for next gen sonata coders:
If your route is not being generated, first check you didn't do:
protected function configureRoutes(RouteCollection $collection)
{
//clear all routes except given !!!
$collection->clearExcept(array('list', 'show'));
}
It costs me two days...
Do you have the $baseRouteName and $baseRoutePattern overriden in your admin class ?
If you do, Sonata will generate both child and parent routes with the same name resulting in the parent routes overriding the child ones.
I bumped into this issue while solving the problem for myself and decided to share the solution, which costed me several debugging hours...
The only way to generate a proper uri in this case is to use low-level routeGenerator which doesn't make any sonata suggestions, made inside generateMenuUrl method.
First you have to debug the routes, you have in your app (including autogenerated by sonata).
php bin/console debug:router
For example I have 3 nesting levels
hall -> seats scheme -> sector
And my routes are following:
adminHall_list ANY ANY ANY /admin/hall/list
adminHall_create ANY ANY ANY /admin/hall/create
adminHall_edit ANY ANY ANY /admin/hall/{id}/edit
adminHall_delete ANY ANY ANY /admin/hall/{id}/delete
adminHall_adminScheme_list ANY ANY ANY /admin/hall/{id}/scheme/list
adminHall_adminScheme_create ANY ANY ANY /admin/hall/{id}/scheme/create
adminHall_adminScheme_edit ANY ANY ANY /admin/hall/{id}/scheme/{childId}/edit
adminHall_adminScheme_delete ANY ANY ANY /admin/hall/{id}/scheme/{childId}/delete
adminHall_adminScheme_adminSector_list ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/list
adminHall_adminScheme_adminSector_create ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/create
adminHall_adminScheme_adminSector_edit ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/{childChildId}/edit
adminHall_adminScheme_adminSector_delete ANY ANY ANY /admin/hall/{id}/scheme/{childId}/sector/{childChildId}/delete
In admin classes baseRouteName and baseRoutePattern has been overridden.
// HallSchemeAdmin.php
$this->baseRouteName = 'adminScheme';
$this->baseRoutePattern = 'scheme';
To generate a most deep listing url:
$url = $admin->getRouteGenerator()->generate('adminHall_adminScheme_adminSector_list', [
'id' => $admin->getRequest()->get('id'),
'childId' => 555, // put required id
]);
It will produce the url like this:
/admin/hall/495/scheme/555/sector/list
If you need edit url, you have to provide childChildId param too:
$url = $admin->getRouteGenerator()->generate('adminHall_adminScheme_adminSector_edit', [
'id' => $admin->getRequest()->get('id'),
'childId' => 555,
'childChildId' => 12345
]);
The result is:
/admin/hall/495/scheme/555/sector/12345/edit
I have installed Drupal 7.34 in my computer and created a module named "mymodule". I already created successfully the file mymodule.info and mymodule.module. Below are their following contents:
[mymodule.info]
; $Id$
name = mymodule
description = Alyssa Gono's first module.
core = 7.x
package = Example
[mymodule.module]
<?php
// $Id$
/**
* #file
* Main module file for mymodule Module.
*/
/**
* Implementation of hook_permission().
*
* This function takes 0 arguments, and returns an array of permissions defined by our module. Our permissions are automatically made avilable
* under admin/user/permissions.
*/
function mymodule_permission() {
return array(
'administer mymodule' => array(
'title' => t('Administer mymodule'),
'description' => t('Perform administration tasks for mymodule.'),
),
);
}
But when I navigate to Permissions Page, to find out if my hook permissions was implemented successfully, the permission I made seems not to show up. where did I go wrong?
Your code looks fine. Maybe it is a cache issue. Try clearing the cache from ?q=admin/config/development/performance and see if the permission is shown.
I have a module job_post which installs job_post content type.
In this module I have hook_unistall() which calls for node_type_delete() function which removes my content type.
After unistalling process I have errors from Drupal's core module comment which fires from node_type_delete() after module_invoke_all('node_type_delete', $info).
Error is the following and repeats 8 times (because of the loop in comment_node_type_delete()):
Notice: Trying to get property of non-object in comment_node_type_delete()
(line 343 of ....\comment.module).
I have this error because $info variable in node_type_delete() function is false.
My question is, why when my module is installed and when I'm printing var_dump(node_type_get_type('job_post')) on any page, I have an object, but when I'm trying to print the same code in my unistall function I get false and this error?
job_post.install
/**
* Implements hook_install().
*/
function job_post_install() {
node_types_rebuild();
$types = node_type_get_types();
node_add_body_field($types['job_post']);
$body_instance = field_info_instance('node', 'body', 'job_post');
$body_instance['type'] = 'text_summary_or_trimmed';
field_update_instance($body_instance);
}
/**
* Implements hook_uninstall().
*/
function job_post_uninstall() {
$instances = field_info_instances('node', 'job_post');
foreach ($instances as $instance_name => $instance) {
field_delete_instance($instance);
}
// Force rebuild of the node type cache
// as Clive suggested didn't help
// _node_types_build(TRUE);
node_type_delete('job_post');
field_purge_batch(1000);
}
job_post.module
/**
* Implements hook_node_info() to provide our job_post type.
*/
function job_post_node_info() {
return array(
'job_post' => array(
'name' => t('Job Post'),
'base' => 'job_post',
'description' => t('Use this content type to post a job.'),
'has_title' => TRUE,
'title_label' => t('Job Title'),
'help' => t('Enter the job title and job description')
)
);
}
/**
* Implement hook_form() with the standard default form.
*/
function job_post_form($node, $form_state) {
return node_content_form($node, $form_state);
}
Note: This module example was taken from Pro Drupal 7 Development book (page 141) with minor changes and it was given errors even with original.
Hi by referring to documentation an core modules of Drupal 7. There is a usage problem.
hook_node_info defines a content type automatically. The content types which are created in this way, uninstalled-disable automatically.
Core blog module defines hook_node_info but does not operate any node_type_delete on hook_uninstall
http://api.drupal.org/api/drupal/modules%21blog%21blog.module/function/blog_node_info/7
When you call node_type_delete('job_post'); on hook_uninstall, node type info has already gone. Because of that comments module raises error.
Normally you should only remove any data related to your content type. And let the rest to be done by core.
Additionally if you really want create/delete your content type, you may not use hook_node_info. You can manually create/delete content type on install/uninstall hook.
Sample uninstall here:
http://public-action.org/content/drupal-7-field-api-drupal-7-adding-custom-content-type-custom-fields-field-api
It seems like the node type cache hasn't been built fully for some reason, try forcing the rebuild before you call node_type_delete() and all node types should be made available:
// Force rebuild of the node type cache
_node_types_build(TRUE);
// Delete our content type
node_type_delete('job_post');