Overview
Comment:Nouvelle version 0.9.1 stable
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | stable | 0.9.1
Files: files | file ages | folders
SHA1: 3abf798975c331b899c1f2ef0dddc12def83bd7a
User & Date: bohwaz on 2019-01-22 11:39:01
Other Links: manifest | tags
Context
2019-01-22
12:02
Fix missing foreign_keys check-in: d1d91decbf user: bohwaz tags: trunk, stable, 0.9.1
11:39
Nouvelle version 0.9.1 stable check-in: 3abf798975 user: bohwaz tags: trunk, stable, 0.9.1
11:37
Merge trunk avec dev check-in: 344c04b375 user: bohwaz tags: dev
10:51
Avertissement plus explicite à la clôture check-in: 6b9fc8e8d1 user: bohwaz tags: trunk, stable
Changes

Modified src/VERSION from [37225f3c32] to [1c75e70a1f].

1
0.9.0
|
1
0.9.1

Modified src/config.dist.php from [fd9bfab8c2] to [dcde08c471].

194
195
196
197
198
199
200








201
202
203
204
205
206
207
 * - Apache avec mod_xsendfile (paquet libapache2-mod-xsendfile)
 * - Lighttpd
 *
 * N'activer que si vous êtes sûr que le module est installé et activé (sinon 
 * les fichiers ne pourront être vus ou téléchargés).
 * Nginx n'est PAS supporté, car X-Accel-Redirect ne peut gérer que des fichiers
 * qui sont *dans* le document root du vhost, ce qui n'est pas le cas ici.








 *
 * Défaut : false
 */
const ENABLE_XSENDFILE = false;

/**
 * Serveur NTP utilisé pour les connexions avec TOTP







>
>
>
>
>
>
>
>







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
 * - Apache avec mod_xsendfile (paquet libapache2-mod-xsendfile)
 * - Lighttpd
 *
 * N'activer que si vous êtes sûr que le module est installé et activé (sinon 
 * les fichiers ne pourront être vus ou téléchargés).
 * Nginx n'est PAS supporté, car X-Accel-Redirect ne peut gérer que des fichiers
 * qui sont *dans* le document root du vhost, ce qui n'est pas le cas ici.
 *
 * Pour activer X-SendFile mettre dans la config du virtualhost de Garradin:
 * XSendFile On
 * XSendFilePath /var/www/garradin
 *
 * (remplacer le chemin par le répertoire racine de Garradin)
 *
 * Détails : https://tn123.org/mod_xsendfile/
 *
 * Défaut : false
 */
const ENABLE_XSENDFILE = false;

/**
 * Serveur NTP utilisé pour les connexions avec TOTP

Added src/include/data/0.9.1.sql version [8d911832a5].





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Il manquait une clause ON DELETE SET NULL sur la foreign key
-- de cotisations quand on faisait une mise à jour depuis une
-- ancienne version
ALTER TABLE cotisations RENAME TO cotisations_old;

.read schema.sql

INSERT INTO cotisations SELECT * FROM cotisations_old;

DROP TABLE cotisations_old;

-- Changer le compte des reports automatiques
UPDATE compta_journal SET compte_debit = '890' WHERE compte_debit IS NULL;
UPDATE compta_journal SET compte_credit = '890' WHERE compte_credit IS NULL;

Modified src/include/data/categories_comptables.sql from [c7392a223e] to [7430a75c4a].

1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18
19
20
21
22
INSERT INTO "compta_categories" VALUES(NULL,-1,'Prestations de service','','604');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Achat de marchandises à vendre','Marchandises destinées à être revendues en l''état.','607');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Achat de fournitures consommables','','6068');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Publicité et relations publiques','','623');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Frais de déplacement des membres','Billet SNCF, remboursement de frais kilométrique, etc.','625');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Locations','Locations versées pour un local ou du matériel.','613');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Fournitures non stockables : eau, électricité...','Facture d''eau, d''opérateur électrique, etc.','6061');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Fournitures administratives','Cartouches d''encre, papier, matériel bureautique, etc.','6064');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Frais d''actes et de contentieux','Insertion au Journal Officiel, frais de justice, etc.','6227');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Frais postaux et télécommunications','Facture d''accès à Internet, timbres, etc.','626');

INSERT INTO "compta_categories" VALUES(NULL,-1,'Prime d''assurance','','616');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Services bancaires','','627');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Divers','','658');

INSERT INTO "compta_categories" VALUES(NULL,1,'Vente de produits finis','Vente de produits fabriqués par l''association.','701');
INSERT INTO "compta_categories" VALUES(NULL,1,'Prestation de service','','706');
INSERT INTO "compta_categories" VALUES(NULL,1,'Revente de marchandises','','707');
INSERT INTO "compta_categories" VALUES(NULL,1,'Manifestations diverses','Revenus provenant de manifestations au profit de l''association : droit d''entrée, location d''emplacement en vide grenier, ventes, etc.','7780');
INSERT INTO "compta_categories" VALUES(NULL,1,'Cotisations','','756');
INSERT INTO "compta_categories" VALUES(NULL,1,'Dons et collectes','','754');
INSERT INTO "compta_categories" VALUES(NULL,1,'Subventions','','740');
INSERT INTO "compta_categories" VALUES(NULL,1,'Divers','','758');










>












1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
INSERT INTO "compta_categories" VALUES(NULL,-1,'Prestations de service','','604');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Achat de marchandises à vendre','Marchandises destinées à être revendues en l''état.','607');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Achat de fournitures consommables','','6068');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Publicité et relations publiques','','623');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Frais de déplacement des membres','Billet SNCF, remboursement de frais kilométrique, etc.','625');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Locations','Locations versées pour un local ou du matériel.','613');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Fournitures non stockables : eau, électricité...','Facture d''eau, d''opérateur électrique, etc.','6061');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Fournitures administratives','Cartouches d''encre, papier, matériel bureautique, etc.','6064');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Frais d''actes et de contentieux','Insertion au Journal Officiel, frais de justice, etc.','6227');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Frais postaux et télécommunications','Facture d''accès à Internet, timbres, etc.','626');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Licences fédérales','Licences payées pour les adhérents (par exemple fédération sportive etc.)','652');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Prime d''assurance','','616');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Services bancaires','','627');
INSERT INTO "compta_categories" VALUES(NULL,-1,'Divers','','658');

INSERT INTO "compta_categories" VALUES(NULL,1,'Vente de produits finis','Vente de produits fabriqués par l''association.','701');
INSERT INTO "compta_categories" VALUES(NULL,1,'Prestation de service','','706');
INSERT INTO "compta_categories" VALUES(NULL,1,'Revente de marchandises','','707');
INSERT INTO "compta_categories" VALUES(NULL,1,'Manifestations diverses','Revenus provenant de manifestations au profit de l''association : droit d''entrée, location d''emplacement en vide grenier, ventes, etc.','7780');
INSERT INTO "compta_categories" VALUES(NULL,1,'Cotisations','','756');
INSERT INTO "compta_categories" VALUES(NULL,1,'Dons et collectes','','754');
INSERT INTO "compta_categories" VALUES(NULL,1,'Subventions','','740');
INSERT INTO "compta_categories" VALUES(NULL,1,'Divers','','758');

Modified src/include/data/plan_comptable.json from [a0d7ad88ed] to [4d7e33a414].

1387
1388
1389
1390
1391
1392
1393






1394
1395
1396
1397
1398
1399
1400
    },
    "65": {
        "code": 65,
        "nom": "AUTRES CHARGES DE GESTION COURANTE",
        "parent": 6,
        "position": 8
    },






    "658": {
        "code": 658,
        "nom": "Charges diverses de gestion courante",
        "parent": 65,
        "position": 8
    },
    "66": {







>
>
>
>
>
>







1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
    },
    "65": {
        "code": 65,
        "nom": "AUTRES CHARGES DE GESTION COURANTE",
        "parent": 6,
        "position": 8
    },
    "652": {
        "code": 652,
        "nom": "Licences fédérales",
        "parent": 652,
        "position": 8
    },
    "658": {
        "code": 658,
        "nom": "Charges diverses de gestion courante",
        "parent": 65,
        "position": 8
    },
    "66": {
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
        "code": 797,
        "nom": "Transferts de charges exceptionnels",
        "parent": 79,
        "position": 4
    },
    "8": {
        "code": 8,
        "nom": "Classe 8 \u00ad\u2014 Contributions b\u00e9n\u00e9voles en nature",
        "parent": 0,
        "position": 12
    },
    "86": {
        "code": 86,
        "nom": "R\u00c9PARTITION PAR NATURE DE CHARGES",
        "parent": 8,







|







1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
        "code": 797,
        "nom": "Transferts de charges exceptionnels",
        "parent": 79,
        "position": 4
    },
    "8": {
        "code": 8,
        "nom": "Classe 8 \u00ad\u2014 Comptes sp\u00e9ciaux",
        "parent": 0,
        "position": 12
    },
    "86": {
        "code": 86,
        "nom": "R\u00c9PARTITION PAR NATURE DE CHARGES",
        "parent": 8,
1723
1724
1725
1726
1727
1728
1729


















1730
1731
1732
1733
1734
1735
1736
    },
    "875": {
        "code": 875,
        "nom": "Dons en nature",
        "parent": 87,
        "position": 4
    },


















    "9": {
        "code": 9,
        "nom": "Classe 9 \u2014 Comptes analytiques",
        "parent": 0,
        "position": 12
    }
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
    },
    "875": {
        "code": 875,
        "nom": "Dons en nature",
        "parent": 87,
        "position": 4
    },
    "89": {
        "code": 89,
        "nom": "BILAN",
        "parent": 8,
        "position": 3
    },
    "890": {
        "code": 890,
        "nom": "Bilan d'ouverture",
        "parent": 89,
        "position": 3
    },
    "890": {
        "code": 891,
        "nom": "Bilan de clôture",
        "parent": 89,
        "position": 3
    },
    "9": {
        "code": 9,
        "nom": "Classe 9 \u2014 Comptes analytiques",
        "parent": 0,
        "position": 12
    }
}

Modified src/include/init.php from [b52a5657db] to [2707b697be].

122
123
124
125
126
127
128

129
130
131
132
133
134
135
    {
        define($const, $value);
    }
}

const WEBSITE = 'https://garradin.eu/';
const PLUGINS_URL = 'https://garradin.eu/plugins/list.json';


// PHP devrait être assez intelligent pour chopper la TZ système mais nan
// il sait pas faire (sauf sur Debian qui a le bon patch pour ça), donc pour 
// éviter le message d'erreur à la con on définit une timezone par défaut
// Pour utiliser une autre timezone, il suffit de définir date.timezone dans
// un .htaccess ou dans config.local.php
if (!ini_get('date.timezone'))







>







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
    {
        define($const, $value);
    }
}

const WEBSITE = 'https://garradin.eu/';
const PLUGINS_URL = 'https://garradin.eu/plugins/list.json';
const DEFAULT_REPORT_URL = 'http://henga.test/report/?p=ABCD';

// PHP devrait être assez intelligent pour chopper la TZ système mais nan
// il sait pas faire (sauf sur Debian qui a le bon patch pour ça), donc pour 
// éviter le message d'erreur à la con on définit une timezone par défaut
// Pour utiliser une autre timezone, il suffit de définir date.timezone dans
// un .htaccess ou dans config.local.php
if (!ini_get('date.timezone'))
220
221
222
223
224
225
226
227




228
229
230
231
232
233
234
    'rootDirectory'      => ROOT,
    'garradin_data_root' => DATA_ROOT,
    'garradin_version'   => garradin_version(),
]);

if (ERRORS_REPORT_URL)
{
    ErrorManager::setRemoteReporting(ERRORS_REPORT_URL, false);




}

ErrorManager::setProductionErrorTemplate('<!DOCTYPE html><html><head><title>Erreur interne</title>
    <style type="text/css">
    body {font-family: sans-serif; }
    code, p, h1 { max-width: 400px; margin: 1em auto; display: block; }
    code { text-align: right; color: #666; }







|
>
>
>
>







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
    'rootDirectory'      => ROOT,
    'garradin_data_root' => DATA_ROOT,
    'garradin_version'   => garradin_version(),
]);

if (ERRORS_REPORT_URL)
{
    ErrorManager::setRemoteReporting(ERRORS_REPORT_URL, true);
}
else
{
    ErrorManager::setRemoteReporting(DEFAULT_REPORT_URL, false);
}

ErrorManager::setProductionErrorTemplate('<!DOCTYPE html><html><head><title>Erreur interne</title>
    <style type="text/css">
    body {font-family: sans-serif; }
    code, p, h1 { max-width: 400px; margin: 1em auto; display: block; }
    code { text-align: right; color: #666; }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
    vertical-align: top; }
    input { padding: .3em; margin: .5em; font-size: 1.2em; cursor: pointer; }
</style>
<pre id="icn"> \__/<br /> (xx)<br />//||\\\\</pre>
<section>
    <article>
    <h1>Une erreur s\'est produite</h1>
    <if(report)><form method="post" action="https://garradin.eu/report/"><p><input type="hidden" name="report" value="{$report_json}" /><input type="submit" value="Rapporter l\'erreur aux développeur⋅euses de Garradin &rarr;" /></p></form></if>
    </article>
</section>
');

function user_error($e)
{
    if (PHP_SAPI == 'cli')







|







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    vertical-align: top; }
    input { padding: .3em; margin: .5em; font-size: 1.2em; cursor: pointer; }
</style>
<pre id="icn"> \__/<br /> (xx)<br />//||\\\\</pre>
<section>
    <article>
    <h1>Une erreur s\'est produite</h1>
    <if(report)><form method="post" action="{$report_url}"><p><input type="hidden" name="report" value="{$report_json}" /><input type="submit" value="Rapporter l\'erreur aux développeur⋅euses de Garradin &rarr;" /></p></form></if>
    </article>
</section>
');

function user_error($e)
{
    if (PHP_SAPI == 'cli')

Modified src/include/lib/Garradin/Compta/Exercices.php from [a2ca824f36] to [7a15675417].

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

            // Solde du compte à zéro : aucun report à faire
            if (empty($solde))
            {
                continue;
            }

            $compte_debit = $solde < 0 ? NULL : $row['compte'];
            $compte_credit = $solde > 0 ? NULL : $row['compte'];

            $diff += $solde;
            $solde = round(abs($solde), 2);

            // Chaque solde de compte est reporté dans le nouvel exercice
            $journal->add([
                'libelle'       =>  'Report à nouveau',







|
|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

            // Solde du compte à zéro : aucun report à faire
            if (empty($solde))
            {
                continue;
            }

            $compte_debit = $solde < 0 ? 890 : $row['compte'];
            $compte_credit = $solde > 0 ? 890 : $row['compte'];

            $diff += $solde;
            $solde = round(abs($solde), 2);

            // Chaque solde de compte est reporté dans le nouvel exercice
            $journal->add([
                'libelle'       =>  'Report à nouveau',
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
        if ($resultat != 0)
        {
            $journal = new Journal;
            $journal->add([
                'libelle'   =>  'Résultat de l\'exercice précédent',
                'date'      =>  $date,
                'montant'   =>  abs($resultat),
                'compte_debit'  =>  $resultat < 0 ? $resultat_debiteur : NULL,
                'compte_credit' =>  $resultat > 0 ? $resultat_excedent : NULL,
            ]);
        }

        return true;
    }
    
    public function delete($id)
    {
        $db = DB::getInstance();

        // Ne pas supprimer un compte qui est utilisé !
        if ($db->test('compta_journal', $db->where('id_exercice', $id)))
        {







|
|





|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
        if ($resultat != 0)
        {
            $journal = new Journal;
            $journal->add([
                'libelle'   =>  'Résultat de l\'exercice précédent',
                'date'      =>  $date,
                'montant'   =>  abs($resultat),
                'compte_debit'  =>  $resultat < 0 ? $resultat_debiteur : 890,
                'compte_credit' =>  $resultat > 0 ? $resultat_excedent : 890,
            ]);
        }

        return true;
    }

    public function delete($id)
    {
        $db = DB::getInstance();

        // Ne pas supprimer un compte qui est utilisé !
        if ($db->test('compta_journal', $db->where('id_exercice', $id)))
        {

Modified src/include/lib/Garradin/DB.php from [41264a6c51] to [5b61f7e017].

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    }

    public function connect()
    {
        if (parent::connect())
        {
            // Activer les contraintes des foreign keys
            $this->db->exec('PRAGMA foreign_keys = ON;');

            // 10 secondes
            $this->db->busyTimeout(10 * 1000);
            $this->db->exec('PRAGMA journal_mode = TRUNCATE;');

            $this->db->createFunction('transliterate_to_ascii', ['Garradin\Utils', 'transliterateToAscii']);
        }
    }

    public function close()
    {







|



|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    }

    public function connect()
    {
        if (parent::connect())
        {
            // Activer les contraintes des foreign keys
            $this->exec('PRAGMA foreign_keys = ON;');

            // 10 secondes
            $this->db->busyTimeout(10 * 1000);
            $this->exec('PRAGMA journal_mode = TRUNCATE;');

            $this->db->createFunction('transliterate_to_ascii', ['Garradin\Utils', 'transliterateToAscii']);
        }
    }

    public function close()
    {
76
77
78
79
80
81
82
83
84
85

        $dir = dirname($file);

        $sql = preg_replace_callback('/^\.read (.+\.sql)$/m', function ($match) use ($dir) {
            return file_get_contents($dir . DIRECTORY_SEPARATOR . $match[1]) . "\n";
        }, $sql);

        return $this->db->exec($sql);
    }
}







|


76
77
78
79
80
81
82
83
84
85

        $dir = dirname($file);

        $sql = preg_replace_callback('/^\.read (.+\.sql)$/m', function ($match) use ($dir) {
            return file_get_contents($dir . DIRECTORY_SEPARATOR . $match[1]) . "\n";
        }, $sql);

        return $this->exec($sql);
    }
}

Modified src/include/lib/Garradin/Membres/Session.php from [ad925c9b8d] to [c1e59c0b68].

25
26
27
28
29
30
31


32
33
34
35
36
37
38

	const MINIMUM_PASSWORD_LENGTH = 8;

	// Extension des méthodes de UserSession
	public function __construct()
	{
		$url = parse_url(ADMIN_URL);



		parent::__construct(DB::getInstance(), [
			'cookie_domain' => $url['host'],
			'cookie_path'   => preg_replace('!/admin/$!', '/', $url['path']),
			'cookie_secure' => (\Garradin\PREFER_HTTPS >= 2) ? true : false,
		]);
	}







>
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

	const MINIMUM_PASSWORD_LENGTH = 8;

	// Extension des méthodes de UserSession
	public function __construct()
	{
		$url = parse_url(ADMIN_URL);

		//throw new \Exception('lol');

		parent::__construct(DB::getInstance(), [
			'cookie_domain' => $url['host'],
			'cookie_path'   => preg_replace('!/admin/$!', '/', $url['path']),
			'cookie_secure' => (\Garradin\PREFER_HTTPS >= 2) ? true : false,
		]);
	}

Modified src/templates/admin/compta/operations/voir.tpl from [eaf9901138] to [48d792da66].

1
2
3
4
5
6
7
8
9
10
{include file="admin/_head.tpl" title="Opération n°%d"|args:$operation.id current="compta/gestion"}

{if $session->canAccess('compta', Membres::DROIT_ADMIN) && $operation.compte_credit !== null && $operation.compte_debit !== null}
<ul class="actions">
    <li class="edit"><a href="{$admin_url}compta/operations/modifier.php?id={$operation.id}">Modifier cette opération</a></li>
    <li class="delete"><a href="{$admin_url}compta/operations/supprimer.php?id={$operation.id}">Supprimer cette opération</a></li>
</ul>
{/if}

<dl class="describe">


|







1
2
3
4
5
6
7
8
9
10
{include file="admin/_head.tpl" title="Opération n°%d"|args:$operation.id current="compta/gestion"}

{if $session->canAccess('compta', Membres::DROIT_ADMIN)}
<ul class="actions">
    <li class="edit"><a href="{$admin_url}compta/operations/modifier.php?id={$operation.id}">Modifier cette opération</a></li>
    <li class="delete"><a href="{$admin_url}compta/operations/supprimer.php?id={$operation.id}">Supprimer cette opération</a></li>
</ul>
{/if}

<dl class="describe">

Modified src/www/admin/compta/operations/modifier.php from [dcffa78b60] to [6e0e877ba5].

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$operation = $journal->get(qg('id'));

if (!$operation)
{
    throw new UserException("L'opération demandée n'existe pas.");
}

if ($operation->compte_credit === null)
{
    throw new UserException('Impossible de modifier une écriture de report.');
}

if ($operation->id_categorie)
{
    $categorie = $cats->get($operation->id_categorie);
}
else
{
    $categorie = false;







<
<
<
<
<







12
13
14
15
16
17
18





19
20
21
22
23
24
25
$operation = $journal->get(qg('id'));

if (!$operation)
{
    throw new UserException("L'opération demandée n'existe pas.");
}






if ($operation->id_categorie)
{
    $categorie = $cats->get($operation->id_categorie);
}
else
{
    $categorie = false;

Modified src/www/admin/upgrade.php from [16f61c74de] to [92ea3090d6].

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

Static_Cache::store('upgrade', 'Mise à jour en cours.');

$db = DB::getInstance();
$redirect = true;

// Créer une sauvegarde automatique
(new Sauvegarde)->create('pre-upgrade-' . garradin_version());

echo '<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, target-densitydpi=device-dpi" />
    <link rel="stylesheet" type="text/css" href="static/admin.css" media="all" />







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

Static_Cache::store('upgrade', 'Mise à jour en cours.');

$db = DB::getInstance();
$redirect = true;

// Créer une sauvegarde automatique
$backup_name = (new Sauvegarde)->create('pre-upgrade-' . garradin_version());

echo '<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, target-densitydpi=device-dpi" />
    <link rel="stylesheet" type="text/css" href="static/admin.css" media="all" />
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249















250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275









276
277
278
279
280
281
282
<div id="loader" class="loader" style="margin: 2em 0; height: 50px;"></div>
<script>
animatedLoader(document.getElementById("loader"), 5);
</script>';

flush();


if (version_compare($v, '0.7.0', '<'))
{
    $db->exec('PRAGMA foreign_keys = OFF; BEGIN;');

    // Mise à jour base de données
    $db->exec(file_get_contents(ROOT . '/include/data/0.7.0.sql'));

    // Changement de syntaxe du Wiki vers SkrivML
    $wiki = new Wiki;
    $res = $db->get('SELECT id_page, contenu, revision, chiffrement FROM wiki_revisions GROUP BY id_page ORDER BY revision DESC;');

    foreach ($res as $row)
    {
        // Ne pas convertir le contenu chiffré, de toute évidence
        if ($row->chiffrement)
            continue;

        $content = $row->contenu;
        $content = Utils::HTMLToSkriv($content);
        $content = Utils::SpipToSkriv($content);

        if ($content != $row->contenu)
        {
            $wiki->editRevision($row->id_page, $row->revision, [
                'id_auteur'     =>  null,
                'contenu'       =>  $content,
                'modification'  =>  'Mise à jour 0.7.0 (transformation SPIP vers SkrivML)',
            ]);
        }
    }

    $db->exec('END;');
}

if (version_compare($v, '0.7.2', '<'))
{
    $db->exec('PRAGMA foreign_keys = OFF; BEGIN;');

    // Mise à jour base de données
    $db->exec(file_get_contents(ROOT . '/include/data/0.7.2.sql'));

    $db->exec('END;');
}

if (version_compare($v, '0.8.0-beta4', '<'))
{
    // Inscription de l'appid
    $db->exec('PRAGMA application_id = ' . DB::APPID . ';');

    // Changement de la taille de pagesize
    // Cecit devrait améliorer les performances de la DB
    $db->exec('PRAGMA page_size = 4096;');

    // Application du changement de taille de page
    $db->exec('VACUUM;');

    // Désactivation des foreign keys AVANT le début de la transaction
    $db->exec('PRAGMA foreign_keys = OFF;');

    $db->begin();

    $db->import(ROOT . '/include/data/0.8.0.sql');

    $db->commit();

    $config = Config::getInstance();

    // Ajout champ numéro de membre
    $champs = (array) $config->get('champs_membres')->getAll();
    $presets = Membres\Champs::importPresets();

    // Ajout du numéro au début
    $champs = array_merge(['numero' => $presets['numero']], $champs);
    (new Membres\Champs($champs))->save();

    // Si l'ID était l'identificant, utilisons le numéro de membre à la place
    if ($config->get('champ_identifiant') == 'id')
    {
        $config->set('champ_identifiant', 'numero');
        $config->save();
    }

    // Nettoyage de la base de données
    $db->exec('VACUUM;');

    // Mise à jour plan comptable: ajout comptes encaissement
    $comptes = new Compta\Comptes;
    $comptes->importPlan();
}

if (version_compare($v, '0.8.3', '<'))
{
    // Désactivation des foreign keys AVANT le début de la transaction
    $db->exec('PRAGMA foreign_keys = OFF;');

    $db->begin();

    $db->import(ROOT . '/include/data/0.8.3.sql');

    $db->commit();
}

if (version_compare($v, '0.8.4', '<'))
{
    $db->begin();

    $db->import(ROOT . '/include/data/0.8.4.sql');

    $db->commit();
}

if (version_compare($v, '0.9.0-rc1', '<'))
{
    $db->exec('PRAGMA foreign_keys = OFF;');
    $db->begin();

    $db->import(ROOT . '/include/data/0.9.0.sql');

    // Correction des ID parents des comptes qui ont été mal renseignés
    // exemple : compte 512A avec "5" comme parent (c'était permis,
    // par erreur, par le formulaire d'ajout de compte dans le plan)
    // Serait probablement possible en 3-4 lignes de SQL avec
    // WITH RECURSIVE mais c'est au delà de mes compétences
    $comptes = $db->iterate('SELECT id FROM compta_comptes WHERE parent != length(id) - 1;');

    foreach ($comptes as $compte)
    {
        $parent = false;
        $id = $compte->id;

        while (!$parent && strlen($id))
        {
            // On enlève un caractère à la fin jusqu'à trouver un compte parent correspondant
            $id = substr($id, 0, -1);
            $parent = $db->firstColumn('SELECT id FROM compta_comptes WHERE id = ?;', $id);
        }

        if (!$parent)
        {
            // Situation normalement impossible !
            throw new \LogicException(sprintf('Le compte %s est invalide et n\'a pas de compte parent possible !', $compte->id));
        }

        $db->update('compta_comptes', ['parent' => $parent], 'id = :id', ['id' => $compte->id]);
    }

    $champs = $config->get('champs_membres');

    if ($champs->get('lettre_infos'))
    {
        // Ajout d'une recherche avancée en exemple
        $query = [
            'query' => [[
                'operator' => 'AND',
                'conditions' => [
                    [
                        'column'   => 'lettre_infos',
                        'operator' => '= 1',
                        'values'   => [],
                    ],
                ],
            ]],
            'order' => 'numero',
            'desc' => true,
            'limit' => '10000',
        ];

        $recherche = new Recherche;
        $recherche->add('Membres inscrits à la lettre d\'information', null, $recherche::TYPE_JSON, 'membres', $query);
    }

    $db->commit();

    $config->set('desactiver_site', false);
    $config->save();
}
















Utils::clearCaches();

$config->setVersion(garradin_version());

Static_Cache::remove('upgrade');

// Réinstaller les plugins système si nécessaire
Plugin::checkAndInstallSystemPlugins();

// Mettre à jour les plugins si nécessaire
foreach (Plugin::listInstalled() as $id=>$infos)
{
    // Ne pas tenir compte des plugins dont le code n'est pas dispo
    if ($infos->disabled)
    {
        continue;
    }

    $plugin = new Plugin($id);

    if ($plugin->needUpgrade())
    {
        $plugin->upgrade();
    }

    unset($plugin);









}

// Forcer à rafraîchir les données de la session si elle existe
if ($user_is_logged)
{
    $session->refresh();
}







|
|
|
|

|
|

|
|
|

|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|

|
|

|
|
|

|
|

|
|

|
|
|
|

|
|
|

|
|

|
|

|

|

|

|

|
|
|

|
|
|

|
|
|
|
|
|

|
|

|
|
|
|

|
|
|
|

|

|

|
|

|
|
|

|

|
|

|
|
|
|

|

|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|
|

|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|

|

|
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|

|

|
|

|
|
|
|
|
|
|
|

|

|
|
|
|

|
>
>
>
>
>
>
>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
<div id="loader" class="loader" style="margin: 2em 0; height: 50px;"></div>
<script>
animatedLoader(document.getElementById("loader"), 5);
</script>';

flush();

try {
    if (version_compare($v, '0.7.0', '<'))
    {
        $db->exec('PRAGMA foreign_keys = OFF; BEGIN;');

        // Mise à jour base de données
        $db->exec(file_get_contents(ROOT . '/include/data/0.7.0.sql'));

        // Changement de syntaxe du Wiki vers SkrivML
        $wiki = new Wiki;
        $res = $db->get('SELECT id_page, contenu, revision, chiffrement FROM wiki_revisions GROUP BY id_page ORDER BY revision DESC;');

        foreach ($res as $row)
        {
            // Ne pas convertir le contenu chiffré, de toute évidence
            if ($row->chiffrement)
                continue;

            $content = $row->contenu;
            $content = Utils::HTMLToSkriv($content);
            $content = Utils::SpipToSkriv($content);

            if ($content != $row->contenu)
            {
                $wiki->editRevision($row->id_page, $row->revision, [
                    'id_auteur'     =>  null,
                    'contenu'       =>  $content,
                    'modification'  =>  'Mise à jour 0.7.0 (transformation SPIP vers SkrivML)',
                ]);
            }
        }

        $db->exec('END;');
    }

    if (version_compare($v, '0.7.2', '<'))
    {
        $db->exec('PRAGMA foreign_keys = OFF; BEGIN;');

        // Mise à jour base de données
        $db->exec(file_get_contents(ROOT . '/include/data/0.7.2.sql'));

        $db->exec('END;');
    }

    if (version_compare($v, '0.8.0-beta4', '<'))
    {
        // Inscription de l'appid
        $db->exec('PRAGMA application_id = ' . DB::APPID . ';');

        // Changement de la taille de pagesize
        // Cecit devrait améliorer les performances de la DB
        $db->exec('PRAGMA page_size = 4096;');

        // Application du changement de taille de page
        $db->exec('VACUUM;');

        // Désactivation des foreign keys AVANT le début de la transaction
        $db->exec('PRAGMA foreign_keys = OFF;');

        $db->begin();

        $db->import(ROOT . '/include/data/0.8.0.sql');

        $db->commit();

        $config = Config::getInstance();

        // Ajout champ numéro de membre
        $champs = (array) $config->get('champs_membres')->getAll();
        $presets = Membres\Champs::importPresets();

        // Ajout du numéro au début
        $champs = array_merge(['numero' => $presets['numero']], $champs);
        (new Membres\Champs($champs))->save();

        // Si l'ID était l'identificant, utilisons le numéro de membre à la place
        if ($config->get('champ_identifiant') == 'id')
        {
            $config->set('champ_identifiant', 'numero');
            $config->save();
        }

        // Nettoyage de la base de données
        $db->exec('VACUUM;');

        // Mise à jour plan comptable: ajout comptes encaissement
        $comptes = new Compta\Comptes;
        $comptes->importPlan();
    }

    if (version_compare($v, '0.8.3', '<'))
    {
        // Désactivation des foreign keys AVANT le début de la transaction
        $db->exec('PRAGMA foreign_keys = OFF;');

        $db->begin();

        $db->import(ROOT . '/include/data/0.8.3.sql');

        $db->commit();
    }

    if (version_compare($v, '0.8.4', '<'))
    {
        $db->begin();

        $db->import(ROOT . '/include/data/0.8.4.sql');

        $db->commit();
    }

    if (version_compare($v, '0.9.0-rc1', '<'))
    {
        $db->exec('PRAGMA foreign_keys = OFF;');
        $db->begin();

        $db->import(ROOT . '/include/data/0.9.0.sql');

        // Correction des ID parents des comptes qui ont été mal renseignés
        // exemple : compte 512A avec "5" comme parent (c'était permis,
        // par erreur, par le formulaire d'ajout de compte dans le plan)
        // Serait probablement possible en 3-4 lignes de SQL avec
        // WITH RECURSIVE mais c'est au delà de mes compétences
        $comptes = $db->iterate('SELECT id FROM compta_comptes WHERE parent != length(id) - 1;');

        foreach ($comptes as $compte)
        {
            $parent = false;
            $id = $compte->id;

            while (!$parent && strlen($id))
            {
                // On enlève un caractère à la fin jusqu'à trouver un compte parent correspondant
                $id = substr($id, 0, -1);
                $parent = $db->firstColumn('SELECT id FROM compta_comptes WHERE id = ?;', $id);
            }

            if (!$parent)
            {
                // Situation normalement impossible !
                throw new \LogicException(sprintf('Le compte %s est invalide et n\'a pas de compte parent possible !', $compte->id));
            }

            $db->update('compta_comptes', ['parent' => $parent], 'id = :id', ['id' => $compte->id]);
        }

        $champs = $config->get('champs_membres');

        if ($champs->get('lettre_infos'))
        {
            // Ajout d'une recherche avancée en exemple
            $query = [
                'query' => [[
                    'operator' => 'AND',
                    'conditions' => [
                        [
                            'column'   => 'lettre_infos',
                            'operator' => '= 1',
                            'values'   => [],
                        ],
                    ],
                ]],
                'order' => 'numero',
                'desc' => true,
                'limit' => '10000',
            ];

            $recherche = new Recherche;
            $recherche->add('Membres inscrits à la lettre d\'information', null, $recherche::TYPE_JSON, 'membres', $query);
        }

        $db->commit();

        $config->set('desactiver_site', false);
        $config->save();
    }

    if (version_compare($v, '0.9.1', '<'))
    {
        // Mise à jour plan comptable: ajout compte licences fédérales
        $comptes = new Compta\Comptes;
        $comptes->importPlan();

        $db->begin();

        $db->exec('INSERT INTO "compta_categories" VALUES(NULL,-1,\'Licences fédérales\',\'Licences payées pour les adhérents (par exemple fédération sportive etc.)\',\'652\');');

        $db->import(ROOT . '/include/data/0.9.1.sql');

        $db->commit();
    }

    Utils::clearCaches();

    $config->setVersion(garradin_version());

    Static_Cache::remove('upgrade');

    // Réinstaller les plugins système si nécessaire
    Plugin::checkAndInstallSystemPlugins();

    // Mettre à jour les plugins si nécessaire
    foreach (Plugin::listInstalled() as $id=>$infos)
    {
        // Ne pas tenir compte des plugins dont le code n'est pas dispo
        if ($infos->disabled)
        {
            continue;
        }

        $plugin = new Plugin($id);

        if ($plugin->needUpgrade())
        {
            $plugin->upgrade();
        }

        unset($plugin);
    }
}
catch (\Exception $e)
{
    $s = new Sauvegarde;
    $s->restoreFromLocal($backup_name);
    $s->remove($backup_name);
    Static_Cache::remove('upgrade');
    throw $e;
}

// Forcer à rafraîchir les données de la session si elle existe
if ($user_is_logged)
{
    $session->refresh();
}