Skip to content

ODPresentation Writer : Fixed a link to another slide - #908

Merged
Progi1984 merged 1 commit into
PHPOffice:masterfrom
sapientpro:fix/odp-slide-link
Aug 23, 2026
Merged

ODPresentation Writer : Fixed a link to another slide#908
Progi1984 merged 1 commit into
PHPOffice:masterfrom
sapientpro:fix/odp-slide-link

Conversation

@dkulyk

@dkulyk dkulyk commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description

A hyperlink created with setSlideNumber() stores the PowerPoint action string ppaction://hlinksldjump, and the ODPresentation Writer wrote it verbatim into xlink:href. ODF has never heard of that string, so the link opened nothing -- converted to PDF it comes out as /A<</Type/Action/S/URI/URI(ppaction://hlinksldjump)>>, an unresolvable URI rather than a jump.

ODF addresses a slide by the name of its page, so the Writer now writes #<page name>, and every draw:page carries a draw:name so that a link can reach it. A slide with no name of its own is named after its position, as Slide N. Not as pageN: LibreOffice generates exactly that form for the pages it exports and treats it as its own, so a link to #page3 is left unresolved -- I probed the three forms and only the non-pageN ones produce a real destination. With the fix both #Milestone Overview and #Slide 3 come out as /Dest[9 0 R/FitR 0 0 720 541.417].

If the slide number points outside the deck there is nothing to address, so the value is left as it was rather than pointing nowhere.

Neither Reader recognised such a link either, so the number never survived a round trip and the fixed Writer alone could not carry a link across a format conversion. The PowerPoint2007 Reader stored the raw part name, slide2.xml, as the URL; the ODPresentation Reader stored the raw #Name. Both now resolve the target back to its number -- the PowerPoint2007 Reader from the slide relationship plus the action attribute, the ODPresentation Reader from a pre-pass over the page names, collected before any slide is read because a link can point forwards.

One existing expectation changed as a consequence: ContentTest::testSlideName asserted that an unnamed slide gets no draw:name, and now every page has one. A save/load round trip therefore gives a previously unnamed slide the name Slide N -- the same thing that already happens with any ODP produced by LibreOffice.

Checklist:

  • My CI is 🟢

    Every job is green, including PHPUnit on 7.4 and 8.0.

  • I have covered by unit tests my new code (check build/coverage for coverage report)

    ContentTest::testSlideLink covers both the named and the position-named target, testSlideLinkOutOfRange the untouched fallback, and PowerPoint2007Test::testHyperlinkToSlide / ODPresentationTest::testHyperlinkToSlide the round trip through each Reader, with ODPresentationTest::testHyperlinkToUrl guarding the external-URL path. I checked each one fails without the change.

  • I have updated the documentation to describe the changes

    docs/usage/shapes/richtext.md gained a "Link to another slide" section explaining setSlideNumber() and how each format addresses the target.

  • I have updated the changelog

    Added an entry under 1.3.0.

@coveralls

coveralls commented Aug 20, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 92.407% (+0.01%) from 92.394% — sapientpro:fix/odp-slide-link into PHPOffice:master

@dkulyk
dkulyk force-pushed the fix/odp-slide-link branch from a130016 to bbcd87b Compare August 22, 2026 10:47
…ders

A hyperlink created with `setSlideNumber()` stores the PowerPoint action string
`ppaction://hlinksldjump`, which the ODPresentation Writer wrote verbatim into
`xlink:href`. ODF has never heard of it, so the link opened nothing: the reader
resolved it as an unknown URI. ODF addresses a slide by the name of its page, so
the Writer now writes `#<page name>` and every page carries a `draw:name`. A slide
with no name of its own is named after its position, as `Slide N` -- not as
`pageN`, the form LibreOffice generates for its own exported pages and refuses to
resolve a link to.

Neither Reader recognised such a link either, so the slide number never survived a
round trip. The PowerPoint2007 Reader returned the raw part name, `slide2.xml`,
and the ODPresentation Reader the raw `#Name`. Both now resolve the target back to
its number.
@dkulyk
dkulyk force-pushed the fix/odp-slide-link branch from bbcd87b to 514a008 Compare August 23, 2026 19:21
@Progi1984 Progi1984 added this to the 1.3.0 milestone Aug 23, 2026
@Progi1984
Progi1984 merged commit d08b0f1 into PHPOffice:master Aug 23, 2026
26 checks passed
@dkulyk
dkulyk deleted the fix/odp-slide-link branch August 23, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants