PerlDoc

See PublishedAPI for packages intended to be used by Plugin and Contrib authors, or browse all packages.
See also Developing plugins, Developer's Bible, Technical Overview


Parent package: Foswiki
Child packages:

    internal package Foswiki::Address

    This class is used to handle pointers to Foswiki 'resources', which might be webs, topics or parts of topics (such as attachments or metadata), optionally of a specific revision.

    The primary goal is to end the tyranny of arbitrary (web, topic, attachment, rev...) tuples. Users of Foswiki::Address should be able to enjoy programmatically updating, stringifying, parsing, validating, comparing and passing around of address objects that might eventually be understood by the wider Foswiki universe, without having to maintain proprietary parse/stringify/validate/comparison handling code that must always be considerate of the recipient for such tuples.

    This class does not offer any interaction with resources themselves; rather, functionality is provided to create, hold, manipulate, test and de/serialise addresses

    Fundamentally, Foswiki::Address can be thought of as an interface to a hash of the components necessary to address a specific Foswiki resource.

    my $addr = {
        web        => 'Web/SubWeb',
        topic      => 'Topic',
        attachment => 'Attachment.pdf',
        rev => 3
    };
    

    ALERT! Unresolved issues
    • Is this class necessary, or should we make a cleaner, lighter Foswiki::Meta2 - where 'unloaded' objects are no heavier than Foswiki::Address and provide the same functionality?
    • Should the physical file attachment be treated separately to the metadata view of the file attachment(s)? Desirables:
      • ability to unambiguously create pointers to an attachment's data (file)
      • ability for Foswiki core to calculate an http URL for it
      • ability to create pointers to properties (metadata) of the attachment
        • These questions are slightly loaded in favour of distinguishing between the datastream and metadata about the attachment. In an ideal world a file attachment would be a first-class citizen to topics: rather than topic text, we have the iostream; attachments would have their own user metadata, dataforms...
    • Duplicating QuerySearch parser functionality. 80% of the code in this class is related to parsing "string forms" of addresses of Foswiki resources... querysearch parser needs some refactoring so we can delete the parser code here.
    • API usability - can we stop passing around (web, topic, attachment, rev) tuples - will the ->new() constructor make sense to plugin authors, core hackers? FEEDBACK WELCOME, please comment at Foswiki:Development.TopicAddressing

    ClassMethod new( %constructor ) → $addrObj

    Create a Foswiki::Address instance

    The constructor takes two main forms:

    Explicit form

    Example:
    my $addrObj = Foswiki::Address->new(
        web        => 'Web/SubWeb',
        topic      => 'Topic',
        attachment => 'Attachment.pdf',
        rev => 3
    );

    Options:
    Param Description Notes
    web $string of web path,
    used if webpath is empty/null
     
    webpath \@arrayref of web path, root web first  
    topic $string topic name  
    rev $integer revision number. If the tompath is to a attachment datastream, rev applies to that file; topic rev otherwise
    tompath \@arrayref of a "TOM" path, one of:
    META, text, SECTION, attachment.
    See table below
    string string representation of an object eg. 'Web/SubWeb.Topic/Attachment.pdf@3'

    path forms:
    tompath Description
    ['attachments'] All datastreams attached to a topic
    ['attachment', 'Attachment.pdf'] Datastream of the file attachment named 'Attachment.pdf'
    ['META'] All META on a topic
    ['META', 'FIELD'] All META:FIELD members on a topic
    ['META', 'FIELD', { name => 'Colour' }] The META:FIELD member whose name='Colour'
    ['META', 'FIELD', 3] The fourth META:FIELD member
    ['META', 'FIELD', { name => 'Colour' }, 'title'] The 'title' attribute on the META:FIELD member whose name='Colour'
    ['META', 'FIELD', 3, 'title'] The 'title' attribute on the fourth META:FIELD member
    ['text'] The topic text
    ['SECTION'] All topic sections as defined by VarSTARTSECTION
    ['SECTION', {name => 'foo'}] The topic section named 'foo'
    ['SECTION', {name => 'foo', type => 'include'}] The topic section named 'foo' of type='include'

    Example: Point to the value of a formfield LastName in Web/SubWeb.Topic,
    my $addrObj = Foswiki::Address->new(
      web     => 'Web/SubWeb',
      topic   => 'Topic',
      tompath => ['META', 'FIELD', {name => LastName}, 'value']
    );

    Equivalent:
    %QUERY{"'Web/SubWeb.Topic'/META:FIELD[name='LastName'].value"}%
    or
    %QUERY{"'Web/SubWeb.Topic'/LastName"}%
    

    String form

    Example:
    my $addrObj = Foswiki::Address->new(
        string => 'Web/SubWeb.Topic/Attachment.pdf@3',
        %opts
    );

    ALERT! String form instantiation requires parsing of the address string which comes with many options and caveats - refer to the documentation for parse().

    ClassMethod finish( )

    Clean up the object, releasing any memory stored in it.

    PRIVATE ClassMethod _parse( $string, \%opts ) → $success

    Parse the given string using options provided and update the instance with the resulting address.

    Examples of valid path strings include:

    • Web/
    • Web/SubWeb/
    • Web/SubWeb.Topic or Web/SubWeb/Topic or Web.SubWeb.Topic
    • Web/SubWeb.Topic@2 or Web/SubWeb/Topic@2 or Web.SubWeb.Topic@2
    • Web/SubWeb.Topic/Attachment.pdf or Web/SubWeb/Topic/Attachment.pdf or Web.SubWeb.Topic/Attachment.pdf
    • Web/SubWeb.Topic/Attachment.pdf@3 or Web/SubWeb/Topic/Attachment.pdf@3 or Web.SubWeb.Topic/Attachment.pdf@3

    "String" addresses are notoriously ambiguous: Foswiki traditionally allows web & topic separators '.' & '/' to be used interchangably. For example, the following strings could be topics or attachments (or even webs):
    • Foo.Bar
    • Foo.Bar.Cat.Dog
    • Foo/Bar
    • Foo/Bar/Cat/Dog

    To resolve the ambiguity, components of ambiguous strings are tested for existence as webs, topics or attachments and used as hints to help resolve them, so it follows that:
    ALERT! Ambiguous address strings cannot be considered stable; exactly which resource they resolve to depends on the hinting algorithm, the parameters and hints supplied to it, and the existence (or non-existence) of other resources

    Options:
    Param Description Values Notes
    webpath or web
    topic
    context hints refer to explicit form if string is ambiguous (and possibly not fully qualified, Eg. topic-only or attachment-only), the hinting algorithm tests string against them
    isA resource type specification $type - 'web', 'topic', 'attachment' parse string to resolve to the specified type; exist hinting is skipped
    catchAs default resource type $type - 'web', 'topic', 'attachment', 'none' if string is ambiguous AND (exist hinting fails OR is disabled), THEN assume string to be (web, topic, file attachment or unparseable)
    existAs resource types to test \@typelist containing one or more of 'web', 'topic', 'attachment' if string is ambiguous, test (in order) as each of the specified types. Default: [qw(attachment topic)]
    existHints exist hinting enable/disable $boolean enable/disable hinting through web/topic/attachment existence checks. string is assumed to be using the 'unambiguous' conventions below; if it isn't, catchAs is used

    Unambiguous strings

    To build less ambiguous address strings, use the following conventions:
    • Terminate web addresses with '/'
    • Separate subwebs in the web path with '/'
    • Separate topic from web path with '.'
    • Separate file attachments from topics with '/'
    Examples:
    • Web/SubWeb/, Web/
    • Web/SubWeb.Topic
    • Web.Topic/Attachment.pdf
    • Web/SubWeb.Topic/Attachment.pdf

    Many strings commonly used in Foswiki will always be ambiguous (such as Foo, Foo/Bar, Foo/Bar/Cat, Foo.Bar.Cat). Supplying an isA specification will prevent the parser from using the (somewhat expensive) exist hinting heuristics.

    IDEA! In order to simplify the algorithm, a string may only parse out as a web if:
    • It is of the form Foo/, or
    • isA => 'web' is specified, or
    • No other type is possible, and catchAs => 'web' is specified

    The exist hinting algorithm is skipped if:
    • isA specified
    • string not ambiguous

    If string is ambiguous, the hinting algorithm works roughly as follows:
    • if exist hinting is disabled
      • and catchAs is specified (parse as the catchAs type), otherwise
      • the string cannot be parsed
    • if exist hinting is enabled, the string is checked for existence as each of the existAs types (default is 'attachment', 'topic')
      • if there is an exact match against one of the existAs types (finish), otherwise
      • if there were partial matches (select the combination which scores highest), otherwise
      • if catchAs was specified (parse as that type), otherwise
      • the string cannot be parsed
    The following table attempts to explain how ambiguous forms can be interpreted and resolved.
    String form existHints ambiguous web[s] topic possible types
    Foo/         web
    Foo   ALERT!     web
    needs isA => 'web' or catchAs => 'web',
    error otherwise
    Foo     set   topic
    Foo   1 set set topic, attachment
    Foo/Bar/         web
    Foo/Bar         topic
    Foo/Bar   1 set   topic, attachment
    Foo.Bar         topic
    Foo.Bar   1 set set topic, attachment
    Foo/Bar/Dog/         web
    Foo/Bar/Dog   1     topic, attachment
    Foo.Bar/Dog 0       attachment
    Foo.Bar/Dog   1     topic, attachment
    Foo.Bar/D.g         attachment
    Foo/Bar.Dog         topic
    Foo/Bar.Dog   1 set   topic, attachment
    Foo.Bar.Dog         topic
    Foo.Bar.Dog   1 set set topic, attachment
    Foo/Bar/Dog/Cat/         web
    Foo/Bar.Dog.Cat         topic
    Foo/Bar.Dog.Cat   1 set   topic, attachment
    Foo/Bar.Dog/Cat         attachment
    Foo/Bar.Dog/C.t         attachment
    Foo/Bar/Dog.Cat 0       topic
    Foo/Bar/Dog.Cat   1     topic, attachment
    Foo/Bar/Dog/Cat   1     topic, attachment
    Foo/Bar/Dog/C.t   1     topic, attachment
    Foo.Bar.Dog/Cat 0       attachment
    Foo.Bar.Dog/Cat   1     topic, attachment
    Foo.Bar.Dog/C.t         attachment

    PRIVATE ClassMethod _atomiseAsTOM ( $that, $path, $opts ) → $that

    Parse a small subset ('static' meta path forms) of QuerySearch (VarQUERY) compatible expressions.

    $opts is a hashref holding default context

    'topic'/ ref part is optional; _atomiseAsTOM() falls-back to default topic context supplied in $opts otherwise. In other words, both of these forms are supported:
    • 'Web/SubWeb.Topic@3'/META:FIELD[name='Colour'].value
    • META:FIELD[name='Colour'].value

    Form tompath type
    META ['META'] meta
    META:FIELD ['META', 'FIELD'] metatype
    META:FIELD[name='Colour'] ['META', 'FIELD', {name => 'Colour'}] metamember
    META:FIELD[3] ['META', 'FIELD', 3] metamember
    META:FIELD[name='Colour'].value ['META', 'FIELD', {name => 'Colour'}, 'value'] metakey
    META:FIELD[3].value ['META', 'FIELD', 3, 'value'] metakey
    fields ['META', 'FIELD'] metatype
    fields[name='Colour'] ['META', 'FIELD', {name => 'Colour'}] metamember
    fields[3] ['META', 'FIELD', 3] metamember
    fields[name='Colour'].value ['META', 'FIELD', 3, 'value'] metakey
    MyForm ['META', 'FIELD', {form => 'MyForm'}] metatype
    MyForm[name='Colour'] ['META', 'FIELD', {form => 'MyForm', name => 'Colour'}] metamember
    MyForm[name='Colour'].value ['META', 'FIELD', {form => 'MyForm', name => 'Colour'}, 'value'] metakey
    MyForm.Colour ['META', 'FIELD', {form => 'MyForm', name => 'Colour'}, 'value'] metakey
    Colour ['META', 'FIELD', {name => 'Colour'}, 'value'] metakey

    ClassMethod stringify => $string

    Return a string representation of the address.

    The output of stringify() is understood by _parse(), and vice versa.

    EXPERIMENTAL ClassMethod root( [$boolean] ) → $boolean

    • $boolean - optional, set the hypothetical Foswiki 'root'. Since all Foswiki resources must exist under the root, a false value here basically means the address object is an undefined/invalid state.

    Get/set root

    ALERT! This method (and the root attribute generally) may be removed before we release Foswiki 2.0. We would rather use web => '/'

    ClassMethod web( [$name] ) → $name

    • $name - optional, set a new web name

    Get/set by web string

    ClassMethod webpath( [\@webpath] ) → \@webpath

    • \@webpath - optional, set a new webpath arrayref

    Get/set the webpath arrayref

    ClassMethod topic( [$name] ) → $name

    • $name - optional, set a new topic name

    Get/set the topic name

    ClassMethod attachment( [$file] ) → $file

    • $file - optional, set a new file attachment name

    Get/set the file attachment name

    ClassMethod rev( [$rev] ) → $rev

    • $rev - optional, set rev number

    Get/set the rev

    ClassMethod tompath( [\@tompath] ) → \@tompath

    • \@tompath - optional, tompath specification into the containing topic. The first $tompath->[0] element in the array should be one of the following
      • 'attachment': $tompath->[1] should be a string, Eg. 'Attachment.pdf'.
      • 'META': $tompath->[1..3] identify which META:<type> or member or member key is being addressed:
        • $tompath->[1] contains the META:<type>, Eg. 'FIELD'
        • $tompath->[2] contains a selector to identify a member of the type:
          • undef, for singleton types (such as 'TOPICINFO')
          • integer array index
          • hashref key => 'value' pairs, Eg. {name => 'Colour'}. {name => 'Colour', form => 'MyForm'} is also supported.
        • $tompath->[3] contains the name of a key on the selected member, Eg. 'value'
      • 'SECTION': $tompath->[1] should be a hashref, Eg. {name => 'mysection', type => 'include'}
      • 'text': addresses the topic text

    Get/set the tompath into a topic

    ClassMethod type() → $resourcetype

    Returns the resource type name.

    ClassMethod isA([$resourcetype]) → $boolean

    Returns true if the address points to a resource of the specified type.

    ClassMethod isValid() → $resourcetype

    Returns true if the instance addresses a resource which is one of the following types:
    • webpath, Eg. Web/SubWeb/
    • topic, Eg. Web/SubWeb.Topic
    • attachment, Eg. Web/SubWeb.Topic/Attachment.pdf
    • attachments , Eg. 'Web/SubWeb.Topic/attachment'
    • meta, Eg. 'Web/SubWeb.Topic'/META
    • metatype, Eg. 'Web/SubWeb.Topic'/META:FIELD
    • metamember, Eg. 'Web/SubWeb.Topic'/META:FIELD[name='Colour'] or 'Web/SubWeb.Topic'/META:FIELD[0]
    • metakey, Eg. 'Web/SubWeb.Topic'/META:FIELD[name='Colour'].value or 'Web/SubWeb.Topic'/META:FIELD[0].value
    • section, Eg. 'Web/SubWeb.Topic'/SECTION[name='something']
    • sections, Eg. 'Web/SubWeb.Topic'/SECTION
    • text, Eg. 'Web/SubWeb.Topic'/text

    ClassMethod equiv ( $otherAddr ) → $boolean

    Return true if this address resolves to the same resource as $otherAddr

    Topic revision: r1 - 2022/06/24, ProjectContributor
    This site is powered by FoswikiCopyright © by the contributing authors. All material on this site is the property of the contributing authors.
    Ideas, requests, problems regarding Foswiki? Send feedback