Classi php reference, clone, duplicate

 

È molto interessante notare la differenza tra clonazione, duplicazione e referenza ad una classe. In questo piccolo articolo ci chiariremo le idee in tal senso.

Vi invito ad eseguire lo script che segue in un file .php

// Classe sorgente
$class = new stdClass();
// Assegnazione
$a = $class;
// Referenza
$b = &$class; // Clonazione
$c = clone $class; // Creo una proprietà per $class e gli assegno un valore. $class->roba = 'roba'; // Dump delle differenze var_dump($a); var_dump($b); var_dump($c);

Il risultato che io ottengo è il seguente:

object(stdClass)#1 (1) {
  ["roba"]=>
  string(4) "roba"
}
object(stdClass)#1 (1) {
  ["roba"]=>
  string(4) "roba"
}
object(stdClass)#2 (0) {
}

Come dobbiamo interpretare questo risultato?

La questione è molto semplice come possiamo vedere:

  • $class è la classe sorgente;
  • $a  rappresenta una copia di $class ottenuta per assegnazione (tramite l’operatore di assegnazione ‘=’);
  • $b referenzia $a, significa che è un puntatore alla risorsa, non un suo duplicato;
  • $c è invece un clone della classe.

Quello che vediamo nei 3 var_dump è:

  • che $a e $b si comportano allo stesso modo e dal numero identificativo della risorsa (quello con il cancelletto) capiamo che si tratta della stessa cosa (ovvero di puntatori a $class);
  • $c invece rappresenta una nuova istanza della classe (stdClass) ottenuta per clonazione.

Translate a Drupal 7 custom module via l10n_update

It is really a big deal to manage translations of custom module in Drupal 7 expecially if you have a multisite installation.

Problem

We want use a .po file to translate a custom module programmatically, i.e. without forcing a redactor to do dangerous manual operations.

Furthermore we want have our module always accompained by its translations.

Solution

First of all we need to have l10n_update module installed.

Than we can declare the hook “l10n_update_projects_alter” which allow to set a remote path where the .po file is hosted.

Normally the path should be a remote, indipendent one, but in most cases we would like to have the .po file inside the website itself (i.e. not a separeted environment).

Take a look to the code below in which I declare a .po file that is in the module folder, in particular in “translations” subfolder.

As you can see the file name contains the parameter %language. In this case the filename would be ModuleName.LanguageCode.po.

/**
 * Alter the list of project to be updated by Localization Update.
 *
 * L10n_update uses the same list of projects as update module. Using this hook
 * the list can be altered. This hook is typically used to alter the following
 * values from the .info file:
 *  - interface translation project
 *  - l10n path.
 *
 * @param array $projects
 *   Array of projects.
 */
function my_module_name_l10n_update_projects_alter(array &$projects) {
  // Setting module name.
  $name = 'my_module_name';
  // Setting the path of .po files.
  $pathToModule = drupal_get_path('module', $name);
  $pathToPo = $pathToModule . '/translations/';
  $poFileName = $name . '.%language.po';
  // Getting url to po
  $urlToPoFolder = file_create_url($pathToPo);
  $urlToPoFile = $urlToPoFolder . $poFileName;

  /**
   * In case of S3 filesystem uncomment the code below.
   */
  // Instead of the default ftp.drupal.org we use the file system of the test
  // instance to simulate a remote file location.
  //$wrapper = file_stream_wrapper_get_instance_by_uri('public://');
  //$remote_url = $wrapper->getExternalUrl() . '/remote/';

  // With this hook it is also possible to add a new project which does not
  // exist as a real module or theme project but is treated by the localization
  // update module as one. The below data is the minimum to be specified.
  // As in the previous example the 'l10n path' element is optional.
  $projects[$name] = array(
    'project_type'  => 'module',
    'name' => $name,
    'info' => array(
      'name' => 'My Module name',
      'interface translation project' => $name,
      'version' => '7.x-1.0',
      'core' => '7.x',
      'l10n path' => $urlToPoFile,
    ),
  );
}

Furthermore with the following snippet, I have manually (i.e. programmatically) forced the module to update its translations.

// Getting dependencies.
module_load_include('inc','l10n_update','l10n_update.translation');
module_load_include('inc','l10n_update','l10n_update.fetch');


$projects = ['my_module_name'];


$options = _l10n_update_default_update_options();
$options['customized'] = true;
$options['use_remote'] = true;
$options['overwrite_options']['customized'] = true;

l10n_update_clear_status();
$batch = l10n_update_batch_update_build($projects, [], $options);
batch_set($batch);

The .po files have been extracted thanks to Translation Template Extractor.

Drupal 8 views ajax manual refreshing does not work properly

Interviewer: Drupal 8 is amazing … isn’t it? 

Angry me: No, it’s not!

One of the problems we have spent lot’s of energies on is related to Drupal 8 views.
As you probably know the contrib module views has been integrated as a core module in this version 8 of Drupal.

Eventough there’s a nice page with documentation on D8 views, as a Drupal developers we know we can not fully rely on it to get rid of problems.

The problem

When a view is printed into a webpage as block or in a shape different of “page” display type, you can not have ajax features working properly on it, furthermore you are also not able to manually (via javascript) refresh it (triggering “RefreshView”).

If you watch what happen in a standard views with page as display type, and then start to playing “find the difference” with the other display types, you will (soon or later) notice that lot’s Javascript files views-ajax related, are not even included into the DOM!

But, what is happening?

For some reason, after hours, we have understand that even if you flag the checkbox to “use ajax” you are not able to get 

Drupal.views.instances

in browser console and neither, of course, the ajax views behavior.

The solution

When you are invoking the view do not forget to invoke “preview” method too, because it is responsible to prepare the view as desired.

<?php

// Getting a view.
$view = Views::getView('view_name');
// Invoking preview to pre and post execute the view.
$view->preview('view_display_type');
// Getting the view (WITH AJAX WORKING! YEAH!!)
$sample_reception = $view->render();

?>

We found no documentation on the web, so we assume this article will be useful for some Drupal information thirsty developer.

Thanks to Luca Rossi that achieved the solution.