<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>mooontes.com &#187; montes</title>
	<atom:link href="http://mooontes.com/author/montes/feed/" rel="self" type="application/rss+xml" />
	<link>http://mooontes.com</link>
	<description></description>
	<lastBuildDate>Sun, 12 Feb 2012 09:55:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Los hilos más activos en SMF 2</title>
		<link>http://mooontes.com/2012/02/11/los-hilos-mas-activos-en-smf-2/</link>
		<comments>http://mooontes.com/2012/02/11/los-hilos-mas-activos-en-smf-2/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 21:02:54 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[simple machines forum]]></category>
		<category><![CDATA[smf]]></category>
		<category><![CDATA[smf2]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=501</guid>
		<description><![CDATA[Como me han preguntado cómo hacemos para mostrar los hilos más activos en furgovw, aprovecho y pongo el código aquí por si a alguien más le interesase, simplemente es poner este código en un bloque PHP de TinyPortal o el CMS que usemos con SMF2 (Simple Machines Forum) y obtendremos algo del estilo de la [...]]]></description>
			<content:encoded><![CDATA[<p>Como me han preguntado cómo hacemos para mostrar los hilos más activos en <a href="http://www.furgovw.org">furgovw</a>, aprovecho y pongo el código aquí por si a alguien más le interesase, simplemente es poner este código en un bloque PHP de TinyPortal o el CMS que usemos con SMF2 (<a href="http://www.simplemachines.org">Simple Machines Forum</a>) y obtendremos algo del estilo de la captura:</p>
<p><img src="http://mooontes.com/wp-content/uploads/2012/02/Captura-de-pantalla-2012-02-11-a-las-21.59.50.png" alt="" title="Captura de pantalla 2012-02-11 a la(s) 21.59.50" width="615" height="255" class="alignnone size-full wp-image-507" /></p>
<p><span id="more-501"></span></p>
<pre class="brush: php; title: ; notranslate">
/*
(C) Javier Montes &lt;kalimocho@gmail.com&gt; 

Twitter: @mooontes
Web: http://mooontes.com

Written for: http://www.furgovw.org

This code is licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.html

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

//Set here forums you don't want to have topics shown on hottest topics
$notShowThisForumIDs = array(50, 46, 71, 29, 43, 136, 57, 58, 56, 49, 120, 133, 128, 122, 65, 85);

global $smcFunc;

$sql = '
	SELECT
		value
	FROM {db_prefix}settings
	WHERE variable = &quot;furgovw_hottest_topics&quot;';

$result = $smcFunc['db_query']('', $sql);

if ($row = $smcFunc['db_fetch_assoc']($result)) {

	$hottestTopics = unserialize($row['value']);

	if (($hottestTopics[0]['time'] + (60 * 15)) &lt; time()) {
		$hottestTopics = getHottestTopics($smcFunc, $notShowThisForumIDs);
	}

} else {

	$hottestTopics = getHottestTopics($smcFunc, $notShowThisForumIDs);

}

showHottestTopicsTable($smcFunc, $hottestTopics);

function getHottestTopics($smcFunc, $notShowThisForumIDs)
{
	$hottestTopics = array();

	$sql = '
		SELECT
			COUNT(*) AS total,
			m.id_topic AS id_topic,
			t.id_first_msg AS id_first_msg
		FROM {db_prefix}messages AS m
		LEFT JOIN {db_prefix}topics AS t
		ON m.id_topic = t.id_topic
		WHERE
		t.id_board NOT IN (' . implode(',', $notShowThisForumIDs) . ')
		AND (FROM_UNIXTIME(m.poster_time) &gt; DATE_SUB(DATE(NOW()), INTERVAL 24 HOUR))
		GROUP by m.id_topic
		ORDER BY total DESC
		LIMIT 10
		';

	$result = $smcFunc['db_query']('', $sql);

	while ($row = $smcFunc['db_fetch_assoc']($result)) {
		$hottestTopics[] = $row;
	}

	if (is_array($hottestTopics)) {
		$hottestTopics[0]['time'] = time();

		$smcFunc['db_insert']('replace',
            '{db_prefix}settings',
            array(
                'variable' =&gt; 'string', 'value' =&gt; 'string',
            ),
            array(
                'furgovw_hottest_topics', serialize($hottestTopics),
            ),
            array('variable')
        );

		return $hottestTopics;
	} else
		die('Error getting stats');
}

function showHottestTopicsTable($smcFunc, $hottestTopics)
{
	echo '&lt;table style=&quot;clear:both;margin:0 auto;&quot;&gt;';

	foreach ($hottestTopics as $hottestTopic) {

		$sql = '
			SELECT
				m.subject,
				m.poster_name,
				m.id_member,
				t.id_last_msg
			FROM {db_prefix}messages AS m
			LEFT JOIN {db_prefix}topics AS t
			ON m.id_topic = t.id_topic
			WHERE m.id_topic = ' . $hottestTopic['id_topic'];

		$result = $smcFunc['db_query']('', $sql);
		$row = $smcFunc['db_fetch_assoc']($result);

   		echo '
   			&lt;tr&gt;
   				&lt;td align=&quot;right&quot;&gt;
   					&lt;h2&gt; ['.$hottestTopic['total'].' resp. hoy] &lt;/h2&gt;
   				&lt;/td&gt;
   				&lt;td&gt;
   					&lt;h2&gt;
    					&lt;a href=&quot;/index.php?topic='.
    						$hottestTopic['id_topic'].
    						'.msg'.$row['id_last_msg'].
    						';topicseen#new&quot;&gt;'.$row['subject'].
    						'&lt;/a&gt;
  					&lt;/h2&gt;
  				&lt;/td&gt;
  			&lt;/tr&gt;';
	}

	echo '&lt;/table&gt;';
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2012/02/11/los-hilos-mas-activos-en-smf-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nuestro repositorio Git remoto con Gitosis y Debian</title>
		<link>http://mooontes.com/2011/11/05/repositorio-git-remoto-gitosis-debian/</link>
		<comments>http://mooontes.com/2011/11/05/repositorio-git-remoto-gitosis-debian/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 16:34:09 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[debian]]></category>
		<category><![CDATA[git gitosis linux mac osx debian remote repository]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=446</guid>
		<description><![CDATA[Para poder tener copias remotas de nuestros repositorios Git locales tenemos muchas opciones en internet, la más conocida de lejos github , que funciona muy bien para repositorios públicos y no excesivamente grandes, pero si necesitamos tener repositorios privados o de un tamaño considerable, las opciones tipo Github dejan de ser gratis. Podemos pagar uno [...]]]></description>
			<content:encoded><![CDATA[<p>Para poder tener copias remotas de nuestros repositorios Git locales tenemos muchas opciones en internet, la más conocida de lejos <a href="http://github.com">github</a> , que funciona muy bien para repositorios públicos y no excesivamente grandes, pero si necesitamos tener repositorios privados o de un tamaño considerable, las opciones tipo Github dejan de ser gratis.</p>
<p>Podemos pagar uno de estos servicios, pero si ya tenemos un servidor propio, ¿por qué no aprovecharlo también como repositorio remoto? Aquí es donde entra en juego &#8220;Gitosis&#8221;, que nos ayuda a mantener repositorios Git remotos en nuestro propio servidor, pudiendo configurar el acceso privado a los repositorios incluso por grupos.</p>
<h2>Instalar Gitosis en Debian</h2>
<p>Aunque hay varios tutoriales por internet e incluso un paquete en debian para instalar Gitosis, todos los métodos que he visto dan algún problema más o menos grave. Los siguientes pasos son producto de mezclar varios pasos de los descritos en estos tutoriales y de añadir alguno propio para lograr hacer funcionar correctamente Gitosis en un servidor debian.</p>
<ol>
<span id="more-446"></span></p>
<li>
<h3>Instalar python-setuptools y descargar Gitosis</h3>
</li>
<p>En el servidor:</p>
<pre class="brush: bash; title: ; notranslate">aptitude install python-setuptools</pre>
<p>y descargar Gitosis (clonar con Git)</p>
<pre class="brush: bash; title: ; notranslate">cd /data/temp
git clone git://eagain.net/gitosis</pre>
<p>(Gitosis también está disponible en github: <a href="https://github.com/res0nat0r/gitosis">https://github.com/res0nat0r/gitosis</a> )</p>
<li>
<h3>Instalar Gitosis</h3>
</li>
<p>Ojo con el parámetro &#8220;<em>&#8211;home /data/git</em>&#8220;, aquí deberéis indicar el home del usuario git, que es donde se almacenarán los repositorios</p>
<pre class="brush: bash; title: ; notranslate">python setup.py install
adduser --system --shell /bin/sh --gecos 'git version control' --group --disabled-password --home /data/git git</pre>
<li>
<h3>Generar una llave pública en nuestro ordenador local</h3>
</li>
<p>Tras instalar Gitosis en el servidor, ahora necesitaremos generar una llave pública en nuestro ordenador de desarrollo (desde donde vayamos a hacer los push)</p>
<p>En Linux o Mac:</p>
<pre class="brush: bash; title: ; notranslate">ssh-keygen -t rsa</pre>
<p>Lo que generará las llaves privada/pública en nuestro directorio de usuario, la que nos interesa, la pública, en: &#8220;<em>/home/usuario/.ssh/id_rsa.pub</em>&#8221; en Linux o &#8220;<em>/Users/usuario/.ssh/id_rsa.pub</em>&#8221; en OS X.</p>
<li>
<h3>Instalar nuestra llave pública en el servidor</h3>
</li>
<p>De vuelta al servidor y habiendo subido nuestra llave pública (por ftp por ejemplo)</p>
<p>Lo primero instalamos sudo, que en debian no viene instalado por defecto:</p>
<pre class="brush: bash; title: ; notranslate">aptitude install sudo</pre>
<p>Inicializamos Gitosis con nuestro usuario como admin (pasándole la ruta de nuestra llave pública, en este ejemplo estaría en &#8220;<em>/tmp/id_rsa.pub</em>&#8221;</p>
<pre class="brush: bash; title: ; notranslate">sudo -H -u git gitosis-init &lt; /tmp/id_rsa.pub</pre>
<p>Y para finalizar marcamos &#8220;post-update&#8221; como ejecutable para todos los usuarios:</p>
<pre class="brush: bash; title: ; notranslate">sudo chmod 755 /data/git/repositories/gitosis-admin.git/hooks/post-update</pre>
<li>
<h3>Bonus track: Redmine o cualquier gestor web de Git en el servidor</h3>
</li>
<p>Si vamos a usar Redmine o cualquier tipo de gestor o visualizador web de Git, necesitaremos incluir al usuario de apache &#8220;www-data&#8221; en el grupo de &#8220;git&#8221; para que sea capaz de leer los repositorios que generemos:</p>
<pre class="brush: bash; title: ; notranslate">usermod -a -G git www-data</pre>
<li>
<h3>Ya estamos listos, nuestro primer push</h3>
</li>
<p>Ya sólo nos queda clonar el repositorio de la configuración de Gitosis para poder ir configurando los permisos para los repositorios que añadamos, desde nuestro ordenador de desarrollo (Linux o Mac) sustituyendo &#8220;miservidor.com&#8221; por el dominio o ip de vuestro servidor:</p>
<pre class="brush: bash; title: ; notranslate">git clone git@miservidor.com:gitosis-admin.git</pre>
<p>y ahora podemos entrar a ver la configuración de gitosis y añadir algún repositorio, por ejemplo si queremos añadir el repositorio &#8220;montes&#8221; a nuestro servidor:</p>
<pre class="brush: bash; title: ; notranslate">cd gitosis-admin
vim gitosis.conf</pre>
<p>y en &#8220;<em>gitosis.conf</em>&#8221; añadiremos &#8220;montes&#8221; como writable:</p>
<pre class="brush: bash; title: ; notranslate">[gitosis]
  3 [group gitosis-admin]
  4 writable = gitosis-admin montes
  5 members = yo@gmail.com
</pre>
<p>grabamos y haremos nuestro primer push para actualizar la configuración de gitosis en el servidor remoto:</p>
<pre class="brush: bash; title: ; notranslate">git commit -a -m &quot;Dar permisos de escritura en el repositorio montes para el grupo gitosis-admin&quot;
git push</pre>
<p>Con esto hemos dado permisos de escritura en el repositorio &#8220;montes&#8221; (que aún no existe) a nuestro usuario (yo@gmai.com al que pertenece la llave pública que configuramos en el paso anterior).</p>
<p>Sólo nos queda crear el repositorio en nuestro ordenador de desarrollo (Linux o Mac):</p>
<pre class="brush: bash; title: ; notranslate">cd ..
mkdir montes
cd montes
git init</pre>
<p>añadir nuestro servidor remoto como repositorio remoto:</p>
<pre class="brush: bash; title: ; notranslate">git remote add origin git@miservidor.com:montes</pre>
<p>y hacer nuestro primer push!</p>
<pre class="brush: bash; title: ; notranslate">git add .
git commit -a -m &quot;Primer commit!&quot;
git push miservidor master</pre>
<p>Listo! ya hemos enviado nuestro primer push a nuestro propio servidor Git remoto!</p>
</ol>
<p>&nbsp;</p>
<p>Fuentes:<br />
<a href="http://ymbra.com/es/blog/ramon/gestion-de-repositorios-git-con-gitosis">http://ymbra.com/es/blog/ramon/gestion-de-repositorios-git-con-gitosis</a><br />
<a href="https://github.com/res0nat0r/gitosis">https://github.com/res0nat0r/gitosis</a></p>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2011/11/05/repositorio-git-remoto-gitosis-debian/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Conferencia PHP Profesional &#8211; Carlos Buenosvinos</title>
		<link>http://mooontes.com/2011/05/23/conferencia-php-profesional-carlos-buenosvinos/</link>
		<comments>http://mooontes.com/2011/05/23/conferencia-php-profesional-carlos-buenosvinos/#comments</comments>
		<pubDate>Mon, 23 May 2011 22:42:14 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=432</guid>
		<description><![CDATA[Si te interesa PHP, te recomiendo que busques como sea un par de horas libres y te veas la conferencia de Carlos Buenosvinos sobre las herramientas necesarias para programar en PHP profesionalmente, vale su peso en oro (y gracias de nuevo a decharlas.com!) Vídeo Vimeo Conferencia PHP Profesional y diapositivas]]></description>
			<content:encoded><![CDATA[<p>Si te interesa PHP, te recomiendo que busques como sea un par de horas libres y te veas la conferencia de Carlos Buenosvinos sobre las herramientas necesarias para programar en PHP profesionalmente, vale su peso en oro (y gracias de nuevo a <a href='http://www.decharlas.com'>decharlas.com</a>!)</p>
<p><a target='_blank' href='http://decharlas.uji.es/php-profesional.php'>Vídeo Vimeo Conferencia PHP Profesional y diapositivas</a></p>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2011/05/23/conferencia-php-profesional-carlos-buenosvinos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony2, tutorial para comenzar ultra-rápido</title>
		<link>http://mooontes.com/2011/03/27/symfony2-tutorial-para-comenzar-ultra-rapido/</link>
		<comments>http://mooontes.com/2011/03/27/symfony2-tutorial-para-comenzar-ultra-rapido/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 01:32:44 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=380</guid>
		<description><![CDATA[This post in english at http://en.mooontes.com/2011/03/27/symfony2-ultra-fast-start-tutorial/ NOTA: Este tutorial se ha realizado en Ubuntu 11.04 &#8211; Natty Narwhal, no se ha comprobado su funcionamiento en otros sistemas operativos. Esto es sólo una especie de chuleta de ejemplo por si se te olvida alguna cosa tras leer la documentación de symfony2, pero evidentemente es imprescindible leérsela [...]]]></description>
			<content:encoded><![CDATA[<p><em>This post in english at <a href="http://en.mooontes.com/2011/03/27/symfony2-ultra-fast-start-tutorial/">http://en.mooontes.com/2011/03/27/symfony2-ultra-fast-start-tutorial/</a></p>
<p>NOTA: Este tutorial se ha realizado en Ubuntu 11.04 &#8211; Natty Narwhal, no se ha comprobado su funcionamiento en otros sistemas operativos. Esto es sólo una especie de chuleta de ejemplo por si se te olvida alguna cosa tras leer la documentación de symfony2, pero evidentemente es imprescindible leérsela antes para saber de qué va todo esto <img src='http://mooontes.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  <a href="http://symfony.com/doc/2.0/book/index.html">http://symfony.com/doc/2.0/book/index.html</a></em></p>
<p>El código fuente utilizado está disponible en: <a href='https://github.com/montes/Adictos-Symfony2-Bundle' target='_blank'>https://github.com/montes/Adictos-Symfony2-Bundle</a></p>
<p>ACTUALIZACIÓN 23/5/2011: Actualizado para symfony2 beta2</p>
<p>&nbsp;</p>
<h2>1. Descarga</h2>
<p>Descarga Symfony2 Standard Edition (en el momento de escribir esto la BETA2): <a href='http://symfony.com/download' target='_blank'>http://symfony.com/download</a></p>
<p>Descomprime</p>
<pre class="brush: bash; title: ; notranslate">
tar -zxvf Symfony_Standard_Vendors_2.0.0BETA2.tgz
</pre>
<p>Y cambia los permisos de app/cache y app/logs para que sean escribibles por php, por ejemplo:</p>
<pre class="brush: bash; title: ; notranslate">
chmod 777 app/cache app/logs
</pre>
<p>Configura en tu servidor el directorio &#8220;<em>web/</em>&#8221; como raíz y ya deberías poder cargar la página de bienvenida de symfony2 desde <a target="_blank"  href="http://127.0.0.1/app_dev.php/">http://127.0.0.1/app_dev.php/</a></p>
<p><span id="more-380"></span></p>
<p>&nbsp;</p>
<h2>2. Configura la base de datos</h2>
<p>Configura <em>app/config/parameters.ini</em> con las opciones de tu base de datos (también lo puedes hacer desde <a href="http://127.0.0.1/app_dev.php/_configurator/">http://127.0.0.1/app_dev.php/_configurator/</a> ), para mysql sería algo así:</p>
<pre class="brush: plain; title: ; notranslate">
[parameters]
    database_driver=pdo_mysql
    database_host=localhost
    database_name=symfony2
    database_user=symfony2
    database_password=password
    mailer_transport=smtp
    mailer_host=localhost
    mailer_user=
    mailer_password=
    locale=en
    csrf_secret=op234j234j2424jojpfwesdcsdc
</pre>
<p>&nbsp;</p>
<h2>3. Crear nuestro primer bundle</h2>
<p>Ahora ya podemos crear un bundle:</p>
<pre class="brush: bash; title: ; notranslate">
php app/console init:bundle &quot;Montes\AdictosBundle&quot; src
</pre>
<p>Ahora toca añadir a <em>app/autoload.php</em> :</p>
<pre class="brush: php; title: ; notranslate">
$loader-&gt;registerNamespaces(array(
    'Montes'                         =&gt; __DIR__.'/../src',
    // ...
));
</pre>
<p>y añadir a <em>app/AppKernel.php</em> :</p>
<pre class="brush: php; title: ; notranslate">
    $bundles = array(
        // ...
        new Montes\AdictosBundle\MontesAdictosBundle(),
    );
</pre>
<p>&nbsp;</p>
<h2>4. Ruta</h2>
<p>Para que symfony2 sepa dónde enviar las peticiones, añadimos a <em>app/config/routing_dev.yml</em> :</p>
<pre class="brush: bash; title: ; notranslate">
homepage:
    pattern:  /adictos
    defaults: { _controller: MontesAdictosBundle:Default:index }
</pre>
<p>En este punto ya podemos cargar nuestro recién creado bundle yendo a: <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos">http://127.0.0.1/app_dev.php/adictos</a></p>
<p>&nbsp;</p>
<h2>5. Controller</h2>
<p>El controller por defecto (<em>Montes/AdictosBundle/Controller/DefaultController.php</em>) ya nos lo ha creado Symfony2, ahora vamos a crear el controller StoreController.php</p>
<pre class="brush: php; title: ; notranslate">
//Montes/AdictosBundle/Controller/StoreController.php
&lt;?php

namespace Montes\AdictosBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class StoreController extends Controller
{
    /**
     * @Template()
     */
    public function indexAction($store)
    {
        return array('store' =&gt; $store);
    }
}
</pre>
<p>y añadimos a <em>app/config/routing_dev.yml</em></p>
<pre class="brush: bash; title: ; notranslate">
store:
    pattern: /adictos/{store}
    defaults: { _controller: MontesAdictosBundle:Store:index }
</pre>
<p>y una nueva plantilla de twig a <em>Montes/AdictosBundle/Resources/Views/Store/index.html.twig</em></p>
<pre class="brush: xml; title: ; notranslate">
So you want store &quot;{{ store }}&quot;?
</pre>
<p>Y ahora cargando <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos/mi-tienda">http://127.0.0.1/app_dev.php/adictos/mi-tienda</a> obtendremos:</p>
<p><em>So you want store &#8220;mi-tienda&#8221;?</em></p>
<p>&nbsp;</p>
<h2>6. Modelo</h2>
<p><em>NOTA: Para entrar en detalle sobre Doctrine2 recomiendo <a target='_blank' href='http://parasitovirtual.wordpress.com/category/cursos-y-articulos/desarrollo-de-webs/php/doctrine/'>el blog de Francisco Belmonte</a>, una maravilla.</em></p>
<p><del datetime="2011-05-23T21:32:54+00:00">Primero añadimos a <em>app/config/config.yml</em> &#8220;<em>MontesAdictosBundle: ~</em>&#8220;</del> A partir de la BETA1 por defecto el mapping es automático.</p>
<p>Comenzamos con Doctrine, vamos a definir nuestro modelo para una tienda. Antes de nada, como aún no hemos creado ningún modelo tendremos que crear el directorio <em>Montes/AdictosBundle/Entity</em> que es donde los guardaremos todos.</p>
<p>Y ya podemos empezar, modelo para Store:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Montes/AdictosBundle/Entity/Store.php

namespace Montes\AdictosBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Store
{
    /**
     * @ORM\Id
     * @ORM\Column(type=&quot;integer&quot;)
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */
     protected $id;

    /**
     * @ORM\ManyToMany(targetEntity=&quot;Category&quot;)
     * @ORM\JoinTable(name=&quot;stores_categories&quot;,
     *      joinColumns={@ORM\JoinColumn(name=&quot;store_id&quot;, referencedColumnName=&quot;id&quot;)},
     *      inverseJoinColumns={@ORM\JoinColumn(name=&quot;category_id&quot;, referencedColumnName=&quot;id&quot;)})
     */
    protected $categories;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $url;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $name;

    /**
     * @ORM\Column(type=&quot;integer&quot;)
     */
    protected $clicks = 0;

    /**
     * @ORM\Column(type=&quot;boolean&quot;)
     */
    protected $validated = false;

    /**
     * @ORM\Column(type=&quot;integer&quot;)
     */
    protected $pcomments = 0;

    /**
     * @ORM\Column(type=&quot;integer&quot;)
     */
    protected $ncomments = 0;

    /**
     * @ORM\Column(type=&quot;boolean&quot;)
     */
    protected $active = false;

    /**
     * @ORM\Column(type=&quot;datetime&quot;, name=&quot;updated_at&quot;)
     */
    protected $updatedAt;

    /**
     * @ORM\Column(type=&quot;datetime&quot;, name=&quot;created_at&quot;)
     */
    protected $createdAt;

    public function __construct()
    {
        $this-&gt;categories = new \Doctrine\Common\Collections\ArrayCollection();
        $this-&gt;createdAt = new \DateTime();
        $this-&gt;updatedAt = new \DateTime();
    }
}
</pre>
<p>Modelo para Category:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Montes/AdictosBundle/Entity/Category.php

namespace Montes\AdictosBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Category
{
    /**
     * @ORM\Id
     * @ORM\Column(type=&quot;integer&quot;)
     * @ORM\GeneratedValue(strategy=&quot;AUTO&quot;)
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity=&quot;Category&quot;, mappedBy=&quot;parent&quot;)
     */
    protected $children;

    /**
     * @ORM\ManyToOne(targetEntity=&quot;Category&quot;, inversedBy=&quot;children&quot;)
     * @ORM\JoinColumn(name=&quot;parent_id&quot;, referencedColumnName=&quot;id&quot;)
     * @ORM\Column(nullable=&quot;true&quot;)
     */
    protected $parent;

    /**
     * @ORM\ManyToMany(targetEntity=&quot;Store&quot;, mappedBy=&quot;categories&quot;)
     */
    protected $stores;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;)
     */
    protected $name;

    /**
     * @ORM\Column(type=&quot;string&quot;, length=&quot;255&quot;, name=&quot;url_string&quot;, unique=&quot;true&quot;)
     */
    protected $urlString;

    public function __construct()
    {
        $this-&gt;stores = new \Doctrine\Commmon\Collections\ArrayCollection();
    }
}
</pre>
<p>Y ahora vamos a consola y para generar las tablas en la base de datos ejecutamos:</p>
<pre class="brush: bash; title: ; notranslate">
php app/console doctrine:schema:create
</pre>
<p>y para completar nuestro modelo con sus getters/setters:</p>
<pre class="brush: bash; title: ; notranslate">
php app/console doctrine:generate:entities MontesAdictosBundle
</pre>
<p>&nbsp;</p>
<h2>7. Probando el modelo</h2>
<p>Vamos a cambiar la acción que muestra la tienda a su propia acción (storeAction) para hacer hueco al índice del store controller en indexAction, que ahora mostrará el total de tiendas que tenemos almacenadas en la BD.</p>
<pre class="brush: bash; title: ; notranslate">
# app/config/routing_dev.yml
store:
    pattern: /adictos/{store}
    defaults: { _controller: MontesAdictosBundle:Store:store }

store_index:
    pattern: /adictos/
    defaults: { _controller: MontesAdictosBundle:Store:index }
</pre>
<pre class="brush: php; title: ; notranslate">
&lt;?php
// Montes/AdictosBundle/Controller/StoreController.php

namespace Montes\AdictosBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class StoreController extends Controller
{

    /**
     * @Template()
     */
    public function indexAction()
    {
        $em = $this-&gt;get('doctrine.orm.entity_manager');
        $stores = $em-&gt;createQuery('SELECT count(s.id) AS total FROM Montes\AdictosBundle\Entity\Store s')-&gt;getSingleScalarResult();
        return array('stores' =&gt; $stores);
    }

    /**
     * @Template()
     */
    public function storeAction($store)
    {
        return array('store' =&gt; $store);
    }
}
</pre>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Montes/AdictosBundle/Resources/views/Store/index.html.twig --&gt;
We have a total of {{ stores }} stores.
</pre>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Montes/AdictosBundle/Resources/views/Store/store.html.twig --&gt;
So you want store &quot;{{ store }}&quot;?
</pre>
<p>Ahora al cargar <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos/">http://127.0.0.1/app_dev.php/adictos/</a> nos saldrá <em>We have a total of 0 stores</em> y al cargar <a target="_blank" href="http://127.0.0.1/app_dev.php/adictos/mi-tienda">http://127.0.0.1/app_dev.php/adictos/mi-tienda</a> nos saldrá <em>So you want store &#8220;mi-tienda&#8221;?</em><br />
<a href="http://github.com/montes/Adictos-Symfony2-Bundle"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://d3nwyuy0nl342s.cloudfront.net/img/e6bef7a091f5f3138b8cd40bc3e114258dd68ddf/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2011/03/27/symfony2-tutorial-para-comenzar-ultra-rapido/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>USB TDT (DVB-T) HD para Ubuntu, OSX y Windows</title>
		<link>http://mooontes.com/2010/11/29/usb-tdt-dvb-t-hd-para-ubuntu-osx-y-windows/</link>
		<comments>http://mooontes.com/2010/11/29/usb-tdt-dvb-t-hd-para-ubuntu-osx-y-windows/#comments</comments>
		<pubDate>Mon, 29 Nov 2010 18:32:53 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[dvb-t]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[tdt]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[usb]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=365</guid>
		<description><![CDATA[Llevaba tiempo buscando una tarjeta o USB TDT HD que fuese compatible con los tres sistemas operativos que utilizo y al final lo he encontrado, es el WinTV NOVA-T-HD: Funciona tanto en Ubuntu 10.10 como OSX 10.6.5 sólo conectándolo, no hay que configurar nada. En el caso de Windows aún no he probado, pero trae [...]]]></description>
			<content:encoded><![CDATA[<p>Llevaba tiempo buscando una tarjeta o USB TDT HD que fuese compatible con los tres sistemas operativos que utilizo y al final lo he encontrado, es el WinTV NOVA-T-HD:<br />
<a href="http://www.hauppauge.es/site/products/data_novathdstick.html"><img src="http://mooontes.com/wp-content/uploads/2010/11/novathdstick_top-300x96.jpg" alt="wintv nova-tdt-hd" title="wintv nova-tdt-hd" width="450" class="alignnone size-medium wp-image-367" /></a></p>
<p>Funciona tanto en Ubuntu 10.10 como OSX 10.6.5 sólo conectándolo, no hay que configurar nada. En el caso de Windows aún no he probado, pero trae un CD con los drivers.</p>
<p>En Ubuntu 10.10 yo lo uso con Me TV (<em>sudo aptitude install me-tv</em>)</p>
<p><img src="http://mooontes.com/wp-content/uploads/2010/11/me-tv.png" alt="" title="me-tv" width="567" height="419" class="alignnone size-full wp-image-373" /></p>
<p>En OSX sólo hay que instalar <a href='http://www.elgato.com/elgato/int/mainmenu/products/software/EyeTV-3/product1.en.html'>Eye TV</a> y funcionará perfectamente, ya que este USB es el que llevan dentro los famosos USB de &#8220;elgato&#8221; para Mac.</p>
<p>Yo la compré en un MediaMarkt, creo recordar que por algo menos de 50€ pero se encuentra fácil por internet, por ejemplo en <a href='http://www.pixmania.com/es/es/4031007/art/hauppauge/memoria-usb-wintv-nova-t.html'>pixmania</a>.</p>
<p>- Review en castellano: <a href='http://www.mashardware.com/index.php?/Articulos/Review-de-la-sintonizadora-Hauppauge-WinTV-NOVA-T-HD.html'>mashardware.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2010/11/29/usb-tdt-dvb-t-hd-para-ubuntu-osx-y-windows/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>VPN SSL de Juniper Networks en Debian sin entorno gráfico</title>
		<link>http://mooontes.com/2010/09/06/vpn-ssl-de-juniper-networks-en-debian-sin-entorno-grafico/</link>
		<comments>http://mooontes.com/2010/09/06/vpn-ssl-de-juniper-networks-en-debian-sin-entorno-grafico/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 13:36:40 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[debian]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[juniper]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=347</guid>
		<description><![CDATA[Esta semana he tenido que cambiar el acceso a VPN desde nuestro servidor Debian, que hasta ahora era transparente (mediante Cisco) a una VPN SSL de Juniper Networks, ha llevado bastante tiempo y pruebas sobre todo debido a que no hay soporte de Debian por parte de Juniper, sólo para Red Hat y al final [...]]]></description>
			<content:encoded><![CDATA[<p>Esta semana he tenido que cambiar el acceso a VPN desde nuestro servidor Debian, que hasta ahora era transparente (mediante Cisco) a una VPN SSL de Juniper Networks, ha llevado bastante tiempo y pruebas sobre todo debido a que no hay soporte de Debian por parte de Juniper, sólo para Red Hat y al final se trata de prueba/error.</p>
<p>Nuestro servidor es un Debian Lenny sin entorno gráfico, ese fue uno de los primeros problemas ya que las soluciones que existen por internet y el propio cliente de Juniper para Linux, están siempre pensados para clientes con entorno gráfico.</p>
<p><span id="more-347"></span></p>
<p>&nbsp;</p>
<h2>1. Pasos previos</h2>
<p>Antes de comenzar con la configuración en el servidor, a través de un pc con Linux con entorno gráfico (y java instalado) obtendremos los ficheros necesarios.<br />
Sólo tenemos que conectar a la web de la VPN (yo utilicé Ubuntu+Firefox), con esto nos descargará a <em>/home/user/.juniper_networks/</em> todos los archivos necesarios para la conexión, no importa si establece la conexión a la VPN o no.</p>
<p>Desde <em>/home/usuario/</em> realizamos:</p>
<pre class="brush: bash; title: ; notranslate">tar -czvf juniper.tgz .juniper_networks/*</pre>
<p>Y ya hemos terminado con el pc y podemos pasar al servidor.</p>
<p>&nbsp;</p>
<h2>2. Preparación de archivos para la conexión</h2>
<p>Descomprimimos <em>juniper.tgz</em> en el servidor en <em>/home/usuario/.juniper_networks/</em> y descomprimimos el archivo <em>/home/usuario/.juniper_networks/ncLinuxApp.jar</em></p>
<pre class="brush: bash; title: ; notranslate">jar -xf ncLinuxApp.jar</pre>
<p>Con esto obtenemos varios archivos importantes:</p>
<ol>
<li><strong>getx509certificate.sh</strong> Necesario para obtener el certificado del servidor</li>
<li><strong>ncsvc</strong> El servicio que crea la conexión VPN</li>
</ol>
<p>&nbsp;</p>
<h2>3. Obtener el certificado</h2>
<p>Desde el mismo directorio:</p>
<pre class="brush: bash; title: ; notranslate">chmod +x getx509certificate.sh
./getx509certificate.sh vpn.empresa.com vpn.crt</pre>
<p>Con esto ya tenemos uno de los archivos necesarios para establecer la VPN, el <em>vpn.crt</em></p>
<p>&nbsp;</p>
<h2>4. Instalar el servicio</h2>
<p>Ejecutar como root:</p>
<pre class="brush: bash; title: ; notranslate">install -m 6711 -o root /home/usuario/.juniper_networks/ncsvc /home/usuario/.juniper_networks/network_connect/ncsvc</pre>
<p>&nbsp;</p>
<h2>5. Establecer la conexión</h2>
<p>Ya sólo queda establecer la conexión, para esto necesitaremos consultar al administrador el parámetro &#8220;realm&#8221;, por internet comentan que suele estar entre el HTML de la página de acceso, pero en mi caso no era así.</p>
<p>Conociendo este parámetro sólo nos falta realizar la conexión propiamente dicha:</p>
<pre class="brush: bash; title: ; notranslate">./ncsvc -h vpn.empresa.com -u user01 -p password -r realm -f vpn.crt</pre>
<p>Si en nuestro caso la VPN utiliza URIs personalizadas es necesario añadir también el parámetro <em>-U</em></p>
<pre class="brush: bash; title: ; notranslate">./ncsvc -h vpn.empresa.com -u user01 -p password -r realm -f vpn.crt -U https://vpn.empresa.com/aux/usuario01/</pre>
<p>Entonces el terminal quedará con el mensaje:</p>
<pre class="brush: bash; title: ; notranslate">Connecting to vpn.empresa.com : 443</pre>
<p>Y la VPN conectada hasta que caduque la sesión o cancelemos. La conexión creará un nuevo interface de red <em>tun0</em> (lo podréis ver con <em>ifconfig</em>) y añadirá también unas rutas (ver con <em>route</em>) y unas líneas a <em>/etc/resolv.conf</em></p>
<p>Si de esta forma no funciona y los parámetros son correctos, antes de realizar más pruebas debemos contactar con el administrador, puesto que en algunos casos, como por ejemplo que esté configurado para múltiples sesiones, no funcionará.</p>
<p>&nbsp;</p>
<p><strong>Más documentación:</strong></p>
<ul>
<li><a href="http://www.emiliojuarez.es/Utilidades/juniperendebianlenny.html">emiliojuarez.es</a></li>
<li><a href="http://www.entropy.ch/blog/Mac+OS+X/?permalink=Juniper-Network-Connect-SSL-VPN-and-Virtualization.html">entropy.ch</a></li>
<li><a href="http://mad-scientist.us/juniper.html">mad-scientist.us</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2010/09/06/vpn-ssl-de-juniper-networks-en-debian-sin-entorno-grafico/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free Javascript Calendar / Datepicker adaptado a España</title>
		<link>http://mooontes.com/2010/03/07/javascript-calendar-datepicker/</link>
		<comments>http://mooontes.com/2010/03/07/javascript-calendar-datepicker/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 17:10:42 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[calendar]]></category>
		<category><![CDATA[datepicker]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=339</guid>
		<description><![CDATA[Necesitaba un calendario en javascript tipo pop-up para el proyecto que tengo entre manos y me he encontrado con Javascript Calendar que tiene muy buena pinta, pero que sólo tiene versión anglosajona así que lo he modificado para adaptarlo a mis necesidades: Días de la semana y meses en castellano Primer día de la semana [...]]]></description>
			<content:encoded><![CDATA[<p>Necesitaba un calendario en javascript tipo pop-up para el proyecto que tengo entre manos y me he encontrado con <a href="http://javascriptcalendar.org">Javascript Calendar</a> que tiene muy buena pinta, pero que sólo tiene versión anglosajona así que lo he modificado para adaptarlo a mis necesidades:</p>
<ol>
<li>Días de la semana y meses en castellano</li>
<li>Primer día de la semana Lunes</li>
<li>Formato de fecha dd-mm-yyyy</li>
<li>Posibilidad de darle un id al node (span) que crea</li>
<li>Posiblidad de pasarle el path de las imágenes por si queremos que sea distinto al original</li>
</ol>
<p>Para usar la versión modificada, debéis descargar primero la original de su página y luego sobreescribir &#8220;<em>jsDatePick.full.1.0.js</em>&#8221; con el modificado &#8220;<em>jsDatePick.full.1.0.spain.js</em>&#8221; <a href="http://mooontes.com/codigo/jsDatePick.full.1.0.spain.js">Javascript Calendar Spanish Version</a></p>
<p>Este sería un ejemplo de uso con las dos nuevas opciones (<em>id</em> y <em>path</em>):</p>
<pre lang='javascript'>		new JsDatePick({
			useMode:2,
			id:"idCalendarNode",
			path:"/mis-imagenes/",
			target:"beginDate"
		});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2010/03/07/javascript-calendar-datepicker/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Maps API V3 get_center ahora es getCenter</title>
		<link>http://mooontes.com/2010/02/04/google-maps-api-v3-get_center-ahora-es-getcenter/</link>
		<comments>http://mooontes.com/2010/02/04/google-maps-api-v3-get_center-ahora-es-getcenter/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 17:43:36 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=333</guid>
		<description><![CDATA[He actualizado los ejemplos de Google Maps API V3 que habían dejado de funcionar debido a un cambio en el nombre de la función get_center que ha pasado a ser getCenter. También he eliminado la librería scrollwheelzoom que ya no es necesaria.]]></description>
			<content:encoded><![CDATA[<p>He actualizado los ejemplos de Google Maps API V3 que habían dejado de funcionar debido a un cambio en el nombre de la función <em>get_center</em> que ha pasado a ser <em>getCenter</em>.</p>
<p>También he eliminado la librería scrollwheelzoom que ya no es necesaria.</p>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2010/02/04/google-maps-api-v3-get_center-ahora-es-getcenter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Maps API V3 (javascript)</title>
		<link>http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/</link>
		<comments>http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 19:14:21 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[api v3]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[google maps api v3]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[reverse geocoding]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=319</guid>
		<description><![CDATA[Versión en español de este post Although the Google Maps API V3 is still quite green and much remains to be polished, it is quite usable and if you only need the basic features of Google Maps, then you can use it for your project, the new speed and usability at portable devices is a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/">Versión en español de este post</a></p>
<p>Although the Google Maps API V3 is still quite green and much remains to be polished, it is quite usable and if you only need the basic features of Google Maps, then you can use it for your project, the new speed and usability at portable devices is a plus.</p>
<p>This code is an example of the use of various techniques with javascript:</p>
<ul>
<li>Map centering at user&#8217;s location</li>
<li>Event capturing</li>
<li>Reverse Geocoding</li>
<li>Use of <a href="http://google-maps-utility-library-v3.googlecode.com/svn/tags/scrollwheelzoom/1.0/docs/examples.html">Nianwei&#8217;s library</a> scrollwheelzoom (still not officially supported in V3)</li>
</ul>
<p><span id="more-319"></span></p>
<h3 style="clear:both;padding:20px;width:200px;text-align:center;margin:0px auto;"><a href="http://mooontes.com/codigo/google_maps_api_v3_en.html" target="_blank">Test the code</a></h3>
<p>And here is the code (<a href="http://validator.w3.org/check?uri=http://mooontes.com/codigo/google_maps_api_v3_en.html">validated</a> XHTML with Doctype).</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;!--
** Created at 2009 July by Montes http://mooontes.com
** Under licence http://creativecommons.org/licenses/by/3.0/es/deed.es
**
** Google Maps API V3 javascript example
**
** Visitor's location map centering, event capturing,
** reverse geocoding &amp; Nianwei's scrollwheelzoom
**
**
** Creado en Julio de 2009 por Montes http://mooontes.com
** Bajo licencia http://creativecommons.org/licenses/by/3.0/es/deed.es
**
** Ejemplo de programación con Google Maps API V3
**
** Centrado del mapa en la ubicación del visitante, captura de eventos,
** reverse geocoding y uso de la libreria para hacer zoom con la rueda del ratón
--&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;es&quot; lang=&quot;es&quot;&gt;
&lt;head&gt;

	&lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1.0, user-scalable=no&quot; /&gt;
	&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;

	&lt;title&gt;Test Google Maps API V3 -mooontes.com-&lt;/title&gt;

    &lt;style type=&quot;text/css&quot;&gt;
	html
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	body
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	#map_canvas
	{
		width:100%;
		height:100%;
	}
	#info
	{
		position:absolute;
		width:250px;
		height:250px;
		left:20px;
		top:300px;
		background-color:white;
		padding:5px;
		overflow:auto;
	}
    &lt;/style&gt;

	&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.google.com/maps/api/js?sensor=false&quot;&gt;&lt;/script&gt;	

	&lt;script type=&quot;text/javascript&quot;&gt;
	var map;
	var geocoder;

	function initialize() {

		//Geocoder initialization &amp; visitor's location map centering
		geocoder = new google.maps.Geocoder();
		if (google.loader.ClientLocation)
		{
			//Search for visitor's latitude and longitude
			var latt = google.loader.ClientLocation.latitude;
			var longg = google.loader.ClientLocation.longitude;

			//Center the map at visitor's coordinates
			var latlng = new google.maps.LatLng(latt,longg);
		}
		else
		{
			//If we can't get visitor's coordinates, set Madrid as map center
			var latlng = new google.maps.LatLng(&quot;40.41153868&quot;,&quot;-3.70362707&quot;);
		}

		//Create the map
		var myOptions = {
		zoom: 5,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP
		};
		map = new google.maps.Map(document.getElementById(&quot;map_canvas&quot;), myOptions);

		//Add a listener, it will activate when the map become fully loaded
		google.maps.event.addListener(map, 'bounds_changed',function()
			{
				//First div's update to show actual location details
				actualizaUbicacion();
				//Map fully loaded, clear the listener
				google.maps.event.clearListeners(map, 'bounds_changed');
				//And add two new events, one will update the div's info when user ends dragging the map and the other when map's zoom changes
				google.maps.event.addListener(map, 'dragend',function() { actualizaUbicacion() });
				google.maps.event.addListener(map, 'zoom_changed',function() { actualizaUbicacion() });
			}
		);

	}

	function actualizaUbicacion()
	{

		//Map's center coordinates we'll use for reverse geocoding
		var lattlng = map.getCenter();

		if (geocoder)
		{
			geocoder.geocode({'latLng': lattlng}, function(results, status)
			{
				if (status == google.maps.GeocoderStatus.OK)
				{
					if (results[1])
					{
						var reverse_geo = results[1];

						var text = &quot;&lt;a href='http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/'&gt;Back to post at mooontes.com&lt;&quot;+&quot;/a&gt;&lt;br /&gt;&lt;br /&gt;Map center: &quot;
							+ map.getCenter()+ &quot;&lt;br /&gt;&lt;br /&gt;Reverse Geocoding:&lt;br /&gt;&quot;;
						if (reverse_geo.address_components[0]) { text = text + &quot;0: &quot; + reverse_geo.address_components[0].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[1]) { text = text + &quot;1: &quot; + reverse_geo.address_components[1].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[2]) { text = text + &quot;2: &quot; + reverse_geo.address_components[2].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[3]) { text = text + &quot;3: &quot; + reverse_geo.address_components[3].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[4]) { text = text + &quot;4: &quot; + reverse_geo.address_components[4].long_name + &quot;&lt;br /&gt;&quot;; }

						text = text + &quot;5: &quot; + reverse_geo.formatted_address;

						document.getElementById('info').innerHTML = text;
					}
				}
				else
				{
					document.getElementById('info').innerHTML = &quot;No hay información de Reverse Geocoding.&quot;;
				}
			});
		}
	}

	//--&gt;&lt;/script&gt;

&lt;/head&gt;
&lt;body onload=&quot;initialize()&quot;&gt;
	&lt;div id=&quot;map_canvas&quot;&gt;&lt;/div&gt;
	&lt;div id=&quot;info&quot;&gt;&lt;a href=&quot;http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/&quot;&gt;Back to post at mooontes.com&lt;/a&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2009/07/30/google-maps-api-v3-javascript-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Maps API V3 (javascript)</title>
		<link>http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/</link>
		<comments>http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 20:07:52 +0000</pubDate>
		<dc:creator>montes</dc:creator>
				<category><![CDATA[programacion]]></category>
		<category><![CDATA[api v3]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[google maps api v3]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[reverse geocoding]]></category>

		<guid isPermaLink="false">http://mooontes.com/?p=295</guid>
		<description><![CDATA[Aunque el API V3 de Google Maps aún está bastante verde y le falta mucho por pulir, ya es bastante usable y si sólo necesitamos las características básicas de Google Maps nos puede servir para nuestro proyecto. Este código es un ejemplo del uso de varias técnicas con javascript: Centrar el mapa en la ubicación [...]]]></description>
			<content:encoded><![CDATA[<p>Aunque el API V3 de Google Maps aún está bastante verde y le falta mucho por pulir, ya es bastante usable y si sólo necesitamos las características básicas de Google Maps nos puede servir para nuestro proyecto.</p>
<p>Este código es un ejemplo del uso de varias técnicas con javascript:</p>
<ul>
<li>Centrar el mapa en la ubicación del visitante</li>
<li>Captura de eventos</li>
<li>Reverse Geocoding</li>
<li>Uso de la <a href="http://google-maps-utility-library-v3.googlecode.com/svn/tags/scrollwheelzoom/1.0/docs/examples.html">librería de Nianwei</a> para hacer zoom con la rueda del ratón (aún no soportado oficalmente en la V3)</li>
</ul>
<p><span id="more-295"></span></p>
<h3 style="clear:both;padding:20px;width:200px;text-align:center;margin:0px auto;"><a href="http://mooontes.com/codigo/google_maps_api_v3.html" target="_blank">Probar el código</a></h3>
<p>Y aquí dejo el código, XHTML con doctype y <a href="http://validator.w3.org/check?uri=http://mooontes.com/codigo/google_maps_api_v3.html">validable</a>, a diferencia de lo que nos tiene acostumbrados google <img src='http://mooontes.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;!--
** Creado en Julio de 2009 por Montes http://mooontes.com
** Bajo licencia http://creativecommons.org/licenses/by/3.0/es/deed.es
**
** Ejemplo de programación con Google Maps API V3
**
** Centrado del mapa en la ubicación del visitante, captura de eventos,
** reverse geocoding y uso de la libreria para hacer zoom con la rueda del ratón
--&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;es&quot; lang=&quot;es&quot;&gt;
&lt;head&gt;

	&lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1.0, user-scalable=no&quot; /&gt;
	&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;

	&lt;title&gt;Test Google Maps API V3 -mooontes.com-&lt;/title&gt;

    &lt;style type=&quot;text/css&quot;&gt;
	html
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	body
	{
		border:0;
		padding:0;
		margin:0;
		width:100%;
		height:100%;
	}
	#map_canvas
	{
		width:100%;
		height:100%;
	}
	#info
	{
		position:absolute;
		width:250px;
		height:250px;
		left:20px;
		top:300px;
		background-color:white;
		padding:5px;
		overflow:auto;
	}
    &lt;/style&gt;

	&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.google.com/maps/api/js?sensor=false&quot;&gt;&lt;/script&gt;	

	&lt;script type=&quot;text/javascript&quot;&gt;
	var map;
	var geocoder;

	function initialize() {

		//Inicializamos geocoder y centramos el mapa en la ubicación del visitante
		geocoder = new google.maps.Geocoder();
		if (google.loader.ClientLocation)
		{
			//Averiguamos latitud/longitud del visitante
			var latt = google.loader.ClientLocation.latitude;
			var longg = google.loader.ClientLocation.longitude;

			//Centramos el mapa en sus coordenadas
			var latlng = new google.maps.LatLng(latt,longg);
		}
		else
		{
			//Si no localizamos la ubicacion del visitante, centramos el mapa en Madrid
			var latlng = new google.maps.LatLng(&quot;40.41153868&quot;,&quot;-3.70362707&quot;);
		}

		//Creamos el mapa
		var myOptions = {
		zoom: 5,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP
		};
		map = new google.maps.Map(document.getElementById(&quot;map_canvas&quot;), myOptions);

		//Añadimos un listener, se activará cuando el mapa esté totalmente cargado
		google.maps.event.addListener(map, 'bounds_changed',function()
			{
				//Primera actualización del div que muestra los detalles de la ubicacion actual
				actualizaUbicacion();
				//Al haber cargado totalmente el mapa, eliminamos este listener
				google.maps.event.clearListeners(map, 'bounds_changed');
				//Y añadimos dos, uno se activará cuando se termine de arrastrar el mapa y otro cuando se cambie el nivel de zoom
				google.maps.event.addListener(map, 'dragend',function() { actualizaUbicacion() });
				google.maps.event.addListener(map, 'zoom_changed',function() { actualizaUbicacion() });
			}
		);

	}

	function actualizaUbicacion()
	{

		//Coordenadas del centro del mapa que usaremos para el reverse geocoding
		var lattlng = map.getCenter();

		if (geocoder)
		{
			geocoder.geocode({'latLng': lattlng}, function(results, status)
			{
				if (status == google.maps.GeocoderStatus.OK)
				{
					if (results[1])
					{
						var reverse_geo = results[1];

						var text = &quot;&lt;a href='http://mooontes.com'&gt;mooontes.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Map center: &quot;
							+ map.getCenter()+ &quot;&lt;br /&gt;&lt;br /&gt;Reverse Geocoding:&lt;br /&gt;&quot;;
						if (reverse_geo.address_components[0]) { text = text + &quot;0: &quot; + reverse_geo.address_components[0].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[1]) { text = text + &quot;1: &quot; + reverse_geo.address_components[1].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[2]) { text = text + &quot;2: &quot; + reverse_geo.address_components[2].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[3]) { text = text + &quot;3: &quot; + reverse_geo.address_components[3].long_name + &quot;&lt;br /&gt;&quot;; }
						if (reverse_geo.address_components[4]) { text = text + &quot;4: &quot; + reverse_geo.address_components[4].long_name + &quot;&lt;br /&gt;&quot;; }

						text = text + &quot;5: &quot; + reverse_geo.formatted_address;

						document.getElementById('info').innerHTML = text;
					}
				}
				else
				{
					document.getElementById('info').innerHTML = &quot;No hay información de Reverse Geocoding.&quot;;
				}
			});
		}
	}

	//--&gt;&lt;/script&gt;

&lt;/head&gt;
&lt;body onload=&quot;initialize()&quot;&gt;
	&lt;div id=&quot;map_canvas&quot;&gt;&lt;/div&gt;
	&lt;div id=&quot;info&quot;&gt;&lt;a href=&quot;http://mooontes.com&quot;&gt;mooontes.com&lt;/a&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://mooontes.com/2009/07/29/google-maps-api-v3-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

