Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
open-document
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
lib
unicaen
open-document
Commits
861f45e9
Commit
861f45e9
authored
6 years ago
by
Laurent Lecluse
Browse files
Options
Downloads
Patches
Plain Diff
Pb colier/coller de fichier!!
parent
d9fd6f7a
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/Document.php
+557
-321
557 additions, 321 deletions
src/Document.php
src/Publisher.php
+2
-1
2 additions, 1 deletion
src/Publisher.php
with
559 additions
and
322 deletions
src/Document.php
+
557
−
321
View file @
861f45e9
...
...
@@ -2,107 +2,196 @@
namespace
Unicaen\OpenDocument
;
use
Exception
;
use
DOMDocument
;
use
DOMElement
;
use
DOMNode
;
use
DOMNodeList
;
use
Exception
;
use
ZipArchive
;
class
Publisher
class
Document
{
const
PAGE_BREAK_NAME
=
'UNICAEN_PAGE_BREAK'
;
const
PARAGRAPH
=
'text:p'
;
const
TABLE_ROW
=
'table:table-row'
;
/**
* @var ZipArchive
*/
private
$archive
;
/**
* Lecteur de fichier OpenDocument
*
* @var Document
* @var bool
*/
private
$document
;
private
$pdfOutput
=
false
;
/**
* @var Publisher
*/
private
$publisher
;
/**
* @var Stylist
*/
private
$stylist
;
/**
* @var DomDocument;
*/
private
$meta
;
/**
* @var DOMDocument
*/
private
$styles
;
/**
* Contenu XML du corps de texte
*
* @var DOMDocument
*/
private
$content
;
/**
* @var
DOMElement
* @var
array
*/
private
$
body
;
private
$
namespaces
=
[]
;
/**
* Ajoute un saut de page automatiquement entre deux instances de document lors du publipostage
*
* @var boolean
* @var bool
*/
private
$
autoBreak
=
tru
e
;
private
$
metaChanged
=
fals
e
;
/**
* @var
array
* @var
bool
*/
private
$values
=
[];
private
$stylesChanged
=
false
;
/**
* @var bool
*/
private
$contentChanged
=
false
;
/**
* Variable contenant le résultat final du content.xml
*
* @var string
*/
private
$
outContent
;
private
$
convCommand
=
'unoconv -f pdf -o :outputFile :inputFile'
;
/**
* @var
bool
* @var
string
*/
private
$
published
=
false
;
private
$
tmpDir
;
/**
* @var array
*/
private
$formatters
=
[];
/**
* @
return Document
* @
var array
*/
public
function
getDocument
():
Document
private
$tmpFiles
=
[];
private
$defaultNamespaces
=
[
'office'
=>
"urn:oasis:names:tc:opendocument:xmlns:office:1.0"
,
'style'
=>
"urn:oasis:names:tc:opendocument:xmlns:style:1.0"
,
'text'
=>
"urn:oasis:names:tc:opendocument:xmlns:text:1.0"
,
'table'
=>
"urn:oasis:names:tc:opendocument:xmlns:table:1.0"
,
'draw'
=>
"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
,
'fo'
=>
"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
,
'xlink'
=>
"http://www.w3.org/1999/xlink"
,
'dc'
=>
"http://purl.org/dc/elements/1.1/"
,
'meta'
=>
"urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
,
'number'
=>
"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
,
'svg'
=>
"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
,
'chart'
=>
"urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
,
'dr3d'
=>
"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
,
'math'
=>
"http://www.w3.org/1998/Math/MathML"
,
'form'
=>
"urn:oasis:names:tc:opendocument:xmlns:form:1.0"
,
'script'
=>
"urn:oasis:names:tc:opendocument:xmlns:script:1.0"
,
'ooo'
=>
"http://openoffice.org/2004/office"
,
'ooow'
=>
"http://openoffice.org/2004/writer"
,
'oooc'
=>
"http://openoffice.org/2004/calc"
,
'dom'
=>
"http://www.w3.org/2001/xml-events"
,
'rpt'
=>
"http://openoffice.org/2005/report"
,
'of'
=>
"urn:oasis:names:tc:opendocument:xmlns:of:1.2"
,
'xhtml'
=>
"http://www.w3.org/1999/xhtml"
,
'grddl'
=>
"http://www.w3.org/2003/g/data-view#"
,
'officeooo'
=>
"http://openoffice.org/2009/office"
,
'tableooo'
=>
"http://openoffice.org/2009/table"
,
'drawooo'
=>
"http://openoffice.org/2010/draw"
,
'calcext'
=>
"urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
,
'css3t'
=>
"http://www.w3.org/TR/css3-text/"
,
'xforms'
=>
'http://www.w3.org/2002/xforms'
,
'xsd'
=>
'http://www.w3.org/2001/XMLSchema'
,
'xsi'
=>
'http://www.w3.org/2001/XMLSchema-instance'
,
'loext'
=>
'urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0'
,
'field'
=>
'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0'
,
'formx'
=>
'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0'
,
];
/**
* @return ZipArchive
* @throws Exception
*/
public
function
getArchive
():
ZipArchive
{
return
$this
->
document
;
if
(
!
$this
->
archive
)
{
throw
new
\Exception
(
"Aucun document n\'est chargé"
);
}
return
$this
->
archive
;
}
/**
* @param Document $document
*
* @return Publisher
* @return DOMDocument
*/
public
function
s
et
Document
(
Document
$document
):
Publisher
public
function
g
et
Content
():
DOMDocument
{
$this
->
document
=
$document
;
return
$this
->
content
;
}
return
$this
;
/**
* @return DOMDocument
*/
public
function
getStyles
():
DOMDocument
{
return
$this
->
styles
;
}
/**
* @return DOM
Ele
ment
* @return DOM
Docu
ment
*/
public
function
get
Body
():
DOM
Ele
ment
public
function
get
Meta
():
DOM
Docu
ment
{
return
$this
->
body
;
return
$this
->
meta
;
}
/**
* Peuple l'instance courante du document et l'ajoute à la suite du fichier
* @return bool
*/
public
function
isPdfOutput
():
bool
{
return
$this
->
pdfOutput
;
}
/**
* @param bool $pdfOutput
*
* @
param array $values
* @
return Document
*/
public
function
add
(
array
$values
):
Publisher
public
function
setPdfOutput
(
bool
$pdfOutput
):
Document
{
$this
->
values
[]
=
$values
;
$this
->
pdfOutput
=
$pdfOutput
;
return
$this
;
}
...
...
@@ -110,21 +199,23 @@ class Publisher
/**
* @return
array
* @return
bool
*/
public
function
getValues
():
array
public
function
isMetaChanged
():
bool
{
return
$this
->
values
;
return
$this
->
metaChanged
;
}
/**
* @param array $values
* @param bool $metaChanged
*
* @return Document
*/
public
function
set
Values
(
array
$values
):
Publisher
public
function
set
MetaChanged
(
bool
$metaChanged
):
Document
{
$this
->
values
=
$values
;
$this
->
metaChanged
=
$metaChanged
;
return
$this
;
}
...
...
@@ -134,21 +225,21 @@ class Publisher
/**
* @return bool
*/
public
function
is
AutoBreak
():
bool
public
function
is
StylesChanged
():
bool
{
return
$this
->
autoBreak
;
return
$this
->
stylesChanged
;
}
/**
* @param bool $
autoBreak
* @param bool $
stylesChanged
*
* @return
Publisher
* @return
Document
*/
public
function
set
AutoBreak
(
bool
$autoBreak
):
Publisher
public
function
set
StylesChanged
(
bool
$stylesChanged
):
Document
{
$this
->
autoBreak
=
$autoBreak
;
$this
->
stylesChanged
=
$stylesChanged
;
return
$this
;
}
...
...
@@ -156,167 +247,265 @@ class Publisher
/**
* @param DOMElement $element
*
* @return Publisher
* @throws Exception
* @return bool
*/
public
function
getVariables
(
DOMElement
$element
):
array
public
function
isContentChanged
():
bool
{
$textNs
=
$this
->
getDocument
()
->
getNamespaceUrl
(
'text'
);
return
$this
->
contentChanged
;
}
$variables
=
[];
$vElements
=
$element
->
getElementsByTagNameNS
(
$textNs
,
'variable-set'
);
foreach
(
$vElements
as
$vElement
)
{
$name
=
$vElement
->
getAttributeNS
(
$textNs
,
'name'
);
/**
* @param bool $contentChanged
*
* @return Document
*/
public
function
setContentChanged
(
bool
$contentChanged
):
Document
{
$this
->
contentChanged
=
$contentChanged
;
if
(
!
isset
(
$variables
[
$name
]))
$variables
[
$name
]
=
[];
$variables
[
$name
][]
=
$vElement
;
return
$this
;
}
return
$variables
;
/**
* @return string
*/
public
function
getConvCommand
():
string
{
return
$this
->
convCommand
;
}
public
function
getSections
(
DOMElement
$element
):
array
/**
* @param string $convCommand
*
* @return Document
*/
public
function
setConvCommand
(
string
$convCommand
):
Document
{
$textNs
=
$this
->
getDocument
()
->
getNamespaceUrl
(
'text'
);
$this
->
convCommand
=
$convCommand
;
return
$this
;
}
$sections
=
[];
$vElements
=
$this
->
findFrom
(
$element
,
'text:section'
);
foreach
(
$vElements
as
$vElement
)
{
$name
=
$vElement
->
getAttributeNS
(
$textNs
,
'name'
);
if
(
!
isset
(
$sections
[
$name
]))
$sections
[
$name
]
=
[];
$sections
[
$name
][]
=
$vElement
;
/**
* Retourne les méta-données du fichier OpenDocument
*
* @return array
*/
public
function
getMetaArray
():
array
{
$m
=
[];
$nodes
=
$this
->
getMeta
()
->
documentElement
->
childNodes
->
item
(
0
)
->
childNodes
;
foreach
(
$nodes
as
$node
)
{
if
(
isset
(
$node
->
tagName
))
{
switch
(
$node
->
tagName
)
{
case
'meta:generator'
:
case
'meta:initial-creator'
:
case
'meta:editing-cycles'
:
case
'meta:editing-duration'
:
case
'meta:printed-by'
:
case
'dc:title'
:
case
'dc:description'
:
case
'dc:subject'
:
case
'dc:creator'
:
case
'dc:language'
:
list
(
$ns
,
$tag
)
=
explode
(
':'
,
$node
->
tagName
);
$m
[
$tag
]
=
$node
->
textContent
;
break
;
case
'meta:creation-date'
:
$m
[
'creation-date'
]
=
substr
(
$node
->
textContent
,
0
,
10
);
break
;
case
'meta:print_date'
:
$m
[
'print_date'
]
=
substr
(
$node
->
textContent
,
0
,
10
);
break
;
case
'dc:date'
:
$m
[
'date'
]
=
substr
(
$node
->
textContent
,
0
,
10
);
break
;
case
'meta:document-statistic'
:
$m
[
'document-statistic'
]
=
[];
foreach
(
$node
->
attributes
as
$attribute
)
{
$m
[
'document-statistic'
][
$attribute
->
name
]
=
$attribute
->
value
;
}
break
;
case
'meta:user-defined'
:
if
(
!
isset
(
$m
[
'user-defined'
]))
$m
[
'user-defined'
]
=
[];
foreach
(
$node
->
attributes
as
$attribute
)
{
$m
[
'user-defined'
][
$attribute
->
name
]
=
$attribute
->
value
;
}
break
;
case
'meta:keywords'
:
$m
[
'keywords'
]
=
[];
foreach
(
$node
->
childNodes
as
$knode
)
{
$m
[
'keywords'
][]
=
$knode
->
textContent
;
}
break
;
}
}
}
return
$
sections
;
return
$
m
;
}
public
function
hideSection
(
DOMElement
$section
):
Publisher
/**
* @param string $variable
* @param mixed $value
*
* @return string
*/
public
function
formatValue
(
string
$variable
,
$value
):
string
{
$section
->
parentNode
->
removeChild
(
$section
);
if
(
isset
(
$this
->
formatters
[
$variable
])
&&
$format
=
$this
->
formatters
[
$variable
]){
if
(
is_callable
(
$format
)){
$value
=
$format
(
$value
);
}
}
return
$this
;
if
(
is_float
(
$value
)){
return
number_format
(
$value
,
2
,
','
,
' '
);
}
return
(
string
)
$value
;
}
/**
* @param DOMElement $element
* @param mixed $value
* Retourne les espaces de nom associés à leurs URI respectives sous forme de tableau associatif
*
* @return
Publisher
* @return
array
*/
p
rotected
function
s
et
Variable
(
DOMElement
$element
,
$value
):
Publisher
p
ublic
function
g
et
Namespaces
():
array
{
$textNs
=
$this
->
getDocument
()
->
getNamespaceUrl
(
'text'
);
$document
=
$element
->
ownerDocument
;
if
(
empty
(
$this
->
namespaces
))
{
$content
=
$this
->
getArchive
()
->
getFromName
(
'content.xml'
)
;
if
(
is_string
(
$value
)
&&
false
!==
strpos
(
$value
,
"
\n
"
)){
$value
=
explode
(
"
\n
"
,
$value
);
}
else
{
$value
=
(
array
)
$value
;
$begin
=
strpos
(
$content
,
'<'
,
1
)
+
2
+
strlen
(
'office:document-content'
);
$end
=
strpos
(
$content
,
'>'
,
50
)
-
$begin
;
$content
=
explode
(
' '
,
substr
(
$content
,
$begin
,
$end
));
$this
->
namespaces
=
$this
->
defaultNamespaces
;
foreach
(
$content
as
$str
)
{
if
(
0
===
strpos
(
$str
,
'xmlns:'
))
{
$namespace
=
substr
(
$str
,
6
,
strpos
(
$str
,
'"'
)
-
7
);
$url
=
substr
(
$str
,
strpos
(
$str
,
'"'
)
+
1
,
-
1
);
$this
->
namespaces
[
$namespace
]
=
$url
;
}
for
(
$i
=
0
;
$i
<
count
(
$value
);
$i
++
)
{
if
(
$i
>
0
)
{
$returnVNode
=
$document
->
createElementNS
(
$textNs
,
'text:line-break'
);
$element
->
parentNode
->
insertBefore
(
$returnVNode
,
$element
);
}
$vText
=
$document
->
createTextNode
(
$this
->
getDocument
()
->
formatValue
(
$element
->
nodeValue
,
$value
[
$i
]));
$element
->
parentNode
->
insertBefore
(
$vText
,
$element
);
}
$element
->
parentNode
->
removeChild
(
$element
);
return
$this
;
return
$this
->
namespaces
;
}
private
function
addPageBreakStyle
():
Publisher
/**
* @param string $name
*
* @return bool
*/
public
function
hasNamespace
(
string
$name
):
bool
{
/* get office:automatic-styles node */
$styles
=
$this
->
content
->
getElementsByTagNameNS
(
$this
->
getDocument
()
->
getNamespaceUrl
(
'office'
),
'automatic-styles'
)
->
item
(
0
);
$this
->
getNamespaces
();
return
isset
(
$this
->
namespaces
[
$name
]);
}
$stylePageBreak
=
$this
->
newElement
(
'style:style'
,
[
'style:name'
=>
self
::
PAGE_BREAK_NAME
,
'style:family'
=>
'paragraph'
,
'style:parent-style-name'
=>
'Standard'
,
'style:master-page-name'
=>
'Standard'
,
]);
$stylePageBreakProperties
=
$this
->
newElement
(
'style:paragraph-properties'
,
[
'style:writing-mode'
=>
'page'
,
'style:page-number'
=>
'1'
,
]);
$stylePageBreak
->
appendChild
(
$stylePageBreakProperties
);
$styles
->
appendChild
(
$stylePageBreak
);
/**
* @param string $name
* @param string $url
*
* @return Document
*/
public
function
addNamespace
(
string
$name
,
string
$url
):
Document
{
if
(
!
$this
->
hasNamespace
(
$name
))
{
$this
->
namespaces
[
$name
]
=
$url
;
}
return
$this
;
}
private
function
addPageBreak
(
DOMElement
$element
):
Publisher
/**
* Retourne l'url associé à un espace de nom
*
* @param string $namespace
*
* @return string
*/
public
function
getNamespaceUrl
(
string
$namespace
):
string
{
$
textN
s
=
$this
->
get
Document
()
->
getNamespaceUrl
(
'text'
);
$
n
s
=
$this
->
get
Namespaces
(
);
$pageBreak
=
$this
->
content
->
createElementNS
(
$textNs
,
'text:p'
);
$pageBreak
->
setAttributeNS
(
$textNs
,
'text:style-name'
,
self
::
PAGE_BREAK_NAME
);
$element
->
insertBefore
(
$pageBreak
,
$element
->
firstChild
);
if
(
!
isset
(
$ns
[
$namespace
]))
{
throw
new
Exception
(
'L\'espace de nom '
.
$namespace
.
' n\'a pas été trouvé.'
);
}
return
$
this
;
return
$
ns
[
$namespace
]
;
}
/**
* @return Publisher
* @throws Exception
* Retourne un champ d'information
*
* @param integer $index
*
* @return string
*/
public
function
publishBegin
():
Publisher
public
function
getInfo
(
$index
)
{
/* On récupère le content du document */
$this
->
content
=
new
DOMDocument
();
$this
->
content
->
loadXML
(
$this
->
getDocument
()
->
getContent
()
->
saveXML
());
$infonodes
=
$this
->
getMeta
()
->
getElementsByTagNameNS
(
$this
->
getNamespaceUrl
(
'meta'
),
'user-defined'
);
if
(
$this
->
isAutoBreak
())
{
$this
->
addPageBreakStyle
();
return
$infonodes
->
item
(
$index
)
->
nodeValue
;
}
$contentText
=
$this
->
content
->
saveXML
();
$officeDocumentContentPos
=
strpos
(
$contentText
,
'<office:document-content'
);
$length
=
strpos
(
$contentText
,
'>'
,
$officeDocumentContentPos
)
+
1
;
$this
->
out
(
substr
(
$contentText
,
0
,
$length
));
/* wtite all nodes, except body */
foreach
(
$this
->
content
->
documentElement
->
childNodes
as
$node
)
{
if
(
$node
->
nodeName
!=
'office:body'
)
{
$this
->
out
(
$this
->
content
->
saveXML
(
$node
));
}
}
$this
->
out
(
"<office:body>"
);
/* declaration tags */
$declTags
=
[
'variable-decls'
,
'sequence-decls'
,
'user-field-decls'
,
'dde-connexion-decls'
,
];
foreach
(
$declTags
as
$tagName
)
{
$node
=
$this
->
content
->
getElementsByTagNameNS
(
$this
->
getDocument
()
->
getNamespaceUrl
(
'text'
),
$tagName
);
if
(
$node
->
length
>
0
)
{
$this
->
out
(
$this
->
content
->
saveXML
(
$node
->
item
(
0
)));
$node
->
item
(
0
)
->
parentNode
->
removeChild
(
$node
->
item
(
0
));
/**
* Modifie un champ d'information
*
* @todo à finir d'implémenter, car ça ne marche pas!!
*
* @param integer $index
* @param string $value
*/
public
function
setInfo
(
$index
,
$value
):
Document
{
throw
new
\Exception
(
'Implémentation à corriger : ne fonctionne pas'
);
$infonodes
=
$this
->
getMeta
()
->
getElementsByTagNameNS
(
$this
->
getNamespaceUrl
(
'meta'
),
'user-defined'
);
if
(
$infonodes
->
length
>
0
)
{
$infonodes
->
item
(
$index
)
->
nodeValue
=
$value
;
$this
->
setMetaChanged
(
true
);
}
return
$this
;
}
$this
->
body
=
$this
->
content
->
getElementsByTagNameNS
(
$this
->
getDocument
()
->
getNamespaceUrl
(
'office'
),
'text'
)[
0
];
/**
* @param array $values
*
* @return Document
*/
public
function
publish
(
array
$values
):
Document
{
$this
->
getPublisher
()
->
setValues
(
$values
);
$this
->
getPublisher
()
->
publish
();
return
$this
;
}
...
...
@@ -326,114 +515,167 @@ class Publisher
/**
* @return Publisher
*/
public
function
p
ublish
End
():
Publisher
public
function
getP
ublish
er
():
Publisher
{
$this
->
out
(
"</office:body></office:document-content>"
);
if
(
!
$this
->
publisher
)
{
$this
->
publisher
=
new
Publisher
();
$this
->
publisher
->
setDocument
(
$this
);
}
/* On renvoie le content dans le document */
$this
->
getDocument
()
->
getArchive
()
->
addFromString
(
'content.xml'
,
$this
->
outContent
);
$this
->
published
=
true
;
return
$this
->
publisher
;
}
return
$this
;
/**
* @return Stylist
*/
public
function
getStylist
():
Stylist
{
if
(
!
$this
->
stylist
)
{
$this
->
stylist
=
new
Stylist
();
$this
->
stylist
->
setDocument
(
$this
);
}
return
$this
->
stylist
;
}
/**
* @param DOMElement $element
* @param array $values
* @param $data
*
* @return
Publisher
* @return
Document
* @throws Exception
*/
public
function
publishValues
(
DOMElement
$element
,
array
$values
):
Publisher
public
function
loadFromData
(
$data
):
Document
{
if
(
$element
===
$this
->
body
)
{
$
th
is
->
getDocument
()
->
getStylist
()
->
setVariables
(
$values
);
if
(
!
class_exists
(
'ZipArchive'
)
)
{
th
row
new
Exception
(
'Zip extension not loaded'
);
}
$
variab
le
s
=
$this
->
getVariables
(
$element
);
$sections
=
$this
->
getSections
(
$element
);
$
odtFi
le
=
$this
->
tempFileName
(
'odtfile_'
,
'odt'
);
file_put_contents
(
$odtFile
,
$data
);
foreach
(
$values
as
$name
=>
$val
)
{
if
(
is_array
(
$val
))
{
/* On traite les données filles... */
list
(
$vname
,
$vparent
)
=
explode
(
"@"
,
$name
);
if
(
isset
(
$variables
[
$vname
]))
{
foreach
(
$variables
[
$vname
]
as
$elVar
)
{
$this
->
publishSubData
(
$elVar
,
$vparent
,
$val
);
return
$this
->
loadFromFile
(
$odtFile
,
false
);
}
/**
* @param string $fileName
* @param bool $duplicate
*
* @return Document
* @throws Exception
*/
public
function
loadFromFile
(
string
$fileName
,
bool
$duplicate
=
true
):
Document
{
if
(
!
class_exists
(
'ZipArchive'
))
{
throw
new
Exception
(
'Zip extension not loaded'
);
}
if
(
isset
(
$sections
[
$vname
]))
{
foreach
(
$sections
[
$vname
]
as
$elSec
)
{
$this
->
publishSubData
(
$elSec
,
$vparent
,
$val
);
}
if
(
!
file_exists
(
$fileName
))
{
throw
new
Exception
(
'OpenDocument file "'
.
$fileName
.
'" doesn\'t exists.'
);
}
if
(
$duplicate
)
{
$odtFile
=
$this
->
tempFileName
(
'odtFile_'
,
'odt'
);
copy
(
$fileName
,
$odtFile
);
}
else
{
if
(
isset
(
$variables
[
$name
]))
{
foreach
(
$variables
[
$name
]
as
$vElement
)
{
$this
->
setVariable
(
$vElement
,
$val
?
$val
:
''
);
}
}
if
(
false
!==
strpos
(
$name
,
'@'
))
{
list
(
$sName
,
$sType
)
=
explode
(
"@"
,
$name
);
if
(
$sType
==
'text:section'
)
{
$name
=
$sName
;
$odtFile
=
$fileName
;
}
$this
->
archive
=
new
ZipArchive
();
if
(
!
true
===
$this
->
archive
->
open
(
$odtFile
,
ZIPARCHIVE
::
CREATE
))
{
throw
new
Exception
(
'OpenDocument file "'
.
$fileName
.
'" don\'t readable.'
);
}
if
(
isset
(
$sections
[
$name
]))
{
foreach
(
$sections
[
$name
]
as
$sElement
)
{
if
(
$val
===
null
||
$val
===
0
||
$val
===
'0'
||
$val
===
false
||
$val
===
''
||
strtolower
(
$val
)
===
'false'
)
{
$this
->
hideSection
(
$sElement
);
$this
->
meta
=
new
DOMDocument
;
$this
->
meta
->
loadXML
(
$this
->
archive
->
getFromName
(
'meta.xml'
));
$this
->
styles
=
new
DOMDocument
;
$this
->
styles
->
loadXML
(
$this
->
archive
->
getFromName
(
'styles.xml'
));
$this
->
content
=
new
DOMDocument
;
$this
->
content
->
loadXML
(
$this
->
archive
->
getFromName
(
'content.xml'
));
$this
->
namespaces
=
[];
return
$this
;
}
/**
* @return string
* @throws Exception
*/
private
function
prepareSaving
(
$filename
=
null
):
string
{
if
(
$this
->
isMetaChanged
())
{
$this
->
getArchive
()
->
addFromString
(
'meta.xml'
,
$this
->
getMeta
()
->
saveXML
());
}
if
(
$this
->
isStylesChanged
())
{
$this
->
getArchive
()
->
addFromString
(
'styles.xml'
,
$this
->
getStyles
()
->
saveXML
());
}
if
(
$this
->
isContentChanged
())
{
$this
->
getArchive
()
->
addFromString
(
'content.xml'
,
$this
->
getContent
()
->
saveXML
());
}
$actualFile
=
$this
->
getArchive
()
->
filename
;
$this
->
getArchive
()
->
close
();
$this
->
archive
=
null
;
if
(
$this
->
isPdfOutput
())
{
if
(
!
$filename
)
{
$filename
=
$this
->
tempFileName
(
'odt2pdf_'
,
'pdf'
);
}
if
(
$element
===
$this
->
b
od
y
)
{
$
this
->
out
(
$this
->
content
->
saveXML
(
$element
))
;
$this
->
od
tToPdf
(
$actualFile
,
$filename
);
$
actualFile
=
$filename
;
}
return
$
this
;
return
$
actualFile
;
}
/**
* @param DOMElement $element
* @param string $parent
* @param string $variable
* @param $origine
* @param $destination
*
* @return D
OMEle
ment
* @return D
ocu
ment
* @throws Exception
*/
public
function
getSubDoc
(
DOMElement
$element
,
string
$parent
,
st
r
in
g
$variable
):
DOMEle
ment
public
function
odtToPdf
(
$origine
,
$de
stin
ation
):
Docu
ment
{
$variables
=
$this
->
getVariables
(
$element
);
if
(
!
isset
(
$variables
[
$variable
][
0
]))
{
throw
new
\Exception
(
'La variable "'
.
$variable
.
'"" n\'a pas été trouvée dans le document'
);
$command
=
$this
->
getConvCommand
();
$command
=
str_replace
(
':inputFile'
,
$origine
,
$this
->
getConvCommand
());
$command
=
str_replace
(
':outputFile'
,
$destination
,
$command
);
exec
(
$command
,
$output
,
$return
);
if
(
0
!=
$return
)
{
throw
new
\Exception
(
'La conversion de document en PDF a échoué'
);
}
return
$this
->
getSubDocWithVariable
(
$variables
[
$variable
][
0
],
$parent
)
;
return
$this
;
}
/**
* @param
DOMElement $element
* @param
string $fileName
*
* @return Publisher
* @return Document
* @throws Exception
*/
public
function
remove
(
DOMElement
$element
):
Publisher
public
function
saveToFile
(
string
$fileName
):
Document
{
$
element
->
p
a
re
ntNode
->
removeChild
(
$element
);
$
actualFile
=
$this
->
pre
pareSaving
(
$fileName
);
return
$this
;
}
...
...
@@ -441,192 +683,186 @@ class Publisher
/**
* @param DOMElement $subDoc
* @param array $variables
* @param DOMElement $refNode
*
* @return Publisher
* @return string
* @throws Exception
*/
public
function
publishBefore
(
DOMElement
$subDoc
,
array
$variables
,
DOMElement
$refNode
):
Publisher
public
function
saveToData
():
string
{
$node
=
$subDoc
->
cloneNode
(
true
);
$this
->
publishValues
(
$node
,
$variables
);
$refNode
->
parentNode
->
insertBefore
(
$node
,
$refNode
);
$actualFile
=
$this
->
prepareSaving
();
return
$this
;
return
file_get_contents
(
$actualFile
)
;
}
/**
* @param DOMElement $element
* @param string $parent
* @param DOMElement $variable
*
* @return DOMElement
* @throws Exception
* @return string
*/
p
rivate
function
get
SubDocWithVariable
(
DOMElement
$element
,
string
$parent
):
DOMElement
p
ublic
function
get
TmpDir
():
string
{
if
(
$element
->
tagName
==
'text:section'
)
{
return
$element
;
// C'est la section qui est dupliquée
}
else
{
$i
=
10
;
$found
=
false
;
for
(
$i
=
0
;
$i
<
10
;
$i
++
)
{
$parentNode
=
isset
(
$parentNode
)
?
$parentNode
->
parentNode
:
$element
->
parentNode
;
if
(
$parentNode
->
nodeName
==
$parent
)
{
$found
=
true
;
break
;
}
if
(
!
$this
->
tmpDir
)
{
return
sys_get_temp_dir
();
}
if
(
!
$found
)
{
throw
new
\Exception
(
'Le noeud parent de type '
.
$parent
.
' n\'a pas été trouvé'
);
}
return
$parentNode
;
}
return
$this
->
tmpDir
;
}
/**
* @param DOMElement $element
* @param string $parent
* @param array $values
* @param string $tmpDir
*
* @return
Publisher
* @return
Document
*/
p
rivate
function
publishSubData
(
DOMElement
$element
,
string
$parent
,
array
$values
):
Publisher
p
ublic
function
setTmpDir
(
string
$tmpDir
):
Document
{
$parentNode
=
$this
->
getSubDocWithVariable
(
$element
,
$parent
);
foreach
(
$values
as
$vals
)
{
$clone
=
$parentNode
->
cloneNode
(
true
);
$this
->
publishValues
(
$clone
,
$vals
);
$parentNode
->
parentNode
->
insertBefore
(
$clone
,
$parentNode
);
$this
->
tmpDir
=
$tmpDir
;
if
(
!
file_exists
(
$tmpDir
))
{
mkdir
(
$tmpDir
);
}
return
$this
->
remove
(
$parentNode
)
;
return
$this
;
}
/**
* Construit le fichier final à partir des données
* @param null $prefix
*
* @return string
*/
p
ublic
function
publish
()
p
rivate
function
tempFileName
(
$prefix
=
null
,
$ext
=
'odt'
):
string
{
$this
->
publishBegin
();
$first
=
true
;
foreach
(
$this
->
values
as
$values
)
{
$bodyNode
=
$this
->
body
->
cloneNode
(
true
);
if
(
$first
)
{
$first
=
false
;
}
elseif
(
$this
->
isAutoBreak
())
{
$this
->
addPageBreak
(
$bodyNode
);
$tmpDir
=
$this
->
getTmpDir
();
if
(
'/'
!=
substr
(
$tmpDir
,
-
1
))
{
$tmpDir
.
=
'/'
;
}
$this
->
publishValues
(
$bodyNode
,
$values
);
$this
->
getDocument
()
->
getStylist
()
->
setVariables
(
$values
);
$this
->
out
(
$this
->
content
->
saveXML
(
$bodyNode
));
$first
=
false
;
}
$tempFileName
=
uniqid
(
$tmpDir
.
$prefix
)
.
'.'
.
$ext
;
$this
->
tmpFiles
[]
=
$tempFileName
;
$this
->
publishEnd
()
;
return
$tempFileName
;
}
/**
* @param string $name
*
* @return DOMNode[]
* @throws Exception
* @return array
*/
p
rivate
function
find
(
string
$name
):
DOMNodeList
p
ublic
function
getFormatters
():
array
{
$document
=
$this
->
getDocument
();
return
$document
->
find
(
$this
->
content
,
$name
);
return
$this
->
formatters
;
}
/**
* @param
DOMNode $nod
e
* @param
$name
* @param
string $variabl
e
* @param
mixed $format
*
* @return DOMNodeList
* @throws Exception
* @return Document
*/
p
rivate
function
findFrom
(
DOMNode
$node
,
$name
):
DOMNodeLis
t
p
ublic
function
addFormatter
(
string
$variable
,
$format
):
Documen
t
{
return
$this
->
getDocument
()
->
find
(
$node
,
$name
);
$this
->
formatters
[
$variable
]
=
$format
;
return
$this
;
}
/**
* @param string $name
* @param array $attrs
* PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++.
* The destructor method will be called as soon as all references to a particular object are removed or
* when the object is explicitly destroyed or in any order in shutdown sequence.
*
* @return DOMElement
* Like constructors, parent destructors will not be called implicitly by the engine.
* In order to run a parent destructor, one would have to explicitly call parent::__destruct() in the destructor body.
*
* Note: Destructors called during the script shutdown have HTTP headers already sent.
* The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache).
*
* Note: Attempting to throw an exception from a destructor (called in the time of script termination) causes a fatal
* error.
*
* @return void
* @link https://php.net/manual/en/language.oop5.decon.php
*/
p
rivate
function
newElement
(
string
$name
,
array
$attrs
=
[]):
DOMElement
p
ublic
function
__destruct
()
{
$document
=
$this
->
getDocument
();
return
$document
->
newElement
(
$this
->
content
,
$name
,
$attrs
);
/* On supprime les éventuels fichiers temporaires pour libérer l'espace */
foreach
(
$this
->
tmpFiles
as
$tmpFile
)
{
if
(
file_exists
(
$tmpFile
))
{
unlink
(
$tmpFile
);
}
}
}
/**
* Ajoute du contenu au fichier content.xml
* Méthode à ne pas exploiter
* @param $fileName
*
* @param string $xml
* @return Document
* @throws Exception
*/
public
function
out
(
$xml
)
public
function
download
(
$fileName
):
Document
{
$this
->
outContent
.
=
$xml
;
$actualFile
=
$this
->
prepareSaving
();
if
(
headers_sent
())
{
throw
new
Exception
(
'Headers Allready Sent'
);
}
$contentType
=
$this
->
isPdfOutput
()
?
'application/pdf'
:
'application/vnd.oasis.opendocument.text'
;
header
(
'Content-type: '
.
$contentType
);
header
(
'Content-Disposition: attachment; filename="'
.
$fileName
.
'"'
);
header
(
'Content-Transfer-Encoding: binary'
);
header
(
'Pragma: no-cache'
);
header
(
'Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
);
header
(
'Expires: 0'
);
readfile
(
$actualFile
);
/**
* @return string
*/
public
function
getOutContent
():
string
{
return
$this
->
outContent
;
return
$this
;
}
/**
* @return bool
* @param DOMNode $node
* @param string $name
*
* @return DOMNode[]
* @throws Exception
*/
public
function
isPublished
():
bool
public
function
find
(
DOMNode
$node
,
string
$name
):
DOMNodeList
{
return
$this
->
published
;
list
(
$namespace
,
$name
)
=
explode
(
':'
,
$name
);
return
$node
->
getElementsByTagNameNS
(
$this
->
getNamespaceUrl
(
$namespace
),
$name
);
}
/**
* @param bool $published
* @param DOMDocument $document
* @param string $name
* @param array $attrs
*
* @return Publisher
* @return DOMElement
* @throws Exception
*/
public
function
setPublished
(
bool
$published
):
Publisher
public
function
newElement
(
DOMDocument
$document
,
string
$name
,
array
$attrs
=
[]):
DOMElement
{
$this
->
published
=
$published
;
list
(
$namespace
)
=
explode
(
':'
,
$name
)
;
return
$this
;
$newNode
=
$document
->
createElementNS
(
$this
->
getNamespaceUrl
(
$namespace
),
$name
);
foreach
(
$attrs
as
$attrName
=>
$attrValue
)
{
list
(
$attrNS
)
=
explode
(
':'
,
$attrName
);
$newNode
->
setAttributeNS
(
$this
->
getNamespaceUrl
(
$attrNS
),
$attrName
,
$attrValue
);
}
return
$newNode
;
}
}
This diff is collapsed.
Click to expand it.
src/Publisher.php
+
2
−
1
View file @
861f45e9
...
...
@@ -505,7 +505,7 @@ class Publisher
foreach
(
$values
as
$vals
)
{
$clone
=
$parentNode
->
cloneNode
(
true
);
$this
->
publishValues
(
$clone
,
$vals
);
$
this
->
insertBefore
(
$clone
,
$parentNode
);
$
parentNode
->
parentNode
->
insertBefore
(
$clone
,
$parentNode
);
}
return
$this
->
remove
(
$parentNode
);
...
...
@@ -530,6 +530,7 @@ class Publisher
}
$this
->
publishValues
(
$bodyNode
,
$values
);
$this
->
getDocument
()
->
getStylist
()
->
setVariables
(
$values
);
$this
->
out
(
$this
->
content
->
saveXML
(
$bodyNode
));
$first
=
false
;
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment