My You Tube channel

Visto che l'ho fatto per YouTube perchè non fare qualcosa anche per Twitter? Qualcosa di molto semplice che però consente di avere praticamente le stesse possibilità di composizione che trovate su Twitter quando create un widget. In più avete la possibilità di imparare come integrare correttamente queste risorse nel vostro CMS Joomla!

[30-8-2014] Attenzione: gli script sono stati aggiornati correggendo 2 malfunzionamenti e implementando l'helper al fine di ritrovare codice molto più leggibile nel nostro sorgente e soprattutto per migliorare l'integrazione con il framework lasciando il template grafico libero da codice eseguibile.
Ovviamente anche nell'immagine a cui faccio riferimento nell'articolo non esiste il nuovo file helper.php. Ho tolto anche la possibilità di scelta della lingua prendendo il valore dall'internazionalizzazione del cms.

Per integrare la/le timelines di Twitter le strade possono essere più di una, fatto sta che molti dei "vecchi modi" non funzionano più perchè le API sono cambiate e d'ora in avanti l'accesso ai dati di Twitter sarà possibile solo attraverso widget ufficiali; le personalizzazioni dovranno essere conformi al Developer Display Requirements. Uso poco Twitter e soprattutto per scemenze per cui non ho mai guardato bene come customizzare le mie pagine e non mi sono mai chiesto cosa servissero i mille pulsantini sparsi ovunque,... è venuto il momento di farlo.

Per accedere alla timeline/s è necessario creare un widget, configurando o meno i parametri, al fine di ottenere un widget id legato alla vostra utenza. Per creare un widget è necessario autenticarsi e dal menù con "l'ingranaggio" scegliere prima -> Impostazioni e poi -> crea widget (a meno non ne abbiate già creati e volete esporre quelli). Alla fine della creazione verrà mostrato un codice html e un Javascript da includere nelle nostre pagine per visualizzare il widget secondo i parametri scelti. Semplice no? Però voglio qualcosa in più, ovvero poter customizzare il mio widget con dei parametri gestiti all'interno di Joomla con la realizzazione di un modulo.

La pagina per capirne qualcosa in più è questa: dev.twitter.com/docs/embedded-timelines e occorre sicuramente capirne qualcosa in più per poterlo customizzare. Ora occupiamoci di costruire una struttura così come mostrata nell'immagine sopra; i files index.html sono e resteranno vuoti mentre gli altri vedremo cosa scriverci. Ma facciamo una parentesi.

Perchè un modulo? Visto quello che trovo in giro credo non sia superfluo ragionare un'attimo scegliendo la cosa più opportuna e corretta per integrare codice nel nostro CMS Joomla!, nella speranza che dopo aver letto anche molti di voi evitino sempre le solite scorciatoie che rendono tutto instabile e insicuro nonchè sicuramente meno performate. Usando come paragone il plugin per youtube, illustrato in altro articolo, si può subito notare il differente modo d'uso dettato soprattutto dal diverso scopo del widget. Da youtube solitamente si "prelevano" singoli contenuti/video destinati a singole pagine/contenuto in punti precisi di questo e con poche problematiche di integrazione grafica. Questo widget invece è destinato ad apparire nel nostro template e raramente capiterà di doverla integrare in un contenuto e, qualora capitasse basterà creare un apposito modulo e posizionarlo con loadmodule dove vogliamo. Quindi cosa possiamo desumere sommariamente: plugin -> per manipolare il codice che si occupa della costruzione dei contenuti (non solo articoli) e moduli per mostrare il risultato di codice all'interno della grafica della nostra pagina, staticamente. Non è forse la regola più azzeccata ma se già seguite questa difficilmente vi troverete a sbagliare. Ma ora torniamo al nostro modulo.

Il file xml o manifesto serve ad installare la nostra estensione->modulo creando anche la parte relativa all'amministrazione del modulo e dei suoi parametri; dividere in più fieldsets la parte dei parametri consente di avere schermate separate in cui gestirli, quindi diamo un contenuto a mod_twstream.xml

<?xml version="1.0" encoding="utf-8"?>
<extension type="module"
    version="3.3"
    client="site"
    method="upgrade"
    >
    <name>mod_twstream</name>
    <author>Spazioalchimia</author>
    <creationDate>Agosto 2014</creationDate>
    <copyright>Copyright (C) 2014 - 2019 Spazioalchimia</copyright>
    <license>GNU General Public License version 2 or later</license>
    <authorEmail>job[at]spazioalchimia.it</authorEmail>
    <authorUrl>www.spazioalchimia.it</authorUrl>
    <version>0.2</version>
    <description>MOD_TWSTREAM_XML_DESCRIPTION</description>
    <files>
            <filename module="mod_twstream">mod_twstream</filename>
            <folder>tmpl</folder>
            <folder>language</folder>
            <filename>helper.php</filename>
            <filename>index.html</filename>
            <filename>mod_twstream.xml</filename>
    </files>

    <config>
        <fields name="params">

            <fieldset name="basic">
                <field name="usrname"
                    type="text"
                    default=""
                    label="MOD_TWSTREAM_USERNAME_LABEL"
                    description="MOD_TWSTREAM_USERNAME_DESC"
                    />
                <field name="widgetid"
                    type="text"
                    default=""
                    label="MOD_TWSTREAM_WIDGETID_LABEL"
                    description="MOD_TWSTREAM_WIDGETID_DESC"
                    />
            </fieldset>
            
            <fieldset name="twstream_customize">
                <field name="dwidth"
                    type="text"
                    default="520"
                    label="MOD_TWSTREAM_HOR_DIM_LABEL"
                    description="MOD_TWSTREAM_HOR_DIM_DESC"
                    />
                <field name="dheight"
                    type="text"
                    default="600"
                    label="MOD_TWSTREAM_VERT_DIM_LABEL"
                    description="MOD_TWSTREAM_VERT_DIM_DESC"
                    />
                <field name="theme"
                    type="list"
                    default="1"
                    label="MOD_TWSTREAM_THEME_LABEL"
                    description="MOD_TWSTREAM_THEME_DESC"
                    >
                    <option value="1">Dark</option>
                    <option value="0">Light</option>
                </field>
                <field name="lkcolor"
                    type="text"
                    default="#cc0000"
                    label="MOD_TWSTREAM_LINK_COLOR_LABEL"
                    description="MOD_TWSTREAM_LINK_COLOR_DESC"
                    />
                <field name="brdcolor"
                    type="text"
                    default="#cc0000"
                    label="MOD_TWSTREAM_BORDER_COLOR_LABEL"
                    description="MOD_TWSTREAM_BORDER_COLOR_DESC"
                    />
                <field name="twlimit"
                    type="text"
                    default="5"
                    label="MOD_TWSTREAM_TWEET_LIMIT_LABEL"
                    description="MOD_TWSTREAM_TWEET_LIMIT_DESC"
                    />
                <field name="userrel"
                    type="textarea"
                    rows="2"
                    label="MOD_TWSTREAM_WIRU_LABEL"
                    description="MOD_TWSTREAM_WIRU_DESC"
                    />
                <field name="aria"
                    type="list"
                    default="0"
                    label="MOD_TWSTREAM_ARIA_LABEL"
                    description="MOD_TWSTREAM_ARIA_DESC"
                    >
                    <option value="0">Polite</option>
                    <option value="1">Assertive</option>
                </field>
            </fieldset>
            
            <fieldset name="twstream_chrome">
                <field
                    name="noheader"
                    type="radio"
                    class="btn-group btn-group-yesno"
                    default="0"
                    label="MOD_TWSTREAM_NOHEADER_LABEL"
                    description="MOD_TWSTREAM_NOHEADER_DESC"
                    >
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field
                    name="nofooter"
                    type="radio"
                    class="btn-group btn-group-yesno"
                    default="0"
                    label="MOD_TWSTREAM_NOFOOTER_LABEL"
                    description="MOD_TWSTREAM_NOFOOTER_DESC"
                    >
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field
                    name="noborders"
                    type="radio"
                    class="btn-group btn-group-yesno"
                    default="0"
                    label="MOD_TWSTREAM_NOBORDERS_LABEL"
                    description="MOD_TWSTREAM_NOBORDERS_DESC"
                    >
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field
                    name="noscrollbar"
                    type="radio"
                    class="btn-group btn-group-yesno"
                    default="0"
                    label="MOD_TWSTREAM_NOSCROLLBAR_LABEL"
                    description="MOD_TWSTREAM_NOSCROLLBAR_DESC"
                    >
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field
                    name="transparent"
                    type="radio"
                    class="btn-group btn-group-yesno"
                    default="0"
                    label="MOD_TWSTREAM_TRANSPARENT_LABEL"
                    description="MOD_TWSTREAM_TRANSPARENT_DESC"
                    >
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
            </fieldset>
            
            <fieldset name="advanced">
                <field name="layout"
                    type="modulelayout"
                    label="JFIELD_ALT_LAYOUT_LABEL"
                    description="JFIELD_ALT_MODULE_LAYOUT_DESC"
                    />
                <field name="moduleclass_sfx"
                    type="textarea"
                    rows="3"
                    label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
                    description="COM_MODULES_FIELD_MODULECLASS_SFX_DESC"
                    />
                <field name="cache"
                    type="list"
                    default="1"
                    label="COM_MODULES_FIELD_CACHING_LABEL"
                    description="COM_MODULES_FIELD_CACHING_DESC"
                    >
                    <option value="1">JGLOBAL_USE_GLOBAL</option>
                    <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
                </field>

                <field name="cache_time"
                    type="text"
                    default="900"
                    label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
                    description="COM_MODULES_FIELD_CACHE_TIME_DESC"
                    />
                <field name="cachemode"
                    type="hidden"
                    default="static">
                    <option value="static"></option>
                </field>
            </fieldset>
        </fields>
    </config>
</extension>

I moduli hanno un "entry point" nella loro root col nome stesso del modulo che si occupa di "mettere insieme" la parte grafica del nostro modulo con la parte dati usando le classi e i metodi opportuni.

Diamo quindi un contenuto anche a mod_twstream.php

<?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_twstream
 * @copyright   Copyright (C) Spazioalchimia
 */

defined('_JEXEC') or die;

require_once __DIR__ . '/helper.php';

$conf_params = ModTwstreamHelper::getConfOverride($params);

//-> Basic
$usrname=htmlspecialchars($params->get('usrname', ''));
$widgetid=htmlspecialchars($params->get('widgetid', ''));
//-> Advanced
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx'));

// Add twitter js (copy & paste from Twitter widget mask)
$document = JFactory::getDocument();
$document->addScriptDeclaration('
          !function(d,s,id){
            var js,
            fjs=d.getElementsByTagName(s)[0],
            p=/^http:/.test(d.location)?\'http\':\'https\';
            if(!d.getElementById(id)){
                js=d.createElement(s);
                js.id=id;
                js.src=p+\'://platform.twitter.com/widgets.js\';
                fjs.parentNode.insertBefore(js,fjs);
            }
        }(document,\'script\',\'twitter-wjs\');
');

require JModuleHelper::getLayoutPath('mod_twstream', (string)$params->get('layout', 'default'));

Il pezzetto da evidenziare è quello che si occupa di integrare lo script javascript fornito da Twitter, nel nostro modulo. Per approfondire questa importante funzionalità/metodo si può fare riferimento alla pagina della guida di sviluppo.

Ora il file helper.php che si occupa di eseguire quel poco di php presente necessario a recuperare i parametri e a fornire al template grafico un contenuto adatto

<?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_twstream
 */

defined('_JEXEC') or die;

class ModTwstreamHelper{

    public static function getConfOverride($params){

        (string)$conf_string = '';

        // Get all needed parameters

        //-> Customize fieldset
        $dwidth=htmlspecialchars($params->get('dwidth', '520'));
        $dheight=htmlspecialchars($params->get('dheight', '600'));
        $theme=(int)($params->get('theme', '1')); // 1-> dark 0->light
        $lkcolor=htmlspecialchars($params->get('lkcolor', '#cc0000'));
        $brdcolor=htmlspecialchars($params->get('brdcolor', '#cc0000'));
        $twlimit=(int)($params->get('twlimit', 5));
        $userrel=trim(htmlspecialchars($params->get('userrel', 'Maurizio Spazioalchimia')));
        // is a comma separated string, must be exploded in array to better handling
        $datarel = explode(',', $userrel);
        $aria=htmlspecialchars($params->get('aria', 1)); // 0-> polite (default) 1-> assertive

        //-> Chrome fieldset
        $noheader=(bool)($params->get('noheader', 0));
        $nofooter=(bool)($params->get('nofooter', 0));
        $noborders=(bool)($params->get('noborders', 0));
        $noscrollbar=(bool)($params->get('noscrollbar', 0));
        $transparent=(bool)($params->get('transparent', 0));

        /* Width */
        if($dwidth >= 180 && $dwidth <= 600){
            $conf_string .= ' width="'.$dwidth.'"';
        }
        /* Height */
        if($dheight >= 200 && $dheight <= 520){
            $conf_string .= ' height="'.$dheight.'"';
        }
        /* Theme */
        switch((int)$theme){
            case 1: $conf_string .= ' data-theme="dark"';
                break;
            case 0: $conf_string .= ' data-theme="light"';
                break;
            default: $conf_string .= ' data-theme="dark"';
        }
        /* Link color */
        if(trim($lkcolor) != ''){
            $conf_string .= ' data-link-color="'.$lkcolor.'"';
        }
        /* Chrome -> Control the widget layout*/
        // open chrome only if occours
        if($noheader or $nofooter or $noborders or $noscrollbar or $transparent){
            $conf_string .= ' data-chrome="';
            if($noheader){
                // Hides the timeline header.
                $conf_string .= ' noheader';
            }
            if($nofooter){
                // Hides the timeline footer and Tweet box, if included
                $conf_string .= ' nofooter';
            }
            if($noborders){
                // Removes all borders within the widget (between Tweets, cards, around the widget.)
                $conf_string .= ' noborders';
            }
            if($noscrollbar){
                // Crops and hides the main timeline scrollbar, if visible.
                // Please consider that hiding standard user interface components can affect the accessibility of your website.
                $conf_string .= ' noscrollbar';
            }
            if($transparent){
                // Removes the background color
                $conf_string .= ' transparent';
            }
            // close chrome
            $conf_string .= ' " ';
        }
        /* Border color: Change the border color used by the widget */
        if(trim($brdcolor) != ''){
            $conf_string .= ' data-border-color="'.$brdcolor.'"';
        }
        /* Language: The widget language is detected from the page, based on the HTML lang attribute of your content */
        // get Joomla language
        $conf_string .= ' lang="'.JFactory::getLanguage()->getName().'"';
        /* Tweet limit: To fix the size of a timeline to a preset number of Tweets (between 1 and 20 Tweets) */
        if($twlimit >= 1 && $twlimit <= 20){
            $conf_string .= ' data-tweet-limit="'.$twlimit.'"';
        }
        /* Web Intent Related Users: As per the Tweet and follow buttons,
        * you may provide a comma-separated list of user screen names as suggested followers to a user
        *  after they reply, Retweet, or favorite a Tweet in the timeline. */
        if(!empty($datarel)){ 
            $conf_string .= ' data-related="'.implode(',', $datarel).'"';
        }
        /* ARIA politeness. ARIA is an accessibility system that aids people using assistive technology
        * interacting with dynamic web content. Read more about ARIA on W3C's website.
        * By default, the embedded timeline uses the least obtrusive setting: aria-polite="polite".
        * If you're using an embedded timeline as a primary source of content on your page,
        * you may wish to override this to the assertive setting, using data-aria-polite="assertive".
        */
        /* if default is "polite" we override only if there's a different choice // 0-> polite (default) 1-> assertive */
        if($aria){ 
            $conf_string .= ' data-aria-polite="assertive"';
        }
        
        return $conf_string;

    }
    
}

I files relativi alla internazionalizzazione o lingua possono venire installati nella cartella language di Joomla o restare all'interno di una stessa cartella nella root del modulo; io preferisco quasi sempre questa soluzione perchè sono più semplici da trovare, joomla li mette tutti insieme.
Uno dei due files si occuperà dei vocaboli di installazione e amministrazione mentre l'altro dei vocaboli nei contenuti e sono necessari entrambi. Potete cambiare le definizioni come più vi pare, per le descrizioni ho usato direttamente quelle che offre twitter quando usi la medesima funzionalità.

it-IT.mod_twstream

MOD_TWSTREAM="Embedded Twitter timeline stream"
MOD_TWSTREAM_XML_DESCRIPTION="Questo modulo visualizza lo streaming della timeline di Twitter"
MOD_TWSTREAM_LAYOUT_DEFAULT="Predefinito"
MOD_TWSTREAM_USERNAME_LABEL="Twitter user"
MOD_TWSTREAM_USERNAME_DESC=""
MOD_TWSTREAM_WIDGETID_LABEL="Widget Id"
MOD_TWSTREAM_WIDGETID_DESC=""
COM_MODULES_TWSTREAM_CUSTOMIZE_FIELDSET_LABEL="Personalizza"
MOD_TWSTREAM_HOR_DIM_LABEL="Dimensione orizzontale"
MOD_TWSTREAM_HOR_DIM_DESC="Se lasciato vuoto il modulo occuperà lo spazio del tag div che lo contiene (min.180px - max.520px - default 520px)"
MOD_TWSTREAM_VERT_DIM_LABEL="Dimensione verticale"
MOD_TWSTREAM_VERT_DIM_DESC="Se lasciato vuoto il modulo occuperà lo spazio del tag div che lo contiene (min.200px - default 600px)"
MOD_TWSTREAM_THEME_LABEL="Tema"
MOD_TWSTREAM_THEME_DESC="Chiaro o scuro"
MOD_TWSTREAM_LINK_COLOR_LABEL="Colore links"
MOD_TWSTREAM_LINK_COLOR_DESC="Colore dei links"
MOD_TWSTREAM_BORDER_COLOR_LABEL="Colore dei bordi"
MOD_TWSTREAM_BORDER_COLOR_DESC="Colore dei bordi del widget"
MOD_TWSTREAM_TWEET_LIMIT_LABEL="Tweets mostrati"
MOD_TWSTREAM_TWEET_LIMIT_DESC="To fix the size of a timeline to a preset number of Tweets, use the data-tweet-limit=5 attribute with any value between 1 and 20 Tweets. The timeline will render the specified number of Tweets from the timeline, expanding the height of the widget to display all Tweets without scrolling. Since the widget is of a fixed size, it will not poll for updates when using this option."
MOD_TWSTREAM_WIRU_LABEL="Web Intent Related Users"
MOD_TWSTREAM_WIRU_DESC="As per the Tweet and follow buttons, you may provide a comma-separated list of user screen names as suggested followers to a user after they reply, Retweet, or favorite a Tweet in the timeline. Use a data-related=benward,endform attribute on the embed code."
MOD_TWSTREAM_ARIA_LABEL="ARIA Accessibility"
MOD_TWSTREAM_ARIA_DESC="ARIA is an accessibility system that aids people using assistive technology interacting with dynamic web content. Read more about ARIA on W3C's website. By default, the embedded timeline uses the least obtrusive setting: aria-polite=polite. If you're using an embedded timeline as a primary source of content on your page, you may wish to override this to the assertive setting, using data-aria-polite=assertive"
COM_MODULES_TWSTREAM_CHROME_FIELDSET_LABEL="Chrome"
MOD_TWSTREAM_NOHEADER_LABEL="Rimuovi Header"
MOD_TWSTREAM_NOHEADER_DESC="Hides the timeline header. Please refer to the timeline display requirements when implementing your own header."
MOD_TWSTREAM_NOFOOTER_LABEL="Rimuovi Footer"
MOD_TWSTREAM_NOFOOTER_DESC="Hides the timeline footer and Tweet box, if included."
MOD_TWSTREAM_NOBORDERS_LABEL="Rimuovi Borders"
MOD_TWSTREAM_NOBORDERS_DESC="Removes all borders within the widget (between Tweets, cards, around the widget.) See also: border-color."
MOD_TWSTREAM_NOSCROLLBAR_LABEL="Rimuovi Scrollbars"
MOD_TWSTREAM_NOSCROLLBAR_DESC="Crops and hides the main timeline scrollbar, if visible. Please consider that hiding standard user interface components can affect the accessibility of your website."
MOD_TWSTREAM_TRANSPARENT_LABEL="Rimuovi Background"
MOD_TWSTREAM_TRANSPARENT_DESC="Removes the background color"
MOD_TWSTREAM_TPL_ALTERNATIVE_MSG="Tweets di @Spazioalchimia"
MOD_TWSTREAM_TWEET_DONT_OVERRIDE="Impostazioni widget"

 it-IT.mod_twstream.sys

MOD_TWSTREAM="Embedded Twitter timeline stream"
MOD_TWSTREAM_XML_DESCRIPTION="Questo modulo visualizza lo streaming della timeline di Twitter"
MOD_TWSTREAM_LAYOUT_DEFAULT="Predefinito"

 E ora la parte finale, quella grafica, quella che si occuperà di usare tutti i parametri recuperati nell'entry point per costruire graficamente il modulo e dallo stesso entry point "richiamata" quando abbiamo scritto questo:

require JModuleHelper::getLayoutPath('mod_twstream', (string)$params->get('layout', 'default'));

default.php

<?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_twstream
 * @copyright   Copyright (C) Spazioalchimia
 */

defined('_JEXEC') or die;

?>

<div class="spazioalchimia<?php echo $moduleclass_sfx;?>">
    <a class="twitter-timeline" <?php echo $conf_params;?> href="https://twitter.com/<?php echo $usrname; ?>" data-widget-id="<?php echo $widgetid; ?>">
    <?php echo JText::_('MOD_TWSTREAM_TPL_ALTERNATIVE_MSG'); ?></a>
</div>

Cosa manca? Nulla! O meglio, una cosina ve l'ho lasciata da fare perchè può essere ulteriormente customizzato con ulteriori overrides, sono spiegati quì: dev.twitter.com/docs/embedded-timelines#timeline-selection.

E anche se è il penultimo della pagina non tralasciate di leggere anche il paragrafo dedicato alla compatibilità "mobile devices", ..è una soddisfazione in più.

Per installarlo potete usare due modi:

  • Una volta creato il pacchetto così come composto da immagine all'inizio dell'articolo, lo zippate facendo attenzione a non creare un ulteriore cartella .zip; dopodichè lo installate caricando il file e facendo tutto automaticamente.
  • una volta creato il pacchetto spostate la cartella del vostro modulo all'interno della cartella /modules di Joomla poi dall'amministrazione -> esplora -> ricerca -> spunta e installa

Ricordatevi di installare il modulo anche nel pannello di amministrazione andando su "gestione moduli" -> nuovo

ATTENZIONE: usando widget.js di twitter nel vostro codice vi troverete, meraviglia delle meraviglie, un misterioso iframe "rufous-sandbox" di cui non riesco a trovare documentazione, sembra destinato al tracking dei click (se si implementa il codice). Se dovesse creare problemi con alcuni browsers è necessario replicare lo stile display:none !important; nel nostro css.

Multirotori

Multicopters I miei droni multirotore. Una semplice curiosità diventata una passione e qualcosa di più.
Il punto di incontro tra programmazione, volo, arduino, tecnica e manualità ...stimolante!
Consigli ed esperienze realizzative di vari modelli dedicati sia al divertimento che all'uso professionale.

Joomla

Joomla! Un Framework promettente ed un collaudato CMS che, con l'adeguata conoscenza, può diventare un avanzato strumento di lavoro.
Come si può conoscere uno strumento se non usandolo, sperimentando sempre nuove soluzioni e seguendo le sue problematiche di sicurezza?

Lifehacking

Lifehacking Non c'è oggetto per casa che non ho aperto, è maniacale ma non riesco a rinunciare, come se quelle quattro viti, quella fessura a scatto mi impedisse di conoscere, scoprire, imparare qualcosa, sigillandolo come un segreto.
Tutto può funzionare meglio o diventare più utile e versatile ...è Life Hacking!

Parapendio

Parapendio Volare è un po' come avere la possibilità di osservare le cose da un'altra prospettiva, senza i vincoli di una forza che ti costringe a muoverti come un pedone degli scacchi per le strade di una città. Il mio sogno sta nell'armadio, pronto a farmi evadere quando ne sento il bisogno e l'aria lo permette.