lines-num-new"> 5
+  templateUrl: './forgot-password.page.html',
6
+  styleUrls: ['./forgot-password.page.scss'],
7
+})
8
+export class ForgotPasswordPage implements OnInit {
9
+
10
+  email = "";
11
+
12
+  constructor() { }
13
+
14
+  ngOnInit() {
15
+  }
16
+
17
+}

+ 17 - 0
src/app/home/home-routing.module.ts

@@ -0,0 +1,17 @@
1
+import { NgModule } from '@angular/core';
2
+import { Routes, RouterModule } from '@angular/router';
3
+
4
+import { HomePage } from './home.page';
5
+
6
+const routes: Routes = [
7
+  {
8
+    path: '',
9
+    component: HomePage
10
+  }
11
+];
12
+
13
+@NgModule({
14
+  imports: [RouterModule.forChild(routes)],
15
+  exports: [RouterModule],
16
+})
17
+export class HomePageRoutingModule {}

+ 23 - 0
src/app/home/home.module.ts

@@ -0,0 +1,23 @@
1
+import { NgModule } from '@angular/core';
2
+import { CommonModule } from '@angular/common';
3
+import { FormsModule } from '@angular/forms';
4
+
5
+import { IonicModule } from '@ionic/angular';
6
+
7
+import { HomePageRoutingModule } from './home-routing.module';
8
+
9
+import { HomePage } from './home.page';
10
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
11
+import { IonSlides } from '@ionic/angular';
12
+
13
+@NgModule({
14
+  imports: [
15
+    CommonModule,
16
+    FormsModule,
17
+    IonicModule,
18
+    HomePageRoutingModule,
19
+    FontAwesomeModule
20
+  ],
21
+  declarations: [HomePage]
22
+})
23
+export class HomePageModule {}

+ 87 - 0
src/app/home/home.page.html

@@ -0,0 +1,87 @@
1
+<ion-header class="ion-no-border">
2
+  <ion-toolbar class="new-background-color">
3
+    <ion-title>Wellness Route</ion-title>
4
+  </ion-toolbar>
5
+</ion-header>
6
+<ion-content [fullscreen]="true">
7
+  <ion-slides pager="true" [options]="slideOptsOne">
8
+    <ion-slide *ngFor="let p of imageslide">
9
+      <div class="slide">
10
+        <ion-img [src]="p.better_featured_image.source_url"></ion-img>
11
+      </div>
12
+    </ion-slide>
13
+  </ion-slides>
14
+  <ion-grid>
15
+    <ion-row>
16
+      <ion-col>
17
+        <ion-toolbar class="search">
18
+          <ion-searchbar placeholder="ค้นหา"></ion-searchbar>
19
+        </ion-toolbar>
20
+      </ion-col>
21
+    </ion-row>
22
+    <ion-row class="ion-justify-content-start">
23
+      <!-- <ion-col size="6">
24
+        <div class="center catshow">
25
+          <fa-icon [icon]="['fas', 'utensils']" size="3x" class="red"></fa-icon>
26
+        </div>
27
+      </ion-col>
28
+      <ion-col size="6">
29
+        <div class=" catshow center">
30
+          <fa-icon [icon]="['fas', 'spa']" size="3x"></fa-icon>        
31
+        </div>
32
+      </ion-col>
33
+      <ion-col size="6">
34
+        <div class=" catshow center">
35
+          <fa-icon [icon]="['fas', 'praying-hands']" size="3x"></fa-icon>          
36
+        </div>
37
+      </ion-col>
38
+      <ion-col size="6">
39
+        <div class="catshow center">
40
+          <fa-icon [icon]="['fas', 'running']" size="3x"></fa-icon>
41
+        </div>
42
+      </ion-col> -->
43
+      <ion-col size="3">
44
+        <div class="center catshow">
45
+          <a [routerLink]="['/tabs/place/']"><fa-icon [icon]="['fas', 'utensils']" size="2x" class="red"></fa-icon></a>          
46
+        </div>
47
+      </ion-col>
48
+      <ion-col size="3">
49
+        <div class=" catshow center">
50
+          <fa-icon [icon]="['fas', 'spa']" size="2x"></fa-icon>        
51
+        </div>
52
+      </ion-col>
53
+      <ion-col size="3">
54
+        <div class=" catshow center">
55
+          <fa-icon [icon]="['fas', 'praying-hands']" size="2x"></fa-icon>          
56
+        </div>
57
+      </ion-col>
58
+      <ion-col size="3">
59
+        <div class="catshow center">
60
+          <fa-icon [icon]="['fas', 'running']" size="2x"></fa-icon>
61
+        </div>
62
+      </ion-col>
63
+    </ion-row>
64
+    <ion-row>
65
+      <ion-col>
66
+        <ion-card *ngFor="let pldata of placelasted">
67
+          <div *ngIf="$any(pldata).better_featured_image != null">
68
+            <img src="{{$any(pldata).better_featured_image.source_url}}" alt="">
69
+          </div>
70
+          <div *ngIf="$any(pldata).better_featured_image == null">
71
+            <img src="/assets/images/temp.png" />
72
+          </div>
73
+          <ion-card-header>            
74
+            <a [routerLink]="['/tabs/place/', pldata.id]"><ion-card-title [innerHTML]="pldata.title.rendered"></ion-card-title>
75
+            </a>
76
+            <a [routerLink]="['/tabs/province/']">
77
+              <span [innerHTML]="pldata._embedded['wp:term'][1][0].name"></span>
78
+            </a> /
79
+            <a [routerLink]="['/tabs/place/']">
80
+              <span [innerHTML]="pldata._embedded['wp:term'][2][0].name"></span>
81
+            </a>
82
+          </ion-card-header>
83
+        </ion-card>
84
+      </ion-col>
85
+    </ion-row>
86
+  </ion-grid>
87
+</ion-content>

+ 45 - 0
src/app/home/home.page.scss

@@ -0,0 +1,45 @@
1
+ion-card-title {
2
+  font-family: "IBM Plex Sans Thai", sans-serif !important;
3
+  font-weight: 600;
4
+  font-size: 20px;
5
+}
6
+
7
+ion-searchbar{
8
+  // --color:#000;
9
+  // --placeholder-color:#000;
10
+  // --background:#000;
11
+}
12
+
13
+.search{
14
+  padding: 0px !important;
15
+  // margin-bottom: 30px;
16
+  margin-top: 10px;
17
+}
18
+
19
+// .red {
20
+//   color: rgb(255, 0, 0);
21
+// }
22
+
23
+.catshow {
24
+  height: 100px;
25
+  // background-color: rgb(183, 210, 236);
26
+  border: solid 1px;
27
+  border-color: cornflowerblue;
28
+}
29
+
30
+.center {
31
+  // // height: 110px;
32
+  // margin: auto;
33
+  // // width: 50%;
34
+  // border: 3px solid green;
35
+  // padding: 10px;
36
+  // display: block;
37
+  // margin-left: auto;
38
+  // margin-right: auto;
39
+  display: flex;
40
+  // height: 180px;
41
+  // background-color: #ff1124;
42
+  justify-content: center;
43
+  align-items: center;
44
+  // flex-wrap: wrap;
45
+}

+ 24 - 0
src/app/home/home.page.spec.ts

@@ -0,0 +1,24 @@
1
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2
+import { IonicModule } from '@ionic/angular';
3
+
4
+import { HomePage } from './home.page';
5
+
6
+describe('HomePage', () => {
7
+  let component: HomePage;
8
+  let fixture: ComponentFixture<HomePage>;
9
+
10
+  beforeEach(waitForAsync(() => {
11
+    TestBed.configureTestingModule({
12
+      declarations: [ HomePage ],
13
+      imports: [IonicModule.forRoot()]
14
+    }).compileComponents();
15
+
16
+    fixture = TestBed.createComponent(HomePage);
17
+    component = fixture.componentInstance;
18
+    fixture.detectChanges();
19
+  }));
20
+
21
+  it('should create', () => {
22
+    expect(component).toBeTruthy();
23
+  });
24
+});

+ 39 - 0
src/app/home/home.page.ts

@@ -0,0 +1,39 @@
1
+import { Component, OnInit } from '@angular/core';
2
+import { NavController } from '@ionic/angular';
3
+import { WpServiceService } from '../wp-service.service';
4
+
5
+
6
+@Component({
7
+  selector: 'app-home',
8
+  templateUrl: './home.page.html',
9
+  styleUrls: ['./home.page.scss'],
10
+})
11
+export class HomePage implements OnInit {
12
+
13
+  imageslide :any = [];
14
+  placelasted :any = [];
15
+  sliderOne: any;
16
+
17
+  slideOptsOne = {
18
+    initialSlide: 0,
19
+    slidesPerView: 1,
20
+    autoplay: true
21
+  };
22
+
23
+  constructor(public navCtrl: NavController, private wpservice: WpServiceService) { }
24
+
25
+  ngOnInit() {
26
+    
27
+    this.wpservice.getSlideshow().subscribe((data) => {
28
+      this.imageslide = data;
29
+      console.log('load imageslide');
30
+    });
31
+
32
+    this.wpservice.getLasted().subscribe((placedata) => {
33
+      this.placelasted = placedata;
34
+      console.log('load Place');
35
+      console.log(placedata);
36
+    });        
37
+  }
38
+
39
+}

+ 17 - 0
src/app/login/login-routing.module.ts

@@ -0,0 +1,17 @@
1
+import { NgModule } from '@angular/core';
2
+import { Routes, RouterModule } from '@angular/router';
3
+
4
+import { LoginPage } from './login.page';
5
+
6
+const routes: Routes = [
7
+  {
8
+    path: '',
9
+    component: LoginPage
10
+  }
11
+];
12
+
13
+@NgModule({
14
+  imports: [RouterModule.forChild(routes)],
15
+  exports: [RouterModule],
16
+})
17
+export class LoginPageRoutingModule {}

+ 20 - 0
src/app/login/login.module.ts

@@ -0,0 +1,20 @@
1
+import { NgModule } from '@angular/core';
2
+import { CommonModule } from '@angular/common';
3
+import { FormsModule } from '@angular/forms';
4
+
5
+import { IonicModule } from '@ionic/angular';
6
+
7
+import { LoginPageRoutingModule } from './login-routing.module';
8
+
9
+import { LoginPage } from './login.page';
10
+
11
+@NgModule({
12
+  imports: [
13
+    CommonModule,
14
+    FormsModule,
15
+    IonicModule,
16
+    LoginPageRoutingModule
17
+  ],
18
+  declarations: [LoginPage]
19
+})
20
+export class LoginPageModule {}

+ 78 - 0
src/app/login/login.page.html

@@ -0,0 +1,78 @@
1
+<ion-header>
2
+  <ion-toolbar>
3
+    <ion-title>Wellness Route</ion-title>
4
+  </ion-toolbar>
5
+</ion-header>
6
+
7
+<ion-content>
8
+  <ion-row>
9
+    <ion-col>
10
+      <div class="ion-text-center">
11
+        <h1>เข้าสู่ระบบ</h1>
12
+      </div>
13
+    </ion-col>
14
+  </ion-row>
15
+  <ion-row>
16
+    <ion-col>
17
+      <form>
18
+        <ion-item lines="full">
19
+          <ion-label position="floating">อีเมล์</ion-label>
20
+          <ion-input type="text" required="true" [(ngModel)]='registerForm.email' name='email' type='email'></ion-input>
21
+        </ion-item>
22
+
23
+        <ion-item lines="full">
24
+          <ion-label position="floating">รหัสผ่าน</ion-label>
25
+          <ion-input type="password" required [(ngModel)]='registerForm.password' name='password'></ion-input>
26
+        </ion-item>
27
+      </form>
28
+    </ion-col>
29
+  </ion-row>
30
+  <ion-row>
31
+    <ion-col>
32
+      <ion-button type="submit" color="success" expand="block" (click)="userLogin()">Login</ion-button>
33
+    </ion-col>
34
+  </ion-row>
35
+  <ion-row>
36
+    <ion-col class='ion-text-center'>
37
+      <a (click)="openForgotPassword()" class="small-text">ลืมรหัส</a>      
38
+    </ion-col>
39
+    <ion-col class='ion-text-center'>
40
+      <a (click)="openRegister()" class="small-text">สม้ครใหม่</a>
41
+    </ion-col>
42
+  </ion-row>
43
+  <ion-row>
44
+    <ion-col>
45
+      <span class="divider line one-line">หรือ</span>
46
+    </ion-col>
47
+  </ion-row>
48
+  <ion-row>
49
+    <ion-col>
50
+      <ion-button class="log-fb-in-button" expand="block" (click)="doFbLogin()">
51
+        Log in with Facebook
52
+      </ion-button><br>
53
+      <button (click)="appleSignIn()" block [hidden]="isAndroid">
54
+        <img src="assets/images/appleid_button@2x.png">
55
+      </button>
56
+    </ion-col>
57
+  </ion-row>
58
+  <ion-col>      
59
+    <a [routerLink]="['/tabs/forgot-password']">
60
+      page ลืมรหัส
61
+    </a>
62
+  </ion-col>
63
+  <ion-col>      
64
+    <a [routerLink]="['/tabs/register']">
65
+      page register or signin
66
+    </a>
67
+  </ion-col>
68
+  <ion-col>      
69
+    <a [routerLink]="['/tabs/reset-password']">
70
+      page reset password
71
+    </a>
72
+  </ion-col>
73
+  <ion-col>      
74
+    <a [routerLink]="['/tabs/profile']">
75
+      page profile
76
+    </a>
77
+  </ion-col>
78
+</ion-content>

+ 26 - 0
src/app/login/login.page.scss

@@ -0,0 +1,26 @@
1
+
2
+.divider {
3
+    display: flex;
4
+  
5
+    &:before,
6
+    &:after {
7
+      content: "";
8
+      flex: 1;
9
+    }
10
+  }
11
+  .line {
12
+    align-items: center;
13
+    margin: 1em -1em;
14
+    color: #5f5e5e;
15
+    &:before,
16
+    &:after {
17
+      height: 1px;
18
+      margin: 0 1em;
19
+    }
20
+  }
21
+  .one-line {
22
+    &:before,
23
+    &:after {
24
+      background: #5f5e5e;
25
+    }
26
+  }

+ 24 - 0
src/app/login/login.page.spec.ts

@@ -0,0 +1,24 @@
1
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2
+import { IonicModule } from '@ionic/angular';
3
+
4
+import { LoginPage } from './login.page';
5
+
6
+describe('LoginPage', () => {
7
+  let component: LoginPage;
8
+  let fixture: ComponentFixture<LoginPage>;
9
+
10
+  beforeEach(waitForAsync(() => {
11
+    TestBed.configureTestingModule({
12
+      declarations: [ LoginPage ],
13
+      imports: [IonicModule.forRoot()]
14
+    }).compileComponents();
15
+
16
+    fixture = TestBed.createComponent(LoginPage);
17
+    component = fixture.componentInstance;
18
+    fixture.detectChanges();
19
+  }));
20
+
21
+  it('should create', () => {
22
+    expect(component).toBeTruthy();
23
+  });
24
+});

+ 18 - 0
src/app/login/login.page.ts

@@ -0,0 +1,18 @@
1
+import { Component, OnInit } from '@angular/core';
2
+
3
+@Component({
4
+  selector: 'app-login',
5
+  templateUrl: './login.page.html',
6
+  styleUrls: ['./login.page.scss'],
7
+})
8
+export class LoginPage implements OnInit {
9
+
10
+  registerForm = { email: "", password: "" };
11
+  isAndroid = false;
12
+
13
+  constructor() { }
14
+
15
+  ngOnInit() {
16
+  }
17
+
18
+}

+ 17 - 0
src/app/place/place-routing.module.ts

@@ -0,0 +1,17 @@
1
+import { NgModule } from '@angular/core';
2
+import { Routes, RouterModule } from '@angular/router';
3
+
4
+import { PlacePage } from './place.page';
5
+
6
+const routes: Routes = [
7
+  {
8
+    path: '',
9
+    component: PlacePage
10
+  }
11
+];
12
+
13
+@NgModule({
14
+  imports: [RouterModule.forChild(routes)],
15
+  exports: [RouterModule],
16
+})
17
+export class PlacePageRoutingModule {}

+ 20 - 0
src/app/place/place.module.ts

@@ -0,0 +1,20 @@
1
+import { NgModule } from '@angular/core';
2
+import { CommonModule } from '@angular/common';
3
+import { FormsModule } from '@angular/forms';
4
+
5
+import { IonicModule } from '@ionic/angular';
6
+
7
+import { PlacePageRoutingModule } from './place-routing.module';
8
+
9
+import { PlacePage } from './place.page';
10
+
11
+@NgModule({
12
+  imports: [
13
+    CommonModule,
14
+    FormsModule,
15
+    IonicModule,
16
+    PlacePageRoutingModule
17
+  ],
18
+  declarations: [PlacePage]
19
+})
20
+export class PlacePageModule {}

+ 29 - 0
src/app/place/place.page.html

@@ -0,0 +1,29 @@
1
+<ion-header>
2
+  <ion-toolbar class="new-background-color">
3
+    <ion-title>Wellness Route</ion-title>
4
+  </ion-toolbar>
5
+</ion-header>
6
+
7
+<ion-content>
8
+  <img src="/assets/images/golf-bg.jpg">
9
+  <div class="holidaycard">
10
+    <ion-grid>
11
+      <ion-row>
12
+        <ion-col size="12">
13
+          <div class="txt-place-title">Place Category Name</div>
14
+        </ion-col>
15
+      </ion-row>
16
+      <ion-card *ngFor="let pcl of placecatlist">
17
+        <div *ngIf="$any(pcl).better_featured_image != null">
18
+          <img src="{{$any(pcl).better_featured_image.source_url}}" alt="">
19
+        </div>
20
+        <div *ngIf="$any(pcl).better_featured_image == null">
21
+          <img src="/assets/images/temp.png" />
22
+        </div>
23
+        <ion-card-header>
24
+           <a [routerLink]="['/tabs/place/', pcl.id]"><ion-card-title [innerHTML]="pcl.title.rendered"></ion-card-title></a>
25
+        </ion-card-header>
26
+      </ion-card>
27
+    </ion-grid>
28
+  </div>
29
+</ion-content>

+ 18 - 0
src/app/place/place.page.scss

@@ -0,0 +1,18 @@
1
+.holidaycard {
2
+    position: absolute;
3
+    left: 0px;
4
+    // bottom: 0px;
5
+    top:200px;
6
+    min-height: 48%;
7
+    width: 100%;
8
+    padding: 5px;
9
+    border-radius: 15px ;
10
+    background: white;
11
+    --background: white;
12
+  }
13
+  
14
+  ion-card-title {
15
+    font-family: "IBM Plex Sans Thai", sans-serif !important;
16
+    font-weight: 600;
17
+    font-size: 20px;
18
+  }

+ 24 - 0
src/app/place/place.page.spec.ts

@@ -0,0 +1,24 @@
1
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2
+import { IonicModule } from '@ionic/angular';
3
+
4
+import { PlacePage } from './place.page';
5
+
6
+describe('PlacePage', () => {
7
+  let component: PlacePage;
8
+  let fixture: ComponentFixture<PlacePage>;
9
+
10
+  beforeEach(waitForAsync(() => {
11
+    TestBed.configureTestingModule({
12
+      declarations: [ PlacePage ],
13
+      imports: [IonicModule.forRoot()]
14
+    }).compileComponents();
15
+
16
+    fixture = TestBed.createComponent(PlacePage);
17
+    component = fixture.componentInstance;
18
+    fixture.detectChanges();
19
+  }));
20
+
21
+  it('should create', () => {
22
+    expect(component).toBeTruthy();
23
+  });
24
+});

+ 31 - 0
src/app/place/place.page.ts

@@ -0,0 +1,31 @@
1
+import { Component, OnInit, Input } from '@angular/core';
2
+import { ActivatedRoute, Router } from '@angular/router';
3
+import { WpServiceService } from '../wp-service.service';
4
+
5
+@Component({
6
+  selector: 'app-place',
7
+  templateUrl: './place.page.html',
8
+  styleUrls: ['./place.page.scss'],
9
+})
10
+export class PlacePage implements OnInit {
11
+
12
+  data: any;
13
+  placecatlist: any;
14
+
15
+  constructor(private wpservice: WpServiceService, private route: ActivatedRoute, private router: Router) { }
16
+
17
+  @Input() id: string;
18
+
19
+  ngOnInit() {
20
+    let id = this.route.snapshot.paramMap.get('id') || this.id;
21
+    console.log("fetching ...");
22
+    this.wpservice.getPlaceCat().subscribe((data) => {
23
+      this.placecatlist = data;      
24
+      console.log("load Cat Place ...");
25
+      console.log(data);
26
+    }, error => {
27
+      console.log("errror ", error);
28
+    });
29
+  }
30
+
31
+}

+ 17 - 0
src/app/placedetail/placedetail-routing.module.ts

@@ -0,0 +1,17 @@
1
+import { NgModule } from '@angular/core';
2
+import { Routes, RouterModule } from '@angular/router';
3
+
4
+import { PlacedetailPage } from './placedetail.page';
5
+
6
+const routes: Routes = [
7
+  {
8
+    path: '',
9
+    component: PlacedetailPage
10
+  }
11
+];
12
+
13
+@NgModule({
14
+  imports: [RouterModule.forChild(routes)],
15
+  exports: [RouterModule],
16
+})
17
+export class PlacedetailPageRoutingModule {}

+ 0 - 0
src/app/placedetail/placedetail.module.ts


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels

tum/whitesports - Gogs: Simplico Git Service

Aucune description

class-wp-session-tokens.php 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <?php
  2. /**
  3. * Session API: WP_Session_Tokens class
  4. *
  5. * @package WordPress
  6. * @subpackage Session
  7. * @since 4.7.0
  8. */
  9. /**
  10. * Abstract class for managing user session tokens.
  11. *
  12. * @since 4.0.0
  13. */
  14. abstract class WP_Session_Tokens {
  15. /**
  16. * User ID.
  17. *
  18. * @since 4.0.0
  19. * @var int User ID.
  20. */
  21. protected $user_id;
  22. /**
  23. * Protected constructor. Use the `get_instance()` method to get the instance.
  24. *
  25. * @since 4.0.0
  26. *
  27. * @param int $user_id User whose session to manage.
  28. */
  29. protected function __construct( $user_id ) {
  30. $this->user_id = $user_id;
  31. }
  32. /**
  33. * Retrieves a session manager instance for a user.
  34. *
  35. * This method contains a {@see 'session_token_manager'} filter, allowing a plugin to swap out
  36. * the session manager for a subclass of `WP_Session_Tokens`.
  37. *
  38. * @since 4.0.0
  39. *
  40. * @param int $user_id User whose session to manage.
  41. * @return WP_Session_Tokens The session object, which is by default an instance of
  42. * the `WP_User_Meta_Session_Tokens` class.
  43. */
  44. final public static function get_instance( $user_id ) {
  45. /**
  46. * Filters the class name for the session token manager.
  47. *
  48. * @since 4.0.0
  49. *
  50. * @param string $session Name of class to use as the manager.
  51. * Default 'WP_User_Meta_Session_Tokens'.
  52. */
  53. $manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' );
  54. return new $manager( $user_id );
  55. }
  56. /**
  57. * Hashes the given session token for storage.
  58. *
  59. * @since 4.0.0
  60. *
  61. * @param string $token Session token to hash.
  62. * @return string A hash of the session token (a verifier).
  63. */
  64. private function hash_token( $token ) {
  65. // If ext/hash is not present, use sha1() instead.
  66. if ( function_exists( 'hash' ) ) {
  67. return hash( 'sha256', $token );
  68. } else {
  69. return sha1( $token );
  70. }
  71. }
  72. /**
  73. * Retrieves a user's session for the given token.
  74. *
  75. * @since 4.0.0
  76. *
  77. * @param string $token Session token.
  78. * @return array|null The session, or null if it does not exist.
  79. */
  80. final public function get( $token ) {
  81. $verifier = $this->hash_token( $token );
  82. return $this->get_session( $verifier );
  83. }
  84. /**
  85. * Validates the given session token for authenticity and validity.
  86. *
  87. * Checks that the given token is present and hasn't expired.
  88. *
  89. * @since 4.0.0
  90. *
  91. * @param string $token Token to verify.
  92. * @return bool Whether the token is valid for the user.
  93. */
  94. final public function verify( $token ) {
  95. $verifier = $this->hash_token( $token );
  96. return (bool) $this->get_session( $verifier );
  97. }
  98. /**
  99. * Generates a session token and attaches session information to it.
  100. *
  101. * A session token is a long, random string. It is used in a cookie
  102. * to link that cookie to an expiration time and to ensure the cookie
  103. * becomes invalidated when the user logs out.
  104. *
  105. * This function generates a token and stores it with the associated
  106. * expiration time (and potentially other session information via the
  107. * {@see 'attach_session_information'} filter).
  108. *
  109. * @since 4.0.0
  110. *
  111. * @param int $expiration Session expiration timestamp.
  112. * @return string Session token.
  113. */
  114. final public function create( $expiration ) {
  115. /**
  116. * Filters the information attached to the newly created session.
  117. *
  118. * Can be used to attach further information to a session.
  119. *
  120. * @since 4.0.0
  121. *
  122. * @param array $session Array of extra data.
  123. * @param int $user_id User ID.
  124. */
  125. $session = apply_filters( 'attach_session_information', array(), $this->user_id );
  126. $session['expiration'] = $expiration;
  127. // IP address.
  128. if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
  129. $session['ip'] = $_SERVER['REMOTE_ADDR'];
  130. }
  131. // User-agent.
  132. if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
  133. $session['ua'] = wp_unslash( $_SERVER['HTTP_USER_AGENT'] );
  134. }
  135. // Timestamp.
  136. $session['login'] = time();
  137. $token = wp_generate_password( 43, false, false );
  138. $this->update( $token, $session );
  139. return $token;
  140. }
  141. /**
  142. * Updates the data for the session with the given token.
  143. *
  144. * @since 4.0.0
  145. *
  146. * @param string $token Session token to update.
  147. * @param array $session Session information.
  148. */
  149. final public function update( $token, $session ) {
  150. $verifier = $this->hash_token( $token );
  151. $this->update_session( $verifier, $session );
  152. }
  153. /**
  154. * Destroys the session with the given token.
  155. *
  156. * @since 4.0.0
  157. *
  158. * @param string $token Session token to destroy.
  159. */
  160. final public function destroy( $token ) {
  161. $verifier = $this->hash_token( $token );
  162. $this->update_session( $verifier, null );
  163. }
  164. /**
  165. * Destroys all sessions for this user except the one with the given token (presumably the one in use).
  166. *
  167. * @since 4.0.0
  168. *
  169. * @param string $token_to_keep Session token to keep.
  170. */
  171. final public function destroy_others( $token_to_keep ) {
  172. $verifier = $this->hash_token( $token_to_keep );
  173. $session = $this->get_session( $verifier );
  174. if ( $session ) {
  175. $this->destroy_other_sessions( $verifier );
  176. } else {
  177. $this->destroy_all_sessions();
  178. }
  179. }
  180. /**
  181. * Determines whether a session is still valid, based on its expiration timestamp.
  182. *
  183. * @since 4.0.0
  184. *
  185. * @param array $session Session to check.
  186. * @return bool Whether session is valid.
  187. */
  188. final protected function is_still_valid( $session ) {
  189. return $session['expiration'] >= time();
  190. }
  191. /**
  192. * Destroys all sessions for a user.
  193. *
  194. * @since 4.0.0
  195. */
  196. final public function destroy_all() {
  197. $this->destroy_all_sessions();
  198. }
  199. /**
  200. * Destroys all sessions for all users.
  201. *
  202. * @since 4.0.0
  203. */
  204. final public static function destroy_all_for_all_users() {
  205. /** This filter is documented in wp-includes/class-wp-session-tokens.php */
  206. $manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' );
  207. call_user_func( array( $manager, 'drop_sessions' ) );
  208. }
  209. /**
  210. * Retrieves all sessions for a user.
  211. *
  212. * @since 4.0.0
  213. *
  214. * @return array Sessions for a user.
  215. */
  216. final public function get_all() {
  217. return array_values( $this->get_sessions() );
  218. }
  219. /**
  220. * Retrieves all sessions of the user.
  221. *
  222. * @since 4.0.0
  223. *
  224. * @return array Sessions of the user.
  225. */
  226. abstract protected function get_sessions();
  227. /**
  228. * Retrieves a session based on its verifier (token hash).
  229. *
  230. * @since 4.0.0
  231. *
  232. * @param string $verifier Verifier for the session to retrieve.
  233. * @return array|null The session, or null if it does not exist.
  234. */
  235. abstract protected function get_session( $verifier );
  236. /**
  237. * Updates a session based on its verifier (token hash).
  238. *
  239. * Omitting the second argument destroys the session.
  240. *
  241. * @since 4.0.0
  242. *
  243. * @param string $verifier Verifier for the session to update.
  244. * @param array $session Optional. Session. Omitting this argument destroys the session.
  245. */
  246. abstract protected function update_session( $verifier, $session = null );
  247. /**
  248. * Destroys all sessions for this user, except the single session with the given verifier.
  249. *
  250. * @since 4.0.0
  251. *
  252. * @param string $verifier Verifier of the session to keep.
  253. */
  254. abstract protected function destroy_other_sessions( $verifier );
  255. /**
  256. * Destroys all sessions for the user.
  257. *
  258. * @since 4.0.0
  259. */
  260. abstract protected function destroy_all_sessions();
  261. /**
  262. * Destroys all sessions for all users.
  263. *
  264. * @since 4.0.0
  265. */
  266. public static function drop_sessions() {}
  267. }