Compare commits
10 Commits
v2.1.1-bet
...
v2.1
Author | SHA1 | Date |
---|---|---|
Andy Heathershaw | fa861c0b09 | |
Andy Heathershaw | 0836ca5557 | |
Andy Heathershaw | c029c6ca00 | |
Andy Heathershaw | aa2998ac70 | |
Andy Heathershaw | eedfd5abdd | |
Andy Heathershaw | 9a65e8f1c9 | |
Andy Heathershaw | 9ea1953ada | |
Andy Heathershaw | 8dd31961e7 | |
Andy Heathershaw | c784c623ba | |
Andy Heathershaw | 9064495f1f |
|
@ -70,17 +70,20 @@ class DbHelper
|
|||
->leftJoin('permissions AS group_permissions', 'group_permissions.id', '=', 'album_group_permissions.permission_id')
|
||||
->leftJoin('permissions AS user_permissions', 'user_permissions.id', '=', 'album_user_permissions.permission_id')
|
||||
->leftJoin('user_groups', 'user_groups.group_id', '=', 'album_group_permissions.group_id')
|
||||
->where('albums.user_id', $user->id)
|
||||
->orWhere([
|
||||
['group_permissions.section', 'album'],
|
||||
['group_permissions.description', $permission],
|
||||
['user_groups.user_id', $user->id]
|
||||
])
|
||||
->orWhere([
|
||||
['user_permissions.section', 'album'],
|
||||
['user_permissions.description', $permission],
|
||||
['album_user_permissions.user_id', $user->id]
|
||||
]);
|
||||
->where(function($query) use ($user, $permission)
|
||||
{
|
||||
$query->where('albums.user_id', $user->id)
|
||||
->orWhere([
|
||||
['group_permissions.section', 'album'],
|
||||
['group_permissions.description', $permission],
|
||||
['user_groups.user_id', $user->id]
|
||||
])
|
||||
->orWhere([
|
||||
['user_permissions.section', 'album'],
|
||||
['user_permissions.description', $permission],
|
||||
['album_user_permissions.user_id', $user->id]
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
$parentAlbumID = intval($parentAlbumID);
|
||||
|
|
|
@ -15,6 +15,7 @@ use App\Http\Requests\SaveSettingsRequest;
|
|||
use App\Label;
|
||||
use App\Mail\TestMailConfig;
|
||||
use App\Photo;
|
||||
use App\Services\GiteaService;
|
||||
use App\Services\GithubService;
|
||||
use App\Services\PhotoService;
|
||||
use App\Storage;
|
||||
|
@ -46,18 +47,18 @@ class DefaultController extends Controller
|
|||
{
|
||||
try
|
||||
{
|
||||
$githubService = new GithubService();
|
||||
$releaseInfo = $githubService->checkForLatestRelease();
|
||||
$giteaService = new GiteaService();
|
||||
$releaseInfo = $giteaService->checkForLatestRelease();
|
||||
|
||||
// Convert the publish date so we can re-format it with the user's settings
|
||||
$publishDate = \DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $releaseInfo->published_at);
|
||||
$publishDate = \DateTime::createFromFormat('Y-m-d\TH:i:sP', $releaseInfo->published_at);
|
||||
|
||||
// HTML-ify the body text
|
||||
$body = nl2br($releaseInfo->body);
|
||||
$body = preg_replace('/\*\*(.+)\*\*/', '<b>$1</b>', $body);
|
||||
|
||||
// Remove the "v" from the release name
|
||||
$version = substr($releaseInfo->name, 1);
|
||||
$version = substr($releaseInfo->tag_name, 1);
|
||||
|
||||
// Determine if we can upgrade
|
||||
$canUpgrade = version_compare($version, config('app.version')) > 0;
|
||||
|
|
|
@ -71,14 +71,14 @@ class AlbumController extends Controller
|
|||
else if ($requestedView != 'slideshow')
|
||||
{
|
||||
$photos = $album->photos()
|
||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
||||
->orderBy(DB::raw('COALESCE(taken_at, created_at), name, id'))
|
||||
->paginate(UserConfig::get('items_per_page'));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The slideshow view needs access to all photos, not paged
|
||||
$photos = $album->photos()
|
||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
||||
->orderBy(DB::raw('COALESCE(taken_at, created_at), name, id'))
|
||||
->get();
|
||||
}
|
||||
|
||||
|
|
|
@ -105,14 +105,40 @@ class PhotoController extends Controller
|
|||
// Load the Next/Previous buttons
|
||||
$thisPhotoDate = is_null($photo->taken_at) ? $photo->created_at : $photo->taken_at;
|
||||
|
||||
$previousPhoto = $album->photos()
|
||||
->where(DB::raw('COALESCE(taken_at, created_at)'), '<', $thisPhotoDate)
|
||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'), 'desc')
|
||||
->first();
|
||||
$nextPhoto = $album->photos()
|
||||
->where(DB::raw('COALESCE(taken_at, created_at)'), '>', $thisPhotoDate)
|
||||
->orderBy(DB::raw('COALESCE(taken_at, created_at)'))
|
||||
->first();
|
||||
// I don't like the idea of using a totally raw SQL query, but it's the only sure-fire way to number the rows
|
||||
// so we can get the previous/next photos accurately - and we don't have to load all data for the photo objects
|
||||
$previousPhoto = null;
|
||||
$nextPhoto = null;
|
||||
|
||||
$allAlbumPhotos = DB::select(
|
||||
DB::raw(
|
||||
'SELECT p.id, (@row_number:=@row_number + 1) AS row_number
|
||||
FROM photos p, (SELECT @row_number:=0) AS t
|
||||
WHERE p.album_id = :album_id
|
||||
ORDER BY COALESCE(p.taken_at, p.created_at), p.name, p.id;'
|
||||
),
|
||||
[
|
||||
'album_id' => $album->id
|
||||
]
|
||||
);
|
||||
|
||||
for ($i = 0; $i < count($allAlbumPhotos); $i++)
|
||||
{
|
||||
if ($allAlbumPhotos[$i]->id === $photo->id)
|
||||
{
|
||||
if ($i > 0)
|
||||
{
|
||||
$previousPhoto = Photo::where('id', $allAlbumPhotos[$i - 1]->id)->first();
|
||||
}
|
||||
|
||||
if ($i + 1 < count($allAlbumPhotos))
|
||||
{
|
||||
$nextPhoto = Photo::where('id', $allAlbumPhotos[$i + 1]->id)->first();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Record the visit to the photo
|
||||
if (UserConfig::get('enable_visitor_hits'))
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
class GiteaService
|
||||
{
|
||||
private $cacheFile = null;
|
||||
private $config = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = config('services.gitea');
|
||||
$this->cacheFile = storage_path('app/gitea_cache.txt');
|
||||
}
|
||||
|
||||
public function checkForLatestRelease()
|
||||
{
|
||||
$cacheData = null;
|
||||
|
||||
if ($this->doesCacheExist())
|
||||
{
|
||||
// Get the etag from the cache
|
||||
$cacheData = $this->getCacheData();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lookup and store the version information
|
||||
$statusCode = -1;
|
||||
$result = $this->getLatestReleaseFromGitea($statusCode);
|
||||
|
||||
if ($statusCode == 200)
|
||||
{
|
||||
$releases = json_decode($result[1]);
|
||||
|
||||
$latestRelease = null;
|
||||
foreach ($releases as $release)
|
||||
{
|
||||
if (is_null($latestRelease) || version_compare($release->tag_name, $latestRelease->tag_name) > 0)
|
||||
{
|
||||
$latestRelease = $release;
|
||||
}
|
||||
}
|
||||
|
||||
$cacheData = $this->setCacheData($latestRelease);
|
||||
}
|
||||
}
|
||||
|
||||
// GitHub compatibility
|
||||
$cacheData->html_url = sprintf($this->config['releases_url'], $this->config['repo_owner'], $this->config['repo_name']);
|
||||
|
||||
return $cacheData;
|
||||
}
|
||||
|
||||
private function doesCacheExist()
|
||||
{
|
||||
$exists = file_exists($this->cacheFile);
|
||||
|
||||
if ($exists)
|
||||
{
|
||||
// Check modified time on the file
|
||||
$stat = stat($this->cacheFile);
|
||||
|
||||
$diff = time() - $stat['mtime'];
|
||||
if ($diff > $this->config['cache_time_seconds'])
|
||||
{
|
||||
$exists = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $exists;
|
||||
}
|
||||
|
||||
private function getCacheData()
|
||||
{
|
||||
return json_decode(file_get_contents($this->cacheFile));
|
||||
}
|
||||
|
||||
private function getLatestReleaseFromGitea(&$statusCode)
|
||||
{
|
||||
$httpHeaders = [
|
||||
sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', config('app.version'))
|
||||
];
|
||||
|
||||
if (isset($this->config['api_key']) && !empty($this->config['api_key']))
|
||||
{
|
||||
$httpHeaders[] = sprintf('Authorization: %s', $this->config['api_key']);
|
||||
}
|
||||
|
||||
$apiUrl = sprintf('%s/repos/%s/%s/releases', $this->config['api_url'], $this->config['repo_owner'], $this->config['repo_name']);
|
||||
|
||||
$ch = curl_init($apiUrl);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$result = curl_exec($ch);
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
throw new \Exception(sprintf('Error from Gitea: %s', curl_error($ch)));
|
||||
}
|
||||
|
||||
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
return explode("\r\n\r\n", $result, 2);
|
||||
}
|
||||
|
||||
private function setCacheData($data)
|
||||
{
|
||||
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
return [
|
||||
// Version number of Blue Twilight
|
||||
'version' => '2.1.1-beta',
|
||||
'version' => '2.1.2',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
@ -14,33 +14,15 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'github' => [
|
||||
'latest_release_url' => 'https://api.github.com/repos/pandy06269/blue-twilight/releases/latest'
|
||||
'gitea' => [
|
||||
'api_url' => 'https://apps.andysh.uk/api/v1',
|
||||
'cache_time_seconds' => 3600,
|
||||
'releases_url' => 'https://apps.andysh.uk/%s/%s/releases',
|
||||
'repo_name' => 'blue-twilight',
|
||||
'repo_owner' => 'aheathershaw'
|
||||
],
|
||||
|
||||
'recaptcha' => [
|
||||
'verify_url' => 'https://www.google.com/recaptcha/api/siteverify'
|
||||
]
|
||||
|
||||
/*'mailgun' => [
|
||||
'domain' => env('MAILGUN_DOMAIN'),
|
||||
'secret' => env('MAILGUN_SECRET'),
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'key' => env('SES_KEY'),
|
||||
'secret' => env('SES_SECRET'),
|
||||
'region' => 'us-east-1',
|
||||
],
|
||||
|
||||
'sparkpost' => [
|
||||
'secret' => env('SPARKPOST_SECRET'),
|
||||
],
|
||||
|
||||
'stripe' => [
|
||||
'model' => App\User::class,
|
||||
'key' => env('STRIPE_KEY'),
|
||||
'secret' => env('STRIPE_SECRET'),
|
||||
],*/
|
||||
|
||||
];
|
||||
|
|
|
@ -48,6 +48,9 @@ class BlueTwilightUpdater
|
|||
cd <?php echo $this->baseDirectory; ?>
|
||||
|
||||
php artisan clear-compiled
|
||||
php artisan cache:clear
|
||||
php artisan config:clear
|
||||
php artisan view:clear
|
||||
/path/to/composer.phar install
|
||||
</pre>
|
||||
</body>
|
||||
|
@ -65,6 +68,8 @@ php artisan clear-compiled
|
|||
<?php
|
||||
$steps = [
|
||||
['Removing compiled cache', 'removeCompiledCached'],
|
||||
['Fetching Composer signature', 'fetchComposerSignature'],
|
||||
['Installing Composer', 'installComposer'],
|
||||
['Updating dependencies using Composer', 'runComposer']
|
||||
];
|
||||
|
||||
|
@ -92,6 +97,31 @@ php artisan clear-compiled
|
|||
<?php
|
||||
}
|
||||
|
||||
private function fetchComposerSignature()
|
||||
{
|
||||
if (!boolval(ini_get('allow_url_fopen')))
|
||||
{
|
||||
$this->echoError('allow_url_fopen is disabled so we cannot use Composer');
|
||||
echo '<br/>';
|
||||
$this->echoError('You will need to install the vendor libraries manually - <a href="https://github.com/pandy06269/blue-twilight/wiki/Install-Vendor-libraries-manually" target="_blank">see this page for more details</a>');
|
||||
return false;
|
||||
}
|
||||
|
||||
$signatureUrl = 'https://composer.github.io/installer.sig';
|
||||
$this->composerSignature = trim(file_get_contents($signatureUrl));
|
||||
if (strlen($this->composerSignature) == 0)
|
||||
{
|
||||
$this->echoError(sprintf("Failed downloading the Composer signature from %s", $signatureUrl));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->echoOK($this->composerSignature);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function removeCompiledCached()
|
||||
{
|
||||
ob_start();
|
||||
|
@ -155,6 +185,55 @@ php artisan clear-compiled
|
|||
echo '</span>' . PHP_EOL;
|
||||
}
|
||||
|
||||
private function installComposer()
|
||||
{
|
||||
$rc = -1;
|
||||
|
||||
ob_start();
|
||||
system('php -r "copy(\'https://getcomposer.org/installer\', \'composer-setup.php\');"', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to fetch Composer');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system(sprintf('php -r "if (hash_file(\'SHA384\', \'composer-setup.php\') === \'%s\') { echo \'Installer verified\'; } else { echo \'Installer corrupt\'; unlink(\'composer-setup.php\'); } echo PHP_EOL;"', $this->composerSignature), $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Composer verification failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php composer-setup.php', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to install Composer');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php -r "unlink(\'composer-setup.php\');"', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to remove Composer setup file');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->echoOK();
|
||||
return true;
|
||||
}
|
||||
|
||||
private function runComposer()
|
||||
{
|
||||
ob_start();
|
||||
|
|
|
@ -7,12 +7,12 @@ return [
|
|||
'about' => [
|
||||
'current_version' => 'You are running version',
|
||||
'date_published_label' => 'Release date:',
|
||||
'github_link' => 'Github Project Website',
|
||||
'intro' => 'Blue Twilight is an <a href="https://www.andyheathershaw.uk/software/" target="_blank">App by Andy</a>.',
|
||||
'intro_2' => 'It is made with <i class="fa fa-heart text-red"></i> in the UK by software developer <a href="https://www.andyheathershaw.uk" target="_blank">Andy Heathershaw</a>.',
|
||||
'latest_version_loading' => 'Checking for the latest release on Github...',
|
||||
'intro' => 'Blue Twilight is an <a href="https://andysh.uk/software/" target="_blank">App by Andy</a>.',
|
||||
'intro_2' => 'It is made with <i class="fa fa-heart text-red"></i> in the UK by software developer <a href="https://andysh.uk" target="_blank">Andy Heathershaw</a>.',
|
||||
'latest_version_loading' => 'Checking for the latest release...',
|
||||
'licence_header' => 'Licence',
|
||||
'links_header' => 'Useful Links',
|
||||
'project_website_link' => 'Project Website',
|
||||
'title' => 'About Blue Twilight',
|
||||
'up_to_date' => 'Good job - your installation of Blue Twilight is up-to-date!',
|
||||
'update_available' => 'An update is available to Blue Twilight.',
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">@lang('admin.about.links_header')</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="https://showmy.photos" target="_blank">@lang('admin.about.website_link')</a>
|
||||
<a class="dropdown-item" href="https://www.andyheathershaw.uk/software/blue-twilight-php-photo-gallery/manual/" target="_blank">@lang('admin.about.user_guide_link')</a>
|
||||
<a class="dropdown-item" href="https://github.com/pandy06269/blue-twilight" target="_blank">@lang('admin.about.github_link')</a>
|
||||
<a class="dropdown-item" href="https://andysh.uk/software/blue-twilight-php-photo-gallery/" target="_blank">@lang('admin.about.website_link')</a>
|
||||
<a class="dropdown-item" href="https://andysh.uk/software/blue-twilight-php-photo-gallery/manual/" target="_blank">@lang('admin.about.user_guide_link')</a>
|
||||
<a class="dropdown-item" href="https://apps.andysh.uk/aheathershaw/blue-twilight" target="_blank">@lang('admin.about.project_website_link')</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -21,11 +21,10 @@
|
|||
<p>@lang('admin.statistics_enable_public_intro')</p>
|
||||
<form method="post" action="{{ route('admin.statistics.save') }}">
|
||||
{{ csrf_field() }}
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" name="enable_public_statistics" @if (UserConfig::get('public_statistics')) checked="checked"@endif/>
|
||||
<span class="custom-control-indicator"></span>
|
||||
<span class="custom-control-description">@lang('admin.statistics_enable_public_checkbox')</span>
|
||||
</label><br/>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="enable-public-statistics" name="enable_public_statistics" @if (UserConfig::get('public_statistics')) checked="checked"@endif/>
|
||||
<label class="form-check-label" for="enable-public-statistics">@lang('admin.statistics_enable_public_checkbox')</label>
|
||||
</div><br/>
|
||||
<button class="btn btn-success"><i class="fa fa-floppy-o"></i> @lang('forms.save_action')</button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
<label for="email" class="col-md-4 col-form-label text-md-right">@lang('forms.email_label')</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" autofocus>
|
||||
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" autofocus>
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<div class="form-control-feedback">
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
|
@ -19,10 +19,10 @@
|
|||
<label for="password" class="col-md-4 col-form-label text-md-right">@lang('forms.password_label')</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control" name="password">
|
||||
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password">
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<div class="form-control-feedback">
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
|
@ -33,8 +33,8 @@
|
|||
<div class="col-md-4"><!-- --></div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input class="form-check-input" type="checkbox" name="remember"> @lang('forms.remember_me_label')
|
||||
<input class="form-check-input" type="checkbox" id="remember-me" name="remember">
|
||||
<label class="form-check-label" for="remember-me">@lang('forms.remember_me_label')
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue