Commit 6ecb3821 authored by Simonas's avatar Simonas

pre release-0.0.0

parent 54e600b1
This source diff could not be displayed because it is too large. You can view the blob instead.
var/ var/
ssh/
wordpress/ wordpress/
node_modules/ node_modules/
logs/nginx/*.log logs/nginx/*.log
......
...@@ -12,18 +12,17 @@ ...@@ -12,18 +12,17 @@
- Clone [dev.biuro](http://git.biuro.lt/biuro/dev.biuro) repository - Clone [dev.biuro](http://git.biuro.lt/biuro/dev.biuro) repository
- in Command Prompt run `docker-compose up -d` - in Command Prompt run `docker-compose up -d`
- `docker ps` command should output existing docker containers (nginx, mysql, wordpress) - `docker ps` command should output existing docker containers (nginx, mysql, wordpress)
- restore DB as written in *DB restore* section
- set dev.biuro.lt, dev.biuro.lv, dev.biuro.ee to 127.0.0.1 in hosts - set dev.biuro.lt, dev.biuro.lv, dev.biuro.ee to 127.0.0.1 in hosts
- check if dev.biuro.lt, dev.biuro.lv, dev.biuro.ee works - check if dev.biuro.lt, dev.biuro.lv, dev.biuro.ee works
### DB backup ### DB backup
- `C:\web\dev.biuro> docker exec -i mysql mysqldump -uroot -pIiIjnsLi2wR9i1kWVbVpUAzP --default-character-set=utf8 wordpress > docker/mariadb/db_011.sql` - `C:\web\dev.biuro> docker exec -i dev-biuro-mysql mysqldump -udev_user -pY6V6bFkD6@GyD!wTShgFmWz! --default-character-set=utf8 dev_biuro > docker/mariadb/data-001.sql`
### DB restore ### DB restore
- `C:\web\dev.biuro> docker exec -i mysql mysql -uroot -pIiIjnsLi2wR9i1kWVbVpUAzP --default-character-set=utf8 wordpress < docker/mariadb/db_010.sql` - `C:\web\dev.biuro> docker exec -i dev-biuro-mysql mysql -udev_user -pY6V6bFkD6@GyD!wTShgFmWz! --default-character-set=utf8 dev_biuro < docker/mariadb/data-000.sql`
## Development ## Development
- `C:\web\dev.biuro\wordpress>npm install` - `C:\web\dev.biuro\ npm install`
## Wordpress ## Wordpress
- Regions created using [Wordpress Network](https://codex.wordpress.org/Create_A_Network) - Regions created using [Wordpress Network](https://codex.wordpress.org/Create_A_Network)
...@@ -37,7 +36,7 @@ ...@@ -37,7 +36,7 @@
#### Akismet Anti-Spam #### Akismet Anti-Spam
#### Cookies warning #### Cookies warning
#### Data controller #### Data controller
#### Gutenberg (not yet) #### Jobs importer
#### Permalink Manager Lite #### Permalink Manager Lite
#### Pods - Custom Content Types and Fields #### Pods - Custom Content Types and Fields
#### Polylang #### Polylang
......
...@@ -19,6 +19,8 @@ services: ...@@ -19,6 +19,8 @@ services:
- ./wp-content/plugins/cookies-warning:/var/www/html/wp-content/plugins/cookies-warning - ./wp-content/plugins/cookies-warning:/var/www/html/wp-content/plugins/cookies-warning
- ./wp-content/plugins/data-controller:/var/www/html/wp-content/plugins/data-controller - ./wp-content/plugins/data-controller:/var/www/html/wp-content/plugins/data-controller
- ./wp-content/plugins/jobs-importer:/var/www/html/wp-content/plugins/jobs-importer
- ./wp-content/plugins/permalink-manager:/var/www/html/wp-content/plugins/permalink-manager - ./wp-content/plugins/permalink-manager:/var/www/html/wp-content/plugins/permalink-manager
- ./wp-content/plugins/pods:/var/www/html/wp-content/plugins/pods - ./wp-content/plugins/pods:/var/www/html/wp-content/plugins/pods
- ./wp-content/plugins/polylang:/var/www/html/wp-content/plugins/polylang - ./wp-content/plugins/polylang:/var/www/html/wp-content/plugins/polylang
...@@ -60,6 +62,8 @@ services: ...@@ -60,6 +62,8 @@ services:
- ./wp-content/plugins/cookies-warning:/var/www/html/wp-content/plugins/cookies-warning - ./wp-content/plugins/cookies-warning:/var/www/html/wp-content/plugins/cookies-warning
- ./wp-content/plugins/data-controller:/var/www/html/wp-content/plugins/data-controller - ./wp-content/plugins/data-controller:/var/www/html/wp-content/plugins/data-controller
- ./wp-content/plugins/jobs-importer:/var/www/html/wp-content/plugins/jobs-importer
- ./wp-content/plugins/permalink-manager:/var/www/html/wp-content/plugins/permalink-manager - ./wp-content/plugins/permalink-manager:/var/www/html/wp-content/plugins/permalink-manager
- ./wp-content/plugins/pods:/var/www/html/wp-content/plugins/pods - ./wp-content/plugins/pods:/var/www/html/wp-content/plugins/pods
- ./wp-content/plugins/polylang:/var/www/html/wp-content/plugins/polylang - ./wp-content/plugins/polylang:/var/www/html/wp-content/plugins/polylang
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<?php
/**
* Class DataCollector - Prepare data for import into WP posts
*
* @package Biuro Jobs importer
* @used-by \jobs-importer\job-importer.php
*/
class DataCollector
{
// Data mapping
protected $dataMap = [
'livas-id' => '@livas_id',
'valid' => '@valid',
'division' => 'division',
'name' => 'title',
// 'position' => 'PAREIGOS',
'post_content' => 'content',
// 'tag' => 'other_info',
'type' => 'type',
'field' => 'field',
'city' => 'city',
'company' => 'company',
'email' => 'email',
'contact' => 'contact',
'post_date' => '@published_date',
'post_modified' => '@updated',
'lang' => '@lang',
];
// Relations mapping
protected $relationsMap = [
'division' => 'division-id'
];
// Fields, witch separates in metalanguages environment
protected $multilingual = ['city', 'division', /*'position',*/ 'company', 'type', 'field'];
// Records container's node tag name
protected $containerTag = 'ads';
// Item's node tag name
protected $elementTag = 'ad';
// Initial options for xml parser
private $parserDefaults = [
'namespaceSeparator' => ':',//you may want this to be something other than a colon
'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name
'alwaysArray' => array(), //array of xml tag names which should always become arrays
'autoArray' => true, //only create arrays for tags which appear more than once
'textContent' => '$', //key used for the text content of elements
'autoText' => true, //skip textContent key if node has no attributes or child nodes
'keySearch' => false, //optional search and replace on tag and attribute names
'keyReplace' => false //replace values for above search values (as passed to str_replace())
];
// Source data
protected $sourceData;
protected $data;
public function __construct($source)
{
$this->setData($source);
$this->transformData();
}
/**
* Set data source:
* get data from source and transform into array
*
* @param $source
*/
protected function setData($source)
{
$this->sourceData = $this->xmlToArray($this->loadData($source));
}
/**
* Parse xml data
*
* @param $source
*
* @return SimpleXMLElement
*/
protected function loadData($source)
{
$context = stream_context_create([
'http' => [
'header' => 'Accept: application/xml',
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
],
]);
$xml = file_get_contents($source, false, $context);
return simplexml_load_string($xml);
}
/**
* Get data
*
* @return mixed
*/
public function getData()
{
return $this->data;
}
/**
* Transform data for import
*/
protected function transformData()
{
$transformed = [];
$parsedData = $this->sourceData;
if (array_key_exists($this->containerTag, $parsedData)) {
$container = $parsedData[$this->containerTag];
if (array_key_exists($this->elementTag, $container)) {
foreach ($container[$this->elementTag] as $elementData) {
$lang = $elementData['@lang'];
$element = [];
foreach ($this->dataMap as $key => $item) {
$itemValue = (empty($elementData[$item])) ? '' : $elementData[$item];
$value = (is_array($itemValue))
? [$this->getKey($key, $itemValue, $lang) => html_entity_decode($this->getValue($itemValue))]
: html_entity_decode($itemValue);
$element[$key] = $value;
if (array_key_exists($key, $this->relationsMap)) {
$element['related_items'][$key] = $this->relationsMap[$key];
}
}
$transformed[] = $element;
}
}
}
$this->data = $transformed;
}
/**
* Get value
*
* @param $value
*
* @return mixed|string
*/
private function getValue($value)
{
if (is_array($value)) {
if (array_key_exists('@key', $value)) {
return (isset($value['$'])) ? $value['$'] : '';
}
}
return $value;
}
/**
* Get key
*
* @param $key
* @param $value
* @param $lang
*
* @return string
*/
private function getKey($key, $value, $lang)
{
if (is_array($value)) {
if (array_key_exists('@key', $value)) {
$key_id = '-' . $value['@key'];
return $key . $key_id . $this->addLang($key, $lang);
}
}
return $key . $this->addLang($key, $lang);
}
/**
* Adds language slug
*
* @param $key
* @param $lang
*
* @return string
*/
private function addLang($key, $lang)
{
if (in_array($key, $this->multilingual)) {
return '-' . $lang;
}
return '';
}
/**
* XML parser, return array
*
* @param $xml
* @param array $options
*
* @return array
*/
function xmlToArray($xml, $options = array())
{
$options = array_merge($this->parserDefaults, $options);
$namespaces = $xml->getDocNamespaces();
$namespaces[''] = null; //add base (empty) namespace
//get attributes from all namespaces
$attributesArray = array();
foreach ($namespaces as $prefix => $namespace) {
foreach ($xml->attributes($namespace) as $attributeName => $attribute) {
//replace characters in attribute name
if ($options['keySearch']) {
$attributeName =
str_replace($options['keySearch'], $options['keyReplace'], $attributeName);
}
$attributeKey = $options['attributePrefix']
. ($prefix ? $prefix . $options['namespaceSeparator'] : '')
. $attributeName;
$attributesArray[$attributeKey] = (string)$attribute;
}
}
//get child nodes from all namespaces
$tagsArray = array();
foreach ($namespaces as $prefix => $namespace) {
foreach ($xml->children($namespace) as $childXml) {
//recurse into child nodes
$childArray = $this->xmlToArray($childXml, $options);
// list($childTagName, $childProperties) = each($childArray);
foreach ($childArray as $key => $item) {
$childTagName = $key;
$childProperties = $item;
}
//replace characters in tag name
if ($options['keySearch']) {
$childTagName =
str_replace($options['keySearch'], $options['keyReplace'], $childTagName);
}
//add namespace prefix, if any
if ($prefix) {
$childTagName = $prefix . $options['namespaceSeparator'] . $childTagName;
}
if (!isset($tagsArray[$childTagName])) {
//only entry with this key
//test if tags of this type should always be arrays, no matter the element count
$tagsArray[$childTagName] =
in_array($childTagName, $options['alwaysArray']) || !$options['autoArray']
? array($childProperties) : $childProperties;
} elseif (
is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName])
=== range(0, count($tagsArray[$childTagName]) - 1)
) {
//key already exists and is integer indexed array
$tagsArray[$childTagName][] = $childProperties;
} else {
//key exists so convert to integer indexed array with previous value in position 0
$tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties);
}
}
}
//get text content of node
$textContentArray = array();
$plainText = trim((string)$xml);
if ($plainText !== '') {
$textContentArray[$options['textContent']] = $plainText;
}
//stick it all together
$propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '')
? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText;
//return node as array
return array(
$xml->getName() => $propertiesArray
);
}
}
<?php
/**
* Class JobsImporter - Import data to WP posts with custom fields
*
* @uses Pods framework
* @package Biuro Jobs importer
* @used-by \jobs-importer\job-importer.php
*/
class JobsImporter {
private $data;
// Biuro record unique key
protected $primaryKey = 'livas-id';
// Pods instance
protected $pods;
// Posts container in WP
protected $podsType = 'job';
// Additional post fields
protected $postProperties = [
'post_status' => 'publish',
'comment_status' => 'closed'
];
public function __construct($data)
{
$this->data = $data;
$this->setPods();
}
/**
* Set Pods instance
*/
private function setPods()
{
$this->pods = pods($this->podsType);
}
/**
* Get related items mapping array and remove it from data array
*
* @param $data
*
* @return array
*/
private function getRelations(&$data)
{
$relations = [];
if (array_key_exists('related_items', $data)) {
$relations = $data['related_items'];
unset($data['related_items']);
}
return $relations;
}
/**
* Import posts from provided data: if post with given Id exists, it rewrites
*/
public function import()
{
foreach ($this->data as $ad) {
// Get related items
$relations = $this->getRelations($ad);
// Prepare data array fro importing
$this->prepare($ad, $relations);
// Unique key of post
$primaryKey = $ad[$this->primaryKey];
$pod = $this->getPod($primaryKey);
if ($pod->total_found() > 0) {
try {
$podId = $pod->save(array_merge($ad, $this->postProperties));
print_r("Old record ($this->idKey: $primaryKey) has been updated. <br>");
} catch (Exception $e) {
print_r("Error while updating record ($this->idKey: $primaryKey). Error: $e->getMessage()<br>");
}
} else {
try {
$podId = $this->pods->add(array_merge($ad, $this->postProperties));
print_r("New record ($this->idKey: $primaryKey) has been created. <br>");
} catch (Exception $e) {
print_r("Error while creating record ($this->idKey: $primaryKey). Error: $e->getMessage()<br>");
}
}
if (isset($podId)) {
// Set post language
$this->setPostLang($podId, $ad['lang']);
}
}
}
/**
* Creates related pods if needed and prepare data array fro import
*
* @param $ad
* @param $relations
*/
private function prepare(&$ad, $relations)
{
foreach ($ad as $key => $item) {
$lang = $ad['lang'];
if (is_array($item)) {
$slug = array_keys($item)[0];
$value = array_values($item)[0];
$termId = $this->getTerm($key, $slug, $value, $lang);
$ad[$key] = $slug;
// Adding related item if exists
if (array_key_exists($key, $relations)) {
$ad[$relations[$key]] = $termId;
}
}
}
}
/**
* Find and return pod id, if not exist, create it
*
* @param $key
* @param $slug
* @param $value
* @param $lang
*
* @return int
*/
private function getTerm($key, $slug, $value, $lang)
{
$term = pods($key, $slug);
if ( ! $term->exists()) {
try {
$termId = pods($key)->add([
'name' => $value,
'slug' => $slug,
]);
if ($termId) {
$this->setTermLang($termId, $lang);
return $termId;
}
} catch (Exception $e) {
print_r("Error while adding taxonomies ($key => $slug). Error: $e->getMessage()<br>");
}
}
return $term->id();
}
/**
* Set language param for given pod, using Polylang library
*
* @param $termId
* @param $lang
*/
private function setPostLang($termId, $lang)
{
try {
PLL()->model->post->set_language($termId, $lang);
print_r("Set language code '$lang' for item. <br>");
} catch (Exception $e) {
print_r("Error while setting language code for item, error: $e->getMessage().<br>");
}
}
/**
* Set language param for given taxonomy, using Polylang library
*
* @param $termId
* @param $lang
*/
private function setTermLang($termId, $lang)
{
try {
// PLL()->model->post->set_language($termId, $lang);
PLL()->model->term->save_translations($termId, $lang);
print_r("Set language code '$lang' for item. <br>");
} catch (Exception $e) {
print_r("Error while setting language code for item, error: $e->getMessage().<br>");
}
}
/**
* Get pod by given id
*
* @param $id
*
* @return mixed
*/
private function getPod($id)
{
$params = [
'where' => [
'relation' => 'AND',
[
'value' => (int) $id,
'key' => $this->idKey,
'compare' => '=',
]
]
];
return $this->pods->find($params);
}
}
<?php
/*
Plugin Name: Biuro Jobs importer
description: A plugin for import jobs ads from Biuro endpoint
Version: 1.0.0
*/
set_time_limit(300);
// Data collector: prepare data for import
require_once 'DataCollector.php';
// Data importer: imports data to WP posts
require_once 'JobsImporter.php';
if (function_exists('importer_admin_menu')) {
// Add item to admin menu
add_action('admin_menu', 'importer_admin_menu');
}
/**
* Set admin menu item for plugin
*/
function importer_admin_menu()
{
add_submenu_page(
'options-general.php',
'Biuro Jobs importer',
'Biuro Jobs importer',
'data_importer',
'jobs-importer',
'do_import'
);
}
/**
* Imports posts from Biuro endpoint
*/
function do_import()
{
// Set environment type
// $env = 'prod';
$env = 'dev';
// Set data source path by environment type
if ($env === 'dev') {
// $inputFile = plugin_dir_path(__FILE__) . "source_data/wp_biuro.php.xml";
$inputFile = "https://base.biuro.lt/_export/wp_biuro.php";
} elseif ($env === 'prod') {
$inputFile = "http://export.biuro.lt/wp_biuro.php";
}
echo "<pre>";
print_r('<h4>Biuro Jobs importer</h4>');
print_r("Running in <strong>$env</strong> environment.");
echo "<br><br>";
print_r("Data source: $inputFile<br>");
// XML reader
$ads = (new DataCollector($inputFile))->getData();
print_r("Found " . count($ads) . " ads from Biuro.<br>");
if (count($ads) > 0) {
print_r("importing....<br><br>");
// Posts (via Pods framework) creator
(new JobsImporter($ads))->import();
} else {
print_r("<br>There is nothing more to do.");
}
echo "</pre>";
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="UTF-8"?>
<SKELBIMAI>
<SKELBIMAS ID="13138" KALBA="en" TIPAS="1" PASKELBTA="0000-00-00" GALIOJA="2018-11-30" ATNAUJINTA="2018-11-29 10:13:24">
<IMONE>BIURO - padedame, kai labiausiai reikia. Paprastas ir greitas laikinasis įdarbinimas.</IMONE>
<LOGO></LOGO>
<RUSIS>Pastovus darbas</RUSIS>
<SRITIS>Administravimas </SRITIS>
<PAREIGOS>DIREKTORIUS</PAREIGOS>
<APRASYMAS><![CDATA[
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="http://biuro.lt/job-ads/job-description.jpg" alt="" width="40" height="51"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Užduotys būsimam (-ai) darbuotojui (-ai):&lt;/h3&gt;
&lt;p&gt;Gerai vadovaut&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="http://biuro.lt/job-ads/job-requirements.jpg" alt="" width="39" height="46"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Tikimės šių savybių ir įgūdžių:&lt;/h3&gt;
&lt;p&gt;Vadovavimo&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="http://biuro.lt/job-ads/job-offer-eu.jpg" alt="" width="38" height="52"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Siūlome:&lt;/h3&gt;
&lt;p&gt;Maisto&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
]]></APRASYMAS>
<KITA><![CDATA[
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="https://biuro.lt/job-ads/job-contacts.jpg" alt="" width="33" height="48"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Kontaktinė informacija:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;skambinkite &lt;a class="gtm-b2c-phone-click" href="tel:866611222"&gt;866611222&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;rašykite &lt;a class="gtm-b2c-email-click" href="mailto:andrius.mickus@biuro.eu"&gt;andrius.mickus@biuro.eu&lt;/a&gt; laiško pavadinime nurodant „Direktorius“;&lt;/li&gt;
&lt;li&gt;registruokitės internetu per 30 sekundžių: &lt;a href="https://www.biuro.lt/darbo-paieska/klauskite/"&gt;https://www.biuro.lt/darbo-paieska/klauskite/&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;atvykite: &lt;a href="https://maps.google.com/?q=Gedimino pr. 26, Vilnius" target="_blank" rel="noopener"&gt;Gedimino pr. 26, Vilnius&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sekite naujienas prisijungę prie BIURO Facebook puslapio: &lt;a href="https://www.facebook.com/biuro.lietuva" target="_blank" rel="noopener" onclick="dataLayer.push({'event': 'socialClick', 'socialLabel': 'FB click'});"&gt;https://www.facebook.com/biuro.lietuva&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;]]></KITA>
<VIETA>Vilnius</VIETA>
<RODYTI>
<LANG ID="lt"/>
<LANG ID="en"/>
<LANG ID="ru"/>
</RODYTI>
<EPASTAS>andrius.mickus@biuro.eu</EPASTAS>
<PADALINYS></PADALINYS>
<DARBOLAIKAS></DARBOLAIKAS>
<KONTAKTASMUO></KONTAKTASMUO>
</SKELBIMAS>
<SKELBIMAS ID="12998" KALBA="lt" TIPAS="1" PASKELBTA="0000-00-00" GALIOJA="2018-11-29" ATNAUJINTA="2018-11-29 09:47:56">
<IMONE>BIURO - padedame, kai labiausiai reikia. Paprastas ir greitas laikinasis įdarbinimas.</IMONE>
<LOGO>http://export.biuro.lt/logo/182110322.png</LOGO>
<RUSIS>Pastovus darbas</RUSIS>
<SRITIS>Pramonė / Gamyba </SRITIS>
<PAREIGOS>STALIUS - MONTUOTOJAS</PAREIGOS>
<APRASYMAS><![CDATA[
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="http://biuro.lt/job-ads/job-description.jpg" alt="" width="40" height="51"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Užduotys būsimam (-ai) darbuotojui (-ai):&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;gaminių paruošimas išvežimui į objektus ir jų montavimas;&lt;/li&gt;
&lt;li&gt;medžio-stiklo konstrukcijų montavimas;&lt;/li&gt;
&lt;li&gt;langų-durų montavimas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Darbo vieta: Klaipėda&lt;/p&gt;
&lt;p&gt;Darbo grafikas: 8-17, I-V.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="http://biuro.lt/job-ads/job-requirements.jpg" alt="" width="39" height="46"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Tikimės šių savybių ir įgūdžių:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;gebėjimo skaityti brėžinius;&lt;/li&gt;
&lt;li&gt;techninio supratimo;&lt;/li&gt;
&lt;li&gt;B kategorijos vairuotojo pažymėjimo;&lt;/li&gt;
&lt;li&gt;panaši darbo patirtis privalumas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="http://biuro.lt/job-ads/job-offer-eu.jpg" alt="" width="38" height="52"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Siūlome:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;pastovų darbo grafiką;&lt;/li&gt;
&lt;li&gt;priedus pagal atlikto darbo rezultatus;&lt;/li&gt;
&lt;li&gt;socialines garantijas ir laiku mokamą darbo užmokestį.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
]]></APRASYMAS>
<KITA><![CDATA[
&lt;div class="biuro-ti"&gt;
&lt;div class="biuro-ti-img"&gt;
&lt;img src="https://biuro.lt/job-ads/job-contacts.jpg" alt="" width="33" height="48"&gt;
&lt;/div&gt;
&lt;div class="biuro-ti-text"&gt;
&lt;h3&gt;Kontaktinė informacija:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;skambinkite &lt;a class="gtm-b2c-phone-click" href="tel:+370 46 246648"&gt;+370 46 246648&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;rašykite &lt;a class="gtm-b2c-email-click" href="mailto:klaipedacv@biuro.lt"&gt;klaipedacv@biuro.lt&lt;/a&gt; laiško pavadinime nurodant „Stalius - montuotojas“;&lt;/li&gt;
&lt;li&gt;registruokitės internetu per 30 sekundžių: &lt;a href="https://www.biuro.lt/darbo-paieska/klauskite/"&gt;https://www.biuro.lt/darbo-paieska/klauskite/&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;atvykite: &lt;a href="https://maps.google.com/?q=Pilies g. 8 - 101, Klaipėda" target="_blank" rel="noopener"&gt;Pilies g. 8 - 101, Klaipėda&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sekite naujienas prisijungę prie BIURO Facebook puslapio: &lt;a href="https://www.facebook.com/biuro.lietuva" target="_blank" rel="noopener" onclick="dataLayer.push({'event': 'socialClick', 'socialLabel': 'FB click'});"&gt;https://www.facebook.com/biuro.lietuva&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;]]></KITA>
<VIETA>Klaipėda</VIETA>
<RODYTI>
<LANG ID="lt"/>
</RODYTI>
<EPASTAS>klaipedacv@biuro.lt</EPASTAS>
<PADALINYS></PADALINYS>
<DARBOLAIKAS></DARBOLAIKAS>
<KONTAKTASMUO></KONTAKTASMUO>
</SKELBIMAS>
</SKELBIMAI>
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
Preamble Preamble
The licenses for most software are designed to take away your The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to the GNU Lesser General Public License instead.) You can apply it to
your programs, too. your programs, too.
When we speak of free software, we are referring to freedom, not When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things. in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights. anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it. distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their source code. And you must show them these terms so they know their
rights. rights.
We protect your rights with two steps: (1) copyright the software, and We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy, (2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software. distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original that any problems introduced by others will not reflect on the original
authors' reputations. authors' reputations.
Finally, any free program is threatened constantly by software Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all. patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and The precise terms and conditions for copying, distribution and
modification follow. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains 0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below, under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program" refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law: means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it, that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you". the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program). Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does. Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's 1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty; notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License and give any other recipients of the Program a copy of this License
along with the Program. along with the Program.
You may charge a fee for the physical act of transferring a copy, and You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee. you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion 2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1 distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions: above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change. stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License. parties under the terms of this License.
c) If the modified program normally reads commands interactively c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on does not normally print such an announcement, your work based on
the Program is not required to print an announcement.) the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it. entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or exercise the right to control the distribution of derivative or
collective works based on the Program. collective works based on the Program.
In addition, mere aggregation of another work not based on the Program In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under a storage or distribution medium does not bring the other work under
the scope of this License. the scope of this License.
3. You may copy and distribute the Program (or a work based on it, 3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following: Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or, 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or, customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such received the program in object code or executable form with such
an offer, in accord with Subsection b above.) an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component operating system on which the executable runs, unless that component
itself accompanies the executable. itself accompanies the executable.
If distribution of executable or object code is made by offering If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not distribution of the source code, even though third parties are not
compelled to copy the source along with the object code. compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program 4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License. void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such this License will not have their licenses terminated so long as such
parties remain in full compliance. parties remain in full compliance.
5. You are not required to accept this License, since you have not 5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying all its terms and conditions for copying, distributing or modifying
the Program or works based on it. the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the 6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein. restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to You are not responsible for enforcing compliance by third parties to
this License. this License.
7. If, as a consequence of a court judgment or allegation of patent 7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues), infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program. refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other apply and the section as a whole is intended to apply in other
circumstances. circumstances.
It is not the purpose of this section to induce you to infringe any It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is integrity of the free software distribution system, which is
implemented by public license practices. Many people have made implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot to distribute software through any other system and a licensee cannot
impose that choice. impose that choice.
This section is intended to make thoroughly clear what is believed to This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License. be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in 8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License. the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions 9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to be similar in spirit to the present version, but may differ in detail to
address new problems or concerns. address new problems or concerns.
Each version is given a distinguishing version number. If the Program Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software this License, you may choose any version ever published by the Free Software
Foundation. Foundation.
10. If you wish to incorporate parts of the Program into other free 10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally. of promoting the sharing and reuse of software generally.
NO WARRANTY NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION. REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms. free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.> <one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author> Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc., with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this If the program is interactive, make it output a short notice like this
when it starts in an interactive mode: when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program. mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names: necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker. `Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989 <signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice Ty Coon, President of Vice
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. Public License instead of this License.
\ No newline at end of file
=== Permalink Manager Lite === === Permalink Manager Lite ===
Contributors: mbis Contributors: mbis
Donate link: https://www.paypal.me/Bismit Donate link: https://www.paypal.me/Bismit
License: GPLv3 License: GPLv3
License URI: http://www.gnu.org/licenses/gpl-2.0.html License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: urls, permalinks, custom permalinks, url, permalink, woocommerce permalinks Tags: urls, permalinks, custom permalinks, url, permalink, woocommerce permalinks
Requires at least: 4.4.0 Requires at least: 4.4.0
Requires PHP: 5.4 Requires PHP: 5.4
Tested up to: 4.9 Tested up to: 5.0
Stable tag: 2.1.1 Stable tag: 2.1.2
Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible). Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
== Description == == Description ==
Permalink Manager is a most advanced and highly rated Wordpress permalink plugin that helps Wordpress users to control the URL addresses of all posts, pages, custom post type elements (taxonomies are supported in Pro version). To avoid 404 or duplicated content errors after the new custom permalink is defined, the visitors trying to access the old permalink will be automatically redirected to the new custom URL. Permalink Manager is a most advanced and highly rated Wordpress permalink plugin that helps Wordpress users to control the URL addresses of all posts, pages, custom post type elements (taxonomies are supported in Pro version). To avoid 404 or duplicated content errors after the new custom permalink is defined, the visitors trying to access the old permalink will be automatically redirected to the new custom URL.
The plugin supports all custom post types & custom taxonomies and popular 3rd party plugins including WooCommerce, Yoast SEO, WPML, and Polylang. To improve SEO performance even more, the plugin settings provide a possibility to disable the canonical redirect (used natively by Wordpress) and control the trailing slashes settings. The plugin supports all custom post types & custom taxonomies and popular 3rd party plugins including WooCommerce, Yoast SEO, WPML, and Polylang. To improve SEO performance even more, the plugin settings provide a possibility to disable the canonical redirect (used natively by Wordpress) and control the trailing slashes settings.
= All features = = All features =
* **Edit full permalinks** | A completely custom permalink can be set for each post, page and public custom post type individually *(categories, tags & custom taxonomies terms permalinks can be edited in Permalink Manager Pro)* * **Edit full permalinks** | A completely custom permalink can be set for each post, page and public custom post type individually *(categories, tags & custom taxonomies terms permalinks can be edited in Permalink Manager Pro)*
* **Custom post types support** | It is also possible to exclude specific post types & taxonomies to stop Permalink Manager from filtering their permalinks. * **Custom post types support** | It is also possible to exclude specific post types & taxonomies to stop Permalink Manager from filtering their permalinks.
* **Custom permastructures** | The plugin allows to specify how the custom permalinks should be formatted by default (when the new post/term is added or after the permalinks are regenerated) * **Custom permastructures** | The plugin allows to specify how the custom permalinks should be formatted by default (when the new post/term is added or after the permalinks are regenerated)
* **Bulk editors** | "Regenerate/Reset" + "Find and replace" tools that allow to bulk/mass change the permalinks (or native slugs). * **Bulk editors** | "Regenerate/Reset" + "Find and replace" tools that allow to bulk/mass change the permalinks (or native slugs).
* **Auto-redirect** | Old (native) permalinks are redirected to new (custom) permalinks (in 301 or 302 mode) to prevent 404 error (SEO friendly). * **Auto-redirect** | Old (native) permalinks are redirected to new (custom) permalinks (in 301 or 302 mode) to prevent 404 error (SEO friendly).
* **Canonical redirects** | Possibility to disable native canonical redirects. * **Canonical redirects** | Possibility to disable native canonical redirects.
* **Trailing slashes settings** | They can be forced or removed from all permalinks. * **Trailing slashes settings** | They can be forced or removed from all permalinks.
= Additional features available in Permalink Manager Pro = = Additional features available in Permalink Manager Pro =
* **Taxonomies** | Full support for taxonomies (categories, tags & custom taxonomies). * **Taxonomies** | Full support for taxonomies (categories, tags & custom taxonomies).
* **WooCommerce** | Full support for WooCommerce (products, product tags, product categories). Permalink Manager allows to remove /product-category and /product from WooCommerce permalinks. * **WooCommerce** | Full support for WooCommerce (products, product tags, product categories). Permalink Manager allows to remove /product-category and /product from WooCommerce permalinks.
* **WooCommerce coupon URLs** | Coupon codes may have their public URLs (eg. http://shop.com/BLACKFRIDAY) that will automatically apply the discount to the cart. * **WooCommerce coupon URLs** | Coupon codes may have their public URLs (eg. http://shop.com/BLACKFRIDAY) that will automatically apply the discount to the cart.
* **Custom fields** | Custom fields can be used inside permalinks (Advanced Custom Fields plugin supported). * **Custom fields** | Custom fields can be used inside permalinks (Advanced Custom Fields plugin supported).
* **Extra internal redirects** | Multiple URLs can lead to a single post/term (they could be defined individually for each element). * **Extra internal redirects** | Multiple URLs can lead to a single post/term (they could be defined individually for each element).
* **External URL redirect** | Posts/terms can redirect the visitors to external websites (the URLs could be defined individually for each element). * **External URL redirect** | Posts/terms can redirect the visitors to external websites (the URLs could be defined individually for each element).
* **"Stop-words"** | User-defined words will be automatically removed from default permalinks. * **"Stop-words"** | User-defined words will be automatically removed from default permalinks.
* **Custom Permalinks** | Import custom permalinks saved with that plugin. * **Custom Permalinks** | Import custom permalinks saved with that plugin.
* **Priority support** | All the support requests from Permalink Manager Pro users are handled in the first place. * **Priority support** | All the support requests from Permalink Manager Pro users are handled in the first place.
Buy <a href="https://permalinkmanager.pro?utm_source=wordpress">Permalink Manager Pro here</a>. Buy <a href="https://permalinkmanager.pro?utm_source=wordpress">Permalink Manager Pro here</a>.
= Translators = = Translators =
* Japaneese - Shinsaku Ikeda * Japaneese - Shinsaku Ikeda
== Installation == == Installation ==
Go to `Plugins -> Add New` section from your admin account and search for `Permalink Manager`. Go to `Plugins -> Add New` section from your admin account and search for `Permalink Manager`.
You can also install this plugin manually: You can also install this plugin manually:
1. Download the plugin's ZIP archive and unzip it. 1. Download the plugin's ZIP archive and unzip it.
2. Copy the unzipped `permalink-manager` folder to the `/wp-content/plugins/` directory. 2. Copy the unzipped `permalink-manager` folder to the `/wp-content/plugins/` directory.
3. Activate the plugin through the 'Plugins' menu in WordPress 3. Activate the plugin through the 'Plugins' menu in WordPress
= Bulk URI editor = = Bulk URI editor =
After the plugin is installed you can access its dashboard from this page: `Tools -> Permalink Manager`. After the plugin is installed you can access its dashboard from this page: `Tools -> Permalink Manager`.
= Single URI editor = = Single URI editor =
To display the URI editor metabox click on gray "Permalink Editor" displayed below the post/page title. To display the URI editor metabox click on gray "Permalink Editor" displayed below the post/page title.
== Frequently Asked Questions == == Frequently Asked Questions ==
= Q. Can I delete/disable Permalink Manager after the permalinks are updated? = = Q. Can I delete/disable Permalink Manager after the permalinks are updated? =
A. Yes, if you used Permalink Manager only to regenerate the slugs (native post names). Please note that if you use custom permalinks (that differ from the native ones), they will no longer be used after the plugin is disabled. A. Yes, if you used Permalink Manager only to regenerate the slugs (native post names). Please note that if you use custom permalinks (that differ from the native ones), they will no longer be used after the plugin is disabled.
It is because Permalink Manager overwrites one of the core Wordpress functionalities to bypass the rewrite rules ("regular expressions" to detect the posts/pages/taxonomies/etc. and another parameters from the URL) by using the array of custom permalinks (you can check them in "Debug" tab) that are used only by my plugin. It is because Permalink Manager overwrites one of the core Wordpress functionalities to bypass the rewrite rules ("regular expressions" to detect the posts/pages/taxonomies/etc. and another parameters from the URL) by using the array of custom permalinks (you can check them in "Debug" tab) that are used only by my plugin.
= Q. Can I use Permalink Manager to change the terms permalinks (eg. post or product categories)? = Q. Can I use Permalink Manager to change the terms permalinks (eg. post or product categories)?
A. This feature is available only in Permalink Manager Pro. A. This feature is available only in Permalink Manager Pro.
= Q. Does this plugin support Buddypress? = Q. Does this plugin support Buddypress?
A. Currently there is no 100% guarantee that Permalink Manager will work correctly with Buddypress. A. Currently there is no 100% guarantee that Permalink Manager will work correctly with Buddypress.
== Screenshots == == Screenshots ==
1. "Permalink editor". 1. "Permalink editor".
2. "Find and replace" section. 2. "Find and replace" section.
3. "Regenerate/Reset" section. 3. "Regenerate/Reset" section.
4. "Permastructures" section. 4. "Permastructures" section.
5. A list of updated posts. 5. A list of updated posts.
6. Editable URI box in Post/Page/CPT edit pagees. 6. Editable URI box in Post/Page/CPT edit pagees.
7. Settings section. 7. Settings section.
8. URI Editor in Gutenberg.
== Changelog ==
== Changelog ==
= 2.1.1 =
* Support for draft custom permalinks = 2.1.2 =
* Support for WP All Import plugin, now the custom permalinks can be defined directly in XML, CSV, ZIP, GZIP, GZ, JSON, SQL, TXT, DAT or PSV import files. * Hotfix for WP All Import - default permalinks are now assigned correctly to imported posts + possibility to disable WP All Import custom URI functions in Permalink Manager settings
* Hotfix for Permalink_Manager_Pro_Functions::save_redirects() method - now the custom redirects are correctly saved when a custom permalink is updated. * Hotfix for Yoast SEO - notice displayed on author pages
* Hotfix for "Language name added as a parameter" mode in "WPML Language URL format" settings. * Adjustments for sanitize slug functions
* Hotfix for canonical redirect triggered by WPML. * Basic support for Gutenberg added
* Better support for non-latin letters in custom URIs & redirects
* Better support for endpoints = 2.1.1 =
* Searchbox in URI Editors * Support for draft custom permalinks
* Support for WP All Import plugin, now the custom permalinks can be defined directly in XML, CSV, ZIP, GZIP, GZ, JSON, SQL, TXT, DAT or PSV import files.
= 2.1.0 = * Hotfix for Permalink_Manager_Pro_Functions::save_redirects() method - now the custom redirects are correctly saved when a custom permalink is updated.
* Support for "url_to_postid" function * Hotfix for "Language name added as a parameter" mode in "WPML Language URL format" settings.
* Bulk tools use now AJAX & transients to prevent timeout when large number of posts/terms is processed * Hotfix for canonical redirect triggered by WPML.
* Fix for multi-domain language setup in WPML * Better support for non-latin letters in custom URIs & redirects
* Better support for endpoints
= 2.0.6.5 = * Searchbox in URI Editors
* Support for %__sku% permastructure tag (WooCommerce) added - now SKU number can be added to the custom permalinks (Permalink Manager Pro)
* Hotfix for license validation system = 2.1.0 =
* Support for "url_to_postid" function
= 2.0.6.4 = * Bulk tools use now AJAX & transients to prevent timeout when large number of posts/terms is processed
* Code optimization * Fix for multi-domain language setup in WPML
* New filter: permalink_manager_fix_uri_duplicates
* Possibility to display the native slug field = 2.0.6.5 =
* Hotfix for license validation functions * Support for %__sku% permastructure tag (WooCommerce) added - now SKU number can be added to the custom permalinks (Permalink Manager Pro)
* Hotfix for license validation system
= 2.0.6.3.2 =
* Support added for Revisionize plugin = 2.0.6.4 =
* Minor tweaks * Code optimization
* New filter: permalink_manager_fix_uri_duplicates
= 2.0.6.2/2.0.6.3 = * Possibility to display the native slug field
* Japaneese translation added * Hotfix for license validation functions
* Some minor improvements
* New filters: permalink_manager_hide_uri_editor_term_{$term->taxonomy}, permalink_manager_hide_uri_editor_post_{$post->post_type} & permalink_manager_update_term_uri_{$this_term->taxonomy}, permalink_manager_update_post_uri_{$post->post_type}, permalink_manager_new_post_uri_{$post_object->post_type} = 2.0.6.3.2 =
* Hotfix for default permalinks (no-hierarchical post types) * Support added for Revisionize plugin
* Hotfix for attachments default permalinks + URI detect function * Minor tweaks
= 2.0.6.1 = = 2.0.6.2/2.0.6.3 =
* Hotfix for endpoints in REGEX * Japaneese translation added
* Minor bug fixed - native slugs are now correctly regenerated * Some minor improvements
* Hotfix for URI sanitization functions * New filters: permalink_manager_hide_uri_editor_term_{$term->taxonomy}, permalink_manager_hide_uri_editor_post_{$post->post_type} & permalink_manager_update_term_uri_{$this_term->taxonomy}, permalink_manager_update_post_uri_{$post->post_type}, permalink_manager_new_post_uri_{$post_object->post_type}
* Hotfix for AMP plugin * Hotfix for default permalinks (no-hierarchical post types)
* Full support for WPML multi-domain language setup * Hotfix for attachments default permalinks + URI detect function
* Hotfix for VisualComposer + Yoast SEO JS functions
* Hotfix for WPML String Translation = 2.0.6.1 =
* Hotfix for endpoints in REGEX
= 2.0.6.0 = * Minor bug fixed - native slugs are now correctly regenerated
* Minor bugs fixed * Hotfix for URI sanitization functions
* New permastrutcure tag - %native_slug% * Hotfix for AMP plugin
* "Force custom slugs" feature enhanced with new options * Full support for WPML multi-domain language setup
* Possibility to redirect the posts & terms to external URL (Permalink Manager Pro) * Hotfix for VisualComposer + Yoast SEO JS functions
* Hotfix for WPML String Translation
= 2.0.5.9 =
* New permastructure tags - %post_type% & %taxonomy% = 2.0.6.0 =
* Support for "Taxonomy" custom field in ACF (Advanced Custom Fields) * Minor bugs fixed
* Minor fix for endpoints * New permastrutcure tag - %native_slug%
* New hook - "permalink_manager-filter-permalink-base" used instead of "permalink-manager-post-permalink-prefix" & "permalink-manager-term-permalink-prefix" * "Force custom slugs" feature enhanced with new options
* Possibility to redirect the posts & terms to external URL (Permalink Manager Pro)
= 2.0.5.7/2.0.5.8 =
* Hotfix for MultilingualPress plugin = 2.0.5.9 =
* Hotfix & better support for attachment post type (Media Library) * New permastructure tags - %post_type% & %taxonomy%
* Custom redirects for old permalinks are now correctly saved in Permalink Manager Pro * Support for "Taxonomy" custom field in ACF (Advanced Custom Fields)
* Support for WooCommerce Wishlist plugin * Minor fix for endpoints
* New hook - "permalink_manager-filter-permalink-base" used instead of "permalink-manager-post-permalink-prefix" & "permalink-manager-term-permalink-prefix"
= 2.0.5.6 =
* The URIs for trashed posts are now correctly removed = 2.0.5.7/2.0.5.8 =
* Better support for non-ASCII characters in URIs * Hotfix for MultilingualPress plugin
* Minor fix for hierarchical post types * Hotfix & better support for attachment post type (Media Library)
* Fix for coupon URL redirect * Custom redirects for old permalinks are now correctly saved in Permalink Manager Pro
* New filter - "permalink-manager-force-hyphens" * Support for WooCommerce Wishlist plugin
= 2.0.5.5 = = 2.0.5.6 =
* Discount URLs for WooCommerce - now the shop clients can use coupons' custom URIs to easily apply the discount to the cart * The URIs for trashed posts are now correctly removed
* Extra AJAX check for duplicated URIs in "Edit URI" box * Better support for non-ASCII characters in URIs
* Wordpress CronJobs for "Automatically remove duplicates" functionality * Minor fix for hierarchical post types
* Extra improvements in "save_post/update_term" hooks * Fix for coupon URL redirect
* Fix for terms permalinks added via "Edit post" page * New filter - "permalink-manager-force-hyphens"
* New filter - "permalink-manager-force-lowercase-uris"
= 2.0.5.5 =
= 2.0.5.4 = * Discount URLs for WooCommerce - now the shop clients can use coupons' custom URIs to easily apply the discount to the cart
* New filter - "permalink_manager_empty_tag_replacement" * Extra AJAX check for duplicated URIs in "Edit URI" box
* Fix for term placeholder tags in taxonomies permastructures * Wordpress CronJobs for "Automatically remove duplicates" functionality
* Page pagination improvement (404 error page for non-existing pages) * Extra improvements in "save_post/update_term" hooks
* New settings field for pagination redirect * Fix for terms permalinks added via "Edit post" page
* Trailing slashes are no longer added to custom permalinks ended with extension, eg. .html, or .php * New filter - "permalink-manager-force-lowercase-uris"
= 2.0.5.3 = = 2.0.5.4 =
* Hotfix for redirects - redirect chain no longer occurs (WPML) * New filter - "permalink_manager_empty_tag_replacement"
* Now $wp_query->is_404() is set to false when custom URI is detected * Fix for term placeholder tags in taxonomies permastructures
* Hotfix for ACF custom fields in terms * Page pagination improvement (404 error page for non-existing pages)
* Fix for trailing slash (in admin dashboard), also the trailing slashes are removed from permalinks containing GET parameters or hastags (often used by 3rd party plugins) * New settings field for pagination redirect
* Trailing slashes are no longer added to custom permalinks ended with extension, eg. .html, or .php
= 2.0.5.2.2 =
* Hotfix for admin requests (+ compatibility with WooCommerce TM Extra Product Options) = 2.0.5.3 =
* Hotfix for no-ASCII characters in custom URIs * Hotfix for redirects - redirect chain no longer occurs (WPML)
* Hotfix for attachments * Now $wp_query->is_404() is set to false when custom URI is detected
* Hotfix for ACF custom fields in terms
= 2.0.5.2.1 = * Fix for trailing slash (in admin dashboard), also the trailing slashes are removed from permalinks containing GET parameters or hastags (often used by 3rd party plugins)
* Hotfix for endpoints redirect
= 2.0.5.2.2 =
= 2.0.5.1/2.0.5.2 = * Hotfix for admin requests (+ compatibility with WooCommerce TM Extra Product Options)
* Hotfix for REGEX rule * Hotfix for no-ASCII characters in custom URIs
* yoast_attachment_redirect setting removed (it is no longer needed) * Hotfix for attachments
* yoast_primary_term setting replaced with "permalink-manager-primary-term" filter
* Hotfix for WP All Import = 2.0.5.2.1 =
* Hotfix for WooCommerce endpoints * Hotfix for endpoints redirect
* Better support for Polylang
* Support for Theme My Login plugin = 2.0.5.1/2.0.5.2 =
* Hotfix for REGEX rule
= 2.0.5 = * yoast_attachment_redirect setting removed (it is no longer needed)
* Now, the duplicates and unused custom permalinks can be automatically removed * yoast_primary_term setting replaced with "permalink-manager-primary-term" filter
* Better support for endpoints * Hotfix for WP All Import
* "Disable slug appendix" field is no longer needed * Hotfix for WooCommerce endpoints
* %{taxonomy}_flat% tag enhanced for post types permastructures * Better support for Polylang
* Fix for WPML language prefixes in REGEX rule used to detect URIs * Support for Theme My Login plugin
* Possibility to disable Permalink Manager functions for particular post types or taxonomies
= 2.0.5 =
= 2.0.4.3 = * Now, the duplicates and unused custom permalinks can be automatically removed
* Hotfix for problem with custom URIs for new terms & posts * Better support for endpoints
* "Disable slug appendix" field is no longer needed
= 2.0.4.2 = * %{taxonomy}_flat% tag enhanced for post types permastructures
* Trailing slashes redirect adjustment * Fix for WPML language prefixes in REGEX rule used to detect URIs
* Possibility to disable Permalink Manager functions for particular post types or taxonomies
= 2.0.4.1 =
* Hotfix for Elementor and another visual editor plugins = 2.0.4.3 =
* Support for endpoints parsed as $_GET parameters * Hotfix for problem with custom URIs for new terms & posts
= 2.0.4 = = 2.0.4.2 =
* New settings field - "Deep detect" * Trailing slashes redirect adjustment
= 2.0.3.1 = = 2.0.4.1 =
* Fix for Custom Fields tag in permastructures * Hotfix for Elementor and another visual editor plugins
* Support for endpoints parsed as $_GET parameters
= 2.0.3 =
* Custom URI editor in "Quick Edit" = 2.0.4 =
* "Quick/Bulk Edit" hotfix * New settings field - "Deep detect"
* New permastrutcure tag %category_custom_uri%
= 2.0.3.1 =
= 2.0.2 = * Fix for Custom Fields tag in permastructures
* WooCommerce search redirect loop - hotfix
= 2.0.3 =
= 2.0.1 = * Custom URI editor in "Quick Edit"
* WooCommerce endpoints hotfix * "Quick/Bulk Edit" hotfix
* Redirects save notices - hotfix * New permastrutcure tag %category_custom_uri%
= 2.0.0 = = 2.0.2 =
* Extra Redirects - possibility to define extra redirects for each post/term * WooCommerce search redirect loop - hotfix
* New "Tools" section - "Permalink Duplicates"
* UI improvements for taxonomies ("Custom URI" panel) = 2.0.1 =
* Fixes for reported bugs * WooCommerce endpoints hotfix
* Redirects save notices - hotfix
= 1.11.6.3 =
* Slug appendix fix = 2.0.0 =
* Hotfix for WooCommerce checkkout * Extra Redirects - possibility to define extra redirects for each post/term
* New "Tools" section - "Permalink Duplicates"
= 1.11.6 = * UI improvements for taxonomies ("Custom URI" panel)
* Hotfix for taxonomy tags * Fixes for reported bugs
* Hotfix for custom field tags
* Hotfix for Jetpack = 1.11.6.3 =
* Suuport for WP All Import * Slug appendix fix
* Support for Custom Permalinks * Hotfix for WooCommerce checkkout
= 1.11.5.1 = = 1.11.6 =
* Hotfix for "Custom URI" form * Hotfix for taxonomy tags
* Hotfix for Yoast SEO & Visual Composer * Hotfix for custom field tags
* Now it is possible to disable slugs appendix * Hotfix for Jetpack
* Suuport for WP All Import
= 1.11.4 = * Support for Custom Permalinks
* Hotfix for RSS feeds URLs
= 1.11.5.1 =
= 1.11.1 = * Hotfix for "Custom URI" form
* Trailing slashes & Decode URIs - new settings * Hotfix for Yoast SEO & Visual Composer
* Fix for "Bulk Edit" URI reset * Now it is possible to disable slugs appendix
* Partial code refactoring
= 1.11.4 =
= 1.11.0 = * Hotfix for RSS feeds URLs
* Hierarchical taxonomies fix
* New hook: "permalink_manager_filter_final_term_permalink" = 1.11.1 =
* Trailing slashes & Decode URIs - new settings
= 1.10.2 = * Fix for "Bulk Edit" URI reset
* Taxonomies & permastructures fix * Partial code refactoring
= 1.1.1 = = 1.11.0 =
* Typo fix * Hierarchical taxonomies fix
* UI improvements * New hook: "permalink_manager_filter_final_term_permalink"
* Fix for canonical redirects in WPML
= 1.10.2 =
= 1.1.0 = * Taxonomies & permastructures fix
* Partial code refactoring
* "Auto-update" feature = 1.1.1 =
* UI/UX improvements * Typo fix
* Support for AMP plugin by Automattic * UI improvements
* Fix for canonical redirects in WPML
= 1.0.3 =
* Another pagination issue - hotfix = 1.1.0 =
* Partial code refactoring
= 1.0.2 = * "Auto-update" feature
* Post pagination fix * UI/UX improvements
* Basic REGEX support * Support for AMP plugin by Automattic
* 'permalink_manager_filter_final_post_permalink' filter added
= 1.0.3 =
= 1.0.1 = * Another pagination issue - hotfix
* WPML support fixes
= 1.0.2 =
= 1.0.0 = * Post pagination fix
* Further refactoring * Basic REGEX support
* WPML support added * 'permalink_manager_filter_final_post_permalink' filter added
* Some minor issues fixed
* "Sample permalink" support added = 1.0.1 =
* WPML support fixes
= 0.5.2/0.5.3 =
* Another hotfix = 1.0.0 =
* Further refactoring
= 0.5.1 = * WPML support added
* Hotfix for "Settings" section * Some minor issues fixed
* "Sample permalink" support added
= 0.5.0 =
* Code refactoring completed = 0.5.2/0.5.3 =
* Interface changes * Another hotfix
* Hooks enabled
= 0.5.1 =
= 0.4.9 = * Hotfix for "Settings" section
* Hook for removed posts (their URI is now automatically removed)
= 0.5.0 =
= 0.4.8 = * Code refactoring completed
* Pagination bug - SQL formula fix (offset variable) * Interface changes
* Hooks enabled
= 0.4.7 =
* Strict standards - fix for arrays with default values = 0.4.9 =
* Hook for removed posts (their URI is now automatically removed)
= 0.4.6 =
* 302 redirect fix. = 0.4.8 =
* Code optimization. * Pagination bug - SQL formula fix (offset variable)
= 0.4.5 = = 0.4.7 =
* Bug with infinite loop fixed. * Strict standards - fix for arrays with default values
* Bug with revisions ID fixed.
= 0.4.6 =
= 0.4.4 = * 302 redirect fix.
* Redirect for old URIs added. * Code optimization.
* Debug tools added.
= 0.4.5 =
= 0.4.3 = * Bug with infinite loop fixed.
* Hotfix for "Screen Options" save process. * Bug with revisions ID fixed.
= 0.4.2 = = 0.4.4 =
* Hotfix for bulk actions' functions - additional conditional check for arrays added. * Redirect for old URIs added.
* Debug tools added.
= 0.4.1 =
* Hotfix for "Edit Post" URI input (the URIs were reseted after "Update" button was pressed). = 0.4.3 =
* Hotfix for "Screen Options" save process.
= 0.4 =
* Rewrite rules are no longer used (SQL queries are optimized). The plugin uses now 'request' filter to detect the page/post that should be loaded instead. = 0.4.2 =
* Now full URI (including slug) is editable. * Hotfix for bulk actions' functions - additional conditional check for arrays added.
* A few major improvements applied.
* Partial code optimization. = 0.4.1 =
* Hotfix for "Edit Post" URI input (the URIs were reseted after "Update" button was pressed).
= 0.3.4 =
* Hotfix for not working custom taxonomies tags. = 0.4 =
* Now the rewrite rules for custom post types are stored in different way. * Rewrite rules are no longer used (SQL queries are optimized). The plugin uses now 'request' filter to detect the page/post that should be loaded instead.
* Now full URI (including slug) is editable.
= 0.3.3 = * A few major improvements applied.
* Hotfix for bug with dynamic function names in PHP7. * Partial code optimization.
= 0.3.2 = = 0.3.4 =
* Hotfix for front-end permalinks. The custom permastructures worked only in wp-admin. * Hotfix for not working custom taxonomies tags.
* Now the rewrite rules for custom post types are stored in different way.
= 0.3.1 =
* Hotfix for Posts & Pages permastructures = 0.3.3 =
* Hotfix for bug with dynamic function names in PHP7.
= 0.3 =
* Now all permalink parts can be edited - new "Permalink Base Editor" section added. = 0.3.2 =
* Code optimization. * Hotfix for front-end permalinks. The custom permastructures worked only in wp-admin.
* Bugfixes for Screen Options & Edit links.
= 0.3.1 =
= 0.2 = * Hotfix for Posts & Pages permastructures
* First public version.
= 0.3 =
= 0.1 = * Now all permalink parts can be edited - new "Permalink Base Editor" section added.
* A first initial version. * Code optimization.
* Bugfixes for Screen Options & Edit links.
= 0.2 =
* First public version.
= 0.1 =
* A first initial version.
...@@ -8,8 +8,9 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class { ...@@ -8,8 +8,9 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
add_action('admin_init', array($this, 'trigger_action'), 9); add_action('admin_init', array($this, 'trigger_action'), 9);
add_action('admin_init', array($this, 'extra_actions')); add_action('admin_init', array($this, 'extra_actions'));
// Ajax-based bulk tools // Ajax-based functions
add_action('wp_ajax_pm_bulk_tools', array($this, 'pm_bulk_tools')); add_action('wp_ajax_pm_bulk_tools', array($this, 'pm_bulk_tools'));
add_action('wp_ajax_pm_save_permalink', array($this, 'pm_save_permalink'));
add_action('clean_permalinks_event', array($this, 'clean_permalinks_hook')); add_action('clean_permalinks_event', array($this, 'clean_permalinks_hook'));
add_action('init', array($this, 'clean_permalinks_cronjob')); add_action('init', array($this, 'clean_permalinks_cronjob'));
...@@ -189,6 +190,24 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class { ...@@ -189,6 +190,24 @@ class Permalink_Manager_Actions extends Permalink_Manager_Class {
die(); die();
} }
/**
* Save permalink via AJAX
*/
public function pm_save_permalink() {
$element_id = (!empty($_POST['permalink-manager-edit-uri-element-id'])) ? sanitize_text_field($_POST['permalink-manager-edit-uri-element-id']) : '';
if(!empty($element_id) && is_numeric($element_id)) {
Permalink_Manager_URI_Functions_Post::update_post_uri($element_id);
// Reload URI Editor
$element = get_post($element_id);
$html = Permalink_Manager_Admin_Functions::display_uri_box($element, true);
echo $html;
die();
}
}
/** /**
* Update all permalinks in "Permalink Editor" * Update all permalinks in "Permalink Editor"
*/ */
......
...@@ -212,7 +212,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -212,7 +212,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
$checked = ($value == 1) ? "checked='checked'" : ""; $checked = ($value == 1) ? "checked='checked'" : "";
$checkbox_label = (isset($args['checkbox_label'])) ? $args['checkbox_label'] : ''; $checkbox_label = (isset($args['checkbox_label'])) ? $args['checkbox_label'] : '';
$fields .= "<input type='hidden' {$input_atts} value='0' name='{$input_name}' checked=\"checked\" />"; $fields .= "<input type='hidden' {$input_atts} value='0' name='{$input_name}' />";
$fields .= "<label for='{$input_name}'><input type='checkbox' {$input_atts} value='1' name='{$input_name}' {$checked} /> {$checkbox_label}</label>"; $fields .= "<label for='{$input_name}'><input type='checkbox' {$input_atts} value='1' name='{$input_name}' {$checked} /> {$checkbox_label}</label>";
$fields .= '</div>'; $fields .= '</div>';
break; break;
...@@ -268,7 +268,12 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -268,7 +268,12 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
case 'permastruct' : case 'permastruct' :
$siteurl = Permalink_Manager_Helper_Functions::get_permalink_base(); $siteurl = Permalink_Manager_Helper_Functions::get_permalink_base();
$fields .= "<div class=\"permastruct-container\"><span><code>{$siteurl}/</code></span><span><input type='text' {$input_atts} value='{$value}' name='{$input_name}'/></span></div>";
$fields .= "<div class=\"permastruct-container\">";
$fields .= "<span><code>{$siteurl}/</code></span>";
$fields .= "<span><input type='text' {$input_atts} value='{$value}' name='{$input_name}'/></span>";
$fields .= "</div>";
break; break;
default : default :
...@@ -309,7 +314,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -309,7 +314,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
/** /**
* Display the form * Display the form
*/ */
static public function get_the_form($fields = array(), $container = '', $button = array(), $sidebar = '', $nonce = array(), $wrap = false) { static public function get_the_form($fields = array(), $container = '', $button = array(), $sidebar = '', $nonce = array(), $wrap = false, $form_class = '') {
// 1. Check if the content will be displayed in columns and button details // 1. Check if the content will be displayed in columns and button details
switch($container) { switch($container) {
case 'columns-3' : case 'columns-3' :
...@@ -331,6 +336,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -331,6 +336,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
$button_attributes = (!empty($button['attributes'])) ? $button['attributes'] : ''; $button_attributes = (!empty($button['attributes'])) ? $button['attributes'] : '';
$nonce_action = (!empty($nonce['action'])) ? $nonce['action'] : ''; $nonce_action = (!empty($nonce['action'])) ? $nonce['action'] : '';
$nonce_name = (!empty($nonce['name'])) ? $nonce['name'] : ''; $nonce_name = (!empty($nonce['name'])) ? $nonce['name'] : '';
$form_classes = (!empty($form_class)) ? $form_class : '';
// 2. Now get the HTML output (start section row container) // 2. Now get the HTML output (start section row container)
$html = ($wrapper_class) ? "<div class=\"{$wrapper_class}\">" : ''; $html = ($wrapper_class) ? "<div class=\"{$wrapper_class}\">" : '';
...@@ -346,7 +352,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -346,7 +352,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
// 4. Start fields' section // 4. Start fields' section
$html .= ($form_column_class) ? "<div class=\"{$form_column_class}\">" : ""; $html .= ($form_column_class) ? "<div class=\"{$form_column_class}\">" : "";
$html .= "<form method=\"POST\">"; $html .= "<form method=\"POST\" class=\"{$form_classes}\">";
$html .= ($wrap) ? "<table class=\"form-table\">" : ""; $html .= ($wrap) ? "<table class=\"form-table\">" : "";
// Loop through all fields assigned to this section // Loop through all fields assigned to this section
...@@ -605,12 +611,13 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -605,12 +611,13 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
/** /**
* Display "Permalink Manager" box * Display "Permalink Manager" box
*/ */
public static function display_uri_box($element, $default_uri, $uri, $native_uri) { public static function display_uri_box($element, $gutenberg = false) {
global $permalink_manager_options; global $permalink_manager_options, $permalink_manager_uris;
if(!empty($element->ID)) { if(!empty($element->ID)) {
$id = $element_id = $element->ID; $id = $element_id = $element->ID;
$native_slug = $element->post_name; $native_slug = $element->post_name;
$is_draft = (!empty($element->post_status) && (in_array($element->post_status, array('draft', 'auto-draft')))) ? true : false;
// Auto-update settings // Auto-update settings
$auto_update_val = get_post_meta($id, "auto_update_uri", true); $auto_update_val = get_post_meta($id, "auto_update_uri", true);
...@@ -621,26 +628,43 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -621,26 +628,43 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
-1 => array("label" => __("No", "permalink-manager"), "atts" => "data-auto-update=\"0\""), -1 => array("label" => __("No", "permalink-manager"), "atts" => "data-auto-update=\"0\""),
1 => array("label" => __("Yes", "permalink-manager"), "atts" => "data-auto-update=\"1\"") 1 => array("label" => __("Yes", "permalink-manager"), "atts" => "data-auto-update=\"1\"")
); );
} else {
// Get URIs
$uri = Permalink_Manager_URI_Functions_Post::get_post_uri($id, true, $is_draft);
$default_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri($id);
$native_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri($id, true);
} else if(class_exists('Permalink_Manager_URI_Functions_Tax')) {
$id = $element->term_id; $id = $element->term_id;
$element_id = "tax-{$id}"; $element_id = "tax-{$id}";
$native_slug = $element->slug; $native_slug = $element->slug;
// Get URIs
$uri = Permalink_Manager_URI_Functions_Tax::get_term_uri($element->term_id, true);
$default_uri = Permalink_Manager_URI_Functions_Tax::get_default_term_uri($element->term_id);
$native_uri = Permalink_Manager_URI_Functions_Tax::get_default_term_uri($element->term_id, true);
} else {
return;
} }
// Decode default URI // Decode default URI
$default_uri = urldecode($default_uri); $default_uri = urldecode($default_uri);
// Start HTML output
// 1. Button // 1. Button
$html = sprintf("<span><button type=\"button\" class=\"button button-small hide-if-no-js\" id=\"permalink-manager-toggle\">%s</button></span>", __("Permalink Manager", "permalink-manager")); if(!$gutenberg) {
$html = sprintf("<span><button type=\"button\" class=\"button button-small hide-if-no-js\" id=\"permalink-manager-toggle\">%s</button></span>", __("Permalink Manager", "permalink-manager"));
$html .= "<div id=\"permalink-manager\" class=\"postbox permalink-manager-edit-uri-box\" style=\"display: none;\">"; $html .= "<div id=\"permalink-manager\" class=\"postbox permalink-manager-edit-uri-box\" style=\"display: none;\">";
// 2. The heading // 2. The heading
$html .= "<a class=\"close-button\"><span class=\"screen-reader-text\">" . __("Close: ", "permalink-manager") . __("Permalink Manager", "permalink-manager") . "</span><span class=\"close-icon\" aria-hidden=\"false\"></span></a>"; $html .= "<a class=\"close-button\"><span class=\"screen-reader-text\">" . __("Close: ", "permalink-manager") . __("Permalink Manager", "permalink-manager") . "</span><span class=\"close-icon\" aria-hidden=\"false\"></span></a>";
$html .= sprintf("<h2><span>%s</span></h2>", __("Permalink Manager", "permalink-manager")); $html .= sprintf("<h2><span>%s</span></h2>", __("Permalink Manager", "permalink-manager"));
// 3. The fields container [start] // 3. The fields container [start]
$html .= "<div class=\"inside\">"; $html .= "<div class=\"inside\">";
} else {
$html = "<div class=\"permalink-manager-gutenberg permalink-manager-edit-uri-box\">";
}
// 4. Custom URI // 4. Custom URI
if(!empty($element->ID) && get_option('page_on_front') == $id) { if(!empty($element->ID) && get_option('page_on_front') == $id) {
...@@ -650,9 +674,9 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -650,9 +674,9 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
$custom_uri_field = Permalink_Manager_Admin_Functions::generate_option_field("custom_uri", array("extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => urldecode($uri))); $custom_uri_field = Permalink_Manager_Admin_Functions::generate_option_field("custom_uri", array("extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => urldecode($uri)));
} }
$html .= sprintf("<div class=\"custom_uri_container\"><label for=\"custom_uri\" class=\"strong\">%s %s</label><span>%s</span><span class=\"duplicated_uri_alert\"></span></div>", $html .= sprintf("<div class=\"custom_uri_container\"><p><label for=\"custom_uri\" class=\"strong\">%s %s</label></p><span>%s</span><span class=\"duplicated_uri_alert\"></span></div>",
__("Current URI", "permalink-manager"), __("Current URI", "permalink-manager"),
($element->ID) ? Permalink_Manager_Admin_Functions::help_tooltip(__("The custom URI can be edited only if 'Auto-update the URI' feature is not enabled.", "permalink-manager")) : "", ($element->ID) ? Permalink_Manager_Admin_Functions::help_tooltip(__("If custom URI is not defined, a default URI will be set (see below). The custom URI can be edited only if 'Auto-update the URI' feature is not enabled.", "permalink-manager")) : "",
$custom_uri_field $custom_uri_field
); );
...@@ -660,7 +684,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -660,7 +684,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
if(!empty($element->ID) && !empty($permalink_manager_options["general"]["show_native_slug_field"])) { if(!empty($element->ID) && !empty($permalink_manager_options["general"]["show_native_slug_field"])) {
$native_slug_field = Permalink_Manager_Admin_Functions::generate_option_field("native_slug", array("extra_atts" => "data-default=\"{$native_slug}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat native_slug", "value" => urldecode($native_slug))); $native_slug_field = Permalink_Manager_Admin_Functions::generate_option_field("native_slug", array("extra_atts" => "data-default=\"{$native_slug}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat native_slug", "value" => urldecode($native_slug)));
$html .= sprintf("<div class=\"native_slug_container\"><label for=\"native_slug\" class=\"strong\">%s %s</label><span>%s</span></div>", $html .= sprintf("<div class=\"native_slug_container\"><p><label for=\"native_slug\" class=\"strong\">%s %s</label></p><span>%s</span></div>",
__("Native slug", "permalink-manager"), __("Native slug", "permalink-manager"),
Permalink_Manager_Admin_Functions::help_tooltip(__("The native slug is by default automatically used in native permalinks (when Permalink Manager is disabled).", "permalink-manager")), Permalink_Manager_Admin_Functions::help_tooltip(__("The native slug is by default automatically used in native permalinks (when Permalink Manager is disabled).", "permalink-manager")),
$native_slug_field $native_slug_field
...@@ -671,7 +695,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -671,7 +695,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
if(get_option('page_on_front') != $id) { if(get_option('page_on_front') != $id) {
// 6. Auto-update URI // 6. Auto-update URI
if(!empty($auto_update_choices)) { if(!empty($auto_update_choices)) {
$html .= sprintf("<div><label for=\"auto_auri\" class=\"strong\">%s %s</label><span>%s</span></div>", $html .= sprintf("<div><p><label for=\"auto_auri\" class=\"strong\">%s %s</label></p><span>%s</span></div>",
__("Auto-update the URI", "permalink-manager"), __("Auto-update the URI", "permalink-manager"),
Permalink_Manager_Admin_Functions::help_tooltip(__("If enabled, the 'Current URI' field will be automatically changed to 'Default URI' (displayed below) after the post is saved or updated.", "permalink-manager")), Permalink_Manager_Admin_Functions::help_tooltip(__("If enabled, the 'Current URI' field will be automatically changed to 'Default URI' (displayed below) after the post is saved or updated.", "permalink-manager")),
Permalink_Manager_Admin_Functions::generate_option_field("auto_update_uri", array("type" => "select", "input_class" => "widefat auto_update", "value" => $auto_update_val, "choices" => $auto_update_choices)) Permalink_Manager_Admin_Functions::generate_option_field("auto_update_uri", array("type" => "select", "input_class" => "widefat auto_update", "value" => $auto_update_val, "choices" => $auto_update_choices))
...@@ -682,7 +706,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -682,7 +706,7 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
$html .= sprintf( $html .= sprintf(
"<div class=\"default-permalink-row columns-container\"><span class=\"column-3_4\"><strong>%s:</strong> %s</span><span class=\"column-1_4\"><a href=\"#\" class=\"restore-default\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span></div>", "<div class=\"default-permalink-row columns-container\"><span class=\"column-3_4\"><strong>%s:</strong> %s</span><span class=\"column-1_4\"><a href=\"#\" class=\"restore-default\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span></div>",
__("Default URI", "permalink-manager"), esc_html($default_uri), __("Default URI", "permalink-manager"), esc_html($default_uri),
__("Restore to Default URI", "permalink-manager") __("Restore Default URI", "permalink-manager")
); );
// 8. Native URI info // 8. Native URI info
...@@ -702,10 +726,18 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -702,10 +726,18 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
// 9. Custom redirects // 9. Custom redirects
$html .= ($element->ID) ? self::display_redirect_panel($id) : self::display_redirect_panel("tax-{$id}"); $html .= ($element->ID) ? self::display_redirect_panel($id) : self::display_redirect_panel("tax-{$id}");
// 10. Extra save button for Gutenberg
if($gutenberg) {
$html .= sprintf(
"<div class=\"default-permalink-row save-row columns-container hidden\"><div><a href=\"#\" class=\"button button-primary\" id=\"permalink-manager-save-button\">%s</a></div></div>",
__("Save permalink", "permalink-manager")
);
}
$html .= "</div>"; $html .= "</div>";
$html .= "</div>"; $html .= "</div>";
// 9. Append nonce field & element ID // 11. Append nonce field & element ID
$html .= Permalink_Manager_Admin_Functions::generate_option_field("permalink-manager-edit-uri-element-id", array("type" => "hidden", "value" => $element_id)); $html .= Permalink_Manager_Admin_Functions::generate_option_field("permalink-manager-edit-uri-element-id", array("type" => "hidden", "value" => $element_id));
$html .= wp_nonce_field('permalink-manager-edit-uri-box', 'permalink-manager-nonce', true, false); $html .= wp_nonce_field('permalink-manager-edit-uri-box', 'permalink-manager-nonce', true, false);
...@@ -720,9 +752,8 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class { ...@@ -720,9 +752,8 @@ class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
// Heading // Heading
$html = sprintf( $html = sprintf(
"<div class=\"permalink-manager redirects-row redirects-panel columns-container\"><div class=\"heading\"><span class=\"dashicons dashicons-edit\"></span> <a href=\"#\" id=\"toggle-redirect-panel\">%s <small>%s</small></a></span></div>", "<div class=\"permalink-manager redirects-row redirects-panel columns-container\"><div><a class=\"button\" href=\"#\" id=\"toggle-redirect-panel\">%s</a></span></div>",
__("Manage redirects", "permalink-manager"), __("Manage redirects", "permalink-manager")
__("[click to open]", "permalink-manager")
); );
$html .= "<div id=\"redirect-panel-inside\">"; $html .= "<div id=\"redirect-panel-inside\">";
......
...@@ -420,7 +420,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class { ...@@ -420,7 +420,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
global $wp_query, $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_external_redirects, $permalink_manager_options, $wp, $pm_query, $pm_uri_parts; global $wp_query, $permalink_manager_uris, $permalink_manager_redirects, $permalink_manager_external_redirects, $permalink_manager_options, $wp, $pm_query, $pm_uri_parts;
// Do not redirect on author pages & front page // Do not redirect on author pages & front page
if(is_author() || is_front_page() || is_home()) { return false; } if(is_author() || is_front_page() || is_home() || is_feed()) { return false; }
// Unset 404 if custom URI is detected // Unset 404 if custom URI is detected
if(isset($pm_query['id'])) { if(isset($pm_query['id'])) {
...@@ -497,6 +497,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class { ...@@ -497,6 +497,7 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
* 1C. Enhance native redirect * 1C. Enhance native redirect
*/ */
if(empty($wp_query->query_vars['do_not_redirect']) && $redirect_mode && !empty($queried_object) && empty($correct_permalink)) { if(empty($wp_query->query_vars['do_not_redirect']) && $redirect_mode && !empty($queried_object) && empty($correct_permalink)) {
// Affect only posts with custom URI and old URIs // Affect only posts with custom URI and old URIs
if(!empty($queried_object->ID) && isset($permalink_manager_uris[$queried_object->ID]) && empty($wp_query->query['preview'])) { if(!empty($queried_object->ID) && isset($permalink_manager_uris[$queried_object->ID]) && empty($wp_query->query['preview'])) {
// Ignore posts with specific statuses // Ignore posts with specific statuses
...@@ -601,17 +602,20 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class { ...@@ -601,17 +602,20 @@ class Permalink_Manager_Core_Functions extends Permalink_Manager_Class {
} }
// Do nothing for posts and terms without custom URIs (when canonical redirect is enabled) // Do nothing for posts and terms without custom URIs (when canonical redirect is enabled)
$element = get_queried_object(); if(is_singular() || is_tax() || is_category() || is_tag()) {
if(!empty($element->ID)) { $element = get_queried_object();
$custom_uri = (!empty($permalink_manager_uris[$element->ID])) ? $permalink_manager_uris[$element->ID] : ""; if(!empty($element->ID)) {
} else if(!empty($element->term_id)) { $custom_uri = (!empty($permalink_manager_uris[$element->ID])) ? $permalink_manager_uris[$element->ID] : "";
$custom_uri = (!empty($permalink_manager_uris["tax-{$element->term_id}"])) ? $permalink_manager_uris["tax-{$element->term_id}"] : ""; } else if(!empty($element->term_id)) {
$custom_uri = (!empty($permalink_manager_uris["tax-{$element->term_id}"])) ? $permalink_manager_uris["tax-{$element->term_id}"] : "";
}
} }
//if(empty($custom_uri) && !empty($permalink_manager_options['general']['canonical_redirect'])) { return; } //if(empty($custom_uri) && !empty($permalink_manager_options['general']['canonical_redirect'])) { return; }
if(!empty($permalink_manager_options['general']['canonical_redirect'])) { return; } if(!empty($permalink_manager_options['general']['canonical_redirect'])) { return; }
if(!($permalink_manager_options['general']['canonical_redirect']) || !empty($wp->query_vars['do_not_redirect'])) { if(!($permalink_manager_options['general']['canonical_redirect']) || !empty($wp->query_vars['do_not_redirect'])) {
remove_action('template_redirect', 'wp_old_slug_redirect');
remove_action('template_redirect', 'redirect_canonical'); remove_action('template_redirect', 'redirect_canonical');
add_filter('wpml_is_redirected', '__return_false', 99, 2); add_filter('wpml_is_redirected', '__return_false', 99, 2);
add_filter('pll_check_canonical_url', '__return_false', 99, 2); add_filter('pll_check_canonical_url', '__return_false', 99, 2);
......
<?php
/**
* Additional hooks for "Permalink Manager Pro"
*/
class Permalink_Manager_Gutenberg extends Permalink_Manager_Class {
public function __construct() {
add_action('enqueue_block_editor_assets', array($this, 'init'));
}
public function init() {
// add_action('enqueue_block_editor_assets', array($this, 'pm_gutenberg_scripts'));
add_meta_box('permalink-manager', __('Permalink Manager', 'permalink-manager'), array($this, 'meta_box'), 'post', 'side', 'high' );
}
public function pm_gutenberg_scripts() {
wp_enqueue_script( 'permalink-manager-gutenberg', PERMALINK_MANAGER_URL . '/out/permalink-manager-gutenberg.js', array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-i18n', ), PERMALINK_MANAGER_VERSION, true );
}
public function meta_box($post) {
global $permalink_manager_uris;
if(empty($post->ID)) {
return '';
}
// Display URI Editor
echo Permalink_Manager_Admin_Functions::display_uri_box($post, true);
}
}
?>
...@@ -433,9 +433,10 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class { ...@@ -433,9 +433,10 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
$clean = ($force_lowercase) ? strtolower(trim($clean, '-')) : trim($clean, '-'); $clean = ($force_lowercase) ? strtolower(trim($clean, '-')) : trim($clean, '-');
// Remove special characters // Remove special characters
if($sanitize_slugs) { if($sanitize_slugs !== false) {
$clean = preg_replace("/[\s_|+-]+/", "-", $clean); $clean = preg_replace("/[\s_|+-]+/", "-", $clean);
$clean = preg_replace("/[\.]+/", "", $clean); $clean = preg_replace("/[\.]+/", "", $clean);
$clean = preg_replace('/([-\s+]\/[-\s+])/', '-', $clean);
} else { } else {
$clean = preg_replace("/[\s]+/", "-", $clean); $clean = preg_replace("/[\s]+/", "-", $clean);
} }
...@@ -447,13 +448,23 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class { ...@@ -447,13 +448,23 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
* Clear the URI * Clear the URI
*/ */
public static function clear_single_uri($uri) { public static function clear_single_uri($uri) {
$uri = preg_replace('/\s+/', '', $uri); $uri = preg_replace("/[\s_|+-]+/", "-", $uri);
$uri = str_replace('//', '/', $uri); $uri = preg_replace('/([-\s+]\/[-\s+])/', '-', $uri);
$uri = str_replace(array('-/', '/-', '//'), '/', $uri);
$uri = trim($uri, "/"); $uri = trim($uri, "/");
return $uri; return $uri;
} }
/**
* Remove all slashes
*/
public static function remove_slashes($uri) {
$uri = preg_replace("/[\/]+/", "", $uri);
return $uri;
}
/** /**
* Force custom slugs * Force custom slugs
*/ */
...@@ -462,6 +473,7 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class { ...@@ -462,6 +473,7 @@ class Permalink_Manager_Helper_Functions extends Permalink_Manager_Class {
if(!empty($permalink_manager_options['general']['force_custom_slugs'])) { if(!empty($permalink_manager_options['general']['force_custom_slugs'])) {
$title = (!empty($object->name)) ? $object->name : $object->post_title; $title = (!empty($object->name)) ? $object->name : $object->post_title;
$title = self::remove_slashes($title);
$old_slug = basename($slug); $old_slug = basename($slug);
$new_slug = self::sanitize_title($title, false, null, true); $new_slug = self::sanitize_title($title, false, null, true);
......
...@@ -32,11 +32,6 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -32,11 +32,6 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
add_filter('template_redirect', array($this, 'wpml_redirect'), 0, 998 ); add_filter('template_redirect', array($this, 'wpml_redirect'), 0, 998 );
} else if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 3) { } else if(isset($sitepress_settings['language_negotiation_type']) && $sitepress_settings['language_negotiation_type'] == 3) {
add_filter('permalink-manager-detect-uri', array($this, 'wpml_ignore_lang_query_parameter'), 9); add_filter('permalink-manager-detect-uri', array($this, 'wpml_ignore_lang_query_parameter'), 9);
// Append query parameter
add_filter('permalink_manager_filter_final_term_permalink', array($this, 'wpml_append_lang_query_parameter'), 9, 2);
add_filter('permalink_manager_filter_final_post_permalink', array($this, 'wpml_append_lang_query_parameter'), 9, 2);
add_filter('permalink_manager_filter_post_sample_permalink', array($this, 'wpml_append_lang_query_parameter'), 9, 2);
} }
// Translate slugs // Translate slugs
...@@ -53,10 +48,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -53,10 +48,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
add_filter('request', array($this, 'enable_amp'), 10, 1); add_filter('request', array($this, 'enable_amp'), 10, 1);
} }
// 4. WP All Import // 3. WooCommerce
add_action('pmxi_after_xml_import', array($this, 'pmxi_fix_permalinks'), 10);
// 5. WooCommerce
if(class_exists('WooCommerce')) { if(class_exists('WooCommerce')) {
add_filter('request', array($this, 'woocommerce_detect'), 9, 1); add_filter('request', array($this, 'woocommerce_detect'), 9, 1);
add_filter('template_redirect', array($this, 'woocommerce_checkout_fix'), 9); add_filter('template_redirect', array($this, 'woocommerce_checkout_fix'), 9);
...@@ -72,27 +64,27 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -72,27 +64,27 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
} }
// 6. Theme My Login // 4. Theme My Login
if(class_exists('Theme_My_Login')) { if(class_exists('Theme_My_Login')) {
add_filter('permalink_manager_filter_final_post_permalink', array($this, 'tml_keep_query_parameters'), 9, 3); add_filter('permalink_manager_filter_final_post_permalink', array($this, 'tml_keep_query_parameters'), 9, 3);
} }
// 7. Yoast SEO // 5. Yoast SEO
add_filter('wpseo_xml_sitemap_post_url', array($this, 'yoast_fix_sitemap_urls')); add_filter('wpseo_xml_sitemap_post_url', array($this, 'yoast_fix_sitemap_urls'));
// 8. WooCommerce Wishlist Plugin // 6. WooCommerce Wishlist Plugin
if(function_exists('tinv_get_option')) { if(function_exists('tinv_get_option')) {
add_filter('permalink-manager-detect-uri', array($this, 'ti_woocommerce_wishlist_uris'), 15, 3); add_filter('permalink-manager-detect-uri', array($this, 'ti_woocommerce_wishlist_uris'), 15, 3);
} }
// 9. Revisionize // 7. Revisionize
if(defined('REVISIONIZE_ROOT')) { if(defined('REVISIONIZE_ROOT')) {
add_action('revisionize_after_create_revision', array($this, 'revisionize_keep_post_uri'), 9, 2); add_action('revisionize_after_create_revision', array($this, 'revisionize_keep_post_uri'), 9, 2);
add_action('revisionize_before_publish', array($this,'revisionize_clone_uri'), 9, 2); add_action('revisionize_before_publish', array($this,'revisionize_clone_uri'), 9, 2);
} }
// 10. WP All Import // 8. WP All Import
if(class_exists('PMXI_Plugin')) { if(class_exists('PMXI_Plugin') && (empty($permalink_manager_options['general']['pmxi_import_support']))) {
add_action('pmxi_extend_options_featured', array($this, 'wpaiextra_uri_display'), 9, 2); add_action('pmxi_extend_options_featured', array($this, 'wpaiextra_uri_display'), 9, 2);
add_filter('pmxi_options_options', array($this, 'wpai_api_options')); add_filter('pmxi_options_options', array($this, 'wpai_api_options'));
add_filter('pmxi_addons', array($this, 'wpai_api_register')); add_filter('pmxi_addons', array($this, 'wpai_api_register'));
...@@ -115,6 +107,10 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -115,6 +107,10 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
if(!empty($query_vars['image_id']) && !empty($query_vars['gallery_id'])) { if(!empty($query_vars['image_id']) && !empty($query_vars['gallery_id'])) {
$wp_query->query_vars['do_not_redirect'] = 1; $wp_query->query_vars['do_not_redirect'] = 1;
} }
// Ultimate member
else if(!empty($query_vars['um_user']) && !empty($query_vars['um_user'])) {
$wp_query->query_vars['do_not_redirect'] = 1;
}
} }
} }
...@@ -205,7 +201,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -205,7 +201,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
foreach($domains as &$domain) { foreach($domains as &$domain) {
$domain = preg_replace("/(http(s)?:\/\/(www\.)?)?(.+?)\/?$/", "http://$4", $domain); $domain = preg_replace('/((http(s)?:\/\/(www\.)?)|(www\.))?(.+?)\/?$/', 'http://$6', $domain);
} }
$request_url = trim(str_replace($domains, "", $request_url), "/"); $request_url = trim(str_replace($domains, "", $request_url), "/");
...@@ -279,21 +275,6 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -279,21 +275,6 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
return $base; return $base;
} }
function wpml_append_lang_query_parameter($permalink, $element) {
$lang = self::wpml_get_language_code($element);
$def_lang = self::get_default_language();
if(!empty($lang) && ($def_lang != $lang)) {
if(filter_var($permalink, FILTER_VALIDATE_URL)) {
$permalink = add_query_arg('lang', $lang, $permalink);
} else {
$permalink .= "?lang={$lang}";
}
}
return $permalink;
}
function wpml_translate_post_type_slug($post_type_slug, $element, $post_type) { function wpml_translate_post_type_slug($post_type_slug, $element, $post_type) {
$post = (is_integer($element)) ? get_post($element) : $element; $post = (is_integer($element)) ? get_post($element) : $element;
$language_code = self::wpml_get_language_code($post); $language_code = self::wpml_get_language_code($post);
...@@ -365,7 +346,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -365,7 +346,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
/** /**
* 3. Custom Permalinks * Parse Custom Permalinks
*/ */
public static function custom_permalinks_uris() { public static function custom_permalinks_uris() {
global $wpdb; global $wpdb;
...@@ -421,32 +402,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -421,32 +402,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
/** /**
* 4. WP All Import * 3. WooCommerce
*/
function pmxi_fix_permalinks($import_id) {
global $permalink_manager_uris, $wpdb;
$post_ids = $wpdb->get_col($wpdb->prepare("SELECT post_id FROM {$wpdb->prefix}pmxi_posts WHERE import_id = %s", $import_id));
// Just in case
sleep(3);
if(array($post_ids)) {
foreach($post_ids as $id) {
// Continue only if no custom URI is already assigned
if(!empty($permalink_manager_uris[$id])) { continue; }
// Get default post URI
$new_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri($id);
$permalink_manager_uris[$id] = $new_uri;
}
}
update_option('permalink-manager-uris', $permalink_manager_uris);
}
/**
* 5. WooCommerce
*/ */
function woocommerce_detect($query) { function woocommerce_detect($query) {
global $woocommerce, $pm_query; global $woocommerce, $pm_query;
...@@ -501,7 +457,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -501,7 +457,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
/** /**
* 6. Theme My Login * 4. Theme My Login
*/ */
function tml_keep_query_parameters($permalink, $post, $old_permalink) { function tml_keep_query_parameters($permalink, $post, $old_permalink) {
// Get the query string from old permalink // Get the query string from old permalink
...@@ -511,7 +467,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -511,7 +467,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
/** /**
* 7. Fix Yoast's homepage URL * 5. Fix Yoast's homepage URL
*/ */
function yoast_fix_sitemap_urls($permalink) { function yoast_fix_sitemap_urls($permalink) {
if(class_exists('WPSEO_Utils')) { if(class_exists('WPSEO_Utils')) {
...@@ -525,7 +481,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -525,7 +481,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
/** /**
* 8. Support WooCommerce Wishlist Plugin * 6. Support WooCommerce Wishlist Plugin
*/ */
function ti_woocommerce_wishlist_uris($uri_parts, $request_url, $endpoints) { function ti_woocommerce_wishlist_uris($uri_parts, $request_url, $endpoints) {
global $permalink_manager_uris, $wp; global $permalink_manager_uris, $wp;
...@@ -550,7 +506,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -550,7 +506,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
/** /**
* 9. Revisionize * 7. Revisionize
*/ */
function revisionize_keep_post_uri($old_id, $new_id) { function revisionize_keep_post_uri($old_id, $new_id) {
global $permalink_manager_uris; global $permalink_manager_uris;
...@@ -576,7 +532,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -576,7 +532,7 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
} }
/** /**
* 10. WP All Import * 8. WP All Import
*/ */
function wpaiextra_uri_display($post_type, $current_values) { function wpaiextra_uri_display($post_type, $current_values) {
...@@ -663,27 +619,25 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -663,27 +619,25 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
function wpai_api_import_function($importData, $parsedData) { function wpai_api_import_function($importData, $parsedData) {
global $permalink_manager_uris; global $permalink_manager_uris;
// Check if post type is disabled
if(empty($parsedData) || Permalink_Manager_Helper_Functions::is_disabled($importData['post_type'], 'post_type')) { return; }
// Get the parsed custom URI // Get the parsed custom URI
$index = (!empty($importData['i'])) ? $importData['i'] : false; $index = (!empty($importData['i'])) ? $importData['i'] : false;
$pid = (!empty($importData['pid'])) ? $importData['pid'] : false; $pid = (!empty($importData['pid'])) ? $importData['pid'] : false;
if($pid && $index && !empty($parsedData['custom_uri'][$index])) { if($index && $pid && !empty($parsedData['custom_uri'][$index])) {
$custom_uri = $parsedData['custom_uri'][$index]; $custom_uri = Permalink_Manager_Helper_Functions::sanitize_title($parsedData['custom_uri'][$index]);
// Store only URIs
$custom_uri = parse_url($custom_uri, PHP_URL_PATH);
// Sanitize the output
$custom_uri = Permalink_Manager_Helper_Functions::sanitize_title($custom_uri);
$permalink_manager_uris[$pid] = $custom_uri; if(!empty($custom_uri)) {
$permalink_manager_uris[$pid] = $custom_uri;
update_option('permalink-manager-uris', $permalink_manager_uris); update_option('permalink-manager-uris', $permalink_manager_uris);
}
} }
} }
function wpai_save_redirects($pid) { function wpai_save_redirects($pid) {
global $permalink_manager_external_redirects; global $permalink_manager_external_redirects, $permalink_manager_uris;
$external_url = get_post_meta($pid, '_external_redirect', true); $external_url = get_post_meta($pid, '_external_redirect', true);
$external_url = (empty($external_url)) ? get_post_meta($pid, 'external_redirect', true) : $external_url; $external_url = (empty($external_url)) ? get_post_meta($pid, 'external_redirect', true) : $external_url;
...@@ -691,6 +645,16 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class { ...@@ -691,6 +645,16 @@ class Permalink_Manager_Third_Parties extends Permalink_Manager_Class {
if($external_url && class_exists('Permalink_Manager_Pro_Functions')) { if($external_url && class_exists('Permalink_Manager_Pro_Functions')) {
Permalink_Manager_Pro_Functions::save_external_redirect($external_url, $pid); Permalink_Manager_Pro_Functions::save_external_redirect($external_url, $pid);
} }
// Save custom URI only if the post type is not disabled (third parameter in get_default_post_uri() function)
if(empty($permalink_manager_uris[$pid])) {
$custom_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri($pid, false, true);
if(!empty($custom_uri)) {
$permalink_manager_uris[$pid] = $custom_uri;
update_option('permalink-manager-uris', $permalink_manager_uris);
}
}
} }
} }
......
...@@ -85,10 +85,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -85,10 +85,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
$permalink = "{$home_url}/" . urldecode("/{$permalink}"); $permalink = "{$home_url}/" . urldecode("/{$permalink}");
} }
// 6. Additional filter // 5. Allow to filter
$permalink = apply_filters('permalink_manager_filter_final_post_permalink', user_trailingslashit($permalink), $post, $old_permalink); return apply_filters('permalink_manager_filter_final_post_permalink', user_trailingslashit($permalink), $post, $old_permalink);
return $permalink;
} }
/** /**
...@@ -110,12 +108,19 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -110,12 +108,19 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
/** /**
* Get the active URI * Get the active URI
*/ */
public static function get_post_uri($post_id, $native_uri = false) { public static function get_post_uri($post_id, $native_uri = false, $is_draft = false) {
global $permalink_manager_uris; global $permalink_manager_uris;
// Check if input is post object // Check if input is post object
$post_id = (isset($post_id->ID)) ? $post_id->ID : $post_id; $post_id = (isset($post_id->ID)) ? $post_id->ID : $post_id;
$final_uri = (!empty($permalink_manager_uris[$post_id])) ? $permalink_manager_uris[$post_id] : self::get_default_post_uri($post_id, $native_uri);
if(!empty($permalink_manager_uris[$post_id])) {
$final_uri = $permalink_manager_uris[$post_id];
} else if(!$is_draft) {
$final_uri = self::get_default_post_uri($post_id, $native_uri);
} else {
$final_uri = '';
}
return $final_uri; return $final_uri;
} }
...@@ -123,7 +128,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -123,7 +128,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
/** /**
* Get the default (not overwritten by the user) or native URI (unfiltered) * Get the default (not overwritten by the user) or native URI (unfiltered)
*/ */
public static function get_default_post_uri($post, $native_uri = false) { public static function get_default_post_uri($post, $native_uri = false, $check_if_disabled = false) {
global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $wp_post_types; global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $wp_post_types;
// Load all bases & post // Load all bases & post
...@@ -135,6 +140,9 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -135,6 +140,9 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
$post_type = $post->post_type; $post_type = $post->post_type;
$post_name = (empty($post->post_name)) ? Permalink_Manager_Helper_Functions::sanitize_title($post->post_title) : $post->post_name; $post_name = (empty($post->post_name)) ? Permalink_Manager_Helper_Functions::sanitize_title($post->post_title) : $post->post_name;
// 1A. Check if post type is allowed
if($check_if_disabled && Permalink_Manager_Helper_Functions::is_disabled($post_type, 'post_type')) { return ''; }
// 1. Get the permastruct // 1. Get the permastruct
if($post_type == 'attachment') { if($post_type == 'attachment') {
$parent_page = ($post->post_parent > 0 && $post->post_parent != $post->ID) ? get_post($post->post_parent) : false; $parent_page = ($post->post_parent > 0 && $post->post_parent != $post->ID) ? get_post($post->post_parent) : false;
...@@ -182,10 +190,11 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -182,10 +190,11 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
$post_type_slug = $post_type; $post_type_slug = $post_type;
} }
$post_type_slug = apply_filters('permalink_manager_filter_post_type_slug', $post_type_slug, $post, $post_type); $post_type_slug = apply_filters('permalink_manager_filter_post_type_slug', $post_type_slug, $post, $post_type);
$post_type_slug = preg_replace('/(%([^%]+)%\/?)/', '', $post_type_slug);
// 3B. Get the full slug // 3B. Get the full slug
$custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($post_name, $post); $post_name = Permalink_Manager_Helper_Functions::remove_slashes($post_name);
$full_custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($post_name, $post); $custom_slug = $full_custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($post_name, $post);
$full_native_slug = $post_name; $full_native_slug = $post_name;
// 3A. Fix for hierarchical CPT (start) // 3A. Fix for hierarchical CPT (start)
...@@ -381,8 +390,9 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -381,8 +390,9 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
// Get default & native URL // Get default & native URL
$native_uri = self::get_default_post_uri($row['ID'], true); $native_uri = self::get_default_post_uri($row['ID'], true);
$default_uri = self::get_default_post_uri($row['ID']); $default_uri = self::get_default_post_uri($row['ID']);
$old_post_name = $row['post_name']; $old_post_name = $row['post_name'];
$old_uri = (isset($permalink_manager_uris[$row['ID']])) ? $permalink_manager_uris[$row['ID']] : $default_uri; $old_uri = (isset($permalink_manager_uris[$row['ID']])) ? $permalink_manager_uris[$row['ID']] : $native_uri;
// Do replacement on slugs (non-REGEX) // Do replacement on slugs (non-REGEX)
if(preg_match("/^\/.+\/[a-z]*$/i", $old_string)) { if(preg_match("/^\/.+\/[a-z]*$/i", $old_string)) {
...@@ -397,7 +407,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -397,7 +407,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
$new_uri = ($mode != 'slugs') ? str_replace($old_string, $new_string, $old_uri) : $old_uri; $new_uri = ($mode != 'slugs') ? str_replace($old_string, $new_string, $old_uri) : $old_uri;
} }
//print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n"); // echo "{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n";
// Check if native slug should be changed // Check if native slug should be changed
if(($mode == 'slugs') && ($old_post_name != $new_post_name)) { if(($mode == 'slugs') && ($old_post_name != $new_post_name)) {
...@@ -448,7 +458,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -448,7 +458,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
$native_uri = self::get_default_post_uri($row['ID'], true); $native_uri = self::get_default_post_uri($row['ID'], true);
$default_uri = self::get_default_post_uri($row['ID']); $default_uri = self::get_default_post_uri($row['ID']);
$old_post_name = $row['post_name']; $old_post_name = $row['post_name'];
$old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : $native_uri; $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : '';
$correct_slug = ($mode == 'slugs') ? sanitize_title($row['post_title']) : Permalink_Manager_Helper_Functions::sanitize_title($row['post_title']); $correct_slug = ($mode == 'slugs') ? sanitize_title($row['post_title']) : Permalink_Manager_Helper_Functions::sanitize_title($row['post_title']);
// Process URI & slug // Process URI & slug
...@@ -457,7 +467,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -457,7 +467,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
// Prepare the new URI // Prepare the new URI
if($mode == 'slugs') { if($mode == 'slugs') {
$new_uri = $old_uri; $new_uri = ($old_uri) ? $old_uri : $native_uri;
} else if($mode == 'native') { } else if($mode == 'native') {
$new_uri = $native_uri; $new_uri = $native_uri;
} else { } else {
...@@ -575,12 +585,12 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -575,12 +585,12 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
// Do not change anything if post is not saved yet (display sample permalink instead) // Do not change anything if post is not saved yet (display sample permalink instead)
if(get_option('page_on_front') == $id) { if(get_option('page_on_front') == $id) {
$uri = $sample_permalink_uri = ""; $$sample_permalink_uri = "";
} }
else if($autosave || empty($post->post_status)) { else if($autosave || empty($post->post_status)) {
$uri = $sample_permalink_uri = $default_uri; $sample_permalink_uri = $default_uri;
} else { } else {
$uri = $sample_permalink_uri = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $native_uri; $sample_permalink_uri = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $native_uri;
} }
// Decode URI & allow to filter it // Decode URI & allow to filter it
...@@ -594,12 +604,10 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -594,12 +604,10 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
// Append new HTML output // Append new HTML output
$html .= sprintf("<span class=\"sample-permalink-span\"><a id=\"sample-permalink\" href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink); $html .= sprintf("<span class=\"sample-permalink-span\"><a id=\"sample-permalink\" href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink);
$html .= (!$autosave) ? Permalink_Manager_Admin_Functions::display_uri_box($post, $default_uri, $uri, $native_uri) : ""; $html .= (!$autosave) ? Permalink_Manager_Admin_Functions::display_uri_box($post) : "";
// Append hidden field with native slug // Append hidden field with native slug
// $html .= (!empty($post->post_name)) ? "<input id=\"new-post-slug\" value=\"{$post->post_name}\" autocomplete=\"off\" type=\"hidden\">" : "";
$html .= (!empty($post->post_name)) ? "<span id=\"editable-post-name-full\">{$post->post_name}</span>" : ""; $html .= (!empty($post->post_name)) ? "<span id=\"editable-post-name-full\">{$post->post_name}</span>" : "";
// $html .= (!empty($post->post_name)) ? "<span id=\"editable-post-name-full\">{$uri}</span>" : "";
return $html; return $html;
} }
...@@ -639,8 +647,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -639,8 +647,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
function new_post_uri($post_id) { function new_post_uri($post_id) {
global $post, $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html; global $post, $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html;
// Do not trigger if post is a revision // Do not trigger if post is a revision or imported via WP All Import (URI should be set after the post meta is added)
if(wp_is_post_revision($post_id)) { return $post_id; } if(wp_is_post_revision($post_id) || (!empty($_REQUEST['page']) && $_REQUEST['page'] == 'pmxi-admin-import')) { return $post_id; }
// Prevent language mismatch in MultilingualPress plugin // Prevent language mismatch in MultilingualPress plugin
if(is_admin() && !empty($post->ID) && $post->ID != $post_id) { return $post_id; } if(is_admin() && !empty($post->ID) && $post->ID != $post_id) { return $post_id; }
...@@ -681,7 +689,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -681,7 +689,7 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
/** /**
* Update URI from "Edit Post" admin page * Update URI from "Edit Post" admin page
*/ */
function update_post_uri($post_id) { static public function update_post_uri($post_id) {
global $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html; global $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html;
// Verify nonce at first // Verify nonce at first
...@@ -690,8 +698,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -690,8 +698,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
// Do not do anything if post is autosaved // Do not do anything if post is autosaved
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; } if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
// Do not do anything on in "Bulk Edit" // Do not do anything on in "Bulk Edit" or when the post is imported via WP All Import
if(!empty($_REQUEST['bulk_edit'])) { return $post_id; } if(!empty($_REQUEST['bulk_edit']) || (!empty($_REQUEST['page']) && $_REQUEST['page'] == 'pmxi-admin-import')) { return $post_id; }
// Do not do anything if the field with URI or element ID are not present // Do not do anything if the field with URI or element ID are not present
if(!isset($_POST['custom_uri']) || empty($_POST['permalink-manager-edit-uri-element-id'])) { return $post_id; } if(!isset($_POST['custom_uri']) || empty($_POST['permalink-manager-edit-uri-element-id'])) { return $post_id; }
...@@ -739,10 +747,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class { ...@@ -739,10 +747,8 @@ class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
} }
// Save only changed URIs // Save only changed URIs
//if($new_uri != $old_uri) { $permalink_manager_uris[$post_id] = $new_uri;
$permalink_manager_uris[$post_id] = $new_uri; update_option('permalink-manager-uris', $permalink_manager_uris);
update_option('permalink-manager-uris', $permalink_manager_uris);
//}
// Update the slug (if changed) // Update the slug (if changed)
if(!empty($_POST['post_name']) && isset($_POST['native_slug']) && ($_POST['native_slug'] !== $_POST['post_name'])) { if(!empty($_POST['post_name']) && isset($_POST['native_slug']) && ($_POST['native_slug'] !== $_POST['post_name'])) {
......
...@@ -106,6 +106,12 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class { ...@@ -106,6 +106,12 @@ class Permalink_Manager_Settings extends Permalink_Manager_Class {
'input_class' => '', 'input_class' => '',
'description' => __('If enabled, the plugin will load the adjacent translation of post when the custom permalink is detected, but the language code in the URL does not match the language code assigned to the post/term.', 'permalink-manager') 'description' => __('If enabled, the plugin will load the adjacent translation of post when the custom permalink is detected, but the language code in the URL does not match the language code assigned to the post/term.', 'permalink-manager')
), ),
'pmxi_import_support' => array(
'type' => 'single_checkbox',
'label' => __('Disable support for WP All Import', 'permalink-manager'),
'input_class' => '',
'description' => __('If checked, the custom URIs will not be assigned to the posts imported by Wp All Import Pro plugin.', 'permalink-manager')
),
'force_custom_slugs' => array( 'force_custom_slugs' => array(
'type' => 'select', 'type' => 'select',
'label' => __('Force custom slugs', 'permalink-manager'), 'label' => __('Force custom slugs', 'permalink-manager'),
......
...@@ -200,7 +200,7 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class { ...@@ -200,7 +200,7 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
$sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>'; $sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>';
$sidebar .= self::display_instructions(); $sidebar .= self::display_instructions();
$output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __('Find and replace', 'permalink-manager'), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'find_and_replace'), true); $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __('Find and replace', 'permalink-manager'), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'find_and_replace'), true, 'form-ajax');
return $output; return $output;
} }
...@@ -270,7 +270,7 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class { ...@@ -270,7 +270,7 @@ class Permalink_Manager_Tools extends Permalink_Manager_Class {
$sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>'; $sidebar = '<h3>' . __('Important notices', 'permalink-manager') . '</h3>';
$sidebar .= self::display_instructions(); $sidebar .= self::display_instructions();
$output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Regenerate', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'regenerate'), true); $output = Permalink_Manager_Admin_Functions::get_the_form($fields, 'columns-3', array('text' => __( 'Regenerate', 'permalink-manager' ), 'class' => 'primary margin-top'), $sidebar, array('action' => 'permalink-manager', 'name' => 'regenerate'), true, 'form-ajax');
return $output; return $output;
} }
......
/** /**
* Permalink Manager CSS * Permalink Manager CSS
*/ */
#permalink-manager #plugin-name-heading .author-link{color:#959595;font-size:60%;text-decoration:none} #permalink-manager #plugin-name-heading .author-link{color:#959595;font-size:60%;text-decoration:none}
#permalink-manager #permalink-manager-tab-nav .section_upgrade,#permalink-manager #permalink-manager-tab-nav .section_support{background:#555;border-color:#555;color:#fff} #permalink-manager #permalink-manager-tab-nav .section_upgrade,#permalink-manager #permalink-manager-tab-nav .section_support{background:#555;border-color:#555;color:#fff}
#permalink-manager h4{font-size:18px;margin-bottom:10px} #permalink-manager h4{font-size:18px;margin-bottom:10px}
#permalink-manager h5{font-size:15px;margin-bottom:10px} #permalink-manager h5{font-size:15px;margin-bottom:10px}
#permalink-manager .small{display:block;font-weight:400;color:#888;font-size:80%} #permalink-manager .small{display:block;font-weight:400;color:#888;font-size:80%}
#permalink-manager .mute{color:#888} #permalink-manager .mute{color:#888}
#permalink-manager .settings-select{min-width:200px} #permalink-manager .settings-select{min-width:200px}
#permalink-manager .fixed-table{max-width:100%;table-layout:fixed} #permalink-manager .fixed-table{max-width:100%;table-layout:fixed}
#permalink-manager .margin-top{margin-top:15px} #permalink-manager .margin-top{margin-top:15px}
#permalink-manager .help_tooltip{text-decoration:none;color:#959595} #permalink-manager .help_tooltip{text-decoration:none;color:#959595}
#permalink-manager .small-select{height:24px;line-height:22px;padding:0 8px 1px;font-size:11px} #permalink-manager .small-select{height:24px;line-height:22px;padding:0 8px 1px;font-size:11px}
#permalink-manager .lead{font-size:125%} #permalink-manager .lead{font-size:125%}
#permalink-manager .licence-info{font-weight:bold} #permalink-manager .licence-info{font-weight:bold}
#permalink-manager p label{font-size:13px;color:#555d66;font-weight:bold}
#permalink-manager .woocommerce-icon:before{font-family:"WooCommerce";font-style:normal}
#permalink-manager .woocommerce-cart:before{content:"\e01d"} #permalink-manager .woocommerce-icon:before{font-family:"WooCommerce";font-style:normal}
#permalink-manager .woocommerce-logo:before{content:"\e03d"} #permalink-manager .woocommerce-cart:before{content:"\e01d"}
#permalink-manager .woocommerce-logo:before{content:"\e03d"}
#permalink-manager .subsubsub{display:block;width:100%;overflow:hidden;margin-bottom:25px}
#permalink-manager .subsubsub li:before{content:" | "} #permalink-manager .subsubsub{display:block;width:100%;overflow:hidden;margin-bottom:25px}
#permalink-manager .subsubsub li:first-child:before{content:"";color:#aaa} #permalink-manager .subsubsub li:before{content:" | "}
#permalink-manager .subsubsub li .dashicons,#permalink-manager .subsubsub li .woocommerce-logo{font-size:100%;line-height:200%;height:auto;width:auto} #permalink-manager .subsubsub li:first-child:before{content:"";color:#aaa}
#permalink-manager .single-section{clear:both} #permalink-manager .subsubsub li .dashicons,#permalink-manager .subsubsub li .woocommerce-logo{font-size:100%;line-height:200%;height:auto;width:auto}
#permalink-manager .tablenav{margin:15px 0;height:auto} #permalink-manager .single-section{clear:both}
#permalink-manager .tablenav.top{margin-top:0} #permalink-manager .tablenav{margin:15px 0;height:auto}
#permalink-manager .tablenav .actions{padding:0;overflow:visible} #permalink-manager .tablenav.top{margin-top:0}
#permalink-manager .tablenav #months-filter{margin-left:10px} #permalink-manager .tablenav .actions{padding:0;overflow:visible}
#permalink-manager .search-box{margin-left:1em} #permalink-manager .tablenav #months-filter{margin-left:10px}
#permalink-manager th#count a{display:inline-block} #permalink-manager .search-box{margin-left:1em}
#permalink-manager .post_permalink a,.post_permalink .dashicons{font-size:13px;color:#aaa;line-height:1.5em;height:auto;width:auto} #permalink-manager th#count a{display:inline-block}
#permalink-manager .post_permalink{margin-top:5px;display:block} #permalink-manager .post_permalink a,.post_permalink .dashicons{font-size:13px;color:#aaa;line-height:1.5em;height:auto;width:auto}
#permalink-manager .column-count,#permalink-manager .column-post_lang{width:1%} #permalink-manager .post_permalink{margin-top:5px;display:block}
#permalink-manager .column-count,#permalink-manager .column-post_lang,#permalink-manager th#count{text-align:right} #permalink-manager .column-count,#permalink-manager .column-post_lang{width:1%}
#permalink-manager .extra-info span{white-space:nowrap} #permalink-manager .column-count,#permalink-manager .column-post_lang,#permalink-manager th#count{text-align:right}
#permalink-manager .extra-info span{white-space:nowrap}
#permalink-manager .info{box-shadow:0 1px 1px 0 rgba(0,0,0,.1);display:block;overflow:hidden;clear:both;font-weight:bold;border-left:4px solid #dc3232;}
#permalink-manager .alert,#permalink-manager .info{line-height:19px;padding:11px 15px;margin:15px 0} #permalink-manager .info{box-shadow:0 1px 1px 0 rgba(0,0,0,.1);display:block;overflow:hidden;clear:both;font-weight:bold;border-left:4px solid #dc3232;}
#permalink-manager .alert p,#permalink-manager .info p{margin-top:0;line-height:200%} #permalink-manager .alert,#permalink-manager .info{line-height:19px;padding:11px 15px;margin:15px 0}
#permalink-manager .alert ul,#permalink-manager .alert ol{margin-top:0;margin-bottom:0} #permalink-manager .alert p,#permalink-manager .info p{margin-top:0;line-height:200%}
#permalink-manager .alert p:last-of-type,#permalink-manager .alert li:last-of-type,#permalink-manager .info p:last-of-type{margin-bottom:0} #permalink-manager .alert ul,#permalink-manager .alert ol{margin-top:0;margin-bottom:0}
#permalink-manager .warning{background:#dc3232} #permalink-manager .alert p:last-of-type,#permalink-manager .alert li:last-of-type,#permalink-manager .info p:last-of-type{margin-bottom:0}
#permalink-manager .warning,#permalink-manager .warning a{color:#fff} #permalink-manager .warning{background:#dc3232}
#permalink-manager .info{background:#f9f9f9} #permalink-manager .warning,#permalink-manager .warning a{color:#fff}
#permalink-manager .section-notes,#permalink-manager .short-pre,#permalink-manager .short-textarea{padding:15px;font-size:13px;margin-top:15px;line-height:20px;background:#e5e5e5;border:1px solid #ccc;color:#555} #permalink-manager .info{background:#f9f9f9}
#permalink-manager .section-notes a,#permalink-manager .section-notes h3{color:#111} #permalink-manager .section-notes,#permalink-manager .short-pre,#permalink-manager .short-textarea{padding:15px;font-size:13px;margin-top:15px;line-height:20px;background:#e5e5e5;border:1px solid #ccc;color:#555}
#permalink-manager .section-notes h3,#permalink-manager .section-notes h4{margin-top:0} #permalink-manager .section-notes a,#permalink-manager .section-notes h3{color:#111}
#permalink-manager .section-notes h4{font-size:14px} #permalink-manager .section-notes h3,#permalink-manager .section-notes h4{margin-top:0}
#permalink-manager .section-notes code{font-size:11px;background:#444;color:#fff} #permalink-manager .section-notes h4{font-size:14px}
#permalink-manager .section-notes ol{margin-top:0;margin-bottom:0} #permalink-manager .section-notes code{font-size:11px;background:#444;color:#fff}
#permalink-manager .section-notes ol li:last-of-type{margin-bottom:0} #permalink-manager .section-notes ol{margin-top:0;margin-bottom:0}
#permalink-manager .short-pre,#permalink-manager .short-textarea{height:150px;overflow:auto;max-width:100%;display:block} #permalink-manager .section-notes ol li:last-of-type{margin-bottom:0}
#permalink-manager .structure-tags-list{margin-top:15px} #permalink-manager .short-pre,#permalink-manager .short-textarea{height:150px;overflow:auto;max-width:100%;display:block}
#permalink-manager .duplicated_uri_alert,.permalink-manager .duplicated_uri_alert{display:block;font-weight:bold;font-size:90%;margin-top:8px;color:#dc3232} #permalink-manager .structure-tags-list{margin-top:15px}
#permalink-manager .duplicated_uri_alert,.permalink-manager .duplicated_uri_alert{display:block;font-weight:bold;font-size:90%;margin-top:8px;color:#dc3232}
#permalink-manager .checkbox_actions{padding-top:10px;border-top:1px solid #ddd}
#permalink-manager .extra-links,.permalink-manager-screen-options .extra-links{margin-top:5px;font-size:12px} #permalink-manager .checkbox_actions{padding-top:10px;border-top:1px solid #ddd}
#permalink-manager .extra-links a,.permalink-manager-screen-options .extra-links a{color:#666;display:inline-block;text-decoration:none} #permalink-manager .extra-links,.permalink-manager-screen-options .extra-links{margin-top:5px;font-size:12px}
#permalink-manager .extra-links a:before,.permalink-manager-screen-options .extra-links a:before{content:" | "} #permalink-manager .extra-links a,.permalink-manager-screen-options .extra-links a{color:#666;display:inline-block;text-decoration:none}
#permalink-manager .extra-links a:first-child:before,.permalink-manager-screen-options .extra-links a:first-child:before{content:""} #permalink-manager .extra-links a:before,.permalink-manager-screen-options .extra-links a:before{content:" | "}
.permalink-manager-screen-options{margin-bottom:15px} #permalink-manager .extra-links a:first-child:before,.permalink-manager-screen-options .extra-links a:first-child:before{content:""}
#permalink-manager .checkboxes{margin-left:-15px;margin-right:15px;overflow:hidden;display:block} .permalink-manager-screen-options{margin-bottom:15px}
#permalink-manager .checkboxes > label{display:inline-block;width:33%;float:left;padding:0 15px;box-sizing:border-box;padding-bottom:5px;overflow:hidden} #permalink-manager .checkboxes{margin-left:-15px;margin-right:15px;overflow:hidden;display:block}
#permalink-manager .checkboxes > label:nth-of-type(3n+1){clear:both} #permalink-manager .checkboxes > label{display:inline-block;width:33%;float:left;padding:0 15px;box-sizing:border-box;padding-bottom:5px;overflow:hidden}
#permalink-manager .field-description{font-size:12px} #permalink-manager .checkboxes > label:nth-of-type(3n+1){clear:both}
#permalink-manager .appended-row td{padding-left:0;padding-right:0} #permalink-manager .field-description{font-size:12px}
#permalink-manager #tools{margin:0 -15px;padding:0 15px 15px} #permalink-manager .appended-row td{padding-left:0;padding-right:0}
#permalink-manager #tools select{min-width:60%} #permalink-manager #tools{margin:0 -15px;padding:0 15px 15px}
#permalink-manager fieldset label{margin-bottom:0 !important} #permalink-manager #tools select{min-width:60%}
#permalink-manager fieldset label{margin-bottom:0 !important}
#permalink-manager .structure-tags-list{display:block;line-height:175%}
#permalink-manager .structure-tags-list code{} #permalink-manager .structure-tags-list{display:block;line-height:175%}
#permalink-manager .structure-tags-list code{}
#permalink-manager .updated-slugs-table .row-title{max-width:400px}
#permalink-manager .updated-slugs-table .row-title{max-width:400px}
/**
* Columns /**
*/ * Columns
#permalink-manager .columns-container{overflow:hidden;margin-left:-15px;margin-right:-15px;clear:both;display:block} */
#permalink-manager .columns-container > *{float:left;padding-left:15px;padding-right:15px;box-sizing:border-box;-webkit-box-sizing:border-box;overflow:hidden;display:block} #permalink-manager .columns-container{overflow:hidden;margin-left:-15px;margin-right:-15px;clear:both;display:block}
#permalink-manager .columns-container a{color:#aaa} #permalink-manager .columns-container > *{float:left;padding-left:15px;padding-right:15px;box-sizing:border-box;-webkit-box-sizing:border-box;overflow:hidden;display:block}
#permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-2_4{width:50%} #permalink-manager .columns-container span a{color:#aaa}
#permalink-manager .columns-container .column-1_3{width:33.33%} #permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-2_4{width:50%}
#permalink-manager .columns-container .column-1_3:nth-of-type(3n+1){clear:left} #permalink-manager .columns-container .column-1_3{width:33.33%}
#permalink-manager .columns-container .column-2_3{width:66.67%} #permalink-manager .columns-container .column-1_3:nth-of-type(3n+1){clear:left}
#permalink-manager .columns-container .column-1_4{width:25%} #permalink-manager .columns-container .column-2_3{width:66.67%}
#permalink-manager .columns-container .column-3_4{width:75%} #permalink-manager .columns-container .column-1_4{width:25%}
#permalink-manager .columns-container .column-3_4{width:75%}
#slugdiv #post_name{width:100%}
#slugdiv #post_name{width:100%}
/**
* Edit URI & Duplicate box /**
*/ * Edit URI & Duplicate box
#permalink-manager.permalink-manager-edit-uri-box{margin:10px -10px} */
#permalink-manager.permalink-manager-edit-uri-box h2{border-bottom:1px solid #eee} #permalink-manager.permalink-manager-edit-uri-box{margin:10px -10px}
#permalink-manager.permalink-manager-edit-uri-box .inside{padding:0 10px 10px 10px;margin-bottom:0} #permalink-manager.permalink-manager-edit-uri-box h2{border-bottom:1px solid #eee}
#permalink-manager.permalink-manager-edit-uri-box .inside > div{font-size:13px;line-height:1.5;margin:1em 0} #permalink-manager.permalink-manager-edit-uri-box .inside{padding:0 10px 10px 10px;margin-bottom:0}
#permalink-manager.permalink-manager-edit-uri-box .inside > div:last-child,#permalink-manager.permalink-manager-edit-uri-box .inside p:last-child{margin-bottom:0} #permalink-manager.permalink-manager-edit-uri-box .inside > div{font-size:13px;line-height:1.5;margin:1em 0}
#permalink-manager.permalink-manager-edit-uri-box .strong{display:block;font-weight:bold;margin-bottom:5px} #permalink-manager.permalink-manager-edit-uri-box .inside > div:last-child,#permalink-manager.permalink-manager-edit-uri-box .inside p:last-child{margin-bottom:0}
#permalink-manager.permalink-manager-edit-uri-box .toggle-indicator:before{content:"\f142";display:inline-block;font:400 20px/1 dashicons} #permalink-manager.permalink-manager-edit-uri-box .strong{display:block;font-weight:bold;margin-bottom:5px}
#permalink-manager.permalink-manager-edit-uri-box .columns-container{margin-left:-10px!important;margin-right:-10px!important} #permalink-manager.permalink-manager-edit-uri-box .toggle-indicator:before{content:"\f142";display:inline-block;font:400 20px/1 dashicons}
#permalink-manager.permalink-manager-edit-uri-box .columns-container > *{padding-left:10px;padding-right:10px} #permalink-manager.permalink-manager-edit-uri-box .columns-container{margin-left:-10px!important;margin-right:-10px!important}
#permalink-manager.permalink-manager-edit-uri-box .close-button{float:right;width:36px;height:36px;padding:0;cursor:pointer;display:block} #permalink-manager.permalink-manager-edit-uri-box .columns-container > *{padding-left:10px;padding-right:10px}
#permalink-manager.permalink-manager-edit-uri-box .close-icon{margin-top:4px;-webkit-border-radius:50%;border-radius:50%;text-indent:-1px;color:#72777c;line-height:36px;display:block;text-align:center} #permalink-manager.permalink-manager-edit-uri-box .close-button{float:right;width:36px;height:36px;padding:0;cursor:pointer;display:block}
#permalink-manager.permalink-manager-edit-uri-box .close-icon:before{content:"\f158";display:inline-block;font:400 20px/1 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none!important} #permalink-manager.permalink-manager-edit-uri-box .close-icon{margin-top:4px;-webkit-border-radius:50%;border-radius:50%;text-indent:-1px;color:#72777c;line-height:36px;display:block;text-align:center}
#permalink-manager .default-permalink-row,#permalink-manager .redirects-row{border-top:1px solid #eee;padding-top:10px} #permalink-manager.permalink-manager-edit-uri-box .close-icon:before{content:"\f158";display:inline-block;font:400 20px/1 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none!important}
#permalink-manager .redirects-row{border-top:3px double #eee;padding-top:10px} #permalink-manager .default-permalink-row,#permalink-manager .redirects-row{border-top:1px solid #eee;padding-top:15px}
#permalink-manager .default-permalink-row,#permalink-manager .default-permastruct-row,#permalink-manager .redirects-row{color:#aaa;font-size:90%} #permalink-manager .default-permalink-row,#permalink-manager .default-permastruct-row,#permalink-manager .redirects-row{color:#aaa;font-size:90%}
#permalink-manager .restore-default{display:inline-block;text-align:right;width:100%;border-radius:0;color:#959595;text-decoration:none} #permalink-manager .restore-default{display:inline-block;text-align:right;width:100%;border-radius:0;color:#959595;text-decoration:none}
#permalink-manager .widefat,#permalink-manager #redirect-panel-inside,#permalink-manager #redirect-panel-inside table{width:100%!important} #permalink-manager .widefat,#permalink-manager #redirect-panel-inside,#permalink-manager #redirect-panel-inside table{width:100%!important}
#permalink-manager .heading,#permalink-manager .heading a{margin:0;line-height:1.4;font-weight:600;text-decoration:none;color:#777} #permalink-manager .heading,#permalink-manager .heading a{margin:0;line-height:1.4;font-weight:600;text-decoration:none;color:#777}
#permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box{display:block!important;margin:0} #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box{display:block!important;margin:0}
#permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box h2,.permalink-manager.postbox .heading{font-size:14px!important;padding:8px 12px;margin:0;line-height:1.4} #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box h2,.permalink-manager.postbox .heading{font-size:14px!important;padding:8px 12px;margin:0;line-height:1.4}
#permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box .close-button,#permalink-manager.permalink-manager-edit-term #permalink-manager-toggle{display:none} #permalink-manager.permalink-manager-edit-term .permalink-manager-edit-uri-box .close-button,#permalink-manager.permalink-manager-edit-term #permalink-manager-toggle{display:none}
#permalink-manager .permalink-manager-duplicate-box table{width:100%;color:#aaa} #permalink-manager .permalink-manager-duplicate-box table{width:100%;color:#aaa}
#permalink-manager .permalink-manager-duplicate-box table tr td{border-top:1px solid #eee} #permalink-manager .permalink-manager-duplicate-box table tr td{border-top:1px solid #eee}
#permalink-manager .permalink-manager-duplicate-box table tr:first-child td{border-top:0} #permalink-manager .permalink-manager-duplicate-box table tr:first-child td{border-top:0}
#permalink-manager .permalink-manager-duplicate-box table td{font-size:12px;line-height:1.5em;padding:8px 12px} #permalink-manager .permalink-manager-duplicate-box table td{font-size:12px;line-height:1.5em;padding:8px 12px}
#permalink-manager .permalink-manager-duplicate-box table tr td:first-child{width:60%} #permalink-manager .permalink-manager-duplicate-box table tr td:first-child{width:60%}
#permalink-manager .permalink-manager-duplicate-box table tr td:last-child{text-align:right} #permalink-manager .permalink-manager-duplicate-box table tr td:last-child{text-align:right}
#permalink-manager .permalink-manager-duplicate-box .actions a{text-decoration:none} #permalink-manager .permalink-manager-duplicate-box .actions a{text-decoration:none}
#permalink-manager .permalink-manager-duplicate-box .remove-duplicate-link{color:#a00} #permalink-manager .permalink-manager-duplicate-box .remove-duplicate-link{color:#a00}
.permalink-manager.postbox .heading{border-bottom:3px double #eee} .permalink-manager.postbox .heading{border-bottom:3px double #eee}
.permalink-manager.postbox a{color:#444;text-decoration:none;white-space:nowrap} .permalink-manager.postbox a{color:#444;text-decoration:none;white-space:nowrap}
/** #permalink-manager .permalink-manager-gutenberg > div{margin-top:15px;}
* Redirect panel #permalink-manager .permalink-manager-gutenberg .default-permalink-row > *{width:100%;float:none}
*/ #permalink-manager .permalink-manager-gutenberg .restore-default{text-align:left;margin-top:15px}
.permalink-manager #redirect-panel-inside{display:none} #permalink-manager .permalink-manager-gutenberg .redirects-row{padding-top:15px}
.permalink-manager #redirect-panel-inside,#permalink-manager #redirect-panel-inside p{margin-top:10px} #permalink-manager .permalink-manager-gutenberg .redirects-panel .heading{background:#eee;padding:15px 10px;margin-bottom:-15px;width:100%;display:block;font-size:110%}
.permalink-manager #redirect-panel-inside table{margin-bottom:10px} #permalink-manager #redirect-panel-inside, #permalink-manager #redirect-panel-inside p{margin-top:15px}
.permalink-manager #redirect-panel-inside table td{padding:5px 0;width:100%} #permalink-manager .redirects-panel-description *{font-size:11px}
.permalink-manager #redirect-panel-inside table td a{text-decoration:none;text-align:right}
.permalink-manager #redirect-panel-inside .single-section{margin-left:-10px;margin-right:-10px;padding:10px;border-top:1px dashed #eee} /**
.permalink-manager #redirect-panel-inside .single-section:last-of-type{padding-bottom:0} * Redirect panel
.permalink-manager .sample-row{display:none} */
.permalink-manager .redirects-panel-description{margin-bottom:10px} #permalink-manager #redirect-panel-inside{display:none}
.permalink-manager .redirects-panel-description *{font-size:12px} #permalink-manager #redirect-panel-inside,#permalink-manager #redirect-panel-inside p{margin-top:15px;}
#permalink-manager #redirect-panel-inside table{margin-bottom:10px;margin-top:-5px}
/** #permalink-manager #redirect-panel-inside table td{padding:5px 0;width:100%}
* Coupon panel #permalink-manager #redirect-panel-inside table td a{text-decoration:none;text-align:right}
*/ #permalink-manager #redirect-panel-inside .single-section{margin-left:-10px;margin-right:-10px;padding:10px;border-top:1px dashed #eee}
#permalink-manager-coupon-url > p:last-of-type{font-size:13px} #permalink-manager #redirect-panel-inside .single-section:last-of-type{padding-bottom:0}
#permalink-manager #redirect-panel-inside .single-section:first-of-type{padding-top:0;border:0}
/** #permalink-manager #redirect-panel-inside .single-section > p:first-of-type{margin-top:0}
* Tippy.js custom theme .permalink-manager .sample-row{display:none}
*/ .permalink-manager .redirects-panel-description{margin-bottom:10px}
.tippy-tooltip.tippy-pm-theme{text-align:left;font-size:13px} .permalink-manager .redirects-panel-description *{font-size:12px}
/** /**
* TagEditor custom theme & "Stop Words" * Coupon panel
*/ */
#permalink-manager .words-editor{font-size:90%;height:400px;overflow-y:auto;border:1px solid #ddd;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.07);box-shadow:inset 0 1px 2px rgba(0,0,0,.07);background-color:#fff;color:#32373c;outline:0;-webkit-transition:50ms border-color ease-in-out;transition:50ms border-color ease-in-out;} #permalink-manager-coupon-url > p:last-of-type{font-size:13px}
#permalink-manager .words-editor .tag{background:#eee}
#permalink-manager .words-editor .tag a{color:#000} /**
#permalink-manager .stop-words-buttons{width:100%} * Tippy.js custom theme
#permalink-manager .stop-words-buttons tr > td:first-child{padding-left:0;width:50%} */
#permalink-manager .stop-words-buttons tr > td:last-child{padding-right:0} .tippy-tooltip.tippy-pm-theme{text-align:left;font-size:13px}
/** /**
* Breakpoints * TagEditor custom theme & "Stop Words"
*/ */
@media only screen and (min-width :992px) { #permalink-manager .words-editor{font-size:90%;height:400px;overflow-y:auto;border:1px solid #ddd;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.07);box-shadow:inset 0 1px 2px rgba(0,0,0,.07);background-color:#fff;color:#32373c;outline:0;-webkit-transition:50ms border-color ease-in-out;transition:50ms border-color ease-in-out;}
#permalink-manager #permalink-manager-tab-nav .section_debug,#permalink-manager #permalink-manager-tab-nav .section_upgrade,#permalink-manager #permalink-manager-tab-nav .section_support{float:right} #permalink-manager .words-editor .tag{background:#eee}
#permalink-manager .permastruct-container{display:table;width:100%;table-layout:auto} #permalink-manager .words-editor .tag a{color:#000}
#permalink-manager .permastruct-container > *{display:table-cell} #permalink-manager .stop-words-buttons{width:100%}
#permalink-manager .permastruct-container > span:first-child{width:1%;white-space:nowrap} #permalink-manager .stop-words-buttons tr > td:first-child{padding-left:0;width:50%}
#permalink-manager .permastruct-field{width:100%} #permalink-manager .stop-words-buttons tr > td:last-child{padding-right:0}
#permalink-manager .column-item_uri{width:600px;max-width:100%} /**
#permalink-manager .column-item_uri input{width:100%} * Breakpoints
} */
@media only screen and (max-width :782px) { @media only screen and (min-width :992px) {
#permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-1_3,#permalink-manager .columns-container .column-2_3{width:100%} #permalink-manager #permalink-manager-tab-nav .section_debug,#permalink-manager #permalink-manager-tab-nav .section_upgrade,#permalink-manager #permalink-manager-tab-nav .section_support{float:right}
#permalink-manager .permalink-manager-duplicate-box table tr td:first-child{width:40%} #permalink-manager .permastruct-container{display:table;width:100%;table-layout:auto}
} #permalink-manager .permastruct-container > *{display:table-cell}
#permalink-manager .permastruct-container > span:first-child{width:1%;white-space:nowrap}
#permalink-manager .permastruct-field{width:100%}
#permalink-manager .column-item_uri{width:600px;max-width:100%}
#permalink-manager .column-item_uri input{width:100%}
}
@media only screen and (max-width :782px) {
#permalink-manager .columns-container .column-1_2,#permalink-manager .columns-container .column-1_3,#permalink-manager .columns-container .column-2_3{width:100%}
#permalink-manager .permalink-manager-duplicate-box table tr td:first-child{width:40%}
}
jQuery(document).ready(function() { jQuery(document).ready(function() {
/** /**
* "(Un)select all" checkboxes * "(Un)select all" checkboxes
*/ */
var checkbox_actions = ['select_all', 'unselect_all']; var checkbox_actions = ['select_all', 'unselect_all'];
checkbox_actions.forEach(function(element) { checkbox_actions.forEach(function(element) {
jQuery('#permalink-manager .' + element).on('click', function() { jQuery('#permalink-manager .' + element).on('click', function() {
jQuery(this).parents('.field-container').find('.checkboxes input[type="checkbox"]').each(function() { jQuery(this).parents('.field-container').find('.checkboxes input[type="checkbox"]').each(function() {
var action = (element == 'select_all') ? true : false; var action = (element == 'select_all') ? true : false;
jQuery(this).prop('checked', action); jQuery(this).prop('checked', action);
}); });
return false; return false;
}); });
}); });
jQuery('#permalink-manager .checkboxes label').not('input').on('click', function(ev) { jQuery('#permalink-manager .checkboxes label').not('input').on('click', function(ev) {
var input = jQuery(this).find("input"); var input = jQuery(this).find("input");
if(!jQuery(ev.target).is("input")) { if(!jQuery(ev.target).is("input")) {
input.prop('checked', !(input.prop("checked"))); input.prop('checked', !(input.prop("checked")));
} }
}); });
/** /**
* Filter by dates in "Permalink editor" * Filter by dates in "Permalink editor"
*/ */
jQuery('#permalink-manager #months-filter-button').on('click', function() { jQuery('#permalink-manager #months-filter-button').on('click', function() {
var filter_name = jQuery("#months-filter-select").attr('name'); var filter_name = jQuery("#months-filter-select").attr('name');
var filter_value = jQuery("#months-filter-select").val(); var filter_value = jQuery("#months-filter-select").val();
var url = jQuery(this).parent().data('filter-url'); var url = jQuery(this).parent().data('filter-url');
if(filter_name != '' && filter_value != '' && url != ''){ if(filter_name != '' && filter_value != '' && url != ''){
document.location.href = url + "&" + filter_name + "=" + filter_value; document.location.href = url + "&" + filter_name + "=" + filter_value;
} }
return false; return false;
}); });
/** /**
* Filter by content types in "Tools" * Filter by content types in "Tools"
*/ */
jQuery('#permalink-manager *[data-field="content_type"] select').on('change', function() { jQuery('#permalink-manager *[data-field="content_type"] select').on('change', function() {
var content_type = jQuery(this).val(); var content_type = jQuery(this).val();
if(content_type == 'post_types') { if(content_type == 'post_types') {
jQuery(this).parents('.form-table').find('*[data-field="post_types"],*[data-field="post_statuses"]').removeClass('hidden'); jQuery(this).parents('.form-table').find('*[data-field="post_types"],*[data-field="post_statuses"]').removeClass('hidden');
jQuery(this).parents('.form-table').find('*[data-field="taxonomies"]').addClass('hidden'); jQuery(this).parents('.form-table').find('*[data-field="taxonomies"]').addClass('hidden');
} else { } else {
jQuery(this).parents('.form-table').find('*[data-field="post_types"],*[data-field="post_statuses"]').addClass('hidden'); jQuery(this).parents('.form-table').find('*[data-field="post_types"],*[data-field="post_statuses"]').addClass('hidden');
jQuery(this).parents('.form-table').find('*[data-field="taxonomies"]').removeClass('hidden'); jQuery(this).parents('.form-table').find('*[data-field="taxonomies"]').removeClass('hidden');
} }
}).trigger("change"); }).trigger("change");
/** /**
* Toggle "Edit URI" box * Toggle "Edit URI" box
*/ */
jQuery('#permalink-manager-toggle, .permalink-manager-edit-uri-box .close-button').on('click', function() { jQuery('#permalink-manager-toggle, .permalink-manager-edit-uri-box .close-button').on('click', function() {
jQuery('.permalink-manager-edit-uri-box').slideToggle(); jQuery('.permalink-manager-edit-uri-box').slideToggle();
return false; return false;
}); });
/** /**
* Toggle "Edit Redirects" box * Toggle "Edit Redirects" box
*/ */
jQuery('#toggle-redirect-panel').on('click', function() { jQuery('#permalink-manager').on('click', '#toggle-redirect-panel', function() {
jQuery('#redirect-panel-inside').slideToggle(); jQuery('#redirect-panel-inside').slideToggle();
return false; return false;
}); });
jQuery('.permalink-manager.redirects-panel #permalink-manager-new-redirect').on('click', function() { jQuery('#permalink-manager').on('click', '.permalink-manager.redirects-panel #permalink-manager-new-redirect', function() {
// Find the table // Find the table
var table = jQuery(this).parents('.redirects-panel').find('table'); var table = jQuery(this).parents('.redirects-panel').find('table');
// Copy the row from the sample // Copy the row from the sample
var new_row = jQuery(this).parents('.redirects-panel').find('.sample-row').clone().removeClass('sample-row'); var new_row = jQuery(this).parents('.redirects-panel').find('.sample-row').clone().removeClass('sample-row');
// Adjust the array key // Adjust the array key
var last_key = jQuery(table).find("tr:last-of-type input[data-index]").data("index") + 1; var last_key = jQuery(table).find("tr:last-of-type input[data-index]").data("index") + 1;
jQuery("input[data-index]", new_row).attr("data-index", last_key).attr("name", function(){ return jQuery(this).attr("name") + "[" + last_key + "]" }); jQuery("input[data-index]", new_row).attr("data-index", last_key).attr("name", function(){ return jQuery(this).attr("name") + "[" + last_key + "]" });
// Append the new row // Append the new row
jQuery(table).append(new_row); jQuery(table).append(new_row);
return false; return false;
}); });
jQuery('.permalink-manager.redirects-panel').on('click', '.remove-redirect', function() { jQuery('#permalink-manager').on('click', '.remove-redirect', function() {
var table = jQuery(this).closest('tr').remove(); var table = jQuery(this).closest('tr').remove();
return false; return false;
}); });
/** /**
* Synchronize "Edit URI" input field with the sample permalink * Synchronize "Edit URI" input field with the sample permalink
*/ */
var custom_uri_input = jQuery('.permalink-manager-edit-uri-box input[name="custom_uri"]'); var custom_uri_input = jQuery('.permalink-manager-edit-uri-box input[name="custom_uri"]');
jQuery(custom_uri_input).on('keyup change', function() { jQuery(custom_uri_input).on('keyup change', function() {
jQuery('.sample-permalink-span .editable').text(jQuery(this).val()); jQuery('.sample-permalink-span .editable').text(jQuery(this).val());
}); });
/** /**
* Synchronize "Coupon URI" input field with the final permalink * Synchronize "Coupon URI" input field with the final permalink
*/ */
jQuery('#permalink-manager-coupon-url input[name="custom_uri"]').on('keyup change', function() { jQuery('#permalink-manager-coupon-url input[name="custom_uri"]').on('keyup change', function() {
var uri = jQuery(this).val(); var uri = jQuery(this).val();
jQuery('#permalink-manager-coupon-url code span').text(uri); jQuery('#permalink-manager-coupon-url code span').text(uri);
if(!uri) { if(!uri) {
jQuery('#permalink-manager-coupon-url .coupon-full-url').addClass("hidden"); jQuery('#permalink-manager-coupon-url .coupon-full-url').addClass("hidden");
} else { } else {
jQuery('#permalink-manager-coupon-url .coupon-full-url').removeClass("hidden"); jQuery('#permalink-manager-coupon-url .coupon-full-url').removeClass("hidden");
} }
}); });
function permalink_manager_duplicate_check(custom_uri_input, multi) { function permalink_manager_duplicate_check(custom_uri_input, multi) {
// Set default values // Set default values
custom_uri_input = typeof custom_uri_input !== 'undefined' ? custom_uri_input : false; custom_uri_input = typeof custom_uri_input !== 'undefined' ? custom_uri_input : false;
multi = typeof multi !== 'undefined' ? multi : false; multi = typeof multi !== 'undefined' ? multi : false;
var all_custom_uris_values = {}; var all_custom_uris_values = {};
if(custom_uri_input) { if(custom_uri_input) {
var custom_uri = jQuery(custom_uri_input).val(); var custom_uri = jQuery(custom_uri_input).val();
var element_id = jQuery(custom_uri_input).attr("data-element-id"); var element_id = jQuery(custom_uri_input).attr("data-element-id");
all_custom_uris_values[element_id] = custom_uri; all_custom_uris_values[element_id] = custom_uri;
} else { } else {
jQuery('.custom_uri').each(function(i, obj) { jQuery('.custom_uri').each(function(i, obj) {
var field_name = jQuery(obj).attr('data-element-id'); var field_name = jQuery(obj).attr('data-element-id');
all_custom_uris_values[field_name] = jQuery(obj).val(); all_custom_uris_values[field_name] = jQuery(obj).val();
}); });
} }
if(all_custom_uris_values) { if(all_custom_uris_values) {
jQuery.ajax(permalink_manager.ajax_url, { jQuery.ajax(permalink_manager.ajax_url, {
type: 'POST', type: 'POST',
async: true, async: true,
data: { data: {
action: 'detect_duplicates', action: 'detect_duplicates',
custom_uris: all_custom_uris_values custom_uris: all_custom_uris_values
}, },
success: function(data) { success: function(data) {
if(data.length > 5) { if(data.length > 5) {
var results = JSON.parse(data); var results = JSON.parse(data);
// Loop through results // Loop through results
jQuery.each(results, function(key, is_duplicate) { jQuery.each(results, function(key, is_duplicate) {
var alert_container = jQuery('.custom_uri[data-element-id="' + key + '"]').parents('.custom_uri_container').find('.duplicated_uri_alert'); var alert_container = jQuery('.custom_uri[data-element-id="' + key + '"]').parents('.custom_uri_container').find('.duplicated_uri_alert');
if(is_duplicate) { if(is_duplicate) {
jQuery(alert_container).text(is_duplicate); jQuery(alert_container).text(is_duplicate);
} else { } else {
jQuery(alert_container).empty(); jQuery(alert_container).empty();
} }
}); });
} }
} }
}); });
} }
} }
/** /**
* Check if a single custom URI is not duplicated * Check if a single custom URI is not duplicated
*/ */
var custom_uri_check_timeout = null; var custom_uri_check_timeout = null;
jQuery('.custom_uri_container input[name="custom_uri"], .custom_uri_container input.custom_uri').each(function() { jQuery('.custom_uri_container input[name="custom_uri"], .custom_uri_container input.custom_uri').each(function() {
var input = this; var input = this;
jQuery(this).on('keyup change', function() { jQuery(this).on('keyup change', function() {
clearTimeout(custom_uri_check_timeout); clearTimeout(custom_uri_check_timeout);
// Wait until user finishes typing // Wait until user finishes typing
custom_uri_check_timeout = setTimeout(function() { custom_uri_check_timeout = setTimeout(function() {
permalink_manager_duplicate_check(input); permalink_manager_duplicate_check(input);
}, 500); }, 500);
}); });
}); });
/** /**
* Check if a all any of displayed custom URIs is not duplicated * Check if a all any of displayed custom URIs is not duplicated
*/ */
if(jQuery('.custom_uri').length > 0) { if(jQuery('.custom_uri').length > 0) {
permalink_manager_duplicate_check(false, true); permalink_manager_duplicate_check(false, true);
} }
/** /**
* Disable "Edit URI" input if URI should be updated automatically * Disable "Edit URI" input if URI should be updated automatically
*/ */
jQuery('.permalink-manager-edit-uri-box select[name="auto_update_uri"]').on('change', function() { jQuery('.permalink-manager-edit-uri-box select[name="auto_update_uri"]').on('change', function() {
var selected = jQuery(this).find('option:selected'); var selected = jQuery(this).find('option:selected');
var auto_update_status = jQuery(selected).data('auto-update'); var auto_update_status = jQuery(selected).data('auto-update');
if(auto_update_status == 1) { if(auto_update_status == 1) {
jQuery(custom_uri_input).attr("readonly", true); jQuery(custom_uri_input).attr("readonly", true);
} else { } else {
jQuery(custom_uri_input).removeAttr("readonly", true); jQuery(custom_uri_input).removeAttr("readonly", true);
} }
}).trigger("change"); }).trigger("change");
/** /**
* Restore "Default URI" * Restore "Default URI"
*/ */
jQuery('#permalink-manager .restore-default').on('click', function() { jQuery('#permalink-manager').on('click', '.restore-default', function() {
var input = jQuery(this).parents('.field-container, .permalink-manager-edit-uri-box').find('input.custom_uri'); var input = jQuery(this).parents('.field-container, .permalink-manager-edit-uri-box, #permalink-manager .inside').find('input.custom_uri, input.permastruct-field');
jQuery(input).val(jQuery(input).data('default')).trigger('keyup'); var default_uri = jQuery(input).attr('data-default');
return false;
}); jQuery(input).val(default_uri).trigger('keyup');
/** return false;
* Hide global admin notices });
*/
jQuery(document).on('click', '.permalink-manager-notice.is-dismissible .notice-dismiss', function() { /**
var alert_id = jQuery(this).closest('.permalink-manager-notice').data('alert_id'); * Hide global admin notices
*/
jQuery.ajax(permalink_manager.ajax_url, { jQuery(document).on('click', '.permalink-manager-notice.is-dismissible .notice-dismiss', function() {
type: 'POST', var alert_id = jQuery(this).closest('.permalink-manager-notice').data('alert_id');
data: {
action: 'dismissed_notice_handler', jQuery.ajax(permalink_manager.ajax_url, {
alert_id: alert_id, type: 'POST',
} data: {
}); action: 'dismissed_notice_handler',
}); alert_id: alert_id,
}
/** });
* Check expiration date });
*/
jQuery(document).on('click', '#pm_get_exp_date', function() { /**
jQuery.ajax(permalink_manager.ajax_url, { * Save permalinks from Gutenberg with AJAX
type: 'POST', */
data: { jQuery('#permalink-manager .save-row.hidden').removeClass('hidden');
action: 'pm_get_exp_date', jQuery('#permalink-manager').on('click', '#permalink-manager-save-button', function() {
}, var pm_container = jQuery(this).parents('#permalink-manager');
beforeSend: function() { var pm_fields = jQuery(pm_container).find("input, select");
var spinner = '<img src="' + permalink_manager.spinners + '/wpspin_light-2x.gif" width="16" height="16">'; var pm_data = jQuery(pm_fields).serialize() + '&action=' + 'pm_save_permalink';
jQuery('#permalink-manager .licence-info').html(spinner); var button = jQuery(this);
},
success: function(data) { jQuery.ajax({
jQuery('#permalink-manager .licence-info').html(data); type: 'POST',
} url: permalink_manager.ajax_url,
}); data: pm_data,
beforeSend: function() {
return false; jQuery(pm_container).LoadingOverlay("show", {
}); background : "rgba(0, 0, 0, 0.1)",
});
/** },
* Bulk tools success: function(html) {
*/ jQuery(pm_container).find('.permalink-manager-gutenberg').replaceWith(html);
function pm_show_progress(elem, progress) { jQuery(pm_container).LoadingOverlay("hide");
if(progress) {
jQuery(elem).LoadingOverlay("text", progress + "%"); if(wp && wp.data !== 'undefined') {
} else { wp.data.dispatch('core/editor').refreshPost();
jQuery(elem).LoadingOverlay("show", { }
background : "rgba(0, 0, 0, 0.1)", }
text: '0%' });
});
} return false;
} });
jQuery('#permalink-manager #tools form').on('submit', function() { /**
var data = jQuery(this).serialize() + '&action=' + 'pm_bulk_tools'; * Help tooltips
var form = jQuery(this); */
var updated_count = total = progress = 0; new Tippy('#permalink-manager .help_tooltip', {
position: 'top-start',
// Hide alert & results table arrow: true,
jQuery('#permalink-manager .updated-slugs-table, .permalink-manager-notice.updated_slugs, #permalink-manager #updated-list').remove(); theme: 'tippy-pm',
distance: 20,
jQuery.ajax({ });
type: 'POST',
url: permalink_manager.ajax_url,
data: data, /**
beforeSend: function() { * Check expiration date
// Show progress overlay */
pm_show_progress("#permalink-manager #tools", progress); jQuery(document).on('click', '#pm_get_exp_date', function() {
}, jQuery.ajax(permalink_manager.ajax_url, {
success: function(data) { type: 'POST',
var table_dom = jQuery('#permalink-manager .updated-slugs-table'); data: {
// console.log(data); action: 'pm_get_exp_date',
},
// Display the table beforeSend: function() {
if(data.hasOwnProperty('html')) { var spinner = '<img src="' + permalink_manager.spinners + '/wpspin_light-2x.gif" width="16" height="16">';
var table = jQuery(data.html); jQuery('#permalink-manager .licence-info').html(spinner);
},
if(table_dom.length == 0) { success: function(data) {
jQuery('#permalink-manager #tools').after(data.html); jQuery('#permalink-manager .licence-info').html(data);
} else { }
jQuery(table_dom).append(jQuery(table).find('tbody').html()); });
}
} return false;
});
// Hide error message
jQuery('.permalink-manager-notice.updated_slugs.error').remove(); /**
* Bulk tools
// Display the alert (should be hidden at first) */
if(data.hasOwnProperty('alert') && jQuery('.permalink-manager-notice.updated_slugs .updated_count').length == 0) { function pm_show_progress(elem, progress) {
var alert = jQuery(data.alert).hide(); if(progress) {
jQuery('#plugin-name-heading').after(alert); jQuery(elem).LoadingOverlay("text", progress + "%");
} } else {
jQuery(elem).LoadingOverlay("show", {
// Increase updated count background : "rgba(0, 0, 0, 0.1)",
if(data.hasOwnProperty('updated_count')) { text: '0%'
if(jQuery(form).attr("data-updated_count")) { });
updated_count = parseInt(jQuery(form).attr("data-updated_count")) + parseInt(data.updated_count); }
} else { }
updated_count = parseInt(data.updated_count);
} jQuery('#permalink-manager #tools form.form-ajax').on('submit', function() {
var data = jQuery(this).serialize() + '&action=' + 'pm_bulk_tools';
jQuery(form).attr("data-updated_count", updated_count); var form = jQuery(this);
jQuery('.permalink-manager-notice.updated_slugs .updated_count').text(updated_count); var updated_count = total = progress = 0;
}
// Hide alert & results table
// Show total jQuery('#permalink-manager .updated-slugs-table, .permalink-manager-notice.updated_slugs, #permalink-manager #updated-list').remove();
if(data.hasOwnProperty('total')) {
total = parseInt(data.total); jQuery.ajax({
type: 'POST',
jQuery(form).attr("data-total", total); url: permalink_manager.ajax_url,
} data: data,
beforeSend: function() {
// Trigger again // Show progress overlay
if(data.hasOwnProperty('left_chunks')) { pm_show_progress("#permalink-manager #tools", progress);
jQuery.ajax(this); },
success: function(data) {
// Update progress var table_dom = jQuery('#permalink-manager .updated-slugs-table');
if(data.hasOwnProperty('progress')) { // console.log(data);
console.log(data.progress);
console.log(total); // Display the table
if(data.hasOwnProperty('html')) {
progress = Math.floor((data.progress / total) * 100) var table = jQuery(data.html);
}
} else { if(table_dom.length == 0) {
// Display results jQuery('#permalink-manager #tools').after(data.html);
jQuery('.permalink-manager-notice.updated_slugs').fadeIn(); } else {
jQuery('#permalink-manager #tools').LoadingOverlay("hide", true); jQuery(table_dom).append(jQuery(table).find('tbody').html());
}
if(table_dom.length > 0) { }
jQuery('html, body').animate({
scrollTop: table_dom.offset().top - 100 // Hide error message
}, 2000); jQuery('.permalink-manager-notice.updated_slugs.error').remove();
}
// Display the alert (should be hidden at first)
// Reset progress & updated count if(data.hasOwnProperty('alert') && jQuery('.permalink-manager-notice.updated_slugs .updated_count').length == 0) {
progress = updated_count = 0; var alert = jQuery(data.alert).hide();
jQuery(form).attr("data-updated_count", 0); jQuery('#plugin-name-heading').after(alert);
} }
}
}); // Increase updated count
if(data.hasOwnProperty('updated_count')) {
return false; if(jQuery(form).attr("data-updated_count")) {
}); updated_count = parseInt(jQuery(form).attr("data-updated_count")) + parseInt(data.updated_count);
} else {
/** updated_count = parseInt(data.updated_count);
* Help tooltips }
*/
new Tippy('#permalink-manager .help_tooltip', { jQuery(form).attr("data-updated_count", updated_count);
position: 'top-start', jQuery('.permalink-manager-notice.updated_slugs .updated_count').text(updated_count);
arrow: true, }
theme: 'tippy-pm',
distance: 20, // Show total
}); if(data.hasOwnProperty('total')) {
total = parseInt(data.total);
/**
* Stop-words jQuery(form).attr("data-total", total);
*/ }
var stop_words_input = '#permalink-manager .field-container textarea.stop_words';
// Trigger again
if(jQuery(stop_words_input).length > 0) { if(data.hasOwnProperty('left_chunks')) {
var stop_words = new TIB(document.querySelector(stop_words_input), { jQuery.ajax(this);
alert: false,
escape: null, // Update progress
classes: ['tags words-editor', 'tag', 'tags-input', 'tags-output', 'tags-view'], if(data.hasOwnProperty('progress')) {
}); console.log(data.progress);
jQuery('.tags-output').hide(); console.log(total);
// Force lowercase progress = Math.floor((data.progress / total) * 100)
stop_words.filter = function(text) { }
return text.toLowerCase(); } else {
}; // Display results
jQuery('.permalink-manager-notice.updated_slugs').fadeIn();
// Remove all words jQuery('#permalink-manager #tools').LoadingOverlay("hide", true);
jQuery('#permalink-manager .field-container .clear_all_words').on('click', function() {
stop_words.reset(); if(table_dom.length > 0) {
}); jQuery('html, body').animate({
scrollTop: table_dom.offset().top - 100
// Load stop-words list }, 2000);
jQuery('#permalink-manager #load_stop_words_button').on('click', function() { }
var lang = jQuery( ".load_stop_words option:selected" ).val();
if(lang) { // Reset progress & updated count
var json_url = permalink_manager.url + "/includes/ext/stopwords-json/dist/" + lang + ".json"; progress = updated_count = 0;
jQuery(form).attr("data-updated_count", 0);
// Load JSON with words list }
jQuery.getJSON(json_url, function(data) { }
var new_words = []; });
jQuery.each(data, function(key, val) { return false;
new_words.push(val); });
});
/**
stop_words.update(new_words); * Stop-words
}); */
} var stop_words_input = '#permalink-manager .field-container textarea.stop_words';
return false; if(jQuery(stop_words_input).length > 0) {
}); var stop_words = new TIB(document.querySelector(stop_words_input), {
} alert: false,
escape: null,
/** classes: ['tags words-editor', 'tag', 'tags-input', 'tags-output', 'tags-view'],
* Quick Edit });
*/ jQuery('.tags-output').hide();
if(typeof inlineEditPost !== "undefined") {
var inline_post_editor = inlineEditPost.edit; // Force lowercase
inlineEditPost.edit = function(id) { stop_words.filter = function(text) {
inline_post_editor.apply(this, arguments); return text.toLowerCase();
};
// Get the Post ID
var post_id = 0; // Remove all words
if(typeof(id) == 'object') { jQuery('#permalink-manager .field-container .clear_all_words').on('click', function() {
post_id = parseInt(this.getId(id)); stop_words.reset();
} });
if(post_id != 0) { // Load stop-words list
// Get the row & "Custom URI" field jQuery('#permalink-manager #load_stop_words_button').on('click', function() {
custom_uri_field = jQuery('#edit-' + post_id).find('.custom_uri'); var lang = jQuery( ".load_stop_words option:selected" ).val();
if(lang) {
// Prepare the Custom URI var json_url = permalink_manager.url + "/includes/ext/stopwords-json/dist/" + lang + ".json";
custom_uri = jQuery("#post-" + post_id).find(".column-permalink-manager-col").text();
// Load JSON with words list
// Fill with the Custom URI jQuery.getJSON(json_url, function(data) {
custom_uri_field.val(custom_uri); var new_words = [];
// Set the element ID jQuery.each(data, function(key, val) {
jQuery('#edit-' + post_id).find('.permalink-manager-edit-uri-element-id').val(post_id); new_words.push(val);
} });
}
} stop_words.update(new_words);
});
if(typeof inlineEditTax !== "undefined") { }
var inline_tax_editor = inlineEditTax.edit;
inlineEditTax.edit = function(id) { return false;
inline_tax_editor.apply(this, arguments); });
}
// Get the Post ID
var term_id = 0; /**
if(typeof(id) == 'object') { * Quick Edit
term_id = parseInt(this.getId(id)); */
} if(typeof inlineEditPost !== "undefined") {
var inline_post_editor = inlineEditPost.edit;
if(term_id != 0) { inlineEditPost.edit = function(id) {
// Get the row & "Custom URI" field inline_post_editor.apply(this, arguments);
custom_uri_field = jQuery('#edit-' + term_id).find('.custom_uri');
// Get the Post ID
// Prepare the Custom URI var post_id = 0;
custom_uri = jQuery("#tag-" + term_id).find(".column-permalink-manager-col").text(); if(typeof(id) == 'object') {
post_id = parseInt(this.getId(id));
// Fill with the Custom URI }
custom_uri_field.val(custom_uri);
if(post_id != 0) {
// Set the element ID // Get the row & "Custom URI" field
jQuery('#edit-' + term_id).find('.permalink-manager-edit-uri-element-id').val("tax-" + term_id); custom_uri_field = jQuery('#edit-' + post_id).find('.custom_uri');
}
} // Prepare the Custom URI
} custom_uri = jQuery("#post-" + post_id).find(".column-permalink-manager-col").text();
}); // Fill with the Custom URI
custom_uri_field.val(custom_uri);
// Set the element ID
jQuery('#edit-' + post_id).find('.permalink-manager-edit-uri-element-id').val(post_id);
}
}
}
if(typeof inlineEditTax !== "undefined") {
var inline_tax_editor = inlineEditTax.edit;
inlineEditTax.edit = function(id) {
inline_tax_editor.apply(this, arguments);
// Get the Post ID
var term_id = 0;
if(typeof(id) == 'object') {
term_id = parseInt(this.getId(id));
}
if(term_id != 0) {
// Get the row & "Custom URI" field
custom_uri_field = jQuery('#edit-' + term_id).find('.custom_uri');
// Prepare the Custom URI
custom_uri = jQuery("#tag-" + term_id).find(".column-permalink-manager-col").text();
// Fill with the Custom URI
custom_uri_field.val(custom_uri);
// Set the element ID
jQuery('#edit-' + term_id).find('.permalink-manager-edit-uri-element-id').val("tax-" + term_id);
}
}
}
});
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Plugin Name: Permalink Manager Lite * Plugin Name: Permalink Manager Lite
* Plugin URI: https://permalinkmanager.pro?utm_source=plugin * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
* Description: Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible). * Description: Advanced plugin that allows to set-up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
* Version: 2.1.1 * Version: 2.1.2
* Author: Maciej Bis * Author: Maciej Bis
* Author URI: http://maciejbis.net/ * Author URI: http://maciejbis.net/
* License: GPL-2.0+ * License: GPL-2.0+
...@@ -21,7 +21,7 @@ if (!defined('WPINC')) { ...@@ -21,7 +21,7 @@ if (!defined('WPINC')) {
// Define the directories used to load plugin files. // Define the directories used to load plugin files.
define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' ); define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' ); define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
define( 'PERMALINK_MANAGER_VERSION', '2.1.1' ); define( 'PERMALINK_MANAGER_VERSION', '2.1.2' );
define( 'PERMALINK_MANAGER_FILE', __FILE__ ); define( 'PERMALINK_MANAGER_FILE', __FILE__ );
define( 'PERMALINK_MANAGER_DIR', untrailingslashit(dirname(__FILE__)) ); define( 'PERMALINK_MANAGER_DIR', untrailingslashit(dirname(__FILE__)) );
define( 'PERMALINK_MANAGER_BASENAME', dirname(plugin_basename(__FILE__))); define( 'PERMALINK_MANAGER_BASENAME', dirname(plugin_basename(__FILE__)));
...@@ -182,18 +182,18 @@ class Permalink_Manager_Class { ...@@ -182,18 +182,18 @@ class Permalink_Manager_Class {
*/ */
public function default_alerts($alerts) { public function default_alerts($alerts) {
$default_alerts = apply_filters('permalink-manager-default-alerts', array( $default_alerts = apply_filters('permalink-manager-default-alerts', array(
'october2018' => array( 'spring' => array(
'txt' => sprintf( 'txt' => sprintf(
__("Get access to extra features: full taxonomy and WooCommerce support, possibility to use custom fields inside the permalinks and more!<br /><strong>Buy Permalink Manager Pro <a href=\"%s\" target=\"_blank\">here</a> and save %s using \"%s\" coupon code!</strong> Valid until %s!", "permalink-manager"), __("Get access to extra features: full taxonomy and WooCommerce support, possibility to use custom fields inside the permalinks and more!<br /><strong>Buy Permalink Manager Pro <a href=\"%s\" target=\"_blank\">here</a> and save %s using \"%s\" coupon code!</strong> Valid until %s!", "permalink-manager"),
PERMALINK_MANAGER_WEBSITE, PERMALINK_MANAGER_WEBSITE,
'30&#37;', '20&#37;',
'OCTOBER', 'SPRING',
'31st October' '31.03'
), ),
'type' => 'notice-info', 'type' => 'notice-info',
'show' => 'pro_hide', 'show' => 'pro_hide',
'plugin_only' => true, 'plugin_only' => true,
'until' => '2018-11-01' 'until' => '2018-04-01'
) )
)); ));
......
<?php
/**
* The front page template file
*
* If the user has selected a static page for their homepage, this is what will
* appear.
* Learn more: https://codex.wordpress.org/Template_Hierarchy
*
* @package WordPress
* @subpackage Biuro
* @since 1.0
* @version 1.0
*/
get_header(); ?>
<?php
while ( have_posts() ) :
the_post();
the_content();
endwhile;
?>
<br>
<br>
<h1>Svetainės medis:</h1>
<h2>Darbas + Miestas</h2>
<?php
getSiteTree( 'city' );
?>
<h2>Darbas + Tag'as</h2>
<ul>
<li style="color: red">ToDo: aptarti kaip turi būti LIVAS</li>
</ul>
<h2>Darbas + Sritis</h2>
<?php
getSiteTree( 'field' );
?>
<h2>Darbas + Įmonė</h2>
<?php
getSiteTree( 'company' );
?>
<br>
<br>
<?php get_footer();
...@@ -230,3 +230,28 @@ $m = $l ? wp_get_nav_menu_object( $l[ 'main-menu' ] ) : null; ...@@ -230,3 +230,28 @@ $m = $l ? wp_get_nav_menu_object( $l[ 'main-menu' ] ) : null;
$items = $m ? wp_get_nav_menu_items( $m->term_id, array( 'order' => 'DESC' ) ) : array(); $items = $m ? wp_get_nav_menu_items( $m->term_id, array( 'order' => 'DESC' ) ) : array();
$searchPageURL = $items[0] ? $items[0]->url : '/'; $searchPageURL = $items[0] ? $items[0]->url : '/';
function getSiteTree($taxonomy)
{
$terms = get_terms( array(
'taxonomy' => $taxonomy,
'hide_empty' => false,
));
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ):
echo '<ul>';
foreach ( $terms as $term ):
$page = get_term_meta( $term->term_id, 'page-id', true);
if ( $page ) :
?>
<li><a href="<?php echo get_page_link( $page['ID'] ); ?>"><?php echo $page['post_title']; ?></a></li>
<?
endif;
endforeach;
echo '</ul>';
endif;
}
...@@ -31,6 +31,8 @@ get_header(); ?> ...@@ -31,6 +31,8 @@ get_header(); ?>
$ID = get_the_ID(); $ID = get_the_ID();
$keys = get_post_custom_keys(); $keys = get_post_custom_keys();
$where = 'valid.meta_value > "' . date('Y-m-d', strtotime('-1 days')) . '"';
$taxonomies = array(); $taxonomies = array();
foreach ( $keys as $key => $value ) { foreach ( $keys as $key => $value ) {
...@@ -53,24 +55,46 @@ get_header(); ?> ...@@ -53,24 +55,46 @@ get_header(); ?>
continue; continue;
} }
$taxonomies[] = array( $where = $where . ' AND ' . $taxonomy . '.slug = "' . $term . '"';
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $term
);
} }
$jobs = get_posts( array( $params = array(
'posts_per_page' => -1, 'orderby' => 'date DESC',
'post_type' => 'job', 'where' => $where,
'tax_query' => $taxonomies 'limit' => 9
) ); );
$jobs = pods( 'job', $params );
// debug($jobs->fetch());
// $jobs = get_posts( array(
// 'posts_per_page' => -1,
// 'post_type' => 'job',
// 'tax_query' => $taxonomies
// ) );
// the_posts_pagination(
// array(
// 'mid_size' => 2,
// 'prev_text' => sprintf( '%s <span class="nav-prev-text">%s</span>', $prev_icon, __( 'Newer posts', 'twentynineteen' ) ),
// 'next_text' => sprintf( '<span class="nav-next-text">%s</span> %s', __( 'Older posts', 'twentynineteen' ), $next_icon ),
// )
// );
if ( 0 < $jobs->total() ):
get_template_part( 'template-parts/jobs/jobs', 'list' );
else:
get_template_part( 'template-parts/jobs/jobs', 'none' );
// debug($jobs); endif;
foreach ($jobs as $job) : // foreach ($jobs as $job) :
echo '<h3><a href="' . get_post_permalink( $job->ID ) . '" target="_blank">' . $job->post_title . '</a></h3>'; // echo '<h3><a href="' . get_post_permalink( $job->ID ) . '" target="_blank">' . $job->post_title . '</a></h3>';
endforeach; // endforeach;
?> ?>
......
...@@ -18,24 +18,6 @@ ...@@ -18,24 +18,6 @@
$periodID = get_query_var('period'); $periodID = get_query_var('period');
$fieldID = get_query_var('field'); $fieldID = get_query_var('field');
$typeID = get_query_var('type'); $typeID = get_query_var('type');
// function print()
// $cities = get_terms( 'city', array(
// 'hide_empty' => false,
// ));
// debug($cityID)
// if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
// echo '<ul>';
// foreach ( $terms as $term ) {
// echo '<li>' . $term->name . '</li>';
// }
// echo '</ul>';
// }
?> ?>
<form id="filter-form" action="<?php echo esc_url( $searchPageURL ); ?>" method="get" enctype="application/x-www-form-urlencoded"> <form id="filter-form" action="<?php echo esc_url( $searchPageURL ); ?>" method="get" enctype="application/x-www-form-urlencoded">
...@@ -52,7 +34,8 @@ ...@@ -52,7 +34,8 @@
<select name="city" id="city" class="el_130"> <select name="city" id="city" class="el_130">
<option value="">Visi miestai</option> <option value="">Visi miestai</option>
<?php <?php
$cities = get_terms( 'city', array( $cities = get_terms( array(
'taxonomy' => 'city',
'hide_empty' => false, 'hide_empty' => false,
)); ));
...@@ -81,7 +64,8 @@ ...@@ -81,7 +64,8 @@
<select name="field" id="field" class="el_130"> <select name="field" id="field" class="el_130">
<option value="">Visos sritys</option> <option value="">Visos sritys</option>
<?php <?php
$fields = get_terms( 'field', array( $fields = get_terms( array(
'taxonomy' => 'field',
'hide_empty' => false, 'hide_empty' => false,
)); ));
...@@ -101,7 +85,8 @@ ...@@ -101,7 +85,8 @@
<select name="type" id="type" class="el_130"> <select name="type" id="type" class="el_130">
<option value="">Visos rūšys</option> <option value="">Visos rūšys</option>
<?php <?php
$types = get_terms( 'type', array( $types = get_terms( array(
'taxonomy' => 'type',
'hide_empty' => false, 'hide_empty' => false,
)); ));
...@@ -127,7 +112,7 @@ ...@@ -127,7 +112,7 @@
// Use for search // Use for search
// https://pods.io/docs/code/pods/find/ // https://pods.io/docs/code/pods/find/
$where = 't.post_title LIKE "%' . $search . '%"'; $where = 'valid.meta_value > "' . date('Y-m-d', strtotime('-1 days')) . '" AND t.post_title LIKE "%' . $search . '%"';
// 'where' => 't.post_title LIKE "%' . $keyword . '%" OR my_field.meta_value LIKE "%' . $keyword . '%"' // 'where' => 't.post_title LIKE "%' . $keyword . '%" OR my_field.meta_value LIKE "%' . $keyword . '%"'
if ($cityID): if ($cityID):
...@@ -144,52 +129,21 @@ ...@@ -144,52 +129,21 @@
$params = array( $params = array(
'orderby' => 'date DESC',
'where' => $where, 'where' => $where,
'limit' => -1 'limit' => 9
); );
$jobs = pods( 'job', $params ); $jobs = pods( 'job', $params );
if ( 0 < $jobs->total() ): if ( 0 < $jobs->total() ):
$i = 0;
?>
<table cellspacing="0" cellpadding="0" class="advert_table"> get_template_part( 'template-parts/jobs/jobs', 'list' );
<tr>
<th>Pozicija </th>
<th>Vietovė</th>
<th>Data</th>
<th>Rūšis</th>
</tr>
<?php else:
while ( $jobs->fetch() ) :
$i++;
?>
<tr <?php if ( $i % 2 == 0 ) { echo 'class="bg"'; } ?>>
<td>
<a href="<?php echo get_post_permalink( $jobs->display( 'ID' ) ); ?>" target="_blank" title="<?php echo $jobs->display( 'name' ); ?>">
<strong><?php echo $jobs->display( 'name' ); ?></strong>
</a>
</td>
<td>
<span style="opacity: 0.25;">Šiauliai</span>
</td>
<td>
<span style="opacity: 0.25;">Paskelbta: 2018 11 30 <br> Galioja iki: 2018 12 28</span>
</td>
<td>
<span style="opacity: 0.25;">Nuolatinis darbas</span>
</td>
</tr>
<?php
endwhile;
?>
</table> get_template_part( 'template-parts/jobs/jobs', 'none' );
<?php
endif; endif;
?> ?>
......
<?php
/**
* Template part for displaying a list of jobs
*
* @link https://developer.wordpress.org/themes/basics/template-hierarchy/
*
* @package WordPress
* @subpackage Biuro
* @since 1.0.0
*/
global $jobs;
?>
<table cellspacing="0" cellpadding="0" class="advert_table">
<tr>
<th>Pozicija </th>
<th>Vietovė</th>
<th>Data</th>
<th>Rūšis</th>
</tr>
<?php
while ( $jobs->fetch() ) :
$ID = $jobs->display( 'ID' );
$i++;
?>
<tr <?php if ( $i % 2 != 0 ) { echo 'class="bg"'; } ?>>
<td>
<a href="<?php echo get_post_permalink( $ID ); ?>" target="_blank" title="<?php echo $jobs->display( 'name' ); ?>">
<strong><?php echo $jobs->display( 'name' ); ?></strong>
</a>
</td>
<td>
<?php echo $jobs->display( 'city' ); ?>
</td>
<td>
Paskelbta: <?php echo get_the_date( 'Y-m-d', $ID ); ?> <br>Galioja iki: <?php echo get_the_date( $jobs->display( 'valid' ) ); ?>
</td>
<td>
<?php echo $jobs->display( 'type' ); ?>
</td>
</tr>
<?php
endwhile;
?>
</table>
<?php
echo $jobs->pagination( array( 'type' => 'paginate' ) );
?>
<?php
/**
* Template part for displaying a message that jobs cannot be found
*
* @link https://developer.wordpress.org/themes/basics/template-hierarchy/
*
* @package WordPress
* @subpackage Twenty_Nineteen
* @since 1.0.0
*/
?>
<p>Pagal Jūsų paiešką rezultatų neradome.</p>
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