<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=ObjectModel</id>
	<title>ObjectModel - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=ObjectModel"/>
	<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;action=history"/>
	<updated>2026-08-23T15:57:45Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=26516&amp;oldid=prev</id>
		<title>Barton: /* Singular vs plural file names */</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=26516&amp;oldid=prev"/>
		<updated>2017-09-03T21:26:44Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Singular vs plural file names&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 17:26, 3 September 2017&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l70&quot;&gt;Line 70:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 70:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Attachment.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Attachment.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Attachments.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Attachments.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;}&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;- valign=&quot;top&quot;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[CachedGroupMember]].pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[CachedGroupMember]].pm | [[CachedGroupMembers]].pm | | [[CustomField]].pm | [[CustomFields]].pm | | [[CustomFieldValue]].pm | [[CustomFieldValues]].pm | | [[GroupMember]].pm | [[GroupMembers]].pm &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;|&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[CachedGroupMembers]].pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;- valign=&quot;top&quot;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;{| border=&quot;1&quot;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[CustomField]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[CustomFields]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;- valign=&quot;top&quot;  &lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[CustomFieldValue]].pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[CustomFieldValues]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;- valign=&quot;top&quot;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[GroupMember]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[GroupMembers]].pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|- valign=&amp;quot;top&amp;quot;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|- valign=&amp;quot;top&amp;quot;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Group.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Group.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l87&quot;&gt;Line 87:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 94:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Queue.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Queue.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Queues.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Queues.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;}&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;- valign=&quot;top&quot;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[ScripAction]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[ScripAction]].pm | [[ScripActions]].pm | | [[ScripCondition]].pm | [[ScripConditions]].pm &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;|&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[ScripActions]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;- valign=&quot;top&quot;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;{| border=&quot;1&quot;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[ScripCondition]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[ScripConditions]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|- valign=&amp;quot;top&amp;quot;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|- valign=&amp;quot;top&amp;quot;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Scrip.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Scrip.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l98&quot;&gt;Line 98:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 106:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Template.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Template.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Templates.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Templates.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;}&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;- valign=&quot;top&quot;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[TicketCustomFieldValue]].pm  &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[TicketCustomFieldValue]].pm | [[TicketCustomFieldValues]].pm &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;|&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| [[TicketCustomFieldValues]].pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;{| border=&quot;1&quot;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|- valign=&amp;quot;top&amp;quot;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;|- valign=&amp;quot;top&amp;quot;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Ticket.pm&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;| Ticket.pm&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key bestpractical_mediawiki1459887241:diff:1.41:old-2357:rev-26516:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Barton</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=2357&amp;oldid=prev</id>
		<title>Admin: 3 revisions imported</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=2357&amp;oldid=prev"/>
		<updated>2016-04-06T20:15:48Z</updated>

		<summary type="html">&lt;p&gt;3 revisions imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 16:15, 6 April 2016&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key bestpractical_mediawiki1459887241:diff:1.41:old-2356:rev-2357 --&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=2356&amp;oldid=prev</id>
		<title>184.171.226.2: grammar correction</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=2356&amp;oldid=prev"/>
		<updated>2012-04-20T23:18:47Z</updated>

		<summary type="html">&lt;p&gt;grammar correction&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;NOTE:&amp;#039;&amp;#039;&amp;#039; This document expects that you&amp;#039;re using default installation directory of /opt/rt3. Relative paths are all against /opt/rt3.&lt;br /&gt;
&lt;br /&gt;
= Files in library =&lt;br /&gt;
&lt;br /&gt;
== Base files ==&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;gt; ls lib/RT/ | grep &amp;#039;^Queue&amp;#039;&lt;br /&gt;
 Queue_Overlay.pm&lt;br /&gt;
 Queue.pm&lt;br /&gt;
 Queues_Overlay.pm&lt;br /&gt;
 Queues.pm&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Queue.pm&amp;lt;/code&amp;gt; is the base file for the RT::Queue package. You can list all RT packages and their base files with command:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;gt; find lib/RT -name &amp;#039;*.pm&amp;#039; | \&lt;br /&gt;
     perl -ne &amp;#039;print $_ unless /Overlay|Local|Vendor/&amp;#039; | \&lt;br /&gt;
     xargs grep &amp;#039;^package &amp;#039;&lt;br /&gt;
 &lt;br /&gt;
 lib/RT/ACE.pm:package RT::ACE;&lt;br /&gt;
 lib/RT/ACL.pm:package RT::ACL;&lt;br /&gt;
 lib/RT/Action/AutoOpen.pm:package RT::Action::AutoOpen;&lt;br /&gt;
 lib/RT/Action/Autoreply.pm:package RT::Action::Autoreply;&lt;br /&gt;
 lib/RT/Action/CreateTickets.pm:package RT::Action::CreateTickets;&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
As you can see almost all files that have no &amp;#039;_&amp;#039; character in the file name define a package.&lt;br /&gt;
&lt;br /&gt;
== Overlay, Local and Vendor files ==&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;gt; cat Queue.pm&lt;br /&gt;
 ...&lt;br /&gt;
        eval &amp;quot;require RT::Queue_Overlay&amp;quot;;&lt;br /&gt;
        if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Queue_Overlay.pm}) {&lt;br /&gt;
            die $@;&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
This code tries load the file lib/RT/[[Queue Overlay|Queue_Overlay]].pm. If the file doesn&amp;#039;t exist then RT will silently ignore it. On other errors RT will throw an exception. lib/RT/[[Queue Overlay|Queue_Overlay]].pm has no package definition so all code in it loads into RT::Queue package(name-space)&lt;br /&gt;
&lt;br /&gt;
If Queue_Overlay.pm defines a subroutine already present in Queue.pm Perl will override the original subroutine from Queue.pm with subroutine in Queue_Overlay.pm. Almost all base files (packages) load overrides from _Overlay.pm, _Vendor.pm and _Local.pm files. RT loads files in predefined order: the _Local.pm file is last and its subroutines have highest priority.&lt;br /&gt;
&lt;br /&gt;
RT uses this technique because RT many base files (Queue.pm, Ticket.pm, etc) are generated automatically from information about data base. From the file&amp;#039;s heading:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# Autogenerated by DBIx::SearchBuilder factory (by &amp;amp;lt;jesse@bestpractical.com&amp;amp;gt;)&lt;br /&gt;
  # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.&lt;br /&gt;
  #&lt;br /&gt;
  # !! DO NOT EDIT THIS FILE !!&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also: [[CleanlyCustomizeRT]]&lt;br /&gt;
&lt;br /&gt;
== So many overlaying files where to look? ==&lt;br /&gt;
&lt;br /&gt;
Again, on example. There is a Queues table in the DB, so Queue.pm is autogenerated from table schema and RT developers use [[Queue Overlay|Queue_Overlay]].pm. [[Queue Vendor|Queue_Vendor]].pm is for distributors packaging RT with extensions and fixes. [[Queue Local|Queue_Local]].pm is for end-administrators for customization. If you want to know more about Queue class and its methods then you look at Queue.pm for basic list of methods to access data fields and then at [[Queue Overlay|Queue_Overlay]].pm to get more advanced methods.&lt;br /&gt;
&lt;br /&gt;
== Singular vs plural file names ==&lt;br /&gt;
&lt;br /&gt;
Table in DB is a &amp;lt;u&amp;gt;collection&amp;lt;/u&amp;gt; of the &amp;lt;u&amp;gt;records&amp;lt;/u&amp;gt;. RT has tickets(collection). When you search tickets you limit collection with some conditions, each item in the collection is a ticket(record). So each table is represented with two classes. One represent a record in the table, second represent the table like collection of records.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Records&lt;br /&gt;
| Collections(tables)&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| ACE.pm&lt;br /&gt;
| ACL.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Attachment.pm&lt;br /&gt;
| Attachments.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
| [[CachedGroupMember]].pm | [[CachedGroupMembers]].pm | | [[CustomField]].pm | [[CustomFields]].pm | | [[CustomFieldValue]].pm | [[CustomFieldValues]].pm | | [[GroupMember]].pm | [[GroupMembers]].pm |&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Group.pm&lt;br /&gt;
| Groups.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Link.pm&lt;br /&gt;
| Links.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Principal.pm&lt;br /&gt;
| Principals.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Queue.pm&lt;br /&gt;
| Queues.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
| [[ScripAction]].pm | [[ScripActions]].pm | | [[ScripCondition]].pm | [[ScripConditions]].pm |&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Scrip.pm&lt;br /&gt;
| Scrips.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Template.pm&lt;br /&gt;
| Templates.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
| [[TicketCustomFieldValue]].pm | [[TicketCustomFieldValues]].pm |&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Ticket.pm&lt;br /&gt;
| Tickets.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Transaction.pm&lt;br /&gt;
| Transactions.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| User.pm&lt;br /&gt;
| Users.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Classes listed in the left column are inherited from &amp;lt;code&amp;gt;RT::Record&amp;lt;/code&amp;gt; class. The right column represents classes inherited from [=RT::[[SearchBuilder]]] class. Both(Record and SearchBuilder) are major classes that provide a platform (based on [=[[DBIx]]::[[SearchBuilder]]] framework) to manipulate RT&amp;#039;s DB.&lt;br /&gt;
&lt;br /&gt;
See below about records and collections.&lt;br /&gt;
&lt;br /&gt;
== How local folder works ==&lt;br /&gt;
&lt;br /&gt;
In RT files hierarchy there is &amp;lt;code&amp;gt;local&amp;lt;/code&amp;gt; folder that has special meaning, see [[CleanlyCustomizeRT]] for details.&lt;br /&gt;
&lt;br /&gt;
= API =&lt;br /&gt;
&lt;br /&gt;
== RT::Base ==&lt;br /&gt;
&lt;br /&gt;
Base class for all RT classes. Implements minor functionality that is general for all classes. Provides several methods, description below.&lt;br /&gt;
&lt;br /&gt;
 perldoc lib/RT/Base.pm&lt;br /&gt;
&lt;br /&gt;
=== CurrentUser ===&lt;br /&gt;
&lt;br /&gt;
When you construct RT objects from classes then you should define user context. Example: [=my $ticket = RT::Ticket-&amp;amp;gt;new( $RT::[[SystemUser]] );] with this code you create an object of RT::Ticket class in context of SystemUser(see below about SystemUser). You can do everything with the ticket now, but if you create a ticket object in context of user &amp;#039;John&amp;#039; then some operations may fail because of right restrictions.&lt;br /&gt;
&lt;br /&gt;
This sub also allows you to change user context. For example, if you get a ticket object from external code and want to execute code that shouldn&amp;#039;t fail even if the user doesn&amp;#039;t have some rights, then you can switch to SystemUser do what you need and then switch back. Code example:&lt;br /&gt;
&lt;br /&gt;
 my $old_user = $ticket-&amp;amp;gt;CurrentUser;&lt;br /&gt;
 $ticket-&amp;amp;gt;CurrentUser( $RT::SystemUser );&lt;br /&gt;
 ...&lt;br /&gt;
 $ticket-&amp;amp;gt;CurrentUser( $old_user );&lt;br /&gt;
&lt;br /&gt;
* [=$RT::[[SystemUser]]] is described in [[GlobalObjects]] page&lt;br /&gt;
&lt;br /&gt;
If some object method returns other RT object then the returned object is also in the same user context as original object. Example:&lt;br /&gt;
&lt;br /&gt;
 my $queue = $ticket-&amp;amp;gt;QueueObj;&lt;br /&gt;
 my $cur_user = $queue-&amp;amp;gt;CurrentUser; # same user as for $ticket&lt;br /&gt;
&lt;br /&gt;
=== loc ===&lt;br /&gt;
&lt;br /&gt;
i18n stuff, see examples in code, how RT uses it and also see [=perldoc Locale::Maketext].&lt;br /&gt;
&lt;br /&gt;
== RT::Record ==&lt;br /&gt;
&lt;br /&gt;
Base class for records in tables. This class allows you to:&lt;br /&gt;
&lt;br /&gt;
* load a record that already exists by one column value or by several column values;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;use RT::Ticket;&lt;br /&gt;
  my $TicketObj = new RT::Ticket( $RT::SystemUser );&lt;br /&gt;
  # loads ticket with id = 1&lt;br /&gt;
  $TicketObj-&amp;amp;gt;Load( 1 );&lt;br /&gt;
  &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* create new record;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;use RT::Ticket;&lt;br /&gt;
  my $TicketObj = new RT::Ticket( $RT::SystemUser );&lt;br /&gt;
  # creates new ticket&lt;br /&gt;
  $TicketObj-&amp;amp;gt;Create( Queue =&amp;amp;gt; 1, Subject =&amp;amp;gt; &amp;#039; &amp;#039; );&lt;br /&gt;
  &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* after you load or create new record, you can get or set its column values;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$TicketObj-&amp;amp;gt;Load( 1 );&lt;br /&gt;
  # gets current subject&lt;br /&gt;
  my $subject = $TicketObj-&amp;amp;gt;Subject;&lt;br /&gt;
  # adds urgent mark to old subject and updates ticket&lt;br /&gt;
  $TicketObj-&amp;amp;gt;SetSubject(&amp;quot;urgent: $subject&amp;quot;);&lt;br /&gt;
  &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* get other objects that relates to the current.&lt;br /&gt;
&lt;br /&gt;
 my $transactions = $TicketObj-&amp;amp;gt;Transactions;&lt;br /&gt;
&lt;br /&gt;
=== [=Set*], [=_Set] and [=__Set] methods ===&lt;br /&gt;
&lt;br /&gt;
* You call [=[[SetXxxx]]( $Value )] method of the RT object.&lt;br /&gt;
** If perl can&amp;#039;t find method, &amp;lt;code&amp;gt;AUTOLOAD&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
*** &amp;lt;code&amp;gt;AUTOLOAD&amp;lt;/code&amp;gt; splits [=[[SetXxxx]]] into &amp;#039;Set&amp;#039; and &amp;#039;Xxxx&amp;#039;&lt;br /&gt;
*** Check is there accesible field in object? No?! Then RT will die.&lt;br /&gt;
*** Is field mutable or readonly. Return error if readonly.&lt;br /&gt;
*** Create alias: [=[[SetXxxx]]($Value) ~ _Set(Field =&amp;amp;gt; &amp;#039;Xxxx&amp;#039;, Value =&amp;amp;gt; $Value)]&lt;br /&gt;
*** Call alias.&lt;br /&gt;
** Next time RT will find this function because of alias.&lt;br /&gt;
* &amp;lt;code&amp;gt;_Set&amp;lt;/code&amp;gt; actually comes from [=[[SearchBuilder]]], this function is specially intended for inheritance.&lt;br /&gt;
** RT check user rights here and do some magic if needed.&lt;br /&gt;
** If everything is allright &amp;lt;code&amp;gt;_Set&amp;lt;/code&amp;gt; calls &amp;lt;code&amp;gt;__Set&amp;lt;/code&amp;gt; which updates DB. &amp;lt;code&amp;gt;__Set&amp;lt;/code&amp;gt; rare does more magic.&lt;br /&gt;
&lt;br /&gt;
== RT::SearchBuilder ==&lt;br /&gt;
&lt;br /&gt;
Base class for collections of records(tables). This class has several groups of functions that alow you to:&lt;br /&gt;
&lt;br /&gt;
* limit collection from all records in table to several records that match some conditions;&lt;br /&gt;
* walk through this collection and get first, last, next, prev records or by index;&lt;br /&gt;
* change records order by colum values;&lt;br /&gt;
* limit collection with conditions based on other tables via relationships of tables.&lt;br /&gt;
&lt;br /&gt;
== RT API docs ==&lt;br /&gt;
&lt;br /&gt;
Perl supports POD(Plain Old Documentation) embeded into code. RT uses POD to describe methods of the clases. You can view this documentation with &amp;lt;code&amp;gt;perldoc&amp;lt;/code&amp;gt; utility that comes with perl.&lt;br /&gt;
&lt;br /&gt;
 perldoc /www/rt3/lib/RT/CustomField_Overlay.pm&lt;br /&gt;
&lt;br /&gt;
Also you can use [http://search.cpan.org/dist/RT-OnlineDocs RT::OnlineDocs] module.&lt;br /&gt;
&lt;br /&gt;
== RT API Inspector ==&lt;br /&gt;
&lt;br /&gt;
I wrote a small snippet that uses [http://search.cpan.org/~adamk/Class-Inspector-1.13/ Class::Inspector] to show which methods are available to specific RT objects.&lt;br /&gt;
&lt;br /&gt;
http://www.cpan.org/authors/id/A/AH/AHARRISON/scripts/rt-class-map-1.3.pl&lt;/div&gt;</summary>
		<author><name>184.171.226.2</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=2354&amp;oldid=prev</id>
		<title>BillCole at 13:20, 11 November 2010</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=ObjectModel&amp;diff=2354&amp;oldid=prev"/>
		<updated>2010-11-11T13:20:43Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;NOTE:&amp;#039;&amp;#039;&amp;#039; This documents expects that you&amp;#039;re using default installation directory of /opt/rt3. Relative paths are all against /opt/rt3.&lt;br /&gt;
&lt;br /&gt;
= Files in library =&lt;br /&gt;
&lt;br /&gt;
== Base files ==&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;gt; ls lib/RT/ | grep &amp;#039;^Queue&amp;#039;&lt;br /&gt;
 Queue_Overlay.pm&lt;br /&gt;
 Queue.pm&lt;br /&gt;
 Queues_Overlay.pm&lt;br /&gt;
 Queues.pm&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Queue.pm&amp;lt;/code&amp;gt; is the base file for the RT::Queue package. You can list all RT packages and their base files with command:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;gt; find lib/RT -name &amp;#039;*.pm&amp;#039; | \&lt;br /&gt;
     perl -ne &amp;#039;print $_ unless /Overlay|Local|Vendor/&amp;#039; | \&lt;br /&gt;
     xargs grep &amp;#039;^package &amp;#039;&lt;br /&gt;
 &lt;br /&gt;
 lib/RT/ACE.pm:package RT::ACE;&lt;br /&gt;
 lib/RT/ACL.pm:package RT::ACL;&lt;br /&gt;
 lib/RT/Action/AutoOpen.pm:package RT::Action::AutoOpen;&lt;br /&gt;
 lib/RT/Action/Autoreply.pm:package RT::Action::Autoreply;&lt;br /&gt;
 lib/RT/Action/CreateTickets.pm:package RT::Action::CreateTickets;&lt;br /&gt;
 ...&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
As you can see almost all files that have no &amp;#039;_&amp;#039; character in the file name define a package.&lt;br /&gt;
&lt;br /&gt;
== Overlay, Local and Vendor files ==&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;gt; cat Queue.pm&lt;br /&gt;
 ...&lt;br /&gt;
        eval &amp;quot;require RT::Queue_Overlay&amp;quot;;&lt;br /&gt;
        if ($@ &amp;amp;amp;&amp;amp;amp; $@ !~ qr{^Can&amp;#039;t locate RT/Queue_Overlay.pm}) {&lt;br /&gt;
            die $@;&lt;br /&gt;
        };&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
This code tries load the file lib/RT/[[Queue Overlay|Queue_Overlay]].pm. If the file doesn&amp;#039;t exist then RT will silently ignore it. On other errors RT will throw an exception. lib/RT/[[Queue Overlay|Queue_Overlay]].pm has no package definition so all code in it loads into RT::Queue package(name-space)&lt;br /&gt;
&lt;br /&gt;
If Queue_Overlay.pm defines a subroutine already present in Queue.pm Perl will override the original subroutine from Queue.pm with subroutine in Queue_Overlay.pm. Almost all base files (packages) load overrides from _Overlay.pm, _Vendor.pm and _Local.pm files. RT loads files in predefined order: the _Local.pm file is last and its subroutines have highest priority.&lt;br /&gt;
&lt;br /&gt;
RT uses this technique because RT many base files (Queue.pm, Ticket.pm, etc) are generated automatically from information about data base. From the file&amp;#039;s heading:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# Autogenerated by DBIx::SearchBuilder factory (by &amp;amp;lt;jesse@bestpractical.com&amp;amp;gt;)&lt;br /&gt;
 # WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.&lt;br /&gt;
 #&lt;br /&gt;
 # !! DO NOT EDIT THIS FILE !!&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also: [[CleanlyCustomizeRT]]&lt;br /&gt;
&lt;br /&gt;
== So many overlaying files where to look? ==&lt;br /&gt;
&lt;br /&gt;
Again, on example. There is a Queues table in the DB, so Queue.pm is autogenerated from table schema and RT developers use [[Queue Overlay|Queue_Overlay]].pm. [[Queue Vendor|Queue_Vendor]].pm is for distributors packaging RT with extensions and fixes. [[Queue Local|Queue_Local]].pm is for end-administrators for customization. If you want to know more about Queue class and its methods then you look at Queue.pm for basic list of methods to access data fields and then at [[Queue Overlay|Queue_Overlay]].pm to get more advanced methods.&lt;br /&gt;
&lt;br /&gt;
== Singular vs plural file names ==&lt;br /&gt;
&lt;br /&gt;
Table in DB is a &amp;lt;u&amp;gt;collection&amp;lt;/u&amp;gt; of the &amp;lt;u&amp;gt;records&amp;lt;/u&amp;gt;. RT has tickets(collection). When you search tickets you limit collection with some conditions, each item in the collection is a ticket(record). So each table is represented with two classes. One represent a record in the table, second represent the table like collection of records.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Records&lt;br /&gt;
| Collections(tables)&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| ACE.pm&lt;br /&gt;
| ACL.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Attachment.pm&lt;br /&gt;
| Attachments.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
| [[CachedGroupMember]].pm | [[CachedGroupMembers]].pm | | [[CustomField]].pm | [[CustomFields]].pm | | [[CustomFieldValue]].pm | [[CustomFieldValues]].pm | | [[GroupMember]].pm | [[GroupMembers]].pm |&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Group.pm&lt;br /&gt;
| Groups.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Link.pm&lt;br /&gt;
| Links.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Principal.pm&lt;br /&gt;
| Principals.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Queue.pm&lt;br /&gt;
| Queues.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
| [[ScripAction]].pm | [[ScripActions]].pm | | [[ScripCondition]].pm | [[ScripConditions]].pm |&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Scrip.pm&lt;br /&gt;
| Scrips.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Template.pm&lt;br /&gt;
| Templates.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
| [[TicketCustomFieldValue]].pm | [[TicketCustomFieldValues]].pm |&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Ticket.pm&lt;br /&gt;
| Tickets.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| Transaction.pm&lt;br /&gt;
| Transactions.pm&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
| User.pm&lt;br /&gt;
| Users.pm&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Classes listed in the left column are inherited from &amp;lt;code&amp;gt;RT::Record&amp;lt;/code&amp;gt; class. The right column represents classes inherited from [=RT::[[SearchBuilder]]] class. Both(Record and SearchBuilder) are major classes that provide a platform (based on [=[[DBIx]]::[[SearchBuilder]]] framework) to manipulate RT&amp;#039;s DB.&lt;br /&gt;
&lt;br /&gt;
See below about records and collections.&lt;br /&gt;
&lt;br /&gt;
== How local folder works ==&lt;br /&gt;
&lt;br /&gt;
In RT files hierarchy there is &amp;lt;code&amp;gt;local&amp;lt;/code&amp;gt; folder that has special meaning, see [[CleanlyCustomizeRT]] for details.&lt;br /&gt;
&lt;br /&gt;
= API =&lt;br /&gt;
&lt;br /&gt;
== RT::Base ==&lt;br /&gt;
&lt;br /&gt;
Base class for all RT classes. Implements minor functionality that is general for all classes. Provides several methods, description below.&lt;br /&gt;
&lt;br /&gt;
 perldoc lib/RT/Base.pm&lt;br /&gt;
&lt;br /&gt;
=== CurrentUser ===&lt;br /&gt;
&lt;br /&gt;
When you construct RT objects from classes then you should define user context. Example: [=my $ticket = RT::Ticket-&amp;amp;gt;new( $RT::[[SystemUser]] );] with this code you create an object of RT::Ticket class in context of SystemUser(see below about SystemUser). You can do everything with the ticket now, but if you create a ticket object in context of user &amp;#039;John&amp;#039; then some operations may fail because of right restrictions.&lt;br /&gt;
&lt;br /&gt;
This sub also allows you to change user context. For example, if you get a ticket object from external code and want to execute code that shouldn&amp;#039;t fail even if the user doesn&amp;#039;t have some rights, then you can switch to SystemUser do what you need and then switch back. Code example:&lt;br /&gt;
&lt;br /&gt;
 my $old_user = $ticket-&amp;amp;gt;CurrentUser;&lt;br /&gt;
 $ticket-&amp;amp;gt;CurrentUser( $RT::SystemUser );&lt;br /&gt;
 ...&lt;br /&gt;
 $ticket-&amp;amp;gt;CurrentUser( $old_user );&lt;br /&gt;
&lt;br /&gt;
* [=$RT::[[SystemUser]]] is described in [[GlobalObjects]] page&lt;br /&gt;
&lt;br /&gt;
If some object method returns other RT object then the returned object is also in the same user context as original object. Example:&lt;br /&gt;
&lt;br /&gt;
 my $queue = $ticket-&amp;amp;gt;QueueObj;&lt;br /&gt;
 my $cur_user = $queue-&amp;amp;gt;CurrentUser; # same user as for $ticket&lt;br /&gt;
&lt;br /&gt;
=== loc ===&lt;br /&gt;
&lt;br /&gt;
i18n stuff, see examples in code, how RT uses it and also see [=perldoc Locale::Maketext].&lt;br /&gt;
&lt;br /&gt;
== RT::Record ==&lt;br /&gt;
&lt;br /&gt;
Base class for records in tables. This class allows you to:&lt;br /&gt;
&lt;br /&gt;
* load a record that already exists by one column value or by several column values;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;use RT::Ticket;&lt;br /&gt;
 my $TicketObj = new RT::Ticket( $RT::SystemUser );&lt;br /&gt;
 # loads ticket with id = 1&lt;br /&gt;
 $TicketObj-&amp;amp;gt;Load( 1 );&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* create new record;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;use RT::Ticket;&lt;br /&gt;
 my $TicketObj = new RT::Ticket( $RT::SystemUser );&lt;br /&gt;
 # creates new ticket&lt;br /&gt;
 $TicketObj-&amp;amp;gt;Create( Queue =&amp;amp;gt; 1, Subject =&amp;amp;gt; &amp;#039; &amp;#039; );&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* after you load or create new record, you can get or set its column values;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;$TicketObj-&amp;amp;gt;Load( 1 );&lt;br /&gt;
 # gets current subject&lt;br /&gt;
 my $subject = $TicketObj-&amp;amp;gt;Subject;&lt;br /&gt;
 # adds urgent mark to old subject and updates ticket&lt;br /&gt;
 $TicketObj-&amp;amp;gt;SetSubject(&amp;quot;urgent: $subject&amp;quot;);&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* get other objects that relates to the current.&lt;br /&gt;
&lt;br /&gt;
 my $transactions = $TicketObj-&amp;amp;gt;Transactions;&lt;br /&gt;
&lt;br /&gt;
=== [=Set*], [=_Set] and [=__Set] methods ===&lt;br /&gt;
&lt;br /&gt;
* You call [=[[SetXxxx]]( $Value )] method of the RT object.&lt;br /&gt;
** If perl can&amp;#039;t find method, &amp;lt;code&amp;gt;AUTOLOAD&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
*** &amp;lt;code&amp;gt;AUTOLOAD&amp;lt;/code&amp;gt; splits [=[[SetXxxx]]] into &amp;#039;Set&amp;#039; and &amp;#039;Xxxx&amp;#039;&lt;br /&gt;
*** Check is there accesible field in object? No?! Then RT will die.&lt;br /&gt;
*** Is field mutable or readonly. Return error if readonly.&lt;br /&gt;
*** Create alias: [=[[SetXxxx]]($Value) ~ _Set(Field =&amp;amp;gt; &amp;#039;Xxxx&amp;#039;, Value =&amp;amp;gt; $Value)]&lt;br /&gt;
*** Call alias.&lt;br /&gt;
** Next time RT will find this function because of alias.&lt;br /&gt;
* &amp;lt;code&amp;gt;_Set&amp;lt;/code&amp;gt; actually comes from [=[[SearchBuilder]]], this function is specially intended for inheritance.&lt;br /&gt;
** RT check user rights here and do some magic if needed.&lt;br /&gt;
** If everything is allright &amp;lt;code&amp;gt;_Set&amp;lt;/code&amp;gt; calls &amp;lt;code&amp;gt;__Set&amp;lt;/code&amp;gt; which updates DB. &amp;lt;code&amp;gt;__Set&amp;lt;/code&amp;gt; rare does more magic.&lt;br /&gt;
&lt;br /&gt;
== RT::SearchBuilder ==&lt;br /&gt;
&lt;br /&gt;
Base class for collections of records(tables). This class has several groups of functions that alow you to:&lt;br /&gt;
&lt;br /&gt;
* limit collection from all records in table to several records that match some conditions;&lt;br /&gt;
* walk through this collection and get first, last, next, prev records or by index;&lt;br /&gt;
* change records order by colum values;&lt;br /&gt;
* limit collection with conditions based on other tables via relationships of tables.&lt;br /&gt;
&lt;br /&gt;
== RT API docs ==&lt;br /&gt;
&lt;br /&gt;
Perl supports POD(Plain Old Documentation) embeded into code. RT uses POD to describe methods of the clases. You can view this documentation with &amp;lt;code&amp;gt;perldoc&amp;lt;/code&amp;gt; utility that comes with perl.&lt;br /&gt;
&lt;br /&gt;
 perldoc /www/rt3/lib/RT/CustomField_Overlay.pm&lt;br /&gt;
&lt;br /&gt;
Also you can use [http://search.cpan.org/dist/RT-OnlineDocs RT::OnlineDocs] module.&lt;br /&gt;
&lt;br /&gt;
== RT API Inspector ==&lt;br /&gt;
&lt;br /&gt;
I wrote a small snippet that uses [http://search.cpan.org/~adamk/Class-Inspector-1.13/ Class::Inspector] to show which methods are available to specific RT objects.&lt;br /&gt;
&lt;br /&gt;
http://www.cpan.org/authors/id/A/AH/AHARRISON/scripts/rt-class-map-1.3.pl&lt;/div&gt;</summary>
		<author><name>BillCole</name></author>
	</entry>
</feed>