view release on metacpan or search on metacpan
MANIFEST.SKIP view on Meta::CPAN
\bMakeMaker-\d
# Avoid Module::Build generated and utility files.
\b_build
\bBuild$
\bBuild.bat$
# Avoid Devel::Cover generated files
\bcover_db
# Avoid temp and backup files.
~$
\#$
\.#
\.bak$
\.old$
\.rej$
\.tmp$
# Avoid OS-specific files/dirs
# Mac OSX metadata
docs/html/cms.help.html view on Meta::CPAN
<tr><td align="center"><a href="#Duplication_of_Data">Duplication of Data</a></td></tr>
<tr><td align="center"><a href="#1%3A_Create_a_new_Site_and_a_new_Design">1: Create a new Site and a new Design</a></td></tr>
<tr><td align="center"><a href="#2%3A_Build_the_Site_via_it%27s_menu">2: Build the Site via it's menu</a></td></tr>
<tr><td align="center"><a href="#3%3A_Edit_the_Design%27s_content">3: Edit the Design's content</a></td></tr>
<tr><td align="center"><a href="#4%3A_Generate_the_web_site%27s_pages">4: Generate the web site's pages</a></td></tr>
<tr><td align="center"><a href="#Changing_the_names_of_Sites%2FDesigns%2FPages">Changing the names of Sites/Designs/Pages</a></td></tr>
<tr><td align="center"><a href="#1%3A_Editing_names">1: Editing names</a></td></tr>
<tr><td align="center"><a href="#2%3A_Editing_menus">2: Editing menus</a></td></tr>
<tr><td align="center"><a href="#Deleting_Pages">Deleting Pages</a></td></tr>
<tr><td align="center"><a href="#How_do_I_skin_the_Design%3F">How do I skin the Design?</a></td></tr>
<tr><td align="center"><a href="#How_do_I_backup_my_Designs%3F">How do I backup my Designs?</a></td></tr>
</table>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="How_do_I_use_this_CMS?"
>How do I use this CMS?</a></h1>
<p>CMS means Content Management System.</p>
<p>If you're starting with an empty database,
the program will default to the [New Site] tab.</p>
docs/html/cms.help.html view on Meta::CPAN
name="How_do_I_skin_the_Design?"
>How do I skin the Design?</a></h1>
<p>See <a href="http://developer.yahoo.com/yui/articles/skinning/" class="podlinkurl"
>http://developer.yahoo.com/yui/articles/skinning/</a>.</p>
<p>YUI is the Yahoo User Interface,
the Javascript library I used to write the client-side code for this program.</p>
<h1><a class='u' href='#___top' title='click to go to top of document'
name="How_do_I_backup_my_Designs?"
>How do I backup my Designs?</a></h1>
<p>All designs are stored in a database,
so it's a matter of running the database's standard backup procedure.</p>
<p>That means also that to restore after a mistake,
you need to run the database's recovery program.</p>
<p>Which is a way of saying that this program does not yet have an undo command.</p>
<!-- end doc -->
</body></html>
docs/pod/cms.help.pod view on Meta::CPAN
The 'first page' is the one on the Edit Pages tab which appears at the top of the site map.
=head1 How do I skin the Design?
See L<http://developer.yahoo.com/yui/articles/skinning/>.
YUI is the Yahoo User Interface, the Javascript library I used to write the client-side
code for this program.
=head1 How do I backup my Designs?
All designs are stored in a database, so it's a matter of running the database's standard
backup procedure.
That means also that to restore after a mistake, you need to run the database's
recovery program.
Which is a way of saying that this program does not yet have an undo command.
htdocs/assets/templates/app/office/cms/content.js view on Meta::CPAN
var action = document.update_content_form.action.value;
var url = "<: $form_action :>/content/";
switch (action)
{
case "1":
url = url + "update";
break;
case "2":
url = url + "backup";
break;
case "3":
url = url + "generate";
break;
}
var p = YAHOO.util.Connect.setForm("update_content_form");
if (action == 1)
htdocs/assets/templates/app/office/cms/content.tx view on Meta::CPAN
<td colspan="2"><textarea name="body_text" id="body_text" rows="12" cols="100"><: $body_text :></textarea></td>
</tr>
<tr>
<td></td>
<td><input type="reset" value="Reset" /></td>
<td align="center"><input type="submit" name="submit_<: $context :>_content" id="submit_<: $context :>_content" value="<: $submit_text :>" onClick="document.<: $context :>_content_form.action.value=1" /></td>
</tr>
<tr><td colspan="3"><hr /></td></tr>
<tr>
<td></td>
: if $backup {
<td><input type="submit" name="submit_backup_content" id="submit_backup_content" value="Backup" onClick="document.<: $context :>_content_form.action.value=2" /></td>
: }
: else {
: }
<td align="center" colspan="$colspan"><input type="submit" name="submit_generate_content" id="submit_generate_content" value="Generate" onClick="document.<: $context :>_content_form.action.value=3" /></td>
</tr>
</table>
<input type="hidden" name="action" id="action" value="0" />
<input type="hidden" name="sid" id="sid" value="<: $sid :>" />
</form>
lib/App/Office/CMS.pm view on Meta::CPAN
=item o Does the database server have pre-requisites?
The code is DBI-based, of course.
Also, the code assumes the database server supports $dbh -> last_insert_id(undef, undef, $table_name, undef).
=item o How do I back up the database?
See the config file .htoffice.cms.conf:
backup_command = pg_dump -U cms cms
backup_file = /tmp/pg.cms.backup.dat
When backup_command has a value, the Edit Contents tab gets a [Backup] button, and when this button
is clicked:
=over 4
=item o The command is run
=item o STDOUT and STDERR are captured
=item o If STDERR contains anything, the program exits
=item o Otherwise, STDOUT is written to the output file
=back
So, why are there 2 lines, and not something like 'pg_dump -U cms cms > /tmp/pg.cms.backup.dat'?
Because I use L<Capture::Tiny>, which does not want you to use redirection.
Lastly, the output is written using L<File::Slurper>.
=item o What's this thing called 'context' in the menus and pages tables?
It's the value ("$site_id/$design_id") which ties those 2 tables together, just like a foreign key.
=item o What are these fields menu_orientation_id and os_type_id in the designs table?
lib/App/Office/CMS.pm view on Meta::CPAN
For massive wikiness (as distinct from wickedness :-) I draw your attention to
both L<Silki> and L<http://foswiki.org/Home/WebHome>.
=back
=head1 TODO
=over 4
=item o Adopt Git::Repository for versioned backup
=item o Clean up error handling
For example, when build_error_result is called, rather than build_success_result, the
data sent to Javascript must be handled slightly differently.
This includes HandleError in DBI's connect() attributes.
=item o Make asset handling more sophisticated
lib/App/Office/CMS.pm view on Meta::CPAN
=item o Enhance New Site tab with an Edit Site button
This saves the user the effort of going to the Search tab to find a site or design
=item o When clicking on the site map, the Edit Pages fields are updated, but the Edit Content fields are not
=item o Add an option, perhaps, to escape entities when inputting HTML
=item o Adopt DBIx::Connector
=item o Implement user-initiated backup and restore
=item o Change class hierarchy
This is so View does not have to pass so many parameters to its 'has-a' attributes
=item o Adopt L<CGI::Untaint::html> or L<HTML::Defang>
Considered and rejected: L<HTML::Sanitizer>, L<HTML::Scrubber>.
=item o Test CGI::Untaint as to its handling of <script>...</script>
lib/App/Office/CMS/.htoffice.cms.conf view on Meta::CPAN
host = localhost
[localhost]
# Backup stuff
# ------------
# o Database stuff (below) also refers to database stuff.
# o Session stuff (below) also refers to database stuff.
backup_command = pg_dump -U cms cms
backup_file = /tmp/pg.cms.backup.dat
# CSS stuff
# ---------
# This is a URL.
# My DocumentRoot: /dev/shm/html.
# hence my disk path: /dev/shm/html/assets/css/app/office/cms.
css_url = /assets/css/app/office/cms
# Database stuff
lib/App/Office/CMS/Controller/Content.pm view on Meta::CPAN
use String::Dirify;
use Try::Tiny;
# We don't use Moo because we isa CGI::Application.
our $VERSION = '0.93';
# -----------------------------------------------
sub backup
{
my($self) = @_;
$self -> log(debug => 'backup()');
my($target_div) = 'update_content_message_div';
my($result);
try
{
my($message, $page, $content) = $self -> process_content_form('update');
if (! $message)
{
# Success.
$message = $self -> param('db') -> content -> backup($page, $content);
$result = $self -> build_success_result($page, $message, $target_div);
}
}
catch
{
$result = $self -> build_error_result($_, $target_div);
};
# update_content_message_div is on screen (under the Edit Content tab)
# because we're displaying content.
return JSON::XS -> new -> utf8 -> encode({results => $result});
} # End of backup.
# -----------------------------------------------
sub build_content_hash
{
my($self, $valid) = @_;
$self -> log(debug => 'build_content_hash()');
my($content) =
lib/App/Office/CMS/Controller/Content.pm view on Meta::CPAN
};
} # End of build_success_result.
# -----------------------------------------------
sub cgiapp_init
{
my($self) = @_;
$self -> run_modes([qw/backup generate update/]);
} # End of cgiapp_init.
# -----------------------------------------------
sub display
{
my($self) = @_;
$self -> log(debug => 'display()');
lib/App/Office/CMS/Database/Content.pm view on Meta::CPAN
$self -> log(debug => '-' x 50);
$self -> save_content_record('add', $page, $content);
return "Saved (add) content for page '$$page{name}'";
} # End of add.
# --------------------------------------------------
sub backup
{
my($self, $page, $content) = @_;
my($backup_command) = ${$self -> db -> config}{backup_command};
my($backup_file) = ${$self -> db -> config}{backup_file};
my($stdout) = $self -> capture_or_die($backup_command);
write_text($backup_file, $stdout) || die "Error: Can't write backup file: $!\n";
return $self -> update($page, $content) . " and backed-up";
} # End of backup.
# -----------------------------------------------
sub capture_or_die
{
my($self, @command) = @_;
my($stdout, $stderr) = capture{system(@command)};
$stderr && die "Error: $stderr\n";
lib/App/Office/CMS/View/Content.pm view on Meta::CPAN
} # End of build_head_js.
# -----------------------------------------------
sub build_update_content_html
{
my($self, $site, $design, $page, $asset) = @_;
$self -> log(debug => 'build_update_content_html()');
my($backup_command) = ${$self -> config}{backup_command};
my($content) = $self -> db -> content -> get_content_by_page_id($$page{id});
my($context) = 'update';
my($param) =
{
backup => $backup_command ? 1 : 0, # We only need a Boolean in the template.
body_text => mark_raw($$content{body_text}),
colspan => $backup_command ? 1 : 2, # Make generate button's position look pretty.
context => $context,
design_name => $$design{name},
head_text => mark_raw($$content{head_text}),
page_name => $$page{name},
sid => $self -> session -> id,
site_name => $$site{name},
submit_text => 'Save',
};
return $self -> templater -> render('content.tx', $param);