├── po
├── potfiles.in
└── Makefile
├── locale
├── en_CA
│ └── LC_MESSAGES
│ │ └── site.mo
├── en_GB
│ └── LC_MESSAGES
│ │ └── site.mo
└── en_US
│ └── LC_MESSAGES
│ └── site.mo
├── tests
└── amqp
│ ├── amqp-test.ini
│ ├── amqp-test-server.xml
│ ├── amqp-test-client.php
│ ├── amqp-test-server.php
│ ├── AMQPTestServer.php
│ └── AMQPTestClient.php
├── www
├── styles
│ ├── site-admin-forgot-password-page.css
│ ├── site-account-reset-password-page.css
│ ├── site-search-results-page.css
│ ├── site-account-login-page.css
│ ├── site-contact-page.css
│ ├── site-image-cell-renderer.css
│ ├── site-jw-player-media-display.css
│ └── site-content-slider.css
└── admin
│ ├── images
│ ├── site-comment-status-slider-bg.gif
│ ├── site-comment-status-slider-thumb.gif
│ ├── site-comment-display-actions-arrow.png
│ └── site-comment-display-actions-arrow@2x.png
│ └── styles
│ ├── site-image-upload.css
│ ├── site-account-merge.css
│ └── site-comment-status-slider.css
├── sql
├── mysql
│ ├── views
│ │ ├── EnabledArticleView.sql
│ │ └── AdReferrerByPeriodView.sql
│ └── functions
│ │ ├── convertTZ.sql
│ │ ├── convertToUTC.sql
│ │ ├── getArticleNavBar.sql
│ │ ├── getArticlePathInfo.sql
│ │ ├── getArticlePath.sql
│ │ └── findArticle.sql
├── pgsql
│ ├── tables
│ │ ├── ConfigSetting.sql
│ │ ├── ImageType.sql
│ │ ├── MediaType.sql
│ │ ├── AdReferrer.sql
│ │ ├── Instance.sql
│ │ ├── Image.sql
│ │ ├── AttachmentSet.sql
│ │ ├── AttachmentCdnQueue.sql
│ │ ├── ImageSet.sql
│ │ ├── ArticleInstanceBinding.sql
│ │ ├── Ad.sql
│ │ ├── MediaPlayer.sql
│ │ ├── SiteEmailLog.sql
│ │ ├── AccountLoginHistory.sql
│ │ ├── ApiSignOnToken.sql
│ │ ├── Account.sql
│ │ ├── ApiCredential.sql
│ │ ├── Comment.sql
│ │ ├── MediaEncoding.sql
│ │ ├── ImageCdnQueue.sql
│ │ ├── MediaCdnQueue.sql
│ │ ├── InstanceConfigSetting.sql
│ │ ├── MediaSet.sql
│ │ ├── ContactMessage.sql
│ │ ├── MediaEncodingBinding.sql
│ │ ├── ImageDimensionBinding.sql
│ │ ├── AccountLoginSession.sql
│ │ ├── Attachment.sql
│ │ ├── ImageDimension.sql
│ │ ├── Media.sql
│ │ └── Article.sql
│ ├── views
│ │ ├── ArticleChildCountView.sql
│ │ ├── EnabledArticleView.sql
│ │ ├── VisibleArticleView.sql
│ │ ├── SuspiciousAccountView.sql
│ │ └── AdReferrerByPeriodView.sql
│ └── functions
│ │ ├── convertTZ.sql
│ │ ├── convertToUTC.sql
│ │ ├── getArticlePathInfo.sql
│ │ ├── getArticlePath.sql
│ │ ├── getArticleNavBar.sql
│ │ └── findArticle.sql
├── mssql
│ └── tables
│ │ ├── ImageType.sql
│ │ ├── Instance.sql
│ │ ├── AccountLoginHistory.sql
│ │ ├── Image.sql
│ │ ├── ImageSet.sql
│ │ ├── AccountLoginSession.sql
│ │ ├── ImageDimensionBinding.sql
│ │ ├── Account.sql
│ │ └── ImageDimension.sql
└── fixtures
│ ├── SiteBotrMediaSet.sql
│ ├── SiteImageType.sql
│ ├── SiteMediaType.sql
│ └── SiteBotrMediaEncoding.sql
├── Site
├── exceptions
│ ├── SiteCommentJSONException.php
│ ├── SiteMailException.php
│ ├── SiteCdnException.php
│ ├── SiteAMQPJobException.php
│ ├── SiteCookieException.php
│ ├── SiteInvalidImageException.php
│ ├── SiteCommandLineException.php
│ ├── SiteApiSignOnException.php
│ ├── SiteInvalidMacException.php
│ ├── SitePathTooLongException.php
│ ├── SiteInvalidImageDimensionException.php
│ ├── SiteNotFoundException.php
│ ├── SiteBadRequestException.php
│ ├── SiteException.php
│ ├── SiteNotAuthorizedException.php
│ ├── SitePathInvalidUtf8Exception.php
│ ├── SiteInvalidClassException.php
│ ├── SiteAMQPJobFailureException.php
│ ├── SiteClassNotFoundException.php
│ └── SiteInvalidPropertyException.php
├── SiteObject.php
├── templates
│ ├── SiteBlankTemplate.php
│ ├── SiteFileLoaderTemplate.php
│ ├── SiteSMILTemplate.php
│ ├── SiteVTTTemplate.php
│ ├── SiteAtomTemplate.php
│ ├── SiteJSONTemplate.php
│ ├── SiteTemplateInterface.php
│ ├── SiteAbstractTemplate.php
│ ├── SiteXMLRPCServerTemplate.php
│ ├── SiteXMLSiteMapTemplate.php
│ └── SiteDefaultTemplate.php
├── pages
│ ├── account-sessions.xml
│ ├── search-results.xml
│ ├── search-form.xml
│ ├── SiteConnectionClosePage.php
│ ├── SiteJSONPage.php
│ ├── account-forgot-password.xml
│ ├── account-reset-password.xml
│ ├── SiteMessageDisplayPageDecorator.php
│ ├── SiteXmlSiteMapIndexPage.php
│ ├── SiteDBEditPage.php
│ ├── contact.xml
│ ├── SiteXMLRPCServer.php
│ ├── SiteSearchPage.php
│ ├── SitePage.php
│ ├── SiteXhtmlExceptionPage.php
│ ├── account-login.xml
│ └── account-change-password.xml
├── SitePrivateDataDeleter.php
├── layouts
│ ├── SiteXmlSiteMapLayout.php
│ └── SiteXMLRPCServerLayout.php
├── SiteFulltextSearchEngine.php
├── dataobjects
│ ├── SiteVideoScrubberImage.php
│ ├── SiteInstanceWrapper.php
│ ├── SiteAdWrapper.php
│ ├── SiteAudioMediaWrapper.php
│ ├── SiteImageCdnTaskWrapper.php
│ ├── SiteInstanceConfigSettingWrapper.php
│ ├── SiteAccountWrapper.php
│ ├── SiteCdnTaskWrapper.php
│ ├── SiteImageSetWrapper.php
│ ├── SiteCommentWrapper.php
│ ├── SiteAccountLoginHistoryWrapper.php
│ ├── SiteVideoImage.php
│ ├── SiteAccountLoginSessionWrapper.php
│ ├── SiteApiCredentialWrapper.php
│ ├── SiteAttachmentSetWrapper.php
│ ├── SiteImageDimensionWrapper.php
│ ├── SiteVideoMediaEncodingWrapper.php
│ ├── SiteContactMessageWrapper.php
│ ├── SiteMediaTypeWrapper.php
│ ├── SiteVideoMediaEncodingBinding.php
│ ├── SiteMediaEncodingWrapper.php
│ ├── SiteVideoMediaEncodingBindingWrapper.php
│ ├── SiteVideoMediaSet.php
│ ├── SiteVideoMediaEncoding.php
│ ├── SiteSimpleMediaWrapper.php
│ ├── SiteSimpleVideoMediaWrapper.php
│ ├── SiteImageDimensionBindingWrapper.php
│ ├── SiteVideoMediaSetWrapper.php
│ ├── SiteImageLazyWrapper.php
│ ├── SiteAttachmentWrapper.php
│ ├── SiteAccountLoginHistory.php
│ ├── SiteVideoMediaWrapper.php
│ ├── SiteAdReferrer.php
│ ├── SiteInstanceConfigSetting.php
│ ├── SiteArticleWrapper.php
│ ├── SiteAttachmentCdnTaskWrapper.php
│ ├── SiteMediaEncodingBindingWrapper.php
│ ├── SiteMediaCdnTaskWrapper.php
│ ├── SiteMediaSetWrapper.php
│ ├── SiteImageType.php
│ └── SiteAttachmentSet.php
├── admin
│ ├── SiteCommentVisibilityCellRenderer.php
│ ├── components
│ │ ├── InstanceSetting
│ │ │ ├── include
│ │ │ │ ├── SiteConfigPage.php
│ │ │ │ └── config-page.xml
│ │ │ └── index.xml
│ │ ├── Account
│ │ │ ├── forgot-password.xml
│ │ │ ├── edit.xml
│ │ │ ├── search.xml
│ │ │ ├── details.xml
│ │ │ ├── suspicious.xml
│ │ │ └── index.xml
│ │ ├── Image
│ │ │ ├── delete.xml
│ │ │ └── upload.xml
│ │ ├── Attachment
│ │ │ └── upload.xml
│ │ ├── Media
│ │ │ └── poster-frame.xml
│ │ ├── Ad
│ │ │ ├── edit.xml
│ │ │ ├── Index.php
│ │ │ ├── details.xml
│ │ │ └── Delete.php
│ │ ├── Article
│ │ │ └── include
│ │ │ │ └── SiteArticleVisibilityCellRenderer.php
│ │ └── Comment
│ │ │ ├── index.xml
│ │ │ └── edit.xml
│ └── SiteCommentApprovalPage.php
├── SiteCommentable.php
├── SiteError.php
├── SiteSentryExceptionLogger.php
├── SiteKeywordEntry.php
├── SiteCommentStatus.php
├── SiteXMLRPCServerFactory.php
├── SiteSentryErrorLogger.php
├── SiteSearchCheckboxList.php
├── SiteUnnamedButton.php
├── SiteAmazonCdnUpdater.php
├── SiteSearchForm.php
├── SiteCommandLineConfigModule.php
├── SiteArticlePath.php
├── SiteLayoutData.php
├── SiteFulltextSearchResult.php
├── SiteSearchIndexer.php
├── SiteArticleSearchEngine.php
├── SitePathEntry.php
├── SiteCdnModule.php
├── SiteTimerCheckpoint.php
└── SiteVideoMediaLocalMover.php
├── .gitignore
├── phpstan.dist.neon
├── phpcs.xml
├── .editorconfig
├── Jenkinsfile
├── rector.php
├── .github
├── pull_request_template.md
└── workflows
│ └── pull-requests.yml
├── dependencies
└── site.yaml
└── .php-cs-fixer.php
/po/potfiles.in:
--------------------------------------------------------------------------------
1 | ../Site
2 |
--------------------------------------------------------------------------------
/locale/en_CA/LC_MESSAGES/site.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cviebrock/site/master/locale/en_CA/LC_MESSAGES/site.mo
--------------------------------------------------------------------------------
/locale/en_GB/LC_MESSAGES/site.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cviebrock/site/master/locale/en_GB/LC_MESSAGES/site.mo
--------------------------------------------------------------------------------
/locale/en_US/LC_MESSAGES/site.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cviebrock/site/master/locale/en_US/LC_MESSAGES/site.mo
--------------------------------------------------------------------------------
/tests/amqp/amqp-test.ini:
--------------------------------------------------------------------------------
1 | [amqp]
2 | server = 192.168.0.100
3 | default_namespace = site-test
4 | sync_timeout = 5000
5 |
--------------------------------------------------------------------------------
/www/styles/site-admin-forgot-password-page.css:
--------------------------------------------------------------------------------
1 | .swat-footer-form-field .swat-button-processing-throbber {
2 | display: none;
3 | }
4 |
--------------------------------------------------------------------------------
/sql/mysql/views/EnabledArticleView.sql:
--------------------------------------------------------------------------------
1 | create or replace view EnabledArticleView as
2 | select id from Article
3 | where enabled = 1;
4 |
--------------------------------------------------------------------------------
/www/admin/images/site-comment-status-slider-bg.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cviebrock/site/master/www/admin/images/site-comment-status-slider-bg.gif
--------------------------------------------------------------------------------
/sql/pgsql/tables/ConfigSetting.sql:
--------------------------------------------------------------------------------
1 | create table ConfigSetting (
2 | name varchar(255) not null,
3 | value varchar(255),
4 | primary key (name)
5 | );
6 |
--------------------------------------------------------------------------------
/www/admin/images/site-comment-status-slider-thumb.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cviebrock/site/master/www/admin/images/site-comment-status-slider-thumb.gif
--------------------------------------------------------------------------------
/www/admin/images/site-comment-display-actions-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cviebrock/site/master/www/admin/images/site-comment-display-actions-arrow.png
--------------------------------------------------------------------------------
/www/admin/images/site-comment-display-actions-arrow@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cviebrock/site/master/www/admin/images/site-comment-display-actions-arrow@2x.png
--------------------------------------------------------------------------------
/sql/pgsql/tables/ImageType.sql:
--------------------------------------------------------------------------------
1 | create table ImageType (
2 | id serial,
3 | extension varchar(10) not null,
4 | mime_type varchar(50) not null,
5 | primary key(id)
6 | );
7 |
--------------------------------------------------------------------------------
/www/admin/styles/site-image-upload.css:
--------------------------------------------------------------------------------
1 | #image_display {
2 | position: relative;
3 | float: right;
4 | margin: 0 0 20px 2em;
5 | clear: after;
6 | border: none;
7 | }
8 |
--------------------------------------------------------------------------------
/sql/mysql/functions/convertTZ.sql:
--------------------------------------------------------------------------------
1 | CREATE FUNCTION convertTZ (param_date timestamp, param_time_zone varchar(50)) RETURNS timestamp
2 | RETURN CONVERT_TZ(param_date, 'UTC', param_time_zone);
3 |
--------------------------------------------------------------------------------
/sql/pgsql/views/ArticleChildCountView.sql:
--------------------------------------------------------------------------------
1 | create or replace view ArticleChildCountView as
2 | select parent as article,
3 | count(id) as child_count
4 | from Article
5 | group by parent;
6 |
--------------------------------------------------------------------------------
/sql/mssql/tables/ImageType.sql:
--------------------------------------------------------------------------------
1 | create table ImageType (
2 | id int not null identity,
3 |
4 | extension varchar(10) null,
5 | mime_type varchar(50) null,
6 |
7 | primary key(id)
8 | );
9 |
--------------------------------------------------------------------------------
/sql/mysql/functions/convertToUTC.sql:
--------------------------------------------------------------------------------
1 | CREATE FUNCTION convertToUTC (param_date timestamp, param_time_zone varchar(50)) RETURNS timestamp
2 | RETURN CONVERT_TZ(param_date, param_time_zone, 'UTC');
3 |
--------------------------------------------------------------------------------
/www/styles/site-account-reset-password-page.css:
--------------------------------------------------------------------------------
1 | /* Account Reset Password page */
2 |
3 | .redirect-links li {
4 | margin-bottom: 0.5em;
5 | }
6 |
7 | .redirect-links a {
8 | font-size: 120%;
9 | }
10 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/MediaType.sql:
--------------------------------------------------------------------------------
1 | create table MediaType (
2 | id serial,
3 |
4 | extension varchar(10),
5 | mime_type varchar(50),
6 | alternate_mime_types varchar(200),
7 |
8 | primary key(id)
9 | );
10 |
11 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/AdReferrer.sql:
--------------------------------------------------------------------------------
1 | create table AdReferrer (
2 | id serial,
3 | createdate timestamp,
4 | http_referer varchar(255),
5 | ad integer not null references Ad(id) on delete set null,
6 | primary key (id)
7 | );
8 |
9 |
--------------------------------------------------------------------------------
/sql/fixtures/SiteBotrMediaSet.sql:
--------------------------------------------------------------------------------
1 |
2 | insert into MediaSet (
3 | shortname,
4 | use_cdn,
5 | obfuscate_filename,
6 | private,
7 | skin
8 | ) values (
9 | 'public',
10 | true,
11 | false,
12 | false,
13 | null
14 | );
15 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/Instance.sql:
--------------------------------------------------------------------------------
1 | create table Instance (
2 | id serial,
3 | shortname varchar(255),
4 | title varchar(255),
5 | primary key (id)
6 | );
7 |
8 | CREATE INDEX Instance_shortname_index ON Instance(shortname);
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/amqp/amqp-test-server.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tests SiteAMQPModule and SiteAMQPApplication sync and async calls.
4 | 1.0
5 |
6 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteCommentJSONException.php:
--------------------------------------------------------------------------------
1 | content;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/MediaPlayer.sql:
--------------------------------------------------------------------------------
1 | create table MediaPlayer (
2 | id serial,
3 |
4 | media_set integer not null references MediaSet(id) on delete cascade,
5 | shortname varchar(255),
6 | key varchar(50) not null,
7 | width int,
8 | height int,
9 |
10 | primary key (id)
11 | );
12 |
13 | create index MediaPlayer_shortname_index on MediaPlayer(shortname);
14 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/SiteEmailLog.sql:
--------------------------------------------------------------------------------
1 | create table SiteEmailLog (
2 | id serial,
3 | createdate timestamp,
4 | instance integer default null,
5 | type varchar(255),
6 | attachment_count integer default 0,
7 | attachment_size integer default 0,
8 | to_address varchar(255),
9 | from_address varchar(255),
10 | recipient_type varchar(3),
11 |
12 | primary key (id)
13 | );
14 |
15 |
--------------------------------------------------------------------------------
/sql/pgsql/functions/convertTZ.sql:
--------------------------------------------------------------------------------
1 | CREATE OR REPLACE FUNCTION convertTZ (timestamp, varchar(50)) RETURNS timestamp AS $$
2 | DECLARE
3 | param_date ALIAS FOR $1;
4 | param_time_zone ALIAS FOR $2;
5 | local_date timestamp;
6 | BEGIN
7 | select into local_date ((param_date at time zone 'UTC') at time zone param_time_zone);
8 | RETURN local_date;
9 | END;
10 | $$ LANGUAGE 'plpgsql' IMMUTABLE;
11 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/AccountLoginHistory.sql:
--------------------------------------------------------------------------------
1 | create table AccountLoginHistory (
2 | id serial,
3 |
4 | account integer not null references Account(id) on delete cascade,
5 | login_date timestamp not null,
6 | ip_address varchar(15),
7 | user_agent varchar(255),
8 |
9 | primary key (id)
10 | );
11 |
12 | create index AccountLoginHistory_account_index on AccountLoginHistory(account);
13 |
--------------------------------------------------------------------------------
/sql/pgsql/functions/convertToUTC.sql:
--------------------------------------------------------------------------------
1 | CREATE OR REPLACE FUNCTION convertToUTC (timestamp, varchar(50)) RETURNS timestamp AS $$
2 | DECLARE
3 | param_date ALIAS FOR $1;
4 | param_time_zone ALIAS FOR $2;
5 | local_date timestamp;
6 | BEGIN
7 | select into local_date ((param_date at time zone param_time_zone) at time zone 'UTC');
8 | RETURN local_date;
9 | END;
10 | $$ LANGUAGE 'plpgsql' IMMUTABLE;
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | vendor/
5 | node_modules/
6 |
7 | # misc
8 | .DS_Store
9 | .env
10 | .idea/
11 | .php-cs-fixer.cache
12 | npm-debug.log*
13 | yarn-debug.log*
14 | yarn-error.log*
15 | *.swp
16 |
17 | # dependency lock file
18 | composer.lock
19 | yarn.lock
20 |
21 | # overrides for local tooling
22 | /phpstan.neon
23 |
--------------------------------------------------------------------------------
/Site/templates/SiteSMILTemplate.php:
--------------------------------------------------------------------------------
1 | content;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Site/templates/SiteVTTTemplate.php:
--------------------------------------------------------------------------------
1 | content;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Site/pages/account-sessions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Site/SitePrivateDataDeleter.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | ./Site
11 |
12 | */layouts/xhtml/*
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Site/SiteFulltextSearchEngine.php:
--------------------------------------------------------------------------------
1 | image_set_shortname = 'video-scrubber';
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Site/templates/SiteAtomTemplate.php:
--------------------------------------------------------------------------------
1 | content;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/ApiSignOnToken.sql:
--------------------------------------------------------------------------------
1 | create table ApiSignOnToken (
2 | id serial,
3 |
4 | ident varchar(255) not null,
5 | token varchar(255) not null,
6 |
7 | api_credential integer not null references ApiCredential(id) on delete cascade,
8 | createdate timestamp not null default LOCALTIMESTAMP,
9 |
10 | primary key (id)
11 | );
12 |
13 | create index ApiSignOnToken_ident_index on ApiSignOnToken(ident);
14 | create index ApiSignOnToken_token_index on ApiSignOnToken(token);
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 | indent_style = space
13 | indent_size = 2
14 |
15 | [*.php]
16 | indent_size = 4
17 |
18 | [*.{diff,md}]
19 | trim_trailing_whitespace = false
20 |
21 | [Jenkinsfile]
22 | indent_size = 4
23 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/Account.sql:
--------------------------------------------------------------------------------
1 | create table Account (
2 | id serial,
3 | instance integer references Instance(id),
4 | fullname varchar(255),
5 | email varchar(255),
6 | password varchar(255),
7 | password_salt varchar(50),
8 | password_tag varchar(255),
9 | createdate timestamp,
10 | last_login timestamp,
11 | delete_date timestamp,
12 | primary key (id)
13 | );
14 |
15 | CREATE INDEX Account_instance_index ON Account(instance);
16 | CREATE INDEX Account_email_index ON Account(email);
17 |
--------------------------------------------------------------------------------
/sql/fixtures/SiteImageType.sql:
--------------------------------------------------------------------------------
1 | insert into ImageType (
2 | extension,
3 | mime_type
4 | ) values (
5 | 'jpg',
6 | 'image/jpeg'
7 | );
8 |
9 | insert into ImageType (
10 | extension,
11 | mime_type
12 | ) values (
13 | 'tif',
14 | 'image/tiff'
15 | );
16 |
17 | insert into ImageType (
18 | extension,
19 | mime_type
20 | ) values (
21 | 'png',
22 | 'image/png'
23 | );
24 |
25 | insert into ImageType (
26 | extension,
27 | mime_type
28 | ) values (
29 | 'gif',
30 | 'image/gif'
31 | );
32 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteInstanceWrapper.php:
--------------------------------------------------------------------------------
1 | index_field = 'id';
15 | $this->row_wrapper_class = SwatDBClassMap::get(SiteInstance::class);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/ApiCredential.sql:
--------------------------------------------------------------------------------
1 | create table ApiCredential (
2 | id serial,
3 | title varchar(255) not null,
4 | api_key varchar(255),
5 | api_shared_secret varchar(255),
6 | createdate timestamp not null,
7 |
8 | instance integer references Instance(id) on delete set null,
9 |
10 | primary key (id),
11 | unique (api_key, instance)
12 | );
13 |
14 | create index ApiCredential_api_key_index on ApiCredential(api_key);
15 | create index ApiCredential_instance_index on ApiCredential(instance);
16 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAdWrapper.php:
--------------------------------------------------------------------------------
1 | index_field = 'id';
17 | $this->row_wrapper_class = SwatDBClassMap::get(SiteAd::class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAudioMediaWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteAudioMedia::class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/sql/mssql/tables/AccountLoginSession.sql:
--------------------------------------------------------------------------------
1 | create table AccountLoginSession (
2 | id int not null identity,
3 |
4 | account int not null references Account(id) on delete cascade,
5 | tag varchar(255),
6 | session_id varchar(255) not null,
7 | createdate datetime2 not null,
8 | login_date datetime2 not null,
9 | ip_address varchar(15) not null,
10 | user_agent nvarchar(255),
11 | dirty bit not null default 0,
12 |
13 | primary key(id)
14 | );
15 |
16 | create index AccountLoginSession_tag on AccountLoginSession(tag);
17 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/Comment.sql:
--------------------------------------------------------------------------------
1 | create table Comment (
2 | id serial,
3 | instance int references Instance(id),
4 | fullname varchar(255),
5 | link varchar(255),
6 | email varchar(255),
7 | bodytext text not null,
8 | status integer not null default 0,
9 | spam boolean not null default false,
10 | ip_address varchar(15),
11 | user_agent varchar(255),
12 | createdate timestamp not null,
13 | primary key (id)
14 | );
15 |
16 | create index Comment_spam_index on Comment(spam);
17 | create index Comment_status_index on Comment(status);
18 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteImageCdnTaskWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteImageCdnTask::class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/sql/mssql/tables/ImageDimensionBinding.sql:
--------------------------------------------------------------------------------
1 | create table ImageDimensionBinding (
2 | image int not null references Image(id),
3 |
4 | dimension int not null references ImageDimension(id),
5 | image_type int not null references ImageType(id),
6 | width int not null,
7 | height int not null,
8 | dpi int not null default 72,
9 | filesize int null,
10 | on_cdn bit not null default 0,
11 |
12 | primary key(image, dimension)
13 | );
14 |
15 | create index ImageDimensionBinding_image_index on ImageDimensionBinding(image);
16 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteInstanceConfigSettingWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
15 | SwatDBClassMap::get(SiteInstanceConfigSetting::class);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/MediaEncoding.sql:
--------------------------------------------------------------------------------
1 | create table MediaEncoding (
2 | id serial,
3 |
4 | media_set integer not null references MediaSet(id) on delete cascade,
5 | default_type integer references MediaType(id) on delete set null,
6 |
7 | title varchar(255),
8 | shortname varchar(255),
9 |
10 | default_encoding boolean not null default true,
11 |
12 | -- SiteBotrMedia Specific Fields
13 | key varchar(50),
14 | width integer,
15 |
16 | primary key(id)
17 | );
18 |
19 | create index MediaEncoding_shortname_index on MediaEncoding(shortname);
20 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAccountWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteAccount::class);
18 | $this->index_field = 'id';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteCdnTaskWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteCdnTask::class);
18 | $this->index_field = 'id';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteImageSetWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteImageSet::class);
17 | $this->index_field = 'id';
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteCommentWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteComment::class);
18 | $this->index_field = 'id';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAccountLoginHistoryWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
17 | SwatDBClassMap::get(SiteAccountLoginHistory::class);
18 |
19 | $this->index_field = 'id';
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/ImageCdnQueue.sql:
--------------------------------------------------------------------------------
1 | create table ImageCdnQueue (
2 | id serial,
3 |
4 | operation varchar(255) not null,
5 |
6 | -- for copy operations, and delete operations where we're just deleting from
7 | -- the cdn, but not deleting from the database.
8 | image int default null references Image(id) on delete cascade,
9 | dimension int default null references ImageDimension(id) on delete cascade,
10 | override_http_headers text,
11 |
12 | -- for delete operations
13 | file_path varchar(255),
14 |
15 | error_date timestamp,
16 |
17 | primary key(id)
18 | );
19 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/MediaCdnQueue.sql:
--------------------------------------------------------------------------------
1 | create table MediaCdnQueue (
2 | id serial,
3 |
4 | operation varchar(255) not null,
5 |
6 | -- for copy operations, and delete operations where we're just deleting from
7 | -- the cdn, but not deleting from the database.
8 | media int default null references Media(id) on delete cascade,
9 | encoding int default null references MediaEncoding(id) on delete cascade,
10 | override_http_headers text,
11 |
12 | -- for delete operations
13 | file_path varchar(255),
14 |
15 | error_date timestamp,
16 |
17 | primary key(id)
18 | );
19 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/InstanceConfigSetting.sql:
--------------------------------------------------------------------------------
1 | create table InstanceConfigSetting (
2 | name varchar(255) not null,
3 | value varchar(1024),
4 | is_default boolean not null default false,
5 | instance integer not null references Instance(id) on delete cascade,
6 | primary key (name, is_default, instance)
7 | );
8 |
9 | CREATE INDEX InstanceConfigSetting_name_index ON InstanceConfigSetting(name);
10 | CREATE INDEX InstanceConfigSetting_is_default_index ON InstanceConfigSetting(is_default);
11 | CREATE INDEX InstanceConfigSetting_instance_index ON InstanceConfigSetting(instance);
12 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/MediaSet.sql:
--------------------------------------------------------------------------------
1 | create table MediaSet (
2 | id serial,
3 |
4 | instance integer default null references Instance(id) on delete cascade,
5 | shortname varchar(255),
6 | use_cdn boolean not null default false,
7 | obfuscate_filename boolean not null default false,
8 | private boolean not null default false,
9 |
10 | skin varchar(50),
11 |
12 | primary key (id)
13 | );
14 |
15 | create index MediaSet_instance_index on MediaSet(instance);
16 | create index MediaSet_shortname_index on MediaSet(shortname);
17 |
--------------------------------------------------------------------------------
/Site/admin/SiteCommentVisibilityCellRenderer.php:
--------------------------------------------------------------------------------
1 | spam
17 | ? Site::_('Spam')
18 | : SiteComment::getStatusTitle($this->status);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteVideoImage.php:
--------------------------------------------------------------------------------
1 | image_set_shortname = 'videos';
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAccountLoginSessionWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(
17 | SiteAccountLoginSession::class
18 | );
19 |
20 | $this->index_field = 'id';
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteApiCredentialWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteApiCredential::class);
18 | $this->index_field = 'id';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAttachmentSetWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteAttachmentSet::class);
18 | $this->index_field = 'id';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | pipeline {
2 | agent any
3 | stages {
4 | stage('Install Composer Dependencies') {
5 | steps {
6 | sh 'rm -rf composer.lock vendor/'
7 | sh 'composer install'
8 | }
9 | }
10 |
11 | stage('Check PHP Coding Style') {
12 | steps {
13 | sh 'composer run phpcs:ci'
14 | }
15 | }
16 |
17 | stage('Check PHP Static Analysis') {
18 | steps {
19 | sh 'composer run phpstan:ci'
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteImageDimensionWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteImageDimension::class);
18 | $this->index_field = 'id';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteVideoMediaEncodingWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
19 | SwatDBClassMap::get(SiteVideoMediaEncoding::class);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sql/fixtures/SiteMediaType.sql:
--------------------------------------------------------------------------------
1 | insert into MediaType (
2 | extension,
3 | mime_type,
4 | alternate_mime_types
5 | ) values (
6 | 'mp4',
7 | 'video/mp4',
8 | null
9 | );
10 |
11 | insert into MediaType (
12 | extension,
13 | mime_type,
14 | alternate_mime_types
15 | ) values (
16 | 'm4a',
17 | 'audio/mp4',
18 | 'audio/aac, audio/x-m4a, audio/MP4A-LATM, audio/mpeg4-generic'
19 | );
20 |
21 | insert into MediaType (
22 | extension,
23 | mime_type,
24 | alternate_mime_types
25 | ) values (
26 | 'mp3',
27 | 'audio/mpeg',
28 | 'audio/mpeg, audio/mp3, audio/MPA, audio/mpa-robust'
29 | );
30 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/ContactMessage.sql:
--------------------------------------------------------------------------------
1 | create table ContactMessage (
2 | id serial,
3 |
4 | instance integer references Instance(id),
5 | class_name varchar(255) not null,
6 | subject varchar(255) not null,
7 | email varchar(255) not null,
8 | message text not null,
9 | spam boolean not null default false,
10 | ip_address varchar(15),
11 | user_agent varchar(255),
12 | createdate timestamp not null,
13 | sent_date timestamp,
14 | error_date timestamp,
15 |
16 | primary key (id)
17 | );
18 |
19 | create index ContactMessage_spam_index on ContactMessage(spam);
20 |
--------------------------------------------------------------------------------
/www/admin/styles/site-comment-status-slider.css:
--------------------------------------------------------------------------------
1 | .site-comment-status-slider {
2 | position: relative;
3 | background: url(../images/site-comment-status-slider-bg.gif) 5px 0 no-repeat;
4 | height: 50px;
5 | width: 218px;
6 | }
7 |
8 | .site-comment-status-slider-thumb {
9 | position: absolute;
10 | }
11 |
12 | img.site-comment-status-slider-image {
13 | position: relative;
14 | top: 3px;
15 | }
16 |
17 | .site-comment-status-slider-legend {
18 | color: #666;
19 | font-size: 85%;
20 | }
21 |
22 | .site-comment-status-slider-legend-selected {
23 | color: #333;
24 | font-weight: bold;
25 | }
26 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteContactMessageWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteContactMessage::class);
18 | $this->index_field = 'id';
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteMediaTypeWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
19 | SwatDBClassMap::get(SiteMediaType::class);
20 |
21 | $this->index_field = 'id';
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/sql/mssql/tables/Account.sql:
--------------------------------------------------------------------------------
1 | create table Account (
2 | id int not null identity,
3 |
4 | instance int null references Instance(id),
5 | fullname nvarchar(255) null,
6 | email nvarchar(255) null,
7 | password nvarchar(255) null,
8 | password_salt varchar(50) null,
9 | password_tag varchar(255) null,
10 | createdate datetime2 null,
11 | last_login datetime2 null,
12 | delete_date datetime2 null,
13 |
14 | primary key (id)
15 | );
16 |
17 | CREATE INDEX Account_instance_index ON Account(instance);
18 | CREATE INDEX Account_email_index ON Account(email);
19 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/MediaEncodingBinding.sql:
--------------------------------------------------------------------------------
1 | create table MediaEncodingBinding (
2 | media integer not null references Media(id) on delete cascade,
3 | media_encoding integer not null references MediaEncoding(id),
4 | media_type integer not null references MediaType(id),
5 |
6 | filesize bigint,
7 |
8 | on_cdn boolean not null default false,
9 |
10 | -- SiteBotrMedia Specific Fields
11 | key varchar(50),
12 | width integer,
13 | height integer,
14 |
15 | primary key(media, media_encoding)
16 | );
17 |
18 | create index MediaEncodingBinding_media_index on MediaEncodingBinding(media);
19 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteVideoMediaEncodingBinding.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
19 | SwatDBClassMap::get(SiteMediaEncoding::class);
20 |
21 | $this->index_field = 'id';
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteVideoMediaEncodingBindingWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
19 | SwatDBClassMap::get(SiteVideoMediaEncodingBinding::class);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteVideoMediaSet.php:
--------------------------------------------------------------------------------
1 | run();
27 |
--------------------------------------------------------------------------------
/Site/SiteCommentable.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Search Results
7 | false
8 |
9 | text/xml
10 |
11 |
12 | 10
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Site/SiteError.php:
--------------------------------------------------------------------------------
1 | registerInternalProperty(
25 | 'media_set',
26 | SwatDBClassMap::get(SiteVideoMediaSet::class)
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/sql/mssql/tables/ImageDimension.sql:
--------------------------------------------------------------------------------
1 | create table ImageDimension (
2 | id int not null identity,
3 |
4 | image_set int not null references ImageSet(id),
5 | default_type int null references ImageType(id),
6 | shortname varchar(255) null,
7 | title nvarchar(255) null,
8 | max_width int null,
9 | max_height int null,
10 | crop bit not null default 0,
11 | dpi int not null default 72,
12 | quality int not null default 85,
13 | strip bit not null default 1,
14 | interlace bit not null default 0,
15 | resize_filter varchar(50) null,
16 |
17 | primary key(id)
18 | );
19 |
20 | CREATE INDEX ImageDimension_shortname_index ON ImageDimension(shortname);
21 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteNotFoundException.php:
--------------------------------------------------------------------------------
1 | title = Site::_('Not Found');
21 | $this->http_status_code = 404;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteSimpleMediaWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
21 | SwatDBClassMap::get(SiteMedia::class);
22 |
23 | $this->index_field = 'id';
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteBadRequestException.php:
--------------------------------------------------------------------------------
1 | title = Site::_('Bad Request');
21 | $this->http_status_code = 400;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/ImageDimension.sql:
--------------------------------------------------------------------------------
1 | create table ImageDimension (
2 | id serial,
3 | image_set integer not null references ImageSet(id) on delete cascade,
4 | default_type integer not null references ImageType(id) on delete cascade,
5 | shortname varchar(255),
6 | title varchar(255),
7 | max_width integer,
8 | max_height integer,
9 | crop boolean not null default false,
10 | dpi integer not null default 72,
11 | quality integer not null default 85,
12 | strip boolean not null default true,
13 | upscale boolean not null default false,
14 | interlace boolean not null default false,
15 | resize_filter varchar(50),
16 | primary key(id)
17 | );
18 |
19 | CREATE INDEX ImageDimension_shortname_index ON ImageDimension(shortname);
20 |
--------------------------------------------------------------------------------
/tests/amqp/amqp-test-server.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | content;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Site/admin/components/InstanceSetting/include/SiteConfigPage.php:
--------------------------------------------------------------------------------
1 | ['title', 'meta_description'], 'date' => ['time_zone']];
20 | }
21 |
22 | protected function getUiXml()
23 | {
24 | return __DIR__ . '/config-page.xml';
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Site/templates/SiteTemplateInterface.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class =
21 | SwatDBClassMap::get(SiteVideoMedia::class);
22 |
23 | $this->index_field = 'id';
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Site/pages/search-form.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Keywords
8 |
9 | 255
10 |
11 |
12 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteException.php:
--------------------------------------------------------------------------------
1 | getMessage();
19 | $message .= "\n" . $error->getUserInfo();
20 | $code = $error->getCode();
21 | }
22 |
23 | parent::__construct($message, $code);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Site/pages/SiteConnectionClosePage.php:
--------------------------------------------------------------------------------
1 | app, SiteBlankTemplate::class);
18 | }
19 |
20 | public function init()
21 | {
22 | parent::init();
23 | header('Connection: close');
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteNotAuthorizedException.php:
--------------------------------------------------------------------------------
1 | title = Site::_('Not Authorized');
21 | $this->http_status_code = 401;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/www/styles/site-contact-page.css:
--------------------------------------------------------------------------------
1 | .swat-frame {
2 | margin: 0;
3 | }
4 |
5 | #contact_form {
6 | float: right;
7 | width: 300px;
8 | margin-left: 20px;
9 | margin-bottom: 1em;
10 | }
11 |
12 | #contact_form .swat-entry,
13 | #contact_form .swat-flydown,
14 | #contact_form .swat-textarea {
15 | width: 98%;
16 | }
17 |
18 | dl#contact_details {
19 | margin: 1em;
20 | }
21 |
22 | dl#contact_details dt {
23 | font-weight: bold;
24 | margin-bottom: 0.5em;
25 | }
26 |
27 | dl#contact_details dd {
28 | margin-left: 1em;
29 | margin-bottom: 1em;
30 | }
31 |
32 | #email_to_field.swat-form-field label,
33 | #email_to_field.swat-form-field .swat-form-field-contents {
34 | display: inline;
35 | }
36 |
37 | #email_to_field.swat-form-field {
38 | margin-bottom: 1em;
39 | }
40 |
--------------------------------------------------------------------------------
/Site/SiteSentryExceptionLogger.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteImageDimensionBindingWrapper.php:
--------------------------------------------------------------------------------
1 | index_field = 'dimension';
18 | $this->row_wrapper_class = $this->getImageDimensionBindingClassName();
19 | }
20 |
21 | protected function getImageDimensionBindingClassName()
22 | {
23 | return SwatDBClassMap::get(SiteImageDimensionBinding::class);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Site/admin/components/InstanceSetting/include/config-page.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 | 255
8 |
9 |
10 |
11 | Meta Description
12 |
13 |
14 |
15 | Time Zone
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/Media.sql:
--------------------------------------------------------------------------------
1 | create table Media (
2 | id serial,
3 |
4 | path_key varchar(30) not null,
5 | media_set integer not null references MediaSet(id),
6 | image integer references Image(id) on delete set null,
7 |
8 | title varchar(255),
9 | filename varchar(255),
10 | original_filename varchar(255),
11 |
12 | has_hls boolean not null default false,
13 | downloadable boolean not null default false,
14 | duration integer,
15 | description text,
16 |
17 | key varchar(50), -- deprecated
18 |
19 | createdate timestamp,
20 |
21 | -- SiteVideoMedia specific fields
22 | scrubber_image integer references Image(id) on delete set null,
23 | scrubber_image_count integer not null default 0,
24 |
25 | primary key (id)
26 | );
27 |
28 | create index Media_path_key_index on Media(path_key);
29 |
--------------------------------------------------------------------------------
/www/styles/site-image-cell-renderer.css:
--------------------------------------------------------------------------------
1 | .swat-tile-view .swat-tile {
2 | width: 126px;
3 | height: auto;
4 | padding: 0;
5 | margin: 5px;
6 | float: left;
7 | text-align: center;
8 | }
9 |
10 | .swat-tile-view .swat-tile a {
11 | padding: 10px;
12 | display: block;
13 | text-decoration: none;
14 | }
15 |
16 | .swat-tile-view .swat-tile a:hover {
17 | background: #eee;
18 | }
19 |
20 | .swat-tile-view .swat-tile span.title {
21 | display: block;
22 | height: 2em;
23 | padding: 0.2em 0;
24 | }
25 |
26 | .swat-tile-view .swat-tile .site-image-wrapper {
27 | display: table-cell;
28 | vertical-align: middle;
29 | position: relative;
30 | }
31 |
32 | .swat-tile-view .site-image-wrapper img {
33 | display: block;
34 | margin: 0 auto;
35 | padding: 2px;
36 | border: 1px solid #ddd;
37 | background: #ccc;
38 | }
39 |
--------------------------------------------------------------------------------
/tests/amqp/AMQPTestServer.php:
--------------------------------------------------------------------------------
1 | getBody() === 'fail-test') {
10 | $this->logger->debug(' => sending test failure' . PHP_EOL);
11 | $job->sendFail('This is a test exception');
12 | } else {
13 | $this->logger->debug(
14 | ' => reversing "{string}"' . PHP_EOL,
15 | ['string' => $job->getBody()]
16 | );
17 | $job->sendSuccess(strrev($job->getBody()));
18 | }
19 | sleep(1);
20 | }
21 |
22 | protected function getDefaultModuleList()
23 | {
24 | return ['config' => 'SiteConfigModule'];
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteVideoMediaSetWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteVideoMediaSet::class);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Site/exceptions/SitePathInvalidUtf8Exception.php:
--------------------------------------------------------------------------------
1 | path = $raw_path;
20 | }
21 |
22 | public function getRawPath()
23 | {
24 | return $this->path;
25 | }
26 |
27 | public function getEscapedPath()
28 | {
29 | return SwatString::escapeBinary($this->getRawPath());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Site/admin/SiteCommentApprovalPage.php:
--------------------------------------------------------------------------------
1 | ui->getWidget('delete_button')->title = Site::_('Deny');
15 | }
16 |
17 | protected function approve()
18 | {
19 | $this->data_object->status = SiteComment::STATUS_PUBLISHED;
20 | $this->data_object->save();
21 | $this->data_object->postSave($this->app);
22 | }
23 |
24 | protected function delete()
25 | {
26 | $this->data_object->delete();
27 | $this->data_object->clearCache($this->app);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Site/SiteKeywordEntry.php:
--------------------------------------------------------------------------------
1 | name !== null) {
27 | $tag->name = $this->name;
28 | }
29 |
30 | return $tag;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Site/templates/SiteAbstractTemplate.php:
--------------------------------------------------------------------------------
1 | display($data);
13 |
14 | return ob_get_clean();
15 | }
16 |
17 | public function getBaseUri()
18 | {
19 | $uri = $_SERVER['HTTP_HOST'];
20 | $is_stage = (mb_strpos($uri, 'berna.silverorange.com') !== false);
21 | $stage_uri = 'https://' . $_SERVER['HTTP_HOST'] .
22 | mb_substr($_SERVER['REQUEST_URI'], 0, mb_strpos($_SERVER['REQUEST_URI'], 'www') + 3);
23 |
24 | return $is_stage
25 | ? $stage_uri
26 | : 'https://www.emrap.org';
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/sql/pgsql/views/SuspiciousAccountView.sql:
--------------------------------------------------------------------------------
1 | create or replace view SuspiciousAccountView as
2 |
3 | SELECT accountloginhistory.account,
4 | min(accountloginhistory.login_date) AS first_suspicious_login,
5 | max(accountloginhistory.login_date) AS last_suspicious_login,
6 | count(accountloginhistory.id) AS login_count,
7 | count(DISTINCT accountloginhistory.user_agent) AS user_agent_count,
8 | count(DISTINCT accountloginhistory.ip_address) AS ip_address_count
9 | FROM accountloginhistory
10 |
11 | /* In the past week there have been more than 5 logins from more than 5 IPs and more than 5 user-agents */
12 | WHERE accountloginhistory.login_date > (now() - '7 days'::interval)
13 | GROUP BY accountloginhistory.account
14 | HAVING count(accountloginhistory.id) > 4
15 | and count(DISTINCT accountloginhistory.user_agent) > 4
16 | and count(DISTINCT accountloginhistory.ip_address) > 4
17 | ;
18 |
19 |
--------------------------------------------------------------------------------
/Site/templates/SiteXMLRPCServerTemplate.php:
--------------------------------------------------------------------------------
1 | response;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteImageLazyWrapper.php:
--------------------------------------------------------------------------------
1 | lazy_load recordset wrapper option
16 | */
17 | class SiteImageLazyWrapper extends SiteImageWrapper
18 | {
19 | public function __construct(
20 | ?MDB2_Result_Common $rs = null,
21 | array $options = []
22 | ) {
23 | $options = array_merge(
24 | $options,
25 | ['lazy_load' => true]
26 | );
27 |
28 | parent::__construct($rs, $options);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/sql/mysql/functions/getArticleNavBar.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Returns navbar information from an article.
3 | *
4 | * @param_parent INTEGER: the id of the article to search from.
5 | *
6 | * Returns a set of returned_rows ordered correctly to go in the navbar.
7 | * Checking if the parent articles are enabled is left up to sp_article_find.
8 | * If the article is not found, returns an empty recordset.
9 | *
10 | * This procedure uses recursion to output entries in the correct order for
11 | * applications.
12 | */
13 |
14 | CREATE PROCEDURE getArticleNavBar(param_id INTEGER)
15 | BEGIN
16 | CREATE TEMPORARY TABLE Tree_Ids(displayorder SERIAL, id INTEGER);
17 | CALL getTreeIds(param_id);
18 |
19 | SELECT Article.id, Article.parent, Article.shortname, Article.title
20 | FROM Article
21 | INNER JOIN Tree_Ids ON Article.id = Tree_Ids.id
22 | ORDER BY Tree_Ids.displayorder desc;
23 |
24 | DROP TABLE Tree_Ids;
25 | END;
26 |
--------------------------------------------------------------------------------
/Site/SiteCommentStatus.php:
--------------------------------------------------------------------------------
1 | getLayout($source);
15 | $map = $this->getPageMap();
16 |
17 | if (!isset($map[$source])) {
18 | throw new SiteNotFoundException();
19 | }
20 |
21 | $class = $map[$source];
22 |
23 | return $this->instantiatePage($class, $layout);
24 | }
25 |
26 | protected function getPageMap(): array
27 | {
28 | return [];
29 | }
30 |
31 | protected function getLayout($source): SiteXMLRPCServerLayout
32 | {
33 | return new SiteXMLRPCServerLayout($this->app);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Site/SiteSentryErrorLogger.php:
--------------------------------------------------------------------------------
1 | filter($e)) {
24 | \Sentry\captureException(
25 | new ErrorException(
26 | $e->getMessage(),
27 | 0,
28 | $e->getSeverity(),
29 | $e->getFile(),
30 | $e->getLine()
31 | )
32 | );
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Site/templates/SiteXMLSiteMapTemplate.php:
--------------------------------------------------------------------------------
1 | ';
26 |
27 | echo $data->site_map;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/sql/mysql/functions/getArticlePathInfo.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Returns path information for an article.
3 | *
4 | * @param_id INTEGER: the id of the article.
5 | *
6 | * Returns a set of type_article_path_info. The set is ordered from the leaf to the root.
7 | * If the article is not found, an empty record set is returned.
8 | */
9 |
10 | CREATE PROCEDURE getTreeIds(IN param_id INTEGER)
11 | BEGIN
12 | DECLARE parent_id INTEGER;
13 | INSERT INTO Tree_Ids (id) values (param_id);
14 |
15 | SELECT parent INTO parent_id FROM Article where id = param_id;
16 |
17 | IF parent_id IS NOT NULL THEN
18 | CALL getTreeIds(parent_id);
19 | END IF;
20 | END;
21 |
22 | CREATE PROCEDURE getArticlePathInfo(param_id INTEGER)
23 | BEGIN
24 | CREATE TEMPORARY TABLE Tree_Ids (displayorder SERIAL, id INTEGER);
25 | CALL getTreeIds(param_id);
26 |
27 | SELECT id, parent, shortname, title FROM Article WHERE id IN (
28 | SELECT id FROM Tree_Ids);
29 |
30 | DROP TABLE Tree_Ids;
31 | END;
32 |
--------------------------------------------------------------------------------
/Site/SiteSearchCheckboxList.php:
--------------------------------------------------------------------------------
1 | getForm();
19 |
20 | SwatOptionControl::process();
21 |
22 | $this->getCompositeWidget('check_all')->process();
23 |
24 | $data = &$form->getFormData();
25 |
26 | $this->processValues();
27 | }
28 |
29 | protected function getLiTag($option)
30 | {
31 | $tag = parent::getLiTag($option);
32 |
33 | if (in_array($option->value, $this->highlight_values)) {
34 | $tag->class = 'highlight';
35 | }
36 |
37 | return $tag;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/sql/pgsql/tables/Article.sql:
--------------------------------------------------------------------------------
1 | create table Article (
2 | id serial,
3 | parent int, -- constraint added below
4 | title varchar(255),
5 | html_title varchar(255),
6 | description text,
7 | bodytext text,
8 | createdate timestamp not null default LOCALTIMESTAMP,
9 | modified_date timestamp not null default LOCALTIMESTAMP,
10 | displayorder int not null default 0,
11 | enabled boolean not null default true,
12 | visible boolean not null default true,
13 | searchable boolean not null default true,
14 | shortname varchar(255),
15 | primary key (id)
16 | );
17 |
18 | ALTER TABLE Article ADD CONSTRAINT Articlefk FOREIGN KEY (parent) REFERENCES Article(id) MATCH FULL on delete cascade;
19 |
20 | CREATE INDEX Article_parent_index ON Article(parent);
21 | CREATE INDEX Article_shortname_index ON Article(shortname);
22 | CREATE INDEX Article_visible_index ON Article(visible);
23 | CREATE INDEX Article_enabled_index ON Article(enabled);
24 | CREATE INDEX Article_searchable_index ON Article(searchable);
25 |
26 |
--------------------------------------------------------------------------------
/Site/pages/SiteJSONPage.php:
--------------------------------------------------------------------------------
1 | setLayout(
17 | new SiteLayout(
18 | $this->app,
19 | SiteJSONTemplate::class
20 | )
21 | );
22 | }
23 |
24 | // build phase
25 |
26 | public function build()
27 | {
28 | $this->layout->data->content = json_encode($this->getResponse());
29 | }
30 |
31 | abstract protected function getResponse();
32 |
33 | protected function getStatus($code = 'ok', $message = '')
34 | {
35 | return ['code' => $code, 'message' => $message];
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/rector.php:
--------------------------------------------------------------------------------
1 | withPaths([
13 | __DIR__ . '/po',
14 | __DIR__ . '/Site',
15 | __DIR__ . '/tests',
16 | __DIR__ . '/www',
17 | ])
18 | // uncomment to reach your current PHP version
19 | ->withPhpSets(php82: true)
20 | ->withRules([
21 | ])
22 | ->withSkip([
23 | ClassPropertyAssignToConstructorPromotionRector::class,
24 | MixedTypeRector::class,
25 | NullToStrictStringFuncCallArgRector::class,
26 | RemoveUnusedVariableInCatchRector::class,
27 | ])
28 | ->withTypeCoverageLevel(1)
29 | ->withDeadCodeLevel(1);
30 |
--------------------------------------------------------------------------------
/Site/SiteUnnamedButton.php:
--------------------------------------------------------------------------------
1 | visible) {
16 | return;
17 | }
18 |
19 | $form = $this->getFirstAncestor('SwatForm');
20 | $primary = ($form !== null
21 | && $form->getFirstDescendant('SwatButton') === $this);
22 |
23 | $input_tag = new SwatHtmlTag('input');
24 | $input_tag->type = 'submit';
25 | $input_tag->id = $this->id;
26 | $input_tag->value = $this->title;
27 | $input_tag->class = $this->getCSSClassString();
28 |
29 | if ($this->access_key != '') {
30 | $input_tag->accesskey = $this->access_key;
31 | }
32 |
33 | $input_tag->display();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAttachmentWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteAttachment::class);
18 | $this->index_field = 'id';
19 | }
20 |
21 | public function getBySet($shortname)
22 | {
23 | $wrapper_class = SwatDBClassMap::get(SiteAttachmentWrapper::class);
24 | $attachments = new $wrapper_class();
25 |
26 | foreach ($this as $attachment) {
27 | if ($attachment->attachment_set->shortname === $shortname) {
28 | $attachments->add($attachment);
29 | }
30 | }
31 |
32 | return $attachments;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/sql/mysql/views/AdReferrerByPeriodView.sql:
--------------------------------------------------------------------------------
1 | create or replace view AdReferrerByPeriodView as
2 |
3 | select id as ad,
4 | -- {{{ day
5 | (select count(ad)
6 | from AdReferrer
7 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval 1 day) and AdReferrer.ad = Ad.id
8 | group by ad)
9 | as day,
10 | -- }}}
11 | -- {{{ week
12 | (select count(ad)
13 | from AdReferrer
14 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval 1 week) and AdReferrer.ad = Ad.id
15 | group by ad)
16 | as week,
17 | -- }}}
18 | -- {{{ 2 week
19 | (select count(ad)
20 | from AdReferrer
21 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval 2 week) and AdReferrer.ad = Ad.id
22 | group by ad)
23 | as two_week,
24 | -- }}}
25 | -- {{{ month
26 | (select count(ad)
27 | from AdReferrer
28 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval 1 month) and AdReferrer.ad = Ad.id
29 | group by ad)
30 | as month,
31 | -- }}}
32 | -- {{{ total
33 | (select count(ad)
34 | from AdReferrer
35 | where AdReferrer.ad = Ad.id
36 | group by ad)
37 | as total
38 | -- }}}
39 | from Ad;
40 |
--------------------------------------------------------------------------------
/sql/pgsql/views/AdReferrerByPeriodView.sql:
--------------------------------------------------------------------------------
1 | create or replace view AdReferrerByPeriodView as
2 |
3 | select id as ad,
4 | -- {{{ day
5 | (select count(ad)
6 | from AdReferrer
7 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval '1 day') and AdReferrer.ad = Ad.id
8 | group by ad)
9 | as day,
10 | -- }}}
11 | -- {{{ week
12 | (select count(ad)
13 | from AdReferrer
14 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval '1 week') and AdReferrer.ad = Ad.id
15 | group by ad)
16 | as week,
17 | -- }}}
18 | -- {{{ 2 week
19 | (select count(ad)
20 | from AdReferrer
21 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval '2 week') and AdReferrer.ad = Ad.id
22 | group by ad)
23 | as two_week,
24 | -- }}}
25 | -- {{{ month
26 | (select count(ad)
27 | from AdReferrer
28 | where AdReferrer.createdate > (LOCALTIMESTAMP - interval '1 month') and AdReferrer.ad = Ad.id
29 | group by ad)
30 | as month,
31 | -- }}}
32 | -- {{{ total
33 | (select count(ad)
34 | from AdReferrer
35 | where AdReferrer.ad = Ad.id
36 | group by ad)
37 | as total
38 | -- }}}
39 | from Ad;
40 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | # Description
2 |
3 | Add a description of new changes, the reason for new changes, and how the new
4 | changes work here.
5 |
6 | # Testing Instructions (optional)
7 |
8 | Add step-by-step instructions for testing the PR, if necessary.
9 |
10 | 1. Check out this PR
11 | 2. …
12 |
13 | # Developer Checklist
14 |
15 | Before requesting review for this PR, make sure the following tasks are
16 | complete:
17 |
18 | - [ ] I added a link to the relevant Shortcut story, if applicable
19 | - [ ] I added testing instructions, if any
20 | - [ ] I made sure existing CI checks pass
21 | - [ ] I checked that all requirements of the ticket are fulfilled
22 |
23 | # Reviewer Checklist
24 |
25 | Before merging this PR, make sure the following tasks are complete:
26 |
27 | - [ ] I made sure there are no active labels that block merge
28 | - [ ] I followed the testing instructions
29 | - [ ] I made sure the CI checks pass
30 | - [ ] I reviewed the file changes on GitHub
31 | - [ ] I checked that all requirements of the ticket (if any) are fulfilled
32 |
--------------------------------------------------------------------------------
/Site/admin/components/Account/forgot-password.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | false
12 |
13 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Site/SiteAmazonCdnUpdater.php:
--------------------------------------------------------------------------------
1 | cdn->bucket = $config->amazon->bucket;
18 | $this->cdn->access_key_id = $config->amazon->access_key_id;
19 | $this->cdn->access_key_secret = $config->amazon->access_key_secret;
20 |
21 | if ($config->amazon->reduced_redundancy) {
22 | $this->cdn->setReducedRedundancy();
23 | }
24 | }
25 |
26 | protected function getDefaultModuleList()
27 | {
28 | return array_merge(
29 | parent::getDefaultModuleList(),
30 | [
31 | 'cdn' => SiteAmazonCdnModule::class,
32 | ]
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAccountLoginHistory.php:
--------------------------------------------------------------------------------
1 | table = 'AccountLoginHistory';
39 | $this->id_field = 'integer:id';
40 |
41 | $this->registerDateProperty('login_date');
42 |
43 | $this->registerInternalProperty(
44 | 'account',
45 | SwatDBClassMap::get(SiteAccount::class)
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteVideoMediaWrapper.php:
--------------------------------------------------------------------------------
1 | row_wrapper_class = SwatDBClassMap::get(SiteVideoMedia::class);
18 | }
19 |
20 | protected function getMediaSetWrapperClass()
21 | {
22 | return SwatDBClassMap::get(SiteVideoMediaSetWrapper::class);
23 | }
24 |
25 | protected function getMediaEncodingBindingWrapperClass()
26 | {
27 | return SwatDBClassMap::get(SiteVideoMediaEncodingBindingWrapper::class);
28 | }
29 |
30 | protected function getMediaEncodingBindingOrderBy()
31 | {
32 | // order by width with nulls first so that encodings are ordered from
33 | // audio (no width), then from smallest to largest encoding.
34 | return 'media, width asc nulls first';
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Site/admin/components/Image/delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/www/styles/site-jw-player-media-display.css:
--------------------------------------------------------------------------------
1 | .video-player-container {
2 | position: relative;
3 | }
4 |
5 | .video-player .video-player-upgrade {
6 | background: rgba(255, 255, 255, 0.5);
7 | border-radius: 10px;
8 | width: 80%;
9 | margin: 0 10%;
10 | text-shadow: none;
11 | font-size: 14px;
12 | color: #333;
13 | }
14 |
15 | .video-player .video-player-upgrade a {
16 | color: #333!important;
17 | }
18 |
19 | /* Fix for apsect-ratio sized flash player. Was broken in Chrome. */
20 | .video-player object {
21 | top: 0;
22 | left: 0;
23 | }
24 |
25 | .video-player > div {
26 | vertical-align: bottom;
27 | }
28 |
29 | .video-player .overlay {
30 | position: absolute;
31 | top: 0;
32 | left: 0;
33 | right: 0;
34 | bottom: 0;
35 | z-index: 2;
36 | background: #fff;
37 | border-radius: 0;
38 | }
39 |
40 | .video-player .overlay-content {
41 | position: absolute;
42 | height: auto;
43 | width: auto;
44 | top: 40px;
45 | left: 40px;
46 | bottom: 40px;
47 | right: 40px;
48 | z-index: 3;
49 | text-align: center;
50 | color: #666;
51 | text-shadow: none;
52 | }
53 |
54 | .video-player.no-captions .jw-icon-cc {
55 | display: none;
56 | }
57 |
--------------------------------------------------------------------------------
/.github/workflows/pull-requests.yml:
--------------------------------------------------------------------------------
1 | name: Pull Requests
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | runner:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Check out repository code
14 | uses: actions/checkout@v4
15 |
16 | - name: Setup PHP with tools
17 | uses: silverorange/actions-setup-php@v2
18 | with:
19 | php-version: '8.2'
20 | extensions: gd
21 |
22 | - name: Get composer cache directory
23 | id: composer-cache
24 | run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
25 |
26 | - name: Cache dependencies
27 | uses: actions/cache@v4
28 | with:
29 | path: ${{ steps.composer-cache.outputs.dir }}
30 | key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
31 | restore-keys: ${{ runner.os }}-composer-
32 |
33 | - name: Install PHP dependencies
34 | run: 'composer install'
35 |
36 | - name: Run tests
37 | timeout-minutes: 5
38 | run: |
39 | composer run phpcs:ci
40 | composer run phpstan:ci
41 |
--------------------------------------------------------------------------------
/Site/SiteSearchForm.php:
--------------------------------------------------------------------------------
1 | setMethod(SwatForm::METHOD_GET);
21 | $this->requires_id = false;
22 | }
23 |
24 | public function isSubmitted()
25 | {
26 | /*
27 | * Search forms do not output an hidden field to determine if they
28 | * have been submitted. Instead they are always assummed to be
29 | * submitted.
30 | */
31 | return true;
32 | }
33 |
34 | protected function displayHiddenFields()
35 | {
36 | /*
37 | * Override to not output any hidden fields since search forms use the
38 | * HTTP GET method.
39 | */
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteInvalidClassException.php:
--------------------------------------------------------------------------------
1 | object = $object;
29 | }
30 |
31 | /**
32 | * Gets the object that is of the wrong class.
33 | *
34 | * @return mixed the object that is of the wrong class
35 | */
36 | public function getObject()
37 | {
38 | return $this->object;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Site/admin/components/Attachment/upload.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Title
9 |
10 | true
11 | 255
12 |
13 |
14 |
15 | File
16 |
17 | true
18 | true
19 |
20 |
21 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteAMQPJobFailureException.php:
--------------------------------------------------------------------------------
1 | raw_body = (string) $raw_body;
29 | }
30 |
31 | /**
32 | * Gets the raw AMQP response body of this exception.
33 | *
34 | * @return string the raw AMQP response body
35 | */
36 | public function getRawBody()
37 | {
38 | return $this->raw_body;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Site/admin/components/Account/edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Account
7 |
8 |
9 | Full Name
10 |
11 | true
12 | 255
13 |
14 |
15 |
16 | Email
17 |
18 | true
19 | 255
20 |
21 |
22 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Site/admin/components/Media/poster-frame.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Poster Frame
7 |
8 |
9 | text/xml
10 |
11 |
12 | Custom Poster Frame
13 |
14 | true
15 | image/jpeg
16 | image/png
17 | image/tiff
18 |
19 |
20 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Site/admin/components/Ad/edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Ad
7 |
8 |
9 | Title
10 |
11 | true
12 | 255
13 |
14 |
15 |
16 | Short Name
17 |
18 | true
19 | 255
20 |
21 |
22 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAdReferrer.php:
--------------------------------------------------------------------------------
1 | table = 'AdReferrer';
44 | $this->id_field = 'integer:id';
45 | $this->registerDateProperty('createdate');
46 | $this->registerInternalProperty('ad', SiteAd::class);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteInstanceConfigSetting.php:
--------------------------------------------------------------------------------
1 | table = 'InstanceConfigSetting';
42 |
43 | $this->registerInternalProperty(
44 | 'instance',
45 | SwatDBClassMap::get(SiteInstance::class)
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteClassNotFoundException.php:
--------------------------------------------------------------------------------
1 | class_name = $class_name;
29 | }
30 |
31 | /**
32 | * Gets the name of the class that is not found.
33 | *
34 | * @return string the name of the class that is not found
35 | */
36 | public function getClassName()
37 | {
38 | return $this->class_name;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Site/pages/account-forgot-password.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Forgot your password? No problem.
6 |
7 |
8 | Simply enter your email address and a link to create a new password will be sent to you.
]]>
9 | text/xml
10 |
11 |
12 | Email
13 |
14 | true
15 | 255
16 |
17 |
18 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/sql/pgsql/functions/getArticlePathInfo.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Returns path information for an article.
3 | *
4 | * @param_id INTEGER: the id of the article.
5 | *
6 | * @returned_row type_article_path_info: a row containing id, parent, shortname, title
7 | *
8 | * Returns a set of type_article_path_info. The set is ordered from the leaf to the root.
9 | * If the article is not found, an empty record set is returned.
10 | */
11 | CREATE TYPE type_article_path_info AS (id INTEGER, parent INTEGER, shortname VARCHAR(255), title VARCHAR(255));
12 |
13 | CREATE OR REPLACE FUNCTION getArticlePathInfo(INTEGER) RETURNS SETOF type_article_path_info AS $$
14 | DECLARE
15 | param_id ALIAS FOR $1;
16 | local_id INTEGER;
17 | returned_row type_article_path_info%ROWTYPE;
18 | BEGIN
19 | local_id := param_id;
20 |
21 | WHILE local_id is not null LOOP
22 | BEGIN
23 | SELECT INTO returned_row id, parent, shortname, title
24 | FROM Article
25 | WHERE id = local_id;
26 |
27 | -- return the row
28 | IF FOUND THEN
29 | RETURN NEXT returned_row;
30 | END IF;
31 |
32 | -- move up the tree
33 | local_id := returned_row.parent;
34 | END;
35 | END LOOP;
36 |
37 | RETURN;
38 | END;
39 | $$ LANGUAGE 'plpgsql';
40 |
--------------------------------------------------------------------------------
/sql/mysql/functions/getArticlePath.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Returns the path string of an article.
3 | *
4 | * @param_parent INTEGER: the id of the category to search from.
5 | *
6 | * Returns a VARCHAR containing the path string for the given category. If the
7 | * category does not exist, NULL is returned.
8 | */
9 |
10 | CREATE FUNCTION getArticlePath(param_id INTEGER) RETURNS VARCHAR(255)
11 | BEGIN
12 | DECLARE local_parent INTEGER;
13 | DECLARE local_shortname VARCHAR(255);
14 | DECLARE local_path VARCHAR(255);
15 |
16 | SET local_path = NULL;
17 |
18 | -- get current article results
19 | SELECT parent, shortname INTO local_parent, local_shortname
20 | FROM Article
21 | WHERE id = param_id;
22 |
23 | IF FOUND THEN
24 | SET local_path = local_shortname;
25 | END IF;
26 |
27 | -- get parent article results
28 | WHILE local_parent IS NOT NULL DO
29 |
30 | SELECT parent, shortname INTO local_parent, local_shortname
31 | FROM Article
32 | WHERE id = local_parent;
33 |
34 | IF FOUND THEN
35 | IF local_path IS NULL THEN
36 | SET local_path = local_shortname;
37 | ELSE
38 | SET local_path = CONCAT(local_shortname, '/', local_path);
39 | END IF;
40 | END IF;
41 | END WHILE;
42 |
43 | RETURN local_path;
44 | END;
45 |
--------------------------------------------------------------------------------
/tests/amqp/AMQPTestClient.php:
--------------------------------------------------------------------------------
1 | initModules();
10 | $this->parseCommandLineArguments();
11 |
12 | $strings = ['test', 'abcdefg', 'fail-test'];
13 |
14 | $this->debug("Async test:\n", true);
15 |
16 | foreach ($strings as $string) {
17 | $this->debug($string . "\n");
18 | $this->amqp->doAsync('strrev', $string);
19 | }
20 |
21 | $this->debug("\n");
22 | $this->debug("Sync test:\n", true);
23 |
24 | try {
25 | foreach ($strings as $string) {
26 | $this->debug($string . ' => ');
27 | $this->debug($this->amqp->doSync('strrev', $string));
28 | $this->debug("\n");
29 | }
30 | } catch (SiteAMQPJobFailureException $e) {
31 | $this->debug("CAUGHT EXPECTED FAIL\n");
32 | }
33 |
34 | $this->debug("\n");
35 | $this->debug("done\n", true);
36 | }
37 |
38 | protected function getDefaultModuleList()
39 | {
40 | return ['config' => 'SiteConfigModule', 'amqp' => 'SiteAMQPModule'];
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteArticleWrapper.php:
--------------------------------------------------------------------------------
1 | shortname === $shortname) {
28 | $returned_article = $article;
29 | break;
30 | }
31 | }
32 |
33 | return $returned_article;
34 | }
35 |
36 | protected function init()
37 | {
38 | parent::init();
39 | $this->row_wrapper_class = SwatDBClassMap::get(SiteArticle::class);
40 | $this->index_field = 'id';
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAttachmentCdnTaskWrapper.php:
--------------------------------------------------------------------------------
1 | getOption('lazy_load')) {
23 | $this->loadAllSubDataObjects(
24 | 'attachment',
25 | $this->db,
26 | 'select * from Attachment where id in (%s)',
27 | SwatDBClassMap::get(SiteAttachmentWrapper::class)
28 | );
29 | }
30 | }
31 |
32 | protected function init()
33 | {
34 | parent::init();
35 |
36 | $this->row_wrapper_class = SwatDBClassMap::get(SiteAttachmentCdnTask::class);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/sql/pgsql/functions/getArticlePath.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Returns the path string of an article.
3 | *
4 | * @param_parent INTEGER: the id of the article to search from.
5 | *
6 | * Returns a VARCHAR containing the path string for the given article. If the
7 | * article does not exist, NULL is returned.
8 | */
9 | CREATE OR REPLACE FUNCTION getArticlePath(INTEGER) RETURNS VARCHAR(255) AS $$
10 | DECLARE
11 | param_id ALIAS FOR $1;
12 | local_parent INTEGER;
13 | local_shortname VARCHAR(255);
14 | local_path VARCHAR(255);
15 | BEGIN
16 | local_path = NULL;
17 |
18 | -- get current article results
19 | SELECT INTO local_parent, local_shortname parent, shortname
20 | FROM Article
21 | WHERE id = param_id;
22 |
23 | IF FOUND THEN
24 | local_path = local_shortname;
25 | END IF;
26 |
27 | -- get parent article results
28 | WHILE local_parent IS NOT NULL LOOP
29 | BEGIN
30 |
31 | SELECT INTO local_parent, local_shortname parent, shortname
32 | FROM Article
33 | WHERE id = local_parent;
34 |
35 | IF FOUND THEN
36 | IF local_path IS NULL THEN
37 | local_path = local_shortname;
38 | ELSE
39 | local_path = local_shortname || '/' || local_path;
40 | END IF;
41 | END IF;
42 |
43 | END;
44 | END LOOP;
45 |
46 | RETURN local_path;
47 | END;
48 | $$ LANGUAGE 'plpgsql';
49 |
--------------------------------------------------------------------------------
/Site/pages/account-reset-password.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | New Password
10 |
11 | 4
12 | true
13 |
14 |
15 |
16 | Confirm New Password
17 | Password is case-sensitive.
18 |
19 |
20 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Site/SiteCommandLineConfigModule.php:
--------------------------------------------------------------------------------
1 | app->database->dsn = $this->database->dsn;
32 |
33 | if ($this->date->time_zone !== null) {
34 | $this->app->default_time_zone =
35 | new DateTimeZone($this->date->time_zone);
36 | }
37 |
38 | $this->app->default_locale = $this->i18n->locale;
39 |
40 | setlocale(LC_ALL, $this->i18n->locale . '.UTF-8');
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Site/admin/components/Image/upload.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | false
9 |
10 |
11 | Upload an image to be automatically resized
12 |
13 | Image
14 |
15 |
16 |
17 |
18 | false
19 | or Upload images that have been manually resized
20 |
21 | true
22 |
23 |
24 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteMediaEncodingBindingWrapper.php:
--------------------------------------------------------------------------------
1 | getOption('lazy_load')) {
23 | $this->loadAllSubDataObjects(
24 | 'media_type',
25 | $this->db,
26 | 'select * from MediaType where id in (%s)',
27 | SwatDBClassMap::get(SiteMediaTypeWrapper::class)
28 | );
29 | }
30 | }
31 |
32 | protected function init()
33 | {
34 | parent::init();
35 |
36 | $this->row_wrapper_class =
37 | SwatDBClassMap::get(SiteMediaEncodingBinding::class);
38 |
39 | $this->index_field = 'media_encoding';
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Site/admin/components/Article/include/SiteArticleVisibilityCellRenderer.php:
--------------------------------------------------------------------------------
1 | enabled) {
23 | $messages[] = Site::_('not enabled');
24 | } elseif ($this->display_positive_states) {
25 | $messages[] = Site::_('enabled');
26 | }
27 |
28 | if (!$this->searchable) {
29 | $messages[] = Site::_('not searchable');
30 | } elseif ($this->display_positive_states) {
31 | $messages[] = Site::_('searchable');
32 | }
33 |
34 | if (!$this->show_in_menu) {
35 | $messages[] = Site::_('not shown in menu');
36 | } elseif ($this->display_positive_states) {
37 | $messages[] = Site::_('shown in menu');
38 | }
39 |
40 | echo implode($this->separator, $messages);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Site/pages/SiteMessageDisplayPageDecorator.php:
--------------------------------------------------------------------------------
1 | message_display = new SwatMessageDisplay();
21 | }
22 |
23 | // build phase
24 |
25 | public function build()
26 | {
27 | parent::build();
28 |
29 | foreach ($this->app->messages->getAll() as $message) {
30 | $this->message_display->add($message);
31 | }
32 |
33 | if ($this->message_display->getMessageCount() > 0) {
34 | $this->layout->startCapture('content', true);
35 | $this->message_display->display();
36 | $this->layout->endCapture();
37 | }
38 | }
39 |
40 | // finalize phase
41 |
42 | public function finalize()
43 | {
44 | parent::finalize();
45 |
46 | if ($this->message_display->getMessageCount() > 0) {
47 | $this->layout->addHtmlHeadEntrySet(
48 | $this->message_display->getHtmlHeadEntrySet()
49 | );
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Site/SiteArticlePath.php:
--------------------------------------------------------------------------------
1 | loadFromId($app, $id);
20 | }
21 | }
22 |
23 | /**
24 | * Creates a new path object.
25 | *
26 | * @param int $article_id
27 | */
28 | public function loadFromId(SiteWebApplication $app, $article_id)
29 | {
30 | foreach ($this->queryPath($app, $article_id) as $row) {
31 | $this->addEntry(new SitePathEntry(
32 | $row->id,
33 | $row->parent,
34 | $row->shortname,
35 | $row->title
36 | ));
37 | }
38 | }
39 |
40 | protected function queryPath($app, $article_id)
41 | {
42 | return SwatDB::executeStoredProc(
43 | $app->db,
44 | 'getArticlePathInfo',
45 | $article_id
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Site/admin/components/Ad/Index.php:
--------------------------------------------------------------------------------
1 | ui->loadFromXML($this->getUiXml());
17 | }
18 |
19 | protected function getUiXml()
20 | {
21 | return __DIR__ . '/index.xml';
22 | }
23 |
24 | // process phase
25 |
26 | protected function processActions(SwatView $view, SwatActions $actions)
27 | {
28 | $num = count($view->getSelection());
29 |
30 | switch ($actions->selected->id) {
31 | case 'delete':
32 | $this->app->replacePage('Ad/Delete');
33 | $this->app->getPage()->setItems($view->getSelection());
34 | break;
35 | }
36 | }
37 |
38 | // build phase
39 |
40 | protected function getTableModel(SwatView $view): ?SwatTableModel
41 | {
42 | $sql = sprintf(
43 | 'select * from Ad
44 | order by %s',
45 | $this->getOrderByClause($view, 'createdate desc')
46 | );
47 |
48 | return SwatDB::query(
49 | $this->app->db,
50 | $sql,
51 | SwatDBClassMap::get(SiteAdWrapper::class)
52 | );
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Site/pages/SiteXmlSiteMapIndexPage.php:
--------------------------------------------------------------------------------
1 | setLayout(new SiteXmlSiteMapLayout($this->app));
17 | }
18 |
19 | public function build()
20 | {
21 | $this->layout->startCapture('site_map');
22 |
23 | echo '';
24 | $this->displaySiteMapIndex();
25 | echo '';
26 |
27 | $this->layout->endCapture();
28 | }
29 |
30 | protected function displayIndex($path, ?SwatDate $last_modified = null)
31 | {
32 | echo "\n";
33 |
34 | printf(
35 | "%s\n",
36 | htmlspecialchars($this->app->getBaseHref() . $path)
37 | );
38 |
39 | if ($last_modified !== null) {
40 | printf(
41 | "%s\n",
42 | $last_modified->getISO8601()
43 | );
44 | }
45 |
46 | echo "\n";
47 | }
48 |
49 | abstract protected function displaySiteMapIndex();
50 | }
51 |
--------------------------------------------------------------------------------
/Site/SiteLayoutData.php:
--------------------------------------------------------------------------------
1 | display($this);
17 | }
18 |
19 | /**
20 | * @deprecated use the isset() function on this class instead
21 | *
22 | * @param mixed $name
23 | */
24 | public function exists($name)
25 | {
26 | return isset($this->{$name});
27 | }
28 |
29 | public function __isset($name)
30 | {
31 | return isset($this->_properties[$name]);
32 | }
33 |
34 | /**
35 | * @param mixed $name
36 | *
37 | * @throws SiteInvalidPropertyException
38 | */
39 | public function __get($name)
40 | {
41 | if (!isset($this->_properties[$name])) {
42 | throw new SiteInvalidPropertyException(
43 | "There is no content available for '{$name}'.",
44 | 0,
45 | $this,
46 | $name
47 | );
48 | }
49 |
50 | return $this->_properties[$name];
51 | }
52 |
53 | public function __set($name, $content)
54 | {
55 | $this->_properties[$name] = $content;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/po/Makefile:
--------------------------------------------------------------------------------
1 | ##
2 | ## i18n Makefile
3 | ##
4 |
5 | DOMAIN = site
6 | XGETTEXT = xgettext --from-code=UTF-8
7 | MSGFMT = msgfmt -c
8 | MSGMERGE = msgmerge --no-fuzzy-matching
9 | MSGUNIQ = msguniq
10 | INSTALL = install
11 | INSTALLDIR = mkdir -p
12 | DATA_MODE = 660
13 |
14 | TRANSLATIONS := en_CA en_US en_GB de_DE
15 | MO_FILES := $(patsubst %,%.mo, $(TRANSLATIONS))
16 |
17 | POTFILE = $(DOMAIN).pot
18 |
19 | TARGETS = $(MO_FILES)
20 |
21 | LOCALEDIR = ../locale
22 |
23 | ######################################
24 |
25 | all:
26 | make $(TARGETS)
27 |
28 | potfiles:
29 | rm -f $@-t1 $@-t2 $@
30 | (sed -e '/^#/d' < potfiles.in) > $@-t1
31 | (for i in `cat $@-t1`; do find $$i -name \*.php; done) >> $@-t2
32 | (for i in `cat $@-t2`; do php preprocess.php $$i > $$i.gettext; echo $$i.gettext; done) >> $@
33 | rm -f $@-t1 $@-t2
34 |
35 | pot: $(POTFILE)
36 |
37 | $(POTFILE): potfiles
38 | $(XGETTEXT) -o $(POTFILE) -L Php -f potfiles
39 | $(MSGUNIQ) -o $(POTFILE) $(POTFILE)
40 | for i in `cat potfiles`; do rm -f $$i; done
41 | rm -f potfiles
42 |
43 | %.mo: %.po
44 | $(MSGFMT) -o $@ $<
45 |
46 | install:
47 | for i in $(TRANSLATIONS); do \
48 | $(INSTALLDIR) $(LOCALEDIR)/$$i/LC_MESSAGES ; \
49 | $(INSTALL) -m $(DATA_MODE) $$i.mo $(LOCALEDIR)/$$i/LC_MESSAGES/$(DOMAIN).mo ; \
50 | done
51 |
52 | update: pot
53 | for i in $(TRANSLATIONS); do \
54 | $(MSGMERGE) -U $$i.po $(POTFILE); \
55 | done
56 |
57 | clean:
58 | rm -f potfiles *.mo *.pot
59 |
--------------------------------------------------------------------------------
/Site/SiteFulltextSearchResult.php:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {$data->html_head_entries}
22 | {$data->html_title}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
{$data->title}
32 | {$data->content}
33 |
34 |
35 |
36 |
37 |
38 | HTML;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Site/SiteSearchIndexer.php:
--------------------------------------------------------------------------------
1 | SiteCommandLineConfigModule::class,
31 | 'database' => SiteDatabaseModule::class,
32 | ]
33 | );
34 | }
35 |
36 | /**
37 | * Configures modules of this application before they are initialized.
38 | *
39 | * @param SiteConfigModule $config the config module of this application to
40 | * use for configuration other modules
41 | */
42 | protected function configure(SiteConfigModule $config)
43 | {
44 | parent::configure($config);
45 | $this->database->dsn = $config->database->dsn;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteMediaCdnTaskWrapper.php:
--------------------------------------------------------------------------------
1 | getOption('lazy_load')) {
23 | $this->loadAllSubDataObjects(
24 | 'media',
25 | $this->db,
26 | 'select * from Media where id in (%s)',
27 | SwatDBClassMap::get(SiteMediaWrapper::class)
28 | );
29 |
30 | $this->loadAllSubDataObjects(
31 | 'encoding',
32 | $this->db,
33 | 'select * from MediaEncoding where id in (%s)',
34 | SwatDBClassMap::get(SiteMediaEncodingWrapper::class)
35 | );
36 | }
37 | }
38 |
39 | protected function init()
40 | {
41 | parent::init();
42 | $this->row_wrapper_class = SwatDBClassMap::get(SiteMediaCdnTask::class);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/sql/pgsql/functions/getArticleNavBar.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Returns navbar information from an article.
3 | *
4 | * @param_parent INTEGER: the id of the article to search from.
5 | *
6 | * @returned_row type_article_navbar: a row containing id, shortname and title
7 | *
8 | * Returns a set of returned_rows ordered correctly to go in the navbar.
9 | * Checking if the parent articles are enabled is left up to sp_article_find.
10 | * If the article is not found, returns an empty recordset.
11 | *
12 | * This procedure uses recursion to output entries in the correct order for
13 | * applications.
14 | */
15 | CREATE TYPE type_article_navbar AS (id INTEGER, parent INTEGER, shortname VARCHAR(255), title VARCHAR(255));
16 |
17 | CREATE OR REPLACE FUNCTION getArticleNavBar(INTEGER) RETURNS SETOF type_article_navbar AS $$
18 | DECLARE
19 | param_id ALIAS FOR $1;
20 | local_found BOOLEAN;
21 | returned_row type_article_navbar%ROWTYPE;
22 | parent_row type_article_navbar%ROWTYPE;
23 | BEGIN
24 | -- get current article results
25 | SELECT INTO returned_row id, parent, shortname, title
26 | FROM Article
27 | WHERE id = param_id;
28 |
29 | local_found := FOUND;
30 |
31 | -- get parent article results
32 | IF returned_row.parent IS NOT NULL THEN
33 | FOR parent_row IN SELECT * FROM getArticleNavBar(returned_row.parent) LOOP
34 | RETURN NEXT parent_row;
35 | END LOOP;
36 | END IF;
37 |
38 | IF local_found THEN
39 | RETURN NEXT returned_row;
40 | END IF;
41 |
42 | RETURN;
43 | END;
44 | $$ LANGUAGE 'plpgsql';
45 |
--------------------------------------------------------------------------------
/Site/admin/components/Account/search.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Search Accounts
7 |
8 |
9 | Add an Account
10 | Account/Edit
11 | create
12 |
13 |
14 |
15 |
16 | Name
17 |
18 |
19 |
20 | Email Address
21 |
22 |
23 |
24 | Instance
25 | false
26 |
27 |
28 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteMediaSetWrapper.php:
--------------------------------------------------------------------------------
1 | getOption('lazy_load')) {
23 | $this->loadAllSubRecordsets(
24 | 'encodings',
25 | $this->getMediaEncodingWrapperClass(),
26 | 'MediaEncoding',
27 | 'media_set',
28 | '',
29 | $this->getMediaEncodingOrderBy()
30 | );
31 | }
32 | }
33 |
34 | protected function getMediaEncodingWrapperClass()
35 | {
36 | return SwatDBClassMap::get(SiteMediaEncodingWrapper::class);
37 | }
38 |
39 | protected function getMediaEncodingOrderBy()
40 | {
41 | return 'media_set';
42 | }
43 |
44 | protected function init()
45 | {
46 | parent::init();
47 |
48 | $this->row_wrapper_class =
49 | SwatDBClassMap::get(SiteMediaSet::class);
50 |
51 | $this->index_field = 'id';
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Site/SiteArticleSearchEngine.php:
--------------------------------------------------------------------------------
1 | fulltext_result !== null) {
26 | $clause .= ' ' .
27 | $this->fulltext_result->getJoinClause(
28 | 'Article.id',
29 | 'article'
30 | );
31 | }
32 |
33 | return $clause;
34 | }
35 |
36 | protected function getWhereClause()
37 | {
38 | return sprintf(
39 | 'where Article.searchable = %s',
40 | $this->app->db->quote(true, 'boolean')
41 | );
42 | }
43 |
44 | protected function getOrderByClause()
45 | {
46 | if ($this->fulltext_result === null) {
47 | $clause = sprintf('order by Article.title');
48 | } else {
49 | $clause =
50 | $this->fulltext_result->getOrderByClause('Article.title');
51 | }
52 |
53 | return $clause;
54 | }
55 |
56 | protected function getMemcacheNs()
57 | {
58 | return 'article';
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Site/pages/SiteDBEditPage.php:
--------------------------------------------------------------------------------
1 | app->db);
16 |
17 | try {
18 | $this->saveData($form);
19 | $transaction->commit();
20 | } catch (SwatDBException $e) {
21 | if ($this->app->hasModule('SiteMessagesModule')) {
22 | $messages = $this->app->getModule('SiteMessagesModule');
23 | $messages->add($this->getRollbackMessage($form));
24 | }
25 | $transaction->rollback();
26 | $this->handleDBException($e);
27 | } catch (Throwable $e) {
28 | $this->handleException($transaction, $e);
29 | }
30 | }
31 |
32 | abstract protected function saveData(SwatForm $form);
33 |
34 | protected function getRollbackMessage(SwatForm $form)
35 | {
36 | return new SwatMessage(
37 | Site::_('An error has occurred. The item was not saved.'),
38 | 'system-error'
39 | );
40 | }
41 |
42 | protected function handleDBException(SwatDBException $e)
43 | {
44 | $e->processAndContinue();
45 | }
46 |
47 | protected function handleException(
48 | SwatDBTransaction $transaction,
49 | Throwable $e
50 | ) {
51 | throw $e;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/www/styles/site-content-slider.css:
--------------------------------------------------------------------------------
1 | .site-content-slider {
2 | position: relative;
3 | overflow: hidden;
4 | }
5 |
6 | .site-content-slider .slider-next-prev,
7 | .site-content-slider .slider-nav {
8 | position: absolute;
9 | bottom: 10px;
10 | width: 100%;
11 | text-align: center;
12 | }
13 |
14 | .site-content-slider .slider-next-prev span,
15 | .site-content-slider .slider-next-prev a {
16 | text-decoration: none;
17 | color: #fff;
18 | margin: 0 5px;
19 | }
20 |
21 | .site-content-slider .slider-next-prev a:hover {
22 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4);
23 | }
24 |
25 | .site-content-slider .slider-next-prev span {
26 | opacity: 0.3;
27 | filter: alpha(opacity=30);
28 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
29 | }
30 |
31 | .site-content-slider .slider-nav a {
32 | width: 20px;
33 | height: 20px;
34 | display: inline-block;
35 | }
36 |
37 | .site-content-slider .slider-nav a span {
38 | display: inline-block;
39 | width: 8px;
40 | height: 8px;
41 | margin: 6px;
42 | background: #fff;
43 | border-radius: 50%;
44 | border: 1px solid #999;
45 | opacity: 0.5;
46 | filter: alpha(opacity=50);
47 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
48 | }
49 |
50 | .site-content-slider .slider-nav a:hover span {
51 | opacity: 1;
52 | filter: alpha(opacity=100);
53 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
54 | }
55 |
56 | .site-content-slider .slider-nav a.selected span {
57 | opacity: 1;
58 | filter: alpha(opacity=100);
59 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
60 | border: 1px solid #666;
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/sql/mysql/functions/findArticle.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Finds an article in the article tree.
3 | *
4 | * @param_source VARCHAR(255): a string containing the path to the article delimited by forward slashes.
5 | *
6 | * Returns an integer containing the id of the searched for article.
7 | * If the article is not found, returns NULL.
8 | */
9 | CREATE FUNCTION findArticle (param_source VARCHAR(255)) RETURNS INTEGER
10 | BEGIN
11 | DECLARE local_source VARCHAR(255);
12 | DECLARE local_shortname VARCHAR(255);
13 | DECLARE local_parent INTEGER;
14 | DECLARE local_pos INTEGER;
15 | DECLARE local_id INTEGER;
16 |
17 | -- Find the first forward slash in the source string.
18 | SET local_source = CONCAT(param_source, '/');
19 | SET local_pos = POSITION('/' IN local_source);
20 |
21 | SET local_id = NULL;
22 |
23 | WHILE local_pos != 0 DO
24 | BEGIN
25 | -- Get shortname from beginning of source string.
26 | SET local_shortname = SUBSTRING(local_source FROM 1 FOR (local_pos - 1));
27 | -- Get the remainder of the source string.
28 | SET local_source = SUBSTRING(local_source FROM local_pos + 1 FOR character_length(local_source) - local_pos);
29 |
30 | -- Get the id of the parent
31 | SELECT id INTO local_id
32 | FROM Article
33 | WHERE (Article.parent = local_id OR (local_id is null AND parent is null))
34 | AND shortname = local_shortname
35 | AND id != 0;
36 |
37 | IF local_id IS NULL THEN
38 | RETURN NULL;
39 | END IF;
40 |
41 | -- Find next forward slash in the source string.
42 | SET local_pos = POSITION('/' IN local_source);
43 | END;
44 | END WHILE;
45 |
46 | RETURN local_id;
47 | END;
48 |
--------------------------------------------------------------------------------
/sql/pgsql/functions/findArticle.sql:
--------------------------------------------------------------------------------
1 | /*
2 | * Finds an article in the article tree.
3 | *
4 | * @param_source VARCHAR(255): a string containing the path to the article delimited by forward slashes.
5 | *
6 | * Returns an integer containing the id of the searched for article.
7 | * If the article is not found, returns NULL.
8 | */
9 | CREATE OR REPLACE FUNCTION findArticle (VARCHAR(255)) RETURNS INTEGER AS $$
10 | DECLARE
11 | param_source ALIAS FOR $1;
12 | local_source VARCHAR(255);
13 | local_shortname VARCHAR(255);
14 | local_parent INTEGER;
15 | local_pos INTEGER;
16 | local_id INTEGER;
17 | BEGIN
18 | -- Find the first forward slash in the source string.
19 | local_source := param_source || '/';
20 | local_pos := POSITION('/' IN local_source);
21 |
22 | local_id := NULL;
23 |
24 | WHILE local_pos != 0 LOOP
25 | BEGIN
26 | -- Get shortname from beginning of source string.
27 | local_shortname := SUBSTRING(local_source FROM 0 FOR local_pos);
28 | -- Get the remainder of the source string.
29 | local_source := SUBSTRING(local_source FROM local_pos + 1 FOR character_length(local_source) - local_pos + 1);
30 |
31 | -- Get the id of the parent
32 | SELECT INTO local_id id
33 | FROM Article
34 | WHERE (Article.parent = local_id OR (local_id is null AND parent is null))
35 | AND shortname = local_shortname
36 | AND id != 0;
37 |
38 | IF local_id is null THEN
39 | RETURN null;
40 | END IF;
41 |
42 | -- Find next forward slash in the source string.
43 | local_pos := POSITION('/' IN local_source);
44 | END;
45 | END LOOP;
46 |
47 | RETURN local_id;
48 | END;
49 | $$ LANGUAGE 'plpgsql';
50 |
--------------------------------------------------------------------------------
/Site/admin/components/Comment/index.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Filter Comments
7 |
8 |
9 | Keywords
10 |
11 |
12 |
13 | Author
14 |
15 |
16 |
17 | Show
18 |
19 |
20 |
25 |
26 |
27 |
28 | Manage Comments
29 |
30 |
31 |
32 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Site/pages/contact.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Send us a Message
8 |
9 | Send To
10 |
11 |
12 |
13 | Your Email
14 |
15 | true
16 |
17 |
18 |
19 | Subject
20 |
21 | true
22 | false
23 |
24 |
25 |
26 | Message
27 |
28 | true
29 |
30 |
31 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Site/SitePathEntry.php:
--------------------------------------------------------------------------------
1 | id = $id;
61 | $this->parent = $parent;
62 | $this->shortname = $shortname;
63 | $this->title = $title;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteImageType.php:
--------------------------------------------------------------------------------
1 | checkDB();
46 |
47 | $found = false;
48 |
49 | $sql = 'select * from %s where lower(mime_type) = lower(%s)';
50 |
51 | $sql = sprintf(
52 | $sql,
53 | $this->table,
54 | $this->db->quote($mime_type, 'text')
55 | );
56 |
57 | $row = SwatDB::queryRow($this->db, $sql);
58 |
59 | if ($row !== null) {
60 | $this->initFromRow($row);
61 | $this->generatePropertyHashes();
62 | $found = true;
63 | }
64 |
65 | return $found;
66 | }
67 |
68 | protected function init()
69 | {
70 | $this->table = 'ImageType';
71 | $this->id_field = 'integer:id';
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Site/dataobjects/SiteAttachmentSet.php:
--------------------------------------------------------------------------------
1 | checkDB();
51 |
52 | $found = false;
53 |
54 | $sql = 'select * from %s where shortname = %s';
55 |
56 | $sql = sprintf(
57 | $sql,
58 | $this->table,
59 | $this->db->quote($shortname, 'text')
60 | );
61 |
62 | $row = SwatDB::queryRow($this->db, $sql);
63 |
64 | if ($row !== null) {
65 | $this->initFromRow($row);
66 | $this->generatePropertyHashes();
67 | $found = true;
68 | }
69 |
70 | return $found;
71 | }
72 |
73 | protected function init()
74 | {
75 | $this->table = 'AttachmentSet';
76 | $this->id_field = 'integer:id';
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Site/pages/SiteXMLRPCServer.php:
--------------------------------------------------------------------------------
1 | 'utf-8',
30 | 'input' => 'XML_RPC2_Server_Input_PhpInput',
31 | // Explicitly select the PHP backend. The native backend has
32 | // trouble with UTF-8 encoding and with properly parsing
33 | // method parameters.
34 | 'backend' => 'Php',
35 | ]);
36 |
37 | $this->layout->startCapture('response');
38 | $server->handleCall();
39 | $this->layout->endCapture();
40 | }
41 |
42 | /**
43 | * @xmlrpc.hidden
44 | */
45 | public function __toString(): string
46 | {
47 | return parent::__toString();
48 | }
49 |
50 | /**
51 | * @xmlrpc.hidden
52 | */
53 | protected function createLayout()
54 | {
55 | return new SiteXMLRPCServerLayout($this->app);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Site/admin/components/Account/details.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Edit Account
9 | Account/Edit?id=%s
10 | edit
11 |
12 |
13 | Email New Password
14 | Account/EmailPassword?id=%s
15 | email
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Name
24 |
25 | fullname
26 |
27 |
28 |
29 | Email
30 |
31 | email
32 |
33 |
34 |
35 | Created On
36 |
37 | createdate
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Site/exceptions/SiteInvalidPropertyException.php:
--------------------------------------------------------------------------------
1 | object = $object;
41 | $this->property = $property;
42 | }
43 |
44 | /**
45 | * Gets the object the property is invalid for.
46 | *
47 | * @return mixed the object the property is invalid for
48 | */
49 | public function getObject()
50 | {
51 | return $this->object;
52 | }
53 |
54 | /**
55 | * Gets the name of the property that is invalid.
56 | *
57 | * @return string the name of the property that is invalid
58 | */
59 | public function getProperty()
60 | {
61 | return $this->property;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Site/pages/SiteSearchPage.php:
--------------------------------------------------------------------------------
1 | form_ui = new SwatUI();
31 | $this->form_ui->loadFromXML($this->form_ui_xml);
32 |
33 | $form = $this->form_ui->getWidget('search_form');
34 | $form->action = $this->source;
35 |
36 | $this->form_ui->init();
37 | }
38 |
39 | // process phase
40 |
41 | public function process()
42 | {
43 | parent::process();
44 |
45 | $this->form_ui->process();
46 |
47 | /*
48 | * Nothing else to do...
49 | * the parent class result page is driven by the GET variables this
50 | * form provided.
51 | */
52 | }
53 |
54 | // build phase
55 |
56 | public function build()
57 | {
58 | $this->layout->startCapture('content');
59 | $this->form_ui->display();
60 | $this->layout->endCapture();
61 |
62 | parent::build();
63 | }
64 |
65 | // finalize phase
66 |
67 | public function finalize()
68 | {
69 | parent::finalize();
70 | $this->layout->addHtmlHeadEntrySet(
71 | $this->form_ui->getRoot()->getHtmlHeadEntrySet()
72 | );
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Site/SiteCdnModule.php:
--------------------------------------------------------------------------------
1 | app = $app;
30 | $this->layout = $layout ?? $this->createLayout();
31 | $this->arguments = $arguments;
32 | }
33 |
34 | protected function createLayout()
35 | {
36 | return new SiteLayout($this->app, SiteDefaultTemplate::class);
37 | }
38 |
39 | // build phase
40 |
41 | public function build()
42 | {
43 | $this->buildTitle();
44 | $this->buildMetaDescription();
45 |
46 | if (isset($this->layout->navbar)) {
47 | $this->buildNavBar();
48 | }
49 |
50 | $this->buildContent();
51 | }
52 |
53 | protected function buildTitle() {}
54 |
55 | protected function buildMetaDescription() {}
56 |
57 | protected function buildContent() {}
58 |
59 | protected function buildNavBar() {}
60 | }
61 |
--------------------------------------------------------------------------------
/Site/pages/SiteXhtmlExceptionPage.php:
--------------------------------------------------------------------------------
1 | layout->data->title = $this->getTitle();
16 | }
17 |
18 | protected function buildContent()
19 | {
20 | $this->layout->startCapture('content');
21 | $this->display();
22 | $this->layout->endCapture();
23 | }
24 |
25 | protected function buildNavBar()
26 | {
27 | if (isset($this->layout->navbar)) {
28 | $this->layout->navbar->createEntry($this->getTitle());
29 | }
30 | }
31 |
32 | protected function display()
33 | {
34 | printf('%s
', $this->getSummary());
35 |
36 | $this->displaySuggestions();
37 |
38 | if ($this->exception instanceof SwatException
39 | && !($this->exception instanceof SiteNotAuthorizedException)) {
40 | $this->exception->processAndContinue();
41 | }
42 | }
43 |
44 | protected function displaySuggestions()
45 | {
46 | $suggestions = $this->getSuggestions();
47 |
48 | if (count($suggestions) == 0) {
49 | return;
50 | }
51 |
52 | echo '';
53 | $li_tag = new SwatHtmlTag('li');
54 |
55 | foreach ($suggestions as $suggestion) {
56 | $li_tag->setContent($suggestion, 'text/xml');
57 | $li_tag->display();
58 | }
59 |
60 | echo '
';
61 | }
62 |
63 | // finalize phase
64 |
65 | public function finalize()
66 | {
67 | parent::finalize();
68 | $this->layout->addBodyClass('exception-page');
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/dependencies/site.yaml:
--------------------------------------------------------------------------------
1 | ##
2 | ## Static Web-resource dependencies for the Site package
3 | ##
4 | ## Copyright (c) 2010 silverorange
5 | ##
6 | ## This library is free software; you can redistribute it and/or modify
7 | ## it under the terms of the GNU Lesser General Public License as
8 | ## published by the Free Software Foundation; either version 2.1 of the
9 | ## License, or (at your option) any later version.
10 | ##
11 | ## This library is distributed in the hope that it will be useful,
12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | ## Lesser General Public License for more details.
15 | ##
16 | ## You should have received a copy of the GNU Lesser General Public
17 | ## License along with this library; if not, write to the Free Software
18 | ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 | ##
20 | Site:
21 | Depends:
22 | # Package Dependencies
23 | - Swat
24 | - XML_RPCAjax
25 |
26 | Provides:
27 |
28 | # JavaScript resources
29 | packages/site/javascript/site-gravatar-entry.js:
30 | packages/site/javascript/site-tag-entry.js:
31 | packages/site/javascript/site-upload-progress-bar.js:
32 | packages/site/javascript/site-content-slider.js:
33 | packages/site/admin/javascript/site-comment-display.js:
34 | packages/site/admin/javascript/site-comment-status-slider.js:
35 |
36 | # Style-sheet resources
37 | packages/site/styles/site-account-login-page.css:
38 | packages/site/styles/site-account-reset-password-page.css:
39 | packages/site/styles/site-contact-page.css:
40 | packages/site/styles/site-image-cell-renderer.css:
41 | packages/site/styles/site-search-results-page.css:
42 | packages/site/styles/site-tag-entry.css:
43 | packages/site/styles/site-content-slider.css:
44 | packages/site/admin/styles/site-comment-display.css:
45 | packages/site/admin/styles/site-comment-status-slider.css:
46 |
--------------------------------------------------------------------------------
/Site/admin/components/Comment/edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Comment
7 |
8 |
9 | Name
10 |
11 | 255
12 | true
13 |
14 |
15 |
16 | Website
17 |
18 | 255
19 |
20 |
21 |
22 | Email
23 |
24 | 255
25 |
26 |
27 |
28 | Comment
29 |
30 | true
31 | 15
32 |
33 |
34 |
35 | Status
36 |
37 | false
38 |
39 |
40 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Site/SiteTimerCheckpoint.php:
--------------------------------------------------------------------------------
1 | name = $name;
43 | $this->time = $time;
44 | $this->memory_usage = $memory_usage;
45 | }
46 |
47 | /**
48 | * Gets the time when this checkpoint was created.
49 | *
50 | * @return float the time when this checkpoint was created
51 | */
52 | public function getTime()
53 | {
54 | return $this->time;
55 | }
56 |
57 | /**
58 | * Gets the name of this checkpoint.
59 | *
60 | * return string the name of this checkpoint.
61 | */
62 | public function getName()
63 | {
64 | return $this->name;
65 | }
66 |
67 | /**
68 | * Gets the memory use of this checkpoint.
69 | *
70 | * return string the memory use of this checkpoint.
71 | */
72 | public function getMemoryUsage()
73 | {
74 | return $this->memory_usage;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/sql/fixtures/SiteBotrMediaEncoding.sql:
--------------------------------------------------------------------------------
1 | insert into MediaEncoding (
2 | media_set,
3 | default_type,
4 | title,
5 | shortname,
6 | default_encoding,
7 | width
8 | ) values (
9 | (select id from MediaSet where shortname = 'public'),
10 | (select id from MediaType where mime_type = 'video/mp4'),
11 | '1920-wide (1080p)',
12 | '1920',
13 | true,
14 | 1920
15 | );
16 |
17 | insert into MediaEncoding (
18 | media_set,
19 | default_type,
20 | title,
21 | shortname,
22 | default_encoding,
23 | width
24 | ) values (
25 | (select id from MediaSet where shortname = 'public'),
26 | (select id from MediaType where mime_type = 'video/mp4'),
27 | '1280-wide (720p)',
28 | '1280',
29 | true,
30 | 1280
31 | );
32 |
33 | insert into MediaEncoding (
34 | media_set,
35 | default_type,
36 | title,
37 | shortname,
38 | default_encoding,
39 | width
40 | ) values (
41 | (select id from MediaSet where shortname = 'public'),
42 | (select id from MediaType where mime_type = 'video/mp4'),
43 | '1080-wide',
44 | '1080',
45 | true,
46 | 1080
47 | );
48 |
49 | insert into MediaEncoding (
50 | media_set,
51 | default_type,
52 | title,
53 | shortname,
54 | default_encoding,
55 | width
56 | ) values (
57 | (select id from MediaSet where shortname = 'public'),
58 | (select id from MediaType where mime_type = 'video/mp4'),
59 | '720-wide',
60 | '720',
61 | true,
62 | 720
63 | );
64 |
65 | insert into MediaEncoding (
66 | media_set,
67 | default_type,
68 | title,
69 | shortname,
70 | default_encoding,
71 | width
72 | ) values (
73 | (select id from MediaSet where shortname = 'public'),
74 | (select id from MediaType where mime_type = 'video/mp4'),
75 | '480-wide',
76 | '480',
77 | true,
78 | 480
79 | );
80 |
81 | insert into MediaEncoding (
82 | media_set,
83 | default_type,
84 | title,
85 | shortname,
86 | default_encoding,
87 | width
88 | ) values (
89 | (select id from MediaSet where shortname = 'public'),
90 | (select id from MediaType where mime_type = 'video/mp4'),
91 | '320-wide (QVGA)',
92 | '320',
93 | true,
94 | 320
95 | );
96 |
--------------------------------------------------------------------------------
/Site/SiteVideoMediaLocalMover.php:
--------------------------------------------------------------------------------
1 | file_base = $file_base;
20 | }
21 |
22 | public function getFileBase()
23 | {
24 | if ($this->file_base === null) {
25 | throw new SiteException('File base has not been set.');
26 | }
27 |
28 | return $this->file_base;
29 | }
30 |
31 | protected function getOldPath(SiteVideoMedia $media, $shortname)
32 | {
33 | return sprintf(
34 | '%s/%s/%s/%s',
35 | $this->getFileBase(),
36 | $media->media_set->shortname,
37 | $shortname,
38 | $this->getOldFilename($media, $shortname)
39 | );
40 | }
41 |
42 | protected function getNewPath(SiteVideoMedia $media, $shortname)
43 | {
44 | return sprintf(
45 | '%s/%s/full/%s',
46 | $this->getFileBase(),
47 | $media->id,
48 | $this->getNewFilename($media, $shortname)
49 | );
50 | }
51 |
52 | protected function hasFile($path)
53 | {
54 | return is_file($path);
55 | }
56 |
57 | protected function moveFile(SiteVideoMedia $media, $old_path, $new_path)
58 | {
59 | $parts = pathinfo($new_path);
60 | $directory = $parts['dirname'];
61 |
62 | if (!file_exists($directory)) {
63 | mkdir($directory, 0o777, true);
64 | }
65 |
66 | copy($old_path, $new_path);
67 | }
68 |
69 | protected function cleanUp($path)
70 | {
71 | if (file_exists($path)) {
72 | unlink($path);
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Site/admin/components/Account/suspicious.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Suspicious Accounts
6 |
7 | A suspicious account has 5 or more logins in the last week, from 5 or more locations, and 5 or more different web browsers.
8 |
9 |
10 |
11 |
12 | Name
13 |
14 | fullname
15 | Account/Details?id=%s
16 | id
17 | person
18 |
19 |
20 |
21 | Email
22 |
23 | email
24 |
25 |
26 |
27 | Instance
28 | false
29 |
30 | instance.title
31 |
32 |
33 |
34 |
35 | details
36 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Site/admin/components/Ad/details.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Ad Details
7 |
8 |
9 | Delete Ad
10 | Ad/Delete?id=%s
11 | delete
12 |
13 |
14 |
15 |
16 | Referrers in the Last
17 |
18 |
19 |
20 | period
21 |
22 |
23 |
24 | Referrers
25 |
26 | referrers
27 |
28 |
29 |
30 |
31 |
32 | Top HTTP Referers
33 |
34 | <none>
35 |
36 | URI
37 |
38 | uri
39 |
40 |
41 |
42 | Number of Referrrals
43 |
44 | referer_count
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/.php-cs-fixer.php:
--------------------------------------------------------------------------------
1 | in(__DIR__);
9 |
10 | return (new Config())
11 | ->setParallelConfig(ParallelConfigFactory::detect(null, null, 2**18-1))
12 | ->setRules([
13 | '@PhpCsFixer' => true,
14 | '@PHP82Migration' => true,
15 | 'indentation_type' => true,
16 |
17 | // Overrides for (opinionated) @PhpCsFixer and @Symfony rules:
18 |
19 | // Align "=>" in multi-line array definitions, unless a blank line exists between elements
20 | 'binary_operator_spaces' => ['operators' => ['=>' => 'align_single_space_minimal']],
21 |
22 | // Subset of statements that should be proceeded with blank line
23 | 'blank_line_before_statement' => ['statements' => ['case', 'continue', 'declare', 'default', 'return', 'throw', 'try', 'yield', 'yield_from']],
24 |
25 | // Enforce space around concatenation operator
26 | 'concat_space' => ['spacing' => 'one'],
27 |
28 | // Use {} for empty loop bodies
29 | 'empty_loop_body' => ['style' => 'braces'],
30 |
31 | // Don't change any increment/decrement styles
32 | 'increment_style' => false,
33 |
34 | // Forbid multi-line whitespace before the closing semicolon
35 | 'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'],
36 |
37 | // Clean up PHPDocs, but leave @inheritDoc entries alone
38 | 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true, 'remove_inheritdoc' => false],
39 |
40 | // Ensure that traits are listed first in classes
41 | // (it would be nice to enforce more, but we'll start simple)
42 | 'ordered_class_elements' => ['order' => ['use_trait']],
43 |
44 | // Ensure that param and return types are sorted consistently, with null at end
45 | 'phpdoc_types_order' => ['sort_algorithm' => 'alpha', 'null_adjustment' => 'always_last'],
46 |
47 | // Yoda style is too weird
48 | 'yoda_style' => false,
49 | ])
50 | ->setIndent(' ')
51 | ->setLineEnding("\n")
52 | ->setFinder($finder);
53 |
--------------------------------------------------------------------------------
/Site/admin/components/Ad/Delete.php:
--------------------------------------------------------------------------------
1 | getDeleteSql();
18 | $num = SwatDB::exec($this->app->db, $sql);
19 | $message = new SwatMessage(sprintf(
20 | Site::ngettext(
21 | 'One ad has been deleted.',
22 | '%s ads have been deleted.',
23 | $num
24 | ),
25 | SwatString::numberFormat($num)
26 | ), 'notice');
27 |
28 | $this->app->messages->add($message);
29 | }
30 |
31 | protected function getDeleteSql()
32 | {
33 | $item_list = $this->getItemList('integer');
34 |
35 | return sprintf(
36 | 'delete from Ad where id in (%s)',
37 | $item_list
38 | );
39 | }
40 |
41 | // build phase
42 |
43 | protected function buildInternal()
44 | {
45 | parent::buildInternal();
46 |
47 | $dep = $this->getDependencies();
48 |
49 | $message = $this->ui->getWidget('confirmation_message');
50 | $message->content = $dep->getMessage();
51 | $message->content_type = 'text/xml';
52 |
53 | if ($dep->getStatusLevelCount(AdminDependency::DELETE) == 0) {
54 | $this->switchToCancelButton();
55 | }
56 | }
57 |
58 | protected function getDependencies()
59 | {
60 | $item_list = $this->getItemList('integer');
61 |
62 | $dep = new AdminListDependency();
63 | $dep->setTitle(Site::_('ad'), Site::_('ads'));
64 | $dep->entries = AdminListDependency::queryEntries(
65 | $this->app->db,
66 | 'Ad',
67 | 'integer:id',
68 | null,
69 | 'text:title',
70 | 'id',
71 | 'id in (' . $item_list . ')',
72 | AdminDependency::DELETE
73 | );
74 |
75 | return $dep;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Site/admin/components/Account/index.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Accounts
6 | false
7 |
8 |
9 |
10 |
11 |
12 | id
13 |
14 |
15 |
16 | Name
17 |
18 | fullname
19 | Account/Details?id=%s
20 | id
21 | person
22 |
23 |
24 |
25 | Email
26 |
27 | email
28 |
29 |
30 |
31 | Instance
32 | false
33 |
34 | instance.title
35 |
36 |
37 |
38 |
39 |
40 | delete…
41 |
42 |
43 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Site/pages/account-login.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Email Address
9 |
10 | 255
11 | 40
12 | 1
13 |
14 |
15 |
16 | Password
17 |
18 | 255
19 | 2
20 |
21 |
22 | text/xml
23 |
24 |
25 |
31 |
32 |
33 |
34 | Don’t Have an Account?
35 |
36 | Creating an account will make it quicker and easier to order again when you return.]]>
37 | text/xml
38 |
39 |
40 |
41 |
42 | Create an Account
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Site/pages/account-change-password.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Enter Your Current Password
9 | Forgot your current password?]]>
10 | text/xml
11 |
12 | false
13 | 4
14 | 255
15 | true
16 |
17 |
18 |
19 | Choose a New Password
20 |
21 | false
22 | 4
23 | 255
24 | true
25 |
26 |
27 |
28 | Re-type the New Password
29 |
30 | false
31 | 4
32 | 255
33 | true
34 |
35 |
36 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------