The links package provides a number of application modules, but it also is specifically intended to provide an application programming interface (API) that can be used by other modules. The API is intended to be relatively stable, and over time additions will be more likely than changes to exisitng functions. Every reasonable effort will be made to maintain as much backward compatibility as possible, though of course some changes are inevitable.
Any modules that rely on the links API should respect the setting of system and user-specific configuration variables that are set by this package, so that modules will behave consistently. These variables control preferences such as whether links display as a title or as a raw URL, opening of new browser windows when links are clicked, and so on.
Modules are, of course, permitted to set their own variables. The string "links_" as a variable prefix should be reserved to modules that are an official part of this package. If your add on module isn't, please pick a different variable prefix.
It is also permitted for an add-on module to offer a setting that overrides what the basic links package has defined. In such cases, it is strongly recommended that the add-on module use the links-package-defined value for that option as its default, and document that fact accordingly.
The database schema for the links package uses only a couple of tables. This section explains those tables field-by-field, though it should be emphasized that it is STRONGLY encouraged for add-on modules to rely on the API calls to access the database (especially for updates) rather than doing SQL directly. The APIs are specifically designed to insulate modules from the details of the schema. The maintainer of this package is open to adding or enhancing APIs if there is missing but needed functionality, in preference to having modules do a lot of direct SQL on these tables.
+-----------------+------------------+----------------------------------------+ | Field | Type | Description | +-----------------+------------------+----------------------------------------+ | lid | int(10) unsigned | Link ID, tracked by the sequence | | | | "links_lid" in table {sequences}. | | url_md5 | char(32) | MD5 hash of the value from the "url" | | | | column | | url | text | URL after normalization. DO NOT put | | | | any un-normalized URLs in this field. | | link_title | varchar(255) | The default title for this link, for | | | | nodes that do not assign their own. | | last_click_time | int(11) unsigned | Drupal-standard timestamp for the last | | | | time someone followed this link. | +-----------------+------------------+----------------------------------------+
+-----------------+------------------+----------------------------------------+ | Field | Type | Description | +-----------------+------------------+----------------------------------------+ | lid | int(10) unsigned | Foreign key to the {links} table | | | | | | nid | int(10) unsigned | Drupal-standard node ID | | | | | | link_title | varchar(255) | Node-specific link title, or NULL to | | | | use the default from {links}. The API | | | | nulls this field if it matches the | | | | default from {links}. | | weight | int(4) | Determines order of links listed with | | | | the node. Lower number "float up". | | clicks | int(10) unsigned | Tallies the number of clicks of this | | | | link from this node. | | module | varchar(60) | A context-limiting value; see below. | +-----------------+------------------+----------------------------------------+
+-----------------------+------------------+----------------------------------+ | Field | Type | Description | +-----------------------+------------------+----------------------------------+ | lid | int(10) unsigned | Foreign key to the {links} table | | check_interval | int(10) unsigned | Seconds between monitor scans | | last_check | int(11) | Timestamp of last scan attempt | | fail_count | int(11) | Number of *consecutive* failures | | alternate_monitor_url | text | Scan this URL instead of the one | | | | in the {links} table. (see below)| | redirect_propose_url | text | Redirect URL found by scanner | | redirect_saved_url | text | Old URL (for undo) after redirect| | | | proposal accepted by site admin | | change_threshold | int(11) | Relative tolerance of delta w/o | | | | declaring the page "modified" | | change_flag | int(1) | Nonzero means modification found | | change_last_data | text | Comparison data from last scan | +-----------------------+------------------+----------------------------------+
As indicated above, it is *imperative* that no URL be put into the {links} table unless it has first been processed by links_normalize_url(), else many things break. The design of the links package presumes that all links in the database are normalized by this particular function. Modules that need things to be otherwise will need their own tables. It is *strongly* recommended to perform database updates using only the API functions rather than SQL.
The title field here is assigned the first time each link is cataloged into the table, but can be changed by someone with appropriate administrative level. The API has a function to assign a reasonable title based on whatever information the application module can give it (up to and including a specific title to assign, or down to making a cleaned-up version of the raw URL if that is all that is available). Nodes that attach this link to themselves can either supply their own title (which is stored in {links_node}) or can accept the default. The first node that catalogs a link gets to establish the default. All of these semantics are handled in the API.
Note that the localization of title to node also allows for translations. It is suggested that the default for any given link URL (that is, the link_title field in {links} should be the title of the web page in the native language of the page itself, but that is not mandated by the API. If, for example, a web page in French is cataloged initially by a French- speaking contributor, he or she would establish the default language of that link. Later on, that node could be translated into English (for example) as a new node, and when that new node attaches the same link, it can choose to retitle the link -- locally only -- in English, or can allow the title to remain French even though the rest of the node is English.
There is potential here for an add-on module that does what editasnew.module does, but with the added twist of copying the {links_node} references and allowing them to be optionally retitled for the new node.
Translation is not the only situation where retitling makes sense. In some cases, the way a link is "called out" within a node is not its canonical title. For example, suppose someone is creating a links directory and adds a link about the history of tweedle glomping, http://example.com/tweedles.html. The title of that page is "Intro to Tweedle Glomping", and so it's added to the database in that way. Later on, one of the site's members may refer to the same URL in a blog post, as "A terrific article about tweedle glomping", and may want it to appear that way in the blog post. The node-local title of the link allows this to happen without requiring that the URL itself be replicated in the database.
This may seem like a fanatical level of link-duplication avoidance, but the scanning process for dead, redirected, and changed links consumes both time and server resources, and it is therefore worthwhile to avoid scanning the same page multiple times.
Clicks of links are counted in the {links_node} table rather than directly in {links} so that administrative tools can tell not only how many times a link is followed, but also from where it was clicked. It is easy enough to use the SQL function SUM() to tally all the clicks for a given link, e.g., "SELECT SUM(clicks) FROM {links_node} WHERE lid=...".
The last_click_time field exists to allow site administrators to easily identify outbound links that are never used, as possible candidates for pruning. It is intended that in the future a comprehensive links management module will intelligently analyze how many clicks each link has, what nodes generated those clicks, and how recently each link has been followed, to help administrators manage large links catalogs rationally.
The module reference in {links_node} is intended to localize link references to the module that creates and manages them. This allows the same node to reference a given link in multiple ways without collisions. For example, you may have a site in which the node type "weblink" (which intrinsically defines a single primary link because that's what the node is all about) can also have optional related links, or may have embedded links within the node body.
Add-on modules are free to use a suffix after their name in the module column, so for example, my_module could use "my_module", "my_module.xyz", "my_module.something_else", and so on. The period is the recommended delimiter between a module's official name and any internal suffix it uses in the {links_node} table.
The links monitoring function is still under development, so this table's schema is subject to change. Conceptually, the plan for links monitoring is that it scans each link at intervals set by the site administrator, either specifically stored with the link or a site-wide default, to find destination pages that:
The {links_monitor} table supports these three functions. Here is the intended semantics of each column:
Many of the API functions accept a paramter $module that limits the context of their actions. This parameter is very important, and is discussed in detail in the MODULE-LOCAL LINK REFERENCES section of the database schema description (see above).
(More to be added)