Bienvenidos a un nuevo curso. Ahora estoy en el ciclo de grado superior: Desarrollo de aplicaciones multiplataforma. Y voy a ser parte del experimento de la formación dual. Estaré haciendo practicas durante un año, y a la vez finalizando la formación.

Deseadme suerte.

Mostrando entradas con la etiqueta PROG. Mostrar todas las entradas
Mostrando entradas con la etiqueta PROG. Mostrar todas las entradas

viernes, 16 de septiembre de 2016

Override en Prestashop

0

Definición:
Override es el sistema que tiene Prestashop para proteger aquellos archivos considerados modificados: clases y controladores (php) son de los más importantes, ya que, si añades o modificas alguna función en el fichero original y se te ocurre actualizar Prestashop… ¡adiós! Todos los cambios que hayas realizado en ese archivo se borrarán.

Técnica del Override para los archivos .php:
La técnica del override en Prestashop consiste en la creación de un nuevo archivo que lleve dentro una clase que extienda de la original, cuya información sustituirá a la del archivo original, siempre y cuando, el nombre de la función o instrucción coincida con la del archivo original.

Técnica del Override para los módulos:
En la carpeta de tienda/themes/nombre_del_tema/modules/ se guardan una copia del modulo entero o de ciertos archivos para modificarlos desde ahí, en lugar del original tienda/modules/. Si existe una carpeta en dicha dirección, Prestashop lo leerla sobre el original, pero las actualizaciones solo serán en la carpeta original. Si no ves alguna actualización del modulo, borra la carpeta del override ;)

Ejemplo añadir al formulario un ¿como nos conociste?:

TPL
Me dirijo a /themes/nombre_del_tema/authentication.tpl. Ya que los tpl, no tienen clases y funciones, nos toca hacerlo así.Ahí añadimos las veces que corresponda el siguiente texto:

<div form-group>
<label class="control-label col-sm-4">{l s='¿Como nos conoció?'}</label>
<div class="col-sm-6">
<input type="radio" id="conocer" name="conocer" value="amigo"  class="conocer"> {l s = 'A través de un amigo' } <br>
<input type="radio" id="conocer" name="conocer" value="google"  class="conocer"> {l s = 'Buscando en Google' } <br>
<input type="radio" id="conocer" name="conocer" value="blog"  class="conocer"> {l s = 'A través del blog Ofertitas' } <br>
<input type="radio" id="conocer" name="conocer" value="foro"  class="conocer"> {l s = 'A través de un foro' } <br>
<input type="radio" id="conocer" name="conocer" value="twitter"  class="conocer"> {l s = 'A través de las redes sociales' } <br>
<input type="radio" id="conocer" name="conocer" value="otros"  class="conocer"> {l s = 'De otra forma' } <br>
<div class="col-sm-6">
<label class="control-label col-sm-8">{l s='¿De que otra forma?'}</label>
<input type="text" class="is_required validate form-control" data-validate="conocerOtro" id="conocerOtro" name="conocerOtro" value="{if isset($smarty.post.conoceOtro)}{$smarty.post.conoceOtro}{/if}" /><br>
</div>
</div>
</div>

Para tener la última referencia de las plantillas recomiendo un control de versiones.
Y una documentación, comentando las actualizaciones. 

Nos queda así:

El CSS seguiría los mismos pasos que los archivos.tpl

PHP
Ahora llega lo interesante.

Original (controllers/front/AuthController.php)
class AuthControllerCore extends FrontController
{
}

Override (override/controllers/front/AuthController.php)
class AuthController extends AuthControllerCore
{
}

En este archivo es donde guardamos la acción del boton, que nos guardara la información del formulario.
Si buscas submit en el tpl modificado, encontraras que existen 4 botones, del cual, según mi plantilla, necesitare 2 (submitGuestAccount y submitAccount). Investigando el documento vemos la función:

Original (controllers/front/AuthController.php)
class AuthControllerCore extends FrontController
{
          protected function processSubmitAccount()
          {
                    //función original
           }
}

Override (override/controllers/front/AuthController.php)
class AuthController extends AuthControllerCore
{
           protected function processSubmitAccount()
          {
                    //código a añadir:
                  $customer = new Customer();

                  $conocer = Tools::getValue('conocer');
                  $conocerOtro=Tools::getValue('conocerOtro');

                  $customer->referralcode = $conocer;
                  $customer->referralcode = $conocerOtro;

                  $this->context->cookie->customer_referralcode = $customer->$conocer;
                  $this->context->cookie->customer_referralcode = $customer->$conocerOtro;

                   //para que el resto de la función en la original también se ejecute

                    parent::processSubmitAccount();
           }
}

Podrás ver si funciona con la siguiente "marquita"




Ahora definimos los nuevos campos y los añadimos al objeto customer


Original (classes/Customer.php)
class CustomerCore extends ObjectModel
{

}

Override(override/classes/Customer.php)
class Customer extends CustomerCore
{
    //declaración:
    public $conocer;
    public $conocerOtro;

//definición del objeto:
como no es una función que se pueda 'separar' la creamos entera
public static $definition = array(
        'table' => 'customer',
        'primary' => 'id_customer',
        'fields' => array(
            'secure_key' => array('type' => self::TYPE_STRING, 'validate' => 'isMd5', 'copy_post' => false),
            'lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32),
            'firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName', 'required' => true, 'size' => 32),
            'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'required' => true, 'size' => 128),
            'passwd' => array('type' => self::TYPE_STRING, 'validate' => 'isPasswd', 'required' => true, 'size' => 32),
            'last_passwd_gen' => array('type' => self::TYPE_STRING, 'copy_post' => false),
            'id_gender' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'birthday' => array('type' => self::TYPE_DATE, 'validate' => 'isBirthDate'),
            'newsletter' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
            'newsletter_date_add' => array('type' => self::TYPE_DATE,'copy_post' => false),
            'ip_registration_newsletter' => array('type' => self::TYPE_STRING, 'copy_post' => false),
            'optin' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
            'website' => array('type' => self::TYPE_STRING, 'validate' => 'isUrl'),
            'company' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'),
            'siret' => array('type' => self::TYPE_STRING, 'validate' => 'isSiret'),
            'ape' => array('type' => self::TYPE_STRING, 'validate' => 'isApe'),
            'outstanding_allow_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'copy_post' => false),
            'show_public_prices' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false),
            'id_risk' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'copy_post' => false),
            'max_payment_days' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'copy_post' => false),
            'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false),
            'deleted' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false),
            'note' => array('type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 65000, 'copy_post' => false),
            'is_guest' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'copy_post' => false),
            'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false),
            'id_shop_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false),
            'id_default_group' => array('type' => self::TYPE_INT, 'copy_post' => false),
            'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'copy_post' => false),
            'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false),
            'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'copy_post' => false),
            'conocer' =>                    array('type' => self::TYPE_STRING, 'validate' => 'isName', 'size' => 100),
            'conocerOtro' =>                array('type' => self::TYPE_STRING, 'validate' => 'isName', 'size' => 100),
        ),

    );
}


Por último modifico la base de datos:
ALTER TABLE `pp_customer`
ADD `conocer` VARCHAR( 100 );
ALTER TABLE `pp_customer`
ADD `conocerOtro` VARCHAR( 100 );


Para hacer la prueba es recomendable tener activado el aviso de errores.

En config/defines.inc.php
/* Debug only */
if (!defined('_PS_MODE_DEV_'))
define('_PS_MODE_DEV_', true);

Al hacer la prueba veo que se ha enfadado el smarty

Busco en el foro de prestashop, y la solución es borrar cache, obligar a compilar y si sigue fallando quitar el depurador de errores, ya que no es un error grave o que nos pueda afectar. Más info aquí y aquí.

También recomiendo esta léctura sobre ObjectModel, del cual creare una entrada más adelante. Con más ejemplos. Así como subiré como hacer para que se vea la nueva información en el backOffice (administración).

Por último la prueba final:







miércoles, 7 de septiembre de 2016

Aclaraciónes Curl - xml

0

Hay cosas que parecen tontas, pero si no lo sabes, no lo son. 
Así que quiero hacer un par de aclaraciones y enseñaron un par de trucos. 

¿Recordáis la historia? Quiero que los pedidos de licencias se hagan automáticamente, para ello debo identificar que productos son licencias y luego enviar un xml a la empresa con un post. 

//dentro del modulo, tengo un hook de escucha que se activa si se ha realizado un pedido
public function hookNewOrder($params)
{
//El numero de pedido
$id_order = (int)Tools::getValue('id_order');
//Con el numero de pedido puedo ver las referencias de los productos de dicho pedido (esta comprobación esta dentro de una clase)
$referencia = "SELECT p.reference
                   FROM product p, order_detail od
                   WHERE od.id_order=$id_order
                   AND p.id_product=od.product_id;";
//query realiza una consulta a la base de datos
        $ref Db::getInstance()->query($referencia);
//comprobamos las referencias una por una
while ($re = $ref->fetch())
{
//Compruebo que sea un producto de licencia. (esta comprobación esta dentro de una clase)
$licencia = "SELECT P.reference
                FROM product_lang PL, product P
                WHERE P.reference = '$reference'
                AND PL.name like '% manzana %'
                AND PL.id_product=P.id_product";
//getRow ejecuta una consulta y devuelve la primera fila
        $li Db::getInstance()->getRow($licencia);
//=== si son idénticos
if($re["reference"]===$li["reference"]
{
//necesitamos enviar un valor único a la transferencia, sin modificar la base de datos
//getdate obtiene información de la fecha/hora. Si sumas la fecha y hora, tendrás siempre un valor único.
$tiempo = getdate();
                    $t = $tiempo[year]  + $tiempo[mon]  + $tiempo[mday] + $tiempo[hours]  + $tiempo[minutes] + $tiempo[seconds];
//el post debería estar en un php aparte, para aclarar el texto. 
$service_url = 'http://example.com/api/conversations';
/* inicia sesión curl*/
// el distribuidor nos solicita un archivo xml, pero recuerda que no puedes enviar una variable en xml, y no es necesario un archivo.xml. Lo que necesitas hacer es generar el xml con php. Así que aunque lo lógico sea pensar en usar $input_xml, este genera un xml, así que no te leerá la variable. Por lo que se usa el $curl_post_data.
$curl_post_data = "      <Order>
                        <Version>2.5</Version>
                        <Transaction>
                            <TransactionID>$T</TransactionID>
                        </Transaction>
                        <OrderInformation>
                            ...
                        </OrderInformation>
                    </Order>";
// ya os comente la mayoría de las funciones usadas con curl(+)
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_URL, $service_url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
$curl_response = curl_exec($curl);
if ($curl_response === false) {
    $info = curl_error($curl);
    curl_close($curl);
    $resultado= 'error occured during curl exec. Additioanl info: ' . var_export($info);
//print_r te sacara por pantalla el resultado 
    print_r($resultado);
//exit terminara el programa, es importante salir o continuara el programa convirtiendo el resultado en ok y llevando a error. 
    exit();
}
curl_close($curl);
//json_decode — Decodifica un string de JSON(+)
$decoded = json_decode($curl_response);
//var_dump muestra información estructurada sobre una o más expresiones incluyendo su tipo y valor. (+)
var_dump($curl_response);
/* fin sesión curl*/
if (isset($decoded->response->status) && $decoded->response->status == 'ERROR') {
    $resultado= 'error occured: ' . $decoded->response->errormessage;
    print_r($resultado);
    exit();
}
$resultado= 'response ok!';
var_export($decoded->response);
print_r($resultado);
exit();                    
}
}
}

viernes, 19 de agosto de 2016

cURL

0

El otro día subía el código para un post, donde se utilizaba esta biblioteca. Pero me doy cuenta que necesita una mirada más a fondo. Puedes recordarla aquí

Curl es una librería de funciones para conectar con servidores para trabajar con ellos. El trabajo se realiza con formato URL. Es decir, sirve para realizar acciones sobre archivos que hay en URLs de Internet, soportando los protocolos más comunes, como http, ftp, https, etc.

En lo que respecta a PHP, Curl está integrado dentro, de manera que esas librerías también se pueden utilizar desde scripts PHP. 

Las funciones utilizadas en mi anterior código fueron:

curl_init (+)

resource curl_init ([ string $url = NULL ] )

Inicia una nueva sesión y devuelve el manipulador curl para el uso de las funciones curl_setopt(), curl_exec(), y curl_close(). Devuelve un manipulador de cURL si todo fué bien, FALSE si hay errores.

curl_setopt (+)

bool curl_setopt ( resource $ch , int $option , mixed $value )

Establece una opción en la sesión del recurso cURL.

Los parámetros son los siguientes:

ch: El recurso cURL devuelto por curl_init().

option: La opción CURLOPT_XXX a configurar.

value: Valor a configurar en la option.

A continuación, especifico los parámetros que utilice, para estos parámetros en necesario que value sea bool:

CURLOPT_RETURNTRANSFER

TRUE para devolver el resultado de la transferencia como string del valor de curl_exec() en lugar de mostrarlo directamente.

CURLOPT_POST

TRUE para hacer un HTTP POST normal. Este POST del tipo application/x-www-form-urlencoded, el más común en formularios HTML.

para este parámetro en necesario que value sea string:

CURLOPT_POSTFIELDS

Todos los datos para enviar vía HTTP "POST". para enviar un fichero, prefija el nombre del fichero con @ y utiliza la ruta completa. Se puede especificar explícitamente el tipo de fichero añadiendo el tipo al nombre del fichero, en el formato ';type=mimetype'. Se puede enviar una cadena urlencoded como 'para1=val1&para2=val2&...' o también como un array con el nombre del campo como key y los datos como value. Si value es un array, el encabezado Content-Type será definido como multipart/form-data. .

curl_exec (+)

mixed curl_exec ( resource $ch )

Ejecuta la sesión cURL que se le pasa como parámetro.

Esta función debe llamarse después de inicializar una sesión cURL y todas las opciones para la sesión están establecidas.

El parámetro es el siguiente:

ch: El recurso cURL devuelto por curl_init().

Devuelve TRUE en caso de éxito o FALSE en caso de error. Sin embargo, si la opción CURLOPT_RETURNTRANSFER está establecida, devolverá el resultado si se realizó con éxito, o FALSE si falló.

curl_getinfo (+)

mixed curl_getinfo ( resource $ch [, int $opt = 0 ] )

Obtiene información sobre la última transferencia.

Los parámetros son los siguientes:

ch: El recurso cURL devuelto por curl_init().

opt: Opciones infinitas.

curl_close (+)

mixed curl_exec ( resource $ch )

Ejecuta la sesión cURL que se le pasa como parámetro.

Esta función debe llamarse después de inicializar una sesión cURL y todas las opciones para la sesión están establecidas.

El parámetro es el siguiente:

ch: El recurso cURL devuelto por curl_init().

Devuelve TRUE en caso de éxito o FALSE en caso de error. Sin embargo, si la opción CURLOPT_RETURNTRANSFER está establecida, devolverá el resultado si se realizó con éxito, o FALSE si falló.

domingo, 5 de junio de 2016

Repaso I Evaluación(VII)

0




7.-


8.-


11.-


13.-
using System;

namespace ConsoleApplication21
{
    class Program
    {
        static void Main(string[] args)
        {
            int nivel;
            Console.Write ("Escribe el numero de niveles que deseas: ");
            nivel = int.Parse(Console.ReadLine());
            Console.WriteLine(" ");
            Console.WriteLine("Figura 1");
            Console.WriteLine(" ");
            for(int i=nivel; i>0;i--)
            {
                for(int j=i; j>0; j--)
                {
                    Console.Write("@");
                }
                Console.Write("\n");
            }
            Console.WriteLine(" ");
            Console.WriteLine("Figura 2");
            Console.WriteLine(" ");
            for (int i = 0; i<nivel; i++)
            {
                for (int j = nivel-i; j > 0; j--)
                {
                    Console.Write(" ");
                }
                for (int k = 0; k<i; k++)
                {
                    Console.Write("@");
                }
                for (int m =i-1; m>0;m--)
                {
                    Console.Write("@");
                }
                Console.Write("\n");
            }
            Console.WriteLine(" ");
            Console.WriteLine("Figura 3");
            Console.WriteLine(" ");
            for (int i = 0; i < nivel; i++)
            {
                for (int k = 0; k < i; k++)
                {
                    Console.Write(" ");
                }
                for (int j = nivel - i; j > 0; j--) 
                {
                    Console.Write("@");
                }
                Console.Write("\n");
            }
            Console.ReadKey();
        }
    }
}



14.-


16.-


17.-


21.-



Etiquetas actuales

BD (67) DEF (64) PROG (64) SQL (44) Java (29) PRACTICAS (20) php (18) DI (16) PRESTASHOP (16) PROGRAMACIÓN WEB (16) HTML (13) SGE (12) ERP (9) CONSULTAS (8) css (8) Linux (5) XML (5) Android (4) PDM (4) C (3) NetBeans (3) PSP (3) SMARTY (3) comandos (3) HOOK (2) POST (2) XSD (2) cURL (2) JS (1) MEDIA-QUERYS (1) PDO (1) RESPONSIVE (1) TPL (1) TRADUCCIÓN (1) app_inventor (1)

Todas las etiquetas

EJER (78) BD (67) DEF (64) PROG (64) SQL (44) c# (40) Programación (39) Ficheros (36) Java (29) bases de datos (21) PRACTICAS (20) lenguajes de marcas (19) AD (18) Entorno de desarrollo (18) php (18) PROCEDIMIENTOS (17) DI (16) FORM (16) PRESTASHOP (16) PROGRAMACIÓN WEB (16) lenguaje C (16) E/R (14) HTML (13) SGE (12) Sistemas informáticos (10) ERP (9) CONSULTAS (8) TRANSACCIONES (8) TRIGGER (8) VISUAL BASIC (8) css (8) FUNCIONES (7) html5 (6) Ada (5) EXAMEN (5) Linux (5) XML (5) estructuras (5) Android (4) DISEÑO (4) INTERFAZ (4) LOG (4) OpenBravo (4) PDM (4) ACTUALIZAR (3) C (3) DIAGRAMA (3) Directorios (3) NEW (3) NOR (3) NetBeans (3) OLD (3) PSP (3) SMARTY (3) comandos (3) css3 (3) AISLAMIENTOS (2) C++ (2) CONTROLERRORES (2) ELIMINAR (2) HOOK (2) INSERTAR (2) INST (2) MULTITABLA (2) POST (2) RECURSIVIDAD (2) SUBCONSULTAS (2) VISTAS (2) XSD (2) cURL (2) punteros (2) AJENA (1) BLOQUEOS (1) Byte (1) CREACION (1) CRM (1) Configuración (1) Controles (1) Datos (1) GOTFOCUS (1) IMAGENES (1) INDICES (1) JS (1) Lenght (1) MEDIA-QUERYS (1) Mingw (1) MonoDeveloped (1) OPTIMISTA (1) PDO (1) PESIMISTA (1) RESPONSIVE (1) SPEAK (1) Scanner (1) Serializacion (1) Streams (1) System (1) TPL (1) TRADUCCIÓN (1) USUARIOS (1) UseSystemPasswordChar (1) app_inventor (1) char (1) examenes (1) libreoffice (1) make (1) redes (1)