javascript

Javascript import et symbole @

Vous avez sans doute souvent vu dans un script javascript moderne ceci:

import Component from '@/components/component'

Normalement si on veut importer un module Javascript, il faut utiliser les / et les .. soit pour remonter d’un niveau soit pour descendre d’un niveau, comme on le ferait dans n’importe quel langage de programmation.

Cette notation n’est pas du Javascript natif, elle est rendue possible par l’utilisation d’un plugin de type module loader ou module bundler.

C’est un plugin comme babel plugin root import, qui permet d’avoir cette syntaxe. Mais de quel root? le root du projet javascript en question. Ainsi quelque soit l’emplacement du plugin et de la page qui demande le plugin, on utilisera l’arobase pour atteindre un plugin comme si on le demandait depuis la racine du projet.

Cela permet d’éviter que la syntaxe suivante :

import Component from 'components/component'

Dans ce cas ça va chercher dans /node_modules.

Si on cherche un module dans le projet

import Component from './components/component'

Mécanisme de session de Django

Similaire aux sessions en PHP, dans Django il faut importer deux lignes pour pouvoir travailler avec les sessions:

#settings
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions', // le module Session
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'products.apps.ProductsConfig'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware', // le middleware
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Avec Django par défaut les sessions sont sauvées dans la base de données.

Les formulaires dans Django

Les formulaires sont un vaste chapitre comme dans tout framework web quelque soit le langage. Mais Django permet de les manipuler plus facilement que Symfony par exemple.

cleaned_data qu’est ce que c’est?

Il y a deux types de formulaire dans Django, les formulaires classiques qui héritent de forms.Form, et mes formulaires liés à des entités, qui héritent de forms.ModelForm.

Avec les modelForm, inutile de s’inquiéter du cleaned_data.

Dans un form classique on doit utiliser les données validée:
if form.is_valid():
    ex = Example()
    ex.username = form.cleaned_data['username']
    ex.save()

Alors que dans un modelForm, cette étape est automatique.

if form.is_valid():
    form.save()

https://stackoverflow.com/questions/53594745/what-is-the-use-of-cleaned-data-in-django

Upload de fichiers dans Django

Pour uploader un fichier dans un formulaire, il faut modifier le model,

class Product(models.Model):
    name = models.CharField(max_length=50)
    price = models.FloatField()
    stock = models.IntegerField()
    image = models.CharfieldField(max_length=1000)

class Product(models.Model):
    name = models.CharField(max_length=50)
    price = models.FloatField()
    stock = models.IntegerField()
    image = models.FileField()

Après avoir changé la propriété dans le model, il faut faire une migration

python manage.py makemigrations products  #le nom de l'app
python manage.py migrate

Ensuite il faut faire quelques modification de code, dans le settings.py de votre projet :

#monprojet\settings.py
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'

#monprojet\urls.py
from django.contrib import admin
from django.urls import path, include

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('products/', include('products.urls'))
]

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

php

Doctrine et ses 4 façons de requêter la base de données

DQL Doctrine Query Langage

$query = $this->em->createQuery(
    "
    SELECT p
    FROM AppBundle\Entity\RedditPost p
    WHERE p.id > :id
    "
)->setParameter('id', 50);

$data = $query->getResult();

Mais on ne peut splitter la requête simplement, alors qu’avec le query builder c’est possible:

// it is still DQL, but now it is painful

var $someConditional = false;

if ($someConditional === true) {
    $query = $this->em->createQuery(
        "
        SELECT p
        FROM AppBundle\Entity\RedditPost p
        WHERE p.id > :id
        "
    )->setParameter('id', 50);
} else {
    $query = $this->em->createQuery(
    "
        SELECT p
        FROM AppBundle\Entity\RedditPost p
    "
    );
}

$data = $query->getResult();

Query Builder

C’est mieux avec le query builder, plus facile de paramétrer sa requête, tout est à base de méthode objet.

// using Doctrine's Query Builder

var $someConditional = false;

$query = $this->getDoctrine()->getRepository('AppBundle:RedditPost')->createQueryBuilder('p');

if ($someConditional === true) {
    $query
        ->where('p.id > :id')
        ->setParameter('id', 50)
    ;
} 

$data = $query->getQuery()->getResult();

https://codereviewvideos.com/course/doctrine-databasics/video/dql-vs-doctrine-query-builder

$query = $this->getDoctrine()
    ->getRepository('AppBundle:RedditPost')
    ->createQueryBuilder('p')

createQueryBuilder('p') implicitly creates the equivalent:

    SELECT p
    FROM AppBundle\Entity\RedditPost p

C’est la raison pour laquelle on n’a pas besoin de SELECT et FROM explicite

Native Query

Ressemble beaucoup au SQL, la notion de resultSetMapping est centrale.

use Doctrine\ORM\Query\ResultSetMapping;

$rsm = new ResultSetMapping();
// build rsm here

$query = $entityManager->createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm);
$query->setParameter(1, 'romanb');

$users = $query->getResult();

https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/native-sql.html

On peut utiliser le resultSetMappingBuilder pour construire des requêtes Native Query

use Doctrine\ORM\Query\ResultSetMappingBuilder;

$sql = "SELECT u.id, u.name, a.id AS address_id, a.street, a.city " . 
       "FROM users u INNER JOIN address a ON u.address_id = a.id";

$rsm = new ResultSetMappingBuilder($entityManager);
$rsm->addRootEntityFromClassMetadata('MyProject\User', 'u');
$rsm->addJoinedEntityFromClassMetadata('MyProject\Address', 'a', 'u', 'address', array('id' => 'address_id'));

Raw SQL

On met du pur SQL dans un repository Doctrine

    public function getEvoplusStatusCountByMonthByCommercial(int $idUser, $start, $end)
    {
        $conn = $this->getEntityManager()->getConnection();

        $sql = "select count(*) as count, M.ID_ETAT_MATRICE, EM.LIBELLE_ETAT_MATRICE from MATRICE M 
inner join ETAT_MATRICE EM on 
M.ID_ETAT_MATRICE = EM.ID_ETAT_MATRICE 
where 
CONTRAT_DATE_SIGNATURE BETWEEN '$start' AND '$end'
AND USR_ID = $idUser GROUP by M.ID_ETAT_MATRICE; ";

        $stmt = $conn->prepare($sql);
        $stmt->execute();
        $res = $stmt->fetchAll();

        return $res;
    }

Cette méthode est ma préférée, vou sl’aurez compris je ne suis pas un fan des ORM, c’est tellement plus facile de faire des requêtes SQL, et tant pis si on n’a pas d’objet en résultat, manipuler des tableaux associatifs n’est pas si difficile.

Introduction à Jupyter Notebook

Jupyter Notebook est une interface web pour faire de la datascience, vous exécutez vos scnippet Python dans ce qu’on appelle des cells, des unités d’exécution.

Pour l’installer, voici la procédure :

Installation des librairies

pip install pandas
pip install numpy
pip install matplotlib
pip install xlrd

Installation de Jupyter Notebook

pip install notebook

#démarrer notebook
jupyter notebook

Vous pouvez installer d’abord Jupyter Notebook et installer les librairies depuis Jupyter Notebook

!pip install pandas 

le ! permet d'accéder au shell.

Afficher les log server dans Python Django

Il est pratique de logger en mode développement les requêtes servies par le serveur de Python

dans le fichier settings.py de votre projet mettez ce code juste après le DEBUG = true

if DEBUG:
    # will output to your console
    logging.basicConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)s %(message)s',
    )
else:
    # will output to logging file
    logging.basicConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)s %(message)s',
        filename = '/my_log_file.log',
        filemode = 'a'
    )

https://stackoverflow.com/questions/4558879/python-django-log-to-console-under-runserver-log-to-file-under-apache

Comprendre le mot clé with en Python

La syntaxe en Python de with est assez étrange, quel problème essait-il de résoudre?

with est utilisé lorsqu’on travaille avec des ressources non managées, notamment ouverture d’une fichier. Avant on utilisait try...catch,

    set things up
    try:
        do something
    finally:
        tear things down

Syntaxe basique de with

with expression [as variable]:
    with-block

L’expression est évaluée, et retourne un objet qui implémente le context management protocol, c’est à dire qui possède les méthodes __enter__() et __exit__()

with open('text.txt','w') as fichier
    fichier.write('Hello')

Avec cette syntaxe pas besoin de fermer explicitement le fichier, c’est automatique.

javascript

L’Event Loop dans Javascript

setTimeout n’appartient pas à V8

Javascript est single threaded

Blocking

Async callback and call stack @ 11:25

console.log('hi'); // A

setTimeout(function(){  // B
    console.log('there');
},5000);

console.log('Hello');  // C

Ordre d’appel dans le callstack A, B, C mais le ‘there’ est affiché 5 secondes après. Javascript ne fait qu’une seule chose à la fois

Event Loop

L’event loop regarde s’il reste encore des opérations à faire dans le stack, si le stack est vide, l’Event loop va regarder dans le task queue.

Liens :

JS Async

Latentflip Loupe

Javascript engine talk

Introduction à Numpy

Numpy est une librairie Python qui introduit une nouvelle structure de données l’Array, qui est comme une liste, mais en beaucoup plus rapide.

Installation de Numpy

pip install numpy
#test.py
import numpy
arr = numpy.array([1,2,3,4,5])
print(arr)

Importation de Numpy avec un alias

import numpy as np
arr = np.array([1,2,3,4,5])
print(np.__version__)

Array scalaire 0 dimension

import numpy as np
arr = np.array(42)
print(arr) 

Array unidimensionnel

import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr) 

Array 2D

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr) 

Dans le cas particuliers des matrices Numpy a une librairie dédiée numpy.mat

Array 3D utilisé pour représenter les tenseurs.

Checker la dimension d’un array avec ndim

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.ndim) 

Index des array c’est comme les listes

Le notation est différente ce ce qu’on peut voir en Javascript

import numpy as np
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
print('2nd element on 1st dim: ', arr[0, 1]) 

Index négatif

pour accéder depuis la fin

import numpy as np
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
print('Last element from 2nd dim: ', arr[1, -1]) 

Array slicing

import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[1:5]) 
print(arr[4:]) 
print(arr[:4]) 
print(arr[:]) 
print(arr[-3:-1]) #Array slicing négatif
print(arr[1:5:2]) #step slicing !cette notation exclut le dernier (tem index 5 n'est pas pris en compte)

Slicing 2D array

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr[1, 1:4])  # sur un array
print(arr[0:2, 2]) # sur deux array
print(arr[0:2, 1:4]) # sur deux array de 1 à 4

Les datatype de Numpy


		
logo windows

Clonez votre SSD avec Macrium gratuit pour avoir une sauvegarde

J’ai un SSD qui est une sauvegarde exacte de mon disque principal (un clone), si ce dernier plante, je replugge direct le SSD de sauvegarde, ça fait gagner une journée !

Sélectionnez le disque à cloner, si vous en avez plusieurs, faites attention au choix de votre disque.

Sélectionnez le disque qui sera le clone (disque cible)

Effacez les partitions du disque cible

Sélectionnez les partitions à cloner, dans l’idéal, le disque cible doit être au moins aussi gros que le disque source, si ce n’est pas le cas, il existe des moyens de contourner à chercher sur le Net.

Faire le backup, dans la version gratuite ne cochez pas la seconde case, qui ordonnance une sauvegarde régulière.

Message d’avertissement, vérifiez que tout est bien en ordre et clonez !

Update:

Vidéo clonage de disque SSD avec Macrium

AVERTISSEMENT : Je ne suis pas responsable de la perte de vos données ! Cette vidéo est à titre informative, soyez prudent avec les disque que vous écrasez, conseil : débrancher les disques non sollicité dans le processus de clonage (il doit en rester deux connectés).

Vérifiez à deux fois avant de cloner.

Insérer un modèle dans la base avec Django

De la même façon qu’on peut générer un formulaire facilement avec le modèle, on peut facilement insérer dans la base de données une entité provenant d’un formulaire HTML généré de cette façon, ou en le construisant from scratch depuis une méthode de view

#models.py
class Foo(models.Model):
    name = models.CharField(max_length=100)

#view.py
def add(request):
    foo_instance = Foo.objects.create(name='test')
    return render(request, 'some_name.html.html')

Ou l’on peut se servir du model directement

from django.http import HttpResponse
from django.template import loader

from .models import Article


def index(request):
    article = Article()
    article.title = 'This is the title'
    article.contents = 'This is the content'
    article.save()

    template = loader.get_template('articles/index.html')
    context = {
        'new_article_id': article.pk,
    }
    return HttpResponse(template.render(context, request))

En utilisant les model form c’et plus simple

# views.py
def monform(request):
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = MyProductForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/products/thanks')

    # if a GET (or any other method) we'll create a blank form
    else:
        form = MyProductForm()

    return render(request, 'myproductform.html', {'form': form})

#form.py
class MyProductForm(ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'price', 'stock', 'image']  #or use tuple
#models.py
class Product(models.Model):
    name = models.CharField(max_length=50)
    price = models.FloatField()
    stock = models.IntegerField()
    image = models.CharField(max_length=2000)
xcode

Problème rencontré avec XCode

SI vous passez à XCode 12 depusi une version antérieure (la 11.x dans mon cas) et vous compilez votre projet (React Native) dans mon cas, vous aurez sans doute un problème de compatibilité avec les modules

Module compiled with Swift 5.3.1 cannot be imported by the Swift 5.2.4 compiler

Il faut aller dans les paramètres de XCode, puis Location et sélectionnez la version du CLI

xcode

Mise à jour de React Native suite à la version IOS 14

C’est un casse-tête cette màj de IOS.

J’étais en RN 0.61.5 et après avoir mis à jour la version de XCode vers la version 12, le déploiement sur device IOS marche mais il manque les images. Ce qui est conseillé est de mettre à jour React Native vers la dernière version qui corrige ce problème. Il est conseillé de mettre régulièrement à jour React Native, ça va tellement vite. J’ai lu que si vous ne le faites pas sur une durée de 18 mois, c’est un peu la catastrophe de mettre à jour, car le programme qui met à jour peut changer et d’autres joyeusetés.

Pour mettre à jour suivez ce lien sur Stackoverflow,

Cocoapod refus de s’exécuter, si vous avez le message :

[!] CocoaPods could not find compatible versions for pod "ReactCommon/callinvoker":
  In Podfile:
    ReactCommon/callinvoker (from `../node_modules/react-native/ReactCommon`)

None of your spec sources contain a spec satisfying the dependency: `ReactCommon/callinvoker (from `../node_modules/react-native/ReactCommon`)`.

You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * mistyped the name or version.
 * not added the source repo that hosts the Podspec to your Podfile.

Solution à ce problème :

javascript

Test de nullité en Javascrip : Cas où l’ordre a une importance

    const handleAccountCreation = async () => {
        const exist = await userExistCheck(result.email)
        console.warn('social login', exist)

        if (exist.exist !== null) {
            socialLogin(result.email)
            console.warn('social login')
        }
        else {
            createAccount(result.email)
            console.warn('social create account')
        }
    }

La condition dans le if échoue si exist est null, car exist.exist reverra une erreur undefined.

Il faut mettre une condition autrement

    const handleAccountCreation = async () => {
        const exist = await userExistCheck(result.email)
        console.warn('social login', exist)

        if (exist == null) {
             createAccount(result.email)
             console.warn('social login')
        }
        else {
            socialLogin(result.email)
            console.warn('social create account')
        }
    }

javascript

Opérateur point d’interrogation ?. en Javascript (Null propagation operator)

A ne pas confondre avec le null coalesce operator en Javascript ?? . Cet opérateur est encore appelé optional chaining operator.

        if (data.error?.message) {
          Alert.alert('Erreur carte',
            `Votre transaction ne s\'est pas terminée correctement Message de Stripe.com : ${data.error.message}`)
        } else {
          return data.id
        }

Si error n’existe pas alors data.error?.message évaluera en undefined

https://ponyfoo.com/articles/null-propagation-operator

Linux

Compresser une dossier avec la commande tar (tarball)

Cette commande est rapide et puissante. Vous pouvez archiver une dossier complet, et avoir la possibilité d’excluer certains répertoire. Vous pouvez aussi à la volée compresser l’archive.

Archive simple

tar -cvf archive.tar /folder

Archiver en excluant des répertoires

$ tar --exclude='./folder' --exclude='./upload/folder2' -zcvf /backup/filename.tgz .
react native

Configurer Apple Pay sur React Native (Part 1)

Tuto React Native Apple Pay avec Laravel en backend

C’est quoi Apple Pay?

Pour pouvoir payer avec Apple Pay, vous devez ouvrir l’application Wallet, scanner votre carte bancaire, un process de validation va suivre et si c’est OK vous pourrez utiliser votre Iphone pour payer. C’est en fait une dématérialisation de votre carte bancaire, qui ne fera qu’un avec votre téléphone, vous n’avez plus besoin d’utiliser votre carte bancaire. Apple Pay agit comme un proxy de votre carte bancaire. Vous avez un portefeuille numérique (Digital Wallet)

Ce qu’Apple Pay n’est pas

Apple Pay n’est pas un moyen de paiement au sens Payment Gateway (comme l’est Stripe, Briaintree,, ça n’encaisse pas d’argent sur un compte Apple, ce n’est pas le In App purchase sur lequel Apple prélève 30%. Apple Pay n e peut donc être utilisé pour l’In App purchase. C’est pour ça qu’une fois Apple Pay est intégré sur une application mobile, si vous utilisez Strip epour encaisser, il faudra utiliser le tuto de Stripe pour intégrer Apple Pay, car votre code Apple Pay va faire une requête vers Stripe.

Procédure de configuration sur le site d’Apple

  • créer un CSR depuis le trousseau de clé Application > Utilitaire
  • Aller dans le compte développeur Apple, créer un Id Merchant
  • Aller dans Certificate créer un certificat cochez Apple Pay Payment Processing Certificate
  • Uploadez le CSR généré, attention pour générer un certificat pour Apple Pay, c’est différent il faut associer une clé spéciale
  • Vous serez invité à téléchargé le certificat
  • Allez dans Certificat,Identifier & Profile, cliquez sur l’application sur laquelle vous voulez utiliser Apple Pay, Apple Pay Payment Processing, choisissez le Merchant ID cochez, un nouveau provisioning profile sera créé (à chaque fois que vous ajoutez ou enlevez une Capabilities
  • Ouvrez Xcode, choisissez onglet Signing&Capabilities, cliquez sur le bouton « +Capabilities« , une liste apparait, double cliquez sur Apple Pay
  • Apple Pay apparait maintenant dans l’onglet, cochez la case « MerchantID »

https://medium.com/enappd/implement-apple-pay-in-react-native-apps-dec9cd5c6808, pour ce lien ne suivez pas l’utilisation de la librairie mais seulement la configuration côté Apple developper Account, elle n’est plus maintenue, et préférer ces deux liens, IOS et Android.

Génération du certificat Procédure

Générer le CSR pour Apple Pay : https://docs.skillz.com/docs/v23.2.1/apple-pay/

On your Mac, open Keychain Access
In the menu bar go to Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority....
Input your preferred email address
Select Saved to Disk
Check Let me specify key pair information
Press Continue
Choose a location to save the .certSigningRequest file, and give it a name.
Select Algorithm ECC
Select Key Size 256 Bits ** NOTE: You MUST select ECC before the 256 Bits option becomes available
Press Continue

https://docs.skillz.com/docs/v23.2.1/apple-pay/

Créer un Sandbox tester Account

Pour éviter d’utiliser votre vraie carte, il vous faut ce type de compte. Allez dans AppStore Connect, dans Utilisateurs et Accès, barre latérale gauche, dans Sandbox, cliquez sur Testeurs, ajoutez un testeur, entrez les informations et validez le compte via email.

Attention la procédure suivante nécessite de vous déconnecter de votre Iphone et de vous connecter avec le compte de test.

Une fois connecté, allez dans vos paramètres > wallet and apple Pay ou en cliquant sur l’icône Wallet, il vous faut entrer manuellement votre carte de test. Vérifiez que la région de votre compte est bien dans un pays supporté par Apple Pay. Cette page officielle contient des numéro sde carte, mais je n’ai pu réussir qu’avec le numéro sur cette page.(je n’ai pas tout essayé non plus)

react native

Ajouter Facebook Login dans une application React Native

https://enappd.com/blog/facebook-login-in-react-native-apps/89/

https://developers.facebook.com/docs/react-native/login/

Résumé des étapes pour intégrer le Facebook Login

  • créer une ap dans Facebook developer Console, récuper l’Id de l’app
  • Installer le package pour React Native
  • Implémenter le code 2 composants sont nécessaire LoginButton, LoginManager

Bien suivre les instructions de cette videos, j’ai suivi le tuto, j’ai pu faire marcher sur Android, mais pas sur IOS qui refuse de builder malgré le paramétrage, la solution a été proposée sur Stackoverflow, solution non intuitive si on n’est pa développeur natif.

https://www.youtube.com/watch?v=J-VIu_i0NRM

Ce lien propose une solution quand le projet ne veut lus builder après l’installation de fbsdk sur IOS.

https://stackoverflow.com/questions/50096025/it-gives-errors-when-using-swift-static-library-with-objective-c-project/56187043#56187043

Facebook Login et le système existant de connexion à votre application

Si vous faites coexister votre système de login et celui de Facebook Login, des questions intéressantes peuvent se poser. A la première connexion, l’utilisateur n’a pas de compte sur votre application, il peut choisir soit de recourir à votre système, soit à celui de Facebook. Je suppose que l’ backend de l’appli est un serveur sous PHP (ex Laravel ou Symfony), et que l’application React Native communique par Rest API, donc authentification par JWT.

Votre système de création de compte et de connexion

  • Création de compte : l’utilisateur entre email et mot de passe et valide la création
  • l’utilisateur se connecte en entrant email et mot de passe
  • le serveur envoit un token d’authentification qui sera stocké sur l’application, et envoyé à chaque requête Ajax

Création avec Facebook Login

  • L’utilisateur clique sur le bouton Facebook Login, s’authentifie, et Facebook envoit un Access Token

Mais voilà à ce stade il a le choix de créer son compte ou non. S’il crée un compte sur l’application, on doit pouvoir recueillir son email automatiquement (c’est possible avec Facebook Login de demander l’email, nom et prénom), envoyer vers le serveur (s’assurer que le compte n’existe pas déjà en comparant l’email), la création de compte étant fini, il faut pouvoir renvoyer un token d’authentification vers l’application qui stockera le token.

Obtenir l’email avec le facebook login

import React, { Component } from 'react';
import { View } from 'react-native';
import { LoginButton, AccessToken, LoginManager, GraphRequestManager, GraphRequest } from 'react-native-fbsdk';

export default class Login extends Component {
    render() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <LoginButton
                    onLoginFinished={
                        (error, result) => {
                            LoginManager.logInWithPermissions(['public_profile', 'email']).then(
                                function (result) {
                                    if (result.isCancelled) {
                                        console.log("Login cancelled");
                                    } else {
                                        console.log(
                                            "Login success with permissions: " +
                                            result.grantedPermissions.toString()
                                        );

                                        AccessToken.getCurrentAccessToken().then(
                                            (data) => {
                                                console.log(data)
                                                let accessToken = data.accessToken;

                                                const responseInfoCallback = (error, result) => {
                                                    if (error) {
                                                        console.log(error)
                                                        alert('Error fetching data: ' + error.toString());
                                                    } else {
                                                        console.log(result)
                                                        alert('Success fetching data: ' + result.toString());
                                                    }
                                                }


                                                const infoRequest = new GraphRequest(
                                                    '/me',
                                                    {
                                                        accessToken: accessToken,
                                                        parameters: {
                                                            fields: {
                                                                string: 'email,name,first_name,middle_name,last_name'
                                                            }
                                                        }
                                                    },
                                                    responseInfoCallback
                                                );

                                                // Start the graph request.
                                                new GraphRequestManager().addRequest(infoRequest).start();


                                            }
                                        )
                                    }
                                },
                                function (error) {
                                    console.log("Login fail with error: " + error);
                                }
                            );
                        }
                    }
                    onLogoutFinished={() => console.log("logout.")} />
            </View>
        );
    }
};

Anoter que la section

LoginManager.logInWithPermissions(['public_profile', 'email']).then(
                                function (result) {
                                    if (result.isCancelled) {
                                        console.log("Login cancelled");
                                    } else {
                                        console.log(

la façon dont est géré la promesse ne permet pas de lire le bon mot clé this, donc si on passait une props, elle ne sera pas récupérable on aura un undefined, la bonne technique est:

LoginManager.logInWithPermissions(['public_profile', 'email']).then( (result) => {
if(!result){
    console.log("Login cancelled");
}
else {
// le code quand tout est bon
}

https://github.com/lakshmantgld/react-native-fbsdk-example

https://developers.facebook.com/docs/facebook-login/multiple-providers/

Voir aussi Intégrer Google SignIn

react native

Boucler dans un JSX

La syntaxe JSX n’est pas forcément facile à appréhender, imaginez du HTML dans un return…

Pour faire une boucle sur un tableau afin d’afficher une liste par exemple d’élément JSX, il existe plusieurs façons, mais la plus répandue (99% semble-t-il) est d’utiliser map qui est une méthode de l’objet Array, qui retourne un tableau avec le même nombre d’éléments que le tableau d’entrée)

Façon ES6, la plus compacte avec fonction flèche

<div>
    {montableau.map((item, i) => <ObjectRow obj={item} key={i} />)}
</div>

Méthode avec le mot clé function

<div>
    {montableau.map(function(object, i){
        return <ObjectRow obj={item} key={i} />;
    })}
</div>

Avec la boucle for

Cette méthode est rarement vue mais elle marche

<div>
    for (var i=0; i < objects.length; i++) {
        <ObjectRow obj={objects[i]} key={i}>
    } 
</div>

https://stackoverflow.com/questions/22876978/loop-inside-react-jsx

Wordpress

Créer une page personnalisée dans WordPress

Page de statistique (par exemple)

Création des pages php

Dans le menu du thème, il faut créer une page statistique.php

Ajout dans functions.php le lien vers la page dans le menu

Dans le fichier functions.php il faut insérer dynamiquement les instructions pour charger dans le menu administration de WordPress le lien vers la page statistique

//statistique de jeu 

function stat_setup_menu(){
    add_menu_page( 'Statistiques Franchise', 'Statistiques', 'manage_options', 'export-stat', 'stat_init' );
}
function stat_init(){
    include(get_template_directory().'/statistiques.php');
}
add_action('admin_menu', 'stat_setup_menu');
logo laravel

Les variable d’environnement dans Laravel

Il faut utiliser la librairie Dotenv, cependant pas besoin de la charger avec un use

env('LA_CLE')  // La clé qui se trouve dans le fichier .env
#fichier .env
LA_CLE=lavaleurcorrespondante

Attention si vous n’arrivez pas à lire la clé, il est vraisemblable que le problème soit du côté du cache

php artisan config:clear    // devrait suffire
php artisan cache:clear     // si ça ne marche toujours pas 

https://stackoverflow.com/questions/51987140/laravel-accessing-env-variables

logo laravel

Le routing dans laravel

Route prenant un paramètre

Mais vous voudriez aussi gérer le cas où le paramètre eput être optionnel, dans ce cas créer les deux routes (un avec et un sans)

Route::get('/products','ProductController@getProducts');

Route::get('/products/{type}','ProductController@getProducts')->named('produits');

Ensuite dans le controller gérez le paramètre optionnel

    public function getProducts($type = 'chemise'){
        $product = DB::table('products')
            ->where('type','=',$type)
            ->where('status','=','1')
            ->get()
            ->toArray();
        return response()->json([$product][0]);
    }

Ainsi si vous passez la route '/products', vous aurez les chemises, et si vous passez la route '/products/pantalon' vous aurez les pantalons, de même '/products/chemise' vous renverra aussi les chemises.

logo laravel

Injection de dépendance dans Laravel

Qu’est ce que c’est?

L’injection de dépendance, un mot bine effrayant pour désigner quelque chose de très simple , c’est de passer en paramètre d’une fonction un objet, et ce de façon « automatique », le moteur de Laravel se chargeant d’injecter dans la fonction automatiquement.

 class Mailer
{
    protected $mailer;   
    function __construct(PHPMailer $mailer)
    {
        $this->mailer = $mailer;
    }
    public function sendMail($recipient,$content,$subject){
      //...code envoi email
    }
}

Maintenant supposons que nous soyons dans un e méthode de controller appelée NotifyLogin, qui envoit un mail à l’administrateur lorsque quelqu’un se connecte.

use Illuminate\Http\Request;
use use App\Helper\Mailer;

class LoginController extends Controller
{
    public function __construct(){}
    public function notifyLogin(Request $request, Mailer $mailer){
    $email = $request->email;

    $mailer->sendMail($email,'Un utilisateur s\'est connecté','Connexion');
    
    }
}

On voit que on injecte $request, mais aussi $mailer, il n’est pas besoin d’instancier avec new, Laravel le fait automatiquement pour nous. Ceci est rendu possible parce qu’en amont, le constructeur de la class Mailer a lui-même utilisé l’injection de dépendance pour s’instancier. AInsi de proche en proche le framework arrive à fournir à la méthode notifyLogin le $mailer avec un minimum de travail de notre part, et en plus notre code est plus lisible et mieux organisé.

react native

React Navigation V5 (librairie de React Native)

Cette librairie est considérée comme importante car elle est incluse par défaut quand vous bootstrapez un projet React Native.

React Navigation V5

Bare react Native CLI

⚠️ StackNavigator V4 is deprecated, use createStackNavigator instead in V5

#Step 1:
$ npm install @react-navigation/native @react-navigation/stack
#Step 2: install the required peer dependencies
$ npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

Configuration initiale de React Navigator

Il vous faut installer le package principal et tous les package suivants

$ npm install @react-navigation/native
$ npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

Configuration native pour Android

Pour Android, pas d’installation, mais ajouter deux lignes dans le fichier build.gradle dans votre_projet/android/app/build.gradle dans la directive dependencies

 dependencies {
    ....
  implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
  implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
}

Installation des fichiers natifs IOS

$ cd ios; pod install; cd ..

Chargement de gesture handler en tout début de script du fichier d’entrée App.js ou index.js, cet import doit être vraiment le tout premier code Js de votre projet.

# dans index.js (ou App.js si pas de index.js)
import 'react-native-gesture-handler';

Pour IOS React navigation a besoin de cette opération: Cocoapod

Note: For iOS with bare React Native project, make sure you have Cocoapods installed

IOS. install cocoapod : mandatory for React Native 0.60+ (https://medium.com/@appstud/add-a-splash-screen-to-a-react-native-app-810492e773f9)

$ sudo gem install cocoapods

***Passing data to Screen:

<Button
        title="Go to Details"
        onPress={() => {
          /* 1. Navigate to the Details route with params */
          navigation.navigate('Details', {
            itemId: 86,
            otherParam: 'anything you want here',
          });
        }}
      />

passing initial param to a screen from <Stack.Screen>
<Stack.Screen
  name="Details"
  component={DetailsScreen}
  initialParams={{ itemId: 42 }}
/>


Retrieving from the destination Screen :
function DetailsScreen({ route, navigation }) {
  /* 2. Get the param */
  const { itemId } = route.params;
  const { otherParam } = route.params;
    ....

Pour migrer de la version 4 de React Navigation à la 5, voici le lien, principale différence dans la version 5

« In React Navigation 5.x, we have split the navigation prop into 2 props: navigation prop contains helper methods such as navigate, goBack etc., route prop contains the current screen’s data (previously accessed via navigation.state).

In React Navigation 5.x there’s no createAppContainer which provided screens with navigation context. You’ll need to wrap your app with NavigationContainer provider.

Imbrication de routes

On a des creens qui sont contenu dans des navigators, si on a un lien d’un autre navigator, si depuis l’écran SignupScreen, on a un lien vers HistoryScreen, il y aura une erreur, car le screen History n’est pas connu du HomeStack navigator.

<HomeStack.Navigator>
    <HomeStack.Screen name="SignUp" component={SignUpScreen} />
</HomeStack.Navigator>

<ProfileStack.Navigator>
        <ProfileStack.Screen name="Profil" component={ProfileScreen} />
        <ProfileStack.Screen name="History" component={HistoryScreen} />
        <ProfileStack.Screen name="Edit" component={EditScreen} />
</ProfileStack.Navigator>

Pour permettre la navigation inter navigator, il faut déclarer dans le Homestack navigator le screen History

<HomeStack.Navigator>
    <HomeStack.Screen name="SignUp" component={SignUpScreen} />
    <HomeStack.Screen name="History" component={HistoryScreen} />
</HomeStack.Navigator>

<ProfileStack.Navigator>
        <ProfileStack.Screen name="Profil" component={ProfileScreen} />
        <ProfileStack.Screen name="History" component={HistoryScreen} />
        <ProfileStack.Screen name="Edit" component={EditScreen} />
</ProfileStack.Navigator>

Nesting Navigation: https://reactnavigation.org/docs/nesting-navigators/

function Home() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Feed" component={Feed} />
      <Tab.Screen name="Messages" component={Messages} />
    </Tab.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={Home} />
        <Stack.Screen name="Profile" component={Profile} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

PRO TIP : Régler le problème du refresh lors d’un goBack()

React navigation possède un défaut : imaginez que vous soyez dans votre page profile dans une application, vous voulez éditer, et quand l’édition est finie vous revenez visualiser votre page de profile, les informations ne se rafraichissent pas, car le goBack() ne gère pas le rafraichissement.

Voici une méthode pour forcer le rafraichissement de la page profile (qui est la page parente, la page édition de profile étant la page enfant).

Quand vous passez de la page Profile à EditionProfile, vous allez passer une fonction en props, que vous allez exécuter dans la page enfant EditionProfile, juste avant de revenir à la page parente Profile. Cette fonction va muter une variable arbitraire qui existe dans la page parente, comme ça on pourra détecter la mutation de cette variable au sein de notre hook useEffect.

const [foo, setFoo] = useState(1) 

   useEffect(() => {

        fetch(getUserInfoUrl, {
            method: 'GET',
            headers: headers,
        })
            .then(response => {
                return response.json()
            })
            .then(data => {
                console.log(data)
                setUser(data)
            })
        //AJAX LOAD
        setShowLoader(false)

    }, [foo]) /// foo est la variable surveillée par useEffect pour se déclencher, si vous ne savez pas ce qu'est un hook useEffect allez voir la documentation.

La fonction définie dans Profile et passée puis exécutée dans la page EditionProfile (pas dans Profile, oui on peut passer des props fonction dans React)

    const handleOnNavigateBack = () => {
        setFoo(foo + 1)
    }

Dans la page ProfileEdit

...
          onNavigateBack() // exécuter cette fonction va incrémenter foo dans la page parente !
          navigation.navigate('Profil')
...
Retour en haut