Subversion Repositories eFlore/Applications.cel

Compare Revisions

No changes between revisions

Ignore whitespace Rev 2448 → Rev 2447

/trunk/jrest/tests/cmd-test.php
New file
0,0 → 1,80
#!/usr/bin/env php
<?php
 
define('DEFAULT_DOMAIN', 'http://cel');
define('DEFAULT_USER', 22506);
 
$options = getopt("hiou:d:e:p:FU:P:D",array("help", "images", "obs", "user:", "domain:", "email:", "pass:", "flush", "upload:", "phpsessid", "debug"));
if(isset($options['h']) || isset($options['help'])) die(__help());
 
 
if(isset($options['u'])) define('USER', $options['u']);
elseif(isset($options['user'])) define('USER', $options['user']);
 
define('DOMAIN', isset($options['d']) ? $options['d'] : (isset($options['domain']) ? $options['domain'] : DEFAULT_DOMAIN));
define('EMAIL', isset($options['e']) ? $options['e'] : (isset($options['email']) ? $options['email'] : NULL));
define('PASS', isset($options['p']) ? $options['p'] : (isset($options['pass']) ? $options['pass'] : NULL));
define('DEBUG', isset($options['D']) ? 1 : (isset($options['debug']) ? 1 : 0));
 
if (isset($options['P'])) define('COOKIE', $options['P']);
elseif (isset($options['phpsessid'])) define('COOKIE', $options['phpsessid']);
 
// API::auth() define()'s COOKIE
require_once('api.php');
 
if(!defined('USER')) auth();
if(!defined('USER')) define('USER', DEFAULT_USER);
 
 
if(isset($options['o']) || isset($options['obs']) || isset($options['F']) || isset($options['flush'])) {
cel_delete_all_obs();
}
 
if(isset($options['i']) || isset($options['images']) || isset($options['F']) || isset($options['flush'])) {
cel_delete_all_images();
}
 
$upload = isset($options['U']) ? $options['U'] : (isset($options['upload']) ? $options['upload'] : NULL);
if($upload) cel_upload_image($upload);
 
if(! defined('COOKIE')) { if(!auth()) die('no auth'); }
 
 
// $csv = genCSV(array('ordre' => 1, 'Date' => '23/06/1991', 'rien' => 'rien'));
var_dump(getCSV_line(export(), 1));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
function __help() {
$m = sprintf(
<<<EOF
%1\$s -i|--images -o|--obs -F|--flush
Supprime les images ou les observations, ou les deux, de l'utilisateur donné sur le CEL donné.
 
Options:
%1\$s [-u|--user = %3\$d] [-d|--domain = %2\$s] [-e|--email] [-p|--pass mot de passe] [-P|--phpsessid PHPSESSID]
La priorité est donnée à -P sur le couple (-e , -p) pour l'authentification, eg:
$ sqlite3 .mozilla/firefox/*.default/cookies.sqlite<<<"SELECT * FROM moz_cookies WHERE baseDomain = 'cel' AND name = 'PHPSESSID';"
 
%1\$s -U|--upload <file>
Upload le fichier "file".
 
EOF
, // */
basename(__FILE__),
DEFAULT_DOMAIN,
DEFAULT_USER);
die($m);
}
/trunk/jrest/tests/bin/csv2xls
New file
0,0 → 1,203
#!/usr/bin/env perl
 
# csv2xls: Convert csv to xls
# (m)'11 [06 Oct 2011] Copyright H.M.Brand 2007-2013
 
use strict;
use warnings;
 
our $VERSION = "1.71";
 
sub usage
{
my $err = shift and select STDERR;
print <<EOU;
usage: csv2xls [-s <sep>] [-q <quot>] [-w <width>] [-d <dtfmt>]
[-o <xls>] [file.csv]
-s <sep> use <sep> as seperator char. Auto-detect, default = ','
The string "tab" is allowed.
-e <esc> use <sep> as seperator char. Auto-detect, default = ','
The string "undef" is allowed.
-q <quot> use <quot> as quotation char. Default = '"'
The string "undef" will disable quotation.
-w <width> use <width> as default minimum column width (4)
-o <xls> write output to file named <xls>, defaults
to input file name with .csv replaced with .xls
if from standard input, defaults to csv2xls.xls
-F allow formula's. Otherwise fields starting with
an equal sign are forced to string
-f force usage of <xls> if already exists (unlink before use)
-d <dtfmt> use <dtfmt> as date formats. Default = 'dd-mm-yyyy'
-D cols only convert dates in columns <cols>. Default is everywhere.
-u CSV is UTF8
-v [<lvl>] verbosity (default = 1)
EOU
exit $err;
} # usage
 
use Getopt::Long qw(:config bundling nopermute passthrough);
my $sep; # Set after reading first line in a flurry attempt to auto-detect
my $quo = '"';
my $esc = '"';
my $wdt = 4; # Default minimal column width
my $xls; # Excel out file name
my $frc = 0; # Force use of file
my $utf = 0; # Data is encoded in Unicode
my $frm = 0; # Allow formula's
my $dtf = "dd-mm-yyyy"; # Date format
my $opt_v = 1;
my $dtc;
 
GetOptions (
"help|?" => sub { usage (0); },
 
"c|s=s" => \$sep,
"q=s" => \$quo,
"e=s" => \$esc,
"w=i" => \$wdt,
"o|x=s" => \$xls,
"d=s" => \$dtf,
"D=s" => \$dtc,
"f" => \$frc,
"F" => \$frm,
"u" => \$utf,
"v:1" => \$opt_v,
) or usage (1);
 
my $title = @ARGV && -f $ARGV[0] ? $ARGV[0] : "csv2xls";
($xls ||= $title) =~ s/(?:\.csv)?$/.xls/i;
 
-s $xls && $frc and unlink $xls;
if (-s $xls) {
print STDERR "File '$xls' already exists. Overwrite? [y/N] > N\b";
scalar <STDIN> =~ m/^[yj](es|a)?$/i or exit;
}
 
# Don't split ourselves when modules do it _much_ better, and follow the standards
use Text::CSV_XS;
use Date::Calc qw( Delta_Days Days_in_Month );
use Spreadsheet::WriteExcel;
use Encode qw( from_to );
 
my $csv;
 
my $wbk = Spreadsheet::WriteExcel->new ($xls);
my $wks = $wbk->add_worksheet ();
$dtf =~ s/j/y/g;
my %fmt = (
date => $wbk->add_format (
num_format => $dtf,
align => "center",
),
 
rest => $wbk->add_format (
align => "left",
),
);
 
my ($h, $w, @w) = (0, 1); # data height, -width, and default column widths
my $row;
my $firstline;
unless ($sep) { # No sep char passed, try to auto-detect;
while (<>) {
m/\S/ or next; # Skip empty leading blank lines
$sep = # start auto-detect with quoted strings
m/["\d];["\d;]/ ? ";" :
m/["\d],["\d,]/ ? "," :
m/["\d]\t["\d,]/ ? "\t" :
# If neither, then for unquoted strings
m/\w;[\w;]/ ? ";" :
m/\w,[\w,]/ ? "," :
m/\w\t[\w,]/ ? "\t" :
";" ;
# Yeah I know it should be a ',' (hence Csv), but the majority
# of the csv files to be shown comes from fucking Micky$hit,
# that uses semiColon ';' instead.
$firstline = $_;
last;
}
}
$csv = Text::CSV_XS-> new ({
sep_char => $sep eq "tab" ? "\t" : $sep,
quote_char => $quo eq "undef" ? undef : $quo,
escape_char => $esc eq "undef" ? undef : $esc,
binary => 1,
keep_meta_info => 1,
auto_diag => 1,
});
if ($firstline) {
$csv->parse ($firstline) or die $csv->error_diag ();
$row = [ $csv->fields ];
}
if ($opt_v > 3) {
foreach my $k (qw( sep_char quote_char escape_char )) {
my $c = $csv->$k () || "undef";
$c =~ s/\t/\\t/g;
$c =~ s/\r/\\r/g;
$c =~ s/\n/\\n/g;
$c =~ s/\0/\\0/g;
$c =~ s/([\x00-\x1f\x7f-\xff])/sprintf"\\x{%02x}",ord$1/ge;
printf STDERR "%-11s = %s\n", $k, $c;
}
}
 
if (my $rows = $dtc) {
$rows =~ s/-$/-999/; # 3,6-
$rows =~ s/-/../g;
eval "\$dtc = { map { \$_ => 1 } $rows }";
}
 
while ($row && @$row or $row = $csv->getline (*ARGV)) {
my @row = @$row;
@row > $w and push @w, ($wdt) x (($w = @row) - @w);
foreach my $c (0 .. $#row) {
my $val = $row[$c] || "";
my $l = length $val;
$l > $w[$c] and $w[$c] = $l;
 
if ($utf and $csv->is_binary ($c)) {
from_to ($val, "utf-8", "ucs2");
$wks->write_unicode ($h, $c, $val);
next;
}
 
if ($csv->is_quoted ($c)) {
if ($utf) {
from_to ($val, "utf-8", "ucs2");
$wks->write_unicode ($h, $c, $val);
}
else {
$wks->write_string ($h, $c, $val);
}
next;
}
 
if (!$dtc or $dtc->{$c + 1}) {
my @d = (0, 0, 0); # Y, M, D
$val =~ m/^(\d{4})(\d{2})(\d{2})$/ and @d = ($1, $2, $3);
$val =~ m/^(\d{2})-(\d{2})-(\d{4})$/ and @d = ($3, $2, $1);
if ( $d[2] >= 1 && $d[2] <= 31 &&
$d[1] >= 1 && $d[1] <= 12 &&
$d[0] >= 1900 && $d[0] <= 2199) {
my $dm = Days_in_Month (@d[0,1]);
$d[2] < 1 and $d[2] = 1;
$d[2] > $dm and $d[2] = $dm;
my $dt = 2 + Delta_Days (1900, 1, 1, @d);
$wks->write ($h, $c, $dt, $fmt{date});
next;
}
}
 
if (!$frm && $val =~ m/^=/) {
$wks->write_string ($h, $c, $val);
}
else {
$wks->write ($h, $c, $val);
}
}
++$h % 100 or $opt_v && printf STDERR "%6d x %6d\r", $w, $h;
} continue { $row = undef }
$opt_v && printf STDERR "%6d x %6d\n", $w, $h;
 
$wks->set_column ($_, $_, $w[$_]) for 0 .. $#w;
$wbk->close ();
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/jrest/tests/bin/xls2csv-separate-sheets.pl
New file
0,0 → 1,159
#!/usr/bin/env perl
 
use strict;
use warnings;
use Modern::Perl;
 
use autodie qw{ :all };
use utf8;
use File::Spec;
 
use Smart::Comments '####';
use Getopt::Euclid;
 
use Text::CSV;
use File::Basename;
use Spreadsheet::ParseExcel;
use Text::Trim;
 
my $input_filename = $ARGV{'--infile'};
warn "Warning: The input file does not look like an Excel spreadsheet file."
unless looks_like_xls($input_filename);
my $workbook = Spreadsheet::ParseExcel::Workbook->Parse($input_filename);
 
my ($inbase,$inpath,$insuffix) = fileparse($input_filename, qr{\.[^.]*});
my $output_base = File::Spec->catfile($inpath, $inbase);
my $csv = Text::CSV->new();
 
for my $worksheet ( $workbook->worksheets() ) { #### Processing worksheets (% done)...
my ( $row_min, $row_max ) = $worksheet->row_range();
my ( $col_min, $col_max ) = $worksheet->col_range();
 
my @sheet_data;
 
for my $row ( $row_min .. $row_max ) {
for my $col ( $col_min .. $col_max ) {
my $cell = $worksheet->get_cell( $row, $col ) or undef;
next unless $cell;
$sheet_data[$row][$col] = trim($cell->value());
}
}
### @sheet_data;
 
my $ws_name = $worksheet->{Name};
$ws_name =~ s{\s}{_}xsmg; # no spaces
my $csvname = "${output_base}-${ws_name}.csv";
### $csvname
 
my $output = IO::File->new($csvname, '>') or die $!;
### $output
 
foreach my $line (@sheet_data) {
### $line
$csv->print($output, $line) or die $csv->error_diag();
print $output "\n";
}
 
close $output;
}
 
sub extract_sheet_contents {
my $sheet = $_[0];
my ($nrow, $ncol) = ($sheet->{maxrow}, $sheet->{maxcol});
return extract_rect_from_listref($sheet->{cell}, 1, $nrow, 1, $ncol);
}
 
sub extract_slice_of_listref {
my ($listref, @slice) = @_;
return [ map { $listref->[$_] } @slice ];
}
 
sub extract_rect_from_listref {
my ($listref, $row_start, $row_end, $col_start, $col_end) = @_;
return [ map {
extract_slice_of_listref($_, $col_start..$col_end)
} @{extract_slice_of_listref($listref, $row_start..$row_end)} ];
}
 
sub looks_like_xls {
state $xls_regex = qr{\.xls$};
return 1 if $_[0] =~ m{$xls_regex}i;
return;
}
 
 
__END__
 
=head1 NAME
 
spreadsheet2csv-separate-sheets.pl - Split a spreadsheet into one csv file for each worksheet
 
 
=head1 VERSION
 
Version 1.0
 
 
=head1 USAGE
 
progname [options]
 
 
=head1 REQUIRED ARGUMENTS
 
=over
 
=item --infile [=] <file> | -i <file>
 
The input spreadsheet file.
 
=for Euclid:
file.type: readable
file.default: '-'
 
=back
 
 
=head1 OPTIONS
 
=over
 
=item --version
 
=item --usage
 
=item --help
 
=item --man
 
Print the usual program information
 
=back
 
=head1 DESCRIPTION
 
This program will read a spreadsheet file and output one csv file for
each worksseht in the input file. The name of each output file will be
determined by the name of the input file and the name of the
worksheet. For example, a worksheet "Sheet1" in a file called
"reports.xls" will be output to "reports-Sheet1.csv".
 
=head1 NOTES
 
Empty rows and columns at the beginning of a worksheet will be
omitted. So if a worksheet has columns C through F filled, then the
output for that sheet will have exactly 4 columns, not 6.
 
=head1 AUTHOR
 
Ryan C. Thompson
 
=head1 BUGS
 
If you encounter a problem with this program, please email
rct+perlbug@thompsonclan.org. Bug reports and other feedback are
welcome.
 
=head1 COPYRIGHT
 
Copyright (c) 2010, Ryan C. Thompson
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/jrest/tests/data/image-test.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/trunk/jrest/tests/data/image-test.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/trunk/jrest/tests/data/images.sh
New file
0,0 → 1,8
# upload
curl -s -F file=@test/image-test.jpg -F ce_utilisateur=22506 http://cel/jrest/InventoryImage|grep OK
 
# list
http://cel/jrest/InventoryImageList/22506/?limite=50&numero_page=0|json_pp|egrep 'id_image|nom_original'|awk -F'"' '{print $4}'
 
# IO
POST http://cel/jrest/ExportXLS/22506<<<"format=csv&range=342212"|curl -F "upload=@-" -F utilisateur=22506 "http://cel/jrest/ImportXLS"
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:executable
+*
\ No newline at end of property
/trunk/jrest/tests/data/image-test2.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/trunk/jrest/tests/data/image-test2.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/trunk/jrest/tests/phptests/altitude.test.php
New file
0,0 → 1,3
<?php
// test altitude
return array('data' => array('altitude' => '800'));
/trunk/jrest/tests/phptests/determ-espece-badref-bdnffnn.result.php
New file
0,0 → 1,3
<?php return array (
'nom_sel' => 'Viola riviniana subsp. bavarica',
'nom_referentiel' => 'bdtfx');
/trunk/jrest/tests/phptests/determ-espece-syno-bdnff.test.php
New file
0,0 → 1,11
<?php
// test détermination espèce sur synonyme:
/*
+---------+----------------+-----------------------+
| num_nom | num_nom_retenu | nom_sci |
+---------+----------------+-----------------------+
| 38821 | 101838 | Leuzea conifera |
| 101838 | 101838 | Rhaponticum coniferum |
+---------+----------------+-----------------------+
*/
return array('data' => array('Espèce' => 'bdtfx:nn:38821'));
/trunk/jrest/tests/phptests/date-post-2900.result.php
New file
0,0 → 1,3
<?php return array (
'date_observation' => '',
);
/trunk/jrest/tests/phptests/determ-espece-bdnffnn.result.php
New file
0,0 → 1,8
<?php return array (
'nom_sel' => 'Viola riviniana subsp. bavarica',
'nom_sel_nn' => '72475',
'nom_ret' => 'Viola x bavarica Schrank',
'nom_ret_nn' => '72090',
'nt' => '7705',
'famille' => 'Violaceae',
);
/trunk/jrest/tests/phptests/ref-nonom-num.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx', 'nom_sel_nn' => 182));
/trunk/jrest/tests/phptests/milieu-255.test.php
New file
0,0 → 1,3
<?php
// test milieu, 255 caractères
return array('data' => array('milieu' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur test long commentaire : adipisicing elit, sed do eiusmod tempor incididunt consectetur adipisicing'));
/trunk/jrest/tests/phptests/01-sample.result.php
New file
0,0 → 1,3
<?php return array (
'date_observation' => '1991/06/23',
);
/trunk/jrest/tests/phptests/ref-nom-num.result.php
New file
0,0 → 1,0
<?php return array ('nom_sel' => 'blah','nom_referentiel' => 'autre');
/trunk/jrest/tests/phptests/determ-espece-noref-bdnffnn.result.php
New file
0,0 → 1,3
<?php return array (
'nom_sel' => 'Viola riviniana subsp. bavarica',
'nom_referentiel' => 'bdtfx');
/trunk/jrest/tests/phptests/determ-espece-from-nom-ret.result.php
New file
0,0 → 1,9
<?php return array (
'nom_sel' => 'Hieracium lysanum Arv.-Touv. & Gaut.',
'nom_sel_nn' => '33392',
'nom_ret' => 'Hieracium lysanum Arv.-Touv. & Gaut.',
'nom_ret_nn' => '33392',
'nt' => '11235',
'famille' => 'Asteraceae',
'nom_referentiel' => 'bdtfx'
);
/trunk/jrest/tests/phptests/date-format-invert.result.php
New file
0,0 → 1,3
<?php return array (
'date_observation' => '1991/01/23',
);
/trunk/jrest/tests/phptests/date-format-revert.test.php
New file
0,0 → 1,3
<?php
// test date format inverse YYYY/MM/DD
return array('data' => array('Date' => '23/01/1991'));
/trunk/jrest/tests/phptests/determ-espece-ref-badbdnffnn.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec mauvais bdnffnn mais bon référentiel
return array('data' => array('Espèce' => 'bdtfx:nn:72475000', 'nom_referentiel' => 'bdtfx'));
/trunk/jrest/tests/phptests/determ-espece.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce, simple avec erreur, sans référentiel
return array('data' => array('Espèce' => 'heliotropium europaeum Xxumm'));
/trunk/jrest/tests/phptests/transmission.result.php
New file
0,0 → 1,6
<?php
date_default_timezone_set("Europe/Paris");
return array (
'transmission' => 'oui',
'date_transmission' => date("Y-m-d H:i:s") // attention au décallage (1sec par exemple)
);
/trunk/jrest/tests/phptests/date-pre-1900.test.php
New file
0,0 → 1,4
<?php
// test date format texte, pré 1900
// il est normal que ce test faillisse avec une arch 32bits (ou un xampp 32bits)
return array('data' => array('Date' => '23/06/1811'));
/trunk/jrest/tests/phptests/ref-nonom-nonum.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx'));
/trunk/jrest/tests/phptests/determ-espece-bdnffnn.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec bdnffnn
return array('data' => array('Espèce' => 'bdtfx:nn:72475'));
/trunk/jrest/tests/phptests/colonne-abbrev.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec bdnffnn
return array('data' => array('espece' => 'blah'));
/trunk/jrest/tests/phptests/ref-nom-nonum.result.php
New file
0,0 → 1,0
<?php return array ('nom_sel' => 'blah','nom_referentiel' => 'autre');
/trunk/jrest/tests/phptests/commentaire-quote.test.php
New file
0,0 → 1,3
<?php
// test commentaire avec quotes et double-quotes
return array('data' => array('notes' => "test quote : a'’\"a"));
/trunk/jrest/tests/phptests/01-sample.test.php
New file
0,0 → 1,14
<?php
/*
Clefs prises en compte:
 
* dumpCols = 'standard,...':
colonnes (standard, avancé, ...) : '
* cmpCols' = [+]date,transmis,.. |-date,id_observation,... |"def"
Champs à comparer, ou à exclure de la comparaison. Par défaut: "def" = les champs de "data".
* warn = \d
nombre de warnings attendus
*/
// sample test
return array('cmpCols' => 'Date', // colonne à comparer
'data' => array('ordre' => 1, 'Date' => '23/06/1991', 'rien' => 'rien'));
/trunk/jrest/tests/phptests/date-format-revert.result.php
New file
0,0 → 1,3
<?php return array (
'date_observation' => '1991/01/23',
);
/trunk/jrest/tests/phptests/determ-espece-ref-badbdnffnn.result.php
New file
0,0 → 1,4
<?php return array (
'nom_sel' => 'bdtfx:nn:72475000',
'nom_referentiel' => 'autre',
);
/trunk/jrest/tests/phptests/accents.test.php
New file
0,0 → 1,3
<?php
// test date format texte, pré 1900
return array('data' => array('Lieu-dit' => 'œufs', 'Station' => 'Ératostène', 'Milieu' => 'Byørg'));
/trunk/jrest/tests/phptests/determ-espece.result.php
New file
0,0 → 1,8
<?php return array (
'nom_sel' => 'heliotropium europaeum Xxumm',
'nom_sel_nn' => '31468',
'nom_ret' => 'Heliotropium europaeum L.',
'nom_ret_nn' => '31468',
'nt' => '1382',
'famille' => 'Boraginaceae',
);
/trunk/jrest/tests/phptests/localisation-insee.test.php
New file
0,0 → 1,3
<?php
// test localisation nom (cp sur deux chiffres)
return array('data' => array('ce_zone_geo' => 'INSEE-C:34172'));
/trunk/jrest/tests/phptests/date-post-1900.result.php
New file
0,0 → 1,3
<?php return array (
'date_observation' => '1991/01/23',
);
/trunk/jrest/tests/phptests/latitude-virgule.test.php
New file
0,0 → 1,3
<?php
// test latitude, séparateur décimales = virgule
return array('data' => array('latitude' => '3,3'));
/trunk/jrest/tests/phptests/localisation-cp-seul.result.php
New file
0,0 → 1,3
<?php return array (
'zone_geo' => 'Montpellier',
'ce_zone_geo' => '34');
/trunk/jrest/tests/phptests/localisation-detect.result.php
New file
0,0 → 1,4
<?php return array (
'zone_geo' => 'Marseille',
'ce_zone_geo' => '13',
);
/trunk/jrest/tests/phptests/date-pre-1900.result.php
New file
0,0 → 1,3
<?php return array (
'date_observation' => '1811/06/23',
);
/trunk/jrest/tests/phptests/localisation-comm-PHPExcel-double.test.php
New file
0,0 → 1,4
<?php
// PHPExcel peut caster ZONE_GEO en (double) et stripper le leading '0'
// d'où problème de détection du code commune
return array('data' => array('Commune' => '06161'));
/trunk/jrest/tests/phptests/transmission.test.php
New file
0,0 → 1,4
<?php
// test transmission
return array('dumpCols' => 'avance',
'data' => array('Transmis' => 'OuI'));
/trunk/jrest/tests/phptests/ref-nonom-nonum.result.php
New file
0,0 → 1,0
<?php return array ( 'nom_referentiel' => 'autre' );
/trunk/jrest/tests/phptests/localisation-nom-cp2.test.php
New file
0,0 → 1,3
<?php
// test localisation nom (cp sur deux chiffres)
return array('data' => array('Commune' => 'Villers-lès-Nancy (54)'));
/trunk/jrest/tests/phptests/colonne-abbrev.result.php
New file
0,0 → 1,3
<?php return array (
'nom_sel' => 'blah'
);
/trunk/jrest/tests/phptests/commentaire-quote.result.php
New file
0,0 → 1,3
<?php return array (
'commentaire' => 'test quote : a\'’"a',
);
/trunk/jrest/tests/phptests/ref-nom-nonum.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx', 'nom_sel' => 'blah'));
/trunk/jrest/tests/phptests/localisation-cp-PHPExcel-double.result.php
New file
0,0 → 1,3
<?php return array (
'zone_geo' => 'Villeneuve-Loubet',
'ce_zone_geo' => '06');
/trunk/jrest/tests/phptests/determ-espece-bdnffnt.result.php
New file
0,0 → 1,8
<?php return array (
'nom_sel' => 'Viola riviniana f. riviniana',
'nom_sel_nn' => '72478',
'nom_ret' => 'Viola riviniana f. riviniana',
'nom_ret_nn' => '72478',
'nt' => '5757',
'famille' => 'Violaceae',
);
/trunk/jrest/tests/phptests/latitude-point.test.php
New file
0,0 → 1,3
<?php
// test latitude, séparateur décimales = point
return array('data' => array('latitude' => '3.3'));
/trunk/jrest/tests/phptests/altitude.result.php
New file
0,0 → 1,3
<?php return array (
'altitude' => '800',
);
/trunk/jrest/tests/phptests/determ-espece-badref-bdnffnn.test.php
New file
0,0 → 1,5
<?php
// test détermination espèce avec bdnffnn mais avec un référentiel erroné
// TODO: RechercheInfosTaxonBeta.php, ligne 186 devrait être modifié afin que la détermination
// prennent en priorité le préfixe "bdtfx" et ignore la colonne "nom_referentiel"
return array('data' => array('Espèce' => 'bdtfx:nn:72475', 'nom_referentiel' => 'bdtxa'));
/trunk/jrest/tests/phptests/accents.result.php
New file
0,0 → 1,5
<?php return array (
'lieudit' => 'œufs',
'station' => 'Ératostène',
'milieu' => 'Byørg',
);
/trunk/jrest/tests/phptests/localisation-insee.result.php
New file
0,0 → 1,3
<?php return array (
'zone_geo' => 'Montpellier',
'ce_zone_geo' => '34');
/trunk/jrest/tests/phptests/determ-espece-syno-bdnff.result.php
New file
0,0 → 1,9
<?php
return array (
'nom_sel' => 'Leuzea conifera',
'nom_sel_nn' => '38821',
'nom_ret' => 'Rhaponticum coniferum (L.) Greuter',
'nom_ret_nn' => '101838',
'nt' => '1050',
'famille' => 'Asteraceae');
?>
/trunk/jrest/tests/phptests/latitude-virgule.result.php
New file
0,0 → 1,3
<?php return array (
'latitude' => '3.3',
);
/trunk/jrest/tests/phptests/localisation-cp-seul.test.php
New file
0,0 → 1,3
<?php
// test localisation sur code insee seul
return array('data' => array('Commune' => '34172'));
/trunk/jrest/tests/phptests/localisation-comm-PHPExcel-double.result.php
New file
0,0 → 1,3
<?php return array (
'zone_geo' => 'Villeneuve-Loubet',
'ce_zone_geo' => '06');
/trunk/jrest/tests/phptests/localisation-detect.test.php
New file
0,0 → 1,3
<?php
// test localisation simple (commune seule)
return array('data' => array('Commune' => 'Marseille'));
/trunk/jrest/tests/phptests/date-post-1900.test.php
New file
0,0 → 1,3
<?php
// test date format texte, post 1900
return array('data' => array('Date' => '23/01/1991'));
/trunk/jrest/tests/phptests/date-post-2900.test.php
New file
0,0 → 1,4
<?php
// test date format texte, futur
return array('warn' => 1,
'data' => array('Date' => '23/06/2900'));
/trunk/jrest/tests/phptests/localisation-nom-cp2.result.php
New file
0,0 → 1,3
<?php return array (
'zone_geo' => 'Villers-lès-Nancy',
'ce_zone_geo' => '54');
/trunk/jrest/tests/phptests/milieu-255.result.php
New file
0,0 → 1,3
<?php return array (
'milieu' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur test long commentaire : adipisicing elit, sed do eiusmod tempor incididunt consectetur adi',
);
/trunk/jrest/tests/phptests/ref-nonom-num.result.php
New file
0,0 → 1,0
<?php return array ('nom_referentiel' => 'autre');
/trunk/jrest/tests/phptests/localisation-cp-PHPExcel-double.test.php
New file
0,0 → 1,4
<?php
// PHPExcel peut caster CE_ZONE_GEO en (double) et stripper le leading '0'
// d'où problème de détection du code commune
return array('data' => array('Identifiant Commune' => '06161'));
/trunk/jrest/tests/phptests/ref-nom-num.test.php
New file
0,0 → 1,9
<?php
/* test détermination setting du référentiel:
Théorie, valable pour insert et update:
- pas de nom_sel = pas de num_nom
MAIS:
- pas de nom_sel = pas de référentiel (NULL)
- nom_sel mais pas de num_nom = référentiel = "autre"
*/
return array('data' => array('nom_referentiel' => 'bdtfx', 'nom_sel' => 'blah', 'nom_sel_nn' => -42));
/trunk/jrest/tests/phptests/latitude-point.result.php
New file
0,0 → 1,3
<?php return array (
'latitude' => '3.3',
);
/trunk/jrest/tests/phptests/determ-espece-bdnffnt.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec bdnffnt, minuscules
return array('data' => array('Espèce' => 'bdtfx:nt:5757'));
/trunk/jrest/tests/phptests/determ-espece-from-nom-ret.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec un nom retenu (contenant déjà le nom_sci concaténé)
return array('data' => array('Espèce' => 'Hieracium lysanum Arv.-Touv. & Gaut.', 'nom_referentiel' => 'bdtfx'));
/trunk/jrest/tests/phptests/determ-espece-noref-bdnffnn.test.php
New file
0,0 → 1,3
<?php
// test détermination espèce avec bdnffnn mais sans référentiel
return array('data' => array('Espèce' => 'bdtfx:nn:72475', 'nom_referentiel' => 'autre'));
/trunk/jrest/tests/phptests/date-format-invert.test.php
New file
0,0 → 1,3
<?php
// test date format inverse YYYY/MM/DD
return array('data' => array('Date' => '1991/01/23'));
/trunk/jrest/tests/api-old.php
New file
0,0 → 1,272
<?php
 
global $champs;
$champs = Array(
'nom_sel' => 'Espece',
'nom_sel_nn' => 'Numero nomenclatural',
'nom_ret' => 'Nom retenu',
'nom_ret_nn' => 'Numero nomenclatural nom retenu',
'nt' => 'Numero taxonomique',
'famille' => 'Famille',
'nom_referentiel' => 'Referentiel taxonomique',
'zone_geo' => 'Commune',
'ce_zone_geo' => 'Identifiant Commune',
'date_observation' => 'Date',
'lieudit' => 'Lieu-dit',
'station' => 'Station',
'milieu' => 'Milieu',
'commentaire' => 'Notes',
'latitude' => 'Latitude',
'longitude' => 'Longitude',
'altitude' => 'Altitude',
'geodatum' => 'Referentiel Geographique',
 
'ordre' => 'Ordre',
'id_observation' => 'Identifiant',
 
'mots_cles_texte' => 'Mots Clés',
 
'date_creation' => 'Date Création',
'date_modification' => 'Date Modification',
 
'transmission' => 'Transmis',
'date_transmission' => 'Date Transmission',
'abondance' => 'Abondance',
'certitude' => 'Certitude',
'phenologie' => 'Phénologie',
'images' => 'Image(s)',
'nom_commun' => 'Nom Commun',
);
 
 
function cel_get_obs() {
$URL = DOMAIN . '/jrest/InventoryObservationList/' . USER;
return json_decode(file_get_contents($URL . '/?limite=100000&numero_page=0'));
}
 
function cel_get_images() {
$URL = DOMAIN . '/jrest/InventoryImageList/' . USER;
return json_decode(file_get_contents($URL . '/?limite=100000&numero_page=0'));
}
 
function cel_delete_obs($obs) {
$URL = DOMAIN . '/jrest/InventoryObservationList/' . USER;
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL . '/' . implode(',', $obs));
curl_setopt($ch,CURLOPT_POSTFIELDS, array('action' => 'DELETE'));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function cel_delete_image($img) {
$URL = DOMAIN . '/jrest/InventoryImageList/' . USER;
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL . '/' . implode(',', $img));
curl_setopt($ch,CURLOPT_POSTFIELDS, array('action' => 'DELETE'));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
 
function cel_delete_all_obs() {
$obs = cel_get_obs();
$ordres = array_map(function($item) { return $item->ordre; }, $obs);
cel_delete_obs($ordres);
}
 
 
function cel_delete_all_images() {
$img = cel_get_images();
$ids = array_map(function($item) { return $item->id_image; }, $img);
cel_delete_image($ids);
}
 
function cel_upload_image($file) {
if(! file_exists($file)) return NULL;
$URL = DOMAIN . '/jrest/InventoryImage';
 
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_POSTFIELDS, array(
'file' => '@' . $file,
'ce_utilisateur' => USER
));
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function cel_link_images($user, $id_image, $id_obs) {
$URL = DOMAIN . '/jrest/inventoryImageLink/';
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_POSTFIELDS, array(
'id_image' => $id_obs,
'id_observation' => $id_obs,
'ce_utilisateur' => $user
));
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
 
function auth() {
// TODO: CURLOPT_NETRC + Cel API support
if(!defined('EMAIL') || !defined('PASS') || ! EMAIL || ! PASS) return FALSE;
if(defined('COOKIE') && COOKIE) return TRUE;
$URL = DOMAIN . '/jrest/User/' . EMAIL . '/' . PASS;
 
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_HEADER, true);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
 
$result = curl_exec($ch);
curl_close($ch);
$sess = $id = array();
preg_match('/.*PHPSESSID=(\w+)/', $result, $sess);
preg_match('/"id_utilisateur":"(\d+)"/', $result, $id);
if(DEBUG) fwrite(STDERR, "curl \"".$URL ."\" : {$sess[1]} / {$id[1]}\n");
if(isset($sess[1])) {
define('COOKIE', $sess[1]);
if(!defined('USER')) {
if(!isset($id[1])) return FALSE;
define('USER', $id[1]);
}
return TRUE;
}
return FALSE;
}
 
function genCSV($d = Array()) {
$out = fopen("php://temp", 'r+');
// don't filter-out unknown field (for testing)
// $d = array_intersect_key($d, $GLOBALS['champs']);
$head = array();
foreach($d as $k => $v) {
if(isset($GLOBALS['champs'][$k])) $head[$GLOBALS['champs'][$k]] = $v;
else $head[$k] = $v;
}
fputcsv($out, array_keys($head) , ',', '"');
fputcsv($out, array_values($head) , ',', '"');
rewind($out);
$csv = stream_get_contents($out);
fclose($out);
return $csv;
}
 
function import($d) {
$URL = DOMAIN . '/jrest/InventoryImportExcel';
if(!is_file($d)) return FALSE;
exec("csvtool -o /tmp/a.csv col 1- $d");
exec(__DIR__ . "/bin/csv2xls -v 0 -f -o /tmp/a /tmp/a.csv");
//if(DEBUG) fwrite(STDERR, __DIR__ . "/bin/csv2xls -v 0 -f -o /tmp/a $d\n");
if(DEBUG) fwrite(STDERR, __DIR__ . "/bin/csv2xls -v 0 -f -o /tmp/a /tmp/a.csv\n");
$d = "/tmp/a.xls";
$ch = curl_init();
 
// curl does not support setting filename="X.csv";type=application/octet-stream'
// with plain POST variables
 
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_POSTFIELDS, array(
'upload' => '@' . $d . ';filename=test.csv',
'utilisateur' => USER
));
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
 
if(DEBUG) fwrite(STDERR, "curl -F \"upload=@$d;filename=test.csv\" -F utilisateur=" . USER . " \"$URL\"\n");
 
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function export($cols = NULL) {
if(!defined('COOKIE')) return FALSE;
 
/*$URL = DOMAIN . '/jrest/CelWidgetExport/csv?format=csv&utilisateur=' . EMAIL;
$cookie = 'PHPSESSID=' . COOKIE . '; ' . 'utilisateur=' . EMAIL . '; ' . 'cel_id=' . USER;*/
$URL = DOMAIN . '/jrest/InventoryExport/' . USER . '/';
$cookie = 'PHPSESSID=' . COOKIE;
 
$ch = curl_init();
 
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_COOKIE, $cookie);
$fh = fopen('/tmp/b.xls', 'w');
curl_setopt($ch,CURLOPT_FILE, $fh);
 
if(DEBUG) fwrite(STDERR, "curl -b \"$cookie\" \"$URL\"\n");
 
//execute post
$result = curl_exec($ch);
fflush($fh);
fclose($fh);
curl_close($ch);
exec("xls2csv /tmp/b.xls", $result);
if(DEBUG) fwrite(STDERR, "xls2csv /tmp/b.xls\n");
$result = implode("\n", $result);
return $result;
}
 
function getCSV_line($csv, $line) {
$line = max(0, intval($line - 1)); // -1 à cause du header
 
$out = fopen("php://temp", 'rw');
fwrite($out, $csv);
rewind($out);
 
$head = champsLongToShort(fgetcsv($out));
while ($line--) fgetcsv($out);
$l = fgetcsv($out);
fclose($out);
if(!$l) return FALSE;
return array_combine($head, $l);
}
 
 
function champsLongToShort($a) {
$r = array();
$x = array_flip($GLOBALS['champs']);
foreach($a as $k => $v) {
if(isset($x[$v])) $r[$k] = $x[$v];
else $r[$k] = -1;
}
return $r;
}
 
function champsLongToShort2($a) {
$r = array();
$x = array_flip($GLOBALS['champs']);
foreach($a as $k => $v) {
if(isset($x[$k])) $r[$x[$k]] = $v;
else $r[$k] = $v;
}
return $r;
}
/trunk/jrest/tests/IO-fields-unittest.php
New file
0,0 → 1,160
<?php
 
$options = getopt("hu:d:e:p:P:D",array("help", "user:", "domain:", "email:", "pass:", "phpsessid", "debug"));
if(isset($options['h']) || isset($options['help'])) {
printf(<<<EOF
%s [fichiers de test]
--help|-h: cette aide
-debug|-D: informations sur les requêtes curl
[-u|--user = 22506]
[-d|--domain = "http://cel"]
--pass|-p: pour l'authentifiation
--email|-e: pour l'authentifiation
--phpsessid|-P: pour l'authentifiation, alternative à -e/-p
 
* --phpsessid permet de passer un identifiant de session PHP pour effectuer l'export.
Exemple:
$ sqlite3 ~/.mozilla/firefox/*.default/cookies.sqlite<<<"SELECT * FROM moz_cookies WHERE baseDomain = 'cel' AND name = 'PHPSESSID';"
 
* [fichiers de test]: un ou plusieurs fichier(s) de test valide(s), commençant par "phptests/" et finissant en ".test.php"
Exemple: phptests/a*.test.php ou bien phptests/latitude-virgule.test.php
 
Exemple:
$ php IO-fields-unittest.php -P s97knu4axzi6440n1ihja9ppk1
$ php IO-fields-unittest.php -e me@tela -p blah -u 23004 -d http://localhost phptests/determ-espece*
 
Attention: lancer un test supprime TOUTES les observations existantes de l'utilisateur !
 
EOF
, /* relax emacs*/
basename(__FILE__));
die;
}
 
// stocke les test
define('_TESTDIR', dirname(__FILE__) . '/' . 'phptests');
// stocke les CSV générés à partir des test (répertoire de cache)
define('_RUNDIR', dirname(__FILE__) . '/' . 'run');
 
define('DOMAIN', isset($options['d']) ? $options['d'] : (isset($options['domain']) ? $options['domain'] : 'http://cel'));
define('EMAIL', isset($options['e']) ? $options['e'] : (isset($options['email']) ? $options['email'] : NULL));
define('PASS', isset($options['p']) ? $options['p'] : (isset($options['pass']) ? $options['pass'] : NULL));
define('DEBUG', isset($options['D']) ? 1 : (isset($options['debug']) ? 1 : 0));
 
// could be defined by the API::auth()
if(isset($options['u']) || isset($options['user'])) {
define('USER', isset($options['u']) ? $options['u'] : $options['user']);
}
 
// could be defined by the API::auth()
if(isset($options['P']) || isset($options['phpsessid'])) {
define('COOKIE', isset($options['P']) ? $options['P'] : $options['phpsessid']);
}
 
require_once('api.php');
 
if(!auth()) {
die('auth problem');
}
 
function setupTestEnv() {
cel_delete_all_obs();
cel_delete_all_images();
cel_upload_image('image-test.jpg');
cel_upload_image('image-test2.jpg');
}
 
if(! is_dir(_TESTDIR)) die('no phptests/ directory inside ' . __DIR__);
if(! is_dir(_RUNDIR)) mkdir(_RUNDIR);
if(! is_dir(_RUNDIR)) die('no run/ directory inside ' . __DIR__);
 
$all_tests = array_map('basename', glob(_TESTDIR . '/*.test.php'));
$tests = array_intersect(array_map('basename', $argv), $all_tests);
if(!$tests) $tests = $all_tests;
 
//@array_walk(glob('run/*'), function(&$i) { unlink($i);});
 
foreach($tests as $test) {
setupTestEnv();
$testfile = _TESTDIR . '/' . $test;
 
// cache car l'upload de fichier PHP-curl ne peut être
// simulé avec le contenu d'une variable (cf CURLOPT_POSTFIELDS et @fichier)
$runfile = _RUNDIR . '/' . $test;
 
$test_array = require($testfile);
 
$cols = isset($test_array['dumpCols']) ? $test_array['dumpCols'] : 'standard';
 
if(!is_file($runfile) || filemtime($runfile) < filemtime($testfile)) {
$csv = genCSV($test_array['data']);
file_put_contents($runfile, $csv);
}
 
//echo "\tcurl -F \"upload=@$runfile\" -F utilisateur=" . USER . " \"" . DOMAIN . "/jrest/ImportXLS\"\n";
echo "$test: ";
$var_expected = include(_TESTDIR . '/' . str_replace('.test.', '.result.', $test));
 
$retour = import($runfile);
$count_warn = 0;
preg_match('/^ligne /', $retour, $count_warn);
$count_warn = count($count_warn);
 
$result = getCSV_line(export($cols), 1);
if(!$result) {
echo ("\n!!! export vide, problème probable d'authentification ?\n");
continue;
}
 
//var_dump(champsLongToShort2($test_array['data']));die;
if($var_expected) {
$result = __diff_fields($test_array, $result, $var_expected);
// unset($result['date_creation'], $result['date_modification'], $result['id_observation']);
 
$d1 = array_diff($var_expected, $result);
$d2 = array_diff($result, $var_expected);
if(!$d1 && !$d2) echo "OK\n";
else {
echo "FAIL\n";
if($d1) { echo "expect: "; print_r($d1); }
if($d2) { echo "result: "; print_r($d2); }
//var_dump($var_expected, $result);
}
if(DEBUG) echo $retour;
if($count_warn && (!isset($test_array['warn']) || $test_array['warn'] != $count_warn)) { echo "warnings: $count_warn\n"; }
}
// pas de résultat de test défini ?
else {
if(DEBUG) echo $retour;
if($count_warn && (!isset($test_array['warn']) || $test_array['warn'] != $count_warn)) { echo "warnings: $count_warn\n"; }
 
echo '<?php return ' . var_export($result, true) . ';';
}
}
 
 
 
 
 
function __diff_fields($test_array, $result, $var_expected) {
if(! isset($test_array['cmpCols'])) {
return array_intersect_key($result, $var_expected);
}
 
if($test_array['cmpCols'] == 'def') {
return array_intersect_key($result, champsLongToShort2($test_array['data']));
}
 
$e = array_flip(champsLongToShort2(array_flip(explode(',', ltrim($test_array['cmpCols'], '+-')))));
if($test_array['cmpCols'][0] == '-') {
return array_diff_key($result, array_flip(champsLongToShort2($e)));
}
else { //if($test_array['cmpCols'][0] == '+') {
return array_intersect_key($result, array_flip(champsLongToShort2($e)));
}
 
// pas de 'cmpCols' définie: comparaison de tous les champs par rapport au tableau de résultats attendus
}
 
// sed -i -e '1{/<?php return/!s:^:<?php return :}' -e '${/^)$/s:$:;:}' phptests/*.result.php
/trunk/jrest/tests/api.php
New file
0,0 → 1,350
<?php
 
global $champs;
$champs = Array(
'nom_sel' => 'Espèce',
'nom_sel_nn' => 'Numéro nomenclatural',
'nom_ret' => 'Nom retenu',
'nom_ret_nn' => 'Numéro nomenclatural nom retenu',
'nt' => 'Numéro taxonomique',
'famille' => 'Famille',
'nom_referentiel' => 'Referentiel taxonomique',
'zone_geo' => 'Commune',
'ce_zone_geo' => 'Identifiant Commune',
'date_observation' => 'Date',
'lieudit' => 'Lieu-dit',
'station' => 'Station',
'milieu' => 'Milieu',
'commentaire' => 'Notes',
'latitude' => 'Latitude',
'longitude' => 'Longitude',
'altitude' => 'Altitude',
'geodatum' => 'Référentiel Géographique',
 
'ordre' => 'Ordre',
'id_observation' => 'Identifiant',
 
'mots_cles_texte' => 'Mots Clés',
 
'date_creation' => 'Date Création',
'date_modification' => 'Date Modification',
 
'transmission' => 'Transmis',
'date_transmission' => 'Date Transmission',
'abondance' => 'Abondance',
'certitude' => 'Certitude',
'phenologie' => 'Phénologie',
'images' => 'Image(s)',
'nom_commun' => 'Nom Commun',
 
'observateur' => 'Observateur',
);
 
define('URLPREFIX', 'service-test:cel:');
 
function cel_get_obs() {
$URL = DOMAIN . '/' . URLPREFIX . 'InventoryObservationList/' . USER;
// 5000 (memory_limit)
return json_decode(file_get_contents($URL . '/?limite=5000&numero_page=0'));
}
 
function cel_get_images() {
$URL = DOMAIN . '/' . URLPREFIX . 'InventoryImageList/' . USER;
return json_decode(file_get_contents($URL . '/?limite=100000&numero_page=0'));
}
 
function cel_delete_obs($obs) {
$URL = DOMAIN . '/' . URLPREFIX . 'InventoryObservationList/' . USER;
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL . '/' . implode(',', $obs));
curl_setopt($ch,CURLOPT_POSTFIELDS, array('action' => 'DELETE'));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
 
if(DEBUG) @fwrite(STDERR, sprintf("curl -F action=DELETE '%s/%s'\n", $URL, implode(',', $obs)));
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function cel_delete_image($img) {
$URL = DOMAIN . '/' . URLPREFIX . 'InventoryImageList/' . USER;
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL . '/' . implode(',', $img));
curl_setopt($ch,CURLOPT_POSTFIELDS, array('action' => 'DELETE'));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
 
function cel_delete_all_obs() {
while( ($obs = cel_get_obs()) ) {
$ordres = array_map(function($item) { return $item->ordre; }, $obs);
// les chunks permettent d'éviter des REQUEST-URI too long (500 id * 4 digits + 500 (virgules)) < 4k
while( $ordres_chunk = array_splice($ordres, 0, 500)) {
cel_delete_obs($ordres_chunk);
}
}
}
 
 
function cel_delete_all_images() {
$img = cel_get_images();
$ids = array_map(function($item) { return $item->id_image; }, $img);
cel_delete_image($ids);
}
 
function cel_upload_image($file) {
if(! file_exists($file)) return NULL;
$URL = DOMAIN . '/' . URLPREFIX . 'InventoryImage';
 
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_POSTFIELDS, array(
'file' => '@' . $file,
'ce_utilisateur' => USER
));
 
//curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
if(DEBUG) @fwrite(STDERR, sprintf("curl -F file=@%s '%s'\n", $file, $URL));
 
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function cel_link_images($user, $id_image, $id_obs) {
$URL = DOMAIN . '/' . URLPREFIX . 'inventoryImageLink/';
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_POSTFIELDS, array(
'id_image' => $id_obs,
'id_observation' => $id_obs,
'ce_utilisateur' => $user
));
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
 
function auth() {
// TODO: CURLOPT_NETRC + Cel API support
if(!defined('EMAIL') || !defined('PASS') || ! EMAIL || ! PASS) return FALSE;
if(defined('COOKIE') && COOKIE) return TRUE;
$URL = DOMAIN . '/' . URLPREFIX . 'User/' . EMAIL . '/' . PASS;
 
$ch = curl_init();
 
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_HEADER, true);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
 
$result = curl_exec($ch);
curl_close($ch);
$sess = $id = array();
preg_match('/.*PHPSESSID=(\w+)/', $result, $sess);
preg_match('/"id_utilisateur":"(\d+)"/', $result, $id);
 
if(DEBUG) @fwrite(STDERR, "curl \"".$URL ."\" : {$sess[1]} / {$id[1]}\n");
if(isset($sess[1])) {
define('COOKIE', $sess[1]);
if(!defined('USER')) {
if(!isset($id[1])) return FALSE;
define('USER', $id[1]);
}
return TRUE;
}
return FALSE;
}
 
function genCSV($d = Array()) {
$out = fopen("php://temp", 'r+');
// don't filter-out unknown field (for testing)
// $d = array_intersect_key($d, $GLOBALS['champs']);
$head = array();
foreach($d as $k => $v) {
if(isset($GLOBALS['champs'][$k])) $head[$GLOBALS['champs'][$k]] = $v;
else $head[$k] = $v;
}
fputcsv($out, array_keys($head) , ',', '"');
fputcsv($out, array_values($head) , ',', '"');
rewind($out);
$csv = stream_get_contents($out);
fclose($out);
return $csv;
}
 
function import($d) {
$URL = DOMAIN . '/' . URLPREFIX . 'ImportXLS';
if(!is_file($d)) return FALSE;
$ch = curl_init();
 
// curl does not support setting filename="X.csv";type=application/octet-stream'
// with plain POST variables
 
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_POSTFIELDS, array(
'upload' => '@' . $d . ';filename=test.csv',
'utilisateur' => USER
));
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
 
if(DEBUG) fwrite(STDERR, "curl -F \"upload=@$d;filename=test.csv\" -F utilisateur=" . USER . " \"$URL\"\n");
 
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function importXLS($d) {
$URL = DOMAIN . '/' . URLPREFIX . 'ImportXLS';
if(!is_file($d)) return FALSE;
exec("csvtool -o /tmp/a.csv col 1- $d");
exec(__DIR__ . "/bin/csv2xls -v 0 -f -o /tmp/a /tmp/a.csv &>/dev/null");
if(DEBUG) fwrite(STDERR,
"csvtool -o /tmp/a.csv col 1- $d;\n" .
__DIR__ . "/bin/csv2xls -v 0 -f -o /tmp/a /tmp/a.csv\n");
$d = "/tmp/a.xls";
if(!is_file($d)) { die('error: ' . __FILE__ . ':' . __LINE__); }
 
$ch = curl_init();
 
// curl does not support setting filename="X.csv";type=application/octet-stream'
// with plain POST variables
 
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_POSTFIELDS, array(
'upload' => '@' . $d . ';filename=test.xls',
'utilisateur' => USER
));
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
 
if(DEBUG) fwrite(STDERR, "curl -F \"upload=@$d;filename=test.xls\" -F utilisateur=" . USER . " \"$URL\"\n");
 
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function export($cols = "standard,avance") {
if(!defined('COOKIE')) return FALSE;
 
$URL = DOMAIN . '/' . URLPREFIX . 'CelWidgetExport/export?';
$URL .= http_build_query(array('colonnes' => $cols,
'id_utilisateur' => USER,
'format' => 'csv'));
$ch = curl_init();
 
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_COOKIE, 'PHPSESSID=' . COOKIE);
 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE);
 
if(DEBUG) fwrite(STDERR, "curl -b PHPSESSID=" . COOKIE . ' "' . $URL ."\"\n");
//execute post
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
 
function exportXLS($cols = "standard,avance") {
if(!defined('COOKIE')) return FALSE;
 
$file = "/tmp/b.xls";
 
$URL = DOMAIN . '/' . URLPREFIX . 'CelWidgetExport/export?';
$URL .= http_build_query(array('colonnes' => $cols,
'id_utilisateur' => USER,
'format' => 'xls'));
$ch = curl_init();
 
curl_setopt($ch,CURLOPT_URL, $URL);
curl_setopt($ch,CURLOPT_COOKIE, 'PHPSESSID=' . COOKIE);
 
$fh = fopen($file, 'w');
curl_setopt($ch,CURLOPT_FILE, $fh);
 
if(DEBUG) fwrite(STDERR, "curl -o $file -b PHPSESSID=" . COOKIE . ' "' . $URL ."\"\n");
//execute post
curl_exec($ch);
 
fflush($fh);
fclose($fh);
curl_close($ch);
 
// if(DEBUG) fwrite(STDERR, "xls2csv $file\n");
// exec("xls2csv $file", $result, $ret);
// return implode("\n", $result);
if(DEBUG) fwrite(STDERR, __DIR__ . "/bin/xls2csv-separate-sheets.pl -i $file\n");
exec(__DIR__ . "/bin/xls2csv-separate-sheets.pl -i $file &>/dev/null", $result, $ret);
$newfile = substr($file, 0, -4) . '-Liste' . '.csv';
 
// because xls2csv-separate-sheets.pl does latin9
if(DEBUG) fwrite(STDERR, "iconv -f latin9 -t utf8 $newfile >| /tmp/.x; mv -f /tmp/.x $newfile\n");
exec("iconv -f latin9 -t utf8 -o /tmp/.x $newfile; mv -f /tmp/.x $newfile");
if($ret) die('error: ' . __FILE__ . ':' . __LINE__);
 
return file_get_contents($newfile);
}
 
function getCSV_line($csv, $line) {
$line = max(0, intval($line - 1)); // -1 à cause du header
 
$out = fopen("php://temp", 'rw');
fwrite($out, $csv);
rewind($out);
 
$head = champsLongToShort(fgetcsv($out));
while ($line--) fgetcsv($out);
$l = fgetcsv($out);
fclose($out);
if(!$l) return FALSE;
// xls2csv-separate-sheets.pl supprime les trailing champs vides
if(count($l) != count($head)) {
$l += array_fill(count($l), count($head) - count($l), "");
}
return array_combine($head, $l);
}
 
 
function champsLongToShort($a) {
if(! $a) return array();
$r = array();
$x = array_flip($GLOBALS['champs']);
foreach($a as $k => $v) {
if(isset($x[$v])) $r[$k] = $x[$v];
else $r[$k] = -1;
}
return $r;
}
 
function champsLongToShort2($a) {
$r = array();
$x = array_flip($GLOBALS['champs']);
foreach($a as $k => $v) {
if(isset($x[$k])) $r[$x[$k]] = $v;
else $r[$k] = $v;
}
return $r;
}
/trunk/jrest/tests/multi-tests.xls
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/jrest/tests/multi-tests.xls
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/jrest/tests/XLS-IO-fields-unittest.php
New file
0,0 → 1,160
<?php
 
$options = getopt("hu:d:e:p:P:D",array("help", "user:", "domain:", "email:", "pass:", "phpsessid", "debug"));
if(isset($options['h']) || isset($options['help'])) {
printf(<<<EOF
%s [fichiers de test]
--help|-h: cette aide
-debug|-D: informations sur les requêtes curl
[-u|--user = 22506]
[-d|--domain = "http://cel"]
--pass|-p: pour l'authentifiation
--email|-e: pour l'authentifiation
--phpsessid|-P: pour l'authentifiation, alternative à -e/-p
 
* --phpsessid permet de passer un identifiant de session PHP pour effectuer l'export.
Exemple:
$ sqlite3 ~/.mozilla/firefox/*.default/cookies.sqlite<<<"SELECT * FROM moz_cookies WHERE baseDomain = 'cel' AND name = 'PHPSESSID';"
 
* [fichiers de test]: un ou plusieurs fichier(s) de test valide(s), commençant par "phptests/" et finissant en ".test.php"
Exemple: phptests/a*.test.php ou bien phptests/latitude-virgule.test.php
 
Exemple:
$ php IO-fields-unittest.php -P s97knu4axzi6440n1ihja9ppk1
$ php IO-fields-unittest.php -e me@tela -p blah -u 23004 -d http://localhost phptests/determ-espece*
 
Attention: lancer un test supprime TOUTES les observations existantes de l'utilisateur !
 
EOF
, /* relax emacs*/
basename(__FILE__));
die;
}
 
// stocke les test
define('_TESTDIR', dirname(__FILE__) . '/' . 'phptests');
// stocke les CSV générés à partir des test (répertoire de cache)
define('_RUNDIR', dirname(__FILE__) . '/' . 'run');
 
define('DOMAIN', isset($options['d']) ? $options['d'] : (isset($options['domain']) ? $options['domain'] : 'http://cel'));
define('EMAIL', isset($options['e']) ? $options['e'] : (isset($options['email']) ? $options['email'] : NULL));
define('PASS', isset($options['p']) ? $options['p'] : (isset($options['pass']) ? $options['pass'] : NULL));
define('DEBUG', isset($options['D']) ? 1 : (isset($options['debug']) ? 1 : 0));
 
// could be defined by the API::auth()
if(isset($options['u']) || isset($options['user'])) {
define('USER', isset($options['u']) ? $options['u'] : $options['user']);
}
 
// could be defined by the API::auth()
if(isset($options['P']) || isset($options['phpsessid'])) {
define('COOKIE', isset($options['P']) ? $options['P'] : $options['phpsessid']);
}
 
require_once('api.php');
 
if(!auth()) {
die('auth problem');
}
 
function setupTestEnv() {
cel_delete_all_obs();
cel_delete_all_images();
cel_upload_image('image-test.jpg');
cel_upload_image('image-test2.jpg');
}
 
if(! is_dir(_TESTDIR)) die('no phptests/ directory inside ' . __DIR__);
if(! is_dir(_RUNDIR)) mkdir(_RUNDIR);
if(! is_dir(_RUNDIR)) die('no run/ directory inside ' . __DIR__);
 
$all_tests = array_map('basename', glob(_TESTDIR . '/*.test.php'));
$tests = array_intersect(array_map('basename', $argv), $all_tests);
if(!$tests) $tests = $all_tests;
 
//@array_walk(glob('run/*'), function(&$i) { unlink($i);});
 
foreach($tests as $test) {
setupTestEnv();
$testfile = _TESTDIR . '/' . $test;
 
// cache car l'upload de fichier PHP-curl ne peut être
// simulé avec le contenu d'une variable (cf CURLOPT_POSTFIELDS et @fichier)
$runfile = _RUNDIR . '/' . $test;
 
$test_array = require($testfile);
 
$cols = isset($test_array['dumpCols']) ? $test_array['dumpCols'] : 'standard';
 
if(!is_file($runfile) || filemtime($runfile) < filemtime($testfile)) {
$csv = genCSV($test_array['data']);
file_put_contents($runfile, $csv);
}
 
//echo "\tcurl -F \"upload=@$runfile\" -F utilisateur=" . USER . " \"" . DOMAIN . "/jrest/ImportXLS\"\n";
echo "$test: ";
$var_expected = include(_TESTDIR . '/' . str_replace('.test.', '.result.', $test));
 
$retour = importXLS($runfile);
$count_warn = 0;
preg_match('/^ligne /', $retour, $count_warn);
$count_warn = count($count_warn);
 
$result = getCSV_line(exportXLS($cols), 1);
if(!$result) {
echo ("\n!!! export vide, problème probable d'authentification ?\n");
continue;
}
 
//var_dump(champsLongToShort2($test_array['data']));die;
if($var_expected) {
$result = __diff_fields($test_array, $result, $var_expected);
// unset($result['date_creation'], $result['date_modification'], $result['id_observation']);
 
$d1 = array_diff($var_expected, $result);
$d2 = array_diff($result, $var_expected);
if(!$d1 && !$d2) echo "OK\n";
else {
echo "FAIL\n";
if($d1) { echo "expect: "; print_r($d1); }
if($d2) { echo "result: "; print_r($d2); }
//var_dump($var_expected, $result);
}
if(DEBUG) echo $retour;
if($count_warn && (!isset($test_array['warn']) || $test_array['warn'] != $count_warn)) { echo "warnings: $count_warn\n"; }
}
// pas de résultat de test défini ?
else {
if(DEBUG) echo $retour;
if($count_warn && (!isset($test_array['warn']) || $test_array['warn'] != $count_warn)) { echo "warnings: $count_warn\n"; }
 
echo '<?php return ' . var_export($result, true) . ';';
}
}
 
 
 
 
 
function __diff_fields($test_array, $result, $var_expected) {
if(! isset($test_array['cmpCols'])) {
return array_intersect_key($result, $var_expected);
}
 
if($test_array['cmpCols'] == 'def') {
return array_intersect_key($result, champsLongToShort2($test_array['data']));
}
 
$e = array_flip(champsLongToShort2(array_flip(explode(',', ltrim($test_array['cmpCols'], '+-')))));
if($test_array['cmpCols'][0] == '-') {
return array_diff_key($result, array_flip(champsLongToShort2($e)));
}
else { //if($test_array['cmpCols'][0] == '+') {
return array_intersect_key($result, array_flip(champsLongToShort2($e)));
}
 
// pas de 'cmpCols' définie: comparaison de tous les champs par rapport au tableau de résultats attendus
}
 
// sed -i -e '1{/<?php return/!s:^:<?php return :}' -e '${/^)$/s:$:;:}' phptests/*.result.php
/trunk/jrest/tests/IO-file-diff.sh
New file
0,0 → 1,30
#!/bin/bash
 
orig=/tmp/orig.csv
ret=${1:-/tmp/result.csv}
 
# curl -sF "upload=@test.xls" -F utilisateur=22506 "http://cel/jrest/ImportXLS"
# $ sqlite3 .mozilla/firefox/*.default/cookies.sqlite<<<"SELECT * FROM moz_cookies WHERE baseDomain = 'cel' AND name = 'PHPSESSID';"
# GET -H "Cookie: PHPSESSID=ID" "http://cel/jrest/CelWidgetExport/export/?colonnes=standard,avance,etendu,baseflor&id_utilisateur=22506&format=csv > $ret
[[ ! -f $ret || ! -f test.xls ]] && echo "err" && exit 1
 
[[ ! -f $orig ]] && xls2csv -s cp1252 test.xls 2>/dev/null > $orig
[[ ! -f $orig ]] && echo "err" && exit 1
 
 
IFS=$'\n' cols=( $(csvtool head 1 $orig|tr , "\n") )
 
# test header
#diff <(csvtool head 1 $orig|tr , "\n") <(csvtool head 1 $ret |tr , "\n"); exit;
 
w=$(csvtool width $ret); w=32
 
# wdiff <(xls2csv -s cp1252 test.xls|csvtool readable -) <(csvtool readable $ret)
for i in ${cols[@]}; do
[[ $i =~ ^(Date Transmission|Date Création|Date Modification|Nom Commun|Identifiant|Ordre)$ ]] && continue;
echo "== $i";
wdiff -w "$(tput bold;tput setaf 1)" -x "$(tput sgr0)" -y "$(tput bold;tput setaf 2)" -z "$(tput sgr0)" <(csvtool namedcol "$i" $orig) <(csvtool namedcol "$i" $ret)
done
 
 
#ddiff <(csvtool namedcol Notes,Date /tmp/orig.csv ) <(csvtool namedcol Notes,Date /tmp/result.csv)
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:executable
+*
\ No newline at end of property
/trunk/jrest/tests
New file
Property changes:
Added: svn:ignore
+run
/trunk/jrest/services/InventoryImportExcel.php
New file
0,0 → 1,673
<?php
// In : utf8
// Out : utf8
 
// TODO : doublons
 
/**
Octobre 2010 David Delon.
Import d'observations dans le carnet en ligne à partir d'un fichier excel chargé par l'utilisateur
et liaison d'images déjà chargee aux observations ainsi crées.
 
Nom des colonnes imposé, mais présence de toutes les colonnes non obligatoires, ordre non imposé
Aucune valeur dans les colonnes n'est obligatoire
Pour une ligne donnée, si tous les champs vides on ne fait rien, ou si seul le champ image est présent.
Si la seule différence entre deux lignes est la valeur de la colonne image, on considère que c'est la même observation à laquelle on associe plusieurs images.
Si au moins deux lignes (ou plus) sont complètement identiques on prend en compte une seule ligne (les doublons sont éliminés).
**/
 
// Nom des colonnes
 
define('COMMUNE','commune'); // soit un nom de commune, soit un code INSEE (5 chiffres), ou "nom de commune (numero departement)"
define('LIEUDIT','lieu-dit'); // Texte libre
define('STATION','station'); // Texte libre
define('MILIEU','milieu'); // Texte libre
define('LATITUDE','latitude'); // En decimal systeme WGS84
define('LONGITUDE','longitude'); // En decimal systeme WGS84
define('NOTES','notes'); // Texte libre
define('DATEOBS','date'); // date au format jj/mm/aaaa
define('ESPECE','espece'); // texte libre, nom latin, ou code nomenclatural (format BDNFFnn999999)
define('IMAGE','image'); // nom des fichiers images préalablement uploadés sur le CEL séparés par des "/"
define('DEPARTEMENT','departement'); // Texte libre
define('TRANSMETTRE','transmettre'); // "1" ou "oui", toute autre valeur (y compris vide) sera consideree comme "non""
 
 
// Resultat de l'analyse d'une ligne
define('LIGNE_VIDE',1); //
define('LIGNE_NORMALE',2); //
define('LIGNE_IMAGE_SEULEMENT',3); //
 
 
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// la sortie est binaire (xls), mais OLE n'est pas compatible E_ALL en PHP-5.4
error_reporting(-1); //error_reporting() ^ E_STRICT);
require_once("ExcelReader/excel_reader2.php");
 
//TODO: refactoriser entièrement cette classe
class InventoryImportExcel extends Cel {
 
// Element constituant une observation
var $format_observation=array(COMMUNE ,LIEUDIT ,STATION , DEPARTEMENT, MILIEU ,LATITUDE ,LONGITUDE ,NOTES ,DATEOBS ,ESPECE ,TRANSMETTRE, IMAGE );
 
// Dernier numero d'ordre utilise
var $dernier_ordre = 1;
var $cpt_images_liees = 0;
var $utilisateur = array();
var $chercheur_infos_taxon;
 
/**
Constructeur
**/
function InventoryImportExcel($config) {
 
parent::__construct($config);
$this->chercheur_infos_taxon = new RechercheInfosTaxonBeta($config);
}
 
/**
Sur post
**/
function createElement($pairs) {
 
if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
echo '0'; exit;
}
if(!isset($_SESSION)) {session_start();}
$this->controleUtilisateur($pairs['utilisateur']);
$this->utilisateur = $this->getInfosComplementairesUtilisateur($pairs['utilisateur']);
 
foreach($_FILES as $file) { // C'est le plus simple
$infos_fichier = $file ;
}
// Chargement tableau en memoire
$data = new Spreadsheet_Excel_Reader($infos_fichier['tmp_name'], true); // false : pour menager la memoire.
$arr = array();
 
$rowcount=$data->rowcount(0);
$colcount=$data->colcount(0);
 
if ($rowcount<=1) { // TODO : retour erreur
print "Tableau vide";
exit;
}
 
// Chargement tableau
for($row=1;$row<=$rowcount;$row++)
for($col=1;$col<=$colcount;$col++)
$arr[$col][$row] = $data->val($row,$col,0); // Attention, inversion voulue
// 1 : Traitement intitules
$line = array();
 
/* Les colonnes ne sont pas forcemment dans l'ordre : on les extrait pour traitement futur */
for($col=1;$col<=$colcount;$col++) {
$colonne=strtolower($arr[$col][1]);
$colonne=trim($colonne);
$colonne=iconv('UTF-8', 'ASCII//TRANSLIT', $colonne);
switch ($colonne) { // On ne garde que les colonnes que l'on souhaite traiter
case COMMUNE:
case LIEUDIT:
case STATION:
case MILIEU:
case DEPARTEMENT:
case LATITUDE:
case LONGITUDE:
case NOTES:
case DATEOBS:
case ESPECE:
case TRANSMETTRE:
case IMAGE:
$selection=array_values($arr[$col]);
array_shift($selection); // On ne garde pas la premiere ligne, qui contient les intitules
$line[$colonne]=$selection;
break;
 
}
}
// 1 : Traitement lignes
$cpt_obs=0;
$cpt_img=0;
 
/* Recherche dernier numero d'ordre utilise : pas de mise a jour concurente a priori */
$requete = "SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = ".Cel::db()->proteger($pairs['utilisateur'])." ";
$resultat = Cel::db()->requeter($requete);
 
if(is_array($resultat) && count($resultat) > 0) {
$this->dernier_ordre = $resultat[0]['ordre']; // 1 par defaut
}
 
for ($i=0;$i<=$rowcount-1;$i++) {
// On saute les eventuelles lignes vides du debut et les lignes contenant des information sur image uniquement
while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
if ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
// image non rattachée à une observation
}
else {
// ligne vide
}
$i++;
}
while (($this->analyserLigne($line,$i)==LIGNE_NORMALE) && ($i<=$rowcount)) {
$id_obs = $this->traiterLigne($line,$i,$pairs['utilisateur']);
if ($this->dernier_ordre > 0) {
$cpt_obs++; // Compteur d'observations crees
}
$i++;
// On saute les lignes vide ou on traite les lignes suivantes contenant des informations sur image seulement
while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
if ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
$this->traiterLigneComplement($line,$i,$pairs['utilisateur'],$id_obs); // images supplementaires
}
else {
// print "vide";
}
$i++;
}
}
}
$message = '';
if($this->cpt_images_liees > 0) {
$message = $this->cpt_images_liees.' images liees pour ';
}
$message .= $cpt_obs;
print $message;
}
 
function analyserLigne($line,$i) {
$ligne_vide=true;
$ligne_image_seulement=true;
$ligne_normale=true;
$ligne_identique_sauf_image = true;
foreach ($this->format_observation as $colonne) {
if($i < 1) {
$ligne_identique_sauf_image = false;
} else {
if($colonne!= IMAGE && isset($line[$colonne]) && isset($line[$colonne][$i - 1]) && isset($line[$colonne][$i])
&& $line[$colonne][$i - 1] != $line[$colonne][$i] && $line[$colonne][$i] != '') {
$ligne_identique_sauf_image = false;
}
}
if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
if ($colonne!=IMAGE) {
$ligne_image_seulement=false;
$ligne_vide=false;
}
$ligne_vide=false;
}
}
if ($ligne_vide) {
return LIGNE_VIDE;
}
else {
if ($ligne_image_seulement || $ligne_identique_sauf_image) {
return LIGNE_IMAGE_SEULEMENT;
}
else {
return LIGNE_NORMALE;
}
}
}
 
function traiterLigne($line,$i,$utilisateur) {
// Controle donnee et insertion
$info_image=array();
$info_transmettre = "0";
$info_espece = array(
'nom_sel' => '',
'nom_sel_nn' => '',
'nom_ret' => '',
'nom_ret_nn' => '',
'nt' => '',
'famille' => ''
);
$info_commune = array('nom' => '', 'code' => '');
foreach ($this->format_observation as $colonne) {
if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
switch ($colonne) { // On ne garde que les colonnes que l'on souhaite traiter
case COMMUNE:
$info_commune = $this->traiterCommune($line[COMMUNE][$i]);
break;
case LIEUDIT:
$info_lieudit = $this->traiterLieudit($line[LIEUDIT][$i]);
break;
case STATION:
$info_station = $this->traiterStation($line[STATION][$i]);
break;
case MILIEU:
$info_milieu = $this->traiterMilieu($line[MILIEU][$i]);
break;
case DEPARTEMENT:
$dpt = $this->traiterDepartement($line[DEPARTEMENT][$i]);
if(is_numeric($dpt) && strlen($dpt == 5) && $info_commune['code'] == 'NULL') {
$info_commune['code'] = $dpt;
}
break;
case LATITUDE:
$info_latitude = $this->traiterLatitude($line[LATITUDE][$i]);
break;
case LONGITUDE:
$info_longitude = $this->traiterLongitude($line[LONGITUDE][$i]);
break;
case NOTES:
$info_notes = $this->traiterNotes($line[NOTES][$i]);
break;
case DATEOBS:
$info_dateobs = $this->traiterDateObs($line[DATEOBS][$i]);
break;
case TRANSMETTRE:
$info_transmettre = $this->traiterTransmettre($line[TRANSMETTRE][$i]);
break;
case ESPECE:
// suppression des accents éventuels
$line[ESPECE][$i] = iconv('UTF-8', 'ASCII//TRANSLIT', $line[ESPECE][$i]);
$resultat_recherche_espece = $this->chercheur_infos_taxon->rechercherInfosSurTexteCodeOuNumTax(utf8_encode(trim($line[ESPECE][$i])));
if (isset($resultat_recherche_espece['en_id_nom']) && $resultat_recherche_espece['en_id_nom'] != '') {
$info_espece['nom_sel'] = $resultat_recherche_espece['nom_sel'];
$info_espece['nom_sel_nn'] = $resultat_recherche_espece['en_id_nom'];
$complement = $this->chercheur_infos_taxon->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
$info_espece['nom_ret'] = $complement['Nom_Retenu'];
$info_espece['nom_ret_nn'] = $complement['Num_Nom_Retenu'];
$info_espece['nt'] = $complement['Num_Taxon'];
$info_espece['famille'] = $complement['Famille'];
} else {
$info_espece['nom_sel'] = $line[ESPECE][$i];
}
case IMAGE:
if(isset($line[IMAGE])) {
$info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / + utilisateur
}
break;
}
}
else {
switch($colonne) {
case COMMUNE:
$info_commune['nom']="";
break;
case LIEUDIT:
$info_lieudit="";
break;
case STATION:
$info_station="";
break;
case MILIEU:
$info_milieu="";
break;
case DEPARTEMENT:
if (!isset ($info_commune['code']) || $info_commune['code']=='') {
$info_commune['code']="";
}
break;
case LATITUDE:
$info_latitude = "";
break;
case LONGITUDE:
$info_longitude = "";
break;
case NOTES:
$info_notes='';
break;
case TRANSMETTRE:
$info_transmettre = "0";
break;
}
}
}
$this->dernier_ordre++;
list($jour,$mois,$annee) = isset($info_dateobs) ? explode("/",$info_dateobs) : array(null,null,null);
$info_dateobs=$annee."-".$mois."-".$jour." 0:0:0";
$requete = "INSERT INTO cel_obs (".
"ce_utilisateur,prenom_utilisateur,nom_utilisateur,courriel_utilisateur,".
"ordre,".
"nom_sel,nom_sel_nn,nom_ret,nom_ret_nn,nt,famille,".
"zone_geo,ce_zone_geo,".
"date_observation,".
"lieudit,station, milieu, commentaire, transmission, ".
"date_creation,date_modification,latitude,longitude) ".
" VALUES(".Cel::db()->proteger($utilisateur).",".
Cel::db()->proteger($this->utilisateur['prenom']).",".
Cel::db()->proteger($this->utilisateur['nom']).",".
Cel::db()->proteger($this->utilisateur['courriel']).",".
Cel::db()->proteger($this->dernier_ordre).",".
Cel::db()->proteger($info_espece['nom_sel']).",".
Cel::db()->proteger($info_espece['nom_sel_nn']).",".
Cel::db()->proteger($info_espece['nom_ret']).",".
Cel::db()->proteger($info_espece['nom_ret_nn']).",".
Cel::db()->proteger($info_espece['nt']).",".
Cel::db()->proteger($info_espece['famille']).",".
Cel::db()->proteger($info_commune['nom']).",".
Cel::db()->proteger('INSEE-C:'.$info_commune['code']).",".
Cel::db()->proteger($info_dateobs).",".
Cel::db()->proteger($info_lieudit).",".
Cel::db()->proteger($info_station).",".
Cel::db()->proteger($info_milieu).",".
Cel::db()->proteger($info_notes).",".
Cel::db()->proteger($info_transmettre).",".
"now() , now(),".
Cel::db()->proteger($info_latitude).",".
Cel::db()->proteger($info_longitude).")";
$insertion = Cel::db()->executer($requete);
$requete_id_obs = 'SELECT id_observation FROM cel_obs WHERE ordre = '.Cel::db()->proteger($this->dernier_ordre).' AND ce_utilisateur = '.Cel::db()->proteger($utilisateur);
$resultat_id_obs = Cel::db()->requeter($requete_id_obs);
$id_obs = $resultat_id_obs[0]['id_observation'];
// creation lien image
foreach ($info_image as $pic) {
$requete_liaison = 'INSERT INTO cel_obs_images (id_image, id_observation ) VALUES ('.Cel::db()->proteger($pic['id_image']).', '.$id_obs.') ON DUPLICATE KEY UPDATE id_image = id_image ';
$liaison = Cel::db()->executer($requete_liaison);
if ($liaison !== false) {
$this->cpt_images_liees++;
} else {
return false;
}
}
return $id_obs;
}
 
function traiterLigneComplement($line,$i,$utilisateur, $id_obs = null) {
if(isset($line[IMAGE])) {
$info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / + utilisateur
// creation lien image
foreach ($info_image as $pic) {
$requete = 'INSERT INTO cel_obs_images (id_image, id_observation) VALUES ('.Cel::db()->proteger($pic['id_image']).', '.Cel::db()->proteger($id_obs).') ON DUPLICATE KEY UPDATE id_image = id_image' ;
$resultat_liaison = Cel::db()->executer($requete);
if ($resultat_liaison !== false) {
$this->cpt_images_liees++;
} else {
return false;
}
}
}
}
function traiterCommune($identifiant_commune) {
// Recherche correspondance sur nom, si pas unique, correspondance dep. sinon code insee
$identifiant_commune=trim($identifiant_commune);
preg_match('/(.*) \(([0-9][0-9]*)\)/',$identifiant_commune,$elements);
if (isset($elements[1])) { // commune + departement : montpellier (34)
$nom_commune=$elements[1];
$code_commune=$elements[2];
$requete="SELECT DISTINCT nom, code FROM cel_zones_geo WHERE nom = ".Cel::db()->proteger($nom_commune)." AND code LIKE ".Cel::db()->proteger($code_commune.'%');
}
else { // Code insee seul
preg_match('/([0-9][0-9]*)|(2A[0-9][0-9]*)|(2B[0-9][0-9]*)/',$identifiant_commune,$elements);
if (isset($elements[1])) { // code insee commune
$code_insee_commune=$elements[1];
$requete="SELECT DISTINCT nom, code FROM cel_zones_geo WHERE code = ".Cel::db()->proteger($code_insee_commune);
}
else { // Commune seule (le departement sera recupere dans la colonne departement si elle est presente, on prend le risque ici de retourner une mauvaise
// Commune
preg_match('/(.*)/',$identifiant_commune,$elements);
if (isset($elements[1])) { // commune
$nom_commune=$elements[1];
$nom_commune=trim($nom_commune);
$nom_commune=iconv('UTF-8', 'ASCII//TRANSLIT', $nom_commune);
$nom_commune=preg_replace("/ /","%",$nom_commune);
$requete="SELECT DISTINCT nom, code FROM cel_zones_geo WHERE nom like ".Cel::db()->proteger($nom_commune.'%');
}
}
}
$resultat_commune = Cel::db()->requeter($requete);
// cas de la commune introuvable dans le référentiel
if(!is_array($resultat_commune) || count($resultat_commune) == 0) {
$resultat_commune['nom'] = $identifiant_commune;
$resultat_commune['code'] = 'NULL';
} else {
$resultat_commune = $resultat_commune[0];
}
return $resultat_commune;
}
 
function traiterLieudit($lieudit) {
// texte libre
return trim($lieudit);
}
 
function traiterStation($station) {
// texte libre
return trim($station);
}
 
function traiterMilieu($milieu) {
// texte libre
return trim($milieu);
}
 
function traiterDepartement($departement) {
// texte libre
if(is_numeric($departement) && strlen($departement) == 4) {
$departement = "0"+$departement;
}
if(is_numeric($departement) && $departement <= 9) {
$departement = "0"+$departement;
}
return trim($departement);
}
 
function traiterLatitude($latitude) {
// verifier formal decimal + limite france ? TODO
return trim($latitude);
}
function traiterLongitude($longitude) {
// verifier format decimal + limite france ? TODO
return trim($longitude);
}
function traiterNotes($notes) {
// texte libre
return trim($notes);
}
function traiterDateObs($dateobs) {
// verifier jj/mm/aaaa sinon date vide TODO
$date = trim($dateobs);
if(!preg_match("#[0-9]{2}/[0-9]{2}/([0-9]{4}|[0-9]{2})#", $date)) {
$date = '00/00/0000';
}
return $date;
}
 
function traiterTransmettre($transmettre) {
$transmission = '0';
if (trim($transmettre) == "1" || trim($transmettre) == "oui") {
$transmission = '1';
}
return $transmission;
}
function traiterImage($images,$utilisateur) { // recherche id image de ce nom
$liste_images = explode("/",$images) ;
$row =array();
foreach($liste_images as $image) {
$image = iconv('UTF-8', 'ASCII//TRANSLIT', $image);
$requete = "SELECT * FROM cel_images WHERE ce_utilisateur = ".Cel::db()->proteger($utilisateur)." AND nom_original= ".Cel::db()->proteger($image);
$ligne = Cel::db()->requeter($requete);
if(is_array($ligne) && !empty($ligne)) {
$row[] = $ligne[0];
}
}
return $row;
}
}
 
function init_byte_map(){
$byte_map = array();
for($x=128;$x<256;++$x){
$byte_map[chr($x)]=utf8_encode(chr($x));
}
$cp1252_map=array(
"\x80"=>"\xE2\x82\xAC", // EURO SIGN
"\x82" => "\xE2\x80\x9A", // SINGLE LOW-9 QUOTATION MARK
"\x83" => "\xC6\x92", // LATIN SMALL LETTER F WITH HOOK
"\x84" => "\xE2\x80\x9E", // DOUBLE LOW-9 QUOTATION MARK
"\x85" => "\xE2\x80\xA6", // HORIZONTAL ELLIPSIS
"\x86" => "\xE2\x80\xA0", // DAGGER
"\x87" => "\xE2\x80\xA1", // DOUBLE DAGGER
"\x88" => "\xCB\x86", // MODIFIER LETTER CIRCUMFLEX ACCENT
"\x89" => "\xE2\x80\xB0", // PER MILLE SIGN
"\x8A" => "\xC5\xA0", // LATIN CAPITAL LETTER S WITH CARON
"\x8B" => "\xE2\x80\xB9", // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"\x8C" => "\xC5\x92", // LATIN CAPITAL LIGATURE OE
"\x8E" => "\xC5\xBD", // LATIN CAPITAL LETTER Z WITH CARON
"\x91" => "\xE2\x80\x98", // LEFT SINGLE QUOTATION MARK
"\x92" => "\xE2\x80\x99", // RIGHT SINGLE QUOTATION MARK
"\x93" => "\xE2\x80\x9C", // LEFT DOUBLE QUOTATION MARK
"\x94" => "\xE2\x80\x9D", // RIGHT DOUBLE QUOTATION MARK
"\x95" => "\xE2\x80\xA2", // BULLET
"\x96" => "\xE2\x80\x93", // EN DASH
"\x97" => "\xE2\x80\x94", // EM DASH
"\x98" => "\xCB\x9C", // SMALL TILDE
"\x99" => "\xE2\x84\xA2", // TRADE MARK SIGN
"\x9A" => "\xC5\xA1", // LATIN SMALL LETTER S WITH CARON
"\x9B" => "\xE2\x80\xBA", // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"\x9C" => "\xC5\x93", // LATIN SMALL LIGATURE OE
"\x9E" => "\xC5\xBE", // LATIN SMALL LETTER Z WITH CARON
"\x9F" => "\xC5\xB8" // LATIN CAPITAL LETTER Y WITH DIAERESIS
);
foreach($cp1252_map as $k=>$v){
$byte_map[$k]=$v;
}
return $byte_map;
}
 
function fix_latin($instr){
$byte_map = init_byte_map();
$ascii_char='[\x00-\x7F]';
$cont_byte='[\x80-\xBF]';
$utf8_2='[\xC0-\xDF]'.$cont_byte;
$utf8_3='[\xE0-\xEF]'.$cont_byte.'{2}';
$utf8_4='[\xF0-\xF7]'.$cont_byte.'{3}';
$utf8_5='[\xF8-\xFB]'.$cont_byte.'{4}';
$nibble_good_chars = "@^($ascii_char+|$utf8_2|$utf8_3|$utf8_4|$utf8_5)(.*)$@s";
 
if(mb_check_encoding($instr,'UTF-8'))return $instr; // no need for the rest if it's all valid UTF-8 already
$outstr='';
$char='';
$rest='';
while((strlen($instr))>0){
if(1==@preg_match($nibble_good_chars,$instr,$match)){
$char=$match[1];
$rest=$match[2];
$outstr.=$char;
}elseif(1==@preg_match('@^(.)(.*)$@s',$instr,$match)){
$char=$match[1];
$rest=$match[2];
$outstr.=$byte_map[$char];
}
$instr=$rest;
}
return $outstr;
}
 
function remove_accent($str) {
return supprimerAccents($str);
$a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î',
'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß',
'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î',
'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā',
'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď',
'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ',
'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ',
'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ',
'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ',
'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ',
'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ',
'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż',
'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ',
'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');
$b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I',
'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's',
'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i',
'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a',
'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd',
'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g',
'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i',
'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l',
'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R',
'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't',
'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y',
'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I',
'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
return str_replace($a, $b, $str);
}
 
//TODO: déplacer les fonctions ci dessus et dessous dans une classe
// utilitaire
function supprimerAccents($str, $charset = 'UTF-8')
{
$str = htmlentities($str, ENT_NOQUOTES, $charset);
$str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
$str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. '&oelig;'
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères
 
return $str;
}
 
function cp1252_to_utf8($str) {
$cp1252_map = array ("\xc2\x80" => "\xe2\x82\xac",
"\xc2\x82" => "\xe2\x80\x9a",
"\xc2\x83" => "\xc6\x92",
"\xc2\x84" => "\xe2\x80\x9e",
"\xc2\x85" => "\xe2\x80\xa6",
"\xc2\x86" => "\xe2\x80\xa0",
"\xc2\x87" => "\xe2\x80\xa1",
"\xc2\x88" => "\xcb\x86",
"\xc2\x89" => "\xe2\x80\xb0",
"\xc2\x8a" => "\xc5\xa0",
"\xc2\x8b" => "\xe2\x80\xb9",
"\xc2\x8c" => "\xc5\x92",
"\xc2\x8e" => "\xc5\xbd",
"\xc2\x91" => "\xe2\x80\x98",
"\xc2\x92" => "\xe2\x80\x99",
"\xc2\x93" => "\xe2\x80\x9c",
"\xc2\x94" => "\xe2\x80\x9d",
"\xc2\x95" => "\xe2\x80\xa2",
"\xc2\x96" => "\xe2\x80\x93",
"\xc2\x97" => "\xe2\x80\x94",
"\xc2\x98" => "\xcb\x9c",
"\xc2\x99" => "\xe2\x84\xa2",
"\xc2\x9a" => "\xc5\xa1",
"\xc2\x9b" => "\xe2\x80\xba",
"\xc2\x9c" => "\xc5\x93",
"\xc2\x9e" => "\xc5\xbe",
"\xc2\x9f" => "\xc5\xb8"
);
return strtr(utf8_encode($str), $cp1252_map);
}
?>
/trunk/jrest/lib/Bdd2.php
95,6 → 95,11
return $this->executerRequete($requete, self::SQL_RETOUR_BRUT);
}
 
/**
* Protège automatiquement toutes les chaines comprises entre deux caractères '|'.
* @see protegerRequete()
* @param unknown_type $requete
*/
public function executer($requete) {
try {
$resultat = $this->exec($requete);
/trunk/jrest/lib/Conteneur.php
New file
0,0 → 1,79
<?php
/**
* Le conteneur encapsule les classes et les paramètres de config.
* Il gère leur instanciation, ainsi que la récupération des paramètres depuis les fichiers de configuration.
*
* @category php 5.2
* @package cel
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class Conteneur {
protected $parametres = array();
protected $partages = array();
 
public function __construct(array $parametres = null) {
$this->parametres = is_null($parametres) ? array() : $parametres;
}
 
public function getParametre($cle) {
$valeur = isset($this->parametres[$cle]) ? $this->parametres[$cle] : null;
if (is_null($valeur) && $this->etreParametreASection($cle)) {
$valeur = $this->getParametreAvecSection($cle);
}
return $valeur;
}
 
private function etreParametreASection($cle) {
return strpos($cle, '.') ? true : false;
}
 
private function getParametreAvecSection($cle) {
$cleComposee = explode('.', $cle);
$valeur = $this->parametres;
foreach ($cleComposee as $cleCourrante) {
$valeur = isset($valeur[$cleCourrante]) ? $valeur[$cleCourrante] : null;
}
return $valeur;
}
 
public function getParametreTableau($cle) {
$tableau = array();
$parametre = $this->getParametre($cle);
if (empty($parametre) === false) {
$tableauPartiel = explode(',', $parametre);
$tableauPartiel = array_map('trim', $tableauPartiel);
foreach ($tableauPartiel as $champ) {
if (strpos($champ, '=') === false) {
$tableau[] = trim($champ);
} else {
list($cle, $val) = explode('=', $champ);
$tableau[trim($cle)] = trim($val);
}
}
}
return $tableau;
}
 
public function setParametre($cle, $valeur) {
$this->parametres[$cle] = $valeur;
}
 
public function getBdd() {
if (!isset($this->partages['Bdd'])){
$this->partages['Bdd'] = new Bdd($this->getParametre('database_cel'));
}
return $this->partages['Bdd'];
}
 
public function getScript() {
if (!isset($this->partages['Script'])){
$this->partages['Script'] = new Script();
}
return $this->partages['Script'];
}
}
?>
/trunk/jrest/lib/Script.php
New file
0,0 → 1,42
<?php
/**
* La classe fournissant des méthodes communes aux scripts.
*
* @category php 5.2
* @package cel
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class Script {
 
private static $avancement = array();
 
/**
* Utiliser cette méthode dans une boucle pour afficher un message suivi du nombre de tour de boucle effectué.
* Vous devrez vous même gérer le retour à la ligne à la sortie de la boucle.
*
* @param string le message d'information.
* @param int le nombre de départ à afficher. Par défaut 0.
* @return void le message est affiché dans la console.
*/
public function afficherAvancement($message, $depart = 0) {
if (! isset(self::$avancement[$message])) {
self::$avancement[$message] = $depart;
print "$message : ";
 
$actuel =& self::$avancement[$message];
print $actuel++;
} else {
$actuel =& self::$avancement[$message];
// Cas du passage de 99 (= 2 caractères) à 100 (= 3 caractères)
$passage = (strlen((string) ($actuel - 1)) < strlen((string) ($actuel))) ? 1 : 0;
 
print str_repeat(chr(8), (strlen((string) $actuel) - $passage));
print $actuel++;
}
}
}
?>
/trunk/jrest/scripts/ExtracteurMeta.php
New file
0,0 → 1,183
<?php
// declare(encoding='UTF-8');
/**
* Script d'extration des métadonnées des images pour intégration dans la BDD v2.
* Utilisation : /opt/lampp/bin/php cli.php ExtracteurMeta
*
* @category php 5.2
* @package Cel/Scripts
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class ExtracteurMeta {
 
const DROIT = 0705;
 
private $chemin_images = '';
private $bdd = null;
private $script = null;
 
private $idImg = null;
private $metaComplet = null;
private $exif = null;
private $iptc = null;
private $xmp = null;
private $makerNotes = null;
private $metaAutres = null;
 
 
public function __construct(Conteneur $conteneur) {
$this->chemin_images = $conteneur->getParametre('cel.chemin_images');
$this->bdd = $conteneur->getBdd();
$this->script = $conteneur->getScript();
}
 
public function executer($arguments) {
echo "EXTRACTION des MÉTADONNÉES\n";
echo "Vérification config : ".$this->verifierConfig()."\n";
 
$images = $this->obtenirImagesEnBdd();
foreach ($images as $img) {
$this->idImg = $img['id_image'];
 
$cheminImage = $this->obtenirCheminImageOriginale($this->idImg);
if (file_exists($cheminImage)) {
$cmd = "exiftool -X -file:comment $cheminImage";
$metaFile = $this->executerCommandeSysteme($cmd);
 
if ($this->neccessiterRemplacement($metaFile) === true) {
//print "Remplacement : {$this->idImg} \n";
 
$cmd = "exiftool -X -D -U -b -c '%.6f' -d '%Y-%m-%d %H:%M:%S' -All $cheminImage";
$this->metaComplet = $this->executerCommandeSysteme($cmd);
 
$cmd = "exiftool -X -D -c '%.6f' -d '%Y-%m-%d %H:%M:%S' -exif:all $cheminImage";
$this->exif = $this->executerCommandeSysteme($cmd);
 
$cmd = "exiftool -X -D -c '%.6f' -d '%Y-%m-%d %H:%M:%S' -iptc:all $cheminImage";
$this->iptc = $this->executerCommandeSysteme($cmd);
 
$cmd = "exiftool -X -D -c '%.6f' -d '%Y-%m-%d %H:%M:%S' -xmp:all $cheminImage";
$this->xmp = $this->executerCommandeSysteme($cmd);
 
$cmd = "exiftool -X -D -c '%.6f' -d '%Y-%m-%d %H:%M:%S' -makernotes:all $cheminImage";
$this->makerNotes = $this->executerCommandeSysteme($cmd);
 
$cmd = "exiftool -X -D -c '%.6f' -d '%Y-%m-%d %H:%M:%S' --exif:all --iptc:all --xmp:all --makernotes:all $cheminImage";
$this->metaAutres = $this->executerCommandeSysteme($cmd);
 
$this->ecrireFichierRdf();
$this->mettreAJourBdd();
}
} else {
//print "Fichier image '{$this->idImg}' introuvable\n";
}
$this->script->afficherAvancement("Analyse des images");
}
print "\n";
}
 
private function verifierConfig() {
if (empty($this->chemin_images)) {
$message = "Vous devez indiquer le dossier contenant la hiérarchie des images dans le paramètre : ".
"[cel] chemin_images";
$code = (string) E_USER_ERROR;
throw new Exception($message);
}
return 'OK';
}
 
private function obtenirImagesEnBdd() {
$requete = 'SELECT id_image FROM cel_images ';
$images = $this->bdd->requeter($requete);
return $images;
}
 
private function executerCommandeSysteme($commande) {
$handle = popen($commande, 'r');
$metaXml = '';
while (!feof($handle)) {
$metaXml .= fread($handle, 8192);
}
fclose($handle);
return $metaXml;
}
 
private function obtenirCheminImageRDF() {
return $this->obtenirCheminImage('RDF', 'xml');
}
 
private function obtenirCheminImageOriginale() {
return $this->obtenirCheminImage('O');
}
 
private function obtenirCheminImage($format, $extension = 'jpg') {
$nom = $this->convertirIdBddVersNomFichier($format, $extension);
$cheminDossier = $this->obtenirDossierPourFormat($format);
if (file_exists($cheminDossier) === false) {
$this->creerDossier($cheminDossier);
}
return $cheminDossier.'/'.$nom;
}
 
private function convertirIdBddVersNomFichier($format, $extension) {
$id_avec_zeros = sprintf('%09s', $this->idImg) ;
$id_avec_zeros_underscores = wordwrap($id_avec_zeros, 3 , '_', true) ;
$nom_fichier = $id_avec_zeros_underscores.'_'.$format.'.'.$extension;
return $nom_fichier;
}
 
private function obtenirDossierPourFormat($format) {
$id = sprintf('%09s', $this->idImg);
$id = wordwrap($id, 3 , '_', true);
list($dossierNiveau1, $dossierNiveau2) = explode('_', $id);
 
$chemin_sur_serveur_final = $this->chemin_images.'/'.$dossierNiveau1.'/'.$dossierNiveau2.'/'.$format;
return $chemin_sur_serveur_final;
}
 
private function creerDossier($cheminDossier) {
umask(0);
if (mkdir($cheminDossier, self::DROIT, true) === false) {
$message = "Problème durant la création du dossier '$cheminDossier'.";
throw new Exception($message);
}
}
 
private function neccessiterRemplacement($metaXml) {
$meta = new SimpleXMLElement($metaXml);
$rdf = $meta->children('http://www.w3.org/1999/02/22-rdf-syntax-ns#');
$file = $rdf->children('http://ns.exiftool.ca/File/1.0/');
return strpos($file->Comment, "CREATOR: gd-jpeg") === false ? true : false;
}
 
private function ecrireFichierRdf() {
$cheminRdf = $this->obtenirCheminImageRDF($this->idImg);
file_put_contents($cheminRdf, $this->metaComplet);
}
 
private function mettreAJourBdd() {
$idImg = $this->bdd->proteger($this->idImg);
$exif = $this->bdd->proteger($this->exif);
$iptc = $this->bdd->proteger($this->iptc);
$xmp = $this->bdd->proteger($this->xmp);
$makerNotes = $this->bdd->proteger($this->makerNotes);
$autres = $this->bdd->proteger($this->metaAutres);
 
$requete = 'UPDATE cel_images SET '.
" meta_exif = $exif, ".
" meta_iptc = $iptc, ".
" meta_xmp = $xmp, ".
" meta_makernote = $makerNotes, ".
" meta_autres = $autres ".
"WHERE id_image = $idImg ";
$resultat = $this->bdd->executer($requete);
 
echo "Mise à jour image '{$this->idImg}' : $resultat\n";
}
}
?>
/trunk/jrest/scripts/MigrationObs.php
New file
0,0 → 1,635
<?php
// declare(encoding='UTF-8');
/**
* Script de migration des Observations de la version 1 de la base de données du CEL à la v2.
* Utilisation : /opt/lampp/bin/php cli.php MigrationObs
*
* @category php 5.2
* @package Cel/Scripts
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class MigrationObs {
 
const truncate = true; //Doit on vider les tables de destination ?
const dry_run = false;
const PATTERN_LAT = '/^[+-]?(?:[1-9][0-9]|[0-9])(?:[.][0-9]+|)$/';
const PATTERN_LNG = '/^[+-]?(?:1[0-8][0-9]|[1-9][0-9]|[0-9])(?:[.][0-9]+|)$/';
 
private $bdd = null;
private $script = null;
public static $bdd_cel_migration;
public static $bdd_utilisateurs;
private $communesOubliees = array();
private $tableau_utilisateurs = array();
private $tableau_mots_cles = array();
private $tableau_zones_geo = array();
 
/** Tableau associatif permettant de stocker l'avancement dans une boucle.
* La clé est un md5 du message à afficher au démarrage de la boucle.
* @var array
*/
private static $avancement = array();
 
private $tableau_nouveau_ancien = array(
'id_observation' => 'id',
'ordre' => 'ordre',
'ce_utilisateur' => 'traiterIdentifiantUtilisateur',
'prenom_utilisateur' => 'traiterPrenomUtilisateur',
'nom_utilisateur' => 'traiterNomUtilisateur',
'courriel_utilisateur' => 'traiterCourrielUtilisateur',
'nom_sel' => 'nom_sel',
'nom_sel_nn' => 'num_nom_sel',
'nom_ret' => 'nom_ret',
'nom_ret_nn' => 'num_nom_ret',
'nt' => 'num_taxon',
'famille' => 'famille',
'nom_referentiel' => 'traiterReferentiel',
'ce_zone_geo' => 'traiterIdentifiantZoneGeo',
'zone_geo' => 'location',
'lieudit' => 'lieudit',
'station' => 'station',
'milieu' => 'milieu',
'latitude' => 'traiterLat',
'longitude' => 'traiterLng',
'geodatum' => 'traiterGeodatum',
'date_observation' => 'date_observation',
'mots_cles_texte' => 'traiterMotsClesTexte',
'commentaire' => 'commentaire',
'transmission' => 'transmission',
'date_creation' => 'date_creation',
'date_modification' => 'date_modification',
'date_transmission' => 'date_transmission'
);
 
private $tableau_ancien_nouveau = array(
'id' => 'id_observation',
'identifiant' => '',
'prenom_utilisateur' => 'prenom_utilisateur',
'nom_utilisateur' => 'nom_utilisateur',
'ordre' => 'ordre',
'nom_sel' => 'nom_sel',
'num_nom_sel' => 'nom_sel_nn',
'nom_ret' => 'nom_ret',
'num_nom_ret' => 'nom_ret_nn',
'num_taxon' => 'nt',
'famille' => 'famille',
'location' => '',
'id_location' => '',
'date_observation' => 'date_observation',
'lieu_dit' => 'lieudit',
'station' => 'station',
'milieu' => 'milieu',
'commentaire' => 'commentaire',
'transmission' => 'transmission',
'date_creation' => 'date_creation',
'date_modification' => 'date_modification',
'date_transmission' => 'date_transmission',
'mots_cles' => '',
'coord_x' => 'latitude',
'coord_y' => 'longitude',
'ref_geo' => 'geodatum'
);
 
public function __construct(Conteneur $conteneur) {
$bddMigration = $conteneur->getParametre('database_cel.database_migration');
if ($bddMigration == null || $bddMigration == '') {
echo 'Attention la variable de configuration database_migration dans la section database_cel, contenant la base de données d\'arrivée, doit être remplie '."\n";
exit;
}
$bddIdentification = $conteneur->getParametre('database_ident.database');
if ($bddIdentification == null || $bddIdentification == '') {
echo 'Attention la variable de configuration database dans la section database_ident, contenant la base de données utilisateurs, doit être remplie '."\n";
exit;
}
 
self::$bdd_cel_migration = $conteneur->getParametre('database_cel.database_migration');
self::$bdd_utilisateurs = $conteneur->getParametre('database_ident.database');
 
$this->bdd = $conteneur->getBdd();
$this->script = $conteneur->getScript();
}
 
/**
* Méthode appelée pour executer le script.
*/
public function executer($params) {
echo "--MIGRATION DES OBSERVATIONS --------------------------------------\n";
//1. TEMPORAIRE : vider les tables de destinations
if (self::truncate) {
echo "-------------------------------------------------------------------\n";
echo " ETAPE 0. Vider les tables ... \n";
echo "-------------------------------------------------------------------\n";
$nouvellesTables = array('cel_obs', 'cel_utilisateurs_infos', 'cel_zones_geo');
foreach ($nouvellesTables as $nomTable) {
echo 'Vider la table '.$nomTable.'...';
$requeteTruncate = 'TRUNCATE TABLE '.self::$bdd_cel_migration.'.'.$nomTable;
$resultatTruncate = $this->bdd->executer($requeteTruncate);
echo "ok \n";
}
}
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 1. Paramétrage ... \n";
echo "-------------------------------------------------------------------\n";
$this->getUtilisateurs();
$this->getMotsCles();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 2. Migration des utilisateurs ... \n";
echo "-------------------------------------------------------------------\n";
$this->migrerUtilisateurs();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 3. Migration des zone géographiques ... \n";
echo "-------------------------------------------------------------------\n";
$this->migrerZonesGeo();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 4. Migration des observations ... \n";
echo "-------------------------------------------------------------------\n";
$this->migrerObs();
$this->mettreANullPrenomNomVide();
$this->ordonnerObs();
}
 
private function executerRequeteSimple($requete) {
// Fonction de commodité pour afficher les requetes au lieu de les executer
if (self::dry_run) {
echo str_replace('),','),'."\n", $requete);
return true;
} else {
return $this->bdd->executer($requete);
}
}
 
private function getUtilisateurs() {
echo "SELECTION DES UTILISATEURS\n";
 
$requete = 'SELECT DISTINCT u_id AS id, u_mail AS mail, u_name AS nom, u_surname AS prenom, u_passwd AS pass '.
'FROM cel_inventory INNER JOIN '.self::$bdd_utilisateurs.'.annuaire_tela ON (u_mail = identifiant) ';
$tableau_utilisateurs = $this->bdd->requeter($requete);
 
foreach( $tableau_utilisateurs as &$utilisateur) {
$this->tableau_utilisateurs[$utilisateur['mail']] = $utilisateur;
}
 
echo sizeof($this->tableau_utilisateurs)." utilisateurs sélectionnés\n";
}
 
private function getMotsCles() {
echo "SELECTION DES MOTS-CLES \n";
 
$requete = 'SELECT cmc_id_proprietaire as id_utilisateur, cmc_id_mot_cle_utilisateur as id_mot_cle, '.
'cmc_mot_cle as mot_cle '.
'FROM cel_mots_cles_obs ';
$tableau_mots_cles = $this->bdd->requeter($requete);
 
foreach( $tableau_mots_cles as &$mot_cle) {
$this->tableau_mots_cles[$mot_cle['id_utilisateur']][$mot_cle['id_mot_cle']] = $mot_cle;
}
 
echo sizeof($this->tableau_mots_cles)." mots-clés sélectionnés\n";
}
 
private function migrerUtilisateurs() {
$requete = 'INSERT INTO '.self::$bdd_cel_migration.'.cel_utilisateurs_infos '.
'(id_utilisateur) '.
'VALUES ';
 
$sous_requete = array();
foreach ($this->tableau_utilisateurs as $id => &$utilisateur) {
$sous_requete[] = '('.$this->bdd->proteger($utilisateur['id']).')';
}
$requete .= implode(',', $sous_requete);
 
$migration_utilisateurs = $this->executerRequeteSimple($requete);
 
if ($migration_utilisateurs) {
echo "Migration utilisateurs : ".count($sous_requete);
} else {
exit('Erreur lors de la migration des utilisateurs '."\n");
}
echo "\n";
}
 
private function migrerZonesGeo() {
$pas = 5000;
 
//SELECTIONNER LE NOMBRE DE ZONE GEO
$requete_nombreZonesGeo = 'SELECT count(*) as nb FROM locations';
$resultatNbZonesGeo = $this->bdd->requeter($requete_nombreZonesGeo, Bdd::SQL_RETOUR_COLONNE);
$nbZones = (int) $resultatNbZonesGeo;
 
$nbTotal = 0;
for($i = 0; $i <= $nbZones ; $i += $pas) {
 
$requete_selection_zones_geo = 'SELECT * FROM locations LIMIT '.$i.', '.$pas;
 
$zones_geo = $this->bdd->requeter($requete_selection_zones_geo);
 
$requete_insertion_nouvelles_zones_geo = 'INSERT INTO '.self::$bdd_cel_migration.'.cel_zones_geo '.
'(id_zone_geo, code, nom, utm_secteur, utm_x, utm_y, wgs84_latitude, wgs84_longitude, date_modification) '.
'VALUES ';
 
$sous_requete_insertion_valeurs = '';
 
if(count($zones_geo) > 0) {
foreach($zones_geo as $zone_geo) {
 
$zone_geo['nouveau_code_geo'] = 'INSEE-C:'.$zone_geo['insee_code'];
$lat_long = $this->convertirUtmVersLatLong($zone_geo['x_utm'],$zone_geo['y_utm'],$zone_geo['sector']);
 
$indice_tableau_localites = $this->construireIndiceTableauLocalites($zone_geo['name'], $zone_geo['insee_code']);
$this->tableau_zones_geo[$indice_tableau_localites] = $zone_geo;
 
$sous_requete_insertion_valeurs .= '('.$this->bdd->proteger($zone_geo['nouveau_code_geo']).','.
$this->bdd->proteger($zone_geo['insee_code']).','.
$this->bdd->proteger($zone_geo['name']).','.
$this->bdd->proteger($zone_geo['sector']).','.
$this->bdd->proteger($zone_geo['x_utm']).','.
$this->bdd->proteger($zone_geo['y_utm']).','.
$this->bdd->proteger($lat_long['lat']).','.
$this->bdd->proteger($lat_long['long']).','.
$this->bdd->proteger($zone_geo['update_date']).
'),';
}
 
$sous_requete_insertion_valeurs = rtrim($sous_requete_insertion_valeurs,',');
 
$requete_insertion_nouvelles_zones_geo .= $sous_requete_insertion_valeurs;
 
$migration_zones_geo = $this->executerRequeteSimple($requete_insertion_nouvelles_zones_geo);
} else {
echo 'Fin de migration des zones géo '."\n";
return;
}
 
if ($migration_zones_geo) {
$nbTotal ++;
$this->script->afficherAvancement('Migration des zones (par '.$pas.')', $nbTotal);
} else {
exit('Erreur lors de la migration des zones géo '.$i.' à '.($i+$pas)."\n");
}
}
echo "\n";
}
 
private function convertirUtmVersLatLong($x, $y, $sector) {
$lat_long = array();
 
$convertisseur = new gPoint();
$convertisseur->setUTM($x, $y, $sector);
$convertisseur->convertTMtoLL();
$lat_long['lat'] = str_replace(',','.',$convertisseur->Lat());
$lat_long['long'] = str_replace(',','.',$convertisseur->Long());
 
return $lat_long;
}
 
private function migrerObs() {
$debut = 0;
$pas = 1000;
$nbTotal = 0;
 
//Selectionner le nombre d'observations
$requeteNbObs = "SELECT COUNT(*) as nb FROM cel_inventory";
$fin = $this->bdd->requeter($requeteNbObs, Bdd::SQL_RETOUR_COLONNE);
 
for ($i = $debut; $i < $fin ; $i += $pas) {
$requete_selection_obs = 'SELECT * '.
'FROM cel_inventory '.
'ORDER BY identifiant '.
'LIMIT '.$i.','.$pas;
$observations = $this->bdd->requeter($requete_selection_obs);
 
$requete_insertion_observations = 'INSERT IGNORE INTO '.self::$bdd_cel_migration.'.cel_obs (';
 
foreach ($this->tableau_nouveau_ancien as $nouveau_champ => $ancien_champ) {
$requete_insertion_observations .= $nouveau_champ.',';
}
 
$requete_insertion_observations = rtrim($requete_insertion_observations, ',');
$requete_insertion_observations = $requete_insertion_observations.') VALUES ';
 
if (count($observations) > 0) {
foreach($observations as $observation) {
$nouvelle_observation = $this->traiterLigneObservation($observation);
 
$nouvelle_observation = array_map(array($this, 'protegerSiNonNull'), $nouvelle_observation);
$requete_insertion_observations .= '('.join(',', array_values($nouvelle_observation)).'),';
}
 
$requete_insertion_observations = rtrim($requete_insertion_observations, ',');
 
$migration_observations = $this->executerRequeteSimple($requete_insertion_observations);
} else {
echo "Fin de migration des observations\n";
return;
}
 
if ($migration_observations) {
$nbTotal ++;
$this->script->afficherAvancement('Migration des observations (par '.$pas.')', $nbTotal);
} else {
exit('Erreur lors de la migration des observation de '.$i.' à '.($i+$pas)."\n");
}
}
echo "\n";
if (sizeof($this->communesOubliees) > 0) {
echo "xxxxxxxxx Communes ignorées : ".sizeof($this->communesOubliees)." xxxxxxxxx \n";
}
}
 
private function ordonnerObs() {
$requete = 'ALTER TABLE '.self::$bdd_cel_migration.'.cel_obs ORDER BY id_observation';
$this->executerRequeteSimple($requete);
}
 
private function traiterLigneObservation($obs) {
$nouvelle_obs = array();
foreach($this->tableau_nouveau_ancien as $nouveau_champ_obs => $ancien_champ_obs) {
if ($this->estUnChampATraiter($ancien_champ_obs)) {
if (method_exists($this, $ancien_champ_obs)) {
$nouvelle_obs[$nouveau_champ_obs] = $this->$ancien_champ_obs($obs);
} else {
$nouvelle_obs[$nouveau_champ_obs] = '';
}
} else {
if ($obs[$ancien_champ_obs] == '000null' || $obs[$ancien_champ_obs] == 'null' || trim($obs[$ancien_champ_obs]) == '') {
$obs[$ancien_champ_obs] = 'NULL';
}
 
if (($ancien_champ_obs == 'coord_x' || $ancien_champ_obs == 'coord_y') && ($obs[$ancien_champ_obs] == '0' || $obs[$ancien_champ_obs] == 0)) {
$obs[$ancien_champ_obs] = 'NULL';
}
 
$nouvelle_obs[$nouveau_champ_obs] = $obs[$ancien_champ_obs];
}
}
return $nouvelle_obs;
}
 
private function protegerSiNonNull($valeur) {
if ($valeur != 'NULL') {
$valeur = $this->bdd->proteger($valeur);
}
return $valeur;
}
 
private function estUnChampATraiter($champ) {
return strpos($champ,'traiter') !== false;
}
 
private function traiterReferentiel($observation) {
$retour = 'NULL';
if ($observation['num_nom_sel'] != '' && $observation['num_nom_sel'] != '0') {
$retour = 'bdnff:4.02';
if (isset($observation['nom_referentiel'])) {
$retour = ($observation['nom_referentiel'] == 'bdtfx:1.01') ? 'bdtfx:1.01' : 'bdnff:4.02';
}
}
return $retour;
}
 
private function traiterLat(&$observation) {
if ($this->bdd->etreNull($observation['coord_x'])) {
$observation['coord_x'] = 'NULL';
} else if (preg_match(self::PATTERN_LAT, $observation['coord_x']) == false) {
$latNote = 'Latitude éronnée : '.$observation['coord_x'];
if ($this->bdd->etreNull($observation['commentaire'])) {
$observation['commentaire'] = $latNote;
} else {
$observation['commentaire'] .= "\n".$latNote;
}
$observation['coord_x'] = 'NULL';
}
$retour = $observation['coord_x'];
return $retour;
}
 
private function traiterLng(&$observation) {
if ($this->bdd->etreNull($observation['coord_y'])) {
$observation['coord_y'] = 'NULL';
} else if (preg_match(self::PATTERN_LNG, $observation['coord_y']) == false) {
$lngNote = 'Longitude éronnée : '.$observation['coord_y'];
if ($this->bdd->etreNull($observation['commentaire'])) {
$observation['commentaire'] = $lngNote;
} else {
$observation['commentaire'] .= "\n".$lngNote;
}
$observation['coord_y'] = 'NULL';
}
$retour = $observation['coord_y'];
return $retour;
}
 
private function traiterGeodatum($observation) {
$retour = 'NULL';
if ($observation['coord_x'] != 'NULL' && $observation['coord_y'] != 'NULL') {
$retour = 'WGS84';
}
return $retour;
}
 
private function traiterMotsClesTexte($ligne_observation) {
$mail_observation = $ligne_observation['identifiant'];
$retour = $ligne_observation['mots_cles'];
if (isset($this->tableau_mots_cles[$mail_observation])) {
$mots_cles_tableau = $this->parserMotsCles($mail_observation, $ligne_observation['mots_cles'], ';');
$retour = join(',', $mots_cles_tableau);
$retour = ltrim($retour, ',,') ;
}
 
return $retour;
}
 
private function parserMotsCles($utilisateur, $mot_cles, $separateur = ',') {
$tableau_mots_cles = explode($separateur,$mot_cles);
$tableau_mots_cles_formates = array();
 
foreach ($tableau_mots_cles as $mot_cle) {
 
$mot_cle = str_replace($separateur.$separateur,'',$mot_cle);
$mot_cle = str_replace('null','',$mot_cle);
 
if ($this->estUnIdentifiantMotCle($mot_cle)) {
 
// certains mots clés mal formatés contiennent des virgules
if (strpos($mot_cle,',') !== false) {
$tab_mot_cle_mal_formate = explode(',',$mot_cle);
 
foreach ($tab_mot_cle_mal_formate as $mot_cle_mal_formate) {
if ($this->estUnIdentifiantMotCle($mot_cle_mal_formate)) {
$tableau_mots_cles_formates[$mot_cle_mal_formate] = $this->tableau_mots_cles[$utilisateur][$mot_cle_mal_formate]['mot_cle'];
}
}
} else {
// on met le mot clé dans sa propre case afin d'éviter
// facilement les doublons provoqués par de mauvais formatages
if (isset($this->tableau_mots_cles[$utilisateur][$mot_cle]) && trim($this->tableau_mots_cles[$utilisateur][$mot_cle]['mot_cle']) != '') {
$tableau_mots_cles_formates[$mot_cle] = $this->tableau_mots_cles[$utilisateur][$mot_cle]['mot_cle'];
}
}
 
}
}
 
return $tableau_mots_cles_formates;
}
 
private function estUnIdentifiantMotCle($chaine) {
return trim($chaine) != '' && preg_match('/[0-9A-Z]+\.[0-9A-Z]+/i', $chaine) ;
}
 
private function traiterIdentifiantUtilisateur($ligne_observation) {
$mail_observation = $ligne_observation['identifiant'];
$retour = $this->renvoyerIdPourMigration($mail_observation);
return $retour;
}
 
private function traiterPrenomUtilisateur($ligne_observation) {
$mail_observation = $ligne_observation['identifiant'];
 
$retour = '';
if (isset($this->tableau_utilisateurs[$mail_observation])) {
$prenom = $this->tableau_utilisateurs[$mail_observation]['prenom'];
$retour = self::formaterMotPremiereLettreChaqueMotEnMajuscule($prenom);
}
return $retour;
}
 
private function traiterNomUtilisateur($ligne_observation) {
$mail_observation = $ligne_observation['identifiant'];
 
$retour = 'NULL';
if (isset($this->tableau_utilisateurs[$mail_observation])) {
$nom = $this->tableau_utilisateurs[$mail_observation]['nom'];
$retour = self::formaterMotEnMajuscule($nom);
}
return $retour;
}
 
private function traiterCourrielUtilisateur($observation) {
$courriel = $observation['identifiant'];
 
$retour = 'NULL';
if ($this->mailValide($courriel)) {
$retour = $courriel;
}
return $retour;
}
 
 
public static function formaterMotPremiereLettreChaqueMotEnMajuscule($chaine, $encodage= 'UTF-8') {
$chaine = str_replace('-', ' - ', $chaine);
$chaine = mb_strtolower($chaine, $encodage);
$chaine = mb_convert_case($chaine, MB_CASE_TITLE, $encodage);
$chaine = str_replace(' - ', '-', $chaine);
return $chaine;
}
 
public static function formaterMotEnMajuscule($chaine, $encodage= 'UTF-8') {
return mb_convert_case($chaine, MB_CASE_UPPER, $encodage);
}
 
private function traiterZoneGeo($ligne_observation) {
 
$zone_geo = $ligne_observation['location'];
 
if ($ligne_observation['id_location'] != null && !is_numeric($ligne_observation['id_location']) && $ligne_observation['id_location'] != '000null') {
$id_zone_geo_ancienne = $ligne_observation['id_location'];
if ($zone_geo != '') {
$id_zone_geo_ancienne = '('.$id_zone_geo_ancienne.')';
}
 
$zone_geo .= $id_zone_geo_ancienne;
} else if ($ligne_observation['location'] == null || $ligne_observation['location'] == "" || $ligne_observation['location'] == "000null") {
 
if ($ligne_observation['id_location'] != '' && $ligne_observation['id_location'] != '000null') {
$id_zone_geo_ancienne = $ligne_observation['id_location'];
$id_zone_geo_ancienne = $id_zone_geo_ancienne;
$zone_geo = $id_zone_geo_ancienne;
} else {
$zones_geo = 'NULL';
}
}
 
return $zone_geo;
}
 
private function traiterIdentifiantZoneGeo($ligne_observation) {
$id_zone_geo = '';
 
if ($ligne_observation['id_location'] != '' && $ligne_observation['id_location'] != '000null') {
$indice = $this->construireIndiceTableauLocalites($ligne_observation['location'], $ligne_observation['id_location']);
if (isset($this->tableau_zones_geo[$indice])) {
$id_zone_geo = $this->tableau_zones_geo[$indice]['nouveau_code_geo'];
} else {
if ($ligne_observation['location'] != "000null") {
$this->communesOubliees[$indice] = false;
}
}
} else {
$id_zone_geo = 'NULL';
}
 
return $id_zone_geo;
}
 
private function construireIndiceTableauLocalites($nom, $id) {
$nom = htmlentities($nom, ENT_NOQUOTES, 'UTF-8');
 
$nom = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $nom);
$nom = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $nom); // pour les ligatures e.g. '&oelig;'
$nom = preg_replace('#&[^;]+;#', '', $nom); // supprime les autres caractères
 
$nom = str_replace("'",'_',$nom);
$nom = str_replace(' ','_',$nom);
$nom = str_replace('-','_',$nom);
$nom = str_replace(' ','_',$nom);
$indice = strtolower($nom).substr($id, 0, 2);
 
return $indice;
}
 
// Par défaut, on garde l'utilisateur tel quel (cas de la chaine de session des utilisateur anonymes)
private function renvoyerIdPourMigration($utilisateur) {
$retour = $utilisateur;
// si le mail correspond a un utilisateur de la bdd
if (isset($this->tableau_utilisateurs[$utilisateur])) {
// on renvoie son id
$retour = $this->tableau_utilisateurs[$utilisateur]['id'];
} else if ($utilisateur != '') {
// sinon si c'est un mail inconnu, on garde le md5
if ($this->mailValide($utilisateur)) {
$retour = md5($utilisateur);
}
} else if ($utilisateur == '') {
$retour = 'NULL';
}
return $retour;
}
 
private function mailValide($mail) {
// vérification bidon mais ça suffit pour ici
return !(strpos($mail, '@') === false);
}
 
private function mettreANullPrenomNomVide() {
$bdd = self::$bdd_cel_migration;
$requete = "UPDATE $bdd.cel_obs ".
'SET prenom_utilisateur = NULL '.
"WHERE prenom_utilisateur = '' ";
$this->bdd->executer($requete);
 
$requete = "UPDATE $bdd.cel_obs ".
'SET nom_utilisateur = NULL '.
"WHERE nom_utilisateur = '' ";
$this->bdd->executer($requete);
}
}
/trunk/jrest/scripts/MigrationReferentiel.php
New file
0,0 → 1,190
<?php
// declare(encoding='UTF-8');
/**
* Réalise la migration des obs du référentiel bdnff vers le référentie bdtfx
*
* @category php 5.2
* @package Cel/Scripts
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class MigrationReferentiel {
 
private $bdd = null;
private $script = null;
private $table_eflore = 'tb_eflore.bdtfx_v1_01';
private $table_cel = 'tb_cel.cel_obs';
private $correspondance_nn_sel_nn_ret = null;
private $infos_noms = array();
private $obs_sans_nn = array();
private $obs_a_modifier = array();
private $modif_douteuses = array();
private $modif_familles = 0;
private $chemin_log = '/home/telabotap/www/tmp/migration_noms_log.csv';
private $fp = null;
 
public function __construct(Conteneur $conteneur) {
$this->bdd = $conteneur->getBdd();
$this->script = $conteneur->getScript();
$this->initialiserLog();
}
 
public function executer($arguments) {
if (isset($arguments[0]) == false) {
throw new Exception("Veuillez indiquer l'action à réaliser en paramètre.", E_USER_ERROR);
}
$action = $arguments[0];
switch ($action) {
case 'migration_referentiel' :
$this->migrerReferentiel();
break;
}
fclose($this->fp);
}
private function migrerReferentiel() {
echo "-------------------------------------------------------------------\n";
echo " ETAPE 1. Paramétrage ... \n";
echo "-------------------------------------------------------------------\n";
$this->chargerInfosNoms();
echo "-------------------------------------------------------------------\n";
echo " ETAPE 2. Chargement des observations ... \n";
echo "-------------------------------------------------------------------\n";
$requete_selection_obs = 'SELECT id_observation, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, '.
'famille, nom_referentiel FROM '.$this->table_cel;
$liste_obs = $this->bdd->requeter($requete_selection_obs);
echo sizeof($liste_obs)." observations sélectionnées \n";
foreach ($liste_obs as $obs) {
if($this->doitChangerNomRetenu($obs)) {
$nouveau_nom = $this->getInfosNouveauNumNomRetenu($obs);
$this->obs_a_modifier[] = array(
'id' => $obs['id_observation'],
'nouveau_nom_sci_retenu' => $nouveau_nom['nom_complet'],
'nouveau_nn_retenu' => $nouveau_nom['num_nom'],
'nouveau_num_tax' => $nouveau_nom['num_taxonomique'],
'nouvelle_famille' => $nouveau_nom['famille']
);
$this->logger($obs, $nouveau_nom);
}
}
echo "-------------------------------------------------------------------\n";
echo " ETAPE 3. modification des observations ... \n";
echo "-------------------------------------------------------------------\n";
echo sizeof($this->obs_a_modifier)." obs doivent voir changer leur nom retenu \n";
echo $this->modif_familles." obs doivent voir changer leur famille \n";
echo sizeof($this->obs_sans_nn)." observations n'ont pas de num nom \n";
echo sizeof($this->modif_douteuses)." modifications sont douteuses et ne seront pas effectuées \n";
echo "\n";
$this->executerRequeteMiseAJour();
echo "\n";
echo "-------------------------------------------------------------------\n";
echo " Migration des noms terminée ... \n";
echo "-------------------------------------------------------------------\n";
}
private function chargerInfosNoms() {
$requete = 'SELECT num_nom, num_nom_retenu, nom_complet, num_taxonomique, famille FROM '.$this->table_eflore;
$nums = $this->bdd->requeter($requete);
foreach ($nums as $num) {
$this->correspondance_nn_sel_nn_ret[$num['num_nom']] = $num['num_nom_retenu'];
$this->infos_noms[$num['num_nom']] = $num;
}
echo sizeof($this->correspondance_nn_sel_nn_ret)." noms sélectionnés\n";
}
private function doitChangerNomRetenu($obs) {
$changement = false;
$nn_retenu_obs = $obs['nom_ret_nn'];
$nn_saisi_obs = $obs['nom_sel_nn'];
$famille_saisie_obs = $obs['famille'];
$sans_nn_retenu = false;
if($nn_saisi_obs != '') {
if(!isset($this->correspondance_nn_sel_nn_ret[$nn_saisi_obs]) || $this->correspondance_nn_sel_nn_ret[$nn_saisi_obs] == 0) {
$this->obs_sans_nn[] = $obs['id_observation'];
$sans_nn_retenu = true;
} else {
if($nn_retenu_obs != $this->correspondance_nn_sel_nn_ret[$nn_saisi_obs] && str_word_count($obs['nom_ret']) >= 1) {
$changement = true;
}
}
if(!$sans_nn_retenu && $famille_saisie_obs != $this->infos_noms[$nn_saisi_obs]['famille']) {
$changement = true;
$this->modif_familles++;
}
}
if($changement && str_word_count($obs['nom_ret']) == 1) {
$this->modif_douteuses[] = $obs;
$changement = false;
}
return $changement;
}
private function getInfosNouveauNumNomRetenu($obs) {
$nouveau_nn_ret = $this->correspondance_nn_sel_nn_ret[$obs['nom_sel_nn']];
return $this->infos_noms[$nouveau_nn_ret];
}
private function executerRequeteMiseAJour() {
$total = 0;
foreach($this->obs_a_modifier as $valeurs) {
$requete = $this->assemblerRequeteMiseAJour($valeurs);
$migration_noms = $this->bdd->executer($requete);
if ($migration_noms) {
$total++;
$this->script->afficherAvancement('Migration des noms (par 1)', $total);
} else {
echo $requete."\n";
exit('Erreur lors de la migration des noms de l\'observation '.$valeurs['id']."\n");
}
}
}
private function proteger($valeur) {
return $this->bdd->proteger($valeur);
}
private function assemblerRequeteMiseAJour($tableau) {
$requete = 'UPDATE '.$this->table_cel.' '.
'SET nom_ret = '.$this->proteger($tableau['nouveau_nom_sci_retenu']).', '.
'nom_ret_nn = '.$this->proteger($tableau['nouveau_nn_retenu']).', '.
'nt = '.$this->proteger($tableau['nouveau_num_tax']).', '.
'famille = '.$this->proteger($tableau['nouvelle_famille']).', '.
'nom_referentiel = "bdtfx:v1.01" '.
'WHERE id_observation = '.$this->proteger($tableau['id']);
return $requete;
}
private function initialiserLog() {
$this->fp = fopen($this->chemin_log, 'w');
$colonnes = 'nom sélectionné, nn nom sélectionné, ancien nom retenu, nn ancien nom retenu, '.
'nouveau nom sélectionné, nn nouveau nom sélectionné'."\n";
fwrite($this->fp, $colonnes);
}
private function logger($obs, $nouveau_nom) {
$chaine = '"'.$obs['nom_sel'].'"'.','.'"'.$obs['nom_sel_nn'].'"'.','.'"'.$obs['nom_ret'].'"'.','.
'"'.$obs['nom_ret_nn'].'"'.','.'"'.$nouveau_nom['nom_complet'].'"'.','.
'"'.$nouveau_nom['num_nom'].'"'."\n";
fwrite($this->fp, $chaine);
}
}
?>
/trunk/jrest/scripts/MigrationImages.php
New file
0,0 → 1,1032
<?php
// declare(encoding='UTF-8');
/**
* Script de migration des Images de la version 1 de la base de données du CEL à la v2.
* Utilisation : /opt/lampp/bin/php cli.php MigrationImages
*
* @category php 5.2
* @package Cel/Scripts
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class MigrationImages {
 
const dry_run = false;
const truncate = true; //Doit on vider les tables de destination ?
const separateur_champs_metadonnees = ';';
const separateur_valeurs_metadonnees = ':';
 
private $bdd = null;
private $script = null;
public static $bdd_cel_migration;
public static $bdd_utilisateurs;
private $cle_id_metadonnees = array();
private $tableau_utilisateurs = array();
private $tableau_observations = array();
private $tableau_mots_cles = array();
 
/** Tableau associatif permettant de stocker l'avancement dans une boucle.
* La clé est un md5 du message à afficher au démarrage de la boucle.
* @var array
*/
private static $avancement = array();
 
private $tableau_nouveau_ancien = array(
'id_image' => 'ci_id_image',
'ordre' =>'ci_ordre',
'ce_utilisateur' => 'traiterIdentifiantUtilisateur',
'prenom_utilisateur' => 'traiterPrenomUtilisateur',
'nom_utilisateur' => 'traiterNomUtilisateur',
'courriel_utilisateur' => 'ci_ce_utilisateur',
'hauteur' => 'ci_meta_height',
'largeur' => 'ci_meta_width',
'appareil_fabriquant' => 'ci_meta_make',
'appareil_modele' => 'ci_meta_model',
'date_prise_de_vue' => 'ci_meta_date_time',
'note_qualite' => 'traiterNoteImage',
'mots_cles_texte' => 'ci_meta_mots_cles',
'commentaire' => 'ci_meta_comment',
'nom_original' => 'ci_nom_original',
'md5' => 'ci_md5',
'meta_exif' => 'traiterExif',
'meta_iptc' => 'traiterIptc',
'meta_xmp' => 'traiterXmp',
'meta_makernote' => 'traiterMakernote',
'date_modification' => 'ci_meta_date',
'date_creation' => 'ci_meta_date_ajout'
);
 
private $champs_exifs_non_gardes = array(
'ci_meta_x_resolution',
'ci_meta_y_resolution',
'ci_meta_gps',
'ci_meta_user_comment',
'ci_meta_exif_exposure_time',
'ci_meta_exif_f_number',
'ci_meta_exif_exif_version',
'ci_meta_exif_compressed_bits_per_pixel',
'ci_meta_exif_shutter_speed_value',
'ci_meta_exif_aperture_value',
'ci_meta_exif_exposure_bias_value',
'ci_meta_exif_max_aperture_value',
'ci_meta_exif_metering_mode',
'ci_meta_exif_light_source',
'ci_meta_exif_flash',
'ci_meta_exif_focal_length',
'ci_meta_exif_flash_pix_version',
'ci_meta_exif_color_space',
'ci_meta_exif_interoperability_offset',
'ci_meta_exif_focal_plane_x_resolution',
'ci_meta_exif_focal_plane_y_resolution',
'ci_meta_exif_focal_plane_resolution_unit',
'ci_meta_exif_sensing_method',
'ci_meta_exif_file_source',
'ci_meta_exif_custom_rendered',
'ci_meta_exif_exposure_mode',
'ci_meta_exif_white_balance',
'ci_meta_exif_digital_zoom_ratio',
'ci_meta_exif_scene_capture_type',
'ci_meta_exif_gain_control',
'ci_meta_exif_contrast',
'ci_meta_exif_saturation',
'ci_meta_exif_sharpness',
'ci_meta_exif_subject_distance_range'
);
 
private $champs_iptc_non_gardes = array(
'ci_meta_iptc_category',
'ci_meta_iptc_by_line',
'ci_meta_iptc_by_line_title',
'ci_meta_iptc_city',
'ci_meta_iptc_sub_location',
'ci_meta_iptc_province_state',
'ci_meta_iptc_country_primary_location_code',
'ci_meta_iptc_country_name',
'ci_meta_iptc_headline',
'ci_meta_iptc_credit',
'ci_meta_iptc_copyright_notice',
'ci_meta_iptc_contact'
);
 
private $champs_divers_non_gardes = array(
'ci_publiable_eflore',
'ci_meta_mots_cles'
);
 
private $ids_tags_exif = array(
'InteropIndex' => array('id' => '1', 'tag' => 'InteropIndex', 'categorie' => 'InteropIFD'),
'InteropVersion' => array('id' => '2', 'tag' => 'InteropVersion', 'categorie' => 'InteropIFD'),
'ProcessingSoftware' => array('id' => '11', 'tag' => 'ProcessingSoftware', 'categorie' => 'IFD0'),
'SubfileType' => array('id' => '254', 'tag' => 'SubfileType', 'categorie' => 'IFD0'),
'OldSubfileType' => array('id' => '255', 'tag' => 'OldSubfileType', 'categorie' => 'IFD0'),
'ImageWidth' => array('id' => '256', 'tag' => 'ImageWidth', 'categorie' => 'IFD0'),
'ImageLength' => array('id' => '257', 'tag' => 'ImageHeight', 'categorie' => 'IFD0'),
'BitsPerSample' => array('id' => '258', 'tag' => 'BitsPerSample', 'categorie' => 'IFD0'),
'Compression' => array('id' => '259', 'tag' => 'Compression', 'categorie' => 'IFD0'),
'PhotometricInterpretation' => array('id' => '262', 'tag' => 'PhotometricInterpretation', 'categorie' => 'IFD0'),
'Thresholding' => array('id' => '263', 'tag' => 'Thresholding', 'categorie' => 'IFD0'),
'CellWidth' => array('id' => '264', 'tag' => 'CellWidth', 'categorie' => 'IFD0'),
'CellLength' => array('id' => '265', 'tag' => 'CellLength', 'categorie' => 'IFD0'),
'FillOrder' => array('id' => '266', 'tag' => 'FillOrder', 'categorie' => 'IFD0'),
'DocumentName' => array('id' => '269', 'tag' => 'DocumentName', 'categorie' => 'IFD0'),
'ImageDescription' => array('id' => '270', 'tag' => 'ImageDescription', 'categorie' => 'IFD0'),
'Make' => array('id' => '271', 'tag' => 'Make', 'categorie' => 'IFD0'),
'Model' => array('id' => '272', 'tag' => 'Model', 'categorie' => 'IFD0'),
'StripOffsets' => array('id' => '273', 'tag' => 'StripOffsets', 'categorie' => 'IFD0'),
'Orientation' => array('id' => '274', 'tag' => 'Orientation', 'categorie' => 'IFD0'),
'SamplesPerPixel' => array('id' => '277', 'tag' => 'SamplesPerPixel', 'categorie' => 'IFD0'),
'RowsPerStrip' => array('id' => '278', 'tag' => 'RowsPerStrip', 'categorie' => 'IFD0'),
'StripByteCounts' => array('id' => '279', 'tag' => 'StripByteCounts', 'categorie' => 'IFD0'),
'MinSampleValue' => array('id' => '280', 'tag' => 'MinSampleValue', 'categorie' => 'IFD0'),
'MaxSampleValue' => array('id' => '281', 'tag' => 'MaxSampleValue', 'categorie' => 'IFD0'),
'XResolution' => array('id' => '282', 'tag' => 'XResolution', 'categorie' => 'IFD0'),
'YResolution' => array('id' => '283', 'tag' => 'YResolution', 'categorie' => 'IFD0'),
'PlanarConfiguration' => array('id' => '284', 'tag' => 'PlanarConfiguration', 'categorie' => 'IFD0'),
'PageName' => array('id' => '285', 'tag' => 'PageName', 'categorie' => 'IFD0'),
'XPosition' => array('id' => '286', 'tag' => 'XPosition', 'categorie' => 'IFD0'),
'YPosition' => array('id' => '287', 'tag' => 'YPosition', 'categorie' => 'IFD0'),
'FreeOffsets' => array('id' => '288', 'tag' => 'FreeOffsets', 'categorie' => 'Unknown'),
'FreeByteCounts' => array('id' => '289', 'tag' => 'FreeByteCounts', 'categorie' => 'Unknown'),
'GrayResponseUnit' => array('id' => '290', 'tag' => 'GrayResponseUnit', 'categorie' => 'IFD0'),
'GrayResponseCurve' => array('id' => '291', 'tag' => 'GrayResponseCurve', 'categorie' => 'Unknown'),
'T4Options' => array('id' => '292', 'tag' => 'T4Options', 'categorie' => 'Unknown'),
'T6Options' => array('id' => '293', 'tag' => 'T6Options', 'categorie' => 'Unknown'),
'ResolutionUnit' => array('id' => '296', 'tag' => 'ResolutionUnit', 'categorie' => 'IFD0'),
'PageNumber' => array('id' => '297', 'tag' => 'PageNumber', 'categorie' => 'IFD0'),
'ColorResponseUnit' => array('id' => '300', 'tag' => 'ColorResponseUnit', 'categorie' => 'Unknown'),
'TransferFunction' => array('id' => '301', 'tag' => 'TransferFunction', 'categorie' => 'IFD0'),
'Software' => array('id' => '305', 'tag' => 'Software', 'categorie' => 'IFD0'),
'ModifyDate' => array('id' => '306', 'tag' => 'ModifyDate', 'categorie' => 'IFD0'),
'DateTime' => array('id' => '306', 'tag' => 'ModifyDate', 'categorie' => 'IFD0'),
'Artist' => array('id' => '315', 'tag' => 'Artist', 'categorie' => 'IFD0'),
'HostComputer' => array('id' => '316', 'tag' => 'HostComputer', 'categorie' => 'IFD0'),
'Predictor' => array('id' => '317', 'tag' => 'Predictor', 'categorie' => 'IFD0'),
'WhitePoint' => array('id' => '318', 'tag' => 'WhitePoint', 'categorie' => 'IFD0'),
'PrimaryChromaticities' => array('id' => '319', 'tag' => 'PrimaryChromaticities', 'categorie' => 'IFD0'),
'ColorMap' => array('id' => '320', 'tag' => 'ColorMap', 'categorie' => 'Unknown'),
'HalftoneHints' => array('id' => '321', 'tag' => 'HalftoneHints', 'categorie' => 'IFD0'),
'TileWidth' => array('id' => '322', 'tag' => 'TileWidth', 'categorie' => 'IFD0'),
'TileLength' => array('id' => '323', 'tag' => 'TileLength', 'categorie' => 'IFD0'),
'TileOffsets' => array('id' => '324', 'tag' => 'TileOffsets', 'categorie' => 'Unknown'),
'TileByteCounts' => array('id' => '325', 'tag' => 'TileByteCounts', 'categorie' => 'Unknown'),
'BadFaxLines' => array('id' => '326', 'tag' => 'BadFaxLines', 'categorie' => 'Unknown'),
'CleanFaxData' => array('id' => '327', 'tag' => 'CleanFaxData', 'categorie' => 'Unknown'),
'ConsecutiveBadFaxLines' => array('id' => '328', 'tag' => 'ConsecutiveBadFaxLines', 'categorie' => 'Unknown'),
'SubIFD' => array('id' => '330', 'tag' => 'SubIFD', 'categorie' => 'Unknown'),
'InkSet' => array('id' => '332', 'tag' => 'InkSet', 'categorie' => 'IFD0'),
'InkNames' => array('id' => '333', 'tag' => 'InkNames', 'categorie' => 'Unknown'),
'NumberofInks' => array('id' => '334', 'tag' => 'NumberofInks', 'categorie' => 'Unknown'),
'DotRange' => array('id' => '336', 'tag' => 'DotRange', 'categorie' => 'IFD0'),
'TargetPrinter' => array('id' => '337', 'tag' => 'TargetPrinter', 'categorie' => 'Unknown'),
'ExtraSamples' => array('id' => '338', 'tag' => 'ExtraSamples', 'categorie' => 'Unknown'),
'SampleFormat' => array('id' => '339', 'tag' => 'SampleFormat', 'categorie' => 'Unknown'),
'SMinSampleValue' => array('id' => '340', 'tag' => 'SMinSampleValue', 'categorie' => 'Unknown'),
'SMaxSampleValue' => array('id' => '341', 'tag' => 'SMaxSampleValue', 'categorie' => 'Unknown'),
'TransferRange' => array('id' => '342', 'tag' => 'TransferRange', 'categorie' => 'Unknown'),
'ClipPath' => array('id' => '343', 'tag' => 'ClipPath', 'categorie' => 'Unknown'),
'XClipPathUnits' => array('id' => '344', 'tag' => 'XClipPathUnits', 'categorie' => 'Unknown'),
'YClipPathUnits' => array('id' => '345', 'tag' => 'YClipPathUnits', 'categorie' => 'Unknown'),
'Indexed' => array('id' => '346', 'tag' => 'Indexed', 'categorie' => 'Unknown'),
'JPEGTables' => array('id' => '347', 'tag' => 'JPEGTables', 'categorie' => 'Unknown'),
'OPIProxy' => array('id' => '351', 'tag' => 'OPIProxy', 'categorie' => 'Unknown'),
'GlobalParametersIFD' => array('id' => '400', 'tag' => 'GlobalParametersIFD', 'categorie' => 'Unknown'),
'ProfileType' => array('id' => '401', 'tag' => 'ProfileType', 'categorie' => 'Unknown'),
'FaxProfile' => array('id' => '402', 'tag' => 'FaxProfile', 'categorie' => 'Unknown'),
'CodingMethods' => array('id' => '403', 'tag' => 'CodingMethods', 'categorie' => 'Unknown'),
'VersionYear' => array('id' => '404', 'tag' => 'VersionYear', 'categorie' => 'Unknown'),
'ModeNumber' => array('id' => '405', 'tag' => 'ModeNumber', 'categorie' => 'Unknown'),
'Decode' => array('id' => '433', 'tag' => 'Decode', 'categorie' => 'Unknown'),
'DefaultImageColor' => array('id' => '434', 'tag' => 'DefaultImageColor', 'categorie' => 'Unknown'),
'T82Options' => array('id' => '435', 'tag' => 'T82Options', 'categorie' => 'Unknown'),
'JPEGProc' => array('id' => '512', 'tag' => 'JPEGProc', 'categorie' => 'Unknown'),
'ThumbnailOffset' => array('id' => '513', 'tag' => 'ThumbnailOffset', 'categorie' => 'IFD1'),
'ThumbnailLength' => array('id' => '514', 'tag' => 'ThumbnailLength', 'categorie' => 'IFD1'),
'JPEGRestartInterval' => array('id' => '515', 'tag' => 'JPEGRestartInterval', 'categorie' => 'Unknown'),
'JPEGLosslessPredictors' => array('id' => '517', 'tag' => 'JPEGLosslessPredictors', 'categorie' => 'Unknown'),
'JPEGPointTransforms' => array('id' => '518', 'tag' => 'JPEGPointTransforms', 'categorie' => 'Unknown'),
'JPEGQTables' => array('id' => '519', 'tag' => 'JPEGQTables', 'categorie' => 'Unknown'),
'JPEGDCTables' => array('id' => '520', 'tag' => 'JPEGDCTables', 'categorie' => 'Unknown'),
'JPEGACTables' => array('id' => '521', 'tag' => 'JPEGACTables', 'categorie' => 'Unknown'),
'YCbCrCoefficients' => array('id' => '529', 'tag' => 'YCbCrCoefficients', 'categorie' => 'IFD0'),
'YCbCrSubSampling' => array('id' => '530', 'tag' => 'YCbCrSubSampling', 'categorie' => 'IFD0'),
'YCbCrPositioning' => array('id' => '531', 'tag' => 'YCbCrPositioning', 'categorie' => 'IFD0'),
'ReferenceBlackWhite' => array('id' => '532', 'tag' => 'ReferenceBlackWhite', 'categorie' => 'IFD0'),
'StripRowCounts' => array('id' => '559', 'tag' => 'StripRowCounts', 'categorie' => 'Unknown'),
'ApplicationNotes' => array('id' => '700', 'tag' => 'ApplicationNotes', 'categorie' => 'ExifIFD'),
'USPTOMiscellaneous' => array('id' => '999', 'tag' => 'USPTOMiscellaneous', 'categorie' => 'Unknown'),
'RelatedImageFileFormat' => array('id' => '4096', 'tag' => 'RelatedImageFileFormat', 'categorie' => 'InteropIFD'),
'RelatedImageWidth' => array('id' => '4097', 'tag' => 'RelatedImageWidth', 'categorie' => 'InteropIFD'),
'RelatedImageHeight' => array('id' => '4098', 'tag' => 'RelatedImageHeight', 'categorie' => 'InteropIFD'),
'RelatedImageLength' => array('id' => '4098', 'tag' => 'RelatedImageHeight', 'categorie' => 'InteropIFD'),
'Rating' => array('id' => '18246', 'tag' => 'Rating', 'categorie' => 'IFD0'),
'XP_DIP_XML' => array('id' => '18247', 'tag' => 'XP_DIP_XML', 'categorie' => 'Unknown'),
'StitchInfo' => array('id' => '18248', 'tag' => 'StitchInfo', 'categorie' => 'Unknown'),
'RatingPercent' => array('id' => '18249', 'tag' => 'RatingPercent', 'categorie' => 'IFD0'),
'ImageID' => array('id' => '32781', 'tag' => 'ImageID', 'categorie' => 'Unknown'),
'WangTag1' => array('id' => '32931', 'tag' => 'WangTag1', 'categorie' => 'Unknown'),
'WangAnnotation' => array('id' => '32932', 'tag' => 'WangAnnotation', 'categorie' => 'Unknown'),
'WangTag3' => array('id' => '32933', 'tag' => 'WangTag3', 'categorie' => 'Unknown'),
'WangTag4' => array('id' => '32934', 'tag' => 'WangTag4', 'categorie' => 'Unknown'),
'Matteing' => array('id' => '32995', 'tag' => 'Matteing', 'categorie' => 'Unknown'),
'DataType' => array('id' => '32996', 'tag' => 'DataType', 'categorie' => 'Unknown'),
'ImageDepth' => array('id' => '32997', 'tag' => 'ImageDepth', 'categorie' => 'Unknown'),
'TileDepth' => array('id' => '32998', 'tag' => 'TileDepth', 'categorie' => 'Unknown'),
'Model2' => array('id' => '33405', 'tag' => 'Model2', 'categorie' => 'Unknown'),
'CFARepeatPatternDim' => array('id' => '33421', 'tag' => 'CFARepeatPatternDim', 'categorie' => 'Unknown'),
'CFAPattern2' => array('id' => '33422', 'tag' => 'CFAPattern2', 'categorie' => 'Unknown'),
'BatteryLevel' => array('id' => '33423', 'tag' => 'BatteryLevel', 'categorie' => 'Unknown'),
'KodakIFD' => array('id' => '33424', 'tag' => 'KodakIFD', 'categorie' => 'Unknown'),
'Copyright' => array('id' => '33432', 'tag' => 'Copyright', 'categorie' => 'IFD0'),
'ExposureTime' => array('id' => '33434', 'tag' => 'ExposureTime', 'categorie' => 'ExifIFD'),
'FNumber' => array('id' => '33437', 'tag' => 'FNumber', 'categorie' => 'ExifIFD'),
'MDFileTag' => array('id' => '33445', 'tag' => 'MDFileTag', 'categorie' => 'Unknown'),
'MDScalePixel' => array('id' => '33446', 'tag' => 'MDScalePixel', 'categorie' => 'Unknown'),
'MDColorTable' => array('id' => '33447', 'tag' => 'MDColorTable', 'categorie' => 'Unknown'),
'MDLabName' => array('id' => '33448', 'tag' => 'MDLabName', 'categorie' => 'Unknown'),
'MDSampleInfo' => array('id' => '33449', 'tag' => 'MDSampleInfo', 'categorie' => 'Unknown'),
'MDPrepDate' => array('id' => '33450', 'tag' => 'MDPrepDate', 'categorie' => 'Unknown'),
'MDPrepTime' => array('id' => '33451', 'tag' => 'MDPrepTime', 'categorie' => 'Unknown'),
'MDFileUnits' => array('id' => '33452', 'tag' => 'MDFileUnits', 'categorie' => 'Unknown'),
'PixelScale' => array('id' => '33550', 'tag' => 'PixelScale', 'categorie' => 'Unknown'),
'AdventScale' => array('id' => '33589', 'tag' => 'AdventScale', 'categorie' => 'Unknown'),
'AdventRevision' => array('id' => '33590', 'tag' => 'AdventRevision', 'categorie' => 'Unknown'),
'UIC1Tag' => array('id' => '33628', 'tag' => 'UIC1Tag', 'categorie' => 'Unknown'),
'UIC2Tag' => array('id' => '33629', 'tag' => 'UIC2Tag', 'categorie' => 'Unknown'),
'UIC3Tag' => array('id' => '33630', 'tag' => 'UIC3Tag', 'categorie' => 'Unknown'),
'UIC4Tag' => array('id' => '33631', 'tag' => 'UIC4Tag', 'categorie' => 'Unknown'),
'IPTC-NAA' => array('id' => '33723', 'tag' => 'IPTC-NAA', 'categorie' => 'IFD0'),
'IntergraphPacketData' => array('id' => '33918', 'tag' => 'IntergraphPacketData', 'categorie' => 'Unknown'),
'IntergraphFlagRegisters' => array('id' => '33919', 'tag' => 'IntergraphFlagRegisters', 'categorie' => 'Unknown'),
'IntergraphMatrix' => array('id' => '33920', 'tag' => 'IntergraphMatrix', 'categorie' => 'Unknown'),
'INGRReserved' => array('id' => '33921', 'tag' => 'INGRReserved', 'categorie' => 'Unknown'),
'ModelTiePoint' => array('id' => '33922', 'tag' => 'ModelTiePoint', 'categorie' => 'Unknown'),
'Site' => array('id' => '34016', 'tag' => 'Site', 'categorie' => 'Unknown'),
'ColorSequence' => array('id' => '34017', 'tag' => 'ColorSequence', 'categorie' => 'Unknown'),
'IT8Header' => array('id' => '34018', 'tag' => 'IT8Header', 'categorie' => 'Unknown'),
'RasterPadding' => array('id' => '34019', 'tag' => 'RasterPadding', 'categorie' => 'Unknown'),
'BitsPerRunLength' => array('id' => '34020', 'tag' => 'BitsPerRunLength', 'categorie' => 'Unknown'),
'BitsPerExtendedRunLength' => array('id' => '34021', 'tag' => 'BitsPerExtendedRunLength', 'categorie' => 'Unknown'),
'ColorTable' => array('id' => '34022', 'tag' => 'ColorTable', 'categorie' => 'Unknown'),
'ImageColorIndicator' => array('id' => '34023', 'tag' => 'ImageColorIndicator', 'categorie' => 'Unknown'),
'BackgroundColorIndicator' => array('id' => '34024', 'tag' => 'BackgroundColorIndicator', 'categorie' => 'Unknown'),
'ImageColorValue' => array('id' => '34025', 'tag' => 'ImageColorValue', 'categorie' => 'Unknown'),
'BackgroundColorValue' => array('id' => '34026', 'tag' => 'BackgroundColorValue', 'categorie' => 'Unknown'),
'PixelIntensityRange' => array('id' => '34027', 'tag' => 'PixelIntensityRange', 'categorie' => 'Unknown'),
'TransparencyIndicator' => array('id' => '34028', 'tag' => 'TransparencyIndicator', 'categorie' => 'Unknown'),
'ColorCharacterization' => array('id' => '34029', 'tag' => 'ColorCharacterization', 'categorie' => 'Unknown'),
'HCUsage' => array('id' => '34030', 'tag' => 'HCUsage', 'categorie' => 'Unknown'),
'TrapIndicator' => array('id' => '34031', 'tag' => 'TrapIndicator', 'categorie' => 'Unknown'),
'CMYKEquivalent' => array('id' => '34032', 'tag' => 'CMYKEquivalent', 'categorie' => 'Unknown'),
'SEMInfo' => array('id' => '34118', 'tag' => 'SEMInfo', 'categorie' => 'IFD0'),
'AFCP_IPTC' => array('id' => '34152', 'tag' => 'AFCP_IPTC', 'categorie' => 'Unknown'),
'PixelMagicJBIGOptions' => array('id' => '34232', 'tag' => 'PixelMagicJBIGOptions', 'categorie' => 'Unknown'),
'ModelTransform' => array('id' => '34264', 'tag' => 'ModelTransform', 'categorie' => 'Unknown'),
'WB_GRGBLevels' => array('id' => '34306', 'tag' => 'WB_GRGBLevels', 'categorie' => 'Unknown'),
'LeafData' => array('id' => '34310', 'tag' => 'LeafData', 'categorie' => 'Unknown'),
'PhotoshopSettings' => array('id' => '34377', 'tag' => 'PhotoshopSettings', 'categorie' => 'Unknown'),
'ExifIFDPointer' => array('id' => '34665', 'tag' => 'ExifOffset', 'categorie' => 'Unknown'),
'ICC_Profile' => array('id' => '34675', 'tag' => 'ICC_Profile', 'categorie' => 'Unknown'),
'TIFF_FXExtensions' => array('id' => '34687', 'tag' => 'TIFF_FXExtensions', 'categorie' => 'Unknown'),
'MultiProfiles' => array('id' => '34688', 'tag' => 'MultiProfiles', 'categorie' => 'Unknown'),
'SharedData' => array('id' => '34689', 'tag' => 'SharedData', 'categorie' => 'Unknown'),
'T88Options' => array('id' => '34690', 'tag' => 'T88Options', 'categorie' => 'Unknown'),
'ImageLayer' => array('id' => '34732', 'tag' => 'ImageLayer', 'categorie' => 'Unknown'),
'GeoTiffDirectory' => array('id' => '34735', 'tag' => 'GeoTiffDirectory', 'categorie' => 'Unknown'),
'GeoTiffDoubleParams' => array('id' => '34736', 'tag' => 'GeoTiffDoubleParams', 'categorie' => 'Unknown'),
'GeoTiffAsciiParams' => array('id' => '34737', 'tag' => 'GeoTiffAsciiParams', 'categorie' => 'Unknown'),
'ExposureProgram' => array('id' => '34850', 'tag' => 'ExposureProgram', 'categorie' => 'ExifIFD'),
'SpectralSensitivity' => array('id' => '34852', 'tag' => 'SpectralSensitivity', 'categorie' => 'ExifIFD'),
'GPSIFDPointer' => array('id' => '34853', 'tag' => 'GPSInfo', 'categorie' => 'Unknown'),
'ISO' => array('id' => '34855', 'tag' => 'ISO', 'categorie' => 'ExifIFD'),
'ISOSpeedRatings' => array('id' => '34855', 'tag' => 'ISO', 'categorie' => 'ExifIFD'),
'PhotographicSensitivity' => array('id' => '34855', 'tag' => 'ISO', 'categorie' => 'ExifIFD'),
'Opto-ElectricConvFactor' => array('id' => '34856', 'tag' => 'Opto-ElectricConvFactor', 'categorie' => 'Unknown'),
'OECF' => array('id' => '34856', 'tag' => 'Opto-ElectricConvFactor', 'categorie' => 'Unknown'),
'Interlace' => array('id' => '34857', 'tag' => 'Interlace', 'categorie' => 'Unknown'),
'TimeZoneOffset' => array('id' => '34858', 'tag' => 'TimeZoneOffset', 'categorie' => 'ExifIFD'),
'SelfTimerMode' => array('id' => '34859', 'tag' => 'SelfTimerMode', 'categorie' => 'ExifIFD'),
'SensitivityType' => array('id' => '34864', 'tag' => 'SensitivityType', 'categorie' => 'ExifIFD'),
'StandardOutputSensitivity' => array('id' => '34865', 'tag' => 'StandardOutputSensitivity', 'categorie' => 'ExifIFD'),
'RecommendedExposureIndex' => array('id' => '34866', 'tag' => 'RecommendedExposureIndex', 'categorie' => 'ExifIFD'),
'ISOSpeed' => array('id' => '34867', 'tag' => 'ISOSpeed', 'categorie' => 'ExifIFD'),
'ISOSpeedLatitudeyyy' => array('id' => '34868', 'tag' => 'ISOSpeedLatitudeyyy', 'categorie' => 'ExifIFD'),
'ISOSpeedLatitudezzz' => array('id' => '34869', 'tag' => 'ISOSpeedLatitudezzz', 'categorie' => 'ExifIFD'),
'FaxRecvParams' => array('id' => '34908', 'tag' => 'FaxRecvParams', 'categorie' => 'Unknown'),
'FaxSubAddress' => array('id' => '34909', 'tag' => 'FaxSubAddress', 'categorie' => 'Unknown'),
'FaxRecvTime' => array('id' => '34910', 'tag' => 'FaxRecvTime', 'categorie' => 'Unknown'),
'LeafSubIFD' => array('id' => '34954', 'tag' => 'LeafSubIFD', 'categorie' => 'Unknown'),
'ExifVersion' => array('id' => '36864', 'tag' => 'ExifVersion', 'categorie' => 'ExifIFD'),
'DateTimeOriginal' => array('id' => '36867', 'tag' => 'DateTimeOriginal', 'categorie' => 'ExifIFD'),
'CreateDate' => array('id' => '36868', 'tag' => 'CreateDate', 'categorie' => 'ExifIFD'),
'DateTimeDigitized' => array('id' => '36868', 'tag' => 'CreateDate', 'categorie' => 'ExifIFD'),
'ComponentsConfiguration' => array('id' => '37121', 'tag' => 'ComponentsConfiguration', 'categorie' => 'ExifIFD'),
'CompressedBitsPerPixel' => array('id' => '37122', 'tag' => 'CompressedBitsPerPixel', 'categorie' => 'ExifIFD'),
'ShutterSpeedValue' => array('id' => '37377', 'tag' => 'ShutterSpeedValue', 'categorie' => 'ExifIFD'),
'ApertureValue' => array('id' => '37378', 'tag' => 'ApertureValue', 'categorie' => 'ExifIFD'),
'BrightnessValue' => array('id' => '37379', 'tag' => 'BrightnessValue', 'categorie' => 'ExifIFD'),
'ExposureBiasValue' => array('id' => '37380', 'tag' => 'ExposureCompensation', 'categorie' => 'ExifIFD'),
'MaxApertureValue' => array('id' => '37381', 'tag' => 'MaxApertureValue', 'categorie' => 'ExifIFD'),
'SubjectDistance' => array('id' => '37382', 'tag' => 'SubjectDistance', 'categorie' => 'ExifIFD'),
'MeteringMode' => array('id' => '37383', 'tag' => 'MeteringMode', 'categorie' => 'ExifIFD'),
'LightSource' => array('id' => '37384', 'tag' => 'LightSource', 'categorie' => 'ExifIFD'),
'Flash' => array('id' => '37385', 'tag' => 'Flash', 'categorie' => 'ExifIFD'),
'FocalLength' => array('id' => '37386', 'tag' => 'FocalLength', 'categorie' => 'ExifIFD'),
'FlashEnergy' => array('id' => '37387', 'tag' => 'FlashEnergy', 'categorie' => 'Unknown'),
'SpatialFrequencyResponse' => array('id' => '37388', 'tag' => 'SpatialFrequencyResponse', 'categorie' => 'Unknown'),
'Noise' => array('id' => '37389', 'tag' => 'Noise', 'categorie' => 'Unknown'),
'FocalPlaneXResolution' => array('id' => '37390', 'tag' => 'FocalPlaneXResolution', 'categorie' => 'Unknown'),
'FocalPlaneYResolution' => array('id' => '37391', 'tag' => 'FocalPlaneYResolution', 'categorie' => 'Unknown'),
'FocalPlaneResolutionUnit' => array('id' => '37392', 'tag' => 'FocalPlaneResolutionUnit', 'categorie' => 'Unknown'),
'ImageNumber' => array('id' => '37393', 'tag' => 'ImageNumber', 'categorie' => 'ExifIFD'),
'SecurityClassification' => array('id' => '37394', 'tag' => 'SecurityClassification', 'categorie' => 'ExifIFD'),
'ImageHistory' => array('id' => '37395', 'tag' => 'ImageHistory', 'categorie' => 'ExifIFD'),
'SubjectArea' => array('id' => '37396', 'tag' => 'SubjectArea', 'categorie' => 'ExifIFD'),
'ExposureIndex' => array('id' => '37397', 'tag' => 'ExposureIndex', 'categorie' => 'Unknown'),
'TIFF-EPStandardID' => array('id' => '37398', 'tag' => 'TIFF-EPStandardID', 'categorie' => 'Unknown'),
'SensingMethod' => array('id' => '37399', 'tag' => 'SensingMethod', 'categorie' => 'Unknown'),
'CIP3DataFile' => array('id' => '37434', 'tag' => 'CIP3DataFile', 'categorie' => 'Unknown'),
'CIP3Sheet' => array('id' => '37435', 'tag' => 'CIP3Sheet', 'categorie' => 'Unknown'),
'CIP3Side' => array('id' => '37436', 'tag' => 'CIP3Side', 'categorie' => 'Unknown'),
'StoNits' => array('id' => '37439', 'tag' => 'StoNits', 'categorie' => 'Unknown'),
'MakerNote' => array('id' => '37500', 'tag' => 'MakerNote', 'categorie' => 'ExifIFD'),
'UserComment' => array('id' => '37510', 'tag' => 'UserComment', 'categorie' => 'ExifIFD'),
'SubSecTime' => array('id' => '37520', 'tag' => 'SubSecTime', 'categorie' => 'ExifIFD'),
'SubSecTimeOriginal' => array('id' => '37521', 'tag' => 'SubSecTimeOriginal', 'categorie' => 'ExifIFD'),
'SubSecTimeDigitized' => array('id' => '37522', 'tag' => 'SubSecTimeDigitized', 'categorie' => 'ExifIFD'),
'MSDocumentText' => array('id' => '37679', 'tag' => 'MSDocumentText', 'categorie' => 'Unknown'),
'MSPropertySetStorage' => array('id' => '37680', 'tag' => 'MSPropertySetStorage', 'categorie' => 'Unknown'),
'MSDocumentTextPosition' => array('id' => '37681', 'tag' => 'MSDocumentTextPosition', 'categorie' => 'Unknown'),
'ImageSourceData' => array('id' => '37724', 'tag' => 'ImageSourceData', 'categorie' => 'IFD0'),
'XPTitle' => array('id' => '40091', 'tag' => 'XPTitle', 'categorie' => 'IFD0'),
'XPComment' => array('id' => '40092', 'tag' => 'XPComment', 'categorie' => 'IFD0'),
'XPAuthor' => array('id' => '40093', 'tag' => 'XPAuthor', 'categorie' => 'IFD0'),
'XPKeywords' => array('id' => '40094', 'tag' => 'XPKeywords', 'categorie' => 'IFD0'),
'XPSubject' => array('id' => '40095', 'tag' => 'XPSubject', 'categorie' => 'IFD0'),
'FlashPixVersion' => array('id' => '40960', 'tag' => 'FlashpixVersion', 'categorie' => 'ExifIFD'),
'ColorSpace' => array('id' => '40961', 'tag' => 'ColorSpace', 'categorie' => 'ExifIFD'),
'ExifImageWidth' => array('id' => '40962', 'tag' => 'ExifImageWidth', 'categorie' => 'ExifIFD'),
'PixelXDimension' => array('id' => '40962', 'tag' => 'ExifImageWidth', 'categorie' => 'ExifIFD'),
'ExifImageHeight' => array('id' => '40963', 'tag' => 'ExifImageHeight', 'categorie' => 'ExifIFD'),
'PixelYDimension' => array('id' => '40963', 'tag' => 'ExifImageHeight', 'categorie' => 'ExifIFD'),
'RelatedSoundFile' => array('id' => '40964', 'tag' => 'RelatedSoundFile', 'categorie' => 'ExifIFD'),
'InteroperabilityOffset' => array('id' => '40965', 'tag' => 'InteropOffset', 'categorie' => 'Unknown'),
'SubjectLocation' => array('id' => '41492', 'tag' => 'SubjectLocation', 'categorie' => 'ExifIFD'),
'FileSource' => array('id' => '41728', 'tag' => 'FileSource', 'categorie' => 'ExifIFD'),
'SceneType' => array('id' => '41729', 'tag' => 'SceneType', 'categorie' => 'ExifIFD'),
'CFAPattern' => array('id' => '41730', 'tag' => 'CFAPattern', 'categorie' => 'ExifIFD'),
'CustomRendered' => array('id' => '41985', 'tag' => 'CustomRendered', 'categorie' => 'ExifIFD'),
'ExposureMode' => array('id' => '41986', 'tag' => 'ExposureMode', 'categorie' => 'ExifIFD'),
'WhiteBalance' => array('id' => '41987', 'tag' => 'WhiteBalance', 'categorie' => 'ExifIFD'),
'DigitalZoomRatio' => array('id' => '41988', 'tag' => 'DigitalZoomRatio', 'categorie' => 'ExifIFD'),
'FocalLengthIn35mmFormat' => array('id' => '41989', 'tag' => 'FocalLengthIn35mmFormat', 'categorie' => 'ExifIFD'),
'FocalLengthIn35mmFilm' => array('id' => '41989', 'tag' => 'FocalLengthIn35mmFormat', 'categorie' => 'ExifIFD'),
'SceneCaptureType' => array('id' => '41990', 'tag' => 'SceneCaptureType', 'categorie' => 'ExifIFD'),
'GainControl' => array('id' => '41991', 'tag' => 'GainControl', 'categorie' => 'ExifIFD'),
'Contrast' => array('id' => '41992', 'tag' => 'Contrast', 'categorie' => 'ExifIFD'),
'Saturation' => array('id' => '41993', 'tag' => 'Saturation', 'categorie' => 'ExifIFD'),
'Sharpness' => array('id' => '41994', 'tag' => 'Sharpness', 'categorie' => 'ExifIFD'),
'DeviceSettingDescription' => array('id' => '41995', 'tag' => 'DeviceSettingDescription', 'categorie' => 'Unknown'),
'SubjectDistanceRange' => array('id' => '41996', 'tag' => 'SubjectDistanceRange', 'categorie' => 'ExifIFD'),
'ImageUniqueID' => array('id' => '42016', 'tag' => 'ImageUniqueID', 'categorie' => 'ExifIFD'),
'OwnerName' => array('id' => '42032', 'tag' => 'OwnerName', 'categorie' => 'ExifIFD'),
'CameraOwnerName' => array('id' => '42032', 'tag' => 'OwnerName', 'categorie' => 'ExifIFD'),
'SerialNumber' => array('id' => '42033', 'tag' => 'SerialNumber', 'categorie' => 'ExifIFD'),
'BodySerialNumber' => array('id' => '42033', 'tag' => 'SerialNumber', 'categorie' => 'ExifIFD'),
'LensInfo' => array('id' => '42034', 'tag' => 'LensInfo', 'categorie' => 'ExifIFD'),
'LensSpecification' => array('id' => '42034', 'tag' => 'LensInfo', 'categorie' => 'ExifIFD'),
'LensMake' => array('id' => '42035', 'tag' => 'LensMake', 'categorie' => 'ExifIFD'),
'LensModel' => array('id' => '42036', 'tag' => 'LensModel', 'categorie' => 'ExifIFD'),
'LensSerialNumber' => array('id' => '42037', 'tag' => 'LensSerialNumber', 'categorie' => 'ExifIFD'),
'GDALMetadata' => array('id' => '42112', 'tag' => 'GDALMetadata', 'categorie' => 'Unknown'),
'GDALNoData' => array('id' => '42113', 'tag' => 'GDALNoData', 'categorie' => 'Unknown'),
'Gamma' => array('id' => '42240', 'tag' => 'Gamma', 'categorie' => 'ExifIFD'),
'ExpandSoftware' => array('id' => '44992', 'tag' => 'ExpandSoftware', 'categorie' => 'Unknown'),
'ExpandLens' => array('id' => '44993', 'tag' => 'ExpandLens', 'categorie' => 'Unknown'),
'ExpandFilm' => array('id' => '44994', 'tag' => 'ExpandFilm', 'categorie' => 'Unknown'),
'ExpandFilterLens' => array('id' => '44995', 'tag' => 'ExpandFilterLens', 'categorie' => 'Unknown'),
'ExpandScanner' => array('id' => '44996', 'tag' => 'ExpandScanner', 'categorie' => 'Unknown'),
'ExpandFlashLamp' => array('id' => '44997', 'tag' => 'ExpandFlashLamp', 'categorie' => 'Unknown'),
'PixelFormat' => array('id' => '48129', 'tag' => 'PixelFormat', 'categorie' => 'Unknown'),
'Transformation' => array('id' => '48130', 'tag' => 'Transformation', 'categorie' => 'Unknown'),
'Uncompressed' => array('id' => '48131', 'tag' => 'Uncompressed', 'categorie' => 'Unknown'),
'ImageType' => array('id' => '48132', 'tag' => 'ImageType', 'categorie' => 'Unknown'),
'ImageHeight' => array('id' => '48257', 'tag' => 'ImageHeight', 'categorie' => 'Unknown'),
'WidthResolution' => array('id' => '48258', 'tag' => 'WidthResolution', 'categorie' => 'Unknown'),
'HeightResolution' => array('id' => '48259', 'tag' => 'HeightResolution', 'categorie' => 'Unknown'),
'ImageOffset' => array('id' => '48320', 'tag' => 'ImageOffset', 'categorie' => 'Unknown'),
'ImageByteCount' => array('id' => '48321', 'tag' => 'ImageByteCount', 'categorie' => 'Unknown'),
'AlphaOffset' => array('id' => '48322', 'tag' => 'AlphaOffset', 'categorie' => 'Unknown'),
'AlphaByteCount' => array('id' => '48323', 'tag' => 'AlphaByteCount', 'categorie' => 'Unknown'),
'ImageDataDiscard' => array('id' => '48324', 'tag' => 'ImageDataDiscard', 'categorie' => 'Unknown'),
'AlphaDataDiscard' => array('id' => '48325', 'tag' => 'AlphaDataDiscard', 'categorie' => 'Unknown'),
'OceScanjobDesc' => array('id' => '50215', 'tag' => 'OceScanjobDesc', 'categorie' => 'Unknown'),
'OceApplicationSelector' => array('id' => '50216', 'tag' => 'OceApplicationSelector', 'categorie' => 'Unknown'),
'OceIDNumber' => array('id' => '50217', 'tag' => 'OceIDNumber', 'categorie' => 'Unknown'),
'OceImageLogic' => array('id' => '50218', 'tag' => 'OceImageLogic', 'categorie' => 'Unknown'),
'Annotations' => array('id' => '50255', 'tag' => 'Annotations', 'categorie' => 'Unknown'),
'PrintIM' => array('id' => '50341', 'tag' => 'PrintIM', 'categorie' => 'IFD0'),
'USPTOOriginalContentType' => array('id' => '50560', 'tag' => 'USPTOOriginalContentType', 'categorie' => 'Unknown'),
'DNGVersion' => array('id' => '50706', 'tag' => 'DNGVersion', 'categorie' => 'IFD0'),
'DNGBackwardVersion' => array('id' => '50707', 'tag' => 'DNGBackwardVersion', 'categorie' => 'IFD0'),
'UniqueCameraModel' => array('id' => '50708', 'tag' => 'UniqueCameraModel', 'categorie' => 'IFD0'),
'LocalizedCameraModel' => array('id' => '50709', 'tag' => 'LocalizedCameraModel', 'categorie' => 'IFD0'),
'CFAPlaneColor' => array('id' => '50710', 'tag' => 'CFAPlaneColor', 'categorie' => 'Unknown'),
'CFALayout' => array('id' => '50711', 'tag' => 'CFALayout', 'categorie' => 'Unknown'),
'LinearizationTable' => array('id' => '50712', 'tag' => 'LinearizationTable', 'categorie' => 'SubIFD'),
'BlackLevelRepeatDim' => array('id' => '50713', 'tag' => 'BlackLevelRepeatDim', 'categorie' => 'SubIFD'),
'BlackLevel' => array('id' => '50714', 'tag' => 'BlackLevel', 'categorie' => 'SubIFD'),
'BlackLevelDeltaH' => array('id' => '50715', 'tag' => 'BlackLevelDeltaH', 'categorie' => 'Unknown'),
'BlackLevelDeltaV' => array('id' => '50716', 'tag' => 'BlackLevelDeltaV', 'categorie' => 'Unknown'),
'WhiteLevel' => array('id' => '50717', 'tag' => 'WhiteLevel', 'categorie' => 'SubIFD'),
'DefaultScale' => array('id' => '50718', 'tag' => 'DefaultScale', 'categorie' => 'SubIFD'),
'DefaultCropOrigin' => array('id' => '50719', 'tag' => 'DefaultCropOrigin', 'categorie' => 'SubIFD'),
'DefaultCropSize' => array('id' => '50720', 'tag' => 'DefaultCropSize', 'categorie' => 'SubIFD'),
'ColorMatrix1' => array('id' => '50721', 'tag' => 'ColorMatrix1', 'categorie' => 'IFD0'),
'ColorMatrix2' => array('id' => '50722', 'tag' => 'ColorMatrix2', 'categorie' => 'IFD0'),
'CameraCalibration1' => array('id' => '50723', 'tag' => 'CameraCalibration1', 'categorie' => 'IFD0'),
'CameraCalibration2' => array('id' => '50724', 'tag' => 'CameraCalibration2', 'categorie' => 'IFD0'),
'ReductionMatrix1' => array('id' => '50725', 'tag' => 'ReductionMatrix1', 'categorie' => 'IFD0'),
'ReductionMatrix2' => array('id' => '50726', 'tag' => 'ReductionMatrix2', 'categorie' => 'IFD0'),
'AnalogBalance' => array('id' => '50727', 'tag' => 'AnalogBalance', 'categorie' => 'IFD0'),
'AsShotNeutral' => array('id' => '50728', 'tag' => 'AsShotNeutral', 'categorie' => 'IFD0'),
'AsShotWhiteXY' => array('id' => '50729', 'tag' => 'AsShotWhiteXY', 'categorie' => 'IFD0'),
'BaselineExposure' => array('id' => '50730', 'tag' => 'BaselineExposure', 'categorie' => 'IFD0'),
'BaselineNoise' => array('id' => '50731', 'tag' => 'BaselineNoise', 'categorie' => 'IFD0'),
'BaselineSharpness' => array('id' => '50732', 'tag' => 'BaselineSharpness', 'categorie' => 'IFD0'),
'BayerGreenSplit' => array('id' => '50733', 'tag' => 'BayerGreenSplit', 'categorie' => 'SubIFD'),
'LinearResponseLimit' => array('id' => '50734', 'tag' => 'LinearResponseLimit', 'categorie' => 'IFD0'),
'CameraSerialNumber' => array('id' => '50735', 'tag' => 'CameraSerialNumber', 'categorie' => 'IFD0'),
'DNGLensInfo' => array('id' => '50736', 'tag' => 'DNGLensInfo', 'categorie' => 'IFD0'),
'ChromaBlurRadius' => array('id' => '50737', 'tag' => 'ChromaBlurRadius', 'categorie' => 'SubIFD'),
'AntiAliasStrength' => array('id' => '50738', 'tag' => 'AntiAliasStrength', 'categorie' => 'SubIFD'),
'ShadowScale' => array('id' => '50739', 'tag' => 'ShadowScale', 'categorie' => 'IFD0'),
'SR2Private' => array('id' => '50740', 'tag' => 'SR2Private', 'categorie' => 'Unknown'),
'MakerNoteSafety' => array('id' => '50741', 'tag' => 'MakerNoteSafety', 'categorie' => 'IFD0'),
'RawImageSegmentation' => array('id' => '50752', 'tag' => 'RawImageSegmentation', 'categorie' => 'Unknown'),
'CalibrationIlluminant1' => array('id' => '50778', 'tag' => 'CalibrationIlluminant1', 'categorie' => 'IFD0'),
'CalibrationIlluminant2' => array('id' => '50779', 'tag' => 'CalibrationIlluminant2', 'categorie' => 'IFD0'),
'BestQualityScale' => array('id' => '50780', 'tag' => 'BestQualityScale', 'categorie' => 'SubIFD'),
'RawDataUniqueID' => array('id' => '50781', 'tag' => 'RawDataUniqueID', 'categorie' => 'IFD0'),
'AliasLayerMetadata' => array('id' => '50784', 'tag' => 'AliasLayerMetadata', 'categorie' => 'Unknown'),
'OriginalRawFileName' => array('id' => '50827', 'tag' => 'OriginalRawFileName', 'categorie' => 'IFD0'),
'OriginalRawFileData' => array('id' => '50828', 'tag' => 'OriginalRawFileData', 'categorie' => 'IFD0'),
'ActiveArea' => array('id' => '50829', 'tag' => 'ActiveArea', 'categorie' => 'SubIFD'),
'MaskedAreas' => array('id' => '50830', 'tag' => 'MaskedAreas', 'categorie' => 'SubIFD'),
'AsShotICCProfile' => array('id' => '50831', 'tag' => 'AsShotICCProfile', 'categorie' => 'IFD0'),
'AsShotPreProfileMatrix' => array('id' => '50832', 'tag' => 'AsShotPreProfileMatrix', 'categorie' => 'IFD0'),
'CurrentICCProfile' => array('id' => '50833', 'tag' => 'CurrentICCProfile', 'categorie' => 'IFD0'),
'CurrentPreProfileMatrix' => array('id' => '50834', 'tag' => 'CurrentPreProfileMatrix', 'categorie' => 'IFD0'),
'ColorimetricReference' => array('id' => '50879', 'tag' => 'ColorimetricReference', 'categorie' => 'IFD0'),
'PanasonicTitle' => array('id' => '50898', 'tag' => 'PanasonicTitle', 'categorie' => 'IFD0'),
'PanasonicTitle2' => array('id' => '50899', 'tag' => 'PanasonicTitle2', 'categorie' => 'IFD0'),
'CameraCalibrationSig' => array('id' => '50931', 'tag' => 'CameraCalibrationSig', 'categorie' => 'IFD0'),
'ProfileCalibrationSig' => array('id' => '50932', 'tag' => 'ProfileCalibrationSig', 'categorie' => 'IFD0'),
'ProfileIFD' => array('id' => '50933', 'tag' => 'ProfileIFD', 'categorie' => 'Unknown'),
'AsShotProfileName' => array('id' => '50934', 'tag' => 'AsShotProfileName', 'categorie' => 'IFD0'),
'NoiseReductionApplied' => array('id' => '50935', 'tag' => 'NoiseReductionApplied', 'categorie' => 'SubIFD'),
'ProfileName' => array('id' => '50936', 'tag' => 'ProfileName', 'categorie' => 'IFD0'),
'ProfileHueSatMapDims' => array('id' => '50937', 'tag' => 'ProfileHueSatMapDims', 'categorie' => 'IFD0'),
'ProfileHueSatMapData1' => array('id' => '50938', 'tag' => 'ProfileHueSatMapData1', 'categorie' => 'IFD0'),
'ProfileHueSatMapData2' => array('id' => '50939', 'tag' => 'ProfileHueSatMapData2', 'categorie' => 'IFD0'),
'ProfileToneCurve' => array('id' => '50940', 'tag' => 'ProfileToneCurve', 'categorie' => 'IFD0'),
'ProfileEmbedPolicy' => array('id' => '50941', 'tag' => 'ProfileEmbedPolicy', 'categorie' => 'IFD0'),
'ProfileCopyright' => array('id' => '50942', 'tag' => 'ProfileCopyright', 'categorie' => 'IFD0'),
'ForwardMatrix1' => array('id' => '50964', 'tag' => 'ForwardMatrix1', 'categorie' => 'IFD0'),
'ForwardMatrix2' => array('id' => '50965', 'tag' => 'ForwardMatrix2', 'categorie' => 'IFD0'),
'PreviewApplicationName' => array('id' => '50966', 'tag' => 'PreviewApplicationName', 'categorie' => 'IFD0'),
'PreviewApplicationVersion' => array('id' => '50967', 'tag' => 'PreviewApplicationVersion', 'categorie' => 'IFD0'),
'PreviewSettingsName' => array('id' => '50968', 'tag' => 'PreviewSettingsName', 'categorie' => 'IFD0'),
'PreviewSettingsDigest' => array('id' => '50969', 'tag' => 'PreviewSettingsDigest', 'categorie' => 'IFD0'),
'PreviewColorSpace' => array('id' => '50970', 'tag' => 'PreviewColorSpace', 'categorie' => 'IFD0'),
'PreviewDateTime' => array('id' => '50971', 'tag' => 'PreviewDateTime', 'categorie' => 'IFD0'),
'RawImageDigest' => array('id' => '50972', 'tag' => 'RawImageDigest', 'categorie' => 'IFD0'),
'OriginalRawFileDigest' => array('id' => '50973', 'tag' => 'OriginalRawFileDigest', 'categorie' => 'IFD0'),
'SubTileBlockSize' => array('id' => '50974', 'tag' => 'SubTileBlockSize', 'categorie' => 'Unknown'),
'RowInterleaveFactor' => array('id' => '50975', 'tag' => 'RowInterleaveFactor', 'categorie' => 'Unknown'),
'ProfileLookTableDims' => array('id' => '50981', 'tag' => 'ProfileLookTableDims', 'categorie' => 'IFD0'),
'ProfileLookTableData' => array('id' => '50982', 'tag' => 'ProfileLookTableData', 'categorie' => 'IFD0'),
'OpcodeList1' => array('id' => '51008', 'tag' => 'OpcodeList1', 'categorie' => 'Unknown'),
'OpcodeList2' => array('id' => '51009', 'tag' => 'OpcodeList2', 'categorie' => 'Unknown'),
'OpcodeList3' => array('id' => '51022', 'tag' => 'OpcodeList3', 'categorie' => 'Unknown'),
'NoiseProfile' => array('id' => '51041', 'tag' => 'NoiseProfile', 'categorie' => 'Unknown'),
'Padding' => array('id' => '59932', 'tag' => 'Padding', 'categorie' => 'ExifIFD'),
'OffsetSchema' => array('id' => '59933', 'tag' => 'OffsetSchema', 'categorie' => 'ExifIFD'),
'Lens' => array('id' => '65002', 'tag' => 'Lens', 'categorie' => 'ExifIFD'),
'KDC_IFD' => array('id' => '65024', 'tag' => 'KDC_IFD', 'categorie' => 'Unknown'),
'RawFile' => array('id' => '65100', 'tag' => 'RawFile', 'categorie' => 'ExifIFD'),
'Converter' => array('id' => '65101', 'tag' => 'Converter', 'categorie' => 'ExifIFD'),
'Exposure' => array('id' => '65105', 'tag' => 'Exposure', 'categorie' => 'ExifIFD'),
'Shadows' => array('id' => '65106', 'tag' => 'Shadows', 'categorie' => 'ExifIFD'),
'Brightness' => array('id' => '65107', 'tag' => 'Brightness', 'categorie' => 'ExifIFD'),
'Sharpness:65110' => array('id' => '65110', 'tag' => 'Sharpness', 'categorie' => 'ExifIFD'),
'Smoothness' => array('id' => '65111', 'tag' => 'Smoothness', 'categorie' => 'ExifIFD'),
'MoireFilter' => array('id' => '65112', 'tag' => 'MoireFilter', 'categorie' => 'ExifIFD'),
'FileName' => array('id' => 'php:1', 'tag' => 'FileName', 'categorie' => 'PhpFile'),
'FileDateTime' => array('id' => 'php:2', 'tag' => 'FileDateTime', 'categorie' => 'PhpFile'),
'FileSize' => array('id' => 'php:3', 'tag' => 'FileSize', 'categorie' => 'PhpFile'),
'FileType' => array('id' => 'php:4', 'tag' => 'FileType', 'categorie' => 'PhpFile'),
'MimeType' => array('id' => 'php:5', 'tag' => 'MimeType', 'categorie' => 'PhpFile'),
'SectionsFound' => array('id' => 'php:6', 'tag' => 'SectionsFound', 'categorie' => 'PhpFile'),
'JPEGInterchangeFormat' => array('id' => 'php:7', 'tag' => 'JPEGInterchangeFormat', 'categorie' => 'PhpThumbail'),
'JPEGInterchangeFormatLength' => array('id' => 'php:8', 'tag' => 'JPEGInterchangeFormatLength', 'categorie' => 'PhpThumbail'),
'Thumbnail.FileType' => array('id' => 'php:9', 'tag' => 'ThumbnailFileType', 'categorie' => 'PhpThumbail'),
'Thumbnail.MimeType' => array('id' => 'php:10', 'tag' => 'ThumbnailMimeType', 'categorie' => 'PhpThumbail'),
'Html' => array('id' => 'php:11', 'tag' => 'Html', 'categorie' => 'PhpComputed'),
'IsColor' => array('id' => 'php:12', 'tag' => 'IsColor', 'categorie' => 'PhpComputed'),
'ByteOrderMotorola' => array('id' => 'php:13', 'tag' => 'ByteOrderMotorola', 'categorie' => 'PhpComputed'),
'ApertureFNumber' => array('id' => 'php:14', 'tag' => 'ApertureFNumber', 'categorie' => 'PhpComputed'),
'UserCommentEncoding' => array('id' => 'php:15', 'tag' => 'UserCommentEncoding', 'categorie' => 'PhpComputed'),
'ExifImageLength' => array('id' => 'php:16', 'tag' => 'ExifImageLength', 'categorie' => 'PhpComputed'),
'InterOperabilityIndex' => array('id' => 'php:17', 'tag' => 'InterOperabilityIndex', 'categorie' => 'PhpComputed'),
'InterOperabilityVersion' => array('id' => 'php:18', 'tag' => 'InterOperabilityVersion', 'categorie' => 'PhpComputed'),
'SpecialMode' => array('id' => 'php:19', 'tag' => 'SpecialMode', 'categorie' => 'PhpComputed'),
'JPEGQuality' => array('id' => 'php:20', 'tag' => 'JPEGQuality', 'categorie' => 'PhpComputed'),
'Macro' => array('id' => 'php:21', 'tag' => 'Macro ', 'categorie' => 'PhpComputed'),
'DigitalZoom' => array('id' => 'php:22', 'tag' => 'DigitalZoom', 'categorie' => 'PhpComputed'),
'SoftwareRelease' => array('id' => 'php:23', 'tag' => 'SoftwareRelease', 'categorie' => 'PhpComputed'),
'PictureInfo' => array('id' => 'php:24', 'tag' => 'PictureInfo', 'categorie' => 'PhpComputed'),
'CameraId' => array('id' => 'php:25', 'tag' => 'CameraId', 'categorie' => 'PhpComputed'),
'Gps' => array('id' => 'php:26', 'tag' => 'Gps', 'categorie' => 'PhpComputed'),
'ACDComment' => array('id' => 'php:27', 'tag' => 'ACDComment', 'categorie' => 'PhpComputed'),
'NewSubFile' => array('id' => 'php:28', 'tag' => 'NewSubFile', 'categorie' => 'PhpComputed'),
'Comments' => array('id' => 'php:29', 'tag' => 'Comments', 'categorie' => 'PhpComputed'),
'TIFF/EPStandardID' => array('id' => 'php:30', 'tag' => 'TIFFEPStandardID', 'categorie' => 'PhpComputed'),
'ModeArray' => array('id' => 'php:31', 'tag' => 'ModeArray', 'categorie' => 'PhpComputed'),
'ImageInfo' => array('id' => 'php:32', 'tag' => 'ImageInfo', 'categorie' => 'PhpComputed'),
'FirmwareVersion' => array('id' => 'php:33', 'tag' => 'FirmwareVersion', 'categorie' => 'PhpComputed'),
'Camera' => array('id' => 'php:34', 'tag' => 'Camera', 'categorie' => 'PhpComputed'),
'CustomFunctions' => array('id' => 'php:35', 'tag' => 'CustomFunctions', 'categorie' => 'PhpComputed'),
'CCDWidth' => array('id' => 'php:36', 'tag' => 'CCDWidth', 'categorie' => 'PhpComputed'),
'FocusDistance' => array('id' => 'php:37', 'tag' => 'FocusDistance', 'categorie' => 'PhpComputed'),
'Keywords' => array('id' => 'php:38', 'tag' => 'Keywords', 'categorie' => 'PhpComputed'),
'GPSVersion' => array('id' => 'php:39', 'tag' => 'GPSVersion', 'categorie' => 'PhpComputed')
);
 
private $ids_tags_iptc = array(
'1#000' => array('id' => '0', 'tag' => 'ApplicationRecordVersion', 'categorie' => 'EnvelopeRecord'),
'1#090' => array('id' => '90', 'tag' => 'CodedCharacterSet', 'categorie' => 'EnvelopeRecord'),
'2#003' => array('id' => '3', 'tag' => 'ObjectTypeReference', 'categorie' => 'ApplicationRecord'),
'2#004' => array('id' => '4', 'tag' => 'ObjectAttributeReference', 'categorie' => 'ApplicationRecord'),
'2#005' => array('id' => '5', 'tag' => 'ObjectName', 'categorie' => 'ApplicationRecord'),
'2#007' => array('id' => '7', 'tag' => 'EditStatus', 'categorie' => 'ApplicationRecord'),
'2#008' => array('id' => '8', 'tag' => 'EditorialUpdate', 'categorie' => 'ApplicationRecord'),
'2#010' => array('id' => '10', 'tag' => 'Urgency', 'categorie' => 'ApplicationRecord'),
'2#012' => array('id' => '12', 'tag' => 'SubjectReference', 'categorie' => 'ApplicationRecord'),
'Category' => array('id' => '15', 'tag' => 'Category', 'categorie' => 'ApplicationRecord'),
'2#015' => array('id' => '15', 'tag' => 'Category', 'categorie' => 'ApplicationRecord'),
'2#020' => array('id' => '20', 'tag' => 'SupplementalCategories', 'categorie' => 'ApplicationRecord'),
'2#022' => array('id' => '22', 'tag' => 'FixtureIdentifier', 'categorie' => 'ApplicationRecord'),
'MotsCles' => array('id' => '25', 'tag' => 'Keywords', 'categorie' => 'ApplicationRecord'),
'2#026' => array('id' => '26', 'tag' => 'ContentLocationCode', 'categorie' => 'ApplicationRecord'),
'2#027' => array('id' => '27', 'tag' => 'ContentLocationName', 'categorie' => 'ApplicationRecord'),
'2#030' => array('id' => '30', 'tag' => 'ReleaseDate', 'categorie' => 'ApplicationRecord'),
'2#035' => array('id' => '35', 'tag' => 'ReleaseTime', 'categorie' => 'ApplicationRecord'),
'2#037' => array('id' => '37', 'tag' => 'ExpirationDate', 'categorie' => 'ApplicationRecord'),
'2#038' => array('id' => '38', 'tag' => 'ExpirationTime', 'categorie' => 'ApplicationRecord'),
'2#040' => array('id' => '40', 'tag' => 'SpecialInstructions', 'categorie' => 'ApplicationRecord'),
'2#042' => array('id' => '42', 'tag' => 'ActionAdvised', 'categorie' => 'ApplicationRecord'),
'2#045' => array('id' => '45', 'tag' => 'ReferenceService', 'categorie' => 'ApplicationRecord'),
'2#047' => array('id' => '47', 'tag' => 'ReferenceDate', 'categorie' => 'ApplicationRecord'),
'2#050' => array('id' => '50', 'tag' => 'ReferenceNumber', 'categorie' => 'ApplicationRecord'),
'2#055' => array('id' => '55', 'tag' => 'DateCreated', 'categorie' => 'ApplicationRecord'),
'2#060' => array('id' => '60', 'tag' => 'TimeCreated', 'categorie' => 'ApplicationRecord'),
'2#062' => array('id' => '62', 'tag' => 'DigitalCreationDate', 'categorie' => 'ApplicationRecord'),
'2#063' => array('id' => '63', 'tag' => 'DigitalCreationTime', 'categorie' => 'ApplicationRecord'),
'2#065' => array('id' => '65', 'tag' => 'OriginatingProgram', 'categorie' => 'ApplicationRecord'),
'2#070' => array('id' => '70', 'tag' => 'ProgramVersion', 'categorie' => 'ApplicationRecord'),
'2#075' => array('id' => '75', 'tag' => 'ObjectCycle', 'categorie' => 'ApplicationRecord'),
'ByLine' => array('id' => '80', 'tag' => 'By-line', 'categorie' => 'ApplicationRecord'),
'ByLineTitle' => array('id' => '85', 'tag' => 'By-lineTitle', 'categorie' => 'ApplicationRecord'),
'City' => array('id' => '90', 'tag' => 'City', 'categorie' => 'ApplicationRecord'),
'SubLocation' => array('id' => '92', 'tag' => 'Sub-location', 'categorie' => 'ApplicationRecord'),
'ProvinceState' => array('id' => '95', 'tag' => 'Province-State', 'categorie' => 'ApplicationRecord'),
'CountryPrimaryLocationCode' => array('id' => '100', 'tag' => 'Country-PrimaryLocationCode', 'categorie' => 'ApplicationRecord'),
'CountryName' => array('id' => '101', 'tag' => 'Country-PrimaryLocationName', 'categorie' => 'ApplicationRecord'),
'2#103' => array('id' => '103', 'tag' => 'OriginalTransmissionReference', 'categorie' => 'ApplicationRecord'),
'Headline' => array('id' => '105', 'tag' => 'Headline', 'categorie' => 'ApplicationRecord'),
'Credit' => array('id' => '110', 'tag' => 'Credit', 'categorie' => 'ApplicationRecord'),
'2#115' => array('id' => '115', 'tag' => 'Source', 'categorie' => 'ApplicationRecord'),
'CopyrightNotice' => array('id' => '116', 'tag' => 'CopyrightNotice', 'categorie' => 'ApplicationRecord'),
'Contact' => array('id' => '118', 'tag' => 'Contact', 'categorie' => 'ApplicationRecord'),
'2#120' => array('id' => '120', 'tag' => 'Caption-Abstract', 'categorie' => 'ApplicationRecord'),
'2#121' => array('id' => '121', 'tag' => 'LocalCaption', 'categorie' => 'ApplicationRecord'),
'2#122' => array('id' => '122', 'tag' => 'Writer-Editor', 'categorie' => 'ApplicationRecord'),
'2#125' => array('id' => '125', 'tag' => 'RasterizedCaption', 'categorie' => 'ApplicationRecord'),
'2#130' => array('id' => '130', 'tag' => 'ImageType', 'categorie' => 'ApplicationRecord'),
'2#131' => array('id' => '131', 'tag' => 'ImageOrientation', 'categorie' => 'ApplicationRecord'),
'2#135' => array('id' => '135', 'tag' => 'LanguageIdentifier', 'categorie' => 'ApplicationRecord'),
'2#150' => array('id' => '150', 'tag' => 'AudioType', 'categorie' => 'ApplicationRecord'),
'2#151' => array('id' => '151', 'tag' => 'AudioSamplingRate', 'categorie' => 'ApplicationRecord'),
'2#152' => array('id' => '152', 'tag' => 'AudioSamplingResolution', 'categorie' => 'ApplicationRecord'),
'2#153' => array('id' => '153', 'tag' => 'AudioDuration', 'categorie' => 'ApplicationRecord'),
'2#154' => array('id' => '154', 'tag' => 'AudioOutcue', 'categorie' => 'ApplicationRecord'),
'2#184' => array('id' => '184', 'tag' => 'JobID', 'categorie' => 'ApplicationRecord'),
'2#185' => array('id' => '185', 'tag' => 'MasterDocumentID', 'categorie' => 'ApplicationRecord'),
'2#186' => array('id' => '186', 'tag' => 'ShortDocumentID', 'categorie' => 'ApplicationRecord'),
'2#187' => array('id' => '187', 'tag' => 'UniqueDocumentID', 'categorie' => 'ApplicationRecord'),
'2#188' => array('id' => '188', 'tag' => 'OwnerID', 'categorie' => 'ApplicationRecord'),
'2#200' => array('id' => '200', 'tag' => 'ObjectPreviewFileFormat', 'categorie' => 'ApplicationRecord'),
'2#201' => array('id' => '201', 'tag' => 'ObjectPreviewFileVersion', 'categorie' => 'ApplicationRecord'),
'2#202' => array('id' => '202', 'tag' => 'ObjectPreviewData', 'categorie' => 'ApplicationRecord'),
'2#221' => array('id' => '221', 'tag' => 'Prefs', 'categorie' => 'ApplicationRecord'),
'2#225' => array('id' => '225', 'tag' => 'ClassifyState', 'categorie' => 'ApplicationRecord'),
'2#228' => array('id' => '228', 'tag' => 'SimilarityIndex', 'categorie' => 'ApplicationRecord'),
'2#230' => array('id' => '230', 'tag' => 'DocumentNotes', 'categorie' => 'ApplicationRecord'),
'2#231' => array('id' => '231', 'tag' => 'DocumentHistory', 'categorie' => 'ApplicationRecord'),
'2#232' => array('id' => '232', 'tag' => 'ExifCameraInfo', 'categorie' => 'ApplicationRecord'),
'2#242' => array('id' => '242', 'tag' => 'Unknown242', 'categorie' => 'Unknown'),
'2#254' => array('id' => '254', 'tag' => 'Unknown254', 'categorie' => 'Unknown'),
'2#255' => array('id' => '255', 'tag' => 'CatalogSets', 'categorie' => 'ApplicationRecord')
);
 
public function __construct(Conteneur $conteneur) {
$bddMigration = $conteneur->getParametre('database_cel.database_migration');
if ($bddMigration == null || $bddMigration == '') {
echo 'Attention la variable de configuration database_migration dans la section database_cel, contenant la base de données d\'arrivée, doit être remplie '."\n";
exit;
}
$bddIdentification = $conteneur->getParametre('database_ident.database');
if ($bddIdentification == null || $bddIdentification == '') {
echo 'Attention la variable de configuration database dans la section database_ident, contenant la base de données utilisateurs, doit être remplie '."\n";
exit;
}
 
self::$bdd_cel_migration = $conteneur->getParametre('database_cel.database_migration');
self::$bdd_utilisateurs = $conteneur->getParametre('database_ident.database');
 
$this->bdd = $conteneur->getBdd();
$this->script = $conteneur->getScript();
 
$this->cle_id_metadonnees = array_merge($this->ids_tags_exif, $this->ids_tags_iptc);
}
 
/**
* Méthode appelée pour executer le script.
*/
public function executer($params) {
echo "--MIGRATION DES IMAGES --------------------------------------\n";
//1. TEMPORAIRE : vider les tables de destinations
if (self::truncate) {
echo "-------------------------------------------------------------------\n";
echo " ETAPE 0. Vider les tables ... \n";
echo "-------------------------------------------------------------------\n";
$nouvellesTables = array('cel_images', 'cel_obs_images');
foreach ($nouvellesTables as $nomTable) {
echo 'Vider la table '.$nomTable.'...';
$requeteTruncate = 'TRUNCATE TABLE '.self::$bdd_cel_migration.'.'.$nomTable;
$resultatTruncate = $this->bdd->executer($requeteTruncate);
echo "ok \n";
}
}
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 1. Paramétrage ... \n";
echo "-------------------------------------------------------------------\n";
$this->getUtilisateurs();
$this->getObservations();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 2. Migration des images ... \n";
echo "-------------------------------------------------------------------\n";
$this->migrerImages();
$this->mettreANullPrenomNomVide();
$this->ordonnerImages();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 3. migration des liaisons obs images ... \n";
echo "-------------------------------------------------------------------\n";
$this->migrerLiaisonsObsImages();
}
 
private function getUtilisateurs() {
echo "SELECTION DES UTILISATEURS\n";
 
$requete = 'SELECT U_ID as id, U_MAIL as mail, U_NAME as nom, U_SURNAME as prenom, U_PASSWD as pass '.
'FROM '.self::$bdd_utilisateurs.'.annuaire_tela';
$tableau_utilisateurs = $this->bdd->requeter($requete);
 
foreach ($tableau_utilisateurs as &$utilisateur) {
$this->tableau_utilisateurs[$utilisateur['mail']] = $utilisateur;
}
 
echo sizeof($this->tableau_utilisateurs)." utilisateurs sélectionnés\n";
}
 
private function getObservations() {
$pas = 5000;
$nObs = 'SELECT COUNT(*) AS nb FROM cel_inventory';
$resultatNbObs = $this->bdd->requeter($nObs, Bdd::SQL_RETOUR_COLONNE);
$nbObs = $resultatNbObs;
$maxLimite = $nbObs + $pas;
 
for ($i = 0; $i < $maxLimite; $i += $pas ) {
$requete_selection_observations = "SELECT id, ordre, identifiant FROM cel_inventory LIMIT $i,$pas ";
$tableau_observations = $this->bdd->requeter($requete_selection_observations);
foreach ($tableau_observations as &$obs) {
$this->tableau_observations[$obs['identifiant']][$obs['ordre']] = $obs['id'];
}
$this->script->afficherAvancement('Selection des observations (par '.$pas.' )');
}
echo "\n";
}
 
private function migrerImages() {
$pas = 100;
 
//Selectionner le nombre d'images
$requeteNbImg = "SELECT COUNT(*) as nb FROM cel_images";
$fin = $this->bdd->requeter($requeteNbImg, BDD::SQL_RETOUR_COLONNE);
$maxLimite = $fin + $pas;
 
for ($i = 0; $i <= $maxLimite ; $i += $pas) {
$requete = "SELECT * FROM cel_images ORDER BY ci_id_image ASC LIMIT $i,$pas ";
$images = $this->bdd->requeter($requete);
if (is_array($images)) {
$imagesNouvelles = array();
foreach ($images as $image) {
$image = $this->traiterLigneImage($image);
$image = array_map(array($this, 'protegerSiNonNull'), $image);
$imagesNouvelles[] = '('.implode(',', array_values($image)).')';
}
 
$bdd = self::$bdd_cel_migration;
$champs = implode(', ', array_keys($this->tableau_nouveau_ancien));
$values = implode(',', $imagesNouvelles);
$requete = "INSERT INTO $bdd.cel_images ($champs) VALUES $values ";
$migration_images = $this->executerRequeteSimple($requete);
if (!$migration_images) {
echo 'La migration des images '.$i.' à '.($i + count($images)).' a échoué '."\n";
file_put_contents('/home/jpm/requete.sql', $requete);
} else {
$this->script->afficherAvancement('Migration des images (par '.$pas.' )');
}
}
 
if (count($images) < $pas) {
echo "\n";
return;
}
}
}
 
private function ordonnerImages() {
$requete = 'ALTER TABLE '.self::$bdd_cel_migration.'.cel_images ORDER BY id_image';
$this->executerRequeteSimple($requete);
}
 
private function executerRequeteSimple($requete) {
// Fonction de commodité pour afficher les requetes au lieu de les executer
if (self::dry_run) {
echo str_replace('),','),'."\n", $requete)."\n";
return true;
} else {
return $this->bdd->executer($requete);
}
}
 
private function traiterLigneImage($image) {
$nouvelle_image = array();
 
foreach ($this->tableau_nouveau_ancien as $nouveau_champ_image => $ancien_champ_image) {
if ($this->estUnChampATraiter($ancien_champ_image)) {
if (method_exists($this,$ancien_champ_image)) {
$nouvelle_image[$nouveau_champ_image] = $this->$ancien_champ_image($image);
} else {
echo 'methode manquante : '.$ancien_champ_image."\n";
$nouvelle_image[$nouveau_champ_image] = '';
}
} else {
$nouvelle_image[$nouveau_champ_image] = $image[$ancien_champ_image];
}
}
 
return $nouvelle_image;
}
 
private function estUnChampATraiter($champ) {
return strpos($champ, 'traiter') !== false;
}
 
private function protegerSiNonNull($valeur) {
if ($valeur != 'NULL') {
$valeur = $this->bdd->proteger($valeur);
}
return $valeur;
}
 
private function traiterIdentifiantUtilisateur($ligne_image) {
$mail_image = $ligne_image['ci_ce_utilisateur'];
$retour = $this->renvoyerIdPourMigration($mail_image);
 
return $retour;
}
 
private function renvoyerIdPourMigration($utilisateur) {
// si tout les test suivant échouent, on garde l'utilisateur tel quel (cas de la chaine de session des utilisateur anonymes)
$retour = $utilisateur;
// si le mail correspond a un utilisateur de la bdd
if (isset($this->tableau_utilisateurs[$utilisateur])) {
// on renvoie son id
$retour = $this->tableau_utilisateurs[$utilisateur]['id'];
} else {
// sinon si c'est un mail inconnu, on garde le md5
if($this->mailValide($utilisateur)) {
$retour = md5($utilisateur);
}
}
return $retour;
}
 
private function mailValide($mail) {
// vérification bidon mais ça suffit pour ici
return !(strpos($mail, '@') === false);
}
 
private function traiterPrenomUtilisateur($ligne_image) {
$mail_image = $ligne_image['ci_ce_utilisateur'];
$retour = $mail_image;
 
if (isset($this->tableau_utilisateurs[$mail_image])) {
$retour = self::formaterMotPremiereLettreChaqueMotEnMajuscule($this->tableau_utilisateurs[$mail_image]['prenom']);
} else {
$retour = '';
}
 
return $retour;
}
 
public static function formaterMotPremiereLettreChaqueMotEnMajuscule($chaine, $encodage= 'UTF-8') {
$chaine = str_replace('-', ' - ', $chaine);
$chaine = mb_strtolower($chaine, $encodage);
$chaine = mb_convert_case($chaine, MB_CASE_TITLE, $encodage);
$chaine = str_replace(' - ', '-', $chaine);
return $chaine;
}
 
private function traiterNomUtilisateur($ligne_image) {
$mail_image = $ligne_image['ci_ce_utilisateur'];
$retour = $mail_image;
 
if (isset($this->tableau_utilisateurs[$mail_image])) {
$retour = self::formaterMotEnMajuscule($this->tableau_utilisateurs[$mail_image]['nom']);
} else {
$retour = '';
}
 
return $retour;
}
 
public static function formaterMotEnMajuscule($chaine, $encodage= 'UTF-8') {
return mb_convert_case($chaine, MB_CASE_UPPER, $encodage);
}
 
private function traiterNoteImage($image) {
$retour = $image['ci_note_image'];
if ($image['ci_note_image'] == '-1') {
$retour = 'NULL';
}
return $retour;
}
 
private function traiterExif($ligne_image) {
$metadonnees_autres = $this->decoderTableauMetaDonnees($ligne_image['ci_meta_exif_autres']);
$metadonnees = array_intersect_key($ligne_image, array_flip($this->champs_exifs_non_gardes))+$metadonnees_autres;
 
$retour = 'NULL';
if ($xml = $this->convertirTableauMetadonneesEnXml($metadonnees)) {
$retour = '<?xml version="1.0" encoding="UTF-8" ?>'."\n".
'<exif>'."\n".$xml.'</exif>';
}
return $retour;
}
 
private function traiterIptc($ligne_image) {
$metadonnees_autres = $this->decoderTableauMetaDonnees($ligne_image['ci_meta_iptc_autres']);
$metadonnees = array_intersect_key($ligne_image, array_flip($this->champs_iptc_non_gardes)) + $metadonnees_autres;
 
$retour = 'NULL';
if ($xml = $this->convertirTableauMetadonneesEnXml($metadonnees)) {
$retour = '<?xml version="1.0" encoding="UTF-8" ?>'."\n".
'<iptc>'."\n".$xml.'</iptc>';
}
return $retour;
}
 
private function traiterXmp($ligne_image) {
$retour = 'NULL';
return $retour;
}
 
private function traiterMakernote($ligne_image) {
$retour = 'NULL';
return $retour;
}
 
private function decoderTableauMetaDonnees($chaine) {
$tableau_valeurs_decodees = array();
if (trim($chaine) != '') {
$tableau_meta = explode(self::separateur_champs_metadonnees, $chaine);
foreach ($tableau_meta as &$chaine_meta) {
if (strpos($chaine_meta, 'UndefinedTag:') !== false) {
$chaine_meta = str_replace('UndefinedTag:', 'UndefinedTag', $chaine_meta);
}
$cle_valeur = explode(self::separateur_valeurs_metadonnees, $chaine_meta, 2);
if (is_array($cle_valeur) && count($cle_valeur) == 2) {
$cle = ltrim($cle_valeur[0], ' ');
$tableau_valeurs_decodees[$cle] = $cle_valeur[1];
}
}
}
return $tableau_valeurs_decodees;
}
 
private function convertirTableauMetadonneesEnXml($tableau) {
$xml = '';
foreach ($tableau as $cle => $valeur) {
$cle = str_replace('ci_meta_exif_', '', $cle);
$cle = str_replace('ci_meta_iptc_', '', $cle);
$cle = str_replace('ci_meta_', '', $cle);
 
$cle = str_replace('_', ' ', $cle);
$cle = ucwords($cle);
$cle = str_replace(' ', '', $cle);
 
$valeur = str_replace("\0", '', $valeur);
 
if (isset($this->cle_id_metadonnees[$cle])) {
$id = $this->cle_id_metadonnees[$cle]['id'];
$tag = $this->cle_id_metadonnees[$cle]['tag'];
$categorie = $this->cle_id_metadonnees[$cle]['categorie'];
$xml .= '<'.$tag.' id="'.$id.'" categorie="'.$categorie.'">'.$valeur.'</'.$tag.'>'."\n";
} else {
$xml .= '<'.$cle.' categorie="Undefined">'.$valeur.'</'.$cle.'>'."\n";
}
}
return $xml;
}
 
private function migrerLiaisonsObsImages() {
$pas = 500;
$liaisons_obs_inexistantes = 0;
 
//Selectionner le nombre de liaisons
$requeteNbImgObs = "SELECT COUNT(*) AS nb FROM cel_obs_images";
$fin = $this->bdd->requeter($requeteNbImgObs, Bdd::SQL_RETOUR_COLONNE);
echo "Nbre de liaisons à migrer : $fin\n";
 
for ($i = 0; $i <= $fin ; $i += $pas) {
$requete = "SELECT * FROM cel_obs_images LIMIT $i,$pas ";
$tableau_liaisons = $this->bdd->requeter($requete);
 
if (is_array($tableau_liaisons)) {
$liaisonsNouvelles = array();
foreach ($tableau_liaisons as $liaison) {
$mail_utilisateur = $liaison['coi_ce_utilisateur'];
$ordre_obs = $liaison['coi_ce_observation'];
if (isset($this->tableau_observations[$mail_utilisateur][$ordre_obs])) {
$id_obs = $this->bdd->proteger($this->tableau_observations[$mail_utilisateur][$ordre_obs]);
$id_image = $this->bdd->proteger($liaison['coi_ce_image']);
$date_liaison = $this->bdd->proteger($liaison['coi_date_liaison']);
$liaisonsNouvelles[] = "($id_image, $id_obs, $date_liaison)";
} else {
// cas d'une observation inexistante, la liaison est ignorée
$liaisons_obs_inexistantes++;
}
}
if (count($liaisonsNouvelles) != 0) {
$sousRequete = implode(',', $liaisonsNouvelles);
 
$requete = 'INSERT INTO '.self::$bdd_cel_migration.'.cel_obs_images '.
'(id_image, id_observation, date_liaison) '.
"VALUES $sousRequete ";
$migration_liaison = $this->executerRequeteSimple($requete);
 
if (!$migration_liaison) {
echo 'La migration des liaisons obs images de '.$i.' à '.($i+$pas).' a échoué ! '."\n<br />";
} else {
$this->script->afficherAvancement('Migration des liaisons obs images (par '.$pas.' )');
}
}
}
}
echo "\n";
echo $liaisons_obs_inexistantes ? $liaisons_obs_inexistantes." liaisons image obs ont été ignorées car les obs sont absentes\n" : '' ;
}
 
private function mettreANullPrenomNomVide() {
$bdd = self::$bdd_cel_migration;
$requete = "UPDATE $bdd.cel_images ".
'SET prenom_utilisateur = NULL '.
"WHERE prenom_utilisateur = '' ";
$this->bdd->executer($requete);
 
$requete = "UPDATE $bdd.cel_images ".
'SET nom_utilisateur = NULL '.
"WHERE nom_utilisateur = '' ";
$this->bdd->executer($requete);
}
}
/trunk/jrest/scripts/MigrationMotsCles.php
New file
0,0 → 1,392
<?php
// declare(encoding='UTF-8');
/**
* Script de migration des Mots Clés de la version 1 de la base de données du CEL à la v2.
* Utilisation : /opt/lampp/bin/php cli.php MigrationMotsCles
*
* @category php 5.2
* @package Cel/Scripts
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class MigrationMotsCles {
 
const SEPARATEUR_MOT_CLE_TEXTE = ',';
const truncate = true; //Doit on vider les tables de destination ?
const dry_run = false;
 
private $bdd = null;
private $script = null;
private $nouvellesTables = array('cel_mots_cles_obs', 'cel_mots_cles_images', 'cel_images_mots_cles', 'cel_obs_mots_cles');
public static $bdd_cel_migration;
public static $bdd_utilisateurs;
private $tableau_utilisateurs = array();
 
/** Tableau associatif permettant de stocker l'avancement dans une boucle.
* La clé est un md5 du message à afficher au démarrage de la boucle.
* @var array
*/
private static $avancement = array();
 
public function __construct(Conteneur $conteneur) {
$bddMigration = $conteneur->getParametre('database_cel.database_migration');
if ($bddMigration == null || $bddMigration == '') {
echo 'Attention la variable de configuration database_migration dans la section database_cel, contenant la base de données d\'arrivée, doit être remplie '."\n";
exit;
}
$bddIdentification = $conteneur->getParametre('database_ident.database');
if ($bddIdentification == null || $bddIdentification == '') {
echo 'Attention la variable de configuration database dans la section database_ident, contenant la base de données utilisateurs, doit être remplie '."\n";
exit;
}
 
self::$bdd_cel_migration = $conteneur->getParametre('database_cel.database_migration');
self::$bdd_utilisateurs = $conteneur->getParametre('database_ident.database');
$this->bdd = $conteneur->getBdd();
$this->script = $conteneur->getScript();
}
 
/**
* Méthode appelée pour executer le script.
*/
public function executer($params) {
echo "--MIGRATION DES MOTS CLES --------------------------------------\n";
if (self::truncate) {
echo "-------------------------------------------------------------------\n";
echo " ETAPE 0. Vider les tables ... \n";
echo "-------------------------------------------------------------------\n";
$this->viderTables();
}
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 1. Paramétrage ... \n";
echo "-------------------------------------------------------------------\n";
$this->getUtilisateurs();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 2. Migration des mots clés ... \n";
echo "-------------------------------------------------------------------\n";
$this->migrerTableMotsClesObs();
$this->migrerTableMotsClesImages();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 3. Migration des liaisons mots clés ... \n";
echo "-------------------------------------------------------------------\n";
$this->migrerLiaisonsMotsClesObs();
$this->migrerLiaisonsMotsClesImages();
 
echo "-------------------------------------------------------------------\n";
echo " ETAPE 4. Génération des index des mots clés ... \n";
echo "-------------------------------------------------------------------\n";
$this->genererIndexTexteMotsClesObs();
$this->genererIndexTexteMotsClesImages();
$this->mettreANullMotsClesTxtVide();
}
 
private function viderTables() {
foreach ($this->nouvellesTables as $nomTable) {
echo 'Vider la table '.$nomTable.'...';
$requete = 'TRUNCATE TABLE '.self::$bdd_cel_migration.'.'.$nomTable;
$resultat = $this->bdd->executer($requete);
echo "ok \n";
}
}
 
private function executerRequeteSimple($requete) {
// Fonction de commodité pour afficher les requetes au lieu de les executer
if (self::dry_run) {
echo str_replace('),','),'."\n", $requete);
return true;
} else {
return $this->bdd->executer($requete);
}
 
}
 
 
private function getUtilisateurs() {
echo "SELECTION DES UTILISATEURS\n";
 
$requete = 'SELECT U_ID as id, U_MAIL as mail, U_NAME as nom, U_SURNAME as prenom, U_PASSWD as pass '.
'FROM '.self::$bdd_utilisateurs.'.annuaire_tela';
$tableau_utilisateurs = $this->bdd->requeter($requete);
 
foreach( $tableau_utilisateurs as &$utilisateur) {
$this->tableau_utilisateurs[$utilisateur['mail']] = $utilisateur;
}
 
echo count($this->tableau_utilisateurs)." utilisateurs sélectionnés \n";
}
 
private function migrerTableMotsClesObs() {
$this->migrerTableMotsCles('obs');
}
 
private function migrerTableMotsClesImages() {
$this->migrerTableMotsCles('images');
}
 
private function migrerTableMotsCles($image_ou_obs) {
echo "MIGRATION DES MOTS CLES $image_ou_obs\n";
$pas = 1;
 
//limite des mots clés
$requeteNbMotsCles = 'SELECT count(*) as nb FROM cel_mots_cles_'.$image_ou_obs;
$nbMotsCles = (int) $this->bdd->requeter($requeteNbMotsCles, Bdd::SQL_RETOUR_COLONNE);
 
for ($i = 0; $i < $nbMotsCles; $i += $pas) {
$requete = 'SELECT * '.
'FROM cel_mots_cles_'.$image_ou_obs.' '.
'ORDER BY cmc_niveau '.
"LIMIT $i,$pas ";
$arbres_mots_cles = $this->bdd->requeter($requete);
 
if (count($arbres_mots_cles) > 0) {
$champ_parent = ($image_ou_obs == "obs") ? 'ce_mot_cle_obs_parent' : 'ce_mot_cle_image_parent';
$champ_id = ($image_ou_obs == "obs") ? 'id_mot_cle_obs' : 'id_mot_cle_image';
$requete = 'INSERT INTO '.self::$bdd_cel_migration.".cel_mots_cles_$image_ou_obs ".
"($champ_id, id_utilisateur, mot_cle, md5, bg, bd, niveau, $champ_parent) ".
'VALUES ';
 
$sous_requete = array();
foreach ($arbres_mots_cles as $arbre_mot_cle) {
$sous_requete[] = $this->construireSousRequeteInsertionArbresMotsCles('cmc_', $arbre_mot_cle);
}
$sous_requete = implode(',', $sous_requete);
$requete .= $sous_requete;
 
$migration = $this->executerRequeteSimple($requete);
if (!$migration) {
echo "La migration des mots cles $image_ou_obs a échoué ! "."\n";
} else {
$this->script->afficherAvancement("Migration des mots clés $image_ou_obs (par $pas)");
}
}
}
echo "\n";
}
 
private function construireSousRequeteInsertionArbresMotsCles($prefixe, $ligne) {
$id_proprietaire_mot_cle = $ligne[$prefixe.'id_proprietaire'];
$id_proprietaire_mot_cle = $this->renvoyerIdPourMigration($id_proprietaire_mot_cle);
 
$sous_requete = '('.$this->bdd->proteger($ligne[$prefixe.'id_mot_cle_utilisateur']).','.
$this->bdd->proteger($id_proprietaire_mot_cle).','.
$this->bdd->proteger($ligne[$prefixe.'mot_cle']).','.
$this->bdd->proteger($ligne[$prefixe.'id_mot_cle_general']).','.
$this->bdd->proteger($ligne[$prefixe.'bg']).','.
$this->bdd->proteger($ligne[$prefixe.'bd']).','.
$this->bdd->proteger($ligne[$prefixe.'niveau']).','.
$this->bdd->proteger($ligne[$prefixe.'id_parent']).
')';
return $sous_requete;
}
 
private function renvoyerIdPourMigration($utilisateur) {
// si tout les test suivant échouent, on garde l'utilisateur tel quel
// (cas de la chaine de session des utilisateur anonymes)
$retour = $utilisateur;
// si le mail correspond a un utilisateur de la bdd
if (isset($this->tableau_utilisateurs[$utilisateur])) {
// on renvoie son id
$retour = $this->tableau_utilisateurs[$utilisateur]['id'];
} else {
// sinon si c'est un mail inconnu, on garde le md5
if ($this->mailValide($utilisateur)) {
$retour = md5($utilisateur);
}
}
return $retour;
}
 
private function mailValide($mail) {
// vérification bidon mais ça suffit pour ici
return !(strpos($mail, '@') === false);
}
 
private function migrerLiaisonsMotsClesObs() {
$requete = 'SELECT mots_cles AS mots_cles, id AS id, identifiant AS id_utilisateur '.
'FROM cel_inventory '.
'WHERE mots_cles != "" '.
' AND mots_cles != "NULL" '.
' AND mots_cles != "null" '.
' AND mots_cles IS NOT NULL '.
'ORDER BY identifiant ';
$mots_cles_obs = $this->bdd->requeter($requete);
 
$requete = 'INSERT INTO '.self::$bdd_cel_migration.'.cel_obs_mots_cles '.
'(id_observation, id_mot_cle_obs, id_utilisateur) '.
'VALUES '.
$this->construireSousRequeteInsertionLiaisons($mots_cles_obs, ';');
 
$insertion = $this->executerRequeteSimple($requete);
if (!$insertion) {
echo 'La migration des mots cles obs a échoué ! '."\n";
} else {
echo "Migration des mots cles obs : OK\n";
}
}
 
private function migrerLiaisonsMotsClesImages() {
$requete = 'SELECT ci_meta_mots_cles AS mots_cles, ci_id_image AS id, ci_ce_utilisateur AS id_utilisateur '.
'FROM cel_images '.
'WHERE ci_meta_mots_cles != "" '.
' AND ci_meta_mots_cles != "NULL" '.
' AND ci_meta_mots_cles != "null" '.
' AND ci_meta_mots_cles IS NOT NULL '.
'ORDER BY ci_ce_utilisateur';
$mots_cles_images = $this->bdd->requeter($requete);
 
$requete = 'INSERT INTO '.self::$bdd_cel_migration.'.cel_images_mots_cles '.
'(id_image, id_mot_cle_image, id_utilisateur) '.
'VALUES '.
$this->construireSousRequeteInsertionLiaisons($mots_cles_images, ',');
 
$insertion = $this->executerRequeteSimple($requete);
 
if (!$insertion) {
echo 'La migration des mots cles images a échoué ! '."\n";
} else {
echo "Migration des mots cles images : OK\n";
}
}
 
private function construireSousRequeteInsertionLiaisons($tableau_mots_cles, $separateur) {
$sous_requete = array();
foreach ($tableau_mots_cles as $element) {
$mots_cles_ids = $this->parserMotsCles($element['mots_cles'], $separateur);
foreach ($mots_cles_ids as $mot_cle_id) {
$id = $this->bdd->proteger($element['id']);
$id_mot_cle = $this->bdd->proteger($mot_cle_id);
$id_utilisateur = $this->bdd->proteger($this->renvoyerIdPourMigration($element['id_utilisateur']));
$sous_requete[] = "($id, $id_mot_cle, $id_utilisateur)";
}
}
$sous_requete_chaine = implode(',', $sous_requete);
return $sous_requete_chaine;
}
 
private function parserMotsCles($mot_cles, $separateur = ',') {
$mot_cles = trim($mot_cles, $separateur);
$tableau_mots_cles = explode($separateur, $mot_cles);
 
$tableau_mots_cles_formates = array();
foreach ($tableau_mots_cles as $mot_cle) {
$mot_cle = str_replace($separateur.$separateur, '', $mot_cle);
$mot_cle = str_replace('null', '', $mot_cle);
$mot_cle = trim($mot_cle);
 
if ($this->estUnIdentifiantMotCle($mot_cle)) {
// certains mots clés mal formatés contiennent des virgules
if (strpos($mot_cle, ',') !== false) {
$tab_mot_cle_mal_formate = explode(',', $mot_cle);
 
foreach ( $tab_mot_cle_mal_formate as $mot_cle_mal_formate) {
if ($this->estUnIdentifiantMotCle($mot_cle_mal_formate)) {
$tableau_mots_cles_formates[$mot_cle_mal_formate] = $mot_cle_mal_formate;
}
}
} else {
// on met le mot clé dans sa propre case afin d'éviter
// facilement les doublons provoqués par de mauvais formatages
$tableau_mots_cles_formates[$mot_cle] = $mot_cle;
}
} else if ($mot_cle != '') {
echo "N'est pas un mot clé : $mot_cle\n";
}
}
return $tableau_mots_cles_formates;
}
 
private function estUnIdentifiantMotCle($chaine) {
return preg_match('/^(?:[-][0-9]+[.][0-9]+|[-_a-z0-9]+(?:[.][-_a-z0-9]+)*)$/i', $chaine);
}
 
private function genererIndexTexteMotsClesObs() {
$requete = 'SELECT DISTINCT id_observation, id_utilisateur '.
'FROM '.self::$bdd_cel_migration.'.cel_obs_mots_cles ';
$obs_a_mots_cles = $this->bdd->requeter($requete);
 
foreach ($obs_a_mots_cles as $obs) {
$mots_cles_texte = $this->obtenirMotsClesTexte($obs['id_observation'], $obs['id_utilisateur'], 'obs');
if (is_array($mots_cles_texte) && count($mots_cles_texte) > 0) {
$mots_cles_texte_chaine = implode(',', $mots_cles_texte);
$mise_a_jour_index = $this->executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $obs['id_observation'], $obs['id_utilisateur'], 'obs');
$this->script->afficherAvancement('Génération des index mots clés obs (par 1)');
}
}
echo "\n";
}
 
private function genererIndexTexteMotsClesImages() {
$requete = 'SELECT DISTINCT id_image, id_utilisateur '.
'FROM '.self::$bdd_cel_migration.'.cel_images_mots_cles ';
$images_a_mots_cles = $this->bdd->requeter($requete);
 
foreach ($images_a_mots_cles as $image) {
$mots_cles_texte = $this->obtenirMotsClesTexte($image['id_image'], $image['id_utilisateur'], 'images');
$mots_cles_texte_chaine = '';
if (is_array($mots_cles_texte) && count($mots_cles_texte) > 0) {
$mots_cles_texte_chaine = implode(',', $mots_cles_texte);
$mise_a_jour_index = $this->executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $image['id_image'], $image['id_utilisateur'], 'images');
$this->script->afficherAvancement('Génération des index mots clés images (par 1)');
}
}
echo "\n";
}
 
private function obtenirMotsClesTexte($id_image_ou_obs, $id_utilisateur, $mode) {
$bdd = self::$bdd_cel_migration;
$champ_id_mot_cle = ($mode == 'obs') ? 'id_mot_cle_obs' : 'id_mot_cle_image';
$champ_id_obs_ou_img = ($mode == 'obs') ? 'id_observation' : 'id_image';
$id_image_ou_obs = $this->bdd->proteger($id_image_ou_obs);
$id_utilisateur = $this->bdd->proteger($id_utilisateur);
 
$requete = 'SELECT mot_cle '.
"FROM $bdd.cel_mots_cles_$mode AS a ".
" INNER JOIN $bdd.cel_{$mode}_mots_cles AS b ".
" ON (a.$champ_id_mot_cle = b.$champ_id_mot_cle AND a.id_utilisateur = b.id_utilisateur) ".
"WHERE b.$champ_id_obs_ou_img = $id_image_ou_obs ".
" AND a.id_utilisateur = $id_utilisateur ";
$resultats = $this->bdd->requeter($requete);
 
$mots_cles = array();
foreach ($resultats as $resultat) {
$mots_cles[] = $resultat['mot_cle'];
}
 
return $mots_cles;
}
 
private function executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $id_image_ou_obs, $id_utilisateur, $mode_image_ou_obs) {
$bdd = self::$bdd_cel_migration;
$table = ($mode_image_ou_obs == 'obs') ? 'cel_obs' : 'cel_images';
$chp_id_obs_ou_img = ($mode_image_ou_obs == 'obs') ? 'id_observation' : 'id_image';
$id_image_ou_obs = $this->bdd->proteger($id_image_ou_obs);
$mots_cles_texte = $this->bdd->proteger($mots_cles_texte_chaine);
$ce_utilisateur = $this->bdd->proteger($id_utilisateur);
 
$requete = "UPDATE $bdd.$table ".
"SET mots_cles_texte = $mots_cles_texte ".
"WHERE $chp_id_obs_ou_img = $id_image_ou_obs ".
" AND ce_utilisateur = $ce_utilisateur ";
 
return $this->bdd->executer($requete);
}
 
private function mettreANullMotsClesTxtVide() {
$bdd = self::$bdd_cel_migration;
$tables = array('cel_obs', 'cel_images');
 
foreach ($tables as $table) {
$requete = "UPDATE $bdd.$table ".
'SET mots_cles_texte = NULL '.
"WHERE mots_cles_texte = '' ";
$this->bdd->executer($requete);
}
}
}
/trunk/jrest/scripts/ImagesMaintenance.php
New file
0,0 → 1,120
<?php
// declare(encoding='UTF-8');
/**
* Réalise la maintenance des images.
* Action :
* - suppression_images_orphelines : supprime les images qui ne sont plus dans la bdd.
* Utilisation : /opt/lampp/bin/php cli.php ImagesMaintenance suppression_images_orphelines
*
* @category php 5.2
* @package Cel/Scripts
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class ImagesMaintenance {
 
private $bdd = null;
private $script = null;
private $chemin_base_images = '';
private $nbFichiersSupprimes = 0;
private $espaceLibere = 0;
 
public function __construct(Conteneur $conteneur) {
$this->chemin_base_images = $conteneur->getParametre('cel.chemin_images');
$this->bdd = $conteneur->getBdd();
$this->script = $conteneur->getScript();
}
 
public function executer($arguments) {
if (isset($arguments[0]) == false) {
throw new Exception("Veuillez indiquer l'action à réaliser en paramètre.", E_USER_ERROR);
}
$action = $arguments[0];
switch ($action) {
case 'suppression_images_orphelines' :
$this->supprimerFichiersImagesOrphelins();
break;
}
}
 
private function supprimerFichiersImagesOrphelins() {
$profondeur = 1;
$this->itererRecursivement($this->chemin_base_images, $profondeur);
 
print "Suppression des images orphelines effectuées\n";
$fichiersSupprimes = $this->nbFichiersSupprimes;
print "Fichiers orphelins détectés et supprimés : $fichiersSupprimes\n";
$espaceLibere = $this->convertirOctets($this->espaceLibere);
print "Espace disque économisé : $espaceLibere \n";
}
 
private function itererRecursivement($dossier, $profondeur) {
$dossiersAIgnorer = array('export');
$iterateur = new DirectoryIterator($dossier);
foreach ($iterateur as $element) {
if ($element->isDot() || in_array($element->getBasename(), $dossiersAIgnorer)) {
continue;
}
 
$indentation = str_repeat("\t", ($profondeur - 1));
if ($element->isDir()) {
$profondeur_dossier_fils = $profondeur + 1;
print "$indentation Analyse dossier : {$element->getPathname()}\n";
$this->itererRecursivement($element->getPathname(), $profondeur_dossier_fils);
} else {
print "$indentation Vérif fichier : {$element->getBasename()}\n";
$existe = $this->verifierPresenceImageDansBdd($element);
if ($existe == false) {
$this->supprimerFichierImage($element);
}
}
}
}
 
private function verifierPresenceImageDansBdd($element) {
$existe = true;
$nom_fichier = $element->getFilename();
if (preg_match('/^([0-9]{3})_([0-9]{3})_([0-9]{3})_[^.]+[.](jpg|xml)$/', $nom_fichier, $match)) {
$id_image = $match[1].$match[2].$match[3];
$id_image = ltrim($id_image, '0');
 
$requete = 'SELECT COUNT(ci_id_image) AS image_existe '.
'FROM cel_images '.
"WHERE ci_id_image = $id_image ";
 
$imageExiste = $this->bdd->requeter($requete, Bdd::SQL_RETOUR_COLONNE);
if ($imageExiste < 1) {
print "Image $id_image introuvable dans la base de données\n";
$existe = false;
}
}
return $existe;
}
 
private function supprimerFichierImage($element) {
$fichier = $element->getPathname();
$fichierNom = $element->getBasename();
if (file_exists($fichier)) {
$this->espaceLibere += $element->getSize();
if (unlink($fichier) === false) {
throw new Exception("Problème lors de la suppression du fichier : $fichier \n", E_USER_ERROR);
} else {
$this->nbFichiersSupprimes++;
print "Suppression du fichier : $fichierNom\n";
}
} else {
throw new Exception("Problème le fichier n'existe pas : $fichier\n", E_USER_ERROR);
}
}
 
private function convertirOctets($taille) {
$units = array('B', 'KB', 'MB', 'GB', 'TB');
for ($i = 0; $taille >= 1024 && $i < 4; $i++) $taille /= 1024;
return round($taille, 2).' '.$units[$i];
}
}
?>
/trunk/jrest/php.default.ini
New file
0,0 → 1,3
;; import CSV: 55000 observations en 3 minutes 40.
;; réglons donc ceci à 5 minutes
max_execution_time = 300
/trunk/jrest/migrationBdd.sh
New file
0,0 → 1,4
#!/bin/bash
/opt/lampp/bin/php cli.php MigrationObs
/opt/lampp/bin/php cli.php MigrationImages
/opt/lampp/bin/php cli.php MigrationMotsCles
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:executable
+*
\ No newline at end of property
/trunk/jrest/cli.php
New file
0,0 → 1,82
<?php
/**
* Script principal d'appel aux script de jrest par ligne de commande.
* Pour le moment ne supporte pas correctement les méthodes ayant des paramètres.
*/
 
/**
* La fonction __autoload() charge dynamiquement les classes trouvées dans le code.
*
* Cette fonction est appelée par php5 quand il trouve une instanciation de classe dans le code.
*
*@param string le nom de la classe appelée.
*@return void le fichier contenant la classe doit être inclu par la fonction.
*/
function __autoload($classe) {
if (class_exists($classe)) {
return null;
}
 
$chemins = array('', 'scripts/', 'lib/');
foreach ($chemins as $chemin) {
$chemin = $chemin.$classe.'.php';
if (file_exists($chemin)) {
require_once $chemin;
}
}
}
 
/**
* Configure PHP en fonction des paramètres du fichier de config.
* @param array $config le tableau de paramètres extraits du fichier ini.
*/
function parametrer($config) {
// Réglages de PHP
setlocale(LC_ALL, $config['settings']['locale']);
date_default_timezone_set($config['settings']['fuseauHoraire']);
}
 
try {
if (php_sapi_name() == 'cli') {
if ($_SERVER['argc'] < 2){
$message = "Erreur: vous n'avez pas indiqué le nom du script à appeler.";
throw new Exception($message, E_USER_ERROR);
}
 
// suppression du premier paramètre qui est le nom de ce fichier
array_shift($argv);
 
if ($_SERVER['argc'] == 0){
$message = "Erreur: vous n'avez pas indiqué le nom du script à lancer";
throw new Exception($message, E_USER_ERROR);
}
 
// récupération du nom du script à lancer
$nomScript = array_shift($argv);
 
$params = $argv;
$_SERVER['SERVER_NAME'] = 'localhost';
 
$config = parse_ini_file('jrest.ini.php', TRUE);
parametrer($config);
 
$conteneur = new Conteneur($config);
 
$script = new $nomScript($conteneur);
if (!is_callable(array($script, 'executer'))) {
$message = "Erreur: la méthode 'executer' du script '$nomScript' n'existe pas ou n'est pas accessible";
throw new Exception($message, E_USER_ERROR);
}
$script->executer($params);
} else {
$message = "Erreur: ce fichier est destiné a être appelé en ligne de commande.";
throw new Exception($message, E_USER_ERROR);
}
} catch (Exception $e) {
$tps = date('Y-m-j H:i:s');
$message = $e->getMessage();
$code = $e->getCode();
echo "$tps - $code : $message\n";
}
exit(0);
?>
/trunk/jrest/index.php
22,4 → 22,5
}
 
$jRest = new JRest();
$jRest->exec();
$jRest->exec();
?>