Commit f4381606 authored by Simon's avatar Simon

Teams, manager, banner update

parent 24ee767f
......@@ -20,9 +20,9 @@
## Production
- build CSS & JS assets - `C:\web\dev.biuro\ npm run build`
- build new image `docker build -t biuro/web:1.21.3 .` (update version number)
- build new image `docker build -t biuro/web:1.22.0 .` (update version number)
- login to biuro docker account `docker login --username=biuro --password=9Ndtjd2vKsLvGuFOeFq1KdJs`
- push image to docker repository - `docker push biuro/web:1.21.3`
- push image to docker repository - `docker push biuro/web:1.22.0`
## Production
- update biuro/web image version in .env file (staging or www)
......
-----BEGIN CERTIFICATE-----
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
pMcrgLny/ReJqDwV/7+sGUvz1WHffCCLQ2yQ
ZXRzZW5jcnlwdC5vcmcwggEDBgorBgEEAdZ5AgQCBIH0BIHxAO8AdQBc3EOS/uar
RUSxXprUVuYQN/vV+kfcoXOUsl7m9scOygAAAXXf42yUAAAEAwBGMEQCIBrsCh0m
bdKDvttT/yUreoCLw+JCF7yMyYJClWxPVnH1AiBEbhKH/NOUl32vttAoeaups8ri
m+ZTOLefO018Idum+gB2APZclC/RdzAiFFQYCDCUVo7jTRMZM7/fDC8gC8xO8WTj
AAABdd/jbJIAAAQDAEcwRQIgEgL2jXO1eoxSh2HyvvuPpbXsjzPWJtYOB8Lx4cPN
VjYCIQCoOrc6uknDByywNWzPofwT0aIUbh/MCEet4xeBG736gzANBgkqhkiG9w0B
AQsFAAOCAQEAEkLYTaQbDNt4kwMWiqxlpSLDJO1IUlwD/V4b7bnMRktmoZFjIt0S
wyiqQJ13nCryjJEVFwkSD+iN2xyxP82MpPdKLbdwa1knHKAujwmIEP5Gdt8zd7e+
YD8b3YqtkYQcXeEMgHrUidAjSiY622PAtiAqfqt/qM4mpiGY0AOJLg0qgb3ffCSa
c5XuLboVrkoNcoG0ScXTXYlugAtxn0770BeDdiLCwmfbQ4x8Y7HRvjpQG2e9lNcs
l3ULnvfeVohmGTUlzANYh36PLMoTGN0mBvSNs3Z0lFPuse2q6k+YgRIMRc7Oozd1
KbZysJkH2sLUYaVKpDEnZYmvvX+kgHcsZA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
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
pMcrgLny/ReJqDwV/7+sGUvz1WHffCCLQ2yQ
ZXRzZW5jcnlwdC5vcmcwggEDBgorBgEEAdZ5AgQCBIH0BIHxAO8AdQBc3EOS/uar
RUSxXprUVuYQN/vV+kfcoXOUsl7m9scOygAAAXXf42yUAAAEAwBGMEQCIBrsCh0m
bdKDvttT/yUreoCLw+JCF7yMyYJClWxPVnH1AiBEbhKH/NOUl32vttAoeaups8ri
m+ZTOLefO018Idum+gB2APZclC/RdzAiFFQYCDCUVo7jTRMZM7/fDC8gC8xO8WTj
AAABdd/jbJIAAAQDAEcwRQIgEgL2jXO1eoxSh2HyvvuPpbXsjzPWJtYOB8Lx4cPN
VjYCIQCoOrc6uknDByywNWzPofwT0aIUbh/MCEet4xeBG736gzANBgkqhkiG9w0B
AQsFAAOCAQEAEkLYTaQbDNt4kwMWiqxlpSLDJO1IUlwD/V4b7bnMRktmoZFjIt0S
wyiqQJ13nCryjJEVFwkSD+iN2xyxP82MpPdKLbdwa1knHKAujwmIEP5Gdt8zd7e+
YD8b3YqtkYQcXeEMgHrUidAjSiY622PAtiAqfqt/qM4mpiGY0AOJLg0qgb3ffCSa
c5XuLboVrkoNcoG0ScXTXYlugAtxn0770BeDdiLCwmfbQ4x8Y7HRvjpQG2e9lNcs
l3ULnvfeVohmGTUlzANYh36PLMoTGN0mBvSNs3Z0lFPuse2q6k+YgRIMRc7Oozd1
KbZysJkH2sLUYaVKpDEnZYmvvX+kgHcsZA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
......
-----BEGIN PRIVATE KEY-----
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
kcu2i7tDetB+D9wL7ks44rVS2P71Eg==
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
fWE3FAKd2Fvh9cF7nEwcMwnkcI8Wkh8=
-----END PRIVATE KEY-----
......@@ -51,7 +51,6 @@ class JsonDataCollector
'member' => [
'slug' => 'manager_id',
'name' => 'manager_name',
'position' => 'manager_position',
'__primary' => true,
],
];
......
......@@ -125,8 +125,8 @@ function getSource($env)
if ($env === 'dev') {
// $inputFile = plugin_dir_path(__FILE__) . "source_data/wp_biuro.php.xml";
// $inputFile = "https://base.biuro.lt/_export/wp_biuro.php";
$inputFile = "https://base.biuro.lt/_devSkirmantas/lt/jobs/AdvertExport/Biuro.php";
// $inputFile = "https://base.biuro.lt/_export/{$script}";
// $inputFile = "https://base.biuro.lt/_devSkirmantas/lt/jobs/AdvertExport/Biuro.php";
$inputFile = "https://base.biuro.lt/_export/{$script}";
} elseif ($env === 'prod') {
// $inputFile = "http://export.biuro.lt/wp_biuro.php";
$inputFile = "http://export.biuro.lt/{$script}";
......
......@@ -4,7 +4,7 @@ Plugin Name: Loco Translate
Plugin URI: https://wordpress.org/plugins/loco-translate/
Description: Translate themes and plugins directly in WordPress
Author: Tim Whitlock
Version: 2.4.4
Version: 2.4.5
Author URI: https://localise.biz/wordpress/plugin
Text Domain: loco-translate
Domain Path: /languages/
......@@ -30,7 +30,7 @@ function loco_plugin_file(){
* @return string
*/
function loco_plugin_version(){
return '2.4.4';
return '2.4.5';
}
......@@ -132,17 +132,17 @@ function loco_require_lib( $path ){
*/
function loco_check_extension( $name ) {
static $cache = array();
if ( ! isset( $cache[$name] ) ) {
if ( extension_loaded($name) ) {
$cache[ $name ] = true;
if( ! array_key_exists($name,$cache) ) {
if( extension_loaded($name) ){
$cache[$name] = true;
}
else {
Loco_error_AdminNotices::warn( sprintf( __('Loco requires the "%s" PHP extension. Ask your hosting provider to install it','loco-translate'), $name ) );
Loco_error_AdminNotices::warn( sprintf( __('Loco Translate requires the "%s" PHP extension. Ask your hosting provider to install it','loco-translate'), $name ) );
$class = 'Loco_compat_'.ucfirst($name).'Extension.php';
$cache[$name] = class_exists($class);
}
}
return $cache[ $name ];
return $cache[$name];
}
......@@ -201,6 +201,12 @@ try {
if ( is_admin() ) {
new Loco_hooks_AdminHooks;
}
// enable wp cli commands
if( class_exists('WP_CLI',false) ) {
WP_CLI::add_command('loco','Loco_cli_Commands');
}
}
catch( Exception $e ){ // PHP5+
trigger_error(sprintf('[Loco.fatal] %s in %s:%u',$e->getMessage(), $e->getFile(), $e->getLine() ),E_USER_NOTICE);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
#loco-admin.wrap .revisions-diff{padding:10px;min-height:20px}#loco-admin.wrap table.diff{border-collapse:collapse}#loco-admin.wrap table.diff td{white-space:nowrap;overflow:hidden;font:normal 12px/17px "Monaco","Menlo","Ubuntu Mono","Consolas","source-code-pro",monospace;padding:2px}#loco-admin.wrap table.diff td>span{color:#aaa}#loco-admin.wrap table.diff td>span:after{content:". "}#loco-admin.wrap table.diff tbody{border-top:1px dashed #ccc}#loco-admin.wrap table.diff tbody:first-child{border-top:none}#loco-admin.wrap .revisions.loading .diff-meta{color:#eee}#loco-admin.wrap .revisions.loading .loading-indicator span.spinner{visibility:visible;background:#fff url(../img/spin-modal.gif?v=2.4.4) center center no-repeat}#loco-admin.wrap .revisions-meta{clear:both;padding:10px 12px;margin:0;position:relative;top:10px}#loco-admin.wrap .revisions-meta .diff-meta{clear:none;float:left;width:50%;padding:0;min-height:auto}#loco-admin.wrap .revisions-meta .diff-meta button{margin-top:5px}#loco-admin.wrap .revisions-meta .diff-meta-current{float:right;text-align:right}#loco-admin.wrap .revisions-meta time{color:#72777c}#loco-admin.wrap .revisions-control-frame{margin:10px 0}#loco-admin.wrap .revisions-diff-frame{margin-top:20px}
\ No newline at end of file
#loco-admin.wrap .revisions-diff{padding:10px;min-height:20px}#loco-admin.wrap table.diff{border-collapse:collapse}#loco-admin.wrap table.diff td{white-space:nowrap;overflow:hidden;font:normal 12px/17px "Monaco","Menlo","Ubuntu Mono","Consolas","source-code-pro",monospace;padding:2px}#loco-admin.wrap table.diff td>span{color:#aaa}#loco-admin.wrap table.diff td>span:after{content:". "}#loco-admin.wrap table.diff tbody{border-top:1px dashed #ccc}#loco-admin.wrap table.diff tbody:first-child{border-top:none}#loco-admin.wrap .revisions.loading .diff-meta{color:#eee}#loco-admin.wrap .revisions.loading .loading-indicator span.spinner{visibility:visible;background:#fff url(../img/spin-modal.gif?v=2.4.5) center center no-repeat}#loco-admin.wrap .revisions-meta{clear:both;padding:10px 12px;margin:0;position:relative;top:10px}#loco-admin.wrap .revisions-meta .diff-meta{clear:none;float:left;width:50%;padding:0;min-height:auto}#loco-admin.wrap .revisions-meta .diff-meta button{margin-top:5px}#loco-admin.wrap .revisions-meta .diff-meta-current{float:right;text-align:right}#loco-admin.wrap .revisions-meta time{color:#72777c}#loco-admin.wrap .revisions-control-frame{margin:10px 0}#loco-admin.wrap .revisions-diff-frame{margin-top:20px}
\ No newline at end of file
.js #loco-admin.wrap .loco-loading{min-height:100px;background:#fff url(../img/spin-modal.gif?v=2.4.4) center center no-repeat}.js #loco-admin.wrap .loco-loading ol.msgcat{display:none}#loco-admin.wrap #loco-po{padding-right:0;overflow:auto}#loco-admin.wrap ol.msgcat{margin-left:3em;padding-top:1em;border-top:1px dashed #ccc}#loco-admin.wrap ol.msgcat:first-child{padding-top:0;border-top:none}#loco-admin.wrap ol.msgcat li{color:#aaa;margin:0;padding:0 0 0 1em;font:normal 12px/17px "Monaco","Menlo","Ubuntu Mono","Consolas","source-code-pro",monospace;border-left:1px solid #eee}#loco-admin.wrap ol.msgcat li>*{color:#333;white-space:pre}#loco-admin.wrap ol.msgcat li>.po-comment{color:#3cc200}#loco-admin.wrap ol.msgcat li>.po-refs{color:#0073aa}#loco-admin.wrap ol.msgcat li>.po-refs a{color:inherit;text-decoration:none}#loco-admin.wrap ol.msgcat li>.po-refs a:hover{text-decoration:underline}#loco-admin.wrap ol.msgcat li>.po-flags{color:#77904a}#loco-admin.wrap ol.msgcat li>.po-flags em{font-style:normal}#loco-admin.wrap ol.msgcat li>.po-word{color:#000}#loco-admin.wrap ol.msgcat li>.po-junk{font-style:italic;color:#ccc}#loco-admin.wrap ol.msgcat li>.po-string>span{color:#c931c7}#loco-admin.wrap form.loco-filter{top:0;right:0;position:absolute}#loco-admin.wrap .loco-invalid form.loco-filter input[type=text]:focus{border-color:#c00;-webkit-box-shadow:0 0 2px rgba(153,0,0,.5);-moz-box-shadow:0 0 2px rgba(153,0,0,.5);box-shadow:0 0 2px rgba(153,0,0,.5)}#loco-admin.wrap .loco-invalid ol.msgcat{list-style-type:none}#loco-admin.wrap .loco-invalid ol.msgcat li{color:#000}
\ No newline at end of file
.js #loco-admin.wrap .loco-loading{min-height:100px;background:#fff url(../img/spin-modal.gif?v=2.4.5) center center no-repeat}.js #loco-admin.wrap .loco-loading ol.msgcat{display:none}#loco-admin.wrap #loco-po{padding-right:0;overflow:auto}#loco-admin.wrap ol.msgcat{margin-left:3em;padding-top:1em;border-top:1px dashed #ccc}#loco-admin.wrap ol.msgcat:first-child{padding-top:0;border-top:none}#loco-admin.wrap ol.msgcat li{color:#aaa;margin:0;padding:0 0 0 1em;font:normal 12px/17px "Monaco","Menlo","Ubuntu Mono","Consolas","source-code-pro",monospace;border-left:1px solid #eee}#loco-admin.wrap ol.msgcat li>*{color:#333;white-space:pre}#loco-admin.wrap ol.msgcat li>.po-comment{color:#3cc200}#loco-admin.wrap ol.msgcat li>.po-refs{color:#0073aa}#loco-admin.wrap ol.msgcat li>.po-refs a{color:inherit;text-decoration:none}#loco-admin.wrap ol.msgcat li>.po-refs a:hover{text-decoration:underline}#loco-admin.wrap ol.msgcat li>.po-flags{color:#77904a}#loco-admin.wrap ol.msgcat li>.po-flags em{font-style:normal}#loco-admin.wrap ol.msgcat li>.po-word{color:#000}#loco-admin.wrap ol.msgcat li>.po-junk{font-style:italic;color:#ccc}#loco-admin.wrap ol.msgcat li>.po-string>span{color:#c931c7}#loco-admin.wrap form.loco-filter{top:0;right:0;position:absolute}#loco-admin.wrap .loco-invalid form.loco-filter input[type=text]:focus{border-color:#c00;-webkit-box-shadow:0 0 2px rgba(153,0,0,.5);-moz-box-shadow:0 0 2px rgba(153,0,0,.5);box-shadow:0 0 2px rgba(153,0,0,.5)}#loco-admin.wrap .loco-invalid ol.msgcat{list-style-type:none}#loco-admin.wrap .loco-invalid ol.msgcat li{color:#000}
\ No newline at end of file
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(9,100,132,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#096484;foo:#096484}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1cdc7 !important;background:#db9925 !important;border-color:#db9925 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/blue/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(9,100,132,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#096484;foo:#096484}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1cdc7 !important;background:#db9925 !important;border-color:#db9925 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/blue/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(199,165,137,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#c7a589;foo:#c7a589}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1ccc7 !important;background:#ba906d !important;border-color:#ba906d !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/coffee/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(199,165,137,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#c7a589;foo:#c7a589}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1ccc7 !important;background:#ba906d !important;border-color:#ba906d !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/coffee/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(163,183,69,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#a3b745;foo:#a3b745}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#cfd1c7 !important;background:#89993a !important;border-color:#89993a !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/ectoplasm/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(163,183,69,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#a3b745;foo:#a3b745}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#cfd1c7 !important;background:#89993a !important;border-color:#89993a !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/ectoplasm/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(136,136,136,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#888;foo:#04a4cc}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#c7cfd1 !important;background:#0384a4 !important;border-color:#0384a4 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/light/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(136,136,136,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#888;foo:#04a4cc}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#c7cfd1 !important;background:#0384a4 !important;border-color:#0384a4 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/light/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(225,77,67,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#e14d43;foo:#e14d43}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1c8c7 !important;background:#d92e23 !important;border-color:#d92e23 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/midnight/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(225,77,67,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#e14d43;foo:#e14d43}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1c8c7 !important;background:#d92e23 !important;border-color:#d92e23 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/midnight/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(56,88,233,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#3858e9;foo:#3858e9}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#c7c9d1 !important;background:#193ddf !important;border-color:#193ddf !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/modern/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(56,88,233,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#3858e9;foo:#3858e9}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#c7c9d1 !important;background:#193ddf !important;border-color:#193ddf !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/modern/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(158,186,160,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#9ebaa0;foo:#9ebaa0}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#c7d1c8 !important;background:#86a989 !important;border-color:#86a989 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/ocean/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(158,186,160,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#9ebaa0;foo:#9ebaa0}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#c7d1c8 !important;background:#86a989 !important;border-color:#86a989 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/ocean/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(221,130,59,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#dd823b;foo:#dd823b}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1cbc7 !important;background:#cc6d23 !important;border-color:#cc6d23 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/sunrise/spin-primary-button.gif?v=2.4.4) 0 0 no-repeat !important}
.wrap #loco-editor .is-table .wg-tr:nth-child(even){background-color:rgba(221,130,59,.05)}.wrap #loco-editor .wg-split-x>nav.wg-tabs>a.active,.wrap #loco-editor .is-table .wg-cols>div>div.selected{background-color:#dd823b;foo:#dd823b}.wrap #loco-editor .is-editable>.wg-content>textarea:focus,.wrap #loco-editor .is-editable>.wg-content.has-focus .ace_scroller,.wrap #loco-editor .is-editable>.wg-content.has-focus .mce-content-body{border-color:#5b9dd9;-webkit-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);-moz-box-shadow:inset 0 0 .6em rgba(30,140,190,.8);box-shadow:inset 0 0 .6em rgba(30,140,190,.8)}.wp-core-ui .button-primary.loco-loading[disabled]{color:#d1cbc7 !important;background:#cc6d23 !important;border-color:#cc6d23 !important}.wp-core-ui .button-primary.loco-loading[disabled]:before{background:transparent url(../../img/skins/sunrise/spin-primary-button.gif?v=2.4.5) 0 0 no-repeat !important}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3,8 +3,8 @@ Contributors: timwhitlock
Tags: translation, translators, localization, localisation, l10n, i18n, Gettext, PO, MO, productivity, multilingual, internationalization
Requires at least: 4.1
Requires PHP: 5.2.4
Tested up to: 5.5.1
Stable tag: 2.4.4
Tested up to: 5.5.3
Stable tag: 2.4.5
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
......@@ -100,6 +100,14 @@ We don't collect your data or snoop on you. See the [plugin privacy notice](http
== Changelog ==
= 2.4.5 =
* Added WP-CLI sync and extract commands
* Fixed {locale} placeholder bug introduced in 2.4.4
* Improved handling of invalid character encodings
* Sync (msgmerge) moved to back end
* New fuzzy matching with fuzziness setting
* Bumped WordPress version to 5.5.3
= 2.4.4 =
* Added PO file upload feature
* Added download button to file info page
......@@ -377,7 +385,7 @@ We don't collect your data or snoop on you. See the [plugin privacy notice](http
== Upgrade Notice ==
= 2.4.4 =
= 2.4.5 =
* Various improvements and bugfixes
......
......@@ -66,7 +66,7 @@ class Loco_admin_bundle_LocaleController extends Loco_mvc_AdminController {
$files = $package->findTemplateFiles()->augment($files);
}
/* @var Loco_fs_File */
/* @var Loco_fs_File $file */
foreach( $files as $file ){
$nfiles++;
if( 'pot' !== $file->extension() ){
......
......@@ -70,10 +70,12 @@ class Loco_admin_file_EditController extends Loco_admin_file_BaseController {
// default is to permit editing of any file
$readonly = false;
// All files must belong to a bundle.
$bundle = $this->getBundle();
// Establish if file belongs to a configured project
try {
$bundle = $this->getBundle();
$project = $this->getProject();
}
// Fine if not, this just means sync isn't possible.
......
......@@ -272,7 +272,7 @@ class Loco_admin_init_InitPoController extends Loco_admin_bundle_BaseController
$writable = false;
$disabled = true;
}
$suffix = '-'.$pofile->getSuffix().'.po';
$suffix = $pofile->getSuffix().'.po';
$choice = new Loco_mvc_ViewParams( array (
'checked' => '',
'writable' => $writable,
......@@ -280,7 +280,7 @@ class Loco_admin_init_InitPoController extends Loco_admin_bundle_BaseController
'systype' => $systype,
'parent' => Loco_mvc_FileParams::create( $parent ),
'hidden' => $pofile->getRelativePath($content_dir),
'holder' => str_replace( $suffix, '-<span>{locale}</span>.po', $pofile->basename() ),
'holder' => str_replace( $suffix, '<span>{locale}</span>.po', $pofile->basename() ),
) );
$sortable[] = $choice;
$locations[$typeId]['paths'][] = $choice;
......
......@@ -51,17 +51,6 @@ class Loco_admin_init_InitPotController extends Loco_admin_bundle_BaseController
// Establish default POT path whether it exists or not
$pot = $project->getPot();
while( ! $pot ){
$name = ( $slug ? $slug : $domain ).'.pot';
/* @var $dir Loco_fs_Directory */
foreach( $project->getConfiguredTargets() as $dir ){
$pot = new Loco_fs_File( $dir->getPath().'/'.$name );
break 2;
}
// unlikely to have no configured targets, but possible ... so default to standard
$pot = new Loco_fs_File( $bundle->getDirectoryPath().'/languages/'.$name );
break;
}
// POT should actually not exist at this stage. It should be edited instead.
if( $pot->exists() ){
......
......@@ -69,7 +69,7 @@ class Loco_admin_init_UploadController extends Loco_admin_bundle_BaseController
}
$locations[$typeId]['paths'][] = new Loco_mvc_ViewParams( array(
'parent' => Loco_mvc_FileParams::create($parent),
'holder' => str_replace('-zxx.po','-{locale}</span>.po', $pofile->basename() ),
'holder' => str_replace('zxx.po','{locale}</span>.po', $pofile->basename() ),
) );
}
// we don't know what the specifics will be until a location is chosen and a file is presented.
......
......@@ -13,9 +13,7 @@ class Loco_admin_list_ThemesController extends Loco_admin_list_BaseController {
$this->set('type', 'theme' );
$this->set('title', __( 'Translate themes', 'loco-translate' ) );
/* @var $theme WP_Theme */
foreach( wp_get_themes() as $theme ){
$bundle = Loco_package_Theme::create( $theme->get_stylesheet() );
foreach( Loco_package_Theme::getAll() as $bundle ){
$this->addBundle( $bundle );
}
......
......@@ -40,7 +40,7 @@ class Loco_ajax_DownloadController extends Loco_mvc_AjaxController {
$has_bom = "\xEF\xBB\xBF" === substr($raw,0,3);
$use_bom = (bool) Loco_data_Settings::get()->po_utf8_bom;
// only alter file if valid UTF-8. Deferring detection overhead until required
if( $has_bom !== $use_bom && 'UTF-8' === mb_detect_encoding( $raw, array('UTF-8','ISO-8859-1'), true ) ){
if( $has_bom !== $use_bom && preg_match('//u',$raw) ){
if( $use_bom ){
$raw = "\xEF\xBB\xBF".$raw; // prepend
}
......@@ -52,6 +52,5 @@ class Loco_ajax_DownloadController extends Loco_mvc_AjaxController {
return $raw;
}
}
\ No newline at end of file
}
......@@ -77,14 +77,17 @@ class Loco_ajax_MsginitController extends Loco_ajax_common_BundleController {
}
}
// else parse POT file if project defines one that exists
else if( ( $potfile = $project->getPot() ) && $potfile->exists() ){
$data = Loco_gettext_Data::load($potfile);
}
// else extract directly from source code, assuming domain passed though from front end
else {
$extr = new Loco_gettext_Extraction( $bundle );
$data = $extr->addProject($project)->includeMeta()->getTemplate($domain);
$potfile = null;
$potfile = $project->getPot();
if( $potfile->exists() ){
$data = Loco_gettext_Data::load($potfile);
}
// else extract directly from source code, assuming domain passed though from front end
else {
$extr = new Loco_gettext_Extraction( $bundle );
$data = $extr->addProject($project)->includeMeta()->getTemplate($domain);
$potfile = null;
}
}
// Let template define Project-Id-Version, else set header to current project name
......
<?php
<?php /** @noinspection DuplicatedCode */
/**
* Ajax "sync" route.
* Extracts strings from source (POT or code) and returns to the browser for in-editor merge.
......@@ -17,21 +18,28 @@ class Loco_ajax_SyncController extends Loco_mvc_AjaxController {
if( ! $project instanceof Loco_package_Project ){
throw new Loco_error_Exception('No such project '.$post->domain);
}
// Merging on back end is only required if existing target file exists.
// Currently it always will and the editor is not permitted to contain unsaved changes when syncing.
if( ! $post->has('path') ){
throw new Loco_error_Exception('path argument required');
}
$file = new Loco_fs_File( $post->path );
$base = loco_constant('WP_CONTENT_DIR');
$file->normalize($base);
// POT file always synced with source code (even if a PO being used as POT)
if( 'pot' === $post->type ){
$target = Loco_gettext_Data::load($file);
// POT file always synced with source code
$type = $post->type;
if( 'pot' === $type ){
$potfile = null;
}
// allow post data to force a template file path
else if( $path = $post->sync ){
$potfile = new Loco_fs_File($path);
// allow front end to configure source file. (will have come from $target headers)
else if( $post->has('sync') ){
$potfile = new Loco_fs_File( $post->sync );
$potfile->normalize($base);
}
// else use project-configured template if one is defined
// else use project-configured template path
else {
$potfile = $project->getPot();
}
......@@ -43,22 +51,21 @@ class Loco_ajax_SyncController extends Loco_mvc_AjaxController {
$potfile = null;
}
// sync with POT if it exists
// Parse existing POT for source
if( $potfile ){
$this->set('pot', $potfile->basename() );
try {
$data = Loco_gettext_Data::load($potfile);
$source = Loco_gettext_Data::load($potfile);
}
catch( Exception $e ){
// translators: Where %s is the name of the invalid POT file
throw new Loco_error_ParseException( sprintf( __('Translation template is invalid (%s)','loco-translate'), $potfile->basename() ) );
}
// strip msgstr fields from PO files if template is user-defined and "copy translations" was not selected.
if( '1' === $post->strip ){
$data->strip();
}
// Only copy msgstr fields from source if it's a user-defined PO template and "copy translations" was selected.
$strip = (bool) $post->strip;
$translate = 'pot' !== $potfile->extension() && ! $strip;
}
// else sync with source code
// else extract POT from source code
else {
$this->set('pot', '' );
$domain = (string) $project->getDomain();
......@@ -75,11 +82,79 @@ class Loco_ajax_SyncController extends Loco_mvc_AjaxController {
// not failing, just warning. Nothing will be saved until user saves editor state
Loco_error_AdminNotices::warn( $text );
}
// OK to return available strings
$data = $extr->includeMeta()->getTemplate($domain);
// Have source strings. These cannot contain any translations.
$source = $extr->includeMeta()->getTemplate($domain);
$translate = false;
$strip = false;
}
$this->set( 'po', $data->jsonSerialize() );
// establish on back end what strings will be added, removed, and which could be fuzzy-matches
$ntotal = 0;
$nmatched = 0;
$added = array();
$dropped = array();
$fuzzy = array();
// add latest valid sources to matching instance
$matcher = new LocoFuzzyMatcher;
/* @var LocoPoMessage $new */
foreach( $source as $new ){
$matcher->add($new);
$ntotal++;
}
// Fuzzy matching only applies to syncing PO files. POT files will always do hard sync (add/remove)
if( 'po' === $type ){
$fuzziness = Loco_data_Settings::get()->fuzziness;
$matcher->setFuzziness( (string) $fuzziness );
}
else {
$matcher->setFuzziness('0');
}
// update matches sources, deferring unmatched for deferred fuzzy match
$merged = clone $target;
$merged->clear();
/* @var LocoPoMessage $old */
foreach( $target as $old ){
$new = $matcher->match($old);
// if existing source is still valid, merge any changes
if( $new instanceof LocoPoMessage ){
$p = clone $old;
$p->merge($new,$translate);
$merged->push($p);
$nmatched++;
}
}
// Attempt fuzzy matching after all exact matches have been processed
if( $nmatched !== $ntotal ){
foreach( $matcher->getFuzzyMatches() as $pair ){
list($old,$new) = $pair;
$p = clone $old;
$p->merge($new);
$merged->push($p);
$fuzzy[] = $p->getKey();
}
// Any unmatched strings remaining are NEW
/* @var LocoPoMessage $new */
foreach( $matcher->unmatched() as $new ){
$p = clone $new;
$strip and $p->strip();
$merged->push($p);
$added[] = $p->getKey();
}
// any deferred matches not resolved are dropped
/* @var LocoPoMessage $old */
foreach( $matcher->redundant() as $old ){
$dropped[] = $old->getKey();
}
}
// return to JavaScript with stats in the same form as old front end merge
$this->set( 'done', array (
'add' => $added,
'fuz' => $fuzzy,
'del' => $dropped,
) );
$merged->sort();
$this->set( 'po', $merged->jsonSerialize() );
return parent::render();
}
......
<?php
/**
* Loco Translate commands
*/
class Loco_cli_Commands {
/**
* Sync translation files with the available source strings
*
* ## OPTIONS
*
* [<filter>]
* : Restrict to a type of bundle (plugins|themes|core) or a specific Text Domain
*
* [--locale=<code>]
* : Restrict to one or more locales. Separate multiple codes with commas.
*
* [--fuzziness=<percent>]
* : Override plugin settings for fuzzy matching tolerance (0-100).
*
* [--noop]
* : Specify dry run. Makes no changes on disk.
*
* ## EXAMPLES
*
* wp loco sync plugins
*
*
* @param string[]
* @param string[]
* @codeCoverageIgnore
*/
public function sync( $args, $opts ){
if( array_key_exists('fuzziness',$opts) ){
Loco_data_Settings::get()->fuzziness = (int) $opts['fuzziness'];
}
try {
Loco_cli_SyncCommand::run (
Loco_cli_Utils::collectProjects( isset($args[0]) ? $args[0] : '' ),
Loco_cli_Utils::collectLocales( isset($opts['locale']) ? $opts['locale'] : '' ),
Loco_cli_Utils::bool($opts,'noop')
);
}
catch( Loco_error_Exception $e ){
WP_CLI::error( $e->getMessage() );
}
}
/**
* Extract available source strings
*
* ## OPTIONS
*
* [<filter>]
* : Restrict to a type of bundle (plugins|themes|core) or a specific Text Domain
*
* [--maxsize=<size>]
* : Override plugin settings for maximum PHP file size
*
* [--noop]
* : Specify dry run. Makes no changes on disk.
*
* ## EXAMPLES
*
* wp loco extract core --maxsize=400K
*
* @param string[]
* @param string[]
* @codeCoverageIgnore
*/
public function extract( $args, $opts ){
try {
if( array_key_exists('maxsize',$opts) ){
Loco_data_Settings::get()->max_php_size = $opts['maxsize'];
}
Loco_cli_ExtractCommand::run (
Loco_cli_Utils::collectProjects( isset($args[0]) ? $args[0] : '' ),
Loco_cli_Utils::bool($opts,'noop')
);
}
catch( Loco_error_Exception $e ){
WP_CLI::error( $e->getMessage() );
}
}
}
\ No newline at end of file
<?php
/**
* Called from Loco_cli_Commands::extract
*/
abstract class Loco_cli_ExtractCommand {
/**
* @param Loco_package_Project[] project filter
* @param bool whether dry run
*/
public static function run( array $projects, $noop = true ){
// track total number of POT files synced
$updated = 0;
$content_dir = loco_constant('WP_CONTENT_DIR');
/* @var Loco_package_Project $project */
foreach( $projects as $project ){
$id = rtrim( $project->getId(), '.' );
WP_CLI::log( sprintf('Extracting "%s" (%s)',$project->getName(),$id) );
// POT file may or may not exist currently
$potfile = $project->getPot();
if( ! $potfile ){
WP_CLI::warning('Skipping undefined POT');
continue;
}
if( $potfile->locked() ){
WP_CLI::warning('Skipping unwritable POT');
Loco_cli_Utils::tabulateFiles( $potfile->getParent(), $potfile );
continue;
}
// Do extraction and grab only given domain's strings
$ext = new Loco_gettext_Extraction( $project->getBundle() );
$domain = $project->getDomain()->getName();
$data = $ext->addProject($project)->includeMeta()->getTemplate( $domain );
Loco_cli_Utils::debug('Extraction OK, %u strings', count($data) );
$list = $ext->getSkipped();
if( $list ){
$current = Loco_data_Settings::get()->max_php_size;
$suggest = ceil( $ext->getMaxPhpSize() / 1024 );
WP_CLI::warning(sprintf('%u source files skipped over %s. Consider running with --maxsize=%uK',count($list),$current,$suggest) );
foreach( $list as $file ) {
$f = new Loco_mvc_FileParams(array(),$file);
Loco_cli_Utils::debug('%s (%s)', $f->relpath, $f->size );
}
}
// if POT exists check if update is necessary.
$data->sort();
if( $potfile->exists() ){
try {
Loco_cli_Utils::debug('Checking if sources have changed since '.date('c',$potfile->modified()) );
$prev = Loco_gettext_Data::fromSource( $potfile->getContents() );
if( $prev->equal($data) ){
WP_CLI::log('No update required for '.$potfile->basename() );
continue;
}
}
catch( Loco_error_ParseException $e ){
Loco_cli_Utils::debug( $e->getMessage().' in '.$potfile->basename() );
}
}
if( $noop ){
WP_CLI::success( sprintf('**DRY RUN** would update %s', $potfile->basename() ) );
continue;
}
// additional headers to set in new POT file
$head = $data->getHeaders();
$head['Project-Id-Version'] = $project->getName();
// write POT file to disk returning byte length
Loco_cli_Utils::debug('Writing POT file...');
$bytes = $potfile->putContents( $data->msgcat(false) );
Loco_cli_Utils::debug(' %u bytes written to %s',$bytes, $potfile->getRelativePath($content_dir) );
WP_CLI::success( sprintf('Updated %s', $potfile->basename() ) );
$updated++;
}
// sync summary
if( 0 === $updated ){
WP_CLI::log('Nothing updated');
}
else {
WP_CLI::success( sprintf('%u POT files written',$updated) );
}
}
}
\ No newline at end of file
<?php /** @noinspection DuplicatedCode */
/**
* Called from Loco_cli_Commands::sync
*/
abstract class Loco_cli_SyncCommand {
/**
* @param Loco_package_Project[] project filter
* @param Loco_Locale[] locale filter
* @param bool whether dry run
*/
public static function run( array $projects, array $locales, $noop = true ){
// CLI runs all disk operations directly. No remote authorization here currently.
$fs = new Loco_api_WordPressFileSystem;
$content_dir = loco_constant('WP_CONTENT_DIR');
// track total number of PO files synced
$updated = 0;
/* @var Loco_package_Project $project */
foreach( $projects as $project ){
$id = rtrim( $project->getId(), '.' );
WP_CLI::log( sprintf('Syncing "%s" (%s)',$project->getName(),$id) );
// Check if project has POT, which will be used as default template unless PO overrides
$pot = null;
$potfile = $project->getPot();
if( $potfile && $potfile->exists() ){
Loco_cli_Utils::debug('Parsing template: %s',$potfile->getRelativePath($content_dir));
try {
$pot = Loco_gettext_Data::fromSource( $potfile->getContents() );
}
catch( Loco_error_ParseException $e ){
WP_CLI::error( $e->getMessage().' in '.$potfile->getRelativePath($content_dir), false );
$potfile = null;
}
}
/* @var Loco_fs_LocaleFile $pofile */
$pofiles = $project->findLocaleFiles('po');
foreach( $pofiles as $pofile ){
$locale = $pofile->getLocale();
$tag = (string) $locale;
if( $locales && ! array_key_exists($tag,$locales) ){
continue;
}
// Preempt write errors and print useful file mode info
$mofile = $pofile->cloneExtension('mo');
if( ! $pofile->writable() || $mofile->locked() ){
WP_CLI::warning('Skipping unwritable: '.$pofile->filename() );
Loco_cli_Utils::tabulateFiles( $pofile->getParent(), $pofile, $mofile );
continue;
}
// Parsing candidate PO file (definitions)
Loco_cli_Utils::debug('Parsing PO: %s',$pofile->getRelativePath($content_dir));
try {
$def = Loco_gettext_Data::fromSource( $pofile->getContents() );
}
catch( Loco_error_ParseException $e ){
WP_CLI::error( $e->getMessage().' in '.$pofile->getRelativePath($content_dir), false );
continue;
}
// Check if PO defines alternative template (reference)
$ref = $pot;
$translate = true;
$head = $def->getHeaders();
if( $head->has('X-Loco-Template') ){
$ref = null;
$potfile = new Loco_fs_File( $head['X-Loco-Template'] );
$potfile->normalize( $project->getBundle()->getDirectoryPath() );
if( $potfile->exists() ){
try {
Loco_cli_Utils::debug('> Parsing alternative template: %s',$potfile->getRelativePath($content_dir) );
$ref = Loco_gettext_Data::fromSource( $potfile->getContents() );
// Default sync behaviour is to copy msgstr fields unless in POT mode
if( $head->has('X-Loco-Template-Mode') && 'POT' === $head['X-Loco-Template-Mode'] ){
$translate = false;
}
}
catch( Loco_error_ParseException $e ){
WP_CLI::error( $e->getMessage().' in '.$potfile->getRelativePath($content_dir), false );
}
}
else {
Loco_cli_Utils::debug('Template not found (%s)', $potfile->basename() );
}
}
// Perform merge if we have a reference file
if( $ref ){
Loco_cli_Utils::debug('Merging %s <- %s', $pofile->basename(), $potfile->basename() );
$po = self::msgmerge( $def, $ref, $translate );
}
else {
WP_CLI::warning( sprintf('Skipping %s; no valid translation template',$pofile->getRelativePath($content_dir) ) );
continue;
}
// File is synced, but may be identical
$po->sort();
if( $po->equal($def) ){
WP_CLI::log( sprintf('No update required for %s', $pofile->filename() ) );
continue;
}
if( $noop ){
WP_CLI::success( sprintf('**DRY RUN** would update %s', $pofile->filename() ) );
continue;
}
try {
// file is different so make a backup before overwriting
$backups = new Loco_fs_Revisions($pofile);
if( $backups->rotate($fs) ){
Loco_cli_Utils::debug('+ saved backup file of %s',$pofile->basename() );
}
// write new PO
$po->localize($locale);
$bytes = $pofile->putContents( $po->msgcat() );
Loco_cli_Utils::debug('+ %u bytes written to %s',$bytes, $pofile->basename());
$updated++;
// compile MO
$bytes = $mofile->putContents( $po->msgfmt() );
Loco_cli_Utils::debug('+ %u bytes written to %s',$bytes, $mofile->basename());
// Done PO/MO pair
WP_CLI::success( sprintf('Updated %s', $pofile->filename() ) );
}
catch( Loco_error_WriteException $e ){
WP_CLI::error( $e->getMessage(), false );
}
}
}
// sync summary
if( 0 === $updated ){
WP_CLI::log('Nothing updated');
}
else {
WP_CLI::success( sprintf('%u PO files synced',$updated) );
}
}
/**
* @param Loco_gettext_Data Existing PO file to MODIFY (definitions)
* @param Loco_gettext_Data Latest POT file, being synced in (reference)
* @param bool whether to merge translations in addition to sources
* @return Loco_gettext_Data Merged file replacing $po
*/
private static function msgmerge( Loco_gettext_Data $po, Loco_gettext_Data $pot, $translate = false ){
$ntotal = 0;
$nmatched = 0;
$nfuzzy = 0;
$nadded = 0;
// add latest valid sources to matching instance
$matcher = new LocoFuzzyMatcher;
/* @var LocoPoMessage $new */
foreach( $pot as $new ){
$ntotal++;
$matcher->add($new);
}
// Get fuzzy matching tolerance from plugin settings, can be set temporarily in command line
$fuzziness = Loco_data_Settings::get()->fuzziness;
$matcher->setFuzziness( (string) $fuzziness );
// update matches sources, deferring unmatched for deferred fuzzy match
$merged = clone $po;
$merged->clear();
/* @var LocoPoMessage $old */
foreach( $po as $old ){
$new = $matcher->match($old);
// if existing source is still valid, merge any changes
if( $new instanceof LocoPoMessage ){
$p = clone $old;
$p->merge($new,$translate);
$merged->push($p);
$nmatched += $p->countForms();
}
}
// We can quit early if all strings were matched
if( $nmatched === $ntotal ){
Loco_cli_Utils::debug('> %u identical sources',$ntotal);
return $merged;
}
// Attempt fuzzy matching after all exact matches have been processed
foreach( $matcher->getFuzzyMatches() as $pair ){
list($old,$new) = $pair;
$p = clone $old;
$p->merge($new);
$merged->push($p);
$nfuzzy += $p->countForms();
Loco_cli_Utils::debug('~ %s', $p['source'] );
}
// Any unmatched strings remaining are NEW
/* @var LocoPoMessage $new */
foreach( $matcher->unmatched() as $new ){
$p = clone $new;
$translate or $p->strip();
$merged->push($p);
$nadded += $p->countForms();
Loco_cli_Utils::debug('+ %s', $p['source'] );
}
// TODO Support --previous to keep old strings, or at least comment them out as #| msgid.....
// number of strings dropped is previous total minus those matched
$ndropped = $po->count() - ( $nmatched + $nfuzzy );
Loco_cli_Utils::debug('> unchanged:%u added:%u fuzzy:%u dropped:%u', $nmatched, $nadded, $nfuzzy, $ndropped );
return $merged;
}
}
\ No newline at end of file
<?php
/**
* Utility functions for wp cli commands
*/
abstract class Loco_cli_Utils {
/**
* Collect translation sets according to type/domain filter
* @param string Type of bundle (plugins|themes|core) or a specific Text Domain
* @return Loco_package_Project[]
*/
public static function collectProjects( $filter ){
$projects = array();
$filter = strtolower($filter);
// bundle type filter
if( 'plugins' === $filter ){
$bundles = Loco_package_Plugin::getAll();
$filter = null;
}
else if( 'themes' === $filter ){
$bundles = Loco_package_Theme::getAll();
$filter = null;
}
else if( 'core' === $filter ) {
$bundles = array( Loco_package_Core::create() );
$filter = null;
}
else {
$bundles = array( Loco_package_Core::create() );
$bundles = array_merge( $bundles, Loco_package_Plugin::getAll() );
$bundles = array_merge( $bundles, Loco_package_Theme::getAll() );
}
/* @var Loco_package_Project $project */
foreach( $bundles as $bundle ){
foreach( $bundle as $project ){
if( $filter && strtolower( $project->getDomain() ) !== $filter ){
continue;
}
$projects[] = $project;
}
}
if( ! $projects ){
throw new Loco_error_Exception('No translation sets found');
}
return $projects;
}
/**
* Collect locales from one or more language tags
* @param string zero or more language tags
* @return Loco_Locale[]
*/
public static function collectLocales( $tags ){
$locales = array();
if( '' !== $tags ){
$api = new Loco_api_WordPressTranslations;
foreach( preg_split('/[\\s,;]+/i',$tags,-1,PREG_SPLIT_NO_EMPTY) as $tag ){
$locale = Loco_Locale::parse($tag);
if( ! $locale->isValid() ){
throw new Loco_error_Exception('Invalid locale: '.json_encode($tag) );
}
// TODO could expand language-only tags to known WordPress locales e.g. fr -> fr_FR
$locales[ (string) $locale ] = $locale;
$locale->ensureName($api);
}
// empty locales means ALL locales, so refuse to return ALL when filter was non-empty
if( 0 === count($locales) ){
throw new Loco_error_Exception('No valid locales in: '.json_encode($tags) );
}
}
return $locales;
}
/**
* Simple space-padded table
* @param string[][] data rows to print
*/
public static function tabulate( array $t ){
$w = array();
foreach( $t as $y => $row ){
foreach( $row as $x => $value ){
$width = mb_strlen($value,'UTF-8');
$w[$x] = isset($w[$x]) ? max($w[$x],$width) : $width;
}
}
foreach( $t as $y => $row ){
$line = array();
foreach( $w as $x => $width ){
$value = isset($row[$x]) ? $row[$x] : '';
$value = str_pad($value,$width,' ',STR_PAD_RIGHT);
$line[] = $value;
}
self::debug( implode(' ',$line) );
}
}
/**
* Prints file listing to stdout
*/
public static function tabulateFiles(){
$t = array();
/* @var Loco_fs_File $file */
foreach( func_get_args() as $file ){
if( $file instanceof Loco_fs_File && $file->exists() ){
$f = new Loco_mvc_FileParams(array(),$file);
$t[] = array( $f->owner, $f->group, $f->smode, $f->relpath );
}
}
self::tabulate($t);
}
/**
* WP_CLI debug logger
*/
public static function debug(){
$args = func_get_args();
$message = array_shift($args);
if( $args ){
$message = vsprintf($message,$args);
}
WP_CLI::debug( $message,'loco' );
}
/**
* Parse boolean command line option. Absence is equal to false
*
*/
public static function bool( array $opts, $key ){
$value = isset($opts[$key]) ? $opts[$key] : false;
if( ! is_bool($value) ){
$value = $value && 'false' !== $value & 'no' !== $value;
}
return $value;
}
}
\ No newline at end of file
......@@ -8,8 +8,7 @@
abstract class Loco_compat_MbstringExtension {
public static function mb_detect_encoding( $str, array $encoding_list = null, $strict = null ){
// return ! $str || preg_match('/^(?:[\\0-\\x7F]|[\\xC0-\\xDF][\\x80-\\xBF]|[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xFF][\\x80-\\xBF]{3})+$/',$str)
return ! $str || preg_match('/./u',$str)
return ! $str || preg_match('//u',$str)
? 'UTF-8'
: 'ISO-8859-1'
;
......@@ -20,13 +19,28 @@ abstract class Loco_compat_MbstringExtension {
}
public static function mb_strlen( $str, $encoding = null ){
static $warned = false;
if( ! $warned && preg_match('/[\\x80-\\xFF]/',$str) ){
trigger_error('Character counts will be wrong without mbstring extension',E_USER_WARNING);
$warned = true;
}
return strlen($str);
}
public static function mb_convert_encoding( $str, $to_encoding, $from_encoding ){
if( $to_encoding !== $from_encoding && '' !== $str ){
// loco_convert_utf8 no longer uses mb_convert_encoding for UTF8->latin1
if( '' === $from_encoding || 'ISO-8859-1' === $from_encoding || 'cp1252' === $from_encoding ){
if( '' === $to_encoding || 'UTF-8' === $to_encoding || 'US-ASCII' === $to_encoding ){
if( function_exists('loco_fix_utf8') ) {
return loco_fix_utf8( $str );
}
}
}
trigger_error('Unable to convert from '.$from_encoding.' to '.$to_encoding.' without mbstring', E_USER_NOTICE );
}
return $str;
}
}
......
......@@ -135,7 +135,7 @@ class Loco_config_BundleWriter implements JsonSerializable {
if( $file = $proj->getPot() ){
$templateElement = $projElement->appendChild( $dom->createElement('template') );
$templateElement->appendChild( $model->createFileElement($file) );
// template may be prortected from end-user tampering
// template may be protected from end-user tampering
if( $proj->isPotLocked() ){
$templateElement->setAttribute('locked','true');
}
......
......@@ -36,8 +36,8 @@ class Loco_data_Preferences extends Loco_data_Serializable {
public static function get(){
$id = get_current_user_id();
if( ! $id ){
// allow null return only in tests, because all real users must be logged in
if( defined('LOCO_TEST') && LOCO_TEST ) {
// allow null return only on command line. All web users must be logged in
if( 'cli' === PHP_SAPI || defined('LOCO_TEST') ){
return null;
}
throw new Exception( 'No current user' ); // @codeCoverageIgnore
......
......@@ -5,6 +5,7 @@
* @property string $version Current plugin version installed
* @property bool $gen_hash Whether to compile hash table into MO files
* @property bool $use_fuzzy Whether to include Fuzzy strings in MO files
* @property int $fuzziness Fuzzy matching tolerance level, 0-100
* @property int $num_backups Number of backups to keep of Gettext files
* @property array $pot_alias Alternative names for POT files in priority order
* @property array $php_alias Alternative file extensions for PHP files
......@@ -42,6 +43,7 @@ class Loco_data_Settings extends Loco_data_Serializable {
'version' => '',
'gen_hash' => false,
'use_fuzzy' => true,
'fuzziness' => 20,
'num_backups' => 1,
'pot_alias' => array( 'default.po', 'en_US.po', 'en.po' ),
'php_alias' => array( 'php', 'twig' ),
......
......@@ -34,6 +34,16 @@ class Loco_error_AdminNotices extends Loco_hooks_Hookable {
*/
public static function add( Loco_error_Exception $error ){
$notices = self::get();
// if exception wasn't thrown we have to do some work to establish where it was invoked
if( __FILE__ === $error->getFile() ){
$error->setCallee(1);
}
// write error immediately under WP_CLIT
if( 'cli' === PHP_SAPI && class_exists('WP_CLI',false) ){
$error->logCli();
return $error;
}
// else buffer notices for displaying when UI is ready
$notices->errors[] = $error;
// do late flush if we missed the boat
if( did_action('loco_admin_init') ){
......@@ -42,10 +52,6 @@ class Loco_error_AdminNotices extends Loco_hooks_Hookable {
if( did_action('admin_notices') ){
$notices->on_admin_notices();
}
// if exception wasn't thrown we have to do some work to establish where it was invoked
if( __FILE__ === $error->getFile() ){
$error->setCallee(1);
}
// Log messages of minimum priority and up, depending on debug mode
// note that non-debug level is in line with error_reporting set by WordPress (notices ignored)
$priority = loco_debugging() ? Loco_error_Exception::LEVEL_DEBUG : Loco_error_Exception::LEVEL_WARNING;
......@@ -118,7 +124,8 @@ class Loco_error_AdminNotices extends Loco_hooks_Hookable {
* @return Loco_error_Exception[]
*/
public static function destroy(){
if( $notices = self::$singleton ){
$notices = self::$singleton;
if( $notices instanceof Loco_error_AdminNotices ){
$buffer = $notices->errors;
$notices->errors = array();
self::$singleton = null;
......@@ -145,7 +152,7 @@ class Loco_error_AdminNotices extends Loco_hooks_Hookable {
/**
* @return void
*/
private function flush(){
private function flushHtml(){
if( $this->errors ){
$htmls = array();
foreach( $this->errors as $error ){
......@@ -169,13 +176,24 @@ class Loco_error_AdminNotices extends Loco_hooks_Hookable {
}
}
/**
* @return void
*/
private function flushCli(){
foreach( $this->errors as $e ){
$e->logCli();
}
$this->errors = array();
}
/**
* admin_notices action handler.
*/
public function on_admin_notices(){
if( ! $this->inline ){
$this->flush();
$this->flushHtml();
}
}
......@@ -186,7 +204,7 @@ class Loco_error_AdminNotices extends Loco_hooks_Hookable {
*/
public function on_loco_admin_notices(){
$this->inline = true;
$this->flush();
$this->flushHtml();
}
......@@ -205,8 +223,11 @@ class Loco_error_AdminNotices extends Loco_hooks_Hookable {
*/
public function __destruct(){
$this->inline = false;
if( ! loco_doing_ajax() ){
$this->flush();
if( class_exists('WP_CLI',false) ){
$this->flushCli();
}
else if( ! loco_doing_ajax() ){
$this->flushHtml();
}
}
......
......@@ -26,6 +26,14 @@ class Loco_error_Debug extends Loco_error_Exception {
public function getLevel(){
return Loco_error_Exception::LEVEL_DEBUG;
}
/**
* {@inheritDoc}
*/
public function logCli(){
WP_CLI::debug( $this->getMessage(), 'loco' );
}
/**
......
......@@ -103,7 +103,7 @@ class Loco_error_Exception extends Exception implements JsonSerializable {
$path = $file->getRelativePath( loco_plugin_root() );
$text = sprintf('[Loco.%s] "%s" in %s:%u', $this->getType(), $this->getMessage(), $path, $this->getRealLine() );
// separate error log in CWD for tests
if( 'cli' === PHP_SAPI && defined('LOCO_TEST') && LOCO_TEST ){
if( defined('LOCO_TEST') && LOCO_TEST ){
error_log( '['.date('c').'] '.$text."\n", 3, 'debug.log' );
}
// Else write to default PHP log, but note that WordPress may have set this to wp-content/debug.log.
......@@ -141,6 +141,15 @@ class Loco_error_Exception extends Exception implements JsonSerializable {
}
/**
* Call wp cli logging function
* @return void
*/
public function logCli(){
WP_CLI::error( $this->getMessage(), false );
}
/**
* Get localized notice level name
* @return string
......
......@@ -28,4 +28,12 @@ class Loco_error_Notice extends Loco_error_Exception {
return Loco_error_Exception::LEVEL_NOLOG;
}
/**
* {@inheritDoc}
*/
public function logCli(){
WP_CLI::log( $this->getMessage() );
}
}
\ No newline at end of file
<?php
/**
*
* Exception thrown when parsing fails
*/
class Loco_error_ParseException extends Loco_error_Exception {
/**
* @var string
* @var string[]
*/
private $context;
......@@ -16,32 +16,36 @@ class Loco_error_ParseException extends Loco_error_Exception {
* @return self
*/
public function setContext( $line, $column, $source ){
$this->context = null;
// If line given as 0 then treat column as offset in an unknown number of lines
if( 0 === $line ){
$lines = preg_split( '/\\r?\\n/', substr($source,0,$column));
$line = count($lines);
$column = strlen( end($lines) );
$this->context = array();
$lines = preg_split( '/\\r?\\n/', $source, $line+1 );
$offset = $line - 1;
if( isset($lines[$offset]) ){
$this->context[] = $lines[$offset];
$this->context[] = str_repeat(' ', max(0,$column-1) ).'^';
}
// get line of source code where error is and construct a ____^ thingy to show error on next line
// this requires that full source is passed in, so line number must be real
if( loco_debugging() ){
$lines = preg_split( '/\\r?\\n/', $source, $line+1 );
$offset = $line - 1;
if( isset($lines[$offset]) ){
$this->context = $lines[$offset] ."\n". str_repeat(' ', max(0,$column) ).'^';
}
}
// wrap initial message with context data
$this->message = sprintf("Error at line %u, column %u: %s", $line, $column, $this->message );
return $this;
}
/**
* @param int zero-based offset to failure point
* @param string source in which to identify line and column
* @return self
*/
public function setOffsetContext( $offset, $source ){
$lines = preg_split( '/\\r?\\n/', substr($source,0,$offset) );
$line = count($lines);
$column = 1 + strlen( end($lines) );
return $this->setContext( $line, $column, $source );
}
/**
* @return string
*/
public function getContext(){
return $this->context;
return is_array($this->context) ? implode("\n",$this->context) : '';
}
}
......@@ -27,4 +27,13 @@ class Loco_error_Success extends Loco_error_Exception {
return Loco_error_Exception::LEVEL_NOLOG;
}
/**
* {@inheritDoc}
*/
public function logCli(){
WP_CLI::success( $this->getMessage() );
}
}
......@@ -27,4 +27,12 @@ class Loco_error_Warning extends Loco_error_Exception {
return Loco_error_Exception::LEVEL_WARNING;
}
/**
* {@inheritDoc}
*/
public function logCli(){
WP_CLI::warning( $this->getMessage() );
}
}
\ No newline at end of file
......@@ -170,7 +170,7 @@ class Loco_fs_File {
if( $writer->isDirect() && ( $uid = Loco_compat_PosixExtension::getuid() ) ){
return $uid === $this->uid() || $uid === $parent->uid();
}
// else delete operation won't be done directly, so can't pre-empt sticky problems
// else delete operation won't be done directly, so can't preempt sticky problems
// TODO is it worth comparing FTP username etc.. for ownership?
}
// defaulting to "deletable" based on fact that parent is writable.
......@@ -199,7 +199,7 @@ class Loco_fs_File {
/**
* Check if file can't be overwitten when existent, nor created when non-existent
* Check if file can't be overwritten when existent, nor created when non-existent
* This does not check permissions recursively as directory trees are not built implicitly
* @return bool
*/
......
......@@ -13,6 +13,7 @@ class Loco_fs_FileMode {
/**
* Instantiate from integer file mode
* @param int
*/
public function __construct( $mode ){
$this->i = (int) $mode;
......
......@@ -41,7 +41,7 @@ class Loco_gettext_Data extends LocoPoIterator implements JsonSerializable {
}
catch( Loco_error_ParseException $e ){
$path = $file->getRelativePath( loco_constant('WP_CONTENT_DIR') );
Loco_error_AdminNotices::debug( sprintf('Failed to parse %s as a %s file',$path,$type) );
Loco_error_AdminNotices::debug( sprintf('Failed to parse %s as a %s file; %s',$path,$type,$e->getMessage()) );
throw new Loco_error_ParseException( sprintf('Invalid %s file: %s',$type,basename($path)) );
}
}
......@@ -98,7 +98,6 @@ class Loco_gettext_Data extends LocoPoIterator implements JsonSerializable {
* @return string
*/
public static function ensureUtf8( $src ){
loco_check_extension('mbstring');
$src = loco_remove_bom($src,$cs);
if( ! $cs ){
// read PO header, requiring partial parse
......@@ -108,15 +107,8 @@ class Loco_gettext_Data extends LocoPoIterator implements JsonSerializable {
catch( Loco_error_ParseException $e ){
Loco_error_AdminNotices::debug( $e->getMessage() );
}
// fall back on detection which will only work for latin1
if( ! $cs ){
$cs = mb_detect_encoding($src,array('UTF-8','ISO-8859-1'),true);
}
}
if( $cs && 'UTF-8' !== $cs ){
$src = mb_convert_encoding($src,'UTF-8',array($cs) );
}
return $src;
return loco_convert_utf8($src,$cs,false);
}
......@@ -176,7 +168,7 @@ class Loco_gettext_Data extends LocoPoIterator implements JsonSerializable {
* @param string text domain for JED metadata
* @param LocoPoMessage[] pre-compiled messages
* @return string
*/
*
public function jedize( $domain, array $po ){
$head = $this->getHeaders();
// start locale_data with JED header
......@@ -185,7 +177,7 @@ class Loco_gettext_Data extends LocoPoIterator implements JsonSerializable {
'lang' => $head['language'],
'plural-forms' => $head['plural-forms'],
) );
/* @var LocoPoMessage $msg */
// @var LocoPoMessage $msg
foreach( $po as $msg ){
$data[ $msg->getKey() ] = $msg->getMsgstrs();
}
......@@ -202,7 +194,7 @@ class Loco_gettext_Data extends LocoPoIterator implements JsonSerializable {
$domain => $data,
),
), $json_options );
}
}*/
/**
......
......@@ -25,7 +25,7 @@ class Loco_gettext_Extraction {
/**
* List of files skipped due to memory limit
* @var Loco_fs_FileList
* @var Loco_fs_FileList|null
*/
private $skipped;
......@@ -42,7 +42,6 @@ class Loco_gettext_Extraction {
*/
public function __construct( Loco_package_Bundle $bundle ){
loco_check_extension('ctype');
loco_check_extension('mbstring');
if( ! loco_check_extension('tokenizer') ){
throw new Loco_error_Exception('String extraction not available without required extension');
}
......@@ -50,8 +49,9 @@ class Loco_gettext_Extraction {
$this->extracted = new LocoExtracted;
$this->extracted->setDomain('default');
$this->extras = array();
if( $default = $bundle->getDefaultProject() ){
$domain = (string) $default->getDomain();
$default = $bundle->getDefaultProject();
if( $default instanceof Loco_package_Project ){
$domain = $default->getDomain()->getName();
// wildcard stands in for empty text domain, meaning unspecified or dynamic domains will be included.
// note that strings intended to be in "default" domain must specify explicitly, or be included here too.
if( '*' === $domain ){
......
......@@ -40,9 +40,8 @@ abstract class Loco_mvc_AdminController extends Loco_mvc_Controller {
$this->auth();
// check essential extensions on all pages so admin notices are shown
foreach( array('json','mbstring') as $ext ){
loco_check_extension($ext);
}
loco_check_extension('json');
loco_check_extension('mbstring');
// add contextual help tabs to current screen if there are any
if( $screen = get_current_screen() ){
......
......@@ -5,6 +5,11 @@
* @property-read string $name
* @property-read string $path
* @property-read string $relpath
* @property-read string $size
* @property-read int $imode
* @property-read string $smode
* @property-read string $group
* @property-read string $owner
*/
class Loco_mvc_FileParams extends Loco_mvc_ViewParams {
......@@ -129,7 +134,6 @@ class Loco_mvc_FileParams extends Loco_mvc_ViewParams {
/**
* Using slightly modified version of WordPress's Human time differencing
* + Added "Just now" when in the last 30 seconds
* TODO possibly replace with custom function that includes "Yesterday" etc..
* @internal
* @return string
*/
......
......@@ -24,6 +24,8 @@ class Loco_output_DiffRenderer extends WP_Text_Diff_Renderer_Table {
/**
* Render diff of two files, presumed to be PO or POT
* @param Loco_fs_File Left hand file
* @param Loco_fs_File Right hand file
* @return string HTML table
*/
public function renderFiles( Loco_fs_File $lhs, Loco_fs_File $rhs ){
......@@ -34,10 +36,23 @@ class Loco_output_DiffRenderer extends WP_Text_Diff_Renderer_Table {
}
// like wp_text_diff but avoiding whitespace normalization
// uses deprecated signature for 'auto' in case of old WordPress
return $this->render( new Text_Diff (
preg_split( '/(?:\\n|\\r\\n?)/', Loco_gettext_Data::ensureUtf8( $lhs->getContents() ) ),
preg_split( '/(?:\\n|\\r\\n?)/', Loco_gettext_Data::ensureUtf8( $rhs->getContents() ) )
) );
return $this->render( new Text_Diff( self::splitFile($lhs), self::splitFile($rhs) ) );
}
/**
* @param Loco_fs_File
* @return string[]
*/
private static function splitFile( Loco_fs_File $file ){
$src = $file->getContents();
$src = Loco_gettext_Data::ensureUtf8($src);
$arr = preg_split( '/\\r?\\n/', $src );
if( ! is_array($arr) ){
$f = new Loco_mvc_FileParams( array(), $file );
throw new Loco_error_Exception('Failed to split '.$f->relpath.' ('.$f->size.')' );
}
return $arr;
}
......
......@@ -23,6 +23,7 @@ class Loco_package_Locale {
/**
* Construct with locale to filter on
* @param Loco_Locale|null
*/
public function __construct( Loco_locale $locale = null ){
$this->index = new ArrayObject;
......@@ -34,7 +35,8 @@ class Loco_package_Locale {
/**
* Add another locale to serarch on
* Add another locale to search on
* @param Loco_Locale
* @return Loco_package_Locale
*/
public function addLocale( Loco_Locale $locale ){
......@@ -47,50 +49,33 @@ class Loco_package_Locale {
/**
* @return Loco_package_Project
* @param Loco_fs_File
* @return Loco_package_Project|null
*/
public function getProject( Loco_fs_File $file ){
$path = $file->getPath();
if( isset($this->index[$path]) ){
return $this->index[$path];
}
return null;
}
/**
* @return array
* @return Loco_package_Bundle[]
*/
public function getBundles(){
$bundles = $this->bundles;
if( ! $bundles ){
$bundles = array (
Loco_package_Core::create()
);
foreach( Loco_package_Plugin::get_plugins() as $handle => $data ){
try {
$bundles[] = Loco_package_Plugin::create( $handle );
}
catch( Exception $e ){
// @codeCoverageIgnore
}
}
/* @var $theme WP_Theme */
foreach( wp_get_themes() as $theme ){
try {
$bundles[] = Loco_package_Theme::create( $theme->get_stylesheet() );
}
catch( Exception $e ){
// @codeCoverageIgnore
}
}
$bundles = array( Loco_package_Core::create() );
$bundles = array_merge( $bundles, Loco_package_Plugin::getAll() );
$bundles = array_merge( $bundles, Loco_package_Theme::getAll() );
$this->bundles = $bundles;
}
return $bundles;
}
/**
* @return loco_fs_FileList
*/
......@@ -98,9 +83,8 @@ class Loco_package_Locale {
$index = $this->index;
$suffixes = $this->match;
$list = new Loco_fs_FileList;
/* @var $bundle Loco_package_Bundle */
foreach( $this->getBundles() as $bundle ){
/* @var $project Loco_package_Project */
/* @var Loco_package_Project $project */
foreach( $bundle as $project ){
/* @var $file Loco_fs_File */
foreach( $project->findLocaleFiles('po') as $file ){
......@@ -119,14 +103,12 @@ class Loco_package_Locale {
}
/**
* @return loco_fs_FileList
*/
public function findTemplateFiles(){
$index = $this->index;
$list = new Loco_fs_FileList;
/* @var $bundle Loco_package_Bundle */
foreach( $this->getBundles() as $bundle ){
/* @var $project Loco_package_Project */
foreach( $bundle as $project ){
......@@ -140,6 +122,5 @@ class Loco_package_Locale {
}
return $list;
}
}
......@@ -43,9 +43,26 @@ class Loco_package_Plugin extends Loco_package_Bundle {
}
/**
* @return Loco_package_Plugin[]
*/
public static function getAll(){
$plugins = array();
foreach( self::get_plugins() as $handle => $data ){
try {
$plugins[] = Loco_package_Plugin::create($handle);
}
catch( Exception $e ){
// @codeCoverageIgnore
}
}
return $plugins;
}
/**
* Maintaining our own cache of full paths to available plugins, because get_mu_plugins doesn't get cached by WP
* @return array
* @return array[]
*/
public static function get_plugins(){
$cached = wp_cache_get('plugins','loco');
......
......@@ -355,6 +355,35 @@ class Loco_package_Project {
}
/**
* Get first valid domain path
* @param bool whether directory should exist
* @return Loco_fs_Directory
*/
private function getSafeDomainPath(){
// use first configured domain path that exists
foreach( $this->getConfiguredTargets() as $d ){
if( $d->exists() ){
return $d;
}
}
// fallback to unconfigured, but possibly existent folders
$base = $this->getBundle()->getDirectoryPath();
foreach( array('languages','language','lang','l10n','i18n') as $d ){
$d = new Loco_fs_Directory($d);
$d->normalize($base);
if( $this->isTargetExcluded($d) ){
continue;
}
if( $d->exists() ){
return $d;
}
}
// Give up and place in root
return new Loco_fs_Directory($base);
}
/**
* Lazy create all searchable source paths
* @return Loco_fs_FileFinder
......@@ -523,9 +552,10 @@ class Loco_package_Project {
*/
public function getPot(){
if( ! $this->pot ){
$name = $this->getSlug().'.pot';
$slug = $this->getSlug();
$name = ( $slug ? $slug : $this->getDomain()->getName() ).'.pot';
if( '.pot' !== $name ){
// find under configured domain paths
// find actual file under configured domain paths
$targets = $this->getConfiguredTargets()->copy();
// always permit POT file in the bundle root (i.e. outside domain path)
if( $this->isDomainDefault() && $this->bundle->hasDirectoryPath() ){
......@@ -551,11 +581,16 @@ class Loco_package_Project {
}
}
}
// fall back to a directory that exists, but where the POT may not
if( ! $this->pot ){
$this->pot = new Loco_fs_File($name);
$this->pot->normalize( (string) $this->getSafeDomainPath() );
}
}
return $this->pot;
}
/**
* Force the use of a known POT file. This could be a PO file if necessary
* @param Loco_fs_File template POT file
......
<?php
/**
* Object represents a Text Domain within a bundle.
* TODO implement a conflict watcher to warn when domains are shared by multiple bundles?
*/
class Loco_package_TextDomain extends ArrayIterator {
/**
* Actual Gettext-like name of Text Domain, e.g. "twentyfifteen"
* @var string
*/
private $name;
/**
* Whether this is the officially declared domain for a theme or plugin
* @var bool
*/
private $canonical = false;
/**
* Create new Text Domain from its name
* @param string
*/
public function __construct( $name ){
parent::__construct();
$this->name = $name;
}
/**
* @internal
*/
......@@ -45,6 +46,8 @@ class Loco_package_TextDomain extends ArrayIterator {
/**
* Create a named project in a given bundle for this Text Domain
* @param Loco_package_Bundle bundle of which this is one set of translations
* @param string
* @return Loco_package_Project
*/
public function createProject( Loco_package_Bundle $bundle, $name ){
......@@ -56,6 +59,7 @@ class Loco_package_TextDomain extends ArrayIterator {
/**
* @param bool
* @return Loco_package_TextDomain
*/
public function setCanonical( $bool ){
......@@ -70,5 +74,5 @@ class Loco_package_TextDomain extends ArrayIterator {
public function isCanonical(){
return $this->canonical;
}
}
......@@ -71,6 +71,23 @@ class Loco_package_Theme extends Loco_package_Bundle {
}
/**
* @return Loco_package_Theme[]
*/
public static function getAll(){
$themes = array();
foreach( wp_get_themes(array('errors'=>null)) as $theme ){
try {
$themes[] = self::createFromTheme($theme);
}
catch( Exception $e ){
// @codeCoverageIgnore
}
}
return $themes;
}
/**
* Create theme bundle definition from WordPress theme handle
*
......
......@@ -98,6 +98,23 @@ $fs_help = apply_filters('loco_external','https://localise.biz/wordpress/plugin/
</fieldset>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e('Syncing PO files','loco-translate')?></th>
<td>
<fieldset>
<legend class="screen-reader-text">
<span><?php esc_html_e('Syncing PO files','loco-translate')?></span>
</legend>
<p>
<label for="loco--">
<?php esc_html_e('Fuzzy matching tolerance:','loco-translate')?>
</label>
<input type="text" size="5" maxlength="3" name="opts[fuzziness]" id="loco--fuzziness" value="<?php echo esc_attr( $opts->fuzziness)?>" placeholder="0-100" />
<span>%</span>
</p>
</fieldset>
</td>
</tr>
<!--tr>
<th scope="row"><?php esc_html_e('POT template files','loco-translate')?></th>
<td>
......
......@@ -18,7 +18,7 @@
.l-aside--position--wide {
@media (--min--medium) {
flex: 0 0 470px; padding: 70px 55px; max-width: 470px;
flex: 1 1 280px; padding: 70px 55px; max-width: 470px;
}
}
......
......@@ -8,6 +8,15 @@
}
}
.l-content--position-banner {
max-width: 1096px;
margin: 10px auto 20px;
@media (--min--medium) {
margin: -20px auto 20px;
}
}
.l-content--position { position: relative; padding: 10px 10px 0;
@media (--min--medium) {
padding: 40px 20px;
......
......@@ -3,9 +3,9 @@
/* critical:start */
/*.l-main { flex: 1 1 100%; }*/
.l-main { flex: 1 1 auto; }
.l-main { flex: 1 1 400px; }
.l-main--content { background-color: #FFFFFF; padding: 30px 20px;
.l-main--content { background-color: #fff; padding: 30px 20px;
img { max-width: 100%; height: auto; }
@media (--min--medium) {
padding: 40px 50px;
......
......@@ -42,3 +42,8 @@
padding-bottom: 40px;
}
}
.c-job-facebook--wide {
max-width: 340px;
min-height: 190px;
}
......@@ -15,6 +15,11 @@
}
}
.c-recommend-top {
display: flex;
min-height: 62px;
}
.c-recommend--headline { display: block; color: #fff; max-width: 180px; margin-bottom: 20px; font-size: 21px; font-weight: 500; }
.c-recommend--anchor { color: #fff; font-size: 15px; }
......@@ -38,6 +43,7 @@
background-position: 0 0;
background-size: cover;
transform: rotate(-20deg);
background-repeat: no-repeat;
}
strong {
......@@ -60,10 +66,57 @@
.c-recommend {
&::before { background-image: url(/wp-content/themes/biuro/i/recommend.png); }
}
.c-recommend-top {
&::before { background-image: url(/wp-content/themes/biuro/i/recommend-top.png); }
}
}
.js.webp {
.c-recommend {
&::before { background-image: url(/wp-content/themes/biuro/i/recommend.webp); }
}
.c-recommend-top {
&::before { background-image: url(/wp-content/themes/biuro/i/recommend-top.webp); }
}
}
.c-recommend-top {
background: radial-gradient(44.04% 180.85% at 56.55% 59.57%, rgba(87, 181, 181, 0.54) 0%, rgba(90, 204, 204, 0.54) 0.01%, #34B9BA 100%);
align-items: center;
&:before {
transform: rotate(0);
top: auto;
right: 35px;
bottom: 0;
left: auto;
width: 130px;
height: 51px;
@media (--min--medium) {
width: 228px;
height: 89px;
}
}
.c-recommend--headline {
flex: 1 1 50%;
max-width: 100%;
margin: 0;
padding-right: 20px;
font-size: 14px;
line-height: 20px;
@media (--min--medium) {
font-size: 18px;
line-height: 34px;
}
}
.c-recommend--anchor {
flex: 0 0 auto;
margin: 0 0 20px;
@media (--min--medium) {
margin: 0 240px 0 0;
}
}
}
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -152,7 +152,7 @@
?>
<script src="/wp-content/themes/biuro/js/main.min.js" async defer></script>
<script src="/wp-content/themes/biuro/js/main-ab10603d.min.js" async defer></script>
<script src="/wp-content/themes/biuro/js/vendor/modernizr-custom.js" async defer></script>
......
......@@ -46,15 +46,12 @@
// WP Pods fix for multisite
global $wpdb;
$settings = pods( 'biuro_settings', array(
'limit' => -1,
));
global $biuroSettings;
$params = array(
'orderby' => 'date DESC',
'where' => $where,
'limit' => $settings->field('workis_ad') ? 4 : 5
'limit' => $biuroSettings->field('workis_ad') ? 4 : 5
);
if (get_current_blog_id() != 1):
......@@ -72,7 +69,7 @@
if ( 0 < $jobs->total() ):
if ($settings->field('workis_ad')):
if ($biuroSettings->field('workis_ad')):
get_template_part( 'template-parts/jobs/jobs', 'list-homepage' );
else:
get_template_part( 'template-parts/jobs/jobs', 'list' );
......
......@@ -1269,3 +1269,11 @@ add_action( 'admin_post_nopriv_newsletters_post', 'newsletters_post' );
$inEmployers = (is_page() && get_post_meta( $post->ID, 'section', true) == 'employers') ? true : false;
define('inEmployers', $inEmployers);
if (function_exists('pods')):
$biuroSettings = pods( 'biuro_settings', array(
'limit' => -1,
));
define('biuroSettings', $biuroSettings);
endif;
......@@ -30,7 +30,7 @@
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-500.woff2" crossorigin="anonymous" >
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-regular.woff2" crossorigin="anonymous" >
<style><?php include 'css/core.min.css'; ?></style>
<style><?php include 'css/core-37788b01fc.min.css'; ?></style>
<script>
document.documentElement.classList.replace('no-js', 'js');
......@@ -39,13 +39,13 @@
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-300.woff2" crossorigin="anonymous" >
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-700.woff2" crossorigin="anonymous" >
<link rel="preload" href="/wp-content/themes/biuro/css/main.min.css" as="style" onload="this.rel='stylesheet'">
<link rel="preload" href="/wp-content/themes/biuro/css/main-8bae5e9909.min.css" as="style" onload="this.rel='stylesheet'">
<link rel="preconnect" href="https://www.gstatic.com">
<link rel="preconnect" href="https://fonts.gstatic.com">
<noscript>
<link rel="stylesheet" href="/wp-content/themes/biuro/css/main.min.css">
<link rel="stylesheet" href="/wp-content/themes/biuro/css/main-8bae5e9909.min.css">
</noscript>
<?php wp_head(); ?>
......
......@@ -41,7 +41,7 @@
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-500.woff2" crossorigin="anonymous" >
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-regular.woff2" crossorigin="anonymous" >
<style><?php include 'css/core.min.css'; ?></style>
<style><?php include 'css/core-37788b01fc.min.css'; ?></style>
<script>
document.documentElement.classList.replace('no-js', 'js');
......@@ -50,13 +50,13 @@
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-300.woff2" crossorigin="anonymous" >
<link rel="preload" as="font" type="font/woff2" href="/wp-content/themes/biuro/fonts/roboto-v19-cyrillic_latin_cyrillic-ext_latin-ext-700.woff2" crossorigin="anonymous" >
<link rel="preload" href="/wp-content/themes/biuro/css/main.min.css" as="style" onload="this.rel='stylesheet'">
<link rel="preload" href="/wp-content/themes/biuro/css/main-8bae5e9909.min.css" as="style" onload="this.rel='stylesheet'">
<link rel="preconnect" href="https://www.gstatic.com">
<link rel="preconnect" href="https://fonts.gstatic.com">
<noscript>
<link rel="stylesheet" href="/wp-content/themes/biuro/css/main.min.css">
<link rel="stylesheet" href="/wp-content/themes/biuro/css/main-8bae5e9909.min.css">
</noscript>
<?php
......
(window.webpackJsonp=window.webpackJsonp||[]).push([[0],{7:function(e,t,n){"use strict";n.r(t);const o=e=>{if(!e)return;const t=e.parentNode.nextElementSibling;if(!t||!t.classList.contains("c-accordion--content"))return;const n=e.classList.contains("c-accordion--header--is-expanded");n?(e=>{const t=e.scrollHeight,n=e.style.transition;e.style.transition="",requestAnimationFrame(()=>{e.style.height=t+"px",e.style.transition=n,requestAnimationFrame(()=>{e.style.height="0px"})})})(t):(history.pushState({},"",e.hash),requestAnimationFrame(()=>{(e=>{const t=e.offsetTop-(Math.max(document.documentElement.clientWidth,window.innerWidth||0)<960?72:117);window.scrollTo({top:t,behavior:"smooth"}),e.blur()})(e),requestAnimationFrame(()=>{(e=>{const t=e.scrollHeight,n=t=>{e.removeEventListener("transitionend",n)};e.style.height=t+"px",e.addEventListener("transitionend",n)})(t)})})),e.classList.toggle("c-accordion--header--is-expanded",!n)};t.default=()=>{document.querySelectorAll(".c-accordion--content").forEach(e=>{e.classList.add("c-accordion--content--is-collapsed")}),window.location.hash&&o(document.querySelector(window.location.hash)),document.querySelectorAll(".js-accordion--header").forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),o(e)})})}}}]);
\ No newline at end of file
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["accordion"],{
/***/ "./wp-content/themes/biuro/js/components/accordion/accordion.js":
/*!**********************************************************************!*\
!*** ./wp-content/themes/biuro/js/components/accordion/accordion.js ***!
\**********************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\nconst collapseContent = n => {\n const h = n.scrollHeight;\n const t = n.style.transition;\n n.style.transition = '';\n requestAnimationFrame(() => {\n n.style.height = h + 'px';\n n.style.transition = t;\n requestAnimationFrame(() => {\n n.style.height = 0 + 'px';\n });\n });\n};\n\nconst expandContent = n => {\n const h = n.scrollHeight;\n\n const done = e => {\n n.removeEventListener('transitionend', done);\n };\n\n n.style.height = h + 'px';\n n.addEventListener('transitionend', done);\n};\n\nconst scrollToSection = header => {\n const top = header.offsetTop - (Math.max(document.documentElement.clientWidth, window.innerWidth || 0) < 960 ? 72 : 117);\n window.scrollTo({\n top: top,\n behavior: 'smooth'\n });\n header.blur();\n};\n\nconst toggleSection = header => {\n if (!header) {\n return;\n }\n\n const node = header.parentNode.nextElementSibling;\n\n if (!node || !node.classList.contains('c-accordion--content')) {\n return;\n }\n\n const isOpen = header.classList.contains('c-accordion--header--is-expanded');\n\n if (isOpen) {\n collapseContent(node);\n } else {\n history.pushState({}, '', header.hash);\n requestAnimationFrame(() => {\n scrollToSection(header);\n requestAnimationFrame(() => {\n expandContent(node);\n });\n });\n }\n\n header.classList.toggle('c-accordion--header--is-expanded', !isOpen);\n};\n\nconst inititateAccordion = () => {\n document.querySelectorAll('.c-accordion--content').forEach(content => {\n content.classList.add('c-accordion--content--is-collapsed');\n });\n\n if (window.location.hash) {\n toggleSection(document.querySelector(window.location.hash));\n }\n\n document.querySelectorAll('.js-accordion--header').forEach(header => {\n header.addEventListener('click', e => {\n e.preventDefault();\n toggleSection(header);\n });\n });\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (inititateAccordion);\n\n//# sourceURL=webpack:///./wp-content/themes/biuro/js/components/accordion/accordion.js?");
/***/ })
}]);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{12:function(e,o,t){"use strict";t.r(o);var n=t(0);let c=!0;function a(){const e=document.querySelector("#copy-tooltip");e&&(e.style.opacity=1,setTimeout(()=>{e.style.opacity=0},3e3))}function i(e){if(!navigator.clipboard)return function(e){var o=document.createElement("textarea");o.className="u-hidden",o.value=e,document.querySelector(".c-share").appendChild(o),o.focus(),o.select();try{var t=document.execCommand("copy")?"successful":"unsuccessful";console.log("Fallback: Copying text command was "+t)}catch(e){console.error("Fallback: Oops, unable to copy",e)}document.body.removeChild(o)}(e),void a();navigator.clipboard.writeText(e).then((function(){a()}),(function(e){console.error("Async: Could not copy text: ",e)}))}window.onfocus=function(){c=!0},window.onblur=function(){c=!1};o.default=()=>{document.querySelector(".js-copy-to-clipboard")&&document.querySelector(".js-copy-to-clipboard").addEventListener("click",e=>{e.preventDefault(),i(window.location.origin+window.location.pathname+"?utm_source=copy_share_button_job_page ")});const e=document.querySelector(".js-share-messenger");e&&e.addEventListener("click",e=>{e.preventDefault();const o=e.currentTarget;window.location.href="fb-messenger://share/?link="+encodeURIComponent(window.location.origin+window.location.pathname+"?utm_source=messenger_share_button_job_page&app_id="+o.dataset.id),setTimeout(()=>{!document.hidden&&c&&(window.location.href=o.href)},100)});const o=document.querySelector(".js-share-whatsapp");o&&o.addEventListener("click",e=>{e.preventDefault();const o=e.currentTarget;window.location.href="whatsapp://send?text="+o.dataset.text,setTimeout(()=>{!document.hidden&&c&&window.open(o.href,"_blank")},100)});const t=document.querySelector(".js-biuro-facebook");t&&setTimeout(()=>{!async function(e){Object(n.a)("https://connect.facebook.net/en_US/sdk.js").then(()=>{window.FB&&window.FB.init({appId:e,version:"v3.3",status:!0,xfbml:!0})})}(t.dataset.id)},1500)}}}]);
\ No newline at end of file
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["job-share"],{
/***/ "./wp-content/themes/biuro/js/components/job-share/job-share.js":
/*!**********************************************************************!*\
!*** ./wp-content/themes/biuro/js/components/job-share/job-share.js ***!
\**********************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _utils_load_js_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/load-js.js */ \"./wp-content/themes/biuro/js/utils/load-js.js\");\n\n\nasync function inititateFacebook(ID) {\n Object(_utils_load_js_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])('https://connect.facebook.net/en_US/sdk.js').then(() => {\n if (!window.FB) {\n return;\n }\n\n window.FB.init({\n appId: ID,\n version: 'v3.3',\n status: true,\n xfbml: true\n });\n });\n}\n\nlet isPageActive = true;\n\nwindow.onfocus = function () {\n isPageActive = true;\n};\n\nwindow.onblur = function () {\n isPageActive = false;\n};\n\nfunction fallbackCopyTextToClipboard(text) {\n var textArea = document.createElement('textarea');\n textArea.className = 'u-hidden';\n textArea.value = text;\n document.querySelector('.c-share').appendChild(textArea);\n textArea.focus();\n textArea.select();\n\n try {\n var successful = document.execCommand('copy');\n var msg = successful ? 'successful' : 'unsuccessful';\n console.log('Fallback: Copying text command was ' + msg);\n } catch (err) {\n console.error('Fallback: Oops, unable to copy', err);\n }\n\n document.body.removeChild(textArea);\n}\n\nfunction showCopyTooltip() {\n const tooltip = document.querySelector('#copy-tooltip');\n\n if (tooltip) {\n tooltip.style.opacity = 1;\n setTimeout(() => {\n tooltip.style.opacity = 0;\n }, 3000);\n }\n}\n\nfunction copyTextToClipboard(text) {\n if (!navigator.clipboard) {\n fallbackCopyTextToClipboard(text);\n showCopyTooltip();\n return;\n }\n\n navigator.clipboard.writeText(text).then(function () {\n showCopyTooltip();\n }, function (err) {\n console.error('Async: Could not copy text: ', err);\n });\n}\n\nconst inititateJobShare = () => {\n if (document.querySelector('.js-copy-to-clipboard')) {\n document.querySelector('.js-copy-to-clipboard').addEventListener('click', e => {\n e.preventDefault();\n copyTextToClipboard(window.location.origin + window.location.pathname + '?utm_source=copy_share_button_job_page ');\n });\n }\n\n const messenger = document.querySelector('.js-share-messenger');\n\n if (messenger) {\n messenger.addEventListener('click', e => {\n e.preventDefault();\n const target = e.currentTarget;\n window.location.href = 'fb-messenger://share/?link=' + encodeURIComponent(window.location.origin + window.location.pathname + '?utm_source=messenger_share_button_job_page&app_id=' + target.dataset.id);\n setTimeout(() => {\n if (document.hidden || !isPageActive) {\n return;\n }\n\n window.location.href = target.href;\n }, 100);\n });\n }\n\n const whatsapp = document.querySelector('.js-share-whatsapp');\n\n if (whatsapp) {\n whatsapp.addEventListener('click', e => {\n e.preventDefault();\n const target = e.currentTarget;\n window.location.href = 'whatsapp://send?text=' + target.dataset.text;\n setTimeout(() => {\n if (document.hidden || !isPageActive) {\n return;\n }\n\n window.open(target.href, '_blank');\n }, 100);\n });\n }\n\n const facebook = document.querySelector('.js-biuro-facebook');\n\n if (facebook) {\n setTimeout(() => {\n inititateFacebook(facebook.dataset.id);\n }, 1500);\n }\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (inititateJobShare);\n\n//# sourceURL=webpack:///./wp-content/themes/biuro/js/components/job-share/job-share.js?");
/***/ })
}]);
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{11:function(e,t,n){"use strict";n.r(t);var o,i=n(0);function s(e,t){const n=function(){function e(e,t,n="top"){this.position=e;var o=document.createElement("div");o.innerHTML=t||"",o.classList.add("popup-bubble"),o.classList.add("popup-bubble--"+n);var i=document.createElement("div");i.classList.add("popup-bubble-anchor"),i.appendChild(o),this.containerDiv=document.createElement("div"),this.containerDiv.classList.add("popup-container"),this.containerDiv.appendChild(i),window.google.maps.OverlayView.preventMapHitsAndGesturesFrom(this.containerDiv)}return e.prototype=Object.create(window.google.maps.OverlayView.prototype),e.prototype.onAdd=function(){this.getPanes().floatPane.appendChild(this.containerDiv)},e.prototype.onRemove=function(){this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)},e.prototype.draw=function(){var e=this.getProjection().fromLatLngToDivPixel(this.position),t=Math.abs(e.x)<4e3&&Math.abs(e.y)<4e3?"block":"none";"block"===t&&(this.containerDiv.style.left=e.x+"px",this.containerDiv.style.top=e.y+"px"),this.containerDiv.style.display!==t&&(this.containerDiv.style.display=t)},e}(),o=new window.google.maps.LatLngBounds;let i;for(var s=0;s<t.length;s++){const a=t[s],l=new window.google.maps.LatLng(a.lat,a.lng);i=new n(l,a.title,a.pos),i.setMap(e),o.extend(l)}e.fitBounds(o)}function a(e,t,n){for(var i=new window.google.maps.LatLngBounds,s=0;s<t.length;s++){const l=t[s],d=new window.google.maps.LatLng(l.lat,l.lng);var a=new window.google.maps.Marker({position:d,map:e,icon:"/wp-content/themes/biuro/i/ico--map-pin.svg",title:l.title||""});o&&o.close(),i.extend(d),l.content&&(a.content=l.content,window.google.maps.event.addListener(a,"click",(function(){o&&o.close(),(o=new window.google.maps.InfoWindow({content:this.content})).open(e,this)}))),n&&(window.innerWidth<960&&window.scrollTo(0,0),new google.maps.event.trigger(a,"click"))}e.fitBounds(i),window.innerWidth>1020?e.panBy(250,0):window.innerWidth>959&&e.panBy(180,0)}function l(e){var t=new window.google.maps.Map(e,{}),n=new window.google.maps.StyledMapType([{featureType:"all",elementType:"all",stylers:[{saturation:-92},{lightness:-8},{hue:"#004ed4"}]},{featureType:"water",elementType:"all",stylers:[{saturation:-95},{lightness:-25},{hue:"#004ed4"}]}],{name:"Biuro"});return t.mapTypes.set("biuro",n),t.setMapTypeId("biuro"),window.google.maps.event.addListenerOnce(t,"bounds_changed",(function(){this.getZoom()>15&&this.setZoom(14)})),t}t.default=()=>{const e=document.getElementById("js-map--divisions");e&&fetch("/wp-json/api/v1/divisions?langID="+e.dataset.id).then(e=>e.json()).then(t=>{!function(e,t){Object(i.a)("https://maps.googleapis.com/maps/api/js?key=AIzaSyBQjPQnLGLeICbpTTu8kLjVRrLUYYCTS2M").then(()=>{window.google&&setTimeout(()=>{var n=l(e);let o=[];Object.keys(t).forEach(e=>{const n=t[e];"city"===e.substr(0,4)&&(o=o.concat(n))}),document.querySelectorAll(".js-division").forEach(e=>{e.addEventListener("click",()=>{const i=e&&e.dataset.id?e.dataset.id:"";t[i]?a(n,t[i].filter(e=>e.lat&&e.lng),!0):a(n,o.filter(e=>e.lat&&e.lng))})}),a(n,o.filter(e=>e.lat&&e.lng))},50)})}(e,t)});const t=document.getElementById("js-map--cities");t&&fetch("/wp-content/themes/biuro/json/"+t.dataset.source+".json").then(e=>e.json()).then(e=>{!function e(t,n){if(window.google){var o=l(t);s(o,n),window.innerWidth>1020?o.panBy(-230,0):window.innerWidth>959&&o.panBy(-150,0)}else setTimeout(()=>{e(t,n)},250)}(t,e)});const n=document.getElementById("js-map--regions");n&&function e(t){if(!window.google)return void setTimeout(()=>{e(t)},250);a(l(t),[{title:"Vilnius",lat:54.687157,lng:25.279652},{title:"Rīga",lat:56.946285,lng:24.105078},{title:"Tallinn",lat:59.436962,lng:24.753574}])}(n)}}}]);
\ No newline at end of file
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["map"],{
/***/ "./wp-content/themes/biuro/js/components/map/map.js":
/*!**********************************************************!*\
!*** ./wp-content/themes/biuro/js/components/map/map.js ***!
\**********************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _utils_load_js_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/load-js.js */ \"./wp-content/themes/biuro/js/utils/load-js.js\");\n // https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/overlay-popup\n\nfunction createPopupClass() {\n function Popup(position, city, pos = 'top') {\n this.position = position;\n var content = document.createElement('div');\n content.innerHTML = city || '';\n content.classList.add('popup-bubble');\n content.classList.add('popup-bubble--' + pos); // This zero-height div is positioned at the bottom of the bubble.\n\n var bubbleAnchor = document.createElement('div');\n bubbleAnchor.classList.add('popup-bubble-anchor');\n bubbleAnchor.appendChild(content); // This zero-height div is positioned at the bottom of the tip.\n\n this.containerDiv = document.createElement('div');\n this.containerDiv.classList.add('popup-container');\n this.containerDiv.appendChild(bubbleAnchor); // Optionally stop clicks, etc., from bubbling up to the map.\n\n window.google.maps.OverlayView.preventMapHitsAndGesturesFrom(this.containerDiv);\n } // ES5 magic to extend google.maps.OverlayView.\n\n\n Popup.prototype = Object.create(window.google.maps.OverlayView.prototype);\n /** Called when the popup is added to the map. */\n\n Popup.prototype.onAdd = function () {\n this.getPanes().floatPane.appendChild(this.containerDiv);\n };\n /** Called when the popup is removed from the map. */\n\n\n Popup.prototype.onRemove = function () {\n if (this.containerDiv.parentElement) {\n this.containerDiv.parentElement.removeChild(this.containerDiv);\n }\n };\n /** Called each frame when the popup needs to draw itself. */\n\n\n Popup.prototype.draw = function () {\n var divPosition = this.getProjection().fromLatLngToDivPixel(this.position); // Hide the popup when it is far out of view.\n\n var display = Math.abs(divPosition.x) < 4000 && Math.abs(divPosition.y) < 4000 ? 'block' : 'none';\n\n if (display === 'block') {\n this.containerDiv.style.left = divPosition.x + 'px';\n this.containerDiv.style.top = divPosition.y + 'px';\n }\n\n if (this.containerDiv.style.display !== display) {\n this.containerDiv.style.display = display;\n }\n };\n\n return Popup;\n}\n\nvar info;\n\nfunction setCitiesMarkers(map, positions) {\n const Popup = createPopupClass();\n const bounds = new window.google.maps.LatLngBounds();\n let popup;\n\n for (var i = 0; i < positions.length; i++) {\n const position = positions[i];\n const pos = new window.google.maps.LatLng(position.lat, position.lng);\n popup = new Popup(pos, position.title, position.pos);\n popup.setMap(map);\n bounds.extend(pos);\n }\n\n map.fitBounds(bounds);\n}\n\nfunction setMarkers(map, positions, focus) {\n var bounds = new window.google.maps.LatLngBounds();\n\n for (var i = 0; i < positions.length; i++) {\n const position = positions[i];\n const pos = new window.google.maps.LatLng(position.lat, position.lng);\n var marker = new window.google.maps.Marker({\n position: pos,\n map: map,\n icon: '/wp-content/themes/biuro/i/ico--map-pin.svg',\n title: position.title || ''\n });\n\n if (info) {\n info.close();\n }\n\n bounds.extend(pos);\n\n if (position.content) {\n marker.content = position.content;\n window.google.maps.event.addListener(marker, 'click', function () {\n if (info) {\n info.close();\n }\n\n info = new window.google.maps.InfoWindow({\n content: this.content\n });\n info.open(map, this);\n });\n }\n\n if (focus) {\n if (window.innerWidth < 960) {\n window.scrollTo(0, 0);\n }\n\n new google.maps.event.trigger(marker, 'click');\n }\n }\n\n map.fitBounds(bounds);\n\n if (window.innerWidth > 1020) {\n map.panBy(250, 0);\n } else if (window.innerWidth > 959) {\n map.panBy(180, 0);\n }\n}\n\nfunction setGoogleMap(node) {\n const mapStyles = [{\n featureType: 'all',\n elementType: 'all',\n stylers: [{\n saturation: -92\n }, {\n lightness: -8\n }, {\n hue: '#004ed4'\n }]\n }, {\n featureType: 'water',\n elementType: 'all',\n stylers: [{\n saturation: -95\n }, {\n lightness: -25\n }, {\n hue: '#004ed4'\n }]\n }];\n var map = new window.google.maps.Map(node, {});\n var biuroMap = new window.google.maps.StyledMapType(mapStyles, {\n name: 'Biuro'\n });\n map.mapTypes.set('biuro', biuroMap);\n map.setMapTypeId('biuro');\n window.google.maps.event.addListenerOnce(map, 'bounds_changed', function () {\n if (this.getZoom() > 15) {\n this.setZoom(14);\n }\n });\n return map;\n}\n\nfunction initCitiesMap(node, cities) {\n if (!window.google) {\n setTimeout(() => {\n initCitiesMap(node, cities);\n }, 250);\n return;\n }\n\n var map = setGoogleMap(node);\n setCitiesMarkers(map, cities);\n\n if (window.innerWidth > 1020) {\n map.panBy(-230, 0);\n } else if (window.innerWidth > 959) {\n map.panBy(-150, 0);\n }\n}\n\nfunction initRegionsMap(node) {\n if (!window.google) {\n setTimeout(() => {\n initRegionsMap(node);\n }, 250);\n return;\n }\n\n var map = setGoogleMap(node);\n const regions = [{\n title: 'Vilnius',\n lat: 54.687157,\n lng: 25.279652\n }, {\n title: 'Rīga',\n lat: 56.946285,\n lng: 24.105078\n }, {\n title: 'Tallinn',\n lat: 59.436962,\n lng: 24.753574\n }];\n setMarkers(map, regions);\n}\n\nfunction initDivisionsMap(node, data) {\n Object(_utils_load_js_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])('https://maps.googleapis.com/maps/api/js?key=AIzaSyBQjPQnLGLeICbpTTu8kLjVRrLUYYCTS2M').then(() => {\n if (!window.google) {\n return;\n }\n\n setTimeout(() => {\n var map = setGoogleMap(node);\n let divisions = [];\n Object.keys(data).forEach(key => {\n const division = data[key];\n\n if (key.substr(0, 4) === 'city') {\n divisions = divisions.concat(division);\n }\n });\n document.querySelectorAll('.js-division').forEach(node => {\n node.addEventListener('click', () => {\n const ID = node && node.dataset.id ? node.dataset.id : '';\n\n if (data[ID]) {\n setMarkers(map, data[ID].filter(d => {\n return d.lat && d.lng;\n }), true);\n } else {\n setMarkers(map, divisions.filter(d => {\n return d.lat && d.lng;\n }));\n }\n });\n });\n setMarkers(map, divisions.filter(d => {\n return d.lat && d.lng;\n }));\n }, 50);\n });\n}\n\nconst inititateMap = () => {\n // <script src=\"https://maps.googleapis.com/maps/api/js?key=AIzaSyBQjPQnLGLeICbpTTu8kLjVRrLUYYCTS2M\" async defer></script>\n const division = document.getElementById('js-map--divisions');\n\n if (division) {\n fetch('/wp-json/api/v1/divisions?langID=' + division.dataset.id).then(t => t.json()).then(data => {\n initDivisionsMap(division, data);\n });\n }\n\n const city = document.getElementById('js-map--cities');\n\n if (city) {\n fetch('/wp-content/themes/biuro/json/' + city.dataset.source + '.json').then(t => t.json()).then(data => {\n initCitiesMap(city, data);\n });\n }\n\n const region = document.getElementById('js-map--regions');\n\n if (region) {\n initRegionsMap(region);\n }\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (inititateMap);\n\n//# sourceURL=webpack:///./wp-content/themes/biuro/js/components/map/map.js?");
/***/ })
}]);
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{13:function(e,p,t){"use strict";t.r(p);const o=(e,p,t)=>{const o={value:p,expiry:(new Date).getTime()+t};localStorage.setItem(e,JSON.stringify(o))},n=e=>{const p=localStorage.getItem(e);if(!p)return null;const t=JSON.parse(p);return(new Date).getTime()>t.expiry?(localStorage.removeItem(e),null):t.value},l=()=>{const e=document.getElementById("employer-popup");e&&!n("employer-popup")&&(o("employer-popup","expires",12096e5),window.dataLayer=window.dataLayer||[],e.style.display="block",window.dataLayer.push({event:"b2b_popup_show"}),e.querySelector(".js-popup--btn")&&e.querySelector(".js-popup--btn").addEventListener("click",e=>{window.dataLayer.push({event:"b2b_popup_navigate",label:"Recommend page"})}),e.querySelector(".js-popup--close")&&e.querySelector(".js-popup--close").addEventListener("click",p=>{p.preventDefault(),e.style.display="none"}))},a=e=>{const p=document.getElementById("employee-popup");p&&!n("employee-popup")&&e.clientY<50&&null==e.relatedTarget&&"select"!==e.target.nodeName.toLowerCase()&&(document.removeEventListener("mouseout",a),o("employee-popup","expires",12096e5),window.dataLayer=window.dataLayer||[],p.style.display="block",window.dataLayer.push({event:"b2c_popup_show"}),p.querySelector(".js-popup--btn")&&p.querySelector(".js-popup--btn").addEventListener("click",e=>{window.dataLayer.push({event:"b2c_popup_navigate",label:"Recommend page"})}),p.querySelector(".js-popup--close")&&p.querySelector(".js-popup--close").addEventListener("click",e=>{e.preventDefault(),p.style.display="none"}))};p.default=()=>{document.getElementById("employee-popup")&&!n("employee-popup")&&setTimeout(()=>{document.addEventListener("mouseout",a)},3e3),document.getElementById("employer-popup")&&!n("employer-popup")&&setTimeout(l,45e3)}}}]);
\ No newline at end of file
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["popup"],{
/***/ "./wp-content/themes/biuro/js/components/popup/popup.js":
/*!**************************************************************!*\
!*** ./wp-content/themes/biuro/js/components/popup/popup.js ***!
\**************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\nconst EMPLOYEE_DELAY = 3000; // 3 seconds\n\nconst EMPLOYEE_EXPIRY = 14 * 86400 * 1000; // 14 days\n\nconst EMPLOYER_DELAY = 45000; // 45 seconds\n\nconst EMPLOYER_EXPIRY = 14 * 86400 * 1000; // 14 days\n\nconst setExpirableItem = (key, value, ttl) => {\n const now = new Date(); // `item` is an object which contains the original value\n // as well as the time when it's supposed to expire\n\n const item = {\n value: value,\n expiry: now.getTime() + ttl\n };\n localStorage.setItem(key, JSON.stringify(item));\n};\n\nconst getExpirableItem = key => {\n const itemStr = localStorage.getItem(key); // if the item doesn't exist, return null\n\n if (!itemStr) {\n return null;\n }\n\n const item = JSON.parse(itemStr);\n const now = new Date(); // compare the expiry time of the item with the current time\n\n if (now.getTime() > item.expiry) {\n // If the item is expired, delete the item from storage\n // and return null\n localStorage.removeItem(key);\n return null;\n }\n\n return item.value;\n};\n\nconst showEmployerPopup = () => {\n const container = document.getElementById('employer-popup');\n\n if (!container || getExpirableItem('employer-popup')) {\n return;\n }\n\n setExpirableItem('employer-popup', 'expires', EMPLOYER_EXPIRY);\n window.dataLayer = window.dataLayer || [];\n container.style.display = 'block';\n window.dataLayer.push({\n event: 'b2b_popup_show'\n });\n\n if (container.querySelector('.js-popup--btn')) {\n container.querySelector('.js-popup--btn').addEventListener('click', e => {\n window.dataLayer.push({\n event: 'b2b_popup_navigate',\n label: 'Recommend page'\n });\n });\n }\n\n if (container.querySelector('.js-popup--close')) {\n container.querySelector('.js-popup--close').addEventListener('click', e => {\n e.preventDefault();\n container.style.display = 'none';\n });\n }\n};\n\nconst showEmployeePopup = e => {\n const container = document.getElementById('employee-popup');\n\n if (!container || getExpirableItem('employee-popup')) {\n return;\n }\n\n if (e.clientY < 50 && e.relatedTarget == null && e.target.nodeName.toLowerCase() !== 'select') {\n document.removeEventListener('mouseout', showEmployeePopup);\n setExpirableItem('employee-popup', 'expires', EMPLOYEE_EXPIRY);\n window.dataLayer = window.dataLayer || [];\n container.style.display = 'block';\n window.dataLayer.push({\n event: 'b2c_popup_show'\n });\n\n if (container.querySelector('.js-popup--btn')) {\n container.querySelector('.js-popup--btn').addEventListener('click', e => {\n window.dataLayer.push({\n event: 'b2c_popup_navigate',\n label: 'Recommend page'\n });\n });\n }\n\n if (container.querySelector('.js-popup--close')) {\n container.querySelector('.js-popup--close').addEventListener('click', e => {\n e.preventDefault();\n container.style.display = 'none';\n });\n }\n }\n};\n\nconst inititatePopup = () => {\n if (document.getElementById('employee-popup') && !getExpirableItem('employee-popup')) {\n setTimeout(() => {\n document.addEventListener('mouseout', showEmployeePopup);\n }, EMPLOYEE_DELAY);\n }\n\n if (document.getElementById('employer-popup') && !getExpirableItem('employer-popup')) {\n setTimeout(showEmployerPopup, EMPLOYER_DELAY);\n }\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (inititatePopup);\n\n//# sourceURL=webpack:///./wp-content/themes/biuro/js/components/popup/popup.js?");
/***/ })
}]);
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{8:function(t,e,r){"use strict";r.r(e);e.default=()=>{const t=document.querySelector(".c-tabs"),e=t.querySelector("ul"),r=e.querySelectorAll("a"),a=t.querySelectorAll("section"),i=t=>{t&&(window.location.hash=t,history.pushState?history.pushState(null,t):location.hash=t)},o=(t,e)=>{e.focus(),e.removeAttribute("tabindex"),e.setAttribute("aria-selected","true"),t.removeAttribute("aria-selected"),t.setAttribute("tabindex","-1");const i=Array.prototype.indexOf.call(r,e),o=Array.prototype.indexOf.call(r,t);a[o].hidden=!0,a[i].hidden=!1};e.setAttribute("role","tablist"),Array.prototype.forEach.call(r,(t,n)=>{t.setAttribute("role","tab"),t.setAttribute("id","tab"+(n+1)),t.setAttribute("tabindex","-1"),t.parentNode.setAttribute("role","presentation"),t.addEventListener("click",t=>{t.preventDefault();const r=e.querySelector("[aria-selected]");t.currentTarget!==r&&(i(t.currentTarget.dataset.hash),o(r,t.currentTarget))}),t.addEventListener("keydown",t=>{const e=Array.prototype.indexOf.call(r,t.currentTarget),l=37===t.which?e-1:39===t.which?e+1:40===t.which?"down":null;null!==l&&(t.preventDefault(),"down"===l?a[n].focus():r[l]&&(i(t.currentTarget.dataset.hash),o(t.currentTarget,r[l])))})}),Array.prototype.forEach.call(a,(t,e)=>{t.setAttribute("role","tabpanel"),t.setAttribute("tabindex","-1"),t.setAttribute("aria-labelledby",r[e].id),t.hidden=!0});let n=0;if(location.hash){const t=location.hash.replace("#","");a.forEach((e,r)=>{e.id===t&&(n=r)})}r[n].removeAttribute("tabindex"),r[n].setAttribute("aria-selected","true"),a[n].hidden=!1}}}]);
\ No newline at end of file
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["tabs"],{
/***/ "./wp-content/themes/biuro/js/components/tabs/tabs.js":
/*!************************************************************!*\
!*** ./wp-content/themes/biuro/js/components/tabs/tabs.js ***!
\************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\nconst inititateTabs = () => {\n // Get relevant elements and collections\n const container = document.querySelector('.c-tabs');\n const tablist = container.querySelector('ul');\n const tabs = tablist.querySelectorAll('a');\n const panels = container.querySelectorAll('section');\n\n const updateHash = hash => {\n if (!hash) {\n return;\n }\n\n window.location.hash = hash;\n\n if (history.pushState) {\n history.pushState(null, hash);\n } else {\n location.hash = hash;\n }\n }; // The tab switching function\n\n\n const switchTab = (oldTab, newTab) => {\n newTab.focus(); // Make the active tab focusable by the user (Tab key)\n\n newTab.removeAttribute('tabindex'); // Set the selected state\n\n newTab.setAttribute('aria-selected', 'true');\n oldTab.removeAttribute('aria-selected');\n oldTab.setAttribute('tabindex', '-1'); // Get the indices of the new and old tabs to find the correct\n // tab panels to show and hide\n\n const index = Array.prototype.indexOf.call(tabs, newTab);\n const oldIndex = Array.prototype.indexOf.call(tabs, oldTab);\n panels[oldIndex].hidden = true;\n panels[index].hidden = false;\n }; // Add the tablist role to the first <ul> in the .tabbed container\n\n\n tablist.setAttribute('role', 'tablist'); // Add semantics are remove user focusability for each tab\n\n Array.prototype.forEach.call(tabs, (tab, i) => {\n tab.setAttribute('role', 'tab');\n tab.setAttribute('id', 'tab' + (i + 1));\n tab.setAttribute('tabindex', '-1');\n tab.parentNode.setAttribute('role', 'presentation'); // Handle clicking of tabs for mouse users\n\n tab.addEventListener('click', e => {\n e.preventDefault();\n const currentTab = tablist.querySelector('[aria-selected]');\n\n if (e.currentTarget !== currentTab) {\n updateHash(e.currentTarget.dataset.hash);\n switchTab(currentTab, e.currentTarget);\n }\n }); // Handle keydown events for keyboard users\n\n tab.addEventListener('keydown', e => {\n // Get the index of the current tab in the tabs node list\n const index = Array.prototype.indexOf.call(tabs, e.currentTarget); // Work out which key the user is pressing and\n // Calculate the new tab's index where appropriate\n\n const dir = e.which === 37 ? index - 1 : e.which === 39 ? index + 1 : e.which === 40 ? 'down' : null;\n\n if (dir !== null) {\n e.preventDefault(); // If the down key is pressed, move focus to the open panel,\n // otherwise switch to the adjacent tab\n\n if (dir === 'down') {\n panels[i].focus();\n } else if (tabs[dir]) {\n updateHash(e.currentTarget.dataset.hash);\n switchTab(e.currentTarget, tabs[dir]);\n }\n }\n });\n }); // Add tab panel semantics and hide them all\n\n Array.prototype.forEach.call(panels, (panel, i) => {\n panel.setAttribute('role', 'tabpanel');\n panel.setAttribute('tabindex', '-1');\n panel.setAttribute('aria-labelledby', tabs[i].id);\n panel.hidden = true;\n });\n let indx = 0;\n\n if (location.hash) {\n const ID = location.hash.replace('#', '');\n panels.forEach((panel, i) => {\n if (panel.id === ID) {\n indx = i;\n }\n });\n } // Initially activate the first tab and reveal the first tab panel\n\n\n tabs[indx].removeAttribute('tabindex');\n tabs[indx].setAttribute('aria-selected', 'true');\n panels[indx].hidden = false;\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (inititateTabs);\n\n//# sourceURL=webpack:///./wp-content/themes/biuro/js/components/tabs/tabs.js?");
/***/ })
}]);
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
......@@ -80,11 +80,9 @@ get_header(); ?>
</div><!-- #content -->
<?php
$settings = pods( 'biuro_settings', array(
'limit' => -1,
));
global $biuroSettings;
if ($settings->field('teams_enabled')):
if ($biuroSettings->field('teams_enabled')):
get_template_part( 'template-parts/teams/teams', 'none' );
endif;
......
......@@ -20,6 +20,8 @@ get_header();
<div id="content" class="l-content--position">
<?php
global $biuroSettings;
$ID = get_the_id();
$pod = pods( 'job', $ID );
......@@ -30,17 +32,26 @@ get_header();
logPositions([$livasID], 'details');
endif;
$settings = pods( 'biuro_settings', array(
'limit' => -1,
));
$managers = get_the_terms($pod->ID, 'member');
$manager = $managers[0];
$isManagerVisible = $manager && $manager->term_id && $settings->field('job_page_contacts') === 'manager' ? true : false;
$isManagerVisible = $manager && $manager->term_id && $biuroSettings->field('job_page_contacts') === 'manager' ? true : false;
if ($recommendPage && $biuroSettings->field('job_page_recommend_friend') == 'top'):
?>
<div class="l-content--position-banner">
<a class="c-recommend c-recommend-top" href="<?php echo $recommendPage; ?>">
<span class="c-recommend--headline"><?php _e('Recommend a friend - receive <strong>50 Eur!</strong>', 'biuro'); ?></span>
<span class="c-recommend--anchor"><?php _e('Find out more', 'biuro'); ?></span>
</a>
</div>
<?php
endif;
?>
<div class="l-content--position-inner <?php echo $isManagerVisible ? 'l-content--position-inner--wide' : ''; ?>">
<main id="main" class="l-main l-main--position" itemscope="itemscope" itemtype="http://schema.org/JobPosting">
<?php
......
......@@ -3,6 +3,6 @@ Theme Name: Biuro
Author: Biuro
Author URI: https://www.biuro.lt/
Description: Biuro multiregion theme
Version: 1.21.3
Version: 1.22.0
Text Domain: biuro
*/
......@@ -91,14 +91,11 @@
<?php
global $recommendPage;
global $biuroSettings;
global $isManagerVisible;
global $manager;
$settings = pods( 'biuro_settings', array(
'limit' => -1,
));
if ($recommendPage && $settings->field('job_page_recommend_friend') == 'aside'):
if ($recommendPage && $biuroSettings->field('job_page_recommend_friend') == 'aside'):
?>
<a class="c-recommend" href="<?php echo $recommendPage; ?>">
<span class="c-recommend--headline"><?php _e('Recommend a friend - receive <strong>50 Eur!</strong>', 'biuro'); ?></span>
......@@ -107,7 +104,7 @@
<?php
endif;
if ($settings->field('job_page_contacts') != 'hidden'):
if ($biuroSettings->field('job_page_contacts') != 'hidden'):
if ($isManagerVisible):
$member = pods( 'member', $manager->term_id );
......@@ -153,7 +150,7 @@
endif;
endif;
if ($settings->field('job_page_facebook') == 'visible'):
if ($biuroSettings->field('job_page_facebook') == 'visible'):
$social = get_option( 'wpseo_social' );
......@@ -161,7 +158,7 @@
if ($facebook_site != ''):
?>
<div class="js-biuro-facebook c-job-facebook" data-id="<?php echo $appID; ?>">
<div class="js-biuro-facebook c-job-facebook <?php echo ($isManagerVisible) ? 'c-job-facebook--wide' : ''; ?>" data-id="<?php echo $appID; ?>">
<div class="fb-page" data-href="<?php echo $facebook_site; ?>" data-tabs="" data-width="" data-height="" data-small-header="false" data-adapt-container-width="true" data-hide-cover="false" data-show-facepile="true"><blockquote cite="<?php echo $facebook_site; ?>" class="fb-xfbml-parse-ignore"><a href="<?php echo $facebook_site; ?>">Biuro</a></blockquote></div>
</div>
<?php
......
......@@ -24,8 +24,8 @@ wp core language update;
# wp option update date_format "Y-m-d";
# wp option update time_format "H:i";
# wp plugin install loco-translate --version=2.4.4 --activate-network;
wp plugin update loco-translate --version=2.4.4;
# wp plugin install loco-translate --version=2.4.5 --activate-network;
wp plugin update loco-translate --version=2.4.5;
# wp plugin install pods --version=2.7.24 --activate-network;
wp plugin update pods --version=2.7.24;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment