unable to create drupal 7 module - drupal

Actually I am trying to create drupal module . But I am Faild
Here is my Code . I just want to display Iframe by using module .
CODE (MY_info.info):
name = MY_info
description = embedded widget
core = 7.x
CODE (My_info.module)
/**
* #file
* MY_info.module
*/
/**
* Implements hook_menu().
*/
function MY_info_menu() {
$items = array();
return $items;
}
/**
* Implements hook_form_alter().
*/
function MY_info_form_alter() {
}
Can Anyone hel me how to create it . ?

You Need To Create Block Module To Display Iframe
use hook_block_info() ; hook_block_view();
Try This One CODE (My_info.module)
<?php
function MY_info_block_info() {
$blocks['MY_info_block'] = array(
'info' => t('Your Content For Block Menu'),
// DRUPAL_CACHE_PER_ROLE will be assumed.
);
return $blocks;
}
function MY_info_block_view($delta = '') {
// This example is adapted from node.module.
$block = array();
switch ($delta) {
case 'MY_info_block':
$block['subject'] = t('Your Block Title');
$block['content'] = "Your Html Content";
break;
}
return $block;
}

Related

How to pass parameter to ajax callback from hook_form_alter in Drupal 8

I'm trying to implement a hook_form_alter method to modify the behaviour of one field through ajax callback in the form display of node.
The idea is when I select one option from the select list field (field_country) modify the values of other field list (field_laws). Specificly, when I select one country, the hook method pass this value (current) through ajax callback to changeLawsData. This callback get one external service that returns one array of values filtered by the country selected previously.
The issue is inside of callback method, i can't access to $form and $form_state objects that contain the previous hook_form_alter.
My question is: Is posible to pass by arguments this objects to the callback? With this i could handler the state of form and its field, for example.
Something like this:
$form['field_country']['widget']['#ajax'] = array(
'callback' => [$this,'changeLawsData'],
'event' => 'change',
'disable-refocus' => FALSE,
**'arguments' = array($form, $form_state)**
);
Here is the full code of this implementation.
<?php
namespace Drupal\obs_urban_system\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
/**
* Our event subscriber class.
*/
class NodeUrbanSystemFormAlterEventSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
HookEventDispatcherInterface::FORM_ALTER => 'hookFormAlter'
];
}
/**
* Implements hook_form_alter
*/
public function hookFormAlter($event) {
if($event->getFormId() == 'node_urban_system_edit_form') {
$form = $event->getForm();
$country = $form['field_country']['widget']['#default_value'];
$form['field_laws']['widget'][0]['value']['#options'] = \Drupal::service('custom_services.law')->getLawsByContent($country, 'country');
$form['field_law_articles']['widget'][0]['value']['#options'] = \Drupal::service('custom_services.law')->getLawArticlesByCountry($country);
$form['field_country']['widget']['#ajax'] = array(
'callback' => [$this,'changeLawsData'],
'event' => 'change',
'disable-refocus' => FALSE
);
$event->setForm($form);
}
}
/**
* #param $form
* #param \Drupal\Core\Form\FormStateInterface $form_state
* #return \Drupal\Core\Ajax\AjaxResponse
*/
function changeLawsData(&$form, FormStateInterface $form_state) {
<!--- HERE IM USING THE $form object --->
$country = $form['field_country']['widget']['#default_value'];
<!--- --->
$laws = \Drupal::service('custom_services.law')->getLawsByContent($country, 'country');
foreach ($laws as $key => $value) {
$option .= "<option value='" . $key . "'>" . $value . " </option>";
}
$response = new AjaxResponse();
$response->addCommand(new HtmlCommand('#edit-field-laws-0-value', $option));
return $response;
}
}
Thanks to all very much.
You need to do all the form manipulation within the form_alter.
When the ajax callback is fired, the form will be rebuilt and the current values of the form will be available in the form_state.
Your ajax callback should only return what is needed on the front end, it should not actually manipulate the form array.
Here is an example with your code (example only, untested)
<?php
namespace Drupal\obs_urban_system\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
/**
* Our event subscriber class.
*/
class NodeUrbanSystemFormAlterEventSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
HookEventDispatcherInterface::FORM_ALTER => 'hookFormAlter'
];
}
/**
* Implements hook_form_alter
*/
public function hookFormAlter($event) {
if($event->getFormId() == 'node_urban_system_edit_form') {
$form = $event->getForm();
$country = $form['field_country']['widget']['#default_value'];
// Get the form state object.
$form_state = $event->getFormState();
// Here we should check if a country has been selected.
$country = $form_state->getValue('country');
if ($country) {
// populate the options from service here.
$form['field_laws']['widget']['#options'] = \Drupal::service('custom_services.law')->getLawsByContent($country, 'country');
} else {
// Populate with default options.
$form['field_laws']['widget']['#options'] = [];
}
$form['field_law_articles']['widget'][0]['value']['#options'] = \Drupal::service('custom_services.law')->getLawArticlesByCountry($country);
$form['field_country']['widget']['#ajax'] = array(
'callback' => [$this,'changeLawsData'],
'event' => 'change',
'disable-refocus' => FALSE
);
$event->setForm($form);
}
}
/**
* #param $form
* #param \Drupal\Core\Form\FormStateInterface $form_state
* #return \Drupal\Core\Ajax\AjaxResponse
*/
function changeLawsData(&$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$response->addCommand(new HtmlCommand('#edit-field-laws', $form['field_laws']));
return $response;
}
}
Please remember that the above is an example...

how to send scheduled emails with sendGrid and symfony

I'm building an application with symfony3 in which I have an EmailService basin on SendGridService.
Sending emails is okay, but I want to schedule my emails.
This is SendGridEmailService :
<?php
namespace AppBundle\Services;
use SendGrid;
use Swift_Attachment;
use Swift_Mailer;
use Swift_Message;
use Swift_SmtpTransport;
use Twig_Environment;
class SendGirdEmailService
{
/**
* Library to facilitate email messages being sent out, sendMail deprecated in symfony 1.2
*
* #param string $partial - Array with html and text partials ie array('text'=>'textPartial', 'html'=>'htmlPartial')
* #param array $parameters - Array we will pass into the partials
* #param string $mailFrom - Email source
* #param string $mailTo - Email destination
* #param string $subject - The subject of the email message
* #param array $sgHeaders - What we will be placing in the SMTPAPI header. Must be null or a non-empty array
* #param array $attachments - Email contains the attachments
*/
public static function sendEmail($partials, $parameters, $mailFrom, $mailTo, $subject, $sgHeaders = null, $attachments = null)
{
// verify we have username/password to send out emails - IMPORTANT
/* if (!sfconfig::has('app_sendgrid_username') or !sfconfig::has('app_sendgrid_password')) {
throw new sfException('SMTP username/password is required to send email out');
}*/
$text = null;
$html = null;
if (is_array($partials)) {
// load libraries
//sfContext::getInstance()->getConfiguration()->loadHelpers('Partial');
if (isset($partials['text'])) {
$text = $partials['text'];
}
if (isset($partials['html'])) {
$html = $partials['html'];
}
}
if ($text === null and $html === null) {
throw new sfException('A text and/or HTML partial must be given');
}
try {
/*
* Load connection for mailer
*/
$connection = Swift_SmtpTransport::newInstance('smtp.sendgrid.net', 465, 'ssl')->setUsername('xxxxxx')->setPassword('xxxxxxx');
// setup connection/content
$mailer = Swift_Mailer::newInstance($connection);
$message = Swift_Message::newInstance()->setSubject($subject)->setTo($mailTo);
if ($text and $html) {
$message->setBody($html, 'text/html');
$message->addPart($text, 'text/plain');
} else if ($text) {
$message->setBody($text, 'text/plain');
} else {
$message->setBody($html, 'text/html');
}
// if contains SMTPAPI header add it
if (null !== $sgHeaders) {
$message->getHeaders()->addTextHeader('X-SMTPAPI', json_encode($sgHeaders));
}
// update the from address line to include an actual name
if (is_array($mailFrom) and count($mailFrom) == 2) {
$mailFrom = array(
$mailFrom['email'] => $mailFrom['name']
);
}
// add attachments to email
if ($attachments !== null and is_array($attachments)) {
foreach ($attachments as $attachment) {
$attach = Swift_Attachment::fromPath($attachment['file'], $attachment['mime'])->setFilename($attachment['filename']);
$message->attach($attach);
}
}
// Send
$message->setFrom($mailFrom);
$mailer->send($message);
}
catch (Exception $e) {
throw new sfException('Error sending email out - ' . $e->getMessage());
}
}
}
And this is the function I'm using to send my emails:
SendGirdEmailService::sendEmail(array(
'text' => $htmlContent,
'html' => $htmlContent
),
null,
$this->from,
$to,
$subject,
$sgHeaders = null,
$attachments = null
);
How can I set the parameters to send emails after one hour for example?
I found solution by setting an array with 'sent_at' index with timestamp value like :
SendGirdEmailService::sendEmail(array(
'text' => $htmlContent,
'html' => $htmlContent,
),
null,
$this->from,
$to,
$subject,
$sgHeaders =
array('send_at' => strtotime('+1 day', date_timestamp_get(new \DateTime()) ) ),
$attachments = null
);

Making Simple Rest API call in Wordpress Pages and Widgets

I'm trying to make a simple api call to a site that needs to render the data in a Wordpress Page/Widget.
I created a new page and put this code in the editor box on my dashboard:
<?php
$response = wp_remote_get( 'https://jsonplaceholder.typicode.com/posts/2' );
if( is_array($response) ) {
$header = $response['headers'];
$body = $response['body'];
}
print($response);
print($header);
print($body);
?>
Nothing is rendering on my Wordpress UI.
Yes, i'm on my local environment (using MAMP).
Solution:
Create a folder in your plugin directory and create a .php file that will be containing your api calls.
Your structure will look something like this:
class Api extends WP_Widget {
function __construct() {
$options = array(
'description' => '',
'name' => ''
);
parent::__construct('Api', 'Widget', $options);
}
public function form($instance) {
extract($instance);
// Put your HTML widget form here
}
public function widget($args, $instance) {
extract($args);
extract($instance);
$data = $this->get_api_call($args);
}
public function get_api_call($args) {
$api = wp_remote_get("http://www.example.com/json/");
$json_api = json_decode(stripslashes($api['body']));
return $json_api;
}
}
This is a basic outline instance, you'll have to customize everything according to what you exactly need from here.

Change Link Name on Generated Link Field

I'm creating a custom theme in Drupal 8 and on the node.html.twig template I'm using {{content.field_type}} to display the link of the category which the current page is in to allow the user to link back to the list of pages in that category. Using this, the page renders:
Sub Cat Name
What do I need to do change this to:
My Custom Link
It's possible to change render arrays using preprocess functions, but in your case it's not a good idea. Link you are talking about is a result of rendering of field formatter. So, you just need another field formatter for your 'Type' field, instead of current 'Label' formatter.
Creating new formatter is quite easy(especially if you use EntityReferenceLabelFormatter as an example). Suppose you have a module called entity_reference_link_formatter. Then in the directory of this module create src/Plugin/Field/FieldFormatter folder and put there the following EntityReferenceLinkFormatter.php file:
<?php
/**
* #file
* Contains Drupal\entity_reference_link_formatter\Plugin\Field\FieldFormatter\EntityReferenceLinkFormatter
*/
namespace Drupal\entity_reference_link_formatter\Plugin\Field\FieldFormatter;
use Drupal\Core\Entity\Exception\UndefinedLinkTemplateException;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'entity reference link' formatter.
*
* #FieldFormatter(
* id = "entity_reference_link",
* label = #Translation("Link"),
* description = #Translation("Display the link to the referenced entity."),
* field_types = {
* "entity_reference"
* }
* )
*/
class EntityReferenceLinkFormatter extends EntityReferenceFormatterBase {
/**
* {#inheritdoc}
*/
public static function defaultSettings() {
return [
'text' => 'View',
] + parent::defaultSettings();
}
/**
* {#inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$elements['text'] = [
'#title' => t('Text of the link to the referenced entity'),
'#type' => 'textfield',
'#required' => true,
'#default_value' => $this->getSetting('text'),
];
return $elements;
}
/**
* {#inheritdoc}
*/
public function settingsSummary() {
$summary = [];
$summary[] = t('Link text: #text', ['#text' => $this->getSetting('text')]);
return $summary;
}
/**
* {#inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = array();
foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
if (!$entity->isNew()) {
try {
$uri = $entity->urlInfo();
$elements[$delta] = [
'#type' => 'link',
'#title' => t('!text', ['!text' => $this->getSetting('text')]),
'#url' => $uri,
'#options' => $uri->getOptions(),
];
if (!empty($items[$delta]->_attributes)) {
$elements[$delta]['#options'] += array('attributes' => array());
$elements[$delta]['#options']['attributes'] += $items[$delta]->_attributes;
// Unset field item attributes since they have been included in the
// formatter output and shouldn't be rendered in the field template.
unset($items[$delta]->_attributes);
}
}
catch (UndefinedLinkTemplateException $e) {
// This exception is thrown by \Drupal\Core\Entity\Entity::urlInfo()
// and it means that the entity type doesn't have a link template nor
// a valid "uri_callback", so don't bother trying to output a link for
// the rest of the referenced entities.
}
}
$elements[$delta]['#cache']['tags'] = $entity->getCacheTags();
}
return $elements;
}
}
After enabling this module (or after clearing the cache if this module was enabled earlier), you will have 'Link' formatter for all your 'Entity reference' fields, allowing you to customize link text just in the formatter settings.

How to implement a nice solution for multilang entity slug based routes in Symfony2

I'd like to create a simple bundle to handle some multilingual pages in a website with translated slugs.
Based on translatable, sluggable and i18nrouting
implemented an entity (Page) with title, content, slug fields + locale property as the doc says
created a new Page set its title and content then translated it by $page->setTranslatableLocale('de'); and set those fields again with the german values, so that the data in the tables looks fine, they are all there
implemented the controller with type hinting signature: public function showAction(Page $page)
generated some urls in the template by: {{ path("page_show", {"slug": "test", "_locale": "en"}) }} and {{ path("page_show", {"slug": "test-de", "_locale": "de"}) }}, routes are generated fine, they look correct (/en/test and /de/test-de)
clicking on them:
Only the "en" translation works, the "de" one fails:
MyBundle\Entity\Page object not found.
How to tell Symfony or the Doctrine or whatever bundle to use the current locale when retrieving the Page? Do I have to create a ParamConverter then put a custom DQL into it the do the job manually?
Thanks!
Just found another solution which I think is much nicer and i'm going to use that one!
Implemented a repository method and use that in the controller's annotation:
#ParamConverter("page", class="MyBundle:Page", options={"repository_method" = "findTranslatedOneBy"})
public function findTranslatedOneBy(array $criteria, array $orderBy = null)
{
$page = $this->findOneBy($criteria, $orderBy);
if (!is_null($page)) {
return $page;
}
$qb = $this->getEntityManager()
->getRepository('Gedmo\Translatable\Entity\Translation')
->createQueryBuilder('t');
$i = 0;
foreach ($criteria as $name => $value) {
$qb->orWhere('t.field = :n'. $i .' AND t.content = :v'. $i);
$qb->setParameter('n'. $i, $name);
$qb->setParameter('v'. $i, $value);
$i++;
}
/** #var \Gedmo\Translatable\Entity\Translation[] $trs */
$trs = $qb->groupBy('t.locale', 't.foreignKey')->getQuery()->getResult();
return count($trs) == count($criteria) ? $this->find($trs[0]->getForeignKey()) : null;
}
It has one disadvantage there is no protection against same translated values ...
I found out a solution which i'm not sure the best, but works.
Implemented a PageParamConverter:
class PageParamConverter extends DoctrineParamConverter
{
const PAGE_CLASS = 'MyBundle:Page';
public function apply(Request $request, ParamConverter $configuration)
{
try {
return parent::apply($request, $configuration);
} catch (NotFoundHttpException $e) {
$slug = $request->get('slug');
$name = $configuration->getName();
$class = $configuration->getClass();
$em = $this->registry->getManagerForClass($class);
/** #var \Gedmo\Translatable\Entity\Translation $tr */
$tr = $em->getRepository('Gedmo\Translatable\Entity\Translation')
->findOneBy(['content' => $slug, 'field' => 'slug']);
if (is_null($tr)) {
throw new NotFoundHttpException(sprintf('%s object not found.', $class));
}
$page = $em->find($class, $tr->getForeignKey());
$request->attributes->set($name, $page);
}
return true;
}
public function supports(ParamConverter $configuration)
{
$name = $configuration->getName();
$class = $configuration->getClass();
return parent::supports($configuration) && $class == self::PAGE_CLASS;
}
}
TranslationWalker nicely gets the entity in active locale:
class PagesRepository extends \Doctrine\ORM\EntityRepository
{
public function findTranslatedBySlug(string $slug)
{
$queryBuilder = $this->createQueryBuilder("p");
$queryBuilder
->where("p.slug = :slug")
->setParameter('slug', $slug)
;
$query = $queryBuilder->getQuery();
$query->setHint(
Query::HINT_CUSTOM_OUTPUT_WALKER,
'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
);
return $query->getSingleResult();
}
}
And in controller
/**
* #Entity("page", expr="repository.findTranslatedBySlug(slug)")
* #param $page
*
* #return Response
*/
public function slug(Pages $page)
{
// thanks to #Entity annotation (Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity)
// Pages entity is automatically retrieved by slug
return $this->render('content/index.html.twig', [
'page' => $page
]);
}

Resources